All pastes #2055509 Raw Edit

johnburn

public javascript v1 · immutable
#2055509 ·published 2011-05-08 23:57 UTC
rendered paste body
if (window.CavalryLogger) {
    CavalryLogger.start_js(["LNwoY"])
}
function object(b) {
    var a = new Function();
    a.prototype = b;
    return new a()
}
function is_scalar(a) {
    return (/string|number|boolean/).test(typeof a)
}
function keys(c) {
    var b = [];
    for (var a in c) b.push(a);
    return b
}
function values(b) {
    var c = [];
    for (var a in b) c.push(b[a]);
    return c
}
function count(c) {
    var a = 0;
    for (var b in c) a++;
    return a
}
function are_equal(a, b) {
    return JSON.stringify(a) == JSON.stringify(b)
}
function merge() {
    var b = {};
    for (var a = 0; a < arguments.length; a++) copy_properties(b, arguments[a]);
    return b
}
function head(b) {
    for (var a in b) return b[a];
    return null
}
Object.from = function (c, e) {
    var d = {};
    var b = hasArrayNature(e);
    if (typeof e == 'undefined') e = true;
    for (var a = c.length; a--;) d[c[a]] = b ? e[a] : e;
    return d
};

function coalesce() {
    for (var a = 0; a < arguments.length; ++a) if (arguments[a] != null) return arguments[a];
    return null
}!
function () {
    function a(b) {
        return function () {
            if (this === window) throw new TypeError();
            return b.apply(this, arguments)
        }
    }
    copy_properties(Array.prototype, {
        map: function (c, b) {
            if (this === window || typeof c != 'function') throw new TypeError();
            var d;
            var e = this.length;
            var f = new Array(e);
            for (d = 0; d < e; ++d) if (d in this) f[d] = c.call(b, this[d], d, this);
            return f
        },
        forEach: function (c, b) {
            this.map(c, b);
            return this
        },
        filter: function (c, b) {
            c = c ||
            function (h) {
                return h
            };
            if (this === window || typeof c != 'function') throw new TypeError();
            var d, g, e = this.length,
                f = [];
            for (d = 0; d < e; ++d) if (d in this) {
                g = this[d];
                if (c.call(b, g, d, this)) f.push(g)
            }
            return f
        },
        every: function (d, c) {
            var b = this.filter(function () {
                return 1
            });
            return (this.filter(d, c).length == b.length)
        },
        some: function (c, b) {
            return (this.filter(c, b).length > 0)
        },
        reduce: null,
        reduceRight: null,
        sort: a(Array.prototype.sort),
        reverse: a(Array.prototype.reverse),
        concat: a(Array.prototype.concat),
        slice: a(Array.prototype.slice),
        indexOf: a(Array.prototype.indexOf ||
        function (d, b) {
            var c = this.length;
            b |= 0;
            if (b < 0) b += c;
            for (; b < c; b++) if (b in this && this[b] === d) return b;
            return -1
        }),
        contains: function (b) {
            return this.indexOf(b) != -1
        },
        remove: function (c) {
            var b = this.indexOf(c);
            if (b != -1) this.splice(b, 1)
        }
    });
    Array.prototype.each = Array.prototype.forEach;
    Array.prototype.clone = Array.prototype.slice
}();

function muffinize(d) {
    var c = 'a';
    var b = 'd';
    var a = [c, b].join('');
    return d.replace(/muffin/g, a)
}
window.Util = window.Util || {
    warn: bagofholding,
    error: bagofholding,
    info: bagofholding,
    log: bagofholding,
    stack: bagofholding
};
if (typeof console == 'undefined') console = {
    log: bagofholding
};
window.onloadRegister = function (a) {
    window.loaded ? _runHook(a) : _addHook('onloadhooks', a)
};

function onafterloadRegister(a) {
    window.afterloaded ? setTimeout(function () {
        _runHook(a)
    }, 0) : _addHook('onafterloadhooks', a)
}
function _onloadHook() {
    !window.loaded && window.CavalryLogger && CavalryLogger.getInstance().setTimeStamp('t_prehooks');
    _runHooks('onloadhooks');
    !window.loaded && window.CavalryLogger && CavalryLogger.getInstance().setTimeStamp('t_hooks');
    window.loaded = true;
    Arbiter.inform('uipage_onload', true, Arbiter.BEHAVIOR_STATE)
}
function _onafterloadHook() {
    _runHooks('onafterloadhooks');
    window.afterloaded = true
}
function _runHook(b) {
    try {
        return b()
    } catch (a) {}
}
function _runHooks(b) {
    var d = b == 'onbeforeleavehooks' || b == 'onbeforeunloadhooks';
    var e = null;
    do {
        var a = window[b];
        if (!d) window[b] = null;
        if (!a) break;
        for (var c = 0; c < a.length; c++) if (d) {
            e = e || _runHook(a[c])
        } else _runHook(a[c]);
        if (d) break
    } while (window[b]);
    if (d && e) return e
}
function keep_window_set_as_loaded() {
    if (window.loaded == false) {
        window.loaded = true;
        _runHooks('onloadhooks')
    }
    if (window.afterloaded == false) {
        window.afterloaded = true;
        _runHooks('onafterloadhooks')
    }
}
Arbiter.registerCallback(_onloadHook, [OnloadEvent.ONLOAD_DOMCONTENT_CALLBACK, InitialJSLoader.INITIAL_JS_READY]);
Arbiter.registerCallback(_onafterloadHook, [OnloadEvent.ONLOAD_DOMCONTENT_CALLBACK, OnloadEvent.ONLOAD_CALLBACK, InitialJSLoader.INITIAL_JS_READY]);
Arbiter.subscribe(OnloadEvent.ONBEFOREUNLOAD, function (b, a) {
    a.warn = _runHooks('onbeforeleavehooks') || _runHooks('onbeforeunloadhooks');
    if (!a.warn) {
        window.loaded = false;
        window.afterloaded = false
    }
}, Arbiter.SUBSCRIBE_NEW);
Arbiter.subscribe(OnloadEvent.ONUNLOAD, function (b, a) {
    _runHooks('onunloadhooks')
}, Arbiter.SUBSCRIBE_NEW);

function chain(d, e) {
    var b, a = [];
    for (var c = 0; c < arguments.length; c++) a.push(arguments[c]);
    b = function (event) {
        event = event || window.event;
        for (var f = 0; f < a.length; f++) if (a[f] && a[f].apply(this, arguments) === false) {
            return false
        } else if (event && event.cancelBubble) return true;
        return true
    };
    b.toString = function () {
        return chain._toString(a)
    };
    return b
}
if (!chain._toString) chain._toString = function (b) {
    var d = 'chained fns',
        a = b.filter();
    for (var c = 0; c < b.length; c++) d += '\n' + b[c].toString();
    return d
};
void(0);

function AsyncSignal(b, a) {
    this.data = a || {};
    if (window.Env && Env.tracking_domain && b.charAt(0) == '/') b = Env.tracking_domain + b;
    this.uri = b;
    this.handler = null
}
AsyncSignal.prototype.setHandler = function (a) {
    this.handler = a;
    return this
};
AsyncSignal.prototype.send = function () {
    var c = this.handler,
        b = this.data,
        g = this.uri,
        f = [],
        d = new Image(),
        a = document.getElementById('post_form_id');
    b.asyncSignal = Math.floor(Math.random() * 10000) + 1;
    if (a) b.post_form_id = a.value;
    for (var e in b) f.push(encodeURIComponent(e) + '=' + encodeURIComponent(b[e]));
    if (g.indexOf('?') == -1) g += '?';
    g += f.join('&');
    if (c) d.onload = d.onerror = (function (i, h) {
        return function () {
            h((i.height == 1))
        }
    })(d, c);
    d.src = g;
    return this
};

function setCookie(a, b, d, e) {
    if (env_get('no_cookies') && a != 'tpa') return;
    if (d) {
        var f = new Date();
        var c = new Date();
        c.setTime(f.getTime() + d)
    }
    document.cookie = a + "=" + encodeURIComponent(b) + "; " + (d ? "expires=" + c.toGMTString() + "; " : "") + "path=" + (e || '/') + "; domain=" + window.location.hostname.replace(/^.*(\.facebook\..*)$/i, '$1')
}
function clearCookie(a) {
    document.cookie = a + "=; expires=Sat, 01 Jan 2000 00:00:00 GMT; " + "path=/; domain=" + window.location.hostname.replace(/^.*(\.facebook\..*)$/i, '$1')
}
function getCookie(d) {
    var e = d + "=";
    var b = document.cookie.split(';');
    for (var c = 0; c < b.length; c++) {
        var a = b[c];
        while (a.charAt(0) == ' ') a = a.substring(1, a.length);
        if (a.indexOf(e) == 0) return decodeURIComponent(a.substring(e.length, a.length))
    }
    return null
}
function URI(a) {
    if (a === window) return;
    if (this === window) return new URI(a || window.location.href);
    this.parse(a || '')
}
copy_properties(URI, {
    getRequestURI: function (a, b) {
        a = a === undefined || a;
        if (a && window.PageTransitions && PageTransitions.isInitialized()) {
            return PageTransitions.getCurrentURI( !! b).getQualifiedURI()
        } else return new URI(window.location.href)
    },
    getMostRecentURI: function () {
        if (window.PageTransitions && PageTransitions.isInitialized()) {
            return PageTransitions.getMostRecentURI().getQualifiedURI()
        } else return new URI(window.location.href)
    },
    expression: /(((\w+):\/\/)([^\/:]*)(:(\d+))?)?([^#?]*)(\?([^#]*))?(#(.*))?/,
    arrayQueryExpression: /^(\w+)((?:\[\w*\])+)=?(.*)/,
    explodeQuery: function (g) {
        if (!g) return {};
        var h = {};
        g = g.replace(/%5B/ig, '[').replace(/%5D/ig, ']');
        g = g.split('&');
        for (var b = 0, d = g.length; b < d; b++) {
            var e = g[b].match(URI.arrayQueryExpression);
            if (!e) {
                var j = g[b].split('=');
                h[URI.decodeComponent(j[0])] = j[1] === undefined ? null : URI.decodeComponent(j[1])
            } else {
                var c = e[2].split(/\]\[|\[|\]/).slice(0, -1);
                var f = e[1];
                var k = URI.decodeComponent(e[3] || '');
                c[0] = f;
                var i = h;
                for (var a = 0; a < c.length - 1; a++) if (c[a]) {
                    if (i[c[a]] === undefined) if (c[a + 1] && !c[a + 1].match(/\d+$/)) {
                        i[c[a]] = {}
                    } else i[c[a]] = [];
                    i = i[c[a]]
                } else {
                    if (c[a + 1] && !c[a + 1].match(/\d+$/)) {
                        i.push({})
                    } else i.push([]);
                    i = i[i.length - 1]
                }
                if (i instanceof Array && c[c.length - 1] == '') {
                    i.push(k)
                } else i[c[c.length - 1]] = k
            }
        }
        return h
    },
    implodeQuery: function (f, e, a) {
        e = e || '';
        if (a === undefined) a = true;
        var g = [];
        if (f === null || f === undefined) {
            g.push(a ? URI.encodeComponent(e) : e)
        } else if (f instanceof Array) {
            for (var c = 0; c < f.length; ++c) try {
                if (f[c] !== undefined) g.push(URI.implodeQuery(f[c], e ? (e + '[' + c + ']') : c))
            } catch (b) {}
        } else if (typeof (f) == 'object') {
            if (DOM.isNode(f)) {
                g.push('{node}')
            } else for (var d in f) try {
                if (f[d] !== undefined) g.push(URI.implodeQuery(f[d], e ? (e + '[' + d + ']') : d))
            } catch (b) {}
        } else if (a) {
            g.push(URI.encodeComponent(e) + '=' + URI.encodeComponent(f))
        } else g.push(e + '=' + f);
        return g.join('&')
    },
    encodeComponent: function (d) {
        var c = String(d).split(/([\[\]])/);
        for (var a = 0, b = c.length; a < b; a += 2) c[a] = window.encodeURIComponent(c[a]);
        return c.join('')
    },
    decodeComponent: function (a) {
        return window.decodeURIComponent(a.replace(/\+/g, ' '))
    }
});
copy_properties(URI.prototype, {
    parse: function (b) {
        var a = b.toString().match(URI.expression);
        copy_properties(this, {
            protocol: a[3] || '',
            domain: a[4] || '',
            port: a[6] || '',
            path: a[7] || '',
            query_s: a[9] || '',
            fragment: a[11] || ''
        });
        return this
    },
    setProtocol: function (a) {
        this.protocol = a;
        return this
    },
    getProtocol: function () {
        return this.protocol
    },
    setQueryData: function (a) {
        this.query_s = URI.implodeQuery(a);
        return this
    },
    addQueryData: function (a) {
        return this.setQueryData(copy_properties(this.getQueryData(), a))
    },
    removeQueryData: function (b) {
        if (!(b instanceof Array)) b = [b];
        var d = this.getQueryData();
        for (var a = 0, c = b.length; a < c; ++a) delete d[b[a]];
        return this.setQueryData(d)
    },
    getQueryData: function () {
        return URI.explodeQuery(this.query_s)
    },
    setFragment: function (a) {
        this.fragment = a;
        return this
    },
    getFragment: function () {
        return this.fragment
    },
    setDomain: function (a) {
        this.domain = a;
        return this
    },
    getDomain: function () {
        return this.domain
    },
    setPort: function (a) {
        this.port = a;
        return this
    },
    getPort: function () {
        return this.port
    },
    setPath: function (a) {
        this.path = a;
        return this
    },
    getPath: function () {
        return this.path.replace(/^\/+/, '/')
    },
    toString: function () {
        var a = '';
        this.protocol && (a += this.protocol + '://');
        this.domain && (a += this.domain);
        this.port && (a += ':' + this.port);
        if (this.domain && !this.path) a += '/';
        this.path && (a += this.path);
        this.query_s && (a += '?' + this.query_s);
        this.fragment && (a += '#' + this.fragment);
        return a
    },
    valueOf: function () {
        return this.toString()
    },
    isFacebookURI: function () {
        if (!URI._facebookURIRegex) URI._facebookURIRegex = new RegExp('(^|\\.)facebook\\.com([^.]*)$', 'i');
        return (!this.domain || URI._facebookURIRegex.test(this.domain))
    },
    isQuicklingEnabled: function () {
        return window.Quickling && Quickling.isActive() && Quickling.isPageActive(this)
    },
    getRegisteredDomain: function () {
        if (!this.domain) return '';
        if (!this.isFacebookURI()) return null;
        var b = this.domain.split('.');
        var a = b.indexOf('facebook');
        return b.slice(a).join('.')
    },
    getUnqualifiedURI: function () {
        return new URI(this).setProtocol(null).setDomain(null).setPort(null)
    },
    getQualifiedURI: function () {
        var b = new URI(this);
        if (!b.getDomain()) {
            var a = URI();
            b.setProtocol(a.getProtocol()).setDomain(a.getDomain()).setPort(a.getPort())
        }
        return b
    },
    isSameOrigin: function (a) {
        var b = a || window.location.href;
        if (!(b instanceof URI)) b = new URI(b.toString());
        if (this.getProtocol() && this.getProtocol() != b.getProtocol()) return false;
        if (this.getDomain() && this.getDomain() != b.getDomain()) return false;
        return true
    },
    go: function (a) {
        goURI(this, a)
    },
    setSubdomain: function (b) {
        var c = new URI(this).getQualifiedURI();
        var a = c.getDomain().split('.');
        if (a.length <= 2) {
            a.unshift(b)
        } else a[0] = b;
        return c.setDomain(a.join('.'))
    },
    getSubdomain: function () {
        if (!this.getDomain()) return '';
        var a = this.getDomain().split('.');
        if (a.length <= 2) {
            return ''
        } else return a[0]
    },
    setSecure: function (a) {
        return this.setProtocol(a ? 'https' : 'http')
    },
    isSecure: function () {
        return this.getProtocol() == 'https'
    }
});

function detect_broken_proxy_cache(d, a) {
    var b = getCookie(a);
    if ((b != d) && (b != null) && (d != '0')) {
        var c = {
            c: 'si_detect_broken_proxy_cache',
            m: a + ' ' + d + ' ' + b
        };
        var e = new URI('/common/scribe_endpoint.php').getQualifiedURI().toString();
        new AsyncSignal(e, c).send()
    }
}
function HTML(a) {
    if (a && a.__html) a = a.__html;
    if (this === window) {
        if (a instanceof HTML) return a;
        return new HTML(a)
    }
    this._content = a;
    this._defer = false;
    this._extra_action = '';
    this._nodes = null;
    this._inline_js = bagofholding;
    this._has_option_elements = false;
    return this
}
HTML.isHTML = function (a) {
    return a && (a instanceof HTML || a.__html !== undefined)
};
HTML.replaceJSONWrapper = function (a) {
    return a && a.__html !== undefined ? new HTML(a.__html) : a
};
copy_properties(HTML.prototype, {
    toString: function () {
        var a = this._content || '';
        if (this._extra_action) a += '<script type="text/javascript">' + this._extra_action + '</scr' + 'ipt>';
        return a
    },
    setAction: function (a) {
        this._extra_action = a;
        return this
    },
    getAction: function () {
        this._fillCache();
        var a = function () {
                this._inline_js();
                eval_global(this._extra_action)
            }.bind(this);
        if (this.getDeferred()) {
            return a.defer.bind(a)
        } else return a
    },
    setDeferred: function (a) {
        this._defer = !! a;
        return this
    },
    getDeferred: function () {
        return this._defer
    },
    getContent: function () {
        return this._content
    },
    getNodes: function () {
        this._fillCache();
        return this._nodes
    },
    getRootNode: function () {
        return this.getNodes()[0]
    },
    hasOptionElements: function () {
        this._fillCache();
        return this._has_option_elements
    },
    _fillCache: function () {
        if (null !== this._nodes) return;
        var d = this._content;
        if (!d) {
            this._nodes = [];
            return
        }
        d = d.replace(/(<(\w+)[^>]*?)\/>/g, function (l, m, n) {
            return n.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? l : m + '></' + n + '>'
        });
        var h = d.trim().toLowerCase(),
            k = document.createElement('div'),
            b = false;
        var j = (!h.indexOf('<opt') && [1, '<select multiple="multiple" class="__WRAPPER">', '</select>']) || (!h.indexOf('<leg') && [1, '<fieldset class="__WRAPPER">', '</fieldset>']) || (h.match(/^<(thead|tbody|tfoot|colg|cap)/) && [1, '<table class="__WRAPPER">', '</table>']) || (!h.indexOf('<tr') && [2, '<table><tbody class="__WRAPPER">', '</tbody></table>']) || ((!h.indexOf('<td') || !h.indexOf('<th')) && [3, '<table><tbody><tr class="__WRAPPER">', '</tr></tbody></table>']) || (!h.indexOf('<col') && [2, '<table><tbody></tbody><colgroup class="__WRAPPER">', '</colgroup></table>']) || null;
        if (null === j) {
            k.className = '__WRAPPER';
            if (ua.ie()) {
                j = [0, '<span style="display:none">&nbsp;</span>', ''];
                b = true
            } else j = [0, '', '']
        }
        k.innerHTML = j[1] + d + j[2];
        while (j[0]--) k = k.lastChild;
        if (b) k.removeChild(k.firstChild);
        k.className != '__WRAPPER';
        if (0 != k.getElementsByTagName('option').length) this._has_option_elements = true;
        if (ua.ie()) {
            var i;
            if (!h.indexOf('<table') && -1 == h.indexOf('<tbody')) {
                i = k.firstChild && k.firstChild.childNodes
            } else if (j[1] == '<table>' && -1 == h.indexOf('<tbody')) {
                i = k.childNodes
            } else i = [];
            for (var f = i.length - 1; f >= 0; --f) if (i[f].nodeName && i[f].nodeName.toLowerCase() == 'tbody' && i[f].childNodes.length == 0) i[f].parentNode.removeChild(i[f])
        }
        var g = k.getElementsByTagName('script');
        var a = [];
        for (var e = 0; e < g.length; e++) if (g[e].src) {
            a.push(Bootloader.requestResource.bind(Bootloader, 'js', g[e].src))
        } else a.push(eval_global.bind(null, g[e].innerHTML));
        for (var e = g.length - 1; e >= 0; e--) g[e].parentNode.removeChild(g[e]);
        var c = function () {
                for (var l = 0; l < a.length; l++) a[l]()
            };
        this._nodes = $A(k.childNodes);
        this._inline_js = c
    }
});
var DOM = {
    find: function (a, c) {
        var b = DOM.scry(a, c);
        return b[0]
    },
    scry: function (j, v) {
        if (!j) return [];
        var w = v.split(' ');
        var d = [j];
        var i = j === document;
        for (var m = 0; m < w.length; m++) {
            if (d.length == 0) break;
            if (w[m] == '') continue;
            var u = w[m];
            var s = [];
            var zd = false;
            if (u.charAt(0) == '^') if (m == 0) {
                zd = true;
                u = u.slice(1)
            } else return;
            u = u.replace(/\./g, ' .');
            u = u.replace(/\#/g, ' #');
            u = u.replace(/\[/g, ' [');
            var z = u.split(' ');
            var za = z[0] || '*';
            var n = z[1] && z[1].charAt(0) == '#';
            if (n) {
                var h = ge(z[1].slice(1), true);
                if (h && ('*' == za || h.tagName.toLowerCase() == za)) for (var q = 0; q < d.length; q++) if (zd && DOM.contains(h, d[q])) {
                    s = [h];
                    break
                } else if (document == d[q] || DOM.contains(d[q], h)) {
                    s = [h];
                    break
                }
            } else {
                var zc = [];
                var c = d.length;
                for (var o = 0; o < c; o++) {
                    if (zd) {
                        var k = [];
                        var g = d[o].parentNode;
                        var a = za == '*';
                        while (DOM.isNode(g, DOM.NODE_TYPES.ELEMENT)) {
                            if (a || g.tagName.toLowerCase() == za) k.push(g);
                            g = g.parentNode
                        }
                    } else var k = d[o].getElementsByTagName(za);
                    var l = k.length;
                    for (var r = 0; r < l; r++) zc.push(k[r])
                }
                for (var x = 1; x < z.length; x++) {
                    var y = z[x];
                    var p = y.charAt(0) == '.';
                    var e = y.substring(1);
                    for (var o = 0; o < zc.length; o++) {
                        var zb = zc[o];
                        if (!zb) continue;
                        if (p) {
                            if (!CSS.hasClass(zb, e)) delete zc[o];
                            continue
                        } else {
                            var f = y.slice(1, y.length - 1);
                            if (f.indexOf('=') == -1) {
                                if (zb.getAttribute(f) === null) {
                                    delete zc[o];
                                    continue
                                }
                            } else {
                                var t = f.split('=');
                                var b = t[0];
                                var ze = t[1];
                                ze = ze.slice(1, ze.length - 1);
                                if (zb.getAttribute(b) != ze) {
                                    delete zc[o];
                                    continue
                                }
                            }
                        }
                    }
                }
                for (var o = 0; o < zc.length; o++) if (zc[o]) {
                    s.push(zc[o]);
                    if (zd) break
                }
            }
            d = s
        }
        return d
    },
    getText: (function () {
        var a = document.createElement('div'),
            b = a.innerText == null ? 'textContent' : 'innerText';
        return function (c) {
            if (!c) {
                return ''
            } else if (DOM.isNode(c, DOM.NODE_TYPES.TEXT)) {
                return c.data
            } else return c[b]
        }
    })(),
    getSelection: function () {
        var b = window.getSelection,
            a = document.selection;
        if (b) {
            return b() + ''
        } else if (a) return a.createRange().text;
        return null
    },
    create: function (c, a, b) {
        c = document.createElement(c);
        if (a) {
            a = copy_properties({}, a);
            if (a.style) {
                copy_properties(c.style, a.style);
                delete a.style
            }
            for (var d in a) if (d.toLowerCase().indexOf('on') == 0) {
                if (!(typeof a[d] != 'function')) if (window.Event && Event.listen) {
                    Event.listen(c, d.substr(2), a[d])
                } else c[d] = a[d];
                delete a[d]
            }
            copy_properties(c, a)
        }
        if (b != undefined) DOM.setContent(c, b);
        return c
    },
    prependContent: function (c, b) {
        if (!DOM.isNode(c)) throw new Error('DOM.prependContent: reference element is not a node');
        var a = function (d) {
                if (c.firstChild) {
                    c.insertBefore(d, c.firstChild)
                } else c.appendChild(d)
            };
        return DOM._addContent(b, a, c)
    },
    insertAfter: function (c, b) {
        if (!DOM.isNode(c) || !c.parentNode) throw new Error('DOM.insertAfter: reference element is not a node');
        var a = function (d) {
                if (c.nextSibling) {
                    c.parentNode.insertBefore(d, c.nextSibling)
                } else c.parentNode.appendChild(d)
            };
        return DOM._addContent(b, a, c.parentNode)
    },
    insertBefore: function (b, c) {
        if (!DOM.isNode(c) || !c.parentNode) throw new Error('DOM.insertBefore: reference element is not a node or ' + 'does not have a parent.');
        var a = function (d) {
                c.parentNode.insertBefore(d, c)
            };
        return DOM._addContent(b, a, c.parentNode)
    },
    setContent: function (b, a) {
        if (!DOM.isNode(b)) throw new Error('DOM.setContent: reference element is not a node');
        DOM.empty(b);
        return DOM.appendContent(b, a)
    },
    appendContent: function (c, b) {
        if (!DOM.isNode(c)) throw new Error('DOM.appendContent: reference element is not a node');
        var a = function (d) {
                c.appendChild(d)
            };
        return DOM._addContent(b, a, c)
    },
    replace: function (c, b) {
        if (!DOM.isNode(c) || !c.parentNode) throw new Error('DOM.replace: reference element must be a node with a' + ' parent');
        var a = function (d) {
                c.parentNode.replaceChild(d, c)
            };
        return DOM._addContent(b, a, c.parentNode)
    },
    remove: function (a) {
        a = $(a);
        if (a.parentNode) a.parentNode.removeChild(a)
    },
    empty: function (a) {
        a = $(a);
        while (a.firstChild) DOM.remove(a.firstChild)
    },
    contains: function (b, a) {
        b = ge(b);
        a = ge(a);
        if (!b || !a) {
            return false
        } else if (b === a) {
            return true
        } else if (DOM.isNode(b, '#text')) {
            return false
        } else if (DOM.isNode(a, '#text')) {
            return DOM.contains(b, a.parentNode)
        } else if (b.contains) {
            return b.contains(a)
        } else if (b.compareDocumentPosition) {
            return !!(b.compareDocumentPosition(a) & 16)
        } else return false
    },
    getRootElement: function () {
        var a = null;
        if (window.Quickling && Quickling.isActive()) a = ge('content');
        return a || document.body
    },
    isNode: function (d, e) {
        if (typeof (Node) == 'undefined') Node = null;
        try {
            if (!d || !((Node != undefined && d instanceof Node) || d.nodeName)) return false
        } catch (a) {
            return false
        }
        if (typeof (e) !== 'undefined') {
            e = $A(e).map(function (g) {
                return (g + '').toUpperCase()
            });
            var c, f;
            try {
                c = new String(d.nodeName).toUpperCase();
                f = d.nodeType
            } catch (a) {
                return false
            }
            for (var b = 0; b < e.length; b++) try {
                if (c == e[b] || f == e[b]) return true
            } catch (a) {}
            return false
        }
        return true
    },
    NODE_TYPES: {
        ELEMENT: 1,
        ATTRIBUTE: 2,
        TEXT: 3,
        CDATA_SECTION: 4,
        ENTITY_REFERENCE: 5,
        ENTITY: 6,
        PROCESSING_INSTRUCTION: 7,
        COMMENT: 8,
        DOCUMENT: 9,
        DOCUMENT_TYPE: 10,
        DOCUMENT_FRAGMENT: 11,
        NOTATION_NODE: 12
    },
    _addContent: function (d, a, l) {
        d = HTML.replaceJSONWrapper(d);
        if (d instanceof HTML && -1 == d.toString().indexOf('<scr' + 'ipt') && '' == l.innerHTML) {
            var g = ua.ie();
            if (!g || (g > 7 && !DOM.isNode(l, ['table', 'tbody', 'thead', 'tfoot', 'tr', 'select', 'fieldset']))) {
                l.innerHTML = d;
                return $A(l.childNodes)
            }
        } else if (DOM.isNode(l, DOM.NODE_TYPES.TEXT)) {
            l.data = d;
            return [d]
        }
        var i, e = [],
            b = [];
        var f = document.createDocumentFragment();
        if (!(d instanceof Array)) d = [d];
        for (var h = 0; h < d.length; h++) {
            i = HTML.replaceJSONWrapper(d[h]);
            if (i instanceof HTML) {
                b.push(i.getAction());
                var k = i.getNodes(),
                    c;
                for (var j = 0; j < k.length; j++) {
                    c = (ua.safari() || (ua.ie() && i.hasOptionElements())) ? k[j] : k[j].cloneNode(true);
                    e.push(c);
                    f.appendChild(c)
                }
            } else if (is_scalar(i)) {
                var m = document.createTextNode(i);
                e.push(m);
                f.appendChild(m)
            } else if (DOM.isNode(i)) {
                e.push(i);
                f.appendChild(i)
            } else if (!(i instanceof Array)) i !== null
        }
        a(f);
        for (var h = 0; h < b.length; h++) b[h]();
        return e
    }
};

function $N(c, a, b) {
    if (typeof a != 'object' || DOM.isNode(a) || a instanceof Array || HTML.isHTML(a)) {
        b = a;
        a = null
    }
    return DOM.create(c, a, b)
}
var $$ = function _$$(a) {
        return DOM.scry.apply(null, [document].concat($A(arguments)))
    };
String.prototype.trim = function () {
    if (this == window) return null;
    return this.replace(/^\s*|\s*$/g, '')
};

function trim(b) {
    try {
        return String(b.toString()).trim()
    } catch (a) {
        return ''
    }
}
String.prototype.startsWith = function (a) {
    if (this == window) return null;
    return this.substring(0, a.length) == a
};
String.prototype.endsWith = function (a) {
    if (this == window) return null;
    return this.length >= a.length && this.substring(this.length - a.length) == a
};
String.prototype.split = (function (a) {
    return function (h, e) {
        var b = "";
        if (h === null || e === null) {
            return []
        } else if (typeof h == 'string') {
            return a.call(this, h, e)
        } else if (h === undefined) {
            return [this.toString()]
        } else if (h instanceof RegExp) {
            if (!h._2 || !h._1) {
                b = h.toString().replace(/^[\S\s]+\//, "");
                if (!h._1) if (!h.global) {
                    h._1 = new RegExp(h.source, "g" + b)
                } else h._1 = 1
            }
            separator1 = h._1 === 1 ? h : h._1;
            var i = (h._2 ? h._2 : h._2 = new RegExp("^" + separator1.source + "$", b));
            if (e === undefined || e < 0) {
                e = false
            } else {
                e = Math.floor(e);
                if (!e) return []
            }
            var f, g = [],
                d = 0,
                c = 0;
            while ((e ? c++ <= e : true) && (f = separator1.exec(this))) {
                if ((f[0].length === 0) && (separator1.lastIndex > f.index)) separator1.lastIndex--;
                if (separator1.lastIndex > d) {
                    if (f.length > 1) f[0].replace(i, function () {
                        for (var j = 1; j < arguments.length - 2; j++) if (arguments[j] === undefined) f[j] = undefined
                    });
                    g = g.concat(this.substring(d, f.index), (f.index === this.length ? [] : f.slice(1)));
                    d = separator1.lastIndex
                }
                if (f[0].length === 0) separator1.lastIndex++
            }
            return (d === this.length) ? (separator1.test("") ? g : g.concat("")) : (e ? g : g.concat(this.substring(d)))
        } else return a.call(this, h, e)
    }
})(String.prototype.split);
add_properties('CSS', {
    shown: function (a) {
        return !CSS.hasClass(a, 'hidden_elem')
    },
    toggle: function (a) {
        CSS.conditionShow(a, !CSS.shown(a))
    },
    setClass: function (b, a) {
        $(b).className = a || '';
        return b
    },
    setStyle: function (a, b, d) {
        switch (b) {
        case 'opacity':
            var c = (d == 1);
            a.style.opacity = c ? '' : '' + d;
            a.style.filter = c ? '' : 'alpha(opacity=' + d * 100 + ')';
            break;
        case 'float':
            a.style.cssFloat = a.style.styleFloat = d;
            break;
        default:
            b = b.replace(/-(.)/g, function (e, f) {
                return f.toUpperCase()
            });
            a.style[b] = d
        }
        return a
    },
    getStyle: function (b, d) {
        b = $(b);

        function c(e) {
            return e.replace(/([A-Z])/g, '-$1').toLowerCase()
        }
        if (window.getComputedStyle) {
            var a = window.getComputedStyle(b, null);
            if (a) return a.getPropertyValue(c(d))
        }
        if (document.defaultView && document.defaultView.getComputedStyle) {
            var a = document.defaultView.getComputedStyle(b, null);
            if (a) return a.getPropertyValue(c(d));
            if (d == "display") return "none"
        }
        if (b.currentStyle) return b.currentStyle[d];
        return b.style[d]
    },
    getOpacity: function (a) {
        a = $(a);
        var b = CSS.getStyle(a, 'filter');
        var c = null;
        if (b && (c = /(\d+(?:\.\d+)?)/.exec(b))) {
            return parseFloat(c.pop()) / 100
        } else if (b = CSS.getStyle(a, 'opacity')) {
            return parseFloat(b)
        } else return 1
    }
});

function intl_locale_is_rtl() {
    return ('rtl' == CSS.getStyle(document.body, 'direction'))
}
DataStore = window.DataStore || {
    _storage: {},
    _elements: {},
    _tokenCounter: 1,
    _NOT_IN_DOM_CONST: 1,
    _getStorage: function (a) {
        var b;
        if (typeof a == 'string') {
            b = 'str_' + a
        } else {
            b = 'elem_' + (a.__FB_TOKEN || (a.__FB_TOKEN = [DataStore._tokenCounter++]))[0];
            DataStore._elements[b] = a
        }
        return DataStore._storage[b] || (DataStore._storage[b] = {})
    },
    _shouldDeleteData: function (a) {
        if (!a.nodeName) return false;
        try {
            if (null != a.offsetParent) return false
        } catch (b) {}
        if (document.documentElement.contains) {
            return !document.documentElement.contains(a)
        } else return (document.documentElement.compareDocumentPosition(a) & DataStore._NOT_IN_DOM_CONST)
    },
    set: function (c, b, d) {
        var a = DataStore._getStorage(c);
        a[b] = d;
        return c
    },
    get: function (e, d, c) {
        var b = DataStore._getStorage(e),
            f = b[d];
        if (typeof f === 'undefined' && e.getAttribute) {
            var a = e.getAttribute('data-' + d);
            f = (null === a) ? undefined : a
        }
        if ((c !== undefined) && (f === undefined)) f = b[d] = c;
        return f
    },
    remove: function (c, b) {
        var a = DataStore._getStorage(c),
            d = a[b];
        delete a[b];
        return d
    },
    cleanup: function () {
        var b, a;
        for (b in DataStore._elements) {
            a = DataStore._elements[b];
            if (DataStore._shouldDeleteData(a)) {
                delete DataStore._storage[b];
                delete DataStore._elements[b]
            }
        }
    }
};
Event.DATASTORE_KEY = 'Event.listeners';
if (!Event.prototype) Event.prototype = {};

function $E(a) {
    a = a || window.event || {};
    if (!a._inherits_from_prototype) for (var c in Event.prototype) try {
        a[c] = Event.prototype[c]
    } catch (b) {}
    return a
}(function () {
    copy_properties(Event.prototype, {
        _inherits_from_prototype: true,
        stop: function () {
            this.cancelBubble = true;
            this.stopPropagation && this.stopPropagation();
            return this
        },
        prevent: function () {
            this.returnValue = false;
            this.preventDefault && this.preventDefault();
            return this
        },
        kill: function () {
            this.stop().prevent();
            return false
        },
        getTarget: function () {
            var g = this.target || this.srcElement;
            return g ? $(g) : null
        },
        getRelatedTarget: function () {
            var g = this.relatedTarget || this.fromElement;
            return g ? $(g) : null
        },
        getModifiers: function () {
            var g = {
                control: !! this.ctrlKey,
                shift: !! this.shiftKey,
                alt: !! this.altKey,
                meta: !! this.metaKey
            };
            g.access = ua.osx() ? g.control : g.alt;
            g.any = g.control || g.shift || g.alt || g.meta;
            return g
        }
    });
    copy_properties(Event, {
        listen: function (h, p, j, m) {
            if (typeof h == 'string') h = $(h);
            if (typeof m == 'undefined') m = Event.Priority.NORMAL;
            if (typeof p == 'object') {
                var i = {};
                for (var o in p) i[o] = Event.listen(h, o, p[o], m);
                return i
            }
            if (p.match(/^on/i)) throw new TypeError("Bad event name `" + event + "': use `click', not `onclick'.");
            p = p.toLowerCase();
            var k = DataStore.get(h, b, {});
            if (f[p]) {
                var g = f[p];
                p = g.base;
                j = g.wrap(j)
            }
            a(h, p);
            var q = k[p];
            if (!(m in q)) q[m] = [];
            var l = q[m].length,
                n = new EventHandlerRef(j, q[m], l);
            q[m].push(n);
            return n
        },
        stop: function (g) {
            return $E(g).stop()
        },
        prevent: function (g) {
            return $E(g).prevent()
        },
        kill: function (g) {
            return $E(g).kill()
        },
        getKeyCode: function (event) {
            event = $E(event);
            if (!event) return false;
            switch (event.keyCode) {
            case 63232:
                return 38;
            case 63233:
                return 40;
            case 63234:
                return 37;
            case 63235:
                return 39;
            case 63272:
            case 63273:
            case 63275:
                return null;
            case 63276:
                return 33;
            case 63277:
                return 34
            }
            if (event.shiftKey) switch (event.keyCode) {
            case 33:
            case 34:
            case 37:
            case 38:
            case 39:
            case 40:
                return null
            }
            return event.keyCode
        },
        getPriorities: function () {
            if (!e) {
                var g = values(Event.Priority);
                g.sort(function (h, i) {
                    return h - i
                });
                e = g
            }
            return e
        },
        __fire: function (g, i, event) {
            var h = Event.__getHandler(g, i);
            if (h) return h($E(event))
        },
        __getHandler: function (g, h) {
            return DataStore.get(g, Event.DATASTORE_KEY + h)
        }
    });
    var e = null,
        b = Event.DATASTORE_KEY;
    var c = function (g) {
            return function (h) {
                if (!DOM.contains(this, h.getRelatedTarget())) return g.call(this, h)
            }
        };
    var f = {
        mouseenter: {
            base: 'mouseover',
            wrap: c
        },
        mouseleave: {
            base: 'mouseout',
            wrap: c
        }
    };
    var a = function (g, l) {
            var h = 'on' + l;
            var k = d.bind(g);
            var j = DataStore.get(g, b);
            if (l in j) return;
            j[l] = {};
            if (g.addEventListener) {
                g.addEventListener(l, k, false)
            } else if (g.attachEvent) g.attachEvent(h, k);
            DataStore.set(g, b + l, k);
            if (g[h]) {
                var i = g[h];
                g[h] = null;
                Event.listen(g, l, i, Event.Priority.TRADITIONAL)
            }
            if (g.nodeName === 'FORM' && l === 'submit') Event.listen(g, l, Event.__bubbleSubmit.curry(g), Event.Priority._BUBBLE)
        };
    var d = function (event) {
            event = $E(event);
            var n = event.type;
            if (!DataStore.get(this, b)) throw new Error("Bad listenHandler context.");
            var o = DataStore.get(this, b)[n];
            if (!o) throw new Error("No registered handlers for `" + n + "'.");
            if (n == 'click') {
                var i = Parent.byTag(event.getTarget(), 'a');
                user_action(i, n, event)
            }
            var k = Event.getPriorities();
            for (var j = 0; j < k.length; j++) {
                var l = k[j];
                if (l in o) {
                    var g = o[l];
                    for (var h = 0; h < g.length; h++) {
                        if (!g[h]) continue;
                        var m = g[h].fire(this, event);
                        if (m === false) {
                            return event.kill()
                        } else if (event.cancelBubble) return event.stop()
                    }
                }
            }
            return event.returnValue
        }
})();
Event.Priority = {
    URGENT: -20,
    TRADITIONAL: -10,
    NORMAL: 0,
    _BUBBLE: 1000
};

function EventHandlerRef(b, a, c) {
    this._handler = b;
    this._container = a;
    this._index = c
}
EventHandlerRef.prototype = {
    remove: function () {
        delete this._handler;
        delete this._container[this._index]
    },
    fire: function (a, event) {
        return this._handler.call(a, event)
    }
};

function Vector2(b, c, a) {
    copy_properties(this, {
        x: parseFloat(b),
        y: parseFloat(c),
        domain: a || 'pure'
    })
}
copy_properties(Vector2.prototype, {
    toString: function () {
        return '(' + this.x + ', ' + this.y + ')'
    },
    add: function (c, d) {
        if (arguments.length == 1) {
            if (c.domain != 'pure') c = c.convertTo(this.domain);
            return this.add(c.x, c.y)
        }
        var a = parseFloat(c);
        var b = parseFloat(d);
        return new Vector2(this.x + a, this.y + b, this.domain)
    },
    mul: function (a, b) {
        if (typeof (b) == "undefined") b = a;
        return new Vector2(this.x * a, this.y * b, this.domain)
    },
    sub: function (a, b) {
        if (arguments.length == 1) {
            return this.add(a.mul(-1))
        } else return this.add(-a, -b)
    },
    distanceTo: function (a) {
        return this.sub(a).magnitude()
    },
    magnitude: function () {
        return Math.sqrt((this.x * this.x) + (this.y * this.y))
    },
    convertTo: function (a) {
        if (a != 'pure' && a != 'viewport' && a != 'document') return new Vector2(0, 0);
        if (a == this.domain) return new Vector2(this.x, this.y, this.domain);
        if (a == 'pure') return new Vector2(this.x, this.y);
        if (this.domain == 'pure') return new Vector2(0, 0);
        var b = Vector2.getScrollPosition('document');
        var c = this.x,
            d = this.y;
        if (this.domain == 'document') {
            c -= b.x;
            d -= b.y
        } else {
            c += b.x;
            d += b.y
        }
        return new Vector2(c, d, a)
    },
    setElementPosition: function (a) {
        var b = this.convertTo('document');
        a.style.left = parseInt(b.x) + 'px';
        a.style.top = parseInt(b.y) + 'px';
        return this
    },
    setElementDimensions: function (a) {
        return this.setElementWidth(a).setElementHeight(a)
    },
    setElementWidth: function (a) {
        a.style.width = parseInt(this.x, 10) + 'px';
        return this
    },
    setElementHeight: function (a) {
        a.style.height = parseInt(this.y, 10) + 'px';
        return this
    },
    scrollElementBy: function (a) {
        if (a == document.body) {
            window.scrollBy(this.x, this.y)
        } else {
            a.scrollLeft += this.x;
            a.scrollTop += this.y
        }
        return this
    }
});
copy_properties(Vector2, {
    getEventPosition: function (b, a) {
        a = a || 'document';
        b = $E(b);
        var d = b.pageX || (b.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft));
        var e = b.pageY || (b.clientY + (document.documentElement.scrollTop || document.body.scrollTop));
        var c = new Vector2(d, e, 'document');
        return c.convertTo(a)
    },
    getScrollPosition: function (a) {
        a = a || 'document';
        var b = document.body.scrollLeft || document.documentElement.scrollLeft;
        var c = document.body.scrollTop || document.documentElement.scrollTop;
        return new Vector2(b, c, 'document').convertTo(a)
    },
    getElementPosition: function (c, b) {
        b = b || 'document';
        if (!c) return;
        if (!('getBoundingClientRect' in c)) return new Vector2(0, 0, 'document');
        var e = c.getBoundingClientRect(),
            a = document.documentElement,
            d = Math.round(e.left) - a.clientLeft,
            f = Math.round(e.top) - a.clientTop;
        return new Vector2(d, f, 'viewport').convertTo(b)
    },
    getElementDimensions: function (a) {
        return new Vector2(a.offsetWidth || 0, a.offsetHeight || 0)
    },
    getViewportDimensions: function () {
        var a = (window && window.innerWidth) || (document && document.documentElement && document.documentElement.clientWidth) || (document && document.body && document.body.clientWidth) || 0;
        var b = (window && window.innerHeight) || (document && document.documentElement && document.documentElement.clientHeight) || (document && document.body && document.body.clientHeight) || 0;
        return new Vector2(a, b, 'viewport')
    },
    getDocumentDimensions: function () {
        var a = (document && document.documentElement && document.documentElement.scrollWidth) || (document && document.body && document.body.scrollWidth) || 0;
        var b = (document && document.documentElement && document.documentElement.scrollHeight) || (document && document.body && document.body.scrollHeight) || 0;
        return new Vector2(a, b, 'document')
    }
});
var operaIgnoreScroll = {
    table: true,
    'inline-table': true,
    inline: true
};

function elementX(a) {
    return Vector2.getElementPosition(a, 'document').x
}
function elementY(a) {
    return Vector2.getElementPosition(a, 'document').y
}
function KeyEventController() {
    this.handlers = {};
    document.onkeyup = this.onkeyevent.bind(this, 'onkeyup');
    document.onkeydown = this.onkeyevent.bind(this, 'onkeydown');
    document.onkeypress = this.onkeyevent.bind(this, 'onkeypress')
}
copy_properties(KeyEventController, {
    instance: null,
    getInstance: function () {
        return KeyEventController.instance || (KeyEventController.instance = new KeyEventController())
    },
    defaultFilter: function (event, a) {
        event = $E(event);
        return KeyEventController.filterEventTypes(event, a) && KeyEventController.filterEventTargets(event, a) && KeyEventController.filterEventModifiers(event, a)
    },
    filterEventTypes: function (event, a) {
        if (a === 'onkeydown') return true;
        return false
    },
    filterEventTargets: function (event, b) {
        var a = $E(event).getTarget();
        if (DOM.isNode(a, ['input', 'select', 'textarea', 'object', 'embed'])) if (a.type != 'checkbox' && a.type != 'radio' && a.type != 'submit') return false;
        return a.getAttribute('contentEditable') != 'true'
    },
    filterEventModifiers: function (event, a) {
        if (event.ctrlKey || event.altKey || event.metaKey || event.repeat) return false;
        return true
    },
    registerKey: function (f, a, d, g) {
        if (d === undefined) d = KeyEventController.defaultFilter;
        var b = KeyEventController.getInstance();
        var c = b.mapKey(f);
        if (is_empty(b.handlers)) onleaveRegister(b.resetHandlers.bind(b));
        for (var e = 0; e < c.length; e++) {
            f = c[e];
            if (!b.handlers[f] || g) b.handlers[f] = [];
            b.handlers[f].push({
                callback: a,
                filter: d
            })
        }
    },
    keyCodeMap: {
        BACKSPACE: [8],
        TAB: [9],
        RETURN: [13],
        ESCAPE: [27],
        LEFT: [37, 63234],
        UP: [38, 63232],
        RIGHT: [39, 63235],
        DOWN: [40, 63233],
        DELETE: [46],
        COMMA: [188],
        PERIOD: [190],
        '`': [192],
        '[': [219],
        ']': [221]
    }
});
copy_properties(KeyEventController.prototype, {
    mapKey: function (a) {
        if (typeof (a) == 'number') return [48 + a, 96 + a];
        var b = KeyEventController.keyCodeMap[a.toUpperCase()];
        if (b) return b;
        return [a.toUpperCase().charCodeAt(0)]
    },
    onkeyevent: function (i, c) {
        c = $E(c);
        var d = null;
        var g = this.handlers[c.keyCode];
        var b, f, a;
        if (g) for (var h = 0; h < g.length; h++) {
            b = g[h].callback;
            f = g[h].filter;
            try {
                if (!f || f(c, i)) {
                    var node = null;
                    if (window.Parent && Parent.byTag && c.getTarget) node = Parent.byTag(c.getTarget(), 'a');
                    user_action(node, 'key', c);
                    a = b(c, i);
                    if (a === false) return Event.kill(c)
                }
            } catch (e) {}
        }
        return true
    },
    resetHandlers: function () {
        this.handlers = {}
    }
});

function DOMControl(a) {
    this.root = $(a);
    this.updating = false;
    DataStore.set(a, 'DOMControl', this)
}
DOMControl.prototype = {
    getRoot: function () {
        return this.root
    },
    beginUpdate: function () {
        if (this.updating) return false;
        this.updating = true;
        return true
    },
    endUpdate: function () {
        this.updating = false
    },
    update: function (a) {
        if (!this.beginUpdate()) return this;
        this.onupdate(a);
        this.endUpdate()
    }
};
DOMControl.getInstance = function (a) {
    return DataStore.get(a, 'DOMControl')
};
add_properties('CSS', {
    supportsBorderRadius: function () {
        var c = ['KhtmlBorderRadius', 'OBorderRadius', 'MozBorderRadius', 'WebkitBorderRadius', 'msBorderRadius', 'borderRadius'];
        var d = false,
            a = document.createElement('div');
        for (var b = c.length; b >= 0; b--) if (d = a.style[c[b]] !== undefined) break;
        CSS.supportsBorderRadius = bagof(d);
        return d
    }
});
add_properties('Input', {
    focus: function (a) {
        try {
            a.focus()
        } catch (b) {}
    },
    isEmpty: function (a) {
        return !(/\S/).test(a.value || '') || CSS.hasClass(a, 'DOMControl_placeholder')
    },
    getValue: function (a) {
        return Input.isEmpty(a) ? '' : a.value
    },
    setValue: function (b, c) {
        CSS.removeClass(b, 'DOMControl_placeholder');
        b.value = c;
        var a = DOMControl.getInstance(b);
        a && a.resetHeight && a.resetHeight()
    },
    setPlaceholder: function (a, b) {
        a.setAttribute('title', b);
        a.setAttribute('placeholder', b);
        if (a == document.activeElement) return;
        if (Input.isEmpty(a)) {
            CSS.conditionClass(a, 'DOMControl_placeholder', b);
            a.value = b
        }
    },
    reset: function (a) {
        Input.setValue(a, '');
        var b = a.getAttribute('placeholder');
        b && Input.setPlaceholder(a, b);
        a.style.height = ''
    },
    setSubmitOnEnter: function (a, b) {
        CSS.conditionClass(a, 'enter_submit', b)
    },
    getSubmitOnEnter: function (a) {
        return CSS.hasClass(a, 'enter_submit')
    }
});

function animation(a) {
    if (a == undefined) return;
    if (this == window) {
        return new animation(a)
    } else {
        this.obj = a;
        this._reset_state();
        this.queue = [];
        this.last_attr = null
    }
}
animation.resolution = 20;
animation.offset = 0;
animation.prototype._reset_state = function () {
    this.state = {
        attrs: {},
        duration: 500
    }
};
animation.prototype.stop = function () {
    this._reset_state();
    this.queue = [];
    return this
};
animation.prototype._build_container = function () {
    if (this.container_div) {
        this._refresh_container();
        return
    }
    if (this.obj.firstChild && this.obj.firstChild.__animation_refs) {
        this.container_div = this.obj.firstChild;
        this.container_div.__animation_refs++;
        this._refresh_container();
        return
    }
    var b = document.createElement('div');
    b.style.padding = '0px';
    b.style.margin = '0px';
    b.style.border = '0px';
    b.__animation_refs = 1;
    var a = this.obj.childNodes;
    while (a.length) b.appendChild(a[0]);
    this.obj.appendChild(b);
    this._orig_overflow = this.obj.style.overflow;
    this.obj.style.overflow = 'hidden';
    this.container_div = b;
    this._refresh_container()
};
animation.prototype._refresh_container = function () {
    this.container_div.style.height = 'auto';
    this.container_div.style.width = 'auto';
    this.container_div.style.height = this.container_div.offsetHeight + 'px';
    this.container_div.style.width = this.container_div.offsetWidth + 'px'
};
animation.prototype._destroy_container = function () {
    if (!this.container_div) return;
    if (!--this.container_div.__animation_refs) {
        var a = this.container_div.childNodes;
        while (a.length) this.obj.appendChild(a[0]);
        this.obj.removeChild(this.container_div)
    }
    this.container_div = null;
    this.obj.style.overflow = this._orig_overflow
};
animation.ATTR_TO = 1;
animation.ATTR_BY = 2;
animation.ATTR_FROM = 3;
animation.prototype._attr = function (a, d, c) {
    a = a.replace(/-[a-z]/gi, function (e) {
        return e.substring(1).toUpperCase()
    });
    var b = false;
    switch (a) {
    case 'background':
        this._attr('backgroundColor', d, c);
        return this;
    case 'margin':
        d = animation.parse_group(d);
        this._attr('marginBottom', d[0], c);
        this._attr('marginLeft', d[1], c);
        this._attr('marginRight', d[2], c);
        this._attr('marginTop', d[3], c);
        return this;
    case 'padding':
        d = animation.parse_group(d);
        this._attr('paddingBottom', d[0], c);
        this._attr('paddingLeft', d[1], c);
        this._attr('paddingRight', d[2], c);
        this._attr('paddingTop', d[3], c);
        return this;
    case 'backgroundColor':
    case 'borderColor':
    case 'color':
        d = animation.parse_color(d);
        break;
    case 'opacity':
        d = parseFloat(d, 10);
        break;
    case 'height':
    case 'width':
        if (d == 'auto') {
            b = true
        } else d = parseInt(d, 10);
        break;
    case 'borderWidth':
    case 'lineHeight':
    case 'fontSize':
    case 'marginBottom':
    case 'marginLeft':
    case 'marginRight':
    case 'marginTop':
    case 'paddingBottom':
    case 'paddingLeft':
    case 'paddingRight':
    case 'paddingTop':
    case 'bottom':
    case 'left':
    case 'right':
    case 'top':
    case 'scrollTop':
    case 'scrollLeft':
        d = parseInt(d, 10);
        break;
    default:
        throw new Error(a + ' is not a supported attribute!')
    }
    if (this.state.attrs[a] === undefined) this.state.attrs[a] = {};
    if (b) this.state.attrs[a].auto = true;
    switch (c) {
    case animation.ATTR_FROM:
        this.state.attrs[a].start = d;
        break;
    case animation.ATTR_BY:
        this.state.attrs[a].by = true;
    case animation.ATTR_TO:
        this.state.attrs[a].value = d;
        break
    }
};
animation._get_box_width = function (c) {
    var d = parseInt(CSS.getStyle(c, 'paddingLeft'), 10),
        e = parseInt(CSS.getStyle(c, 'paddingRight'), 10),
        a = parseInt(CSS.getStyle(c, 'borderLeftWidth'), 10),
        b = parseInt(CSS.getStyle(c, 'borderRightWidth'), 10);
    return c.offsetWidth - (d ? d : 0) - (e ? e : 0) - (a ? a : 0) - (b ? b : 0)
};
animation._get_box_height = function (c) {
    var e = parseInt(CSS.getStyle(c, 'paddingTop'), 10),
        d = parseInt(CSS.getStyle(c, 'paddingBottom'), 10),
        a = parseInt(CSS.getStyle(c, 'borderTopWidth'), 10),
        b = parseInt(CSS.getStyle(c, 'borderBottomWidth'), 10);
    return c.offsetHeight - (e ? e : 0) - (d ? d : 0) - (a ? a : 0) - (b ? b : 0)
};
animation.prototype.to = function (a, b) {
    if (b === undefined) {
        this._attr(this.last_attr, a, animation.ATTR_TO)
    } else {
        this._attr(a, b, animation.ATTR_TO);
        this.last_attr = a
    }
    return this
};
animation.prototype.by = function (a, b) {
    if (b === undefined) {
        this._attr(this.last_attr, a, animation.ATTR_BY)
    } else {
        this._attr(a, b, animation.ATTR_BY);
        this.last_attr = a
    }
    return this
};
animation.prototype.from = function (a, b) {
    if (b === undefined) {
        this._attr(this.last_attr, a, animation.ATTR_FROM)
    } else {
        this._attr(a, b, animation.ATTR_FROM);
        this.last_attr = a
    }
    return this
};
animation.prototype.duration = function (a) {
    this.state.duration = a ? a : 0;
    return this
};
animation.prototype.checkpoint = function (b, a) {
    if (b === undefined) b = 1;
    this.state.checkpoint = b;
    this.queue.push(this.state);
    this._reset_state();
    this.state.checkpointcb = a;
    return this
};
animation.prototype.blind = function () {
    this.state.blind = true;
    return this
};
animation.prototype.hide = function () {
    this.state.hide = true;
    return this
};
animation.prototype.show = function () {
    this.state.show = true;
    return this
};
animation.prototype.ease = function (a) {
    this.state.ease = a;
    return this
};
animation.prototype.go = function () {
    var b = (new Date()).getTime();
    this.queue.push(this.state);
    for (var a = 0; a < this.queue.length; a++) {
        this.queue[a].start = b - animation.offset;
        if (this.queue[a].checkpoint) b += this.queue[a].checkpoint * this.queue[a].duration
    }
    animation.push(this);
    return this
};
animation.prototype._show = function () {
    CSS.show(this.obj)
};
animation.prototype._hide = function () {
    CSS.hide(this.obj)
};
animation.prototype._frame = function (l) {
    var d = true;
    var k = false;
    var n = false;
    for (var e = 0; e < this.queue.length; e++) {
        var b = this.queue[e];
        if (b.start > l) {
            d = false;
            continue
        }
        if (b.checkpointcb) {
            this._callback(b.checkpointcb, l - b.start);
            b.checkpointcb = null
        }
        if (b.started === undefined) {
            if (b.show) this._show();
            for (var a in b.attrs) {
                if (b.attrs[a].start !== undefined) continue;
                switch (a) {
                case 'backgroundColor':
                case 'borderColor':
                case 'color':
                    var m = animation.parse_color(CSS.getStyle(this.obj, a == 'borderColor' ? 'borderLeftColor' : a));
                    if (b.attrs[a].by) {
                        b.attrs[a].value[0] = Math.min(255, Math.max(0, b.attrs[a].value[0] + m[0]));
                        b.attrs[a].value[1] = Math.min(255, Math.max(0, b.attrs[a].value[1] + m[1]));
                        b.attrs[a].value[2] = Math.min(255, Math.max(0, b.attrs[a].value[2] + m[2]))
                    }
                    break;
                case 'opacity':
                    var m = CSS.getOpacity(this.obj);
                    if (b.attrs[a].by) b.attrs[a].value = Math.min(1, Math.max(0, b.attrs[a].value + m));
                    break;
                case 'height':
                    var m = animation._get_box_height(this.obj);
                    if (b.attrs[a].by) b.attrs[a].value += m;
                    break;
                case 'width':
                    var m = animation._get_box_width(this.obj);
                    if (b.attrs[a].by) b.attrs[a].value += m;
                    break;
                case 'scrollLeft':
                case 'scrollTop':
                    var m = (this.obj == document.body) ? (document.documentElement[a] || document.body[a]) : this.obj[a];
                    if (b.attrs[a].by) b.attrs[a].value += m;
                    b['last' + a] = m;
                    break;
                default:
                    var m = parseInt(CSS.getStyle(this.obj, a), 10) || 0;
                    if (b.attrs[a].by) b.attrs[a].value += m;
                    break
                }
                b.attrs[a].start = m
            }
            if ((b.attrs.height && b.attrs.height.auto) || (b.attrs.width && b.attrs.width.auto)) {
                if (ua.firefox() < 3) n = true;
                this._destroy_container();
                for (var a in {
                    height: 1,
                    width: 1,
                    fontSize: 1,
                    borderLeftWidth: 1,
                    borderRightWidth: 1,
                    borderTopWidth: 1,
                    borderBottomWidth: 1,
                    paddingLeft: 1,
                    paddingRight: 1,
                    paddingTop: 1,
                    paddingBottom: 1
                }) if (b.attrs[a]) this.obj.style[a] = b.attrs[a].value + (typeof b.attrs[a].value == 'number' ? 'px' : '');
                if (b.attrs.height && b.attrs.height.auto) b.attrs.height.value = animation._get_box_height(this.obj);
                if (b.attrs.width && b.attrs.width.auto) b.attrs.width.value = animation._get_box_width(this.obj)
            }
            b.started = true;
            if (b.blind) this._build_container()
        }
        var h = (l - b.start) / b.duration;
        if (h >= 1) {
            h = 1;
            if (b.hide) this._hide()
        } else d = false;
        var j = b.ease ? b.ease(h) : h;
        if (!k && h != 1 && b.blind) k = true;
        if (n && this.obj.parentNode) {
            var i = this.obj.parentNode;
            var g = this.obj.nextSibling;
            i.removeChild(this.obj)
        }
        for (var a in b.attrs) switch (a) {
        case 'backgroundColor':
        case 'borderColor':
        case 'color':
            this.obj.style[a] = 'rgb(' + animation.calc_tween(j, b.attrs[a].start[0], b.attrs[a].value[0], true) + ',' + animation.calc_tween(j, b.attrs[a].start[1], b.attrs[a].value[1], true) + ',' + animation.calc_tween(j, b.attrs[a].start[2], b.attrs[a].value[2], true) + ')';
            break;
        case 'opacity':
            CSS.setStyle(this.obj, 'opacity', animation.calc_tween(j, b.attrs[a].start, b.attrs[a].value));
            break;
        case 'height':
        case 'width':
            this.obj.style[a] = j == 1 && b.attrs[a].auto ? 'auto' : animation.calc_tween(j, b.attrs[a].start, b.attrs[a].value, true) + 'px';
            break;
        case 'scrollLeft':
        case 'scrollTop':
            var f = this.obj == document.body;
            var m = (f) ? (document.documentElement[a] || document.body[a]) : this.obj[a];
            if (b['last' + a] != m) {
                delete b.attrs[a]
            } else {
                var c = animation.calc_tween(j, b.attrs[a].start, b.attrs[a].value, true) - m;
                if (!f) {
                    this.obj[a] = c + m
                } else if (a == 'scrollLeft') {
                    window.scrollBy(c, 0)
                } else window.scrollBy(0, c);
                b['last' + a] = c + m
            }
            break;
        default:
            this.obj.style[a] = animation.calc_tween(j, b.attrs[a].start, b.attrs[a].value, true) + 'px';
            break
        }
        if (h == 1) {
            this.queue.splice(e--, 1);
            this._callback(b.ondone, l - b.start - b.duration)
        }
    }
    if (n) i[g ? 'insertBefore' : 'appendChild'](this.obj, g);
    if (!k && this.container_div) this._destroy_container();
    return !d
};
animation.prototype.ondone = function (a) {
    this.state.ondone = a;
    return this
};
animation.prototype._callback = function (a, b) {
    if (a) {
        animation.offset = b;
        a.call(this);
        animation.offset = 0
    }
};
animation.calc_tween = function (a, b, c, d) {
    return (d ? parseInt : parseFloat)((c - b) * a + b, 10)
};
animation.parse_color = function (a) {
    var b = /^#([a-f0-9]{1,2})([a-f0-9]{1,2})([a-f0-9]{1,2})$/i.exec(a);
    if (b) {
        return [parseInt(b[1].length == 1 ? b[1] + b[1] : b[1], 16), parseInt(b[2].length == 1 ? b[2] + b[2] : b[2], 16), parseInt(b[3].length == 1 ? b[3] + b[3] : b[3], 16)]
    } else {
        var c = /^rgba? *\(([0-9]+), *([0-9]+), *([0-9]+)(?:, *([0-9]+))?\)$/.exec(a);
        if (c) {
            if (c[4] === '0') {
                return [255, 255, 255]
            } else return [parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10)]
        } else if (a == 'transparent') {
            return [255, 255, 255]
        } else throw 'Named color attributes are not supported.'
    }
};
animation.parse_group = function (a) {
    var a = trim(a).split(/ +/);
    if (a.length == 4) {
        return a
    } else if (a.length == 3) {
        return [a[0], a[1], a[2], a[1]]
    } else if (a.length == 2) {
        return [a[0], a[1], a[0], a[1]]
    } else return [a[0], a[0], a[0], a[0]]
};
animation.push = function (a) {
    if (!animation.active) animation.active = [];
    animation.active.push(a);
    if (!animation.timeout) animation.timeout = setInterval(animation.animate.bind(animation), animation.resolution, false);
    animation.animate(true)
};
animation.animate = function (c) {
    var d = (new Date()).getTime();
    for (var b = c === true ? animation.active.length - 1 : 0; b < animation.active.length; b++) try {
        if (!animation.active[b]._frame(d)) animation.active.splice(b--, 1)
    } catch (a) {
        animation.active.splice(b--, 1)
    }
    if (animation.active.length == 0) {
        clearInterval(animation.timeout);
        animation.timeout = null
    }
};
animation.ease = {};
animation.ease.begin = function (a) {
    return Math.sin(Math.PI / 2 * (a - 1)) + 1
};
animation.ease.end = function (a) {
    return Math.sin(.5 * Math.PI * a)
};
animation.ease.both = function (a) {
    return .5 * Math.sin(Math.PI * (a - .5)) + .5
};
animation.prependInsert = function (b, a) {
    animation.insert(b, a, DOM.prependContent)
};
animation.appendInsert = function (b, a) {
    animation.insert(b, a, DOM.appendContent)
};
animation.insert = function (c, a, b) {
    CSS.setStyle(a, 'opacity', 0);
    b(c, a);
    animation(a).from('opacity', 0).to('opacity', 1).duration(400).go()
};

function show() {
    for (var b = 0; b < arguments.length; b++) {
        var a = ge(arguments[b]);
        if (a && a.style) a.style.display = ''
    }
    return false
}
function hide() {
    for (var b = 0; b < arguments.length; b++) {
        var a = ge(arguments[b]);
        if (a && a.style) a.style.display = 'none'
    }
    return false
}
function shown(a) {
    a = ge(a);
    return (a.style.display != 'none' && !(a.style.display == '' && a.offsetWidth == 0))
}
function toggle() {
    for (var b = 0; b < arguments.length; b++) {
        var a = $(arguments[b]);
        a.style.display = CSS.getStyle(a, "display") == 'block' ? 'none' : 'block'
    }
    return false
}
function toggleDisplayNone() {
    for (var b = 0; b < arguments.length; b++) {
        var a = $(arguments[b]);
        if (shown(a)) {
            hide(a)
        } else show(a)
    }
    return false
}
var KEYS = {
    BACKSPACE: 8,
    TAB: 9,
    RETURN: 13,
    ESC: 27,
    SPACE: 32,
    PAGE_UP: 33,
    PAGE_DOWN: 34,
    LEFT: 37,
    UP: 38,
    RIGHT: 39,
    DOWN: 40,
    DELETE: 46,
    COMMA: 188
};
var ErrorDialog = {
    showAsyncError: function (b) {
        try {
            return ErrorDialog.show(b.getErrorSummary(), b.getErrorDescription())
        } catch (a) {
            alert(b)
        }
    },
    show: function (c, b, a) {
        return (new Dialog()).setTitle(c).setBody(b).setButtons([Dialog.OK]).setStackable(true).setClassName('errorDialog').setModal(true).setHandler(a || bagofholding).show()
    }
};
add_properties('Form', {
    getInputs: function (a) {
        a = a || document;
        return [].concat($A(DOM.scry(a, 'input')), $A(DOM.scry(a, 'select')), $A(DOM.scry(a, 'textarea')), $A(DOM.scry(a, 'button')))
    },
    getSelectValue: function (a) {
        return a.options[a.selectedIndex].value
    },
    setSelectValue: function (b, c) {
        for (var a = 0; a < b.options.length; ++a) if (b.options[a].value == c) {
            b.selectedIndex = a;
            break
        }
    },
    getRadioValue: function (b) {
        for (var a = 0; a < b.length; a++) if (b[a].checked) return b[a].value;
        return null
    },
    getElements: function (a) {
        return $A(a.tagName == 'FORM' ? a.elements : Form.getInputs(a))
    },
    getAttribute: function (b, a) {
        return (b.getAttributeNode(a) || {}).value || null
    },
    setDisabled: function (b, a) {
        Form.getElements(b).forEach(function (c) {
            if (c.disabled != undefined) {
                var d = DataStore.get(c, 'origDisabledState');
                if (a) {
                    if (d === undefined) DataStore.set(c, 'origDisabledState', c.disabled);
                    c.disabled = a
                } else {
                    if (d !== true) c.disabled = false;
                    DataStore.remove(c, 'origDisabledState')
                }
            }
        })
    },
    bootstrap: function (d, e) {
        var f = (Form.getAttribute(d, 'method') || 'GET').toUpperCase();
        e = Parent.byTag(e, 'button') || e;
        var g = DOMPath.findNodePath(d);
        var k = Parent.byClass(e, 'stat_elem') || d;
        if (CSS.hasClass(k, 'async_saving')) return;
        if (e && (e.form !== d || (e.nodeName != 'INPUT' && e.nodeName != 'BUTTON') || e.type != 'submit')) {
            var l = DOM.scry(d, '.enter_submit_target')[0];
            var b = e;
            l && (e = l);
            if (l && window.send_error_signal) {
                var i = 'bogus_last_click = ' + b.nodeName + '\n' + b.name + '\n' + b.type + '\n';
                i += 'new_last_click = ' + e.nodeName + '\n' + e.name + '\n' + e.type + '\n';
                if (window.get_error_stack) i += '\n' + get_error_stack();
                send_error_signal('async_xport_stack', '1357010:::' + i)
            }
        }
        var c = Form.serialize(d, e);
        Form.setDisabled(d, true);
        var a = Form.getAttribute(d, 'ajaxify') || Form.getAttribute(d, 'action');
        if (window.send_error_signal && a && c && a.toString().indexOf('/ufi/modify.php') != -1) if (c.next_page === undefined && c.view_all === undefined && c.email_explain === undefined && c.like === undefined && c.unlike === undefined && c.like_comment_id === undefined && c.unlike_comment_id === undefined && c.flag_comment_id === undefined && c.unflag_comment_id === undefined && c['delete'] === undefined && c.hide_option === undefined && c.comment === undefined && c.subscribe === undefined && c.unsubscribe === undefined && c.save_bookmark === undefined && c.remove_bookmark === undefined) {
            var j = 'lct_orig = ' + (!e ? e : (e.nodeName + '\n' + e.name + '\n' + e.type + '\n'));
            j += ':::add_comment_text = ' + (c.add_comment_text || '');
            if (window.get_error_stack) j += '\n' + get_error_stack();
            send_error_signal('async_xport_stack', '1357010:::' + j)
        }
        var h = new AsyncRequest(a);
        h.setData(c).setNectarModuleDataSafe(d).setReadOnly(f == 'GET').setMethod(f).setRelativeTo(d).setStatusElement(k).setHandler(function (m) {
            if (m.isReplay()) h.setRelativeTo(DOMPath.resolveNodePath(g))
        }).setFinallyHandler(Form.setDisabled.bind(null, d, false)).send()
    },
    serialize: function (b, c) {
        var a = {};
        Form.getElements(b).forEach(function (d) {
            if (d.name && !d.disabled && d.type != 'submit') if (!d.type || ((d.type == 'radio' || d.type == 'checkbox') && d.checked) || d.type == 'text' || d.type == 'password' || d.type == 'hidden' || d.tagName == 'TEXTAREA') {
                Form._serializeHelper(a, d.name, Input.getValue(d))
            } else if (d.tagName == 'SELECT') for (var e = 0, f = d.options.length; e < f; ++e) {
                var g = d.options[e];
                if (g.selected) Form._serializeHelper(a, d.name, g.value)
            }
        });
        if (c && c.name && 'submit' == c.type && DOM.contains(b, c) && DOM.isNode(c, ['input', 'button'])) Form._serializeHelper(a, c.name, c.value);
        return Form._serializeFix(a)
    },
    _serializeHelper: function (a, d, e) {
        var c = /([^\]]+)\[([^\]]*)\](.*)/.exec(d);
        if (c) {
            a[c[1]] = a[c[1]] || {};
            if (c[2] == '') {
                var b = 0;
                while (a[c[1]][b] != undefined) b++
            } else b = c[2];
            if (c[3] == '') {
                a[c[1]][b] = e
            } else Form._serializeHelper(a[c[1]], b.concat(c[3]), e)
        } else a[d] = e
    },
    _serializeFix: function (a) {
        var e = [];
        for (var b in a) {
            if (a instanceof Object) a[b] = Form._serializeFix(a[b]);
            e.push(b)
        }
        var d = 0,
            c = true;
        e.sort().each(function (g) {
            if (g != d++) c = false
        });
        if (c) {
            var f = {};
            e.each(function (g) {
                f[g] = a[g]
            });
            return f
        } else return a
    },
    post: function (d, b, c) {
        var a = document.createElement('form');
        a.action = d.toString();
        a.method = 'POST';
        a.style.display = 'none';
        if (c) a.target = c;
        if (ge('post_form_id')) b.post_form_id = $('post_form_id').value;
        b.fb_dtsg = Env.fb_dtsg;
        b.post_form_id_source = 'dynamic_post';
        b.next = htmlspecialchars(document.location.href);
        Form.createHiddenInputs(b, a);
        DOM.getRootElement().appendChild(a);
        a.submit();
        return false
    },
    createHiddenInputs: function (g, a, d, f) {
        d = d || {};
        var c;
        var h = URI.implodeQuery(g, '', false);
        var i = h.split('&');
        for (var b = 0; b < i.length; b++) if (i[b]) {
            var j = i[b].split('=');
            var e = j[0];
            var k = j[1];
            if (e === undefined || k === undefined) continue;
            k = URI.decodeComponent(k);
            if (d[e] && f) {
                d[e].value = k
            } else {
                c = $N('input', {
                    type: 'hidden',
                    name: e,
                    value: k
                });
                d[e] = c;
                a.appendChild(c)
            }
        }
        return d
    },
    getFirstElement: function (b) {
        var f = ['input[type="text"]', 'textarea', 'input[type="password"]', 'input[type="button"]', 'input[type="submit"]'];
        var e = [];
        for (var c = 0; c < f.length && e.length == 0; c++) e = DOM.scry(b, f[c]);
        if (e.length > 0) {
            var d = e[0];
            try {
                if (elementY(d) > 0 && elementX(d) > 0) return d
            } catch (a) {}
        }
        return null
    },
    focusFirst: function (b) {
        var a = Form.getFirstElement(b);
        if (a) {
            a.focus();
            return true
        }
        return false
    }
});
var DOMPath = {
    findNodePath: function (c, e) {
        e = e || [];
        if (c.id || !DOM.isNode(c.parentNode)) return {
            id: c.id,
            path: e.reverse()
        };
        var d = c.parentNode;
        var b = d.childNodes;
        for (var a = 0; a < b.length; ++a) if (b[a] === c) {
            e.push(a);
            return DOMPath.findNodePath(d, e)
        }
        return null
    },
    resolveNodePath: function (a) {
        var b = ge(a.id) || document.documentElement;
        return DOMPath._resolveNodePathChildren(a.path, b, 0)
    },
    _resolveNodePathChildren: function (c, d, b) {
        if (b === c.length) return d;
        var a = d.childNodes[c[b]];
        if (!a) return null;
        return DOMPath._resolveNodePathChildren(c, a, b + 1)
    }
};

function Dialog(a) {
    this._show_loading = true;
    this._loading_was_shown = false;
    this._auto_focus = true;
    this._fade_enabled = true;
    this._onload_handlers = [];
    this._top = 125;
    this._uniqueID = 'dialog_' + Dialog._globalCount++;
    this._content = null;
    this._obj = null;
    this._popup = null;
    this._overlay = null;
    this._hidden_objects = [];
    if (a) this._setFromModel(a)
}
Metaprototype.makeFinal(Dialog);
copy_properties(Dialog, {
    OK: {
        name: 'ok',
        label: _tx("Okay")
    },
    CANCEL: {
        name: 'cancel',
        label: _tx("Cancel"),
        className: 'inputaux'
    },
    CLOSE: {
        name: 'close',
        label: _tx("Close")
    },
    NEXT: {
        name: 'next',
        label: _tx("Next")
    },
    SAVE: {
        name: 'save',
        label: _tx("Save")
    },
    SUBMIT: {
        name: 'submit',
        label: _tx("Submit")
    },
    CONFIRM: {
        name: 'confirm',
        label: _tx("Confirm")
    },
    DELETE: {
        name: 'delete',
        label: _tx("Delete")
    },
    _globalCount: 0,
    _bottoms: [0],
    max_bottom: 0,
    _updateMaxBottom: function () {
        Dialog.max_bottom = Math.max.apply(Math, Dialog._bottoms)
    }
});
copy_properties(Dialog, {
    OK_AND_CANCEL: [Dialog.OK, Dialog.CANCEL],
    _STANDARD_BUTTONS: [Dialog.OK, Dialog.CANCEL, Dialog.CLOSE, Dialog.SAVE, Dialog.SUBMIT, Dialog.CONFIRM, Dialog.DELETE],
    SHOULD_HIDE_OBJECTS: !ua.windows(),
    _useCSSBorders: CSS.supportsBorderRadius() || ua.ie() <= 6,
    SIZE: {
        WIDE: 555,
        STANDARD: 445
    },
    _HALO_WIDTH: 10,
    _BORDER_WIDTH: 1,
    _PADDING_WIDTH: 10,
    MODALITY: {
        DARK: 'dark',
        WHITE: 'white'
    },
    dialogStack: null,
    newButton: function (e, d, b, c) {
        var a = {
            name: e,
            label: d
        };
        if (b) a.className = b;
        if (c) a.handler = c;
        return a
    },
    getCurrent: function () {
        var a = Dialog.dialogStack;
        if (!a || !a.length) return null;
        return a[a.length - 1]
    },
    bootstrap: function (i, a, f, d, e, c) {
        a = a || {};
        var j = c && c.rel == 'dialog-pipe';
        copy_properties(a, new URI(i).getQueryData());
        d = d || (f ? 'GET' : 'POST');
        var h = Parent.byClass(c, 'stat_elem') || c;
        if (h && CSS.hasClass(h, 'async_saving')) return false;
        var g;
        if (j) {
            g = new AjaxPipeRequest()
        } else g = new AsyncRequest().setReadOnly( !! f).setMethod(d).setRelativeTo(c).setStatusElement(h);
        var b = new Dialog(e).setAsync(g.setURI(i).setData(a), j);
        b.show();
        return false
    },
    _basicMutator: function (a) {
        return function (b) {
            this[a] = b;
            this._dirty();
            return this
        }
    },
    _findButton: function (a, c) {
        if (a) for (var b = 0; b < a.length; ++b) if (a[b].name == c) return a[b];
        return null
    },
    _keyDownFilter: function (event, a) {
        return a == 'onkeydown' && KeyEventController.filterEventModifiers(event, a)
    },
    _tearDown: function () {
        Dialog._hideAll();
        Dialog.dialogStack = null
    },
    _hideAll: function () {
        if (Dialog.dialogStack !== null && Dialog.dialogStack.length) {
            var b = Dialog.dialogStack.clone();
            Dialog.dialogStack = null;
            for (var a = b.length - 1; a >= 0; a--) b[a].hide()
        }
    },
    _handleEscapeKey: function (event, a) {
        Dialog._escape()
    },
    _escape: function () {
        var d = Dialog.getCurrent();
        if (!d) return true;
        var e = d._semi_modal;
        var b = d._buttons;
        if (!b && !e) return true;
        if (e && !b) {
            d.hide();
            return false
        }
        var a;
        var c = Dialog._findButton(b, 'cancel');
        if (d._cancelHandler) {
            d.cancel();
            return false
        } else if (c) {
            a = c
        } else if (b.length == 1) {
            a = b[0]
        } else return true;
        d._handleButton(a);
        return false
    },
    call_or_eval: function (obj, func, args) {
        if (!func) return undefined;
        args = args || {};
        if (typeof (func) == 'string') {
            var params = keys(args).join(', ');
            func = eval('({f: function(' + params + ') { ' + func + '}})').f
        }
        return func.apply(obj, values(args))
    }
});
copy_properties(Dialog.prototype, {
    show: function (a) {
        this._showing = true;
        if (a) {
            if (this._overlay) this._overlay.style.display = '';
            if (this._fade_enabled) CSS.setStyle(this._obj, 'opacity', 1);
            this._obj.style.display = ''
        } else this._dirty();
        return this
    },
    showLoading: function () {
        this._loading_was_shown = true;
        this._renderDialog($N('div', {
            className: 'dialog_loading'
        }, _tx("Loading...")));
        return this
    },
    hide: function (a) {
        if (!this._showing) return this;
        this._showing = false;
        if (this._autohide_timeout) {
            clearTimeout(this._autohide_timeout);
            this._autohide_timeout = null
        }
        if (this._fade_enabled && (!Dialog.dialogStack || Dialog.dialogStack.length <= 1)) {
            this._fadeOut(a)
        } else this._hide(a);
        return this
    },
    cancel: function () {
        if (!this._cancelHandler || this._cancelHandler() !== false) this.hide()
    },
    getRoot: function () {
        return this._obj
    },
    getBody: function () {
        return DOM.scry(this._obj, 'div.dialog_body')[0]
    },
    getButtonElement: function (a) {
        if (typeof a == 'string') a = Dialog._findButton(this._buttons, a);
        if (!a || !a.name) return null;
        var b = DOM.scry(this._popup, 'input');
        var c = function (d) {
                return d.name == a.name
            };
        return b.filter(c)[0] || null
    },
    getContentNode: function () {
        var a = DOM.scry(this._content, 'div.dialog_content');
        a.length != 1;
        return a[0]
    },
    getFormData: function () {
        return Form.serialize(this.getContentNode())
    },
    setShowing: function () {
        this.show();
        return this
    },
    setHiding: function () {
        this.hide();
        return this
    },
    setTitle: Dialog._basicMutator('_title'),
    setBody: Dialog._basicMutator('_body'),
    setExtraData: Dialog._basicMutator('_extra_data'),
    setReturnData: Dialog._basicMutator('_return_data'),
    setShowLoading: Dialog._basicMutator('_show_loading'),
    setFullBleed: Dialog._basicMutator('_full_bleed'),
    setImmediateRendering: function (a) {
        this._immediate_rendering = a;
        return this
    },
    setUserData: Dialog._basicMutator('_user_data'),
    getUserData: function () {
        return this._user_data
    },
    setAutohide: function (a) {
        if (a) {
            if (this._showing) {
                this._autohide_timeout = setTimeout(this.hide.shield(this), a)
            } else this._autohide = a
        } else {
            this._autohide = null;
            if (this._autohide_timeout) {
                clearTimeout(this._autohide_timeout);
                this._autohide_timeout = null
            }
        }
        return this
    },
    setSummary: Dialog._basicMutator('_summary'),
    setButtons: function (a) {
        var c;
        if (!(a instanceof Array)) {
            c = $A(arguments)
        } else c = a;
        for (var d = 0; d < c.length; ++d) if (typeof c[d] == 'string') {
            var b = Dialog._findButton(Dialog._STANDARD_BUTTONS, c[d]);
            !b;
            c[d] = b
        }
        this._buttons = c;
        this._updateButtons();
        return this
    },
    setButtonsMessage: Dialog._basicMutator('_buttons_message'),
    setClickButtonOnEnter: function (b, a) {
        this._clickButtonOnEnter = a;
        this._clickButtonOnEnterInputName = b;
        return this
    },
    setStackable: function (b, a) {
        this._is_stackable = b;
        this._shown_while_stacked = b && a;
        return this
    },
    setHandler: function (a) {
        this._handler = a;
        return this
    },
    setCancelHandler: function (a) {
        this._cancelHandler = Dialog.call_or_eval.bind(null, this, a);
        return this
    },
    setCloseHandler: function (a) {
        this._close_handler = Dialog.call_or_eval.bind(null, this, a);
        return this
    },
    clearHandler: function () {
        return this.setHandler(null)
    },
    setPostURI: function (b, a) {
        if (a === undefined) a = true;
        if (a) {
            this.setHandler(this._submitForm.bind(this, 'POST', b))
        } else this.setHandler(function () {
            Form.post(b, this.getFormData());
            this.hide()
        }.bind(this));
        return this
    },
    setGetURI: function (a) {
        this.setHandler(this._submitForm.bind(this, 'GET', a));
        return this
    },
    setModal: function (a, b) {
        if (a === undefined) a = true;
        this._showing && this._modal && !a;
        if (a && b) switch (b) {
        case Dialog.MODALITY.DARK:
            this._modal_class = 'dark';
            break;
        case Dialog.MODALITY.WHITE:
            this._modal_class = 'white';
            break
        }
        this._modal = a;
        return this
    },
    setSemiModal: function (a) {
        if (a === undefined) a = true;
        if (a) this.setModal(true, Dialog.MODALITY.DARK);
        this._semi_modal = a;
        return this
    },
    setWideDialog: Dialog._basicMutator('_wide_dialog'),
    setContentWidth: Dialog._basicMutator('_content_width'),
    setTitleLoading: function (b) {
        if (b === undefined) b = true;
        var a = DOM.find(this._popup, 'h2.dialog_title');
        if (a) CSS.conditionClass(a, 'loading', b);
        return this
    },
    setSecure: Dialog._basicMutator('_secure'),
    setClassName: Dialog._basicMutator('_class_name'),
    setFadeEnabled: Dialog._basicMutator('_fade_enabled'),
    setFooter: Dialog._basicMutator('_footer'),
    setAutoFocus: Dialog._basicMutator('_auto_focus'),
    setTop: Dialog._basicMutator('_top'),
    onloadRegister: function (a) {
        $A(a).forEach(function (b) {
            if (typeof b == 'string') b = new Function(b);
            this._onload_handlers.push(b.bind(this))
        }.bind(this));
        return this
    },
    setAsyncURL: function (a) {
        return this.setAsync(new AsyncRequest(a))
    },
    setAsync: function (a, f) {
        var c = function (j) {
                if (this._async_request != a) return;
                this._async_request = null;
                var i = j.getPayload();
                var g = i;
                var h = function () {
                        if (typeof g == 'string') {
                            this.setBody(g)
                        } else this._setFromModel(g);
                        this._update(true)
                    }.bind(this);
                if (f) {
                    g = i.dialog;
                    Bootloader.setResourceMap(i.resource_map);
                    Bootloader.loadResources(i.css, h)
                } else h()
            }.bind(this);
        var b = a.getData();
        b.__d = 1;
        a.setData(b);
        var d = bind(this, 'hide');
        var e;
        if (f) {
            a.setFirstResponseHandler(c);
            e = a.getAsyncRequest()
        } else {
            a.setHandler(chain(a.getHandler(), c));
            e = a
        }
        e.setErrorHandler(chain(d, e.getErrorHandler())).setTransportErrorHandler(chain(d, e.getTransportErrorHandler()));
        a.send();
        this._async_request = a;
        this._dirty();
        return this
    },
    _dirty: function () {
        if (!this._is_dirty) {
            this._is_dirty = true;
            if (this._immediate_rendering) {
                this._update()
            } else bind(this, '_update', false).defer()
        }
    },
    _format: function (a) {
        if (typeof a == 'string') {
            a = HTML(a)
        } else a = HTML.replaceJSONWrapper(a);
        if (a instanceof HTML) a.setDeferred(true);
        return a
    },
    _update: function (d) {
        if (!this._is_dirty && d !== true) return;
        this._is_dirty = false;
        if (!this._showing) return;
        if (this._autohide && !this._async_request && !this._autohide_timeout) this._autohide_timeout = setTimeout(bind(this, 'hide'), this._autohide);
        if (!this._async_request || !this._show_loading) {
            if (this._loading_was_shown === true) {
                this._hide(true);
                this._loading_was_shown = false
            }
            var b = [];
            if (this._summary) b.push($N('div', {
                className: 'dialog_summary'
            }, this._format(this._summary)));
            b.push($N('div', {
                className: 'dialog_body'
            }, this._format(this._body)));
            var a = this._getButtonContent();
            if (a.length) b.push($N('div', {
                className: 'dialog_buttons clearfix'
            }, a));
            if (this._footer) b.push($N('div', {
                className: 'dialog_footer'
            }, this._format(this._footer)));
            b = $N('div', {
                className: 'dialog_content'
            }, b);
            if (this._title) {
                var g = $N('span', this._format(this._title));
                var h = $N('h2', {
                    className: 'dialog_title',
                    id: 'title_' + this._uniqueID
                }, g);
                CSS.conditionClass(h, 'secure', this._secure);
                b = [h, b]
            } else b = [b];
            this._renderDialog(b);
            CSS.conditionClass(this.getRoot(), 'omitDialogFooter', !a.length);
            if (this._clickButtonOnEnterInputName && this._clickButtonOnEnter && ge(this._clickButtonOnEnterInputName)) Event.listen(ge(this._clickButtonOnEnterInputName), 'keypress', function (i) {
                if (Event.getKeyCode(i) == KEYS.RETURN) this._handleButton(this._clickButtonOnEnter);
                return true
            }.bind(this));
            for (var f = 0; f < this._onload_handlers.length; ++f) try {
                this._onload_handlers[f]()
            } catch (e) {}
            this._onload_handlers = []
        } else this.showLoading();
        var c = 2 * Dialog._BORDER_WIDTH;
        if (Dialog._useCSSBorders) c += 2 * Dialog._HALO_WIDTH;
        if (this._content_width) {
            c += this._content_width;
            if (!this._full_bleed) c += 2 * Dialog._PADDING_WIDTH
        } else if (this._wide_dialog) {
            c += Dialog.SIZE.WIDE
        } else c += Dialog.SIZE.STANDARD;
        this._popup.style.width = c + 'px'
    },
    _updateButtons: function () {
        if (!this._showing) return;
        var b = this._getButtonContent();
        var c = null;
        if (!this.getRoot()) this._buildDialog();
        CSS.conditionClass(this.getRoot(), 'omitDialogFooter', !b.length);
        if (b.length) c = $N('div', {
            className: 'dialog_buttons clearfix'
        }, b);
        var d = DOM.scry(this._content, 'div.dialog_buttons')[0] || null;
        if (!d) {
            if (!c) return;
            var a = this.getBody();
            if (a) DOM.insertAfter(a, c)
        } else if (c) {
            DOM.replace(d, c)
        } else DOM.remove(d)
    },
    _getButtonContent: function () {
        var b = [];
        if ((this._buttons && this._buttons.length > 0) || this._buttons_message) {
            if (this._buttons_message) b.push($N('div', {
                className: 'dialog_buttons_msg'
            }, this._format(this._buttons_message)));
            if (this._buttons) for (var e = 0; e < this._buttons.length; e++) {
                var a = this._buttons[e];
                var c = $N('input', {
                    type: 'button',
                    name: a.name || '',
                    value: a.label
                });
                var d = $N('label', {
                    className: 'uiButton uiButtonLarge uiButtonConfirm'
                }, c);
                if (a.className) {
                    a.className.split(/\s+/).each(function (f) {
                        CSS.addClass(d, f)
                    });
                    if (CSS.hasClass(d, 'inputaux')) {
                        CSS.removeClass(d, 'inputaux');
                        CSS.removeClass(d, 'uiButtonConfirm')
                    }
                }
                if (a.icon) DOM.prependContent(d, $N('img', {
                    src: a.icon,
                    className: 'img mrs'
                }));
                Event.listen(c, 'click', this._handleButton.bind(this, a.name));
                b.push(d)
            }
        }
        return b
    },
    _renderDialog: function (b) {
        if (Dialog.dialogStack === null) {
            KeyEventController.registerKey('ESCAPE', Dialog._handleEscapeKey, Dialog._keyDownFilter);
            onleaveRegister(Dialog._tearDown);
            Arbiter.subscribe('page_transition', Dialog._tearDown)
        }
        if (!this._obj) this._buildDialog();
        if (this._class_name) CSS.addClass(this._obj, this._class_name);
        CSS.conditionClass(this._obj, 'full_bleed', this._full_bleed);
        if (typeof b == 'string') b = HTML(b).setDeferred(this._immediate_rendering !== true);
        DOM.setContent(this._content, b);
        this._showDialog();
        if (this._auto_focus) Form.focusFirst.bind(this, this._content).defer();
        var a = Vector2.getElementDimensions(this._content).y + Vector2.getElementPosition(this._content).y;
        Dialog._bottoms.push(a);
        this._bottom = a;
        Dialog._updateMaxBottom();
        return this
    },
    _buildDialog: function () {
        this._obj = $N('div', {
            className: 'generic_dialog',
            tabIndex: '0'
        });
        this._obj.setAttribute('role', 'alertdialog');
        this._obj.setAttribute('aria-labelledby', 'title_' + this._uniqueID);
        this._obj.style.display = 'none';
        DOM.getRootElement().appendChild(this._obj);
        if (!this._popup) this._popup = $N('div', {
            className: 'generic_dialog_popup'
        });
        this._popup.style.left = this._popup.style.top = '';
        this._obj.appendChild(this._popup);
        this._buildDialogContent()
    },
    _showDialog: function () {
        if (this._modal) if (this._overlay) {
            this._overlay.style.display = ''
        } else this._buildOverlay();
        if (this._obj && this._obj.style.display) {
            this._obj.style.visibility = 'hidden';
            this._obj.style.display = '';
            this._resetDialog();
            this._obj.style.visibility = '';
            this._obj.dialog = this
        } else this._resetDialog();
        clearInterval(this.active_hiding);
        this.active_hiding = setInterval(this._activeResize.bind(this), 500);
        Arbiter.inform('new_layer');
        if (!Dialog.dialogStack) Dialog.dialogStack = [];
        var c = Dialog.dialogStack;
        if (c.length) {
            var a = c[c.length - 1];
            if (a != this && (!a._is_stackable || (a._show_loading && a._loading_was_shown))) a._hide();
            for (var b = c.length - 1; b >= 0; b--) if (c[b] == this) {
                c.splice(b, 1)
            } else if (!c[b]._shown_while_stacked) c[b]._hide(true)
        }
        c.push(this);
        return this
    },
    _activeResize: function () {
        if (this.last_offset_height != this._content.offsetHeight) this.last_offset_height = this._content.offsetHeight
    },
    _buildDialogContent: function () {
        CSS.addClass(this._obj, 'pop_dialog');
        if (intl_locale_is_rtl()) CSS.addClass(this._obj, 'pop_dialog_rtl');
        var a;
        if (Dialog._useCSSBorders) {
            a = '<div class="pop_container_advanced">' + '<div class="pop_content" id="pop_content"></div>' + '</div>'
        } else a = '<div class="pop_container">' + '<div class="pop_verticalslab"></div>' + '<div class="pop_horizontalslab"></div>' + '<div class="pop_topleft"></div>' + '<div class="pop_topright"></div>' + '<div class="pop_bottomright"></div>' + '<div class="pop_bottomleft"></div>' + '<div class="pop_content pop_content_old" id="pop_content"></div>' + '</div>';
        DOM.setContent(this._popup, HTML(a));
        this._frame = DOM.find(this._popup, 'div.pop_content');
        this._content = this._frame
    },
    _buildOverlay: function () {
        this._overlay = $N('div', {
            id: 'generic_dialog_overlay'
        });
        if (this._modal_class) CSS.addClass(this._overlay, this._modal_class);
        if (this._semi_modal) {
            var a = function (b) {
                    if (b.getTarget() == this._obj || b.getTarget() == this._overlay) this.hide()
                }.bind(this);
            Event.listen(this._obj, 'click', a);
            Event.listen(this._overlay, 'click', a)
        }
        if (ua.ie() < 7) this._overlay.style.height = Vector2.getDocumentDimensions().y + 'px';
        onloadRegister(function () {
            document.body.appendChild(this._overlay)
        }.bind(this))
    },
    _resetDialog: function () {
        if (!this._popup) return;
        this._resetDialogObj()
    },
    _resetDialogObj: function () {
        var a = DOM.find(this._popup, 'div.pop_content');
        var d = Vector2.getScrollPosition().y;
        var f = 20;
        var g = Vector2.getViewportDimensions().y;
        var b = Vector2.getElementDimensions(a).y + f;
        var e = d + this._top + 'px';
        if (this._top + b > g) {
            var c = Math.max(g - b, 0);
            e = ((c / 2) + d) + 'px'
        }
        this._popup.style.top = e
    },
    _fadeOut: function (b) {
        if (!this._popup) return;
        try {
            animation(this._obj).duration(0).checkpoint().to('opacity', 0).hide().duration(250).ondone(this._hide.bind(this, b)).go()
        } catch (a) {
            this._hide(b)
        }
    },
    _hide: function (d) {
        if (this._obj) this._obj.style.display = 'none';
        if (this._overlay) if (d) {
            this._overlay.style.display = 'none'
        } else {
            DOM.remove(this._overlay);
            this._overlay = null
        }
        if (this.timeout) {
            clearTimeout(this.timeout);
            this.timeout = null
        }
        if (this._hidden_objects.length) {
            for (var b = 0, c = this._hidden_objects.length; b < c; b++) this._hidden_objects[b].style.visibility = '';
            this._hidden_objects = []
        }
        clearInterval(this.active_hiding);
        if (this._bottom) {
            var a = Dialog._bottoms;
            a.splice(a.indexOf(this._bottom), 1);
            Dialog._updateMaxBottom()
        }
        if (d) return;
        this.destroy()
    },
    destroy: function () {
        if (Dialog.dialogStack && Dialog.dialogStack.length) {
            var b = Dialog.dialogStack;
            for (var a = b.length - 1; a >= 0; a--) if (b[a] == this) b.splice(a, 1);
            if (b.length) b[b.length - 1]._showDialog()
        }
        if (this._obj) {
            DOM.remove(this._obj);
            this._obj = null
        }
        if (this._close_handler) this._close_handler({
            return_data: this._return_data
        })
    },
    _handleButton: function (a) {
        if (typeof a == 'string') a = Dialog._findButton(this._buttons, a);
        if (!a) return;
        var b = Dialog.call_or_eval(a, a.handler);
        if (b === false) return;
        if (a.name == 'cancel') {
            this.cancel()
        } else if (Dialog.call_or_eval(this, this._handler, {
            button: a
        }) !== false) this.hide()
    },
    _submitForm: function (d, e, b) {
        var c = this.getFormData();
        if (b) c[b.name] = b.label;
        if (this._extra_data) copy_properties(c, this._extra_data);
        var a = new AsyncRequest().setURI(e).setData(c).setMethod(d).setReadOnly(d == 'GET');
        this.setAsync(a);
        return false
    },
    _setFromModel: function (c) {
        var a = {};
        copy_properties(a, c);
        if (a.immediateRendering) {
            this.setImmediateRendering(a.immediateRendering);
            delete a.immediateRendering
        }
        for (var d in a) {
            if (d == 'onloadRegister') {
                this.onloadRegister(a[d]);
                continue
            }
            var b = this['set' + d.substr(0, 1).toUpperCase() + d.substr(1)];
            if (!(!b)) b.apply(this, $A(a[d]))
        }
    },
    _updateBottom: function () {
        var a = Vector2.getElementDimensions(this._content).y + Vector2.getElementPosition(this._content).y;
        Dialog._bottoms[Dialog._bottoms.length - 1] = a;
        Dialog._updateMaxBottom()
    }
});

function AsyncRequest(uri) {
    var dispatchResponse = bind(this, function (asyncResponse) {
        try {
            this.clearStatusIndicator();
            this._measureSaved && this._measureSaved();
            if (this._isPrefetch) {
                this._isPrefetch = false;
                return
            }
            if (!this.isRelevant()) {
                invokeErrorHandler(1010);
                return
            }
            if (this.initialHandler(asyncResponse) !== false) {
                clearTimeout(this.timer);
                asyncResponse.jscc && invoke_callbacks([asyncResponse.jscc]);
                if (this.handler) try {
                    var suppress_onload = this.handler(asyncResponse)
                } catch (exception) {
                    asyncResponse.is_last && this.finallyHandler(asyncResponse);
                    throw exception
                }
                asyncResponse.is_last && this.finallyHandler(asyncResponse);
                if (suppress_onload !== AsyncRequest.suppressOnloadToken) {
                    var onload = asyncResponse.onload;
                    if (onload) for (var ii = 0; ii < onload.length; ii++) try {
                        (new Function(onload[ii])).apply(this)
                    } catch (exception) {}
                    if (this.lid && !asyncResponse.isReplay()) Arbiter.inform('tti_ajax', {
                        s: this.lid,
                        d: [this._sendTimeStamp || 0, (this._sendTimeStamp && this._responseTime) ? (this._responseTime - this._sendTimeStamp) : 0]
                    }, Arbiter.BEHAVIOR_EVENT);
                    var onafterload = asyncResponse.onafterload;
                    if (onafterload) for (var ii = 0; ii < onafterload.length; ii++) try {
                        (new Function(onafterload[ii])).apply(this)
                    } catch (exception) {}
                }
                var invalidate_cache = asyncResponse.invalidate_cache;
                if (!this.getOption('suppressCacheInvalidation') && invalidate_cache && invalidate_cache.length) Arbiter.inform(Arbiter.PAGECACHE_INVALIDATE, invalidate_cache)
            }
            if (asyncResponse.cacheObservation && typeof (TabConsoleCacheobserver) != 'undefined' && TabConsoleCacheobserver.instance) TabConsoleCacheobserver.getInstance().addAsyncObservation(asyncResponse.cacheObservation)
        } catch (exception) {}
    });
    var replayResponses = bind(this, function () {
        if (is_empty(this._asyncResponses)) return;
        this.setNewSerial();
        for (var ii = 0; ii < this._asyncResponses.length; ++ii) {
            var r = this._asyncResponses[ii];
            invokeResponseHandler(r, true)
        }
    });
    var dispatchErrorResponse = bind(this, function (asyncResponse, isTransport) {
        try {
            this.clearStatusIndicator();
            var async_error = asyncResponse.getError();
            if (this._sendTimeStamp) {
                var _duration = (+new Date()) - this._sendTimeStamp;
                var xfb_ip = this._xFbServer || '-';
                asyncResponse.logError('async_error', _duration + ':' + xfb_ip)
            } else asyncResponse.logError('async_error');
            if ((!this.isRelevant()) || async_error === 1010) return;
            if (async_error == 1357008 || async_error == 1357007 || async_error == 1442002 || async_error == 1357001) {
                var is_confirmation = false;
                if (async_error == 1357008 || async_error == 1357007) is_confirmation = true;
                var payload = asyncResponse.getPayload();
                this._displayServerDialog(payload.__dialog, is_confirmation)
            } else if (this.initialHandler(asyncResponse) !== false) {
                clearTimeout(this.timer);
                try {
                    if (isTransport) {
                        this.transportErrorHandler(asyncResponse)
                    } else this.errorHandler(asyncResponse)
                } catch (exception) {
                    this.finallyHandler(asyncResponse);
                    throw exception
                }
                this.finallyHandler(asyncResponse)
            }
        } catch (exception) {}
    });
    var _interpretTransportResponse = bind(this, function () {
        if (this.getOption('suppressEvaluation')) {
            var r = new AsyncResponse(this, this.transport);
            return {
                asyncResponse: r
            }
        }
        var _sendError = function (p, error_code, str) {
                if (!window.send_error_signal) return;
                if (this._xFbServer) {
                    error_code = '1008_' + error_code
                } else error_code = '1012_' + error_code;
                send_error_signal('async_xport_resp', error_code + ':' + (this._xFbServer || '-') + ':' + p.getURI() + ':' + str.length + ':' + str.substr(0, 1600))
            };
        var shield = "for (;;);";
        var shieldlen = shield.length;
        var text = this.transport.responseText;
        if (text.length <= shieldlen) {
            _sendError(this, 'empty', text);
            return {
                transportError: 'Response too short on async to ' + this.getURI()
            }
        }
        var offset = 0;
        while (text.charAt(offset) == " " || text.charAt(offset) == "\n") offset++;
        offset && text.substring(offset, offset + shieldlen) == shield;
        var safeResponse = text.substring(offset + shieldlen);
        try {
            var response = eval('(' + safeResponse + ')')
        } catch (exception) {
            _sendError(this, 'excep', text);
            return {
                transportError: 'eval() failed on async to ' + this.getURI()
            }
        }
        return interpretResponse(response)
    });
    var interpretResponse = bind(this, function (response) {
        if (response.redirect) return {
            redirect: response.redirect
        };
        var r = new AsyncResponse(this);
        if (response.__ar != 1) {
            r.payload = response
        } else {
            copy_properties(r, response);
            if (response.tplts) if (window.DynaTemplate) DynaTemplate.registerTemplates(response.tplts)
        }
        return {
            asyncResponse: r
        }
    });
    var invokeResponseHandler = bind(this, function (interp, is_replay) {
        if (typeof (interp.redirect) != 'undefined') {
            (function () {
                this.setURI(interp.redirect).send()
            }).bind(this).defer();
            return
        }
        if (this.handler || this.errorHandler || this.transportErrorHandler) if (typeof (interp.asyncResponse) != 'undefined') {
            var r = interp.asyncResponse;
            r.setReplay( !! is_replay);
            if (!this.isRelevant()) {
                invokeErrorHandler(1010);
                return
            }
            if (r.inlinejs) eval_global(r.inlinejs);
            if (r.lid) {
                this._responseTime = (+new Date());
                if (window.CavalryLogger) this.cavalry = CavalryLogger.getInstance(r.lid);
                this.lid = r.lid
            }
            if (r.getError() && !r.getErrorIsWarning()) {
                var fn = dispatchErrorResponse
            } else {
                var fn = dispatchResponse;
                if (this._replayable && !is_replay && !r.dontReplay) {
                    this._asyncResponses = this._asyncResponses || [];
                    this._asyncResponses.push(interp)
                }
            }
            Bootloader.setResourceMap(r.resource_map);
            if (r.bootloadable) Bootloader.enableBootload(r.bootloadable);
            fn = fn.shield(null, r);
            fn = fn.defer.bind(fn);
            var is_transitional = false;
            if (this.preBootloadHandler) is_transitional = this.preBootloadHandler(r);
            r.css = r.css || [];
            r.js = r.js || [];
            Bootloader.loadResources(r.css.concat(r.js), fn, is_transitional, this.getURI())
        } else if (typeof (interp.transportError) != 'undefined') {
            if (this._xFbServer) {
                invokeErrorHandler(1008)
            } else invokeErrorHandler(1012)
        } else invokeErrorHandler(1007)
    });
    var invokeErrorHandler = bind(this, function (explicitError) {
        try {
            if (!window.loaded && !this.getOption('handleErrorAfterUnload')) return
        } catch (ex) {
            return
        }
        var r = new AsyncResponse(this);
        var err;
        try {
            err = explicitError || this.transport.status || 1004
        } catch (ex) {
            err = 1005
        }
        if (this._requestAborted) err = 1011;
        try {
            if (this.responseText == '') err = 1002
        } catch (ignore) {}
        if (this.transportErrorHandler) {
            var desc, summary;
            var silent = true;
            if (false === navigator.onLine) {
                summary = _tx("No Network Connection");
                desc = _tx("Your browser appears to be offline. Please check your internet connection and try again.");
                err = 1006
            } else if (err >= 300 && err <= 399) {
                summary = _tx("Redirection");
                desc = _tx("Your access to Facebook was redirected or blocked by a third party at this time, please contact your ISP or reload. ");
                redir_url = this.transport.getResponseHeader("Location");
                if (redir_url) goURI(redir_url, true);
                silent = true
            } else {
                summary = _tx("Oops!");
                desc = _tx("Something went wrong. We're working on getting this fixed as soon as we can. You may be able to try again.")
            }!this.getOption('suppressErrorAlerts');
            copy_properties(r, {
                error: err,
                errorSummary: summary,
                errorDescription: desc,
                silentError: silent
            });
            dispatchErrorResponse(r, true)
        }
    });
    var handleResponse = function (response) {
            var asyncResponse = this.interpretResponse(response);
            this.invokeResponseHandler(asyncResponse)
        };
    var onStateChange = function () {
            try {
                if (this.transport.readyState == 4) {
                    AsyncRequest._inflightPurge();
                    try {
                        if (typeof (this.transport.getResponseHeader) != 'undefined' && this.transport.getResponseHeader('X-FB-Server')) this._xFbServer = this.transport.getResponseHeader('X-FB-Server')
                    } catch (ex) {}
                    if (this.transport.status >= 200 && this.transport.status < 300) {
                        invokeResponseHandler(_interpretTransportResponse())
                    } else if (ua.safari() && (typeof (this.transport.status) == 'undefined')) {
                        invokeErrorHandler(1002)
                    } else if (window.send_error_signal && window.Env && window.Env.retry_ajax_on_network_error && this.transport.status in {
                        0: 1,
                        12029: 1,
                        12030: 1,
                        12031: 1,
                        12152: 1
                    } && this.remainingRetries > 0) {
                        --this.remainingRetries;
                        delete this.transport;
                        this.send(true);
                        return
                    } else invokeErrorHandler();
                    if (this.getOption('asynchronous') !== false) delete this.transport
                }
            } catch (exception) {
                try {
                    if (!window.loaded) return
                } catch (ex) {
                    return
                }
                delete this.transport;
                if (this.remainingRetries > 0) {
                    --this.remainingRetries;
                    this.send(true)
                } else {
                    !this.getOption('suppressErrorAlerts');
                    if (window.send_error_signal) send_error_signal('async_xport_resp', '1007:' + (this._xFbServer || '-') + ':' + this.getURI() + ':' + exception.message);
                    invokeErrorHandler(1007)
                }
            }
        };
    var onJSONPResponse = function (data, more_chunked_response) {
            var is_first = (this.is_first === undefined);
            this.is_first = is_first;
            if (this.transportIframe && !more_chunked_response)(function (x) {
                document.body.removeChild(x)
            }).bind(null, this.transportIframe).defer();
            if (ua.ie() >= 9 && window.JSON) data = window.JSON.parse(window.JSON.stringify(data));
            var r = this.interpretResponse(data);
            r.asyncResponse.is_first = is_first;
            r.asyncResponse.is_last = !more_chunked_response;
            this.invokeResponseHandler(r);
            return more_chunked_response
        };
    copy_properties(this, {
        onstatechange: onStateChange,
        onjsonpresponse: onJSONPResponse,
        replayResponses: replayResponses,
        invokeResponseHandler: invokeResponseHandler,
        interpretResponse: interpretResponse,
        handleResponse: handleResponse,
        transport: null,
        method: 'POST',
        uri: '',
        timeout: null,
        timer: null,
        initialHandler: bagofholding,
        handler: null,
        errorHandler: null,
        transportErrorHandler: null,
        timeoutHandler: null,
        finallyHandler: bagofholding,
        serverDialogCancelHandler: bagofholding,
        relativeTo: null,
        statusElement: null,
        statusClass: '',
        data: {},
        context: {},
        readOnly: false,
        writeRequiredParams: ['post_form_id'],
        remainingRetries: 0,
        option: {
            asynchronous: true,
            suppressCacheInvalidation: false,
            suppressErrorHandlerWarning: false,
            suppressEvaluation: false,
            suppressErrorAlerts: false,
            retries: 0,
            jsonp: false,
            bundle: false,
            useIframeTransport: false,
            tfbEndpoint: true,
            handleErrorAfterUnload: false
        },
        _replayable: undefined,
        _replayKey: '',
        _isPrefetch: false
    });
    this.errorHandler = AsyncResponse.defaultErrorHandler;
    this.transportErrorHandler = bind(this, 'errorHandler');
    if (uri != undefined) this.setURI(uri);
    return this
}
Arbiter.subscribe("page_transition", function (b, a) {
    AsyncRequest._id_threshold = a.id
});
copy_properties(AsyncRequest, {
    pingURI: function (c, a, b) {
        a = a || {};
        return new AsyncRequest().setURI(c).setData(a).setOption('asynchronous', !b).setOption('suppressErrorHandlerWarning', true).setErrorHandler(bagofholding).setTransportErrorHandler(bagofholding).send()
    },
    receiveJSONPResponse: function (b, a, c) {
        if (this._JSONPReceivers[b]) if (!this._JSONPReceivers[b](a, c)) delete this._JSONPReceivers[b]
    },
    _hasBundledRequest: function () {
        return AsyncRequest._allBundledRequests.length > 0
    },
    stashBundledRequest: function () {
        var a = AsyncRequest._allBundledRequests;
        AsyncRequest._allBundledRequests = [];
        return a
    },
    setBundledRequestProperties: function (b) {
        var c = null;
        if (b.stashedRequests) AsyncRequest._allBundledRequests = AsyncRequest._allBundledRequests.concat(b.stashedRequests);
        if (!AsyncRequest._hasBundledRequest()) {
            var a = b.callback;
            a && a()
        } else {
            copy_properties(AsyncRequest._bundledRequestProperties, b);
            if (b.start_immediately) c = AsyncRequest._sendBundledRequests()
        }
        return c
    },
    _bundleRequest: function (b) {
        if (b.getOption('jsonp') || b.getOption('useIframeTransport')) {
            b.setOption('bundle', false);
            return false
        } else if (!b.uri.isFacebookURI()) {
            b.setOption('bundle', false);
            return false
        } else if (!b.getOption('asynchronous')) {
            b.setOption('bundle', false);
            return false
        }
        var a = b.uri.getPath();
        if (!AsyncRequest._bundleTimer) AsyncRequest._bundleTimer = setTimeout(function () {
            AsyncRequest._sendBundledRequests()
        }, 0);
        AsyncRequest._allBundledRequests.push([a, b]);
        return true
    },
    _sendBundledRequests: function () {
        clearTimeout(AsyncRequest._bundleTimer);
        AsyncRequest._bundleTimer = null;
        var a = AsyncRequest._allBundledRequests;
        AsyncRequest._allBundledRequests = [];
        var e = {};
        copy_properties(e, AsyncRequest._bundledRequestProperties);
        AsyncRequest._bundledRequestProperties = {};
        if (is_empty(e) && a.length == 1) {
            var g = a[0][1];
            g.setOption('bundle', false).send();
            return g
        }
        var d = function () {
                e.callback && e.callback()
            };
        if (a.length === 0) {
            d();
            return null
        }
        var b = [];
        for (var c = 0; c < a.length; c++) b.push([a[c][0], URI.implodeQuery(a[c][1].data)]);
        var f = {
            data: b
        };
        if (e.extra_data) copy_properties(f, e.extra_data);
        var g = new AsyncRequest();
        g.setURI('/ajax/proxy.php').setData(f).setMethod('POST').setInitialHandler(e.onInitialResponse || bagof(true)).setAllowCrossPageTransition(true).setHandler(function (l) {
            var k = l.getPayload();
            var n = k.responses;
            if (n.length != a.length) {
                return
            } else for (var i = 0; i < a.length; i++) {
                var j = a[i][0];
                var m = a[i][1];
                m.id = this.id;
                if (n[i][0] != j) {
                    m.invokeResponseHandler({
                        transportError: 'Wrong response order in bundled request to ' + j
                    });
                    continue
                }
                var h = m.interpretResponse(n[i][1]);
                m.invokeResponseHandler(h)
            }
        }).setTransportErrorHandler(function (m) {
            var k = [];
            var i = {
                transportError: m.errorDescription
            };
            for (var h = 0; h < a.length; h++) {
                var j = a[h][0];
                var l = a[h][1];
                k.push(j);
                l.id = this.id;
                l.invokeResponseHandler(i)
            }
        }).setFinallyHandler(function (h) {
            d()
        }).send();
        return g
    },
    bootstrap: function (c, b, d) {
        var e = 'GET';
        var f = true;
        var a = {};
        if (d || (b && b.rel == 'async-post')) {
            e = 'POST';
            f = false;
            if (c) {
                c = URI(c);
                a = c.getQueryData();
                c.setQueryData({})
            }
        }
        var g = Parent.byClass(b, 'stat_elem') || b;
        if (g && CSS.hasClass(g, 'async_saving')) return false;
        new AsyncRequest(c).setReadOnly(f).setMethod(e).setData(a).setNectarModuleDataSafe(b).setStatusElement(g).setRelativeTo(b).send();
        return false
    },
    post: function (b, a) {
        new AsyncRequest(b).setReadOnly(false).setMethod('POST').setData(a).send();
        return false
    },
    clearCache: function () {
        AsyncRequest._reqsCache = {}
    },
    getLastId: function () {
        return AsyncRequest._last_id
    },
    _JSONPReceivers: {},
    _allBundledRequests: [],
    _bundledRequestProperties: {},
    _bundleTimer: null,
    suppressOnloadToken: {},
    REPLAYABLE_AJAX: 'ajax/replayable',
    _last_id: 2,
    _id_threshold: 2,
    _reqsCache: {},
    _inflight: [],
    _inflightAdd: bagofholding,
    _inflightPurge: bagofholding,
    _inflightEnable: function () {
        if (ua.ie()) {
            copy_properties(AsyncRequest, {
                _inflightAdd: function (a) {
                    this._inflight.push(a)
                },
                _inflightPurge: function () {
                    AsyncRequest._inflight = AsyncRequest._inflight.filter(function (a) {
                        return a.transport && a.transport.readyState < 4
                    })
                }
            });
            onunloadRegister(function () {
                AsyncRequest._inflight.each(function (a) {
                    if (a.transport && a.transport.readyState < 4) {
                        a.transport.abort();
                        delete a.transport
                    }
                })
            })
        }
    }
});
copy_properties(AsyncRequest.prototype, {
    setMethod: function (a) {
        this.method = a.toString().toUpperCase();
        return this
    },
    getMethod: function () {
        return this.method
    },
    setData: function (a) {
        this.data = a;
        return this
    },
    getData: function () {
        return this.data
    },
    setContextData: function (b, c, a) {
        a = a === undefined ? true : a;
        if (a) this.context['_log_' + b] = c;
        return this
    },
    setURI: function (a) {
        var b = URI(a);
        if (this.getOption('useIframeTransport') && !b.isFacebookURI()) return this;
        if (!this.getOption('jsonp') && !this.getOption('useIframeTransport') && !b.isSameOrigin()) return this;
        if (!a || b.toString() === '') {
            if (window.send_error_signal && window.get_error_stack) {
                send_error_signal('async_error', '1013:-:0:-:' + window.location.href);
                send_error_signal('async_xport_stack', '1013:' + window.location.href + '::' + get_error_stack())
            }
            return this
        }
        this.uri = b;
        return this
    },
    getURI: function () {
        return this.uri.toString()
    },
    setInitialHandler: function (a) {
        this.initialHandler = a;
        return this
    },
    setHandler: function (a) {
        if (!(typeof (a) != 'function')) this.handler = a;
        return this
    },
    getHandler: function () {
        return this.handler
    },
    setErrorHandler: function (a) {
        if (!(typeof (a) != 'function')) this.errorHandler = a;
        return this
    },
    setTransportErrorHandler: function (a) {
        this.transportErrorHandler = a;
        return this
    },
    getErrorHandler: function () {
        return this.errorHandler
    },
    getTransportErrorHandler: function () {
        return this.transportErrorHandler
    },
    setTimeoutHandler: function (b, a) {
        if (!(typeof (a) != 'function')) {
            this.timeout = b;
            this.timeoutHandler = a
        }
        return this
    },
    resetTimeout: function (a) {
        if (!(this.timeoutHandler === null)) if (a === null) {
            this.timeout = null;
            clearTimeout(this.timer);
            this.timer = null
        } else {
            this.timeout = a;
            clearTimeout(this.timer);
            this.timer = this._handleTimeout.bind(this).defer(this.timeout)
        }
        return this
    },
    _handleTimeout: function () {
        this.abandon();
        this.timeoutHandler(this)
    },
    setNewSerial: function () {
        this.id = ++AsyncRequest._last_id;
        return this
    },
    setFinallyHandler: function (a) {
        this.finallyHandler = a;
        return this
    },
    setServerDialogCancelHandler: function (a) {
        this.serverDialogCancelHandler = a;
        return this
    },
    setPreBootloadHandler: function (a) {
        this.preBootloadHandler = a;
        return this
    },
    setReadOnly: function (a) {
        if (!(typeof (a) != 'boolean')) this.readOnly = a;
        return this
    },
    setFBMLForm: function () {
        this.writeRequiredParams = ["fb_sig"];
        return this
    },
    getReadOnly: function () {
        return this.readOnly
    },
    setRelativeTo: function (a) {
        this.relativeTo = a;
        return this
    },
    getRelativeTo: function () {
        return this.relativeTo
    },
    setStatusClass: function (a) {
        this.statusClass = a;
        return this
    },
    setStatusElement: function (a) {
        this.statusElement = a;
        return this
    },
    getStatusElement: function () {
        return ge(this.statusElement)
    },
    isRelevant: function () {
        if (this._allowCrossPageTransition) return true;
        if (!this.id) return true;
        return this.id > AsyncRequest._id_threshold
    },
    clearStatusIndicator: function () {
        var a = this.getStatusElement();
        if (a) {
            CSS.removeClass(a, 'async_saving');
            CSS.removeClass(a, this.statusClass)
        }
    },
    addStatusIndicator: function () {
        var a = this.getStatusElement();
        if (a) {
            CSS.addClass(a, 'async_saving');
            CSS.addClass(a, this.statusClass)
        }
    },
    specifiesWriteRequiredParams: function () {
        return this.writeRequiredParams.every(function (a) {
            this.data[a] = this.data[a] || Env[a] || (ge(a) || {}).value;
            if (this.data[a] !== undefined) return true;
            return false
        }, this)
    },
    setReplayable: function (b, a) {
        this._replayable = b;
        this._replayKey = a || '';
        return this
    },
    setOption: function (a, b) {
        if (typeof (this.option[a]) != 'undefined') this.option[a] = b;
        return this
    },
    getOption: function (a) {
        typeof (this.option[a]) == 'undefined';
        return this.option[a]
    },
    abort: function () {
        if (this.transport) {
            var a = this.getTransportErrorHandler();
            this.setOption('suppressErrorAlerts', true);
            this.setTransportErrorHandler(bagofholding);
            this._requestAborted = 1;
            this.transport.abort();
            this.setTransportErrorHandler(a)
        }
    },
    abandon: function () {
        clearTimeout(this.timer);
        this.setOption('suppressErrorAlerts', true).setHandler(bagofholding).setErrorHandler(bagofholding).setTransportErrorHandler(bagofholding);
        if (this.transport) {
            this._requestAborted = 1;
            this.transport.abort()
        }
    },
    setNectarActionData: function (a) {
        if (this.data.nctr === undefined) this.data.nctr = {};
        this.data.nctr._ia = 1;
        if (a) {
            if (this.data.nctr._as === undefined) this.data.nctr._as = {};
            copy_properties(this.data.nctr._as, a)
        }
        return this
    },
    setNectarData: function (a) {
        if (a) {
            if (this.data.nctr === undefined) this.data.nctr = {};
            copy_properties(this.data.nctr, a)
        }
        return this
    },
    setNectarModuleDataSafe: function (a) {
        if (this.setNectarModuleData) this.setNectarModuleData(a);
        return this
    },
    setNectarImpressionIdSafe: function () {
        if (this.setNectarImpressionId) this.setNectarImpressionId();
        return this
    },
    setPrefetch: function (a) {
        this._isPrefetch = a;
        this.setAllowCrossPageTransition(true);
        return this
    },
    setAllowCrossPageTransition: function (a) {
        this._allowCrossPageTransition = !! a;
        return this
    },
    send: function (c) {
        if (this._checkCache && this._checkCache()) return true;
        c = c || false;
        if (!this.uri) return false;
        !this.errorHandler && !this.getOption('suppressErrorHandlerWarning');
        if (this.getOption('jsonp') && this.method != 'GET') this.setMethod('GET');
        if (this.getOption('useIframeTransport') && this.method != 'GET') this.setMethod('GET');
        this.timeoutHandler !== null && (this.getOption('jsonp') || this.getOption('useIframeTransport'));
        if (!this.getReadOnly()) {
            if (!this.specifiesWriteRequiredParams()) return false;
            if (this.method != 'POST') return false
        }
        if (this.method == 'POST' && this.getOption('tfbEndpoint')) {
            this.data.fb_dtsg = Env.fb_dtsg;
            this.data.lsd = getCookie('lsd')
        }
        this._replayable = (!this.getReadOnly() && this._replayable !== false) || this._replayable;
        if (this._replayable) Arbiter.inform(AsyncRequest.REPLAYABLE_AJAX, this);
        if (!is_empty(this.context) && this.getOption('tfbEndpoint')) {
            copy_properties(this.data, this.context);
            this.data.ajax_log = 1
        }
        if (!this.getReadOnly() && this.getOption('tfbEndpoint') && this.method == 'POST' && this.data.post_form_id_source === undefined) this.data.post_form_id_source = 'AsyncRequest';
        if (this.getOption('bundle') && AsyncRequest._bundleRequest(this)) return true;
        this.setNewSerial();
        if (this.getOption('tfbEndpoint')) this.uri.addQueryData({
            __a: 1
        });
        this.finallyHandler = async_callback(this.finallyHandler, 'final');
        var h, d;
        if (this.method == 'GET') {
            h = this.uri.addQueryData(this.data).toString();
            d = ''
        } else {
            h = this.uri.toString();
            d = URI.implodeQuery(this.data)
        }
        if (this.getOption('jsonp') || this.getOption('useIframeTransport')) {
            h = this.uri.addQueryData({
                __a: this.id
            }).toString();
            AsyncRequest._JSONPReceivers[this.id] = async_callback(bind(this, 'onjsonpresponse'), 'json');
            if (this.getOption('jsonp')) {
                (function () {
                    document.body.appendChild($N('script', {
                        src: h,
                        type: "text/javascript"
                    }))
                }).bind(this).defer()
            } else {
                var e = {
                    position: 'absolute',
                    top: '-1000px',
                    left: '-1000px',
                    width: '80px',
                    height: '80px'
                };
                this.transportIframe = $N('iframe', {
                    src: h,
                    style: e
                });
                document.body.appendChild(this.transportIframe)
            }
            return true
        }
        if (this.transport) return false;
        var g = null;
        try {
            g = new XMLHttpRequest()
        } catch (b) {}
        if (!g) try {
            g = new ActiveXObject("Msxml2.XMLHTTP")
        } catch (b) {}
        if (!g) try {
            g = new ActiveXObject("Microsoft.XMLHTTP")
        } catch (b) {}
        if (!g) return false;
        g.onreadystatechange = async_callback(bind(this, 'onstatechange'), 'xhr');
        if (!c) this.remainingRetries = this.getOption('retries');
        if (window.send_error_signal || window.ArbiterMonitor) this._sendTimeStamp = this._sendTimeStamp || (+new Date());
        this.transport = g;
        try {
            this.transport.open(this.method, h, this.getOption('asynchronous'))
        } catch (a) {
            return false
        }
        var f = env_get('svn_rev');
        if (f) this.transport.setRequestHeader('X-SVN-Rev', String(f));
        if (this.method == 'POST') this.transport.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        this.addStatusIndicator();
        this.transport.send(d);
        if (this.timeout !== null) this.resetTimeout(this.timeout);
        AsyncRequest._inflightAdd(this);
        return true
    },
    _displayServerDialog: function (c, b) {
        var a = new Dialog(c);
        if (b) a.setHandler(this._displayConfirmationHandler.bind(this, a));
        a.setCancelHandler(function () {
            this.serverDialogCancelHandler.apply(this, arguments);
            this.finallyHandler.apply(this, arguments)
        }.bind(this)).setCloseHandler(this.finallyHandler.bind(this)).show()
    },
    _displayConfirmationHandler: function (a) {
        this.data.confirmed = 1;
        copy_properties(this.data, a.getFormData());
        this.send()
    }
});

function AsyncResponse(b, a) {
    copy_properties(this, {
        error: 0,
        errorSummary: null,
        errorDescription: null,
        onload: null,
        replay: false,
        payload: a || null,
        request: b || null,
        silentError: false,
        is_last: true
    });
    return this
}
copy_properties(AsyncResponse, {
    defaultErrorHandler: function (b) {
        try {
            if (!b.silentError) {
                AsyncResponse.verboseErrorHandler(b)
            } else b.logErrorByGroup('silent', 10)
        } catch (a) {
            alert(b)
        }
    },
    verboseErrorHandler: function (b) {
        try {
            var summary = b.getErrorSummary();
            var desc = b.getErrorDescription();
            b.logErrorByGroup('popup', 10);
            if (b.silentError && desc == '') desc = _tx("Something went wrong. We're working on getting this fixed as soon as we can. You may be able to try again.");
            ErrorDialog.show(summary, desc)
        } catch (a) {
            alert(b)
        }
    }
});
copy_properties(AsyncResponse.prototype, {
    getRequest: function () {
        return this.request
    },
    getPayload: function () {
        return this.payload
    },
    getError: function () {
        return this.error
    },
    getErrorSummary: function () {
        return this.errorSummary
    },
    setErrorSummary: function (a) {
        a = (a === undefined ? null : a);
        this.errorSummary = a;
        return this
    },
    getErrorDescription: function () {
        return this.errorDescription
    },
    getErrorIsWarning: function () {
        return this.errorIsWarning
    },
    setReplay: function (a) {
        a = (a === undefined ? true : a);
        this.replay = !! a;
        return this
    },
    isReplay: function () {
        return this.replay
    },
    logError: function (a, c) {
        if (window.send_error_signal) {
            c = (c === undefined ? '' : (':' + c));
            var d = this.request.getURI();
            var b = this.error + ':' + (env_get('vip') || '-') + c + ':' + d;
            if (!d || d.indexOf('scribe_endpoint.php') != -1) a = 'async_error_double';
            send_error_signal(a, b)
        }
    },
    logErrorByGroup: function (b, a) {
        if (Math.floor(Math.random() * a) == 0) if (this.error == 1357010 || this.error < 15000) {
            this.logError('async_error_oops_' + b)
        } else this.logError('async_error_logic_' + b)
    }
});

function UntrustedLink(a, d, b, c) {
    this.dom = a;
    this.url = a.href;
    this.hash = d;
    this.func_get_params = c ||
    function () {
        return {}
    };
    Event.listen(this.dom, 'click', this.onclick.bind(this));
    Event.listen(this.dom, 'mousedown', this.onmousedown.bind(this));
    Event.listen(this.dom, 'mouseup', this.onmouseup.bind(this));
    Event.listen(this.dom, 'mouseout', this.onmouseout.bind(this));
    this.onmousedown($E(b))
}
UntrustedLink.bootstrap = function (a, d, b, c) {
    if (a.__untrusted) return;
    a.__untrusted = true;
    new UntrustedLink(a, d, b, c)
};
UntrustedLink.prototype.getRewrittenURI = function () {
    var a = copy_properties({
        u: this.url,
        h: this.hash
    }, this.func_get_params(this.dom));
    return new URI('/l.php').setQueryData(a).setSubdomain('www')
};
UntrustedLink.prototype.onclick = function () {
    (function () {
        this.dom.href = this.url
    }).bind(this).defer(100);
    this.dom.href = this.getRewrittenURI()
};
UntrustedLink.prototype.onmousedown = function (a) {
    if (a.button == 2) this.dom.href = this.getRewrittenURI()
};
UntrustedLink.prototype.onmouseup = function () {
    this.dom.href = this.getRewrittenURI()
};
UntrustedLink.prototype.onmouseout = function () {
    this.dom.href = this.url
};
onloadRegister(function () {
    copy_properties(AsyncRequest.prototype, {
        setNectarModuleData: function (c) {
            if (this.method == 'POST') {
                var d = Env.module;
                if (c && d === undefined) {
                    var b = {
                        fbpage_fan_confirm: 1
                    };
                    var e = null;
                    for (var a = c; a && a != document.body; a = a.parentNode) {
                        if (!a.id || typeof a.id !== 'string') continue;
                        if (a.id.startsWith('pagelet_')) {
                            d = a.id;
                            break
                        }
                        if (!e && b[a.id]) e = a.id
                    }
                    if (d === undefined && e) d = e
                }
                if (d !== undefined) {
                    if (this.data.nctr === undefined) this.data.nctr = {};
                    this.data.nctr._mod = d
                }
            }
        },
        setNectarImpressionId: function () {
            if (this.method == 'POST') {
                var a = env_get('impid');
                if (a !== undefined) {
                    if (this.data.nctr === undefined) this.data.nctr = {};
                    this.data.nctr._impid = a
                }
            }
        }
    })
});

function htmlspecialchars(a) {
    if (typeof (a) == 'undefined' || a === null || !a.toString) return '';
    if (a === false) {
        return '0'
    } else if (a === true) return '1';
    return a.toString().replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/'/g, '&#039;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
}
function htmlize(a) {
    return htmlspecialchars(a).replace(/\n/g, '<br />')
}
function escape_js_quotes(a) {
    if (typeof (a) == 'undefined' || !a.toString) return '';
    return a.toString().replace(/\\/g, '\\\\').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/"/g, '\\x22').replace(/'/g, '\\\'').replace(/</g, '\\x3c').replace(/>/g, '\\x3e').replace(/&/g, '\\x26')
}!
function () {
    var a = function () {
            var b = 0;
            return function () {
                if (!b) {
                    b = 1;
                    setTimeout(function () {
                        b = 0;
                        var c = Vector2.getViewportDimensions();
                        setCookie('wd', c.x + 'x' + c.y)
                    }, 100)
                }
            }
        }();
    onloadRegister(a);
    onloadRegister(function () {
        Event.listen(window, 'resize', a)
    });
    onloadRegister(function () {
        Event.listen(window, 'focus', a)
    })
}();
onloadRegister(function () {
    Event.listen(document.documentElement, 'submit', function (b) {
        var a = b.getTarget().getElementsByTagName('*');
        for (var c = 0; c < a.length; c++) if (a[c].getAttribute('placeholder') && Input.isEmpty(a[c])) a[c].value = ''
    })
});
PresenceMessage = {
    STARTED: 'presence/started',
    SHUTDOWN: 'presence/shutdown',
    RESTARTED: 'presence/restarted',
    WINDOW_RESIZED: 'presence/window-resized',
    TAB_CLOSED: 'presence/tab-closed',
    TAB_OPENED: 'presence/tab-opened',
    PRESENCE_UPDATER_READY: 'presence/updater-ready',
    getAppMessageType: function (a, b) {
        return 'presence/app_message:' + a + ':' + b
    },
    getArbiterMessageType: function (a) {
        return 'presence/message:' + a
    }
};
var Live = {
    deferredRegistrations: {},
    logAll: false,
    startup: function () {
        Live.startup = bagofholding;
        Arbiter.subscribe(PresenceMessage.getArbiterMessageType('live'), Live.handleMessage.bind(Live))
    },
    lookupLiveNode: function (b, a) {
        var c = DOM.scry(document.body, '.live_' + b + '_' + a);
        c.forEach(function (e) {
            if (DataStore.get(e, 'seqnum') === undefined) {
                var d = JSON.parse(e.getAttribute('data-live'));
                DataStore.set(e, 'seqnum', d.seq)
            }
        });
        return c
    },
    handleMessage: function (d, a) {
        var b = a.obj;
        var c = this._processMessage.bind(this).curry(b.fbid, b.assoc, b);
        c(false);
        onpagecacheRegister(c.curry(true))
    },
    _processMessage: function (b, a, c, d) {
        var e = this.lookupLiveNode(b, a);
        if (!e) return false;
        e.forEach(function (h) {
            var f = DataStore.get(h, 'seqnum');
            if (c.expseq != f) {
                Live.log('mismatch', c.fbid, c.expseq, f);
                return false
            }
            Live.log('seqmatch', c.fbid, 'exp', c.expseq, 'cur', f);
            var g = {
                getRelativeTo: function () {
                    return h
                }
            };
            $A(c.updates).each(function (i) {
                new Function(i).apply(g)
            })
        })
    },
    log: function () {
        if (Live.logAll) {
            var a = $A(arguments).join(":");
            new AsyncSignal('/common/scribe_endpoint.php', {
                c: 'live_sequence',
                m: a
            }).send()
        }
    }
};
var LiveTimer = {
    restart: function (a) {
        this.serverTime = a;
        this.localStartTime = new Date().getTime() / 1000;
        this.updateTimeStamps()
    },
    updateTimeStamps: function () {
        LiveTimer.timestamps = DOM.scry(document.body, 'abbr.timestamp');
        LiveTimer.startLoop(20000)
    },
    addTimeStamps: function (a) {
        if (!a || !LiveTimer.timestamps) return;
        var c = DOM.scry(a, 'abbr.timestamp');
        for (var b = 0; b < c.length; ++b) LiveTimer.timestamps.push(c[b]);
        LiveTimer.startLoop(0)
    },
    startLoop: function (a) {
        this.stop();
        this.timeout = setTimeout(function () {
            LiveTimer.loop()
        }, a)
    },
    stop: function () {
        clearTimeout(this.timeout)
    },
    updateNode: function (a, b) {
        LiveTimer.updateNode = (ua.ie() < 7) ?
        function (c, d) {
            c.nextSibling.nodeValue = d
        } : function (c, d) {
            c.firstChild.nodeValue = d
        };
        LiveTimer.updateNode(a, b)
    },
    loop: function (d) {
        if (d) LiveTimer.updateTimeStamps();
        var c = Math.floor(new Date().getTime() / 1000 - LiveTimer.localStartTime);
        var a = -1;
        LiveTimer.timestamps && LiveTimer.timestamps.each(function (g) {
            var f = +new Date(g.getAttribute('data-date')) / 1000;
            var e = LiveTimer.renderRelativeTime(LiveTimer.serverTime + c, f);
            if (e.text) LiveTimer.updateNode(g, e.text);
            if (e.next != -1 && (e.next < a || a == -1)) a = e.next
        });
        if (a != -1) {
            var b = Math.max(20000, a * 1000);
            LiveTimer.timeout = setTimeout(function () {
                LiveTimer.loop()
            }, b)
        }
    },
    renderRelativeTime: function (c, d) {
        var e = {
            text: "",
            next: -1
        };
        if (c - d > (12 * 3600) || (new Date(c * 1000).getDay() != new Date(d * 1000).getDay())) return e;
        var f = c - d,
            b = Math.floor(f / 60),
            a = Math.floor(b / 60);
        if (b < 1) {
            e.text = _tx("a few seconds ago");
            e.next = 60 - f % 60;
            return e
        }
        if (a < 1) {
            if (b == 1) {
                e.text = _tx("about a minute ago")
            } else e.text = _tx("{number} minutes ago", {
                number: b
            });
            e.next = 60 - f % 60;
            return e
        }
        if (a != 11) e.next = 3600 - f % 3600;
        if (a == 1) {
            e.text = _tx("about an hour ago");
            return e
        }
        e.text = _tx("{number} hours ago", {
            number: a
        });
        return e
    }
};
if (!this.JSON) this.JSON = function () {
    function f(n) {
        return n < 10 ? '0' + n : n
    }
    Date.prototype.toJSON = function () {
        return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z'
    };
    var m = {
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '"': '\\"',
        '\\': '\\\\'
    };

    function stringify(value, whitelist) {
        var a, i, k, l, v;
        switch (typeof value) {
        case 'string':
            return (new RegExp('[\x00-\x1f\\\\"]')).test(value) ? '"' + value.replace(/[\x00-\x1f\\"]/g, function (a) {
                var c = m[a];
                if (c) return c;
                c = a.charCodeAt();
                return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16)
            }) + '"' : '"' + value + '"';
        case 'number':
            return isFinite(value) ? String(value) : 'null';
        case 'boolean':
            return String(value);
        case 'null':
            return 'null';
        case 'object':
            if (DOM.isNode(value)) return null;
            if (!value) return 'null';
            if (typeof value.toJSON === 'function') return stringify(value.toJSON());
            a = [];
            if (typeof value.length === 'number' && !(propertyIsEnumerable(value, 'length'))) {
                l = value.length;
                for (i = 0; i < l; i += 1) a.push(stringify(value[i], whitelist) || 'null');
                return '[' + a.join(',') + ']'
            }
            if (whitelist) {
                l = whitelist.length;
                for (i = 0; i < l; i += 1) {
                    k = whitelist[i];
                    if (typeof k === 'string') {
                        v = stringify(value[k], whitelist);
                        if (v) a.push(stringify(k) + ':' + v)
                    }
                }
            } else for (k in value) if (typeof k === 'string') {
                v = stringify(value[k], whitelist);
                if (v) a.push(stringify(k) + ':' + v)
            }
            return '{' + a.join(',') + '}'
        }
    }
    return {
        stringify: stringify,
        parse: function (text, filter) {
            var j;

            function walk(k, v) {
                var i, n;
                if (v && typeof v === 'object') for (i in v) if (Object.prototype.hasOwnProperty.apply(v, [i])) {
                    n = walk(i, v[i]);
                    if (n !== undefined) v[i] = n
                }
                return filter(k, v)
            }
            if (text && /^[\],:{}\s]*$/.test(text.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
                j = eval('(' + text + ')');
                return typeof filter === 'function' ? walk('', j) : j
            }
            throw new SyntaxError('decodeJSON')
        }
    }
}();

function propertyIsEnumerable(a, b) {
    if (a.propertyIsEnumerable) return a.propertyIsEnumerable(b);
    for (var c in a) if (c == b) return true;
    return false
}
function ufi_add_ft_hidden_node(c) {
    if (c.link_data) return;
    var a = collect_data_attrib(c, 'ft');
    if (count(a)) {
        var b = $N('input', {
            type: 'hidden',
            name: 'link_data',
            value: JSON.stringify(a)
        });
        c.appendChild(b)
    }
}
function ufi_add_all_link_data() {
    Bootloader.loadComponents('dom-collect', function () {
        DOM.scry(document.body, 'form.commentable_item').forEach(ufi_add_ft_hidden_node)
    })
}
var Button = (function () {
    var a = 'uiButtonDisabled';
    var c = 'button:blocker';
    var b = 'href';

    function d(i, h) {
        var g = DataStore.get(i, c);
        if (h) {
            if (g) {
                g.remove();
                DataStore.remove(i, c)
            }
        } else if (!g) DataStore.set(i, c, Event.listen(i, 'click', bagof(false), Event.Priority.URGENT))
    }
    function e(g) {
        var h = Parent.byClass(g, 'uiButton');
        if (!h) throw new Error('invalid use case');
        return h
    }
    function f(g) {
        return DOM.isNode(g, 'a')
    }
    return {
        getInputElement: function (g) {
            g = e(g);
            if (f(g)) throw new Error('invalid use case');
            return DOM.find(g, 'input')
        },
        isEnabled: function (g) {
            return !CSS.hasClass(e(g), a)
        },
        setEnabled: function (j, g) {
            j = e(j);
            CSS.conditionClass(j, a, !g);
            if (f(j)) {
                var h = j.href;
                var k = DataStore.get(j, b, '#');
                if (g) {
                    if (!h) j.href = k
                } else {
                    if (h && h !== k) DataStore.set(j, b, h);
                    j.removeAttribute('href')
                }
                d(j, g)
            } else {
                var i = Button.getInputElement(j);
                i.disabled = !g;
                d(i, g)
            }
        },
        setLabel: function (h, g) {
            h = e(h);
            if (f(h)) {
                var i = DOM.find(h, 'span.uiButtonText');
                DOM.setContent(i, g)
            } else Button.getInputElement(h).value = g;
            CSS.conditionClass(h, 'uiButtonNoText', !g)
        },
        setIcon: function (h, g) {
            if (!DOM.isNode(g)) return;
            CSS.addClass(g, 'customimg');
            h = e(h);
            var i = DOM.scry(h, '.img')[0];
            if (i) {
                DOM.replace(i, g)
            } else DOM.prependContent(h, g)
        }
    }
})();
(function (window, undefined) {
    var document = window.document;
    var jQuery = (function () {
        var jQuery = function (selector, context) {
                return new jQuery.fn.init(selector, context, rootjQuery)
            },
            _jQuery = window.jQuery,
            _$ = window.$,
            rootjQuery, quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
            rnotwhite = /\S/,
            trimLeft = /^\s+/,
            trimRight = /\s+$/,
            rdigit = /\d/,
            rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
            rvalidchars = /^[\],:{}\s]*$/,
            rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
            rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
            rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
            rwebkit = /(webkit)[ \/]([\w.]+)/,
            ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
            rmsie = /(msie) ([\w.]+)/,
            rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
            userAgent = navigator.userAgent,
            browserMatch, readyList, DOMContentLoaded, toString = Object.prototype.toString,
            hasOwn = Object.prototype.hasOwnProperty,
            push = Array.prototype.push,
            slice = Array.prototype.slice,
            trim = String.prototype.trim,
            indexOf = Array.prototype.indexOf,
            class2type = {};
        jQuery.fn = jQuery.prototype = {
            constructor: jQuery,
            init: function (selector, context, rootjQuery) {
                var match, elem, ret, doc;
                if (!selector) {
                    return this
                }
                if (selector.nodeType) {
                    this.context = this[0] = selector;
                    this.length = 1;
                    return this
                }
                if (selector === "body" && !context && document.body) {
                    this.context = document;
                    this[0] = document.body;
                    this.selector = "body";
                    this.length = 1;
                    return this
                }
                if (typeof selector === "string") {
                    match = quickExpr.exec(selector);
                    if (match && (match[1] || !context)) {
                        if (match[1]) {
                            context = context instanceof jQuery ? context[0] : context;
                            doc = (context ? context.ownerDocument || context : document);
                            ret = rsingleTag.exec(selector);
                            if (ret) {
                                if (jQuery.isPlainObject(context)) {
                                    selector = [document.createElement(ret[1])];
                                    jQuery.fn.attr.call(selector, context, true)
                                } else {
                                    selector = [doc.createElement(ret[1])]
                                }
                            } else {
                                ret = jQuery.buildFragment([match[1]], [doc]);
                                selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes
                            }
                            return jQuery.merge(this, selector)
                        } else {
                            elem = document.getElementById(match[2]);
                            if (elem && elem.parentNode) {
                                if (elem.id !== match[2]) {
                                    return rootjQuery.find(selector)
                                }
                                this.length = 1;
                                this[0] = elem
                            }
                            this.context = document;
                            this.selector = selector;
                            return this
                        }
                    } else if (!context || context.jquery) {
                        return (context || rootjQuery).find(selector)
                    } else {
                        return this.constructor(context).find(selector)
                    }
                } else if (jQuery.isFunction(selector)) {
                    return rootjQuery.ready(selector)
                }
                if (selector.selector !== undefined) {
                    this.selector = selector.selector;
                    this.context = selector.context
                }
                return jQuery.makeArray(selector, this)
            },
            selector: "",
            jquery: "1.5.2",
            length: 0,
            size: function () {
                return this.length
            },
            toArray: function () {
                return slice.call(this, 0)
            },
            get: function (num) {
                return num == null ? this.toArray() : (num < 0 ? this[this.length + num] : this[num])
            },
            pushStack: function (elems, name, selector) {
                var ret = this.constructor();
                if (jQuery.isArray(elems)) {
                    push.apply(ret, elems)
                } else {
                    jQuery.merge(ret, elems)
                }
                ret.prevObject = this;
                ret.context = this.context;
                if (name === "find") {
                    ret.selector = this.selector + (this.selector ? " " : "") + selector
                } else if (name) {
                    ret.selector = this.selector + "." + name + "(" + selector + ")"
                }
                return ret
            },
            each: function (callback, args) {
                return jQuery.each(this, callback, args)
            },
            ready: function (fn) {
                jQuery.bindReady();
                readyList.done(fn);
                return this
            },
            eq: function (i) {
                return i === -1 ? this.slice(i) : this.slice(i, +i + 1)
            },
            first: function () {
                return this.eq(0)
            },
            last: function () {
                return this.eq(-1)
            },
            slice: function () {
                return this.pushStack(slice.apply(this, arguments), "slice", slice.call(arguments).join(","))
            },
            map: function (callback) {
                return this.pushStack(jQuery.map(this, function (elem, i) {
                    return callback.call(elem, i, elem)
                }))
            },
            end: function () {
                return this.prevObject || this.constructor(null)
            },
            push: push,
            sort: [].sort,
            splice: [].splice
        };
        jQuery.fn.init.prototype = jQuery.fn;
        jQuery.extend = jQuery.fn.extend = function () {
            var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {},
                i = 1,
                length = arguments.length,
                deep = false;
            if (typeof target === "boolean") {
                deep = target;
                target = arguments[1] || {};
                i = 2
            }
            if (typeof target !== "object" && !jQuery.isFunction(target)) {
                target = {}
            }
            if (length === i) {
                target = this;
                --i
            }
            for (; i < length; i++) {
                if ((options = arguments[i]) != null) {
                    for (name in options) {
                        src = target[name];
                        copy = options[name];
                        if (target === copy) {
                            continue
                        }
                        if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) {
                            if (copyIsArray) {
                                copyIsArray = false;
                                clone = src && jQuery.isArray(src) ? src : []
                            } else {
                                clone = src && jQuery.isPlainObject(src) ? src : {}
                            }
                            target[name] = jQuery.extend(deep, clone, copy)
                        } else if (copy !== undefined) {
                            target[name] = copy
                        }
                    }
                }
            }
            return target
        };
        jQuery.extend({
            noConflict: function (deep) {
                window.$ = _$;
                if (deep) {
                    window.jQuery = _jQuery
                }
                return jQuery
            },
            isReady: false,
            readyWait: 1,
            ready: function (wait) {
                if (wait === true) {
                    jQuery.readyWait--
                }
                if (!jQuery.readyWait || (wait !== true && !jQuery.isReady)) {
                    if (!document.body) {
                        return setTimeout(jQuery.ready, 1)
                    }
                    jQuery.isReady = true;
                    if (wait !== true && --jQuery.readyWait > 0) {
                        return
                    }
                    readyList.resolveWith(document, [jQuery]);
                    if (jQuery.fn.trigger) {
                        jQuery(document).trigger("ready").unbind("ready")
                    }
                }
            },
            bindReady: function () {
                if (readyList) {
                    return
                }
                readyList = jQuery._Deferred();
                if (document.readyState === "complete") {
                    return setTimeout(jQuery.ready, 1)
                }
                if (document.addEventListener) {
                    document.addEventListener("DOMContentLoaded", DOMContentLoaded, false);
                    window.addEventListener("load", jQuery.ready, false)
                } else if (document.attachEvent) {
                    document.attachEvent("onreadystatechange", DOMContentLoaded);
                    window.attachEvent("onload", jQuery.ready);
                    var toplevel = false;
                    try {
                        toplevel = window.frameElement == null
                    } catch (e) {}
                    if (document.documentElement.doScroll && toplevel) {
                        doScrollCheck()
                    }
                }
            },
            isFunction: function (obj) {
                return jQuery.type(obj) === "function"
            },
            isArray: Array.isArray ||
            function (obj) {
                return jQuery.type(obj) === "array"
            },
            isWindow: function (obj) {
                return obj && typeof obj === "object" && "setInterval" in obj
            },
            isNaN: function (obj) {
                return obj == null || !rdigit.test(obj) || isNaN(obj)
            },
            type: function (obj) {
                return obj == null ? String(obj) : class2type[toString.call(obj)] || "object"
            },
            isPlainObject: function (obj) {
                if (!obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow(obj)) {
                    return false
                }
                if (obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
                    return false
                }
                var key;
                for (key in obj) {}
                return key === undefined || hasOwn.call(obj, key)
            },
            isEmptyObject: function (obj) {
                for (var name in obj) {
                    return false
                }
                return true
            },
            error: function (msg) {
                throw msg
            },
            parseJSON: function (data) {
                if (typeof data !== "string" || !data) {
                    return null
                }
                data = jQuery.trim(data);
                if (rvalidchars.test(data.replace(rvalidescape, "@").replace(rvalidtokens, "]").replace(rvalidbraces, ""))) {
                    return window.JSON && window.JSON.parse ? window.JSON.parse(data) : (new Function("return " + data))()
                } else {
                    jQuery.error("Invalid JSON: " + data)
                }
            },
            parseXML: function (data, xml, tmp) {
                if (window.DOMParser) {
                    tmp = new DOMParser();
                    xml = tmp.parseFromString(data, "text/xml")
                } else {
                    xml = new ActiveXObject("Microsoft.XMLDOM");
                    xml.async = "false";
                    xml.loadXML(data)
                }
                tmp = xml.documentElement;
                if (!tmp || !tmp.nodeName || tmp.nodeName === "parsererror") {
                    jQuery.error("Invalid XML: " + data)
                }
                return xml
            },
            noop: function () {},
            globalEval: function (data) {
                if (data && rnotwhite.test(data)) {
                    var head = document.head || document.getElementsByTagName("head")[0] || document.documentElement,
                        script = document.createElement("script");
                    if (jQuery.support.scriptEval()) {
                        script.appendChild(document.createTextNode(data))
                    } else {
                        script.text = data
                    }
                    head.insertBefore(script, head.firstChild);
                    head.removeChild(script)
                }
            },
            nodeName: function (elem, name) {
                return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase()
            },
            each: function (object, callback, args) {
                var name, i = 0,
                    length = object.length,
                    isObj = length === undefined || jQuery.isFunction(object);
                if (args) {
                    if (isObj) {
                        for (name in object) {
                            if (callback.apply(object[name], args) === false) {
                                break
                            }
                        }
                    } else {
                        for (; i < length;) {
                            if (callback.apply(object[i++], args) === false) {
                                break
                            }
                        }
                    }
                } else {
                    if (isObj) {
                        for (name in object) {
                            if (callback.call(object[name], name, object[name]) === false) {
                                break
                            }
                        }
                    } else {
                        for (var value = object[0]; i < length && callback.call(value, i, value) !== false; value = object[++i]) {}
                    }
                }
                return object
            },
            trim: trim ?
            function (text) {
                return text == null ? "" : trim.call(text)
            } : function (text) {
                return text == null ? "" : text.toString().replace(trimLeft, "").replace(trimRight, "")
            },
            makeArray: function (array, results) {
                var ret = results || [];
                if (array != null) {
                    var type = jQuery.type(array);
                    if (array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow(array)) {
                        push.call(ret, array)
                    } else {
                        jQuery.merge(ret, array)
                    }
                }
                return ret
            },
            inArray: function (elem, array) {
                if (array.indexOf) {
                    return array.indexOf(elem)
                }
                for (var i = 0, length = array.length; i < length; i++) {
                    if (array[i] === elem) {
                        return i
                    }
                }
                return -1
            },
            merge: function (first, second) {
                var i = first.length,
                    j = 0;
                if (typeof second.length === "number") {
                    for (var l = second.length; j < l; j++) {
                        first[i++] = second[j]
                    }
                } else {
                    while (second[j] !== undefined) {
                        first[i++] = second[j++]
                    }
                }
                first.length = i;
                return first
            },
            grep: function (elems, callback, inv) {
                var ret = [],
                    retVal;
                inv = !! inv;
                for (var i = 0, length = elems.length; i < length; i++) {
                    retVal = !! callback(elems[i], i);
                    if (inv !== retVal) {
                        ret.push(elems[i])
                    }
                }
                return ret
            },
            map: function (elems, callback, arg) {
                var ret = [],
                    value;
                for (var i = 0, length = elems.length; i < length; i++) {
                    value = callback(elems[i], i, arg);
                    if (value != null) {
                        ret[ret.length] = value
                    }
                }
                return ret.concat.apply([], ret)
            },
            guid: 1,
            proxy: function (fn, proxy, thisObject) {
                if (arguments.length === 2) {
                    if (typeof proxy === "string") {
                        thisObject = fn;
                        fn = thisObject[proxy];
                        proxy = undefined
                    } else if (proxy && !jQuery.isFunction(proxy)) {
                        thisObject = proxy;
                        proxy = undefined
                    }
                }
                if (!proxy && fn) {
                    proxy = function () {
                        return fn.apply(thisObject || this, arguments)
                    }
                }
                if (fn) {
                    proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++
                }
                return proxy
            },
            access: function (elems, key, value, exec, fn, pass) {
                var length = elems.length;
                if (typeof key === "object") {
                    for (var k in key) {
                        jQuery.access(elems, k, key[k], exec, fn, value)
                    }
                    return elems
                }
                if (value !== undefined) {
                    exec = !pass && exec && jQuery.isFunction(value);
                    for (var i = 0; i < length; i++) {
                        fn(elems[i], key, exec ? value.call(elems[i], i, fn(elems[i], key)) : value, pass)
                    }
                    return elems
                }
                return length ? fn(elems[0], key) : undefined
            },
            now: function () {
                return (new Date()).getTime()
            },
            uaMatch: function (ua) {
                ua = ua.toLowerCase();
                var match = rwebkit.exec(ua) || ropera.exec(ua) || rmsie.exec(ua) || ua.indexOf("compatible") < 0 && rmozilla.exec(ua) || [];
                return {
                    browser: match[1] || "",
                    version: match[2] || "0"
                }
            },
            sub: function () {
                function jQuerySubclass(selector, context) {
                    return new jQuerySubclass.fn.init(selector, context)
                }
                jQuery.extend(true, jQuerySubclass, this);
                jQuerySubclass.superclass = this;
                jQuerySubclass.fn = jQuerySubclass.prototype = this();
                jQuerySubclass.fn.constructor = jQuerySubclass;
                jQuerySubclass.subclass = this.subclass;
                jQuerySubclass.fn.init = function init(selector, context) {
                    if (context && context instanceof jQuery && !(context instanceof jQuerySubclass)) {
                        context = jQuerySubclass(context)
                    }
                    return jQuery.fn.init.call(this, selector, context, rootjQuerySubclass)
                };
                jQuerySubclass.fn.init.prototype = jQuerySubclass.fn;
                var rootjQuerySubclass = jQuerySubclass(document);
                return jQuerySubclass
            },
            browser: {}
        });
        jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function (i, name) {
            class2type["[object " + name + "]"] = name.toLowerCase()
        });
        browserMatch = jQuery.uaMatch(userAgent);
        if (browserMatch.browser) {
            jQuery.browser[browserMatch.browser] = true;
            jQuery.browser.version = browserMatch.version
        }
        if (jQuery.browser.webkit) {
            jQuery.browser.safari = true
        }
        if (indexOf) {
            jQuery.inArray = function (elem, array) {
                return indexOf.call(array, elem)
            }
        }
        if (rnotwhite.test("\xA0")) {
            trimLeft = /^[\s\xA0]+/;
            trimRight = /[\s\xA0]+$/
        }
        rootjQuery = jQuery(document);
        if (document.addEventListener) {
            DOMContentLoaded = function () {
                document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false);
                jQuery.ready()
            }
        } else if (document.attachEvent) {
            DOMContentLoaded = function () {
                if (document.readyState === "complete") {
                    document.detachEvent("onreadystatechange", DOMContentLoaded);
                    jQuery.ready()
                }
            }
        }
        function doScrollCheck() {
            if (jQuery.isReady) {
                return
            }
            try {
                document.documentElement.doScroll("left")
            } catch (e) {
                setTimeout(doScrollCheck, 1);
                return
            }
            jQuery.ready()
        }
        return jQuery
    })();
    var promiseMethods = "then done fail isResolved isRejected promise".split(" "),
        sliceDeferred = [].slice;
    jQuery.extend({
        _Deferred: function () {
            var callbacks = [],
                fired, firing, cancelled, deferred = {
                    done: function () {
                        if (!cancelled) {
                            var args = arguments,
                                i, length, elem, type, _fired;
                            if (fired) {
                                _fired = fired;
                                fired = 0
                            }
                            for (i = 0, length = args.length; i < length; i++) {
                                elem = args[i];
                                type = jQuery.type(elem);
                                if (type === "array") {
                                    deferred.done.apply(deferred, elem)
                                } else if (type === "function") {
                                    callbacks.push(elem)
                                }
                            }
                            if (_fired) {
                                deferred.resolveWith(_fired[0], _fired[1])
                            }
                        }
                        return this
                    },
                    resolveWith: function (context, args) {
                        if (!cancelled && !fired && !firing) {
                            args = args || [];
                            firing = 1;
                            try {
                                while (callbacks[0]) {
                                    callbacks.shift().apply(context, args)
                                }
                            } finally {
                                fired = [context, args];
                                firing = 0
                            }
                        }
                        return this
                    },
                    resolve: function () {
                        deferred.resolveWith(this, arguments);
                        return this
                    },
                    isResolved: function () {
                        return !!(firing || fired)
                    },
                    cancel: function () {
                        cancelled = 1;
                        callbacks = [];
                        return this
                    }
                };
            return deferred
        },
        Deferred: function (func) {
            var deferred = jQuery._Deferred(),
                failDeferred = jQuery._Deferred(),
                promise;
            jQuery.extend(deferred, {
                then: function (doneCallbacks, failCallbacks) {
                    deferred.done(doneCallbacks).fail(failCallbacks);
                    return this
                },
                fail: failDeferred.done,
                rejectWith: failDeferred.resolveWith,
                reject: failDeferred.resolve,
                isRejected: failDeferred.isResolved,
                promise: function (obj) {
                    if (obj == null) {
                        if (promise) {
                            return promise
                        }
                        promise = obj = {}
                    }
                    var i = promiseMethods.length;
                    while (i--) {
                        obj[promiseMethods[i]] = deferred[promiseMethods[i]]
                    }
                    return obj
                }
            });
            deferred.done(failDeferred.cancel).fail(deferred.cancel);
            delete deferred.cancel;
            if (func) {
                func.call(deferred, deferred)
            }
            return deferred
        },
        when: function (firstParam) {
            var args = arguments,
                i = 0,
                length = args.length,
                count = length,
                deferred = length <= 1 && firstParam && jQuery.isFunction(firstParam.promise) ? firstParam : jQuery.Deferred();

            function resolveFunc(i) {
                return function (value) {
                    args[i] = arguments.length > 1 ? sliceDeferred.call(arguments, 0) : value;
                    if (!(--count)) {
                        deferred.resolveWith(deferred, sliceDeferred.call(args, 0))
                    }
                }
            }
            if (length > 1) {
                for (; i < length; i++) {
                    if (args[i] && jQuery.isFunction(args[i].promise)) {
                        args[i].promise().then(resolveFunc(i), deferred.reject)
                    } else {
                        --count
                    }
                }
                if (!count) {
                    deferred.resolveWith(deferred, args)
                }
            } else if (deferred !== firstParam) {
                deferred.resolveWith(deferred, length ? [firstParam] : [])
            }
            return deferred.promise()
        }
    });
    (function () {
        jQuery.support = {};
        var div = document.createElement("div");
        div.style.display = "none";
        div.innerHTML = "   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
        var all = div.getElementsByTagName("*"),
            a = div.getElementsByTagName("a")[0],
            select = document.createElement("select"),
            opt = select.appendChild(document.createElement("option")),
            input = div.getElementsByTagName("input")[0];
        if (!all || !all.length || !a) {
            return
        }
        jQuery.support = {
            leadingWhitespace: div.firstChild.nodeType === 3,
            tbody: !div.getElementsByTagName("tbody").length,
            htmlSerialize: !! div.getElementsByTagName("link").length,
            style: /red/.test(a.getAttribute("style")),
            hrefNormalized: a.getAttribute("href") === "/a",
            opacity: /^0.55$/.test(a.style.opacity),
            cssFloat: !! a.style.cssFloat,
            checkOn: input.value === "on",
            optSelected: opt.selected,
            deleteExpando: true,
            optDisabled: false,
            checkClone: false,
            noCloneEvent: true,
            noCloneChecked: true,
            boxModel: null,
            inlineBlockNeedsLayout: false,
            shrinkWrapBlocks: false,
            reliableHiddenOffsets: true,
            reliableMarginRight: true
        };
        input.checked = true;
        jQuery.support.noCloneChecked = input.cloneNode(true).checked;
        select.disabled = true;
        jQuery.support.optDisabled = !opt.disabled;
        var _scriptEval = null;
        jQuery.support.scriptEval = function () {
            if (_scriptEval === null) {
                var root = document.documentElement,
                    script = document.createElement("script"),
                    id = "script" + jQuery.now();
                try {
                    script.appendChild(document.createTextNode("window." + id + "=1;"))
                } catch (e) {}
                root.insertBefore(script, root.firstChild);
                if (window[id]) {
                    _scriptEval = true;
                    delete window[id]
                } else {
                    _scriptEval = false
                }
                root.removeChild(script)
            }
            return _scriptEval
        };
        try {
            delete div.test
        } catch (e) {
            jQuery.support.deleteExpando = false
        }
        if (!div.addEventListener && div.attachEvent && div.fireEvent) {
            div.attachEvent("onclick", function click() {
                jQuery.support.noCloneEvent = false;
                div.detachEvent("onclick", click)
            });
            div.cloneNode(true).fireEvent("onclick")
        }
        div = document.createElement("div");
        div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
        var fragment = document.createDocumentFragment();
        fragment.appendChild(div.firstChild);
        jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
        jQuery(function () {
            var div = document.createElement("div"),
                body = document.getElementsByTagName("body")[0];
            if (!body) {
                return
            }
            div.style.width = div.style.paddingLeft = "1px";
            body.appendChild(div);
            jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
            if ("zoom" in div.style) {
                div.style.display = "inline";
                div.style.zoom = 1;
                jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2;
                div.style.display = "";
                div.innerHTML = "<div style='width:4px;'></div>";
                jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2
            }
            div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
            var tds = div.getElementsByTagName("td");
            jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0;
            tds[0].style.display = "";
            tds[1].style.display = "none";
            jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0;
            div.innerHTML = "";
            if (document.defaultView && document.defaultView.getComputedStyle) {
                div.style.width = "1px";
                div.style.marginRight = "0";
                jQuery.support.reliableMarginRight = (parseInt(document.defaultView.getComputedStyle(div, null).marginRight, 10) || 0) === 0
            }
            body.removeChild(div).style.display = "none";
            div = tds = null
        });
        var eventSupported = function (eventName) {
                var el = document.createElement("div");
                eventName = "on" + eventName;
                if (!el.attachEvent) {
                    return true
                }
                var isSupported = (eventName in el);
                if (!isSupported) {
                    el.setAttribute(eventName, "return;");
                    isSupported = typeof el[eventName] === "function"
                }
                return isSupported
            };
        jQuery.support.submitBubbles = eventSupported("submit");
        jQuery.support.changeBubbles = eventSupported("change");
        div = all = a = null
    })();
    var rbrace = /^(?:\{.*\}|\[.*\])$/;
    jQuery.extend({
        cache: {},
        uuid: 0,
        expando: "jQuery" + (jQuery.fn.jquery + Math.random()).replace(/\D/g, ""),
        noData: {
            "embed": true,
            "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
            "applet": true
        },
        hasData: function (elem) {
            elem = elem.nodeType ? jQuery.cache[elem[jQuery.expando]] : elem[jQuery.expando];
            return !!elem && !isEmptyDataObject(elem)
        },
        data: function (elem, name, data, pvt) {
            if (!jQuery.acceptData(elem)) {
                return
            }
            var internalKey = jQuery.expando,
                getByName = typeof name === "string",
                thisCache, isNode = elem.nodeType,
                cache = isNode ? jQuery.cache : elem,
                id = isNode ? elem[jQuery.expando] : elem[jQuery.expando] && jQuery.expando;
            if ((!id || (pvt && id && !cache[id][internalKey])) && getByName && data === undefined) {
                return
            }
            if (!id) {
                if (isNode) {
                    elem[jQuery.expando] = id = ++jQuery.uuid
                } else {
                    id = jQuery.expando
                }
            }
            if (!cache[id]) {
                cache[id] = {};
                if (!isNode) {
                    cache[id].toJSON = jQuery.noop
                }
            }
            if (typeof name === "object" || typeof name === "function") {
                if (pvt) {
                    cache[id][internalKey] = jQuery.extend(cache[id][internalKey], name)
                } else {
                    cache[id] = jQuery.extend(cache[id], name)
                }
            }
            thisCache = cache[id];
            if (pvt) {
                if (!thisCache[internalKey]) {
                    thisCache[internalKey] = {}
                }
                thisCache = thisCache[internalKey]
            }
            if (data !== undefined) {
                thisCache[name] = data
            }
            if (name === "events" && !thisCache[name]) {
                return thisCache[internalKey] && thisCache[internalKey].events
            }
            return getByName ? thisCache[name] : thisCache
        },
        removeData: function (elem, name, pvt) {
            if (!jQuery.acceptData(elem)) {
                return
            }
            var internalKey = jQuery.expando,
                isNode = elem.nodeType,
                cache = isNode ? jQuery.cache : elem,
                id = isNode ? elem[jQuery.expando] : jQuery.expando;
            if (!cache[id]) {
                return
            }
            if (name) {
                var thisCache = pvt ? cache[id][internalKey] : cache[id];
                if (thisCache) {
                    delete thisCache[name];
                    if (!isEmptyDataObject(thisCache)) {
                        return
                    }
                }
            }
            if (pvt) {
                delete cache[id][internalKey];
                if (!isEmptyDataObject(cache[id])) {
                    return
                }
            }
            var internalCache = cache[id][internalKey];
            if (jQuery.support.deleteExpando || cache != window) {
                delete cache[id]
            } else {
                cache[id] = null
            }
            if (internalCache) {
                cache[id] = {};
                if (!isNode) {
                    cache[id].toJSON = jQuery.noop
                }
                cache[id][internalKey] = internalCache
            } else if (isNode) {
                if (jQuery.support.deleteExpando) {
                    delete elem[jQuery.expando]
                } else if (elem.removeAttribute) {
                    elem.removeAttribute(jQuery.expando)
                } else {
                    elem[jQuery.expando] = null
                }
            }
        },
        _data: function (elem, name, data) {
            return jQuery.data(elem, name, data, true)
        },
        acceptData: function (elem) {
            if (elem.nodeName) {
                var match = jQuery.noData[elem.nodeName.toLowerCase()];
                if (match) {
                    return !(match === true || elem.getAttribute("classid") !== match)
                }
            }
            return true
        }
    });
    jQuery.fn.extend({
        data: function (key, value) {
            var data = null;
            if (typeof key === "undefined") {
                if (this.length) {
                    data = jQuery.data(this[0]);
                    if (this[0].nodeType === 1) {
                        var attr = this[0].attributes,
                            name;
                        for (var i = 0, l = attr.length; i < l; i++) {
                            name = attr[i].name;
                            if (name.indexOf("data-") === 0) {
                                name = name.substr(5);
                                dataAttr(this[0], name, data[name])
                            }
                        }
                    }
                }
                return data
            } else if (typeof key === "object") {
                return this.each(function () {
                    jQuery.data(this, key)
                })
            }
            var parts = key.split(".");
            parts[1] = parts[1] ? "." + parts[1] : "";
            if (value === undefined) {
                data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
                if (data === undefined && this.length) {
                    data = jQuery.data(this[0], key);
                    data = dataAttr(this[0], key, data)
                }
                return data === undefined && parts[1] ? this.data(parts[0]) : data
            } else {
                return this.each(function () {
                    var $this = jQuery(this),
                        args = [parts[0], value];
                    $this.triggerHandler("setData" + parts[1] + "!", args);
                    jQuery.data(this, key, value);
                    $this.triggerHandler("changeData" + parts[1] + "!", args)
                })
            }
        },
        removeData: function (key) {
            return this.each(function () {
                jQuery.removeData(this, key)
            })
        }
    });

    function dataAttr(elem, key, data) {
        if (data === undefined && elem.nodeType === 1) {
            data = elem.getAttribute("data-" + key);
            if (typeof data === "string") {
                try {
                    data = data === "true" ? true : data === "false" ? false : data === "null" ? null : !jQuery.isNaN(data) ? parseFloat(data) : rbrace.test(data) ? jQuery.parseJSON(data) : data
                } catch (e) {}
                jQuery.data(elem, key, data)
            } else {
                data = undefined
            }
        }
        return data
    }
    function isEmptyDataObject(obj) {
        for (var name in obj) {
            if (name !== "toJSON") {
                return false
            }
        }
        return true
    }
    jQuery.extend({
        queue: function (elem, type, data) {
            if (!elem) {
                return
            }
            type = (type || "fx") + "queue";
            var q = jQuery._data(elem, type);
            if (!data) {
                return q || []
            }
            if (!q || jQuery.isArray(data)) {
                q = jQuery._data(elem, type, jQuery.makeArray(data))
            } else {
                q.push(data)
            }
            return q
        },
        dequeue: function (elem, type) {
            type = type || "fx";
            var queue = jQuery.queue(elem, type),
                fn = queue.shift();
            if (fn === "inprogress") {
                fn = queue.shift()
            }
            if (fn) {
                if (type === "fx") {
                    queue.unshift("inprogress")
                }
                fn.call(elem, function () {
                    jQuery.dequeue(elem, type)
                })
            }
            if (!queue.length) {
                jQuery.removeData(elem, type + "queue", true)
            }
        }
    });
    jQuery.fn.extend({
        queue: function (type, data) {
            if (typeof type !== "string") {
                data = type;
                type = "fx"
            }
            if (data === undefined) {
                return jQuery.queue(this[0], type)
            }
            return this.each(function (i) {
                var queue = jQuery.queue(this, type, data);
                if (type === "fx" && queue[0] !== "inprogress") {
                    jQuery.dequeue(this, type)
                }
            })
        },
        dequeue: function (type) {
            return this.each(function () {
                jQuery.dequeue(this, type)
            })
        },
        delay: function (time, type) {
            time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
            type = type || "fx";
            return this.queue(type, function () {
                var elem = this;
                setTimeout(function () {
                    jQuery.dequeue(elem, type)
                }, time)
            })
        },
        clearQueue: function (type) {
            return this.queue(type || "fx", [])
        }
    });
    var rclass = /[\n\t\r]/g,
        rspaces = /\s+/,
        rreturn = /\r/g,
        rspecialurl = /^(?:href|src|style)$/,
        rtype = /^(?:button|input)$/i,
        rfocusable = /^(?:button|input|object|select|textarea)$/i,
        rclickable = /^a(?:rea)?$/i,
        rradiocheck = /^(?:radio|checkbox)$/i;
    jQuery.props = {
        "for": "htmlFor",
        "class": "className",
        readonly: "readOnly",
        maxlength: "maxLength",
        cellspacing: "cellSpacing",
        rowspan: "rowSpan",
        colspan: "colSpan",
        tabindex: "tabIndex",
        usemap: "useMap",
        frameborder: "frameBorder"
    };
    jQuery.fn.extend({
        attr: function (name, value) {
            return jQuery.access(this, name, value, true, jQuery.attr)
        },
        removeAttr: function (name, fn) {
            return this.each(function () {
                jQuery.attr(this, name, "");
                if (this.nodeType === 1) {
                    this.removeAttribute(name)
                }
            })
        },
        addClass: function (value) {
            if (jQuery.isFunction(value)) {
                return this.each(function (i) {
                    var self = jQuery(this);
                    self.addClass(value.call(this, i, self.attr("class")))
                })
            }
            if (value && typeof value === "string") {
                var classNames = (value || "").split(rspaces);
                for (var i = 0, l = this.length; i < l; i++) {
                    var elem = this[i];
                    if (elem.nodeType === 1) {
                        if (!elem.className) {
                            elem.className = value
                        } else {
                            var className = " " + elem.className + " ",
                                setClass = elem.className;
                            for (var c = 0, cl = classNames.length; c < cl; c++) {
                                if (className.indexOf(" " + classNames[c] + " ") < 0) {
                                    setClass += " " + classNames[c]
                                }
                            }
                            elem.className = jQuery.trim(setClass)
                        }
                    }
                }
            }
            return this
        },
        removeClass: function (value) {
            if (jQuery.isFunction(value)) {
                return this.each(function (i) {
                    var self = jQuery(this);
                    self.removeClass(value.call(this, i, self.attr("class")))
                })
            }
            if ((value && typeof value === "string") || value === undefined) {
                var classNames = (value || "").split(rspaces);
                for (var i = 0, l = this.length; i < l; i++) {
                    var elem = this[i];
                    if (elem.nodeType === 1 && elem.className) {
                        if (value) {
                            var className = (" " + elem.className + " ").replace(rclass, " ");
                            for (var c = 0, cl = classNames.length; c < cl; c++) {
                                className = className.replace(" " + classNames[c] + " ", " ")
                            }
                            elem.className = jQuery.trim(className)
                        } else {
                            elem.className = ""
                        }
                    }
                }
            }
            return this
        },
        toggleClass: function (value, stateVal) {
            var type = typeof value,
                isBool = typeof stateVal === "boolean";
            if (jQuery.isFunction(value)) {
                return this.each(function (i) {
                    var self = jQuery(this);
                    self.toggleClass(value.call(this, i, self.attr("class"), stateVal), stateVal)
                })
            }
            return this.each(function () {
                if (type === "string") {
                    var className, i = 0,
                        self = jQuery(this),
                        state = stateVal,
                        classNames = value.split(rspaces);
                    while ((className = classNames[i++])) {
                        state = isBool ? state : !self.hasClass(className);
                        self[state ? "addClass" : "removeClass"](className)
                    }
                } else if (type === "undefined" || type === "boolean") {
                    if (this.className) {
                        jQuery._data(this, "__className__", this.className)
                    }
                    this.className = this.className || value === false ? "" : jQuery._data(this, "__className__") || ""
                }
            })
        },
        hasClass: function (selector) {
            var className = " " + selector + " ";
            for (var i = 0, l = this.length; i < l; i++) {
                if ((" " + this[i].className + " ").replace(rclass, " ").indexOf(className) > -1) {
                    return true
                }
            }
            return false
        },
        val: function (value) {
            if (!arguments.length) {
                var elem = this[0];
                if (elem) {
                    if (jQuery.nodeName(elem, "option")) {
                        var val = elem.attributes.value;
                        return !val || val.specified ? elem.value : elem.text
                    }
                    if (jQuery.nodeName(elem, "select")) {
                        var index = elem.selectedIndex,
                            values = [],
                            options = elem.options,
                            one = elem.type === "select-one";
                        if (index < 0) {
                            return null
                        }
                        for (var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++) {
                            var option = options[i];
                            if (option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && (!option.parentNode.disabled || !jQuery.nodeName(option.parentNode, "optgroup"))) {
                                value = jQuery(option).val();
                                if (one) {
                                    return value
                                }
                                values.push(value)
                            }
                        }
                        if (one && !values.length && options.length) {
                            return jQuery(options[index]).val()
                        }
                        return values
                    }
                    if (rradiocheck.test(elem.type) && !jQuery.support.checkOn) {
                        return elem.getAttribute("value") === null ? "on" : elem.value
                    }
                    return (elem.value || "").replace(rreturn, "")
                }
                return undefined
            }
            var isFunction = jQuery.isFunction(value);
            return this.each(function (i) {
                var self = jQuery(this),
                    val = value;
                if (this.nodeType !== 1) {
                    return
                }
                if (isFunction) {
                    val = value.call(this, i, self.val())
                }
                if (val == null) {
                    val = ""
                } else if (typeof val === "number") {
                    val += ""
                } else if (jQuery.isArray(val)) {
                    val = jQuery.map(val, function (value) {
                        return value == null ? "" : value + ""
                    })
                }
                if (jQuery.isArray(val) && rradiocheck.test(this.type)) {
                    this.checked = jQuery.inArray(self.val(), val) >= 0
                } else if (jQuery.nodeName(this, "select")) {
                    var values = jQuery.makeArray(val);
                    jQuery("option", this).each(function () {
                        this.selected = jQuery.inArray(jQuery(this).val(), values) >= 0
                    });
                    if (!values.length) {
                        this.selectedIndex = -1
                    }
                } else {
                    this.value = val
                }
            })
        }
    });
    jQuery.extend({
        attrFn: {
            val: true,
            css: true,
            html: true,
            text: true,
            data: true,
            width: true,
            height: true,
            offset: true
        },
        attr: function (elem, name, value, pass) {
            if (!elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2) {
                return undefined
            }
            if (pass && name in jQuery.attrFn) {
                return jQuery(elem)[name](value)
            }
            var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc(elem),
                set = value !== undefined;
            name = notxml && jQuery.props[name] || name;
            if (elem.nodeType === 1) {
                var special = rspecialurl.test(name);
                if (name === "selected" && !jQuery.support.optSelected) {
                    var parent = elem.parentNode;
                    if (parent) {
                        parent.selectedIndex;
                        if (parent.parentNode) {
                            parent.parentNode.selectedIndex
                        }
                    }
                }
                if ((name in elem || elem[name] !== undefined) && notxml && !special) {
                    if (set) {
                        if (name === "type" && rtype.test(elem.nodeName) && elem.parentNode) {
                            jQuery.error("type property can't be changed")
                        }
                        if (value === null) {
                            if (elem.nodeType === 1) {
                                elem.removeAttribute(name)
                            }
                        } else {
                            elem[name] = value
                        }
                    }
                    if (jQuery.nodeName(elem, "form") && elem.getAttributeNode(name)) {
                        return elem.getAttributeNode(name).nodeValue
                    }
                    if (name === "tabIndex") {
                        var attributeNode = elem.getAttributeNode("tabIndex");
                        return attributeNode && attributeNode.specified ? attributeNode.value : rfocusable.test(elem.nodeName) || rclickable.test(elem.nodeName) && elem.href ? 0 : undefined
                    }
                    return elem[name]
                }
                if (!jQuery.support.style && notxml && name === "style") {
                    if (set) {
                        elem.style.cssText = "" + value
                    }
                    return elem.style.cssText
                }
                if (set) {
                    elem.setAttribute(name, "" + value)
                }
                if (!elem.attributes[name] && (elem.hasAttribute && !elem.hasAttribute(name))) {
                    return undefined
                }
                var attr = !jQuery.support.hrefNormalized && notxml && special ? elem.getAttribute(name, 2) : elem.getAttribute(name);
                return attr === null ? undefined : attr
            }
            if (set) {
                elem[name] = value
            }
            return elem[name]
        }
    });
    var rnamespaces = /\.(.*)$/,
        rformElems = /^(?:textarea|input|select)$/i,
        rperiod = /\./g,
        rspace = / /g,
        rescape = /[^\w\s.|`]/g,
        fcleanup = function (nm) {
            return nm.replace(rescape, "\\$&")
        };
    jQuery.event = {
        add: function (elem, types, handler, data) {
            if (elem.nodeType === 3 || elem.nodeType === 8) {
                return
            }
            try {
                if (jQuery.isWindow(elem) && (elem !== window && !elem.frameElement)) {
                    elem = window
                }
            } catch (e) {}
            if (handler === false) {
                handler = returnFalse
            } else if (!handler) {
                return
            }
            var handleObjIn, handleObj;
            if (handler.handler) {
                handleObjIn = handler;
                handler = handleObjIn.handler
            }
            if (!handler.guid) {
                handler.guid = jQuery.guid++
            }
            var elemData = jQuery._data(elem);
            if (!elemData) {
                return
            }
            var events = elemData.events,
                eventHandle = elemData.handle;
            if (!events) {
                elemData.events = events = {}
            }
            if (!eventHandle) {
                elemData.handle = eventHandle = function (e) {
                    return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? jQuery.event.handle.apply(eventHandle.elem, arguments) : undefined
                }
            }
            eventHandle.elem = elem;
            types = types.split(" ");
            var type, i = 0,
                namespaces;
            while ((type = types[i++])) {
                handleObj = handleObjIn ? jQuery.extend({}, handleObjIn) : {
                    handler: handler,
                    data: data
                };
                if (type.indexOf(".") > -1) {
                    namespaces = type.split(".");
                    type = namespaces.shift();
                    handleObj.namespace = namespaces.slice(0).sort().join(".")
                } else {
                    namespaces = [];
                    handleObj.namespace = ""
                }
                handleObj.type = type;
                if (!handleObj.guid) {
                    handleObj.guid = handler.guid
                }
                var handlers = events[type],
                    special = jQuery.event.special[type] || {};
                if (!handlers) {
                    handlers = events[type] = [];
                    if (!special.setup || special.setup.call(elem, data, namespaces, eventHandle) === false) {
                        if (elem.addEventListener) {
                            elem.addEventListener(type, eventHandle, false)
                        } else if (elem.attachEvent) {
                            elem.attachEvent("on" + type, eventHandle)
                        }
                    }
                }
                if (special.add) {
                    special.add.call(elem, handleObj);
                    if (!handleObj.handler.guid) {
                        handleObj.handler.guid = handler.guid
                    }
                }
                handlers.push(handleObj);
                jQuery.event.global[type] = true
            }
            elem = null
        },
        global: {},
        remove: function (elem, types, handler, pos) {
            if (elem.nodeType === 3 || elem.nodeType === 8) {
                return
            }
            if (handler === false) {
                handler = returnFalse
            }
            var ret, type, fn, j, i = 0,
                all, namespaces, namespace, special, eventType, handleObj, origType, elemData = jQuery.hasData(elem) && jQuery._data(elem),
                events = elemData && elemData.events;
            if (!elemData || !events) {
                return
            }
            if (types && types.type) {
                handler = types.handler;
                types = types.type
            }
            if (!types || typeof types === "string" && types.charAt(0) === ".") {
                types = types || "";
                for (type in events) {
                    jQuery.event.remove(elem, type + types)
                }
                return
            }
            types = types.split(" ");
            while ((type = types[i++])) {
                origType = type;
                handleObj = null;
                all = type.indexOf(".") < 0;
                namespaces = [];
                if (!all) {
                    namespaces = type.split(".");
                    type = namespaces.shift();
                    namespace = new RegExp("(^|\\.)" + jQuery.map(namespaces.slice(0).sort(), fcleanup).join("\\.(?:.*\\.)?") + "(\\.|$)")
                }
                eventType = events[type];
                if (!eventType) {
                    continue
                }
                if (!handler) {
                    for (j = 0; j < eventType.length; j++) {
                        handleObj = eventType[j];
                        if (all || namespace.test(handleObj.namespace)) {
                            jQuery.event.remove(elem, origType, handleObj.handler, j);
                            eventType.splice(j--, 1)
                        }
                    }
                    continue
                }
                special = jQuery.event.special[type] || {};
                for (j = pos || 0; j < eventType.length; j++) {
                    handleObj = eventType[j];
                    if (handler.guid === handleObj.guid) {
                        if (all || namespace.test(handleObj.namespace)) {
                            if (pos == null) {
                                eventType.splice(j--, 1)
                            }
                            if (special.remove) {
                                special.remove.call(elem, handleObj)
                            }
                        }
                        if (pos != null) {
                            break
                        }
                    }
                }
                if (eventType.length === 0 || pos != null && eventType.length === 1) {
                    if (!special.teardown || special.teardown.call(elem, namespaces) === false) {
                        jQuery.removeEvent(elem, type, elemData.handle)
                    }
                    ret = null;
                    delete events[type]
                }
            }
            if (jQuery.isEmptyObject(events)) {
                var handle = elemData.handle;
                if (handle) {
                    handle.elem = null
                }
                delete elemData.events;
                delete elemData.handle;
                if (jQuery.isEmptyObject(elemData)) {
                    jQuery.removeData(elem, undefined, true)
                }
            }
        },
        trigger: function (event, data, elem) {
            var type = event.type || event,
                bubbling = arguments[3];
            if (!bubbling) {
                event = typeof event === "object" ? event[jQuery.expando] ? event : jQuery.extend(jQuery.Event(type), event) : jQuery.Event(type);
                if (type.indexOf("!") >= 0) {
                    event.type = type = type.slice(0, -1);
                    event.exclusive = true
                }
                if (!elem) {
                    event.stopPropagation();
                    if (jQuery.event.global[type]) {
                        jQuery.each(jQuery.cache, function () {
                            var internalKey = jQuery.expando,
                                internalCache = this[internalKey];
                            if (internalCache && internalCache.events && internalCache.events[type]) {
                                jQuery.event.trigger(event, data, internalCache.handle.elem)
                            }
                        })
                    }
                }
                if (!elem || elem.nodeType === 3 || elem.nodeType === 8) {
                    return undefined
                }
                event.result = undefined;
                event.target = elem;
                data = jQuery.makeArray(data);
                data.unshift(event)
            }
            event.currentTarget = elem;
            var handle = jQuery._data(elem, "handle");
            if (handle) {
                handle.apply(elem, data)
            }
            var parent = elem.parentNode || elem.ownerDocument;
            try {
                if (!(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()])) {
                    if (elem["on" + type] && elem["on" + type].apply(elem, data) === false) {
                        event.result = false;
                        event.preventDefault()
                    }
                }
            } catch (inlineError) {}
            if (!event.isPropagationStopped() && parent) {
                jQuery.event.trigger(event, data, parent, true)
            } else if (!event.isDefaultPrevented()) {
                var old, target = event.target,
                    targetType = type.replace(rnamespaces, ""),
                    isClick = jQuery.nodeName(target, "a") && targetType === "click",
                    special = jQuery.event.special[targetType] || {};
                if ((!special._default || special._default.call(elem, event) === false) && !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()])) {
                    try {
                        if (target[targetType]) {
                            old = target["on" + targetType];
                            if (old) {
                                target["on" + targetType] = null
                            }
                            jQuery.event.triggered = event.type;
                            target[targetType]()
                        }
                    } catch (triggerError) {}
                    if (old) {
                        target["on" + targetType] = old
                    }
                    jQuery.event.triggered = undefined
                }
            }
        },
        handle: function (event) {
            var all, handlers, namespaces, namespace_re, events, namespace_sort = [],
                args = jQuery.makeArray(arguments);
            event = args[0] = jQuery.event.fix(event || window.event);
            event.currentTarget = this;
            all = event.type.indexOf(".") < 0 && !event.exclusive;
            if (!all) {
                namespaces = event.type.split(".");
                event.type = namespaces.shift();
                namespace_sort = namespaces.slice(0).sort();
                namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)")
            }
            event.namespace = event.namespace || namespace_sort.join(".");
            events = jQuery._data(this, "events");
            handlers = (events || {})[event.type];
            if (events && handlers) {
                handlers = handlers.slice(0);
                for (var j = 0, l = handlers.length; j < l; j++) {
                    var handleObj = handlers[j];
                    if (all || namespace_re.test(handleObj.namespace)) {
                        event.handler = handleObj.handler;
                        event.data = handleObj.data;
                        event.handleObj = handleObj;
                        var ret = handleObj.handler.apply(this, args);
                        if (ret !== undefined) {
                            event.result = ret;
                            if (ret === false) {
                                event.preventDefault();
                                event.stopPropagation()
                            }
                        }
                        if (event.isImmediatePropagationStopped()) {
                            break
                        }
                    }
                }
            }
            return event.result
        },
        props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
        fix: function (event) {
            if (event[jQuery.expando]) {
                return event
            }
            var originalEvent = event;
            event = jQuery.Event(originalEvent);
            for (var i = this.props.length, prop; i;) {
                prop = this.props[--i];
                event[prop] = originalEvent[prop]
            }
            if (!event.target) {
                event.target = event.srcElement || document
            }
            if (event.target.nodeType === 3) {
                event.target = event.target.parentNode
            }
            if (!event.relatedTarget && event.fromElement) {
                event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement
            }
            if (event.pageX == null && event.clientX != null) {
                var doc = document.documentElement,
                    body = document.body;
                event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
                event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0)
            }
            if (event.which == null && (event.charCode != null || event.keyCode != null)) {
                event.which = event.charCode != null ? event.charCode : event.keyCode
            }
            if (!event.metaKey && event.ctrlKey) {
                event.metaKey = event.ctrlKey
            }
            if (!event.which && event.button !== undefined) {
                event.which = (event.button & 1 ? 1 : (event.button & 2 ? 3 : (event.button & 4 ? 2 : 0)))
            }
            return event
        },
        guid: 1E8,
        proxy: jQuery.proxy,
        special: {
            ready: {
                setup: jQuery.bindReady,
                teardown: jQuery.noop
            },
            live: {
                add: function (handleObj) {
                    jQuery.event.add(this, liveConvert(handleObj.origType, handleObj.selector), jQuery.extend({}, handleObj, {
                        handler: liveHandler,
                        guid: handleObj.handler.guid
                    }))
                },
                remove: function (handleObj) {
                    jQuery.event.remove(this, liveConvert(handleObj.origType, handleObj.selector), handleObj)
                }
            },
            beforeunload: {
                setup: function (data, namespaces, eventHandle) {
                    if (jQuery.isWindow(this)) {
                        this.onbeforeunload = eventHandle
                    }
                },
                teardown: function (namespaces, eventHandle) {
                    if (this.onbeforeunload === eventHandle) {
                        this.onbeforeunload = null
                    }
                }
            }
        }
    };
    jQuery.removeEvent = document.removeEventListener ?
    function (elem, type, handle) {
        if (elem.removeEventListener) {
            elem.removeEventListener(type, handle, false)
        }
    } : function (elem, type, handle) {
        if (elem.detachEvent) {
            elem.detachEvent("on" + type, handle)
        }
    };
    jQuery.Event = function (src) {
        if (!this.preventDefault) {
            return new jQuery.Event(src)
        }
        if (src && src.type) {
            this.originalEvent = src;
            this.type = src.type;
            this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse
        } else {
            this.type = src
        }
        this.timeStamp = jQuery.now();
        this[jQuery.expando] = true
    };

    function returnFalse() {
        return false
    }
    function returnTrue() {
        return true
    }
    jQuery.Event.prototype = {
        preventDefault: function () {
            this.isDefaultPrevented = returnTrue;
            var e = this.originalEvent;
            if (!e) {
                return
            }
            if (e.preventDefault) {
                e.preventDefault()
            } else {
                e.returnValue = false
            }
        },
        stopPropagation: function () {
            this.isPropagationStopped = returnTrue;
            var e = this.originalEvent;
            if (!e) {
                return
            }
            if (e.stopPropagation) {
                e.stopPropagation()
            }
            e.cancelBubble = true
        },
        stopImmediatePropagation: function () {
            this.isImmediatePropagationStopped = returnTrue;
            this.stopPropagation()
        },
        isDefaultPrevented: returnFalse,
        isPropagationStopped: returnFalse,
        isImmediatePropagationStopped: returnFalse
    };
    var withinElement = function (event) {
            var parent = event.relatedTarget;
            try {
                if (parent && parent !== document && !parent.parentNode) {
                    return
                }
                while (parent && parent !== this) {
                    parent = parent.parentNode
                }
                if (parent !== this) {
                    event.type = event.data;
                    jQuery.event.handle.apply(this, arguments)
                }
            } catch (e) {}
        },
        delegate = function (event) {
            event.type = event.data;
            jQuery.event.handle.apply(this, arguments)
        };
    jQuery.each({
        mouseenter: "mouseover",
        mouseleave: "mouseout"
    }, function (orig, fix) {
        jQuery.event.special[orig] = {
            setup: function (data) {
                jQuery.event.add(this, fix, data && data.selector ? delegate : withinElement, orig)
            },
            teardown: function (data) {
                jQuery.event.remove(this, fix, data && data.selector ? delegate : withinElement)
            }
        }
    });
    if (!jQuery.support.submitBubbles) {
        jQuery.event.special.submit = {
            setup: function (data, namespaces) {
                if (this.nodeName && this.nodeName.toLowerCase() !== "form") {
                    jQuery.event.add(this, "click.specialSubmit", function (e) {
                        var elem = e.target,
                            type = elem.type;
                        if ((type === "submit" || type === "image") && jQuery(elem).closest("form").length) {
                            trigger("submit", this, arguments)
                        }
                    });
                    jQuery.event.add(this, "keypress.specialSubmit", function (e) {
                        var elem = e.target,
                            type = elem.type;
                        if ((type === "text" || type === "password") && jQuery(elem).closest("form").length && e.keyCode === 13) {
                            trigger("submit", this, arguments)
                        }
                    })
                } else {
                    return false
                }
            },
            teardown: function (namespaces) {
                jQuery.event.remove(this, ".specialSubmit")
            }
        }
    }
    if (!jQuery.support.changeBubbles) {
        var changeFilters, getVal = function (elem) {
                var type = elem.type,
                    val = elem.value;
                if (type === "radio" || type === "checkbox") {
                    val = elem.checked
                } else if (type === "select-multiple") {
                    val = elem.selectedIndex > -1 ? jQuery.map(elem.options, function (elem) {
                        return elem.selected
                    }).join("-") : ""
                } else if (elem.nodeName.toLowerCase() === "select") {
                    val = elem.selectedIndex
                }
                return val
            },
            testChange = function testChange(e) {
                var elem = e.target,
                    data, val;
                if (!rformElems.test(elem.nodeName) || elem.readOnly) {
                    return
                }
                data = jQuery._data(elem, "_change_data");
                val = getVal(elem);
                if (e.type !== "focusout" || elem.type !== "radio") {
                    jQuery._data(elem, "_change_data", val)
                }
                if (data === undefined || val === data) {
                    return
                }
                if (data != null || val) {
                    e.type = "change";
                    e.liveFired = undefined;
                    jQuery.event.trigger(e, arguments[1], elem)
                }
            };
        jQuery.event.special.change = {
            filters: {
                focusout: testChange,
                beforedeactivate: testChange,
                click: function (e) {
                    var elem = e.target,
                        type = elem.type;
                    if (type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select") {
                        testChange.call(this, e)
                    }
                },
                keydown: function (e) {
                    var elem = e.target,
                        type = elem.type;
                    if ((e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || type === "select-multiple") {
                        testChange.call(this, e)
                    }
                },
                beforeactivate: function (e) {
                    var elem = e.target;
                    jQuery._data(elem, "_change_data", getVal(elem))
                }
            },
            setup: function (data, namespaces) {
                if (this.type === "file") {
                    return false
                }
                for (var type in changeFilters) {
                    jQuery.event.add(this, type + ".specialChange", changeFilters[type])
                }
                return rformElems.test(this.nodeName)
            },
            teardown: function (namespaces) {
                jQuery.event.remove(this, ".specialChange");
                return rformElems.test(this.nodeName)
            }
        };
        changeFilters = jQuery.event.special.change.filters;
        changeFilters.focus = changeFilters.beforeactivate
    }
    function trigger(type, elem, args) {
        var event = jQuery.extend({}, args[0]);
        event.type = type;
        event.originalEvent = {};
        event.liveFired = undefined;
        jQuery.event.handle.call(elem, event);
        if (event.isDefaultPrevented()) {
            args[0].preventDefault()
        }
    }
    if (document.addEventListener) {
        jQuery.each({
            focus: "focusin",
            blur: "focusout"
        }, function (orig, fix) {
            var attaches = 0;
            jQuery.event.special[fix] = {
                setup: function () {
                    if (attaches++ === 0) {
                        document.addEventListener(orig, handler, true)
                    }
                },
                teardown: function () {
                    if (--attaches === 0) {
                        document.removeEventListener(orig, handler, true)
                    }
                }
            };

            function handler(donor) {
                var e = jQuery.event.fix(donor);
                e.type = fix;
                e.originalEvent = {};
                jQuery.event.trigger(e, null, e.target);
                if (e.isDefaultPrevented()) {
                    donor.preventDefault()
                }
            }
        })
    }
    jQuery.each(["bind", "one"], function (i, name) {
        jQuery.fn[name] = function (type, data, fn) {
            if (typeof type === "object") {
                for (var key in type) {
                    this[name](key, data, type[key], fn)
                }
                return this
            }
            if (jQuery.isFunction(data) || data === false) {
                fn = data;
                data = undefined
            }
            var handler = name === "one" ? jQuery.proxy(fn, function (event) {
                jQuery(this).unbind(event, handler);
                return fn.apply(this, arguments)
            }) : fn;
            if (type === "unload" && name !== "one") {
                this.one(type, data, fn)
            } else {
                for (var i = 0, l = this.length; i < l; i++) {
                    jQuery.event.add(this[i], type, handler, data)
                }
            }
            return this
        }
    });
    jQuery.fn.extend({
        unbind: function (type, fn) {
            if (typeof type === "object" && !type.preventDefault) {
                for (var key in type) {
                    this.unbind(key, type[key])
                }
            } else {
                for (var i = 0, l = this.length; i < l; i++) {
                    jQuery.event.remove(this[i], type, fn)
                }
            }
            return this
        },
        delegate: function (selector, types, data, fn) {
            return this.live(types, data, fn, selector)
        },
        undelegate: function (selector, types, fn) {
            if (arguments.length === 0) {
                return this.unbind("live")
            } else {
                return this.die(types, null, fn, selector)
            }
        },
        trigger: function (type, data) {
            return this.each(function () {
                jQuery.event.trigger(type, data, this)
            })
        },
        triggerHandler: function (type, data) {
            if (this[0]) {
                var event = jQuery.Event(type);
                event.preventDefault();
                event.stopPropagation();
                jQuery.event.trigger(event, data, this[0]);
                return event.result
            }
        },
        toggle: function (fn) {
            var args = arguments,
                i = 1;
            while (i < args.length) {
                jQuery.proxy(fn, args[i++])
            }
            return this.click(jQuery.proxy(fn, function (event) {
                var lastToggle = (jQuery._data(this, "lastToggle" + fn.guid) || 0) % i;
                jQuery._data(this, "lastToggle" + fn.guid, lastToggle + 1);
                event.preventDefault();
                return args[lastToggle].apply(this, arguments) || false
            }))
        },
        hover: function (fnOver, fnOut) {
            return this.mouseenter(fnOver).mouseleave(fnOut || fnOver)
        }
    });
    var liveMap = {
        focus: "focusin",
        blur: "focusout",
        mouseenter: "mouseover",
        mouseleave: "mouseout"
    };
    jQuery.each(["live", "die"], function (i, name) {
        jQuery.fn[name] = function (types, data, fn, origSelector) {
            var type, i = 0,
                match, namespaces, preType, selector = origSelector || this.selector,
                context = origSelector ? this : jQuery(this.context);
            if (typeof types === "object" && !types.preventDefault) {
                for (var key in types) {
                    context[name](key, data, types[key], selector)
                }
                return this
            }
            if (jQuery.isFunction(data)) {
                fn = data;
                data = undefined
            }
            types = (types || "").split(" ");
            while ((type = types[i++]) != null) {
                match = rnamespaces.exec(type);
                namespaces = "";
                if (match) {
                    namespaces = match[0];
                    type = type.replace(rnamespaces, "")
                }
                if (type === "hover") {
                    types.push("mouseenter" + namespaces, "mouseleave" + namespaces);
                    continue
                }
                preType = type;
                if (type === "focus" || type === "blur") {
                    types.push(liveMap[type] + namespaces);
                    type = type + namespaces
                } else {
                    type = (liveMap[type] || type) + namespaces
                }
                if (name === "live") {
                    for (var j = 0, l = context.length; j < l; j++) {
                        jQuery.event.add(context[j], "live." + liveConvert(type, selector), {
                            data: data,
                            selector: selector,
                            handler: fn,
                            origType: type,
                            origHandler: fn,
                            preType: preType
                        })
                    }
                } else {
                    context.unbind("live." + liveConvert(type, selector), fn)
                }
            }
            return this
        }
    });

    function liveHandler(event) {
        var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, elems = [],
            selectors = [],
            events = jQuery._data(this, "events");
        if (event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click") {
            return
        }
        if (event.namespace) {
            namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)")
        }
        event.liveFired = this;
        var live = events.live.slice(0);
        for (j = 0; j < live.length; j++) {
            handleObj = live[j];
            if (handleObj.origType.replace(rnamespaces, "") === event.type) {
                selectors.push(handleObj.selector)
            } else {
                live.splice(j--, 1)
            }
        }
        match = jQuery(event.target).closest(selectors, event.currentTarget);
        for (i = 0, l = match.length; i < l; i++) {
            close = match[i];
            for (j = 0; j < live.length; j++) {
                handleObj = live[j];
                if (close.selector === handleObj.selector && (!namespace || namespace.test(handleObj.namespace)) && !close.elem.disabled) {
                    elem = close.elem;
                    related = null;
                    if (handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave") {
                        event.type = handleObj.preType;
                        related = jQuery(event.relatedTarget).closest(handleObj.selector)[0]
                    }
                    if (!related || related !== elem) {
                        elems.push({
                            elem: elem,
                            handleObj: handleObj,
                            level: close.level
                        })
                    }
                }
            }
        }
        for (i = 0, l = elems.length; i < l; i++) {
            match = elems[i];
            if (maxLevel && match.level > maxLevel) {
                break
            }
            event.currentTarget = match.elem;
            event.data = match.handleObj.data;
            event.handleObj = match.handleObj;
            ret = match.handleObj.origHandler.apply(match.elem, arguments);
            if (ret === false || event.isPropagationStopped()) {
                maxLevel = match.level;
                if (ret === false) {
                    stop = false
                }
                if (event.isImmediatePropagationStopped()) {
                    break
                }
            }
        }
        return stop
    }
    function liveConvert(type, selector) {
        return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&")
    }
    jQuery.each(("blur focus focusin focusout load resize scroll unload click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup error").split(" "), function (i, name) {
        jQuery.fn[name] = function (data, fn) {
            if (fn == null) {
                fn = data;
                data = null
            }
            return arguments.length > 0 ? this.bind(name, data, fn) : this.trigger(name)
        };
        if (jQuery.attrFn) {
            jQuery.attrFn[name] = true
        }
    });
    (function () {
        var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
            done = 0,
            toString = Object.prototype.toString,
            hasDuplicate = false,
            baseHasDuplicate = true,
            rBackslash = /\\/g,
            rNonWord = /\W/;
        [0, 0].sort(function () {
            baseHasDuplicate = false;
            return 0
        });
        var Sizzle = function (selector, context, results, seed) {
                results = results || [];
                context = context || document;
                var origContext = context;
                if (context.nodeType !== 1 && context.nodeType !== 9) {
                    return []
                }
                if (!selector || typeof selector !== "string") {
                    return results
                }
                var m, set, checkSet, extra, ret, cur, pop, i, prune = true,
                    contextXML = Sizzle.isXML(context),
                    parts = [],
                    soFar = selector;
                do {
                    chunker.exec("");
                    m = chunker.exec(soFar);
                    if (m) {
                        soFar = m[3];
                        parts.push(m[1]);
                        if (m[2]) {
                            extra = m[3];
                            break
                        }
                    }
                } while (m);
                if (parts.length > 1 && origPOS.exec(selector)) {
                    if (parts.length === 2 && Expr.relative[parts[0]]) {
                        set = posProcess(parts[0] + parts[1], context)
                    } else {
                        set = Expr.relative[parts[0]] ? [context] : Sizzle(parts.shift(), context);
                        while (parts.length) {
                            selector = parts.shift();
                            if (Expr.relative[selector]) {
                                selector += parts.shift()
                            }
                            set = posProcess(selector, set)
                        }
                    }
                } else {
                    if (!seed && parts.length > 1 && context.nodeType === 9 && !contextXML && Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1])) {
                        ret = Sizzle.find(parts.shift(), context, contextXML);
                        context = ret.expr ? Sizzle.filter(ret.expr, ret.set)[0] : ret.set[0]
                    }
                    if (context) {
                        ret = seed ? {
                            expr: parts.pop(),
                            set: makeArray(seed)
                        } : Sizzle.find(parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML);
                        set = ret.expr ? Sizzle.filter(ret.expr, ret.set) : ret.set;
                        if (parts.length > 0) {
                            checkSet = makeArray(set)
                        } else {
                            prune = false
                        }
                        while (parts.length) {
                            cur = parts.pop();
                            pop = cur;
                            if (!Expr.relative[cur]) {
                                cur = ""
                            } else {
                                pop = parts.pop()
                            }
                            if (pop == null) {
                                pop = context
                            }
                            Expr.relative[cur](checkSet, pop, contextXML)
                        }
                    } else {
                        checkSet = parts = []
                    }
                }
                if (!checkSet) {
                    checkSet = set
                }
                if (!checkSet) {
                    Sizzle.error(cur || selector)
                }
                if (toString.call(checkSet) === "[object Array]") {
                    if (!prune) {
                        results.push.apply(results, checkSet)
                    } else if (context && context.nodeType === 1) {
                        for (i = 0; checkSet[i] != null; i++) {
                            if (checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i]))) {
                                results.push(set[i])
                            }
                        }
                    } else {
                        for (i = 0; checkSet[i] != null; i++) {
                            if (checkSet[i] && checkSet[i].nodeType === 1) {
                                results.push(set[i])
                            }
                        }
                    }
                } else {
                    makeArray(checkSet, results)
                }
                if (extra) {
                    Sizzle(extra, origContext, results, seed);
                    Sizzle.uniqueSort(results)
                }
                return results
            };
        Sizzle.uniqueSort = function (results) {
            if (sortOrder) {
                hasDuplicate = baseHasDuplicate;
                results.sort(sortOrder);
                if (hasDuplicate) {
                    for (var i = 1; i < results.length; i++) {
                        if (results[i] === results[i - 1]) {
                            results.splice(i--, 1)
                        }
                    }
                }
            }
            return results
        };
        Sizzle.matches = function (expr, set) {
            return Sizzle(expr, null, null, set)
        };
        Sizzle.matchesSelector = function (node, expr) {
            return Sizzle(expr, null, null, [node]).length > 0
        };
        Sizzle.find = function (expr, context, isXML) {
            var set;
            if (!expr) {
                return []
            }
            for (var i = 0, l = Expr.order.length; i < l; i++) {
                var match, type = Expr.order[i];
                if ((match = Expr.leftMatch[type].exec(expr))) {
                    var left = match[1];
                    match.splice(1, 1);
                    if (left.substr(left.length - 1) !== "\\") {
                        match[1] = (match[1] || "").replace(rBackslash, "");
                        set = Expr.find[type](match, context, isXML);
                        if (set != null) {
                            expr = expr.replace(Expr.match[type], "");
                            break
                        }
                    }
                }
            }
            if (!set) {
                set = typeof context.getElementsByTagName !== "undefined" ? context.getElementsByTagName("*") : []
            }
            return {
                set: set,
                expr: expr
            }
        };
        Sizzle.filter = function (expr, set, inplace, not) {
            var match, anyFound, old = expr,
                result = [],
                curLoop = set,
                isXMLFilter = set && set[0] && Sizzle.isXML(set[0]);
            while (expr && set.length) {
                for (var type in Expr.filter) {
                    if ((match = Expr.leftMatch[type].exec(expr)) != null && match[2]) {
                        var found, item, filter = Expr.filter[type],
                            left = match[1];
                        anyFound = false;
                        match.splice(1, 1);
                        if (left.substr(left.length - 1) === "\\") {
                            continue
                        }
                        if (curLoop === result) {
                            result = []
                        }
                        if (Expr.preFilter[type]) {
                            match = Expr.preFilter[type](match, curLoop, inplace, result, not, isXMLFilter);
                            if (!match) {
                                anyFound = found = true
                            } else if (match === true) {
                                continue
                            }
                        }
                        if (match) {
                            for (var i = 0;
                            (item = curLoop[i]) != null; i++) {
                                if (item) {
                                    found = filter(item, match, i, curLoop);
                                    var pass = not ^ !! found;
                                    if (inplace && found != null) {
                                        if (pass) {
                                            anyFound = true
                                        } else {
                                            curLoop[i] = false
                                        }
                                    } else if (pass) {
                                        result.push(item);
                                        anyFound = true
                                    }
                                }
                            }
                        }
                        if (found !== undefined) {
                            if (!inplace) {
                                curLoop = result
                            }
                            expr = expr.replace(Expr.match[type], "");
                            if (!anyFound) {
                                return []
                            }
                            break
                        }
                    }
                }
                if (expr === old) {
                    if (anyFound == null) {
                        Sizzle.error(expr)
                    } else {
                        break
                    }
                }
                old = expr
            }
            return curLoop
        };
        Sizzle.error = function (msg) {
            throw "Syntax error, unrecognized expression: " + msg
        };
        var Expr = Sizzle.selectors = {
            order: ["ID", "NAME", "TAG"],
            match: {
                ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
                CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
                NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
                ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
                TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
                CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
                POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
                PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
            },
            leftMatch: {},
            attrMap: {
                "class": "className",
                "for": "htmlFor"
            },
            attrHandle: {
                href: function (elem) {
                    return elem.getAttribute("href")
                },
                type: function (elem) {
                    return elem.getAttribute("type")
                }
            },
            relative: {
                "+": function (checkSet, part) {
                    var isPartStr = typeof part === "string",
                        isTag = isPartStr && !rNonWord.test(part),
                        isPartStrNotTag = isPartStr && !isTag;
                    if (isTag) {
                        part = part.toLowerCase()
                    }
                    for (var i = 0, l = checkSet.length, elem; i < l; i++) {
                        if ((elem = checkSet[i])) {
                            while ((elem = elem.previousSibling) && elem.nodeType !== 1) {}
                            checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? elem || false : elem === part
                        }
                    }
                    if (isPartStrNotTag) {
                        Sizzle.filter(part, checkSet, true)
                    }
                },
                ">": function (checkSet, part) {
                    var elem, isPartStr = typeof part === "string",
                        i = 0,
                        l = checkSet.length;
                    if (isPartStr && !rNonWord.test(part)) {
                        part = part.toLowerCase();
                        for (; i < l; i++) {
                            elem = checkSet[i];
                            if (elem) {
                                var parent = elem.parentNode;
                                checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false
                            }
                        }
                    } else {
                        for (; i < l; i++) {
                            elem = checkSet[i];
                            if (elem) {
                                checkSet[i] = isPartStr ? elem.parentNode : elem.parentNode === part
                            }
                        }
                        if (isPartStr) {
                            Sizzle.filter(part, checkSet, true)
                        }
                    }
                },
                "": function (checkSet, part, isXML) {
                    var nodeCheck, doneName = done++,
                        checkFn = dirCheck;
                    if (typeof part === "string" && !rNonWord.test(part)) {
                        part = part.toLowerCase();
                        nodeCheck = part;
                        checkFn = dirNodeCheck
                    }
                    checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML)
                },
                "~": function (checkSet, part, isXML) {
                    var nodeCheck, doneName = done++,
                        checkFn = dirCheck;
                    if (typeof part === "string" && !rNonWord.test(part)) {
                        part = part.toLowerCase();
                        nodeCheck = part;
                        checkFn = dirNodeCheck
                    }
                    checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML)
                }
            },
            find: {
                ID: function (match, context, isXML) {
                    if (typeof context.getElementById !== "undefined" && !isXML) {
                        var m = context.getElementById(match[1]);
                        return m && m.parentNode ? [m] : []
                    }
                },
                NAME: function (match, context) {
                    if (typeof context.getElementsByName !== "undefined") {
                        var ret = [],
                            results = context.getElementsByName(match[1]);
                        for (var i = 0, l = results.length; i < l; i++) {
                            if (results[i].getAttribute("name") === match[1]) {
                                ret.push(results[i])
                            }
                        }
                        return ret.length === 0 ? null : ret
                    }
                },
                TAG: function (match, context) {
                    if (typeof context.getElementsByTagName !== "undefined") {
                        return context.getElementsByTagName(match[1])
                    }
                }
            },
            preFilter: {
                CLASS: function (match, curLoop, inplace, result, not, isXML) {
                    match = " " + match[1].replace(rBackslash, "") + " ";
                    if (isXML) {
                        return match
                    }
                    for (var i = 0, elem;
                    (elem = curLoop[i]) != null; i++) {
                        if (elem) {
                            if (not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0)) {
                                if (!inplace) {
                                    result.push(elem)
                                }
                            } else if (inplace) {
                                curLoop[i] = false
                            }
                        }
                    }
                    return false
                },
                ID: function (match) {
                    return match[1].replace(rBackslash, "")
                },
                TAG: function (match, curLoop) {
                    return match[1].replace(rBackslash, "").toLowerCase()
                },
                CHILD: function (match) {
                    if (match[1] === "nth") {
                        if (!match[2]) {
                            Sizzle.error(match[0])
                        }
                        match[2] = match[2].replace(/^\+|\s*/g, '');
                        var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || !/\D/.test(match[2]) && "0n+" + match[2] || match[2]);
                        match[2] = (test[1] + (test[2] || 1)) - 0;
                        match[3] = test[3] - 0
                    } else if (match[2]) {
                        Sizzle.error(match[0])
                    }
                    match[0] = done++;
                    return match
                },
                ATTR: function (match, curLoop, inplace, result, not, isXML) {
                    var name = match[1] = match[1].replace(rBackslash, "");
                    if (!isXML && Expr.attrMap[name]) {
                        match[1] = Expr.attrMap[name]
                    }
                    match[4] = (match[4] || match[5] || "").replace(rBackslash, "");
                    if (match[2] === "~=") {
                        match[4] = " " + match[4] + " "
                    }
                    return match
                },
                PSEUDO: function (match, curLoop, inplace, result, not) {
                    if (match[1] === "not") {
                        if ((chunker.exec(match[3]) || "").length > 1 || /^\w/.test(match[3])) {
                            match[3] = Sizzle(match[3], null, null, curLoop)
                        } else {
                            var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
                            if (!inplace) {
                                result.push.apply(result, ret)
                            }
                            return false
                        }
                    } else if (Expr.match.POS.test(match[0]) || Expr.match.CHILD.test(match[0])) {
                        return true
                    }
                    return match
                },
                POS: function (match) {
                    match.unshift(true);
                    return match
                }
            },
            filters: {
                enabled: function (elem) {
                    return elem.disabled === false && elem.type !== "hidden"
                },
                disabled: function (elem) {
                    return elem.disabled === true
                },
                checked: function (elem) {
                    return elem.checked === true
                },
                selected: function (elem) {
                    if (elem.parentNode) {
                        elem.parentNode.selectedIndex
                    }
                    return elem.selected === true
                },
                parent: function (elem) {
                    return !!elem.firstChild
                },
                empty: function (elem) {
                    return !elem.firstChild
                },
                has: function (elem, i, match) {
                    return !!Sizzle(match[3], elem).length
                },
                header: function (elem) {
                    return (/h\d/i).test(elem.nodeName)
                },
                text: function (elem) {
                    var attr = elem.getAttribute("type"),
                        type = elem.type;
                    return "text" === type && (attr === type || attr === null)
                },
                radio: function (elem) {
                    return "radio" === elem.type
                },
                checkbox: function (elem) {
                    return "checkbox" === elem.type
                },
                file: function (elem) {
                    return "file" === elem.type
                },
                password: function (elem) {
                    return "password" === elem.type
                },
                submit: function (elem) {
                    return "submit" === elem.type
                },
                image: function (elem) {
                    return "image" === elem.type
                },
                reset: function (elem) {
                    return "reset" === elem.type
                },
                button: function (elem) {
                    return "button" === elem.type || elem.nodeName.toLowerCase() === "button"
                },
                input: function (elem) {
                    return (/input|select|textarea|button/i).test(elem.nodeName)
                }
            },
            setFilters: {
                first: function (elem, i) {
                    return i === 0
                },
                last: function (elem, i, match, array) {
                    return i === array.length - 1
                },
                even: function (elem, i) {
                    return i % 2 === 0
                },
                odd: function (elem, i) {
                    return i % 2 === 1
                },
                lt: function (elem, i, match) {
                    return i < match[3] - 0
                },
                gt: function (elem, i, match) {
                    return i > match[3] - 0
                },
                nth: function (elem, i, match) {
                    return match[3] - 0 === i
                },
                eq: function (elem, i, match) {
                    return match[3] - 0 === i
                }
            },
            filter: {
                PSEUDO: function (elem, match, i, array) {
                    var name = match[1],
                        filter = Expr.filters[name];
                    if (filter) {
                        return filter(elem, i, match, array)
                    } else if (name === "contains") {
                        return (elem.textContent || elem.innerText || Sizzle.getText([elem]) || "").indexOf(match[3]) >= 0
                    } else if (name === "not") {
                        var not = match[3];
                        for (var j = 0, l = not.length; j < l; j++) {
                            if (not[j] === elem) {
                                return false
                            }
                        }
                        return true
                    } else {
                        Sizzle.error(name)
                    }
                },
                CHILD: function (elem, match) {
                    var type = match[1],
                        node = elem;
                    switch (type) {
                    case "only":
                    case "first":
                        while ((node = node.previousSibling)) {
                            if (node.nodeType === 1) {
                                return false
                            }
                        }
                        if (type === "first") {
                            return true
                        }
                        node = elem;
                    case "last":
                        while ((node = node.nextSibling)) {
                            if (node.nodeType === 1) {
                                return false
                            }
                        }
                        return true;
                    case "nth":
                        var first = match[2],
                            last = match[3];
                        if (first === 1 && last === 0) {
                            return true
                        }
                        var doneName = match[0],
                            parent = elem.parentNode;
                        if (parent && (parent.sizcache !== doneName || !elem.nodeIndex)) {
                            var count = 0;
                            for (node = parent.firstChild; node; node = node.nextSibling) {
                                if (node.nodeType === 1) {
                                    node.nodeIndex = ++count
                                }
                            }
                            parent.sizcache = doneName
                        }
                        var diff = elem.nodeIndex - last;
                        if (first === 0) {
                            return diff === 0
                        } else {
                            return (diff % first === 0 && diff / first >= 0)
                        }
                    }
                },
                ID: function (elem, match) {
                    return elem.nodeType === 1 && elem.getAttribute("id") === match
                },
                TAG: function (elem, match) {
                    return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match
                },
                CLASS: function (elem, match) {
                    return (" " + (elem.className || elem.getAttribute("class")) + " ").indexOf(match) > -1
                },
                ATTR: function (elem, match) {
                    var name = match[1],
                        result = Expr.attrHandle[name] ? Expr.attrHandle[name](elem) : elem[name] != null ? elem[name] : elem.getAttribute(name),
                        value = result + "",
                        type = match[2],
                        check = match[4];
                    return result == null ? type === "!=" : type === "=" ? value === check : type === "*=" ? value.indexOf(check) >= 0 : type === "~=" ? (" " + value + " ").indexOf(check) >= 0 : !check ? value && result !== false : type === "!=" ? value !== check : type === "^=" ? value.indexOf(check) === 0 : type === "$=" ? value.substr(value.length - check.length) === check : type === "|=" ? value === check || value.substr(0, check.length + 1) === check + "-" : false
                },
                POS: function (elem, match, i, array) {
                    var name = match[2],
                        filter = Expr.setFilters[name];
                    if (filter) {
                        return filter(elem, i, match, array)
                    }
                }
            }
        };
        var origPOS = Expr.match.POS,
            fescape = function (all, num) {
                return "\\" + (num - 0 + 1)
            };
        for (var type in Expr.match) {
            Expr.match[type] = new RegExp(Expr.match[type].source + (/(?![^\[]*\])(?![^\(]*\))/.source));
            Expr.leftMatch[type] = new RegExp(/(^(?:.|\r|\n)*?)/.source + Expr.match[type].source.replace(/\\(\d+)/g, fescape))
        }
        var makeArray = function (array, results) {
                array = Array.prototype.slice.call(array, 0);
                if (results) {
                    results.push.apply(results, array);
                    return results
                }
                return array
            };
        try {
            Array.prototype.slice.call(document.documentElement.childNodes, 0)[0].nodeType
        } catch (e) {
            makeArray = function (array, results) {
                var i = 0,
                    ret = results || [];
                if (toString.call(array) === "[object Array]") {
                    Array.prototype.push.apply(ret, array)
                } else {
                    if (typeof array.length === "number") {
                        for (var l = array.length; i < l; i++) {
                            ret.push(array[i])
                        }
                    } else {
                        for (; array[i]; i++) {
                            ret.push(array[i])
                        }
                    }
                }
                return ret
            }
        }
        var sortOrder, siblingCheck;
        if (document.documentElement.compareDocumentPosition) {
            sortOrder = function (a, b) {
                if (a === b) {
                    hasDuplicate = true;
                    return 0
                }
                if (!a.compareDocumentPosition || !b.compareDocumentPosition) {
                    return a.compareDocumentPosition ? -1 : 1
                }
                return a.compareDocumentPosition(b) & 4 ? -1 : 1
            }
        } else {
            sortOrder = function (a, b) {
                var al, bl, ap = [],
                    bp = [],
                    aup = a.parentNode,
                    bup = b.parentNode,
                    cur = aup;
                if (a === b) {
                    hasDuplicate = true;
                    return 0
                } else if (aup === bup) {
                    return siblingCheck(a, b)
                } else if (!aup) {
                    return -1
                } else if (!bup) {
                    return 1
                }
                while (cur) {
                    ap.unshift(cur);
                    cur = cur.parentNode
                }
                cur = bup;
                while (cur) {
                    bp.unshift(cur);
                    cur = cur.parentNode
                }
                al = ap.length;
                bl = bp.length;
                for (var i = 0; i < al && i < bl; i++) {
                    if (ap[i] !== bp[i]) {
                        return siblingCheck(ap[i], bp[i])
                    }
                }
                return i === al ? siblingCheck(a, bp[i], -1) : siblingCheck(ap[i], b, 1)
            };
            siblingCheck = function (a, b, ret) {
                if (a === b) {
                    return ret
                }
                var cur = a.nextSibling;
                while (cur) {
                    if (cur === b) {
                        return -1
                    }
                    cur = cur.nextSibling
                }
                return 1
            }
        }
        Sizzle.getText = function (elems) {
            var ret = "",
                elem;
            for (var i = 0; elems[i]; i++) {
                elem = elems[i];
                if (elem.nodeType === 3 || elem.nodeType === 4) {
                    ret += elem.nodeValue
                } else if (elem.nodeType !== 8) {
                    ret += Sizzle.getText(elem.childNodes)
                }
            }
            return ret
        };
        (function () {
            var form = document.createElement("div"),
                id = "script" + (new Date()).getTime(),
                root = document.documentElement;
            form.innerHTML = "<a name='" + id + "'/>";
            root.insertBefore(form, root.firstChild);
            if (document.getElementById(id)) {
                Expr.find.ID = function (match, context, isXML) {
                    if (typeof context.getElementById !== "undefined" && !isXML) {
                        var m = context.getElementById(match[1]);
                        return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []
                    }
                };
                Expr.filter.ID = function (elem, match) {
                    var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
                    return elem.nodeType === 1 && node && node.nodeValue === match
                }
            }
            root.removeChild(form);
            root = form = null
        })();
        (function () {
            var div = document.createElement("div");
            div.appendChild(document.createComment(""));
            if (div.getElementsByTagName("*").length > 0) {
                Expr.find.TAG = function (match, context) {
                    var results = context.getElementsByTagName(match[1]);
                    if (match[1] === "*") {
                        var tmp = [];
                        for (var i = 0; results[i]; i++) {
                            if (results[i].nodeType === 1) {
                                tmp.push(results[i])
                            }
                        }
                        results = tmp
                    }
                    return results
                }
            }
            div.innerHTML = "<a href='#'></a>";
            if (div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && div.firstChild.getAttribute("href") !== "#") {
                Expr.attrHandle.href = function (elem) {
                    return elem.getAttribute("href", 2)
                }
            }
            div = null
        })();
        if (document.querySelectorAll) {
            (function () {
                var oldSizzle = Sizzle,
                    div = document.createElement("div"),
                    id = "__sizzle__";
                div.innerHTML = "<p class='TEST'></p>";
                if (div.querySelectorAll && div.querySelectorAll(".TEST").length === 0) {
                    return
                }
                Sizzle = function (query, context, extra, seed) {
                    context = context || document;
                    if (!seed && !Sizzle.isXML(context)) {
                        var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(query);
                        if (match && (context.nodeType === 1 || context.nodeType === 9)) {
                            if (match[1]) {
                                return makeArray(context.getElementsByTagName(query), extra)
                            } else if (match[2] && Expr.find.CLASS && context.getElementsByClassName) {
                                return makeArray(context.getElementsByClassName(match[2]), extra)
                            }
                        }
                        if (context.nodeType === 9) {
                            if (query === "body" && context.body) {
                                return makeArray([context.body], extra)
                            } else if (match && match[3]) {
                                var elem = context.getElementById(match[3]);
                                if (elem && elem.parentNode) {
                                    if (elem.id === match[3]) {
                                        return makeArray([elem], extra)
                                    }
                                } else {
                                    return makeArray([], extra)
                                }
                            }
                            try {
                                return makeArray(context.querySelectorAll(query), extra)
                            } catch (qsaError) {}
                        } else if (context.nodeType === 1 && context.nodeName.toLowerCase() !== "object") {
                            var oldContext = context,
                                old = context.getAttribute("id"),
                                nid = old || id,
                                hasParent = context.parentNode,
                                relativeHierarchySelector = /^\s*[+~]/.test(query);
                            if (!old) {
                                context.setAttribute("id", nid)
                            } else {
                                nid = nid.replace(/'/g, "\\$&")
                            }
                            if (relativeHierarchySelector && hasParent) {
                                context = context.parentNode
                            }
                            try {
                                if (!relativeHierarchySelector || hasParent) {
                                    return makeArray(context.querySelectorAll("[id='" + nid + "'] " + query), extra)
                                }
                            } catch (pseudoError) {} finally {
                                if (!old) {
                                    oldContext.removeAttribute("id")
                                }
                            }
                        }
                    }
                    return oldSizzle(query, context, extra, seed)
                };
                for (var prop in oldSizzle) {
                    Sizzle[prop] = oldSizzle[prop]
                }
                div = null
            })()
        }(function () {
            var html = document.documentElement,
                matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
            if (matches) {
                var disconnectedMatch = !matches.call(document.createElement("div"), "div"),
                    pseudoWorks = false;
                try {
                    matches.call(document.documentElement, "[test!='']:sizzle")
                } catch (pseudoError) {
                    pseudoWorks = true
                }
                Sizzle.matchesSelector = function (node, expr) {
                    expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
                    if (!Sizzle.isXML(node)) {
                        try {
                            if (pseudoWorks || !Expr.match.PSEUDO.test(expr) && !/!=/.test(expr)) {
                                var ret = matches.call(node, expr);
                                if (ret || !disconnectedMatch || node.document && node.document.nodeType !== 11) {
                                    return ret
                                }
                            }
                        } catch (e) {}
                    }
                    return Sizzle(expr, null, null, [node]).length > 0
                }
            }
        })();
        (function () {
            var div = document.createElement("div");
            div.innerHTML = "<div class='test e'></div><div class='test'></div>";
            if (!div.getElementsByClassName || div.getElementsByClassName("e").length === 0) {
                return
            }
            div.lastChild.className = "e";
            if (div.getElementsByClassName("e").length === 1) {
                return
            }
            Expr.order.splice(1, 0, "CLASS");
            Expr.find.CLASS = function (match, context, isXML) {
                if (typeof context.getElementsByClassName !== "undefined" && !isXML) {
                    return context.getElementsByClassName(match[1])
                }
            };
            div = null
        })();

        function dirNodeCheck(dir, cur, doneName, checkSet, nodeCheck, isXML) {
            for (var i = 0, l = checkSet.length; i < l; i++) {
                var elem = checkSet[i];
                if (elem) {
                    var match = false;
                    elem = elem[dir];
                    while (elem) {
                        if (elem.sizcache === doneName) {
                            match = checkSet[elem.sizset];
                            break
                        }
                        if (elem.nodeType === 1 && !isXML) {
                            elem.sizcache = doneName;
                            elem.sizset = i
                        }
                        if (elem.nodeName.toLowerCase() === cur) {
                            match = elem;
                            break
                        }
                        elem = elem[dir]
                    }
                    checkSet[i] = match
                }
            }
        }
        function dirCheck(dir, cur, doneName, checkSet, nodeCheck, isXML) {
            for (var i = 0, l = checkSet.length; i < l; i++) {
                var elem = checkSet[i];
                if (elem) {
                    var match = false;
                    elem = elem[dir];
                    while (elem) {
                        if (elem.sizcache === doneName) {
                            match = checkSet[elem.sizset];
                            break
                        }
                        if (elem.nodeType === 1) {
                            if (!isXML) {
                                elem.sizcache = doneName;
                                elem.sizset = i
                            }
                            if (typeof cur !== "string") {
                                if (elem === cur) {
                                    match = true;
                                    break
                                }
                            } else if (Sizzle.filter(cur, [elem]).length > 0) {
                                match = elem;
                                break
                            }
                        }
                        elem = elem[dir]
                    }
                    checkSet[i] = match
                }
            }
        }
        if (document.documentElement.contains) {
            Sizzle.contains = function (a, b) {
                return a !== b && (a.contains ? a.contains(b) : true)
            }
        } else if (document.documentElement.compareDocumentPosition) {
            Sizzle.contains = function (a, b) {
                return !!(a.compareDocumentPosition(b) & 16)
            }
        } else {
            Sizzle.contains = function () {
                return false
            }
        }
        Sizzle.isXML = function (elem) {
            var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
            return documentElement ? documentElement.nodeName !== "HTML" : false
        };
        var posProcess = function (selector, context) {
                var match, tmpSet = [],
                    later = "",
                    root = context.nodeType ? [context] : context;
                while ((match = Expr.match.PSEUDO.exec(selector))) {
                    later += match[0];
                    selector = selector.replace(Expr.match.PSEUDO, "")
                }
                selector = Expr.relative[selector] ? selector + "*" : selector;
                for (var i = 0, l = root.length; i < l; i++) {
                    Sizzle(selector, root[i], tmpSet)
                }
                return Sizzle.filter(later, tmpSet)
            };
        jQuery.find = Sizzle;
        jQuery.expr = Sizzle.selectors;
        jQuery.expr[":"] = jQuery.expr.filters;
        jQuery.unique = Sizzle.uniqueSort;
        jQuery.text = Sizzle.getText;
        jQuery.isXMLDoc = Sizzle.isXML;
        jQuery.contains = Sizzle.contains
    })();
    var runtil = /Until$/,
        rparentsprev = /^(?:parents|prevUntil|prevAll)/,
        rmultiselector = /,/,
        isSimple = /^.[^:#\[\.,]*$/,
        slice = Array.prototype.slice,
        POS = jQuery.expr.match.POS,
        guaranteedUnique = {
            children: true,
            contents: true,
            next: true,
            prev: true
        };
    jQuery.fn.extend({
        find: function (selector) {
            var ret = this.pushStack("", "find", selector),
                length = 0;
            for (var i = 0, l = this.length; i < l; i++) {
                length = ret.length;
                jQuery.find(selector, this[i], ret);
                if (i > 0) {
                    for (var n = length; n < ret.length; n++) {
                        for (var r = 0; r < length; r++) {
                            if (ret[r] === ret[n]) {
                                ret.splice(n--, 1);
                                break
                            }
                        }
                    }
                }
            }
            return ret
        },
        has: function (target) {
            var targets = jQuery(target);
            return this.filter(function () {
                for (var i = 0, l = targets.length; i < l; i++) {
                    if (jQuery.contains(this, targets[i])) {
                        return true
                    }
                }
            })
        },
        not: function (selector) {
            return this.pushStack(winnow(this, selector, false), "not", selector)
        },
        filter: function (selector) {
            return this.pushStack(winnow(this, selector, true), "filter", selector)
        },
        is: function (selector) {
            return !!selector && jQuery.filter(selector, this).length > 0
        },
        closest: function (selectors, context) {
            var ret = [],
                i, l, cur = this[0];
            if (jQuery.isArray(selectors)) {
                var match, selector, matches = {},
                    level = 1;
                if (cur && selectors.length) {
                    for (i = 0, l = selectors.length; i < l; i++) {
                        selector = selectors[i];
                        if (!matches[selector]) {
                            matches[selector] = jQuery.expr.match.POS.test(selector) ? jQuery(selector, context || this.context) : selector
                        }
                    }
                    while (cur && cur.ownerDocument && cur !== context) {
                        for (selector in matches) {
                            match = matches[selector];
                            if (match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match)) {
                                ret.push({
                                    selector: selector,
                                    elem: cur,
                                    level: level
                                })
                            }
                        }
                        cur = cur.parentNode;
                        level++
                    }
                }
                return ret
            }
            var pos = POS.test(selectors) ? jQuery(selectors, context || this.context) : null;
            for (i = 0, l = this.length; i < l; i++) {
                cur = this[i];
                while (cur) {
                    if (pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors)) {
                        ret.push(cur);
                        break
                    } else {
                        cur = cur.parentNode;
                        if (!cur || !cur.ownerDocument || cur === context) {
                            break
                        }
                    }
                }
            }
            ret = ret.length > 1 ? jQuery.unique(ret) : ret;
            return this.pushStack(ret, "closest", selectors)
        },
        index: function (elem) {
            if (!elem || typeof elem === "string") {
                return jQuery.inArray(this[0], elem ? jQuery(elem) : this.parent().children())
            }
            return jQuery.inArray(elem.jquery ? elem[0] : elem, this)
        },
        add: function (selector, context) {
            var set = typeof selector === "string" ? jQuery(selector, context) : jQuery.makeArray(selector),
                all = jQuery.merge(this.get(), set);
            return this.pushStack(isDisconnected(set[0]) || isDisconnected(all[0]) ? all : jQuery.unique(all))
        },
        andSelf: function () {
            return this.add(this.prevObject)
        }
    });

    function isDisconnected(node) {
        return !node || !node.parentNode || node.parentNode.nodeType === 11
    }
    jQuery.each({
        parent: function (elem) {
            var parent = elem.parentNode;
            return parent && parent.nodeType !== 11 ? parent : null
        },
        parents: function (elem) {
            return jQuery.dir(elem, "parentNode")
        },
        parentsUntil: function (elem, i, until) {
            return jQuery.dir(elem, "parentNode", until)
        },
        next: function (elem) {
            return jQuery.nth(elem, 2, "nextSibling")
        },
        prev: function (elem) {
            return jQuery.nth(elem, 2, "previousSibling")
        },
        nextAll: function (elem) {
            return jQuery.dir(elem, "nextSibling")
        },
        prevAll: function (elem) {
            return jQuery.dir(elem, "previousSibling")
        },
        nextUntil: function (elem, i, until) {
            return jQuery.dir(elem, "nextSibling", until)
        },
        prevUntil: function (elem, i, until) {
            return jQuery.dir(elem, "previousSibling", until)
        },
        siblings: function (elem) {
            return jQuery.sibling(elem.parentNode.firstChild, elem)
        },
        children: function (elem) {
            return jQuery.sibling(elem.firstChild)
        },
        contents: function (elem) {
            return jQuery.nodeName(elem, "iframe") ? elem.contentDocument || elem.contentWindow.document : jQuery.makeArray(elem.childNodes)
        }
    }, function (name, fn) {
        jQuery.fn[name] = function (until, selector) {
            var ret = jQuery.map(this, fn, until),
                args = slice.call(arguments);
            if (!runtil.test(name)) {
                selector = until
            }
            if (selector && typeof selector === "string") {
                ret = jQuery.filter(selector, ret)
            }
            ret = this.length > 1 && !guaranteedUnique[name] ? jQuery.unique(ret) : ret;
            if ((this.length > 1 || rmultiselector.test(selector)) && rparentsprev.test(name)) {
                ret = ret.reverse()
            }
            return this.pushStack(ret, name, args.join(","))
        }
    });
    jQuery.extend({
        filter: function (expr, elems, not) {
            if (not) {
                expr = ":not(" + expr + ")"
            }
            return elems.length === 1 ? jQuery.find.matchesSelector(elems[0], expr) ? [elems[0]] : [] : jQuery.find.matches(expr, elems)
        },
        dir: function (elem, dir, until) {
            var matched = [],
                cur = elem[dir];
            while (cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery(cur).is(until))) {
                if (cur.nodeType === 1) {
                    matched.push(cur)
                }
                cur = cur[dir]
            }
            return matched
        },
        nth: function (cur, result, dir, elem) {
            result = result || 1;
            var num = 0;
            for (; cur; cur = cur[dir]) {
                if (cur.nodeType === 1 && ++num === result) {
                    break
                }
            }
            return cur
        },
        sibling: function (n, elem) {
            var r = [];
            for (; n; n = n.nextSibling) {
                if (n.nodeType === 1 && n !== elem) {
                    r.push(n)
                }
            }
            return r
        }
    });

    function winnow(elements, qualifier, keep) {
        if (jQuery.isFunction(qualifier)) {
            return jQuery.grep(elements, function (elem, i) {
                var retVal = !! qualifier.call(elem, i, elem);
                return retVal === keep
            })
        } else if (qualifier.nodeType) {
            return jQuery.grep(elements, function (elem, i) {
                return (elem === qualifier) === keep
            })
        } else if (typeof qualifier === "string") {
            var filtered = jQuery.grep(elements, function (elem) {
                return elem.nodeType === 1
            });
            if (isSimple.test(qualifier)) {
                return jQuery.filter(qualifier, filtered, !keep)
            } else {
                qualifier = jQuery.filter(qualifier, filtered)
            }
        }
        return jQuery.grep(elements, function (elem, i) {
            return (jQuery.inArray(elem, qualifier) >= 0) === keep
        })
    }
    var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
        rleadingWhitespace = /^\s+/,
        rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
        rtagName = /<([\w:]+)/,
        rtbody = /<tbody/i,
        rhtml = /<|&#?\w+;/,
        rnocache = /<(?:script|object|embed|option|style)/i,
        rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
        wrapMap = {
            option: [1, "<select multiple='multiple'>", "</select>"],
            legend: [1, "<fieldset>", "</fieldset>"],
            thead: [1, "<table>", "</table>"],
            tr: [2, "<table><tbody>", "</tbody></table>"],
            td: [3, "<table><tbody><tr>", "</tr></tbody></table>"],
            col: [2, "<table><tbody></tbody><colgroup>", "</colgroup></table>"],
            area: [1, "<map>", "</map>"],
            _default: [0, "", ""]
        };
    wrapMap.optgroup = wrapMap.option;
    wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
    wrapMap.th = wrapMap.td;
    if (!jQuery.support.htmlSerialize) {
        wrapMap._default = [1, "div<div>", "</div>"]
    }
    jQuery.fn.extend({
        text: function (text) {
            if (jQuery.isFunction(text)) {
                return this.each(function (i) {
                    var self = jQuery(this);
                    self.text(text.call(this, i, self.text()))
                })
            }
            if (typeof text !== "object" && text !== undefined) {
                return this.empty().append((this[0] && this[0].ownerDocument || document).createTextNode(text))
            }
            return jQuery.text(this)
        },
        wrapAll: function (html) {
            if (jQuery.isFunction(html)) {
                return this.each(function (i) {
                    jQuery(this).wrapAll(html.call(this, i))
                })
            }
            if (this[0]) {
                var wrap = jQuery(html, this[0].ownerDocument).eq(0).clone(true);
                if (this[0].parentNode) {
                    wrap.insertBefore(this[0])
                }
                wrap.map(function () {
                    var elem = this;
                    while (elem.firstChild && elem.firstChild.nodeType === 1) {
                        elem = elem.firstChild
                    }
                    return elem
                }).append(this)
            }
            return this
        },
        wrapInner: function (html) {
            if (jQuery.isFunction(html)) {
                return this.each(function (i) {
                    jQuery(this).wrapInner(html.call(this, i))
                })
            }
            return this.each(function () {
                var self = jQuery(this),
                    contents = self.contents();
                if (contents.length) {
                    contents.wrapAll(html)
                } else {
                    self.append(html)
                }
            })
        },
        wrap: function (html) {
            return this.each(function () {
                jQuery(this).wrapAll(html)
            })
        },
        unwrap: function () {
            return this.parent().each(function () {
                if (!jQuery.nodeName(this, "body")) {
                    jQuery(this).replaceWith(this.childNodes)
                }
            }).end()
        },
        append: function () {
            return this.domManip(arguments, true, function (elem) {
                if (this.nodeType === 1) {
                    this.appendChild(elem)
                }
            })
        },
        prepend: function () {
            return this.domManip(arguments, true, function (elem) {
                if (this.nodeType === 1) {
                    this.insertBefore(elem, this.firstChild)
                }
            })
        },
        before: function () {
            if (this[0] && this[0].parentNode) {
                return this.domManip(arguments, false, function (elem) {
                    this.parentNode.insertBefore(elem, this)
                })
            } else if (arguments.length) {
                var set = jQuery(arguments[0]);
                set.push.apply(set, this.toArray());
                return this.pushStack(set, "before", arguments)
            }
        },
        after: function () {
            if (this[0] && this[0].parentNode) {
                return this.domManip(arguments, false, function (elem) {
                    this.parentNode.insertBefore(elem, this.nextSibling)
                })
            } else if (arguments.length) {
                var set = this.pushStack(this, "after", arguments);
                set.push.apply(set, jQuery(arguments[0]).toArray());
                return set
            }
        },
        remove: function (selector, keepData) {
            for (var i = 0, elem;
            (elem = this[i]) != null; i++) {
                if (!selector || jQuery.filter(selector, [elem]).length) {
                    if (!keepData && elem.nodeType === 1) {
                        jQuery.cleanData(elem.getElementsByTagName("*"));
                        jQuery.cleanData([elem])
                    }
                    if (elem.parentNode) {
                        elem.parentNode.removeChild(elem)
                    }
                }
            }
            return this
        },
        empty: function () {
            for (var i = 0, elem;
            (elem = this[i]) != null; i++) {
                if (elem.nodeType === 1) {
                    jQuery.cleanData(elem.getElementsByTagName("*"))
                }
                while (elem.firstChild) {
                    elem.removeChild(elem.firstChild)
                }
            }
            return this
        },
        clone: function (dataAndEvents, deepDataAndEvents) {
            dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
            deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
            return this.map(function () {
                return jQuery.clone(this, dataAndEvents, deepDataAndEvents)
            })
        },
        html: function (value) {
            if (value === undefined) {
                return this[0] && this[0].nodeType === 1 ? this[0].innerHTML.replace(rinlinejQuery, "") : null
            } else if (typeof value === "string" && !rnocache.test(value) && (jQuery.support.leadingWhitespace || !rleadingWhitespace.test(value)) && !wrapMap[(rtagName.exec(value) || ["", ""])[1].toLowerCase()]) {
                value = value.replace(rxhtmlTag, "<$1></$2>");
                try {
                    for (var i = 0, l = this.length; i < l; i++) {
                        if (this[i].nodeType === 1) {
                            jQuery.cleanData(this[i].getElementsByTagName("*"));
                            this[i].innerHTML = value
                        }
                    }
                } catch (e) {
                    this.empty().append(value)
                }
            } else if (jQuery.isFunction(value)) {
                this.each(function (i) {
                    var self = jQuery(this);
                    self.html(value.call(this, i, self.html()))
                })
            } else {
                this.empty().append(value)
            }
            return this
        },
        replaceWith: function (value) {
            if (this[0] && this[0].parentNode) {
                if (jQuery.isFunction(value)) {
                    return this.each(function (i) {
                        var self = jQuery(this),
                            old = self.html();
                        self.replaceWith(value.call(this, i, old))
                    })
                }
                if (typeof value !== "string") {
                    value = jQuery(value).detach()
                }
                return this.each(function () {
                    var next = this.nextSibling,
                        parent = this.parentNode;
                    jQuery(this).remove();
                    if (next) {
                        jQuery(next).before(value)
                    } else {
                        jQuery(parent).append(value)
                    }
                })
            } else {
                return this.length ? this.pushStack(jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value) : this
            }
        },
        detach: function (selector) {
            return this.remove(selector, true)
        },
        domManip: function (args, table, callback) {
            var results, first, fragment, parent, value = args[0],
                scripts = [];
            if (!jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test(value)) {
                return this.each(function () {
                    jQuery(this).domManip(args, table, callback, true)
                })
            }
            if (jQuery.isFunction(value)) {
                return this.each(function (i) {
                    var self = jQuery(this);
                    args[0] = value.call(this, i, table ? self.html() : undefined);
                    self.domManip(args, table, callback)
                })
            }
            if (this[0]) {
                parent = value && value.parentNode;
                if (jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length) {
                    results = {
                        fragment: parent
                    }
                } else {
                    results = jQuery.buildFragment(args, this, scripts)
                }
                fragment = results.fragment;
                if (fragment.childNodes.length === 1) {
                    first = fragment = fragment.firstChild
                } else {
                    first = fragment.firstChild
                }
                if (first) {
                    table = table && jQuery.nodeName(first, "tr");
                    for (var i = 0, l = this.length, lastIndex = l - 1; i < l; i++) {
                        callback.call(table ? root(this[i], first) : this[i], results.cacheable || (l > 1 && i < lastIndex) ? jQuery.clone(fragment, true, true) : fragment)
                    }
                }
                if (scripts.length) {
                    jQuery.each(scripts, evalScript)
                }
            }
            return this
        }
    });

    function root(elem, cur) {
        return jQuery.nodeName(elem, "table") ? (elem.getElementsByTagName("tbody")[0] || elem.appendChild(elem.ownerDocument.createElement("tbody"))) : elem
    }
    function cloneCopyEvent(src, dest) {
        if (dest.nodeType !== 1 || !jQuery.hasData(src)) {
            return
        }
        var internalKey = jQuery.expando,
            oldData = jQuery.data(src),
            curData = jQuery.data(dest, oldData);
        if ((oldData = oldData[internalKey])) {
            var events = oldData.events;
            curData = curData[internalKey] = jQuery.extend({}, oldData);
            if (events) {
                delete curData.handle;
                curData.events = {};
                for (var type in events) {
                    for (var i = 0, l = events[type].length; i < l; i++) {
                        jQuery.event.add(dest, type + (events[type][i].namespace ? "." : "") + events[type][i].namespace, events[type][i], events[type][i].data)
                    }
                }
            }
        }
    }
    function cloneFixAttributes(src, dest) {
        if (dest.nodeType !== 1) {
            return
        }
        var nodeName = dest.nodeName.toLowerCase();
        dest.clearAttributes();
        dest.mergeAttributes(src);
        if (nodeName === "object") {
            dest.outerHTML = src.outerHTML
        } else if (nodeName === "input" && (src.type === "checkbox" || src.type === "radio")) {
            if (src.checked) {
                dest.defaultChecked = dest.checked = src.checked
            }
            if (dest.value !== src.value) {
                dest.value = src.value
            }
        } else if (nodeName === "option") {
            dest.selected = src.defaultSelected
        } else if (nodeName === "input" || nodeName === "textarea") {
            dest.defaultValue = src.defaultValue
        }
        dest.removeAttribute(jQuery.expando)
    }
    jQuery.buildFragment = function (args, nodes, scripts) {
        var fragment, cacheable, cacheresults, doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
        if (args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document && args[0].charAt(0) === "<" && !rnocache.test(args[0]) && (jQuery.support.checkClone || !rchecked.test(args[0]))) {
            cacheable = true;
            cacheresults = jQuery.fragments[args[0]];
            if (cacheresults) {
                if (cacheresults !== 1) {
                    fragment = cacheresults
                }
            }
        }
        if (!fragment) {
            fragment = doc.createDocumentFragment();
            jQuery.clean(args, doc, fragment, scripts)
        }
        if (cacheable) {
            jQuery.fragments[args[0]] = cacheresults ? fragment : 1
        }
        return {
            fragment: fragment,
            cacheable: cacheable
        }
    };
    jQuery.fragments = {};
    jQuery.each({
        appendTo: "append",
        prependTo: "prepend",
        insertBefore: "before",
        insertAfter: "after",
        replaceAll: "replaceWith"
    }, function (name, original) {
        jQuery.fn[name] = function (selector) {
            var ret = [],
                insert = jQuery(selector),
                parent = this.length === 1 && this[0].parentNode;
            if (parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1) {
                insert[original](this[0]);
                return this
            } else {
                for (var i = 0, l = insert.length; i < l; i++) {
                    var elems = (i > 0 ? this.clone(true) : this).get();
                    jQuery(insert[i])[original](elems);
                    ret = ret.concat(elems)
                }
                return this.pushStack(ret, name, insert.selector)
            }
        }
    });

    function getAll(elem) {
        if ("getElementsByTagName" in elem) {
            return elem.getElementsByTagName("*")
        } else if ("querySelectorAll" in elem) {
            return elem.querySelectorAll("*")
        } else {
            return []
        }
    }
    jQuery.extend({
        clone: function (elem, dataAndEvents, deepDataAndEvents) {
            var clone = elem.cloneNode(true),
                srcElements, destElements, i;
            if ((!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem)) {
                cloneFixAttributes(elem, clone);
                srcElements = getAll(elem);
                destElements = getAll(clone);
                for (i = 0; srcElements[i]; ++i) {
                    cloneFixAttributes(srcElements[i], destElements[i])
                }
            }
            if (dataAndEvents) {
                cloneCopyEvent(elem, clone);
                if (deepDataAndEvents) {
                    srcElements = getAll(elem);
                    destElements = getAll(clone);
                    for (i = 0; srcElements[i]; ++i) {
                        cloneCopyEvent(srcElements[i], destElements[i])
                    }
                }
            }
            return clone
        },
        clean: function (elems, context, fragment, scripts) {
            context = context || document;
            if (typeof context.createElement === "undefined") {
                context = context.ownerDocument || context[0] && context[0].ownerDocument || document
            }
            var ret = [];
            for (var i = 0, elem;
            (elem = elems[i]) != null; i++) {
                if (typeof elem === "number") {
                    elem += ""
                }
                if (!elem) {
                    continue
                }
                if (typeof elem === "string" && !rhtml.test(elem)) {
                    elem = context.createTextNode(elem)
                } else if (typeof elem === "string") {
                    elem = elem.replace(rxhtmlTag, "<$1></$2>");
                    var tag = (rtagName.exec(elem) || ["", ""])[1].toLowerCase(),
                        wrap = wrapMap[tag] || wrapMap._default,
                        depth = wrap[0],
                        div = context.createElement("div");
                    div.innerHTML = wrap[1] + elem + wrap[2];
                    while (depth--) {
                        div = div.lastChild
                    }
                    if (!jQuery.support.tbody) {
                        var hasBody = rtbody.test(elem),
                            tbody = tag === "table" && !hasBody ? div.firstChild && div.firstChild.childNodes : wrap[1] === "<table>" && !hasBody ? div.childNodes : [];
                        for (var j = tbody.length - 1; j >= 0; --j) {
                            if (jQuery.nodeName(tbody[j], "tbody") && !tbody[j].childNodes.length) {
                                tbody[j].parentNode.removeChild(tbody[j])
                            }
                        }
                    }
                    if (!jQuery.support.leadingWhitespace && rleadingWhitespace.test(elem)) {
                        div.insertBefore(context.createTextNode(rleadingWhitespace.exec(elem)[0]), div.firstChild)
                    }
                    elem = div.childNodes
                }
                if (elem.nodeType) {
                    ret.push(elem)
                } else {
                    ret = jQuery.merge(ret, elem)
                }
            }
            if (fragment) {
                for (i = 0; ret[i]; i++) {
                    if (scripts && jQuery.nodeName(ret[i], "script") && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript")) {
                        scripts.push(ret[i].parentNode ? ret[i].parentNode.removeChild(ret[i]) : ret[i])
                    } else {
                        if (ret[i].nodeType === 1) {
                            ret.splice.apply(ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))))
                        }
                        fragment.appendChild(ret[i])
                    }
                }
            }
            return ret
        },
        cleanData: function (elems) {
            var data, id, cache = jQuery.cache,
                internalKey = jQuery.expando,
                special = jQuery.event.special,
                deleteExpando = jQuery.support.deleteExpando;
            for (var i = 0, elem;
            (elem = elems[i]) != null; i++) {
                if (elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) {
                    continue
                }
                id = elem[jQuery.expando];
                if (id) {
                    data = cache[id] && cache[id][internalKey];
                    if (data && data.events) {
                        for (var type in data.events) {
                            if (special[type]) {
                                jQuery.event.remove(elem, type)
                            } else {
                                jQuery.removeEvent(elem, type, data.handle)
                            }
                        }
                        if (data.handle) {
                            data.handle.elem = null
                        }
                    }
                    if (deleteExpando) {
                        delete elem[jQuery.expando]
                    } else if (elem.removeAttribute) {
                        elem.removeAttribute(jQuery.expando)
                    }
                    delete cache[id]
                }
            }
        }
    });

    function evalScript(i, elem) {
        if (elem.src) {
            jQuery.ajax({
                url: elem.src,
                async: false,
                dataType: "script"
            })
        } else {
            jQuery.globalEval(elem.text || elem.textContent || elem.innerHTML || "")
        }
        if (elem.parentNode) {
            elem.parentNode.removeChild(elem)
        }
    }
    var ralpha = /alpha\([^)]*\)/i,
        ropacity = /opacity=([^)]*)/,
        rdashAlpha = /-([a-z])/ig,
        rupper = /([A-Z]|^ms)/g,
        rnumpx = /^-?\d+(?:px)?$/i,
        rnum = /^-?\d/,
        cssShow = {
            position: "absolute",
            visibility: "hidden",
            display: "block"
        },
        cssWidth = ["Left", "Right"],
        cssHeight = ["Top", "Bottom"],
        curCSS, getComputedStyle, currentStyle, fcamelCase = function (all, letter) {
            return letter.toUpperCase()
        };
    jQuery.fn.css = function (name, value) {
        if (arguments.length === 2 && value === undefined) {
            return this
        }
        return jQuery.access(this, name, value, true, function (elem, name, value) {
            return value !== undefined ? jQuery.style(elem, name, value) : jQuery.css(elem, name)
        })
    };
    jQuery.extend({
        cssHooks: {
            opacity: {
                get: function (elem, computed) {
                    if (computed) {
                        var ret = curCSS(elem, "opacity", "opacity");
                        return ret === "" ? "1" : ret
                    } else {
                        return elem.style.opacity
                    }
                }
            }
        },
        cssNumber: {
            "zIndex": true,
            "fontWeight": true,
            "opacity": true,
            "zoom": true,
            "lineHeight": true
        },
        cssProps: {
            "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
        },
        style: function (elem, name, value, extra) {
            if (!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style) {
                return
            }
            var ret, origName = jQuery.camelCase(name),
                style = elem.style,
                hooks = jQuery.cssHooks[origName];
            name = jQuery.cssProps[origName] || origName;
            if (value !== undefined) {
                if (typeof value === "number" && isNaN(value) || value == null) {
                    return
                }
                if (typeof value === "number" && !jQuery.cssNumber[origName]) {
                    value += "px"
                }
                if (!hooks || !("set" in hooks) || (value = hooks.set(elem, value)) !== undefined) {
                    try {
                        style[name] = value
                    } catch (e) {}
                }
            } else {
                if (hooks && "get" in hooks && (ret = hooks.get(elem, false, extra)) !== undefined) {
                    return ret
                }
                return style[name]
            }
        },
        css: function (elem, name, extra) {
            var ret, origName = jQuery.camelCase(name),
                hooks = jQuery.cssHooks[origName];
            name = jQuery.cssProps[origName] || origName;
            if (hooks && "get" in hooks && (ret = hooks.get(elem, true, extra)) !== undefined) {
                return ret
            } else if (curCSS) {
                return curCSS(elem, name, origName)
            }
        },
        swap: function (elem, options, callback) {
            var old = {};
            for (var name in options) {
                old[name] = elem.style[name];
                elem.style[name] = options[name]
            }
            callback.call(elem);
            for (name in options) {
                elem.style[name] = old[name]
            }
        },
        camelCase: function (string) {
            return string.replace(rdashAlpha, fcamelCase)
        }
    });
    jQuery.curCSS = jQuery.css;
    jQuery.each(["height", "width"], function (i, name) {
        jQuery.cssHooks[name] = {
            get: function (elem, computed, extra) {
                var val;
                if (computed) {
                    if (elem.offsetWidth !== 0) {
                        val = getWH(elem, name, extra)
                    } else {
                        jQuery.swap(elem, cssShow, function () {
                            val = getWH(elem, name, extra)
                        })
                    }
                    if (val <= 0) {
                        val = curCSS(elem, name, name);
                        if (val === "0px" && currentStyle) {
                            val = currentStyle(elem, name, name)
                        }
                        if (val != null) {
                            return val === "" || val === "auto" ? "0px" : val
                        }
                    }
                    if (val < 0 || val == null) {
                        val = elem.style[name];
                        return val === "" || val === "auto" ? "0px" : val
                    }
                    return typeof val === "string" ? val : val + "px"
                }
            },
            set: function (elem, value) {
                if (rnumpx.test(value)) {
                    value = parseFloat(value);
                    if (value >= 0) {
                        return value + "px"
                    }
                } else {
                    return value
                }
            }
        }
    });
    if (!jQuery.support.opacity) {
        jQuery.cssHooks.opacity = {
            get: function (elem, computed) {
                return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "") ? (parseFloat(RegExp.$1) / 100) + "" : computed ? "1" : ""
            },
            set: function (elem, value) {
                var style = elem.style;
                style.zoom = 1;
                var opacity = jQuery.isNaN(value) ? "" : "alpha(opacity=" + value * 100 + ")",
                    filter = style.filter || "";
                style.filter = ralpha.test(filter) ? filter.replace(ralpha, opacity) : style.filter + ' ' + opacity
            }
        }
    }
    jQuery(function () {
        if (!jQuery.support.reliableMarginRight) {
            jQuery.cssHooks.marginRight = {
                get: function (elem, computed) {
                    var ret;
                    jQuery.swap(elem, {
                        "display": "inline-block"
                    }, function () {
                        if (computed) {
                            ret = curCSS(elem, "margin-right", "marginRight")
                        } else {
                            ret = elem.style.marginRight
                        }
                    });
                    return ret
                }
            }
        }
    });
    if (document.defaultView && document.defaultView.getComputedStyle) {
        getComputedStyle = function (elem, newName, name) {
            var ret, defaultView, computedStyle;
            name = name.replace(rupper, "-$1").toLowerCase();
            if (!(defaultView = elem.ownerDocument.defaultView)) {
                return undefined
            }
            if ((computedStyle = defaultView.getComputedStyle(elem, null))) {
                ret = computedStyle.getPropertyValue(name);
                if (ret === "" && !jQuery.contains(elem.ownerDocument.documentElement, elem)) {
                    ret = jQuery.style(elem, name)
                }
            }
            return ret
        }
    }
    if (document.documentElement.currentStyle) {
        currentStyle = function (elem, name) {
            var left, ret = elem.currentStyle && elem.currentStyle[name],
                rsLeft = elem.runtimeStyle && elem.runtimeStyle[name],
                style = elem.style;
            if (!rnumpx.test(ret) && rnum.test(ret)) {
                left = style.left;
                if (rsLeft) {
                    elem.runtimeStyle.left = elem.currentStyle.left
                }
                style.left = name === "fontSize" ? "1em" : (ret || 0);
                ret = style.pixelLeft + "px";
                style.left = left;
                if (rsLeft) {
                    elem.runtimeStyle.left = rsLeft
                }
            }
            return ret === "" ? "auto" : ret
        }
    }
    curCSS = getComputedStyle || currentStyle;

    function getWH(elem, name, extra) {
        var which = name === "width" ? cssWidth : cssHeight,
            val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
        if (extra === "border") {
            return val
        }
        jQuery.each(which, function () {
            if (!extra) {
                val -= parseFloat(jQuery.css(elem, "padding" + this)) || 0
            }
            if (extra === "margin") {
                val += parseFloat(jQuery.css(elem, "margin" + this)) || 0
            } else {
                val -= parseFloat(jQuery.css(elem, "border" + this + "Width")) || 0
            }
        });
        return val
    }
    if (jQuery.expr && jQuery.expr.filters) {
        jQuery.expr.filters.hidden = function (elem) {
            var width = elem.offsetWidth,
                height = elem.offsetHeight;
            return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css(elem, "display")) === "none")
        };
        jQuery.expr.filters.visible = function (elem) {
            return !jQuery.expr.filters.hidden(elem)
        }
    }
    var r20 = /%20/g,
        rbracket = /\[\]$/,
        rCRLF = /\r?\n/g,
        rhash = /#.*$/,
        rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg,
        rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
        rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|widget):$/,
        rnoContent = /^(?:GET|HEAD)$/,
        rprotocol = /^\/\//,
        rquery = /\?/,
        rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
        rselectTextarea = /^(?:select|textarea)/i,
        rspacesAjax = /\s+/,
        rts = /([?&])_=[^&]*/,
        rucHeaders = /(^|\-)([a-z])/g,
        rucHeadersFunc = function (_, $1, $2) {
            return $1 + $2.toUpperCase()
        },
        rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
        _load = jQuery.fn.load,
        prefilters = {},
        transports = {},
        ajaxLocation, ajaxLocParts;
    try {
        ajaxLocation = document.location.href
    } catch (e) {
        ajaxLocation = document.createElement("a");
        ajaxLocation.href = "";
        ajaxLocation = ajaxLocation.href
    }
    ajaxLocParts = rurl.exec(ajaxLocation.toLowerCase()) || [];

    function addToPrefiltersOrTransports(structure) {
        return function (dataTypeExpression, func) {
            if (typeof dataTypeExpression !== "string") {
                func = dataTypeExpression;
                dataTypeExpression = "*"
            }
            if (jQuery.isFunction(func)) {
                var dataTypes = dataTypeExpression.toLowerCase().split(rspacesAjax),
                    i = 0,
                    length = dataTypes.length,
                    dataType, list, placeBefore;
                for (; i < length; i++) {
                    dataType = dataTypes[i];
                    placeBefore = /^\+/.test(dataType);
                    if (placeBefore) {
                        dataType = dataType.substr(1) || "*"
                    }
                    list = structure[dataType] = structure[dataType] || [];
                    list[placeBefore ? "unshift" : "push"](func)
                }
            }
        }
    }
    function inspectPrefiltersOrTransports(structure, options, originalOptions, jqXHR, dataType, inspected) {
        dataType = dataType || options.dataTypes[0];
        inspected = inspected || {};
        inspected[dataType] = true;
        var list = structure[dataType],
            i = 0,
            length = list ? list.length : 0,
            executeOnly = (structure === prefilters),
            selection;
        for (; i < length && (executeOnly || !selection); i++) {
            selection = list[i](options, originalOptions, jqXHR);
            if (typeof selection === "string") {
                if (!executeOnly || inspected[selection]) {
                    selection = undefined
                } else {
                    options.dataTypes.unshift(selection);
                    selection = inspectPrefiltersOrTransports(structure, options, originalOptions, jqXHR, selection, inspected)
                }
            }
        }
        if ((executeOnly || !selection) && !inspected["*"]) {
            selection = inspectPrefiltersOrTransports(structure, options, originalOptions, jqXHR, "*", inspected)
        }
        return selection
    }
    jQuery.fn.extend({
        load: function (url, params, callback) {
            if (typeof url !== "string" && _load) {
                return _load.apply(this, arguments)
            } else if (!this.length) {
                return this
            }
            var off = url.indexOf(" ");
            if (off >= 0) {
                var selector = url.slice(off, url.length);
                url = url.slice(0, off)
            }
            var type = "GET";
            if (params) {
                if (jQuery.isFunction(params)) {
                    callback = params;
                    params = undefined
                } else if (typeof params === "object") {
                    params = jQuery.param(params, jQuery.ajaxSettings.traditional);
                    type = "POST"
                }
            }
            var self = this;
            jQuery.ajax({
                url: url,
                type: type,
                dataType: "html",
                data: params,
                complete: function (jqXHR, status, responseText) {
                    responseText = jqXHR.responseText;
                    if (jqXHR.isResolved()) {
                        jqXHR.done(function (r) {
                            responseText = r
                        });
                        self.html(selector ? jQuery("<div>").append(responseText.replace(rscript, "")).find(selector) : responseText)
                    }
                    if (callback) {
                        self.each(callback, [responseText, status, jqXHR])
                    }
                }
            });
            return this
        },
        serialize: function () {
            return jQuery.param(this.serializeArray())
        },
        serializeArray: function () {
            return this.map(function () {
                return this.elements ? jQuery.makeArray(this.elements) : this
            }).filter(function () {
                return this.name && !this.disabled && (this.checked || rselectTextarea.test(this.nodeName) || rinput.test(this.type))
            }).map(function (i, elem) {
                var val = jQuery(this).val();
                return val == null ? null : jQuery.isArray(val) ? jQuery.map(val, function (val, i) {
                    return {
                        name: elem.name,
                        value: val.replace(rCRLF, "\r\n")
                    }
                }) : {
                    name: elem.name,
                    value: val.replace(rCRLF, "\r\n")
                }
            }).get()
        }
    });
    jQuery.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function (i, o) {
        jQuery.fn[o] = function (f) {
            return this.bind(o, f)
        }
    });
    jQuery.each(["get", "post"], function (i, method) {
        jQuery[method] = function (url, data, callback, type) {
            if (jQuery.isFunction(data)) {
                type = type || callback;
                callback = data;
                data = undefined
            }
            return jQuery.ajax({
                type: method,
                url: url,
                data: data,
                success: callback,
                dataType: type
            })
        }
    });
    jQuery.extend({
        getScript: function (url, callback) {
            return jQuery.get(url, undefined, callback, "script")
        },
        getJSON: function (url, data, callback) {
            return jQuery.get(url, data, callback, "json")
        },
        ajaxSetup: function (target, settings) {
            if (!settings) {
                settings = target;
                target = jQuery.extend(true, jQuery.ajaxSettings, settings)
            } else {
                jQuery.extend(true, target, jQuery.ajaxSettings, settings)
            }
            for (var field in {
                context: 1,
                url: 1
            }) {
                if (field in settings) {
                    target[field] = settings[field]
                } else if (field in jQuery.ajaxSettings) {
                    target[field] = jQuery.ajaxSettings[field]
                }
            }
            return target
        },
        ajaxSettings: {
            url: ajaxLocation,
            isLocal: rlocalProtocol.test(ajaxLocParts[1]),
            global: true,
            type: "GET",
            contentType: "application/x-www-form-urlencoded",
            processData: true,
            async: true,
            accepts: {
                xml: "application/xml, text/xml",
                html: "text/html",
                text: "text/plain",
                json: "application/json, text/javascript",
                "*": "*/*"
            },
            contents: {
                xml: /xml/,
                html: /html/,
                json: /json/
            },
            responseFields: {
                xml: "responseXML",
                text: "responseText"
            },
            converters: {
                "* text": window.String,
                "text html": true,
                "text json": jQuery.parseJSON,
                "text xml": jQuery.parseXML
            }
        },
        ajaxPrefilter: addToPrefiltersOrTransports(prefilters),
        ajaxTransport: addToPrefiltersOrTransports(transports),
        ajax: function (url, options) {
            if (typeof url === "object") {
                options = url;
                url = undefined
            }
            options = options || {};
            var s = jQuery.ajaxSetup({}, options),
                callbackContext = s.context || s,
                globalEventContext = callbackContext !== s && (callbackContext.nodeType || callbackContext instanceof jQuery) ? jQuery(callbackContext) : jQuery.event,
                deferred = jQuery.Deferred(),
                completeDeferred = jQuery._Deferred(),
                statusCode = s.statusCode || {},
                ifModifiedKey, requestHeaders = {},
                responseHeadersString, responseHeaders, transport, timeoutTimer, parts, state = 0,
                fireGlobals, i, jqXHR = {
                    readyState: 0,
                    setRequestHeader: function (name, value) {
                        if (!state) {
                            requestHeaders[name.toLowerCase().replace(rucHeaders, rucHeadersFunc)] = value
                        }
                        return this
                    },
                    getAllResponseHeaders: function () {
                        return state === 2 ? responseHeadersString : null
                    },
                    getResponseHeader: function (key) {
                        var match;
                        if (state === 2) {
                            if (!responseHeaders) {
                                responseHeaders = {};
                                while ((match = rheaders.exec(responseHeadersString))) {
                                    responseHeaders[match[1].toLowerCase()] = match[2]
                                }
                            }
                            match = responseHeaders[key.toLowerCase()]
                        }
                        return match === undefined ? null : match
                    },
                    overrideMimeType: function (type) {
                        if (!state) {
                            s.mimeType = type
                        }
                        return this
                    },
                    abort: function (statusText) {
                        statusText = statusText || "abort";
                        if (transport) {
                            transport.abort(statusText)
                        }
                        done(0, statusText);
                        return this
                    }
                };

            function done(status, statusText, responses, headers) {
                if (state === 2) {
                    return
                }
                state = 2;
                if (timeoutTimer) {
                    clearTimeout(timeoutTimer)
                }
                transport = undefined;
                responseHeadersString = headers || "";
                jqXHR.readyState = status ? 4 : 0;
                var isSuccess, success, error, response = responses ? ajaxHandleResponses(s, jqXHR, responses) : undefined,
                    lastModified, etag;
                if (status >= 200 && status < 300 || status === 304) {
                    if (s.ifModified) {
                        if ((lastModified = jqXHR.getResponseHeader("Last-Modified"))) {
                            jQuery.lastModified[ifModifiedKey] = lastModified
                        }
                        if ((etag = jqXHR.getResponseHeader("Etag"))) {
                            jQuery.etag[ifModifiedKey] = etag
                        }
                    }
                    if (status === 304) {
                        statusText = "notmodified";
                        isSuccess = true
                    } else {
                        try {
                            success = ajaxConvert(s, response);
                            statusText = "success";
                            isSuccess = true
                        } catch (e) {
                            statusText = "parsererror";
                            error = e
                        }
                    }
                } else {
                    error = statusText;
                    if (!statusText || status) {
                        statusText = "error";
                        if (status < 0) {
                            status = 0
                        }
                    }
                }
                jqXHR.status = status;
                jqXHR.statusText = statusText;
                if (isSuccess) {
                    deferred.resolveWith(callbackContext, [success, statusText, jqXHR])
                } else {
                    deferred.rejectWith(callbackContext, [jqXHR, statusText, error])
                }
                jqXHR.statusCode(statusCode);
                statusCode = undefined;
                if (fireGlobals) {
                    globalEventContext.trigger("ajax" + (isSuccess ? "Success" : "Error"), [jqXHR, s, isSuccess ? success : error])
                }
                completeDeferred.resolveWith(callbackContext, [jqXHR, statusText]);
                if (fireGlobals) {
                    globalEventContext.trigger("ajaxComplete", [jqXHR, s]);
                    if (!(--jQuery.active)) {
                        jQuery.event.trigger("ajaxStop")
                    }
                }
            }
            deferred.promise(jqXHR);
            jqXHR.success = jqXHR.done;
            jqXHR.error = jqXHR.fail;
            jqXHR.complete = completeDeferred.done;
            jqXHR.statusCode = function (map) {
                if (map) {
                    var tmp;
                    if (state < 2) {
                        for (tmp in map) {
                            statusCode[tmp] = [statusCode[tmp], map[tmp]]
                        }
                    } else {
                        tmp = map[jqXHR.status];
                        jqXHR.then(tmp, tmp)
                    }
                }
                return this
            };
            s.url = ((url || s.url) + "").replace(rhash, "").replace(rprotocol, ajaxLocParts[1] + "//");
            s.dataTypes = jQuery.trim(s.dataType || "*").toLowerCase().split(rspacesAjax);
            if (s.crossDomain == null) {
                parts = rurl.exec(s.url.toLowerCase());
                s.crossDomain = !! (parts && (parts[1] != ajaxLocParts[1] || parts[2] != ajaxLocParts[2] || (parts[3] || (parts[1] === "http:" ? 80 : 443)) != (ajaxLocParts[3] || (ajaxLocParts[1] === "http:" ? 80 : 443))))
            }
            if (s.data && s.processData && typeof s.data !== "string") {
                s.data = jQuery.param(s.data, s.traditional)
            }
            inspectPrefiltersOrTransports(prefilters, s, options, jqXHR);
            if (state === 2) {
                return false
            }
            fireGlobals = s.global;
            s.type = s.type.toUpperCase();
            s.hasContent = !rnoContent.test(s.type);
            if (fireGlobals && jQuery.active++ === 0) {
                jQuery.event.trigger("ajaxStart")
            }
            if (!s.hasContent) {
                if (s.data) {
                    s.url += (rquery.test(s.url) ? "&" : "?") + s.data
                }
                ifModifiedKey = s.url;
                if (s.cache === false) {
                    var ts = jQuery.now(),
                        ret = s.url.replace(rts, "$1_=" + ts);
                    s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "")
                }
            }
            if (s.data && s.hasContent && s.contentType !== false || options.contentType) {
                requestHeaders["Content-Type"] = s.contentType
            }
            if (s.ifModified) {
                ifModifiedKey = ifModifiedKey || s.url;
                if (jQuery.lastModified[ifModifiedKey]) {
                    requestHeaders["If-Modified-Since"] = jQuery.lastModified[ifModifiedKey]
                }
                if (jQuery.etag[ifModifiedKey]) {
                    requestHeaders["If-None-Match"] = jQuery.etag[ifModifiedKey]
                }
            }
            requestHeaders.Accept = s.dataTypes[0] && s.accepts[s.dataTypes[0]] ? s.accepts[s.dataTypes[0]] + (s.dataTypes[0] !== "*" ? ", */*; q=0.01" : "") : s.accepts["*"];
            for (i in s.headers) {
                jqXHR.setRequestHeader(i, s.headers[i])
            }
            if (s.beforeSend && (s.beforeSend.call(callbackContext, jqXHR, s) === false || state === 2)) {
                jqXHR.abort();
                return false
            }
            for (i in {
                success: 1,
                error: 1,
                complete: 1
            }) {
                jqXHR[i](s[i])
            }
            transport = inspectPrefiltersOrTransports(transports, s, options, jqXHR);
            if (!transport) {
                done(-1, "No Transport")
            } else {
                jqXHR.readyState = 1;
                if (fireGlobals) {
                    globalEventContext.trigger("ajaxSend", [jqXHR, s])
                }
                if (s.async && s.timeout > 0) {
                    timeoutTimer = setTimeout(function () {
                        jqXHR.abort("timeout")
                    }, s.timeout)
                }
                try {
                    state = 1;
                    transport.send(requestHeaders, done)
                } catch (e) {
                    if (status < 2) {
                        done(-1, e)
                    } else {
                        jQuery.error(e)
                    }
                }
            }
            return jqXHR
        },
        param: function (a, traditional) {
            var s = [],
                add = function (key, value) {
                    value = jQuery.isFunction(value) ? value() : value;
                    s[s.length] = encodeURIComponent(key) + "=" + encodeURIComponent(value)
                };
            if (traditional === undefined) {
                traditional = jQuery.ajaxSettings.traditional
            }
            if (jQuery.isArray(a) || (a.jquery && !jQuery.isPlainObject(a))) {
                jQuery.each(a, function () {
                    add(this.name, this.value)
                })
            } else {
                for (var prefix in a) {
                    buildParams(prefix, a[prefix], traditional, add)
                }
            }
            return s.join("&").replace(r20, "+")
        }
    });

    function buildParams(prefix, obj, traditional, add) {
        if (jQuery.isArray(obj) && obj.length) {
            jQuery.each(obj, function (i, v) {
                if (traditional || rbracket.test(prefix)) {
                    add(prefix, v)
                } else {
                    buildParams(prefix + "[" + (typeof v === "object" || jQuery.isArray(v) ? i : "") + "]", v, traditional, add)
                }
            })
        } else if (!traditional && obj != null && typeof obj === "object") {
            if (jQuery.isArray(obj) || jQuery.isEmptyObject(obj)) {
                add(prefix, "")
            } else {
                for (var name in obj) {
                    buildParams(prefix + "[" + name + "]", obj[name], traditional, add)
                }
            }
        } else {
            add(prefix, obj)
        }
    }
    jQuery.extend({
        active: 0,
        lastModified: {},
        etag: {}
    });

    function ajaxHandleResponses(s, jqXHR, responses) {
        var contents = s.contents,
            dataTypes = s.dataTypes,
            responseFields = s.responseFields,
            ct, type, finalDataType, firstDataType;
        for (type in responseFields) {
            if (type in responses) {
                jqXHR[responseFields[type]] = responses[type]
            }
        }
        while (dataTypes[0] === "*") {
            dataTypes.shift();
            if (ct === undefined) {
                ct = s.mimeType || jqXHR.getResponseHeader("content-type")
            }
        }
        if (ct) {
            for (type in contents) {
                if (contents[type] && contents[type].test(ct)) {
                    dataTypes.unshift(type);
                    break
                }
            }
        }
        if (dataTypes[0] in responses) {
            finalDataType = dataTypes[0]
        } else {
            for (type in responses) {
                if (!dataTypes[0] || s.converters[type + " " + dataTypes[0]]) {
                    finalDataType = type;
                    break
                }
                if (!firstDataType) {
                    firstDataType = type
                }
            }
            finalDataType = finalDataType || firstDataType
        }
        if (finalDataType) {
            if (finalDataType !== dataTypes[0]) {
                dataTypes.unshift(finalDataType)
            }
            return responses[finalDataType]
        }
    }
    function ajaxConvert(s, response) {
        if (s.dataFilter) {
            response = s.dataFilter(response, s.dataType)
        }
        var dataTypes = s.dataTypes,
            converters = {},
            i, key, length = dataTypes.length,
            tmp, current = dataTypes[0],
            prev, conversion, conv, conv1, conv2;
        for (i = 1; i < length; i++) {
            if (i === 1) {
                for (key in s.converters) {
                    if (typeof key === "string") {
                        converters[key.toLowerCase()] = s.converters[key]
                    }
                }
            }
            prev = current;
            current = dataTypes[i];
            if (current === "*") {
                current = prev
            } else if (prev !== "*" && prev !== current) {
                conversion = prev + " " + current;
                conv = converters[conversion] || converters["* " + current];
                if (!conv) {
                    conv2 = undefined;
                    for (conv1 in converters) {
                        tmp = conv1.split(" ");
                        if (tmp[0] === prev || tmp[0] === "*") {
                            conv2 = converters[tmp[1] + " " + current];
                            if (conv2) {
                                conv1 = converters[conv1];
                                if (conv1 === true) {
                                    conv = conv2
                                } else if (conv2 === true) {
                                    conv = conv1
                                }
                                break
                            }
                        }
                    }
                }
                if (!(conv || conv2)) {
                    jQuery.error("No conversion from " + conversion.replace(" ", " to "))
                }
                if (conv !== true) {
                    response = conv ? conv(response) : conv2(conv1(response))
                }
            }
        }
        return response
    }
    var jsc = jQuery.now(),
        jsre = /(\=)\?(&|$)|\?\?/i;
    jQuery.ajaxSetup({
        jsonp: "callback",
        jsonpCallback: function () {
            return jQuery.expando + "_" + (jsc++)
        }
    });
    jQuery.ajaxPrefilter("json jsonp", function (s, originalSettings, jqXHR) {
        var dataIsString = (typeof s.data === "string");
        if (s.dataTypes[0] === "jsonp" || originalSettings.jsonpCallback || originalSettings.jsonp != null || s.jsonp !== false && (jsre.test(s.url) || dataIsString && jsre.test(s.data))) {
            var responseContainer, jsonpCallback = s.jsonpCallback = jQuery.isFunction(s.jsonpCallback) ? s.jsonpCallback() : s.jsonpCallback,
                previous = window[jsonpCallback],
                url = s.url,
                data = s.data,
                replace = "$1" + jsonpCallback + "$2",
                cleanUp = function () {
                    window[jsonpCallback] = previous;
                    if (responseContainer && jQuery.isFunction(previous)) {
                        window[jsonpCallback](responseContainer[0])
                    }
                };
            if (s.jsonp !== false) {
                url = url.replace(jsre, replace);
                if (s.url === url) {
                    if (dataIsString) {
                        data = data.replace(jsre, replace)
                    }
                    if (s.data === data) {
                        url += (/\?/.test(url) ? "&" : "?") + s.jsonp + "=" + jsonpCallback
                    }
                }
            }
            s.url = url;
            s.data = data;
            window[jsonpCallback] = function (response) {
                responseContainer = [response]
            };
            jqXHR.then(cleanUp, cleanUp);
            s.converters["script json"] = function () {
                if (!responseContainer) {
                    jQuery.error(jsonpCallback + " was not called")
                }
                return responseContainer[0]
            };
            s.dataTypes[0] = "json";
            return "script"
        }
    });
    jQuery.ajaxSetup({
        accepts: {
            script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
        },
        contents: {
            script: /javascript|ecmascript/
        },
        converters: {
            "text script": function (text) {
                jQuery.globalEval(text);
                return text
            }
        }
    });
    jQuery.ajaxPrefilter("script", function (s) {
        if (s.cache === undefined) {
            s.cache = false
        }
        if (s.crossDomain) {
            s.type = "GET";
            s.global = false
        }
    });
    jQuery.ajaxTransport("script", function (s) {
        if (s.crossDomain) {
            var script, head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;
            return {
                send: function (_, callback) {
                    script = document.createElement("script");
                    script.async = "async";
                    if (s.scriptCharset) {
                        script.charset = s.scriptCharset
                    }
                    script.src = s.url;
                    script.onload = script.onreadystatechange = function (_, isAbort) {
                        if (!script.readyState || /loaded|complete/.test(script.readyState)) {
                            script.onload = script.onreadystatechange = null;
                            if (head && script.parentNode) {
                                head.removeChild(script)
                            }
                            script = undefined;
                            if (!isAbort) {
                                callback(200, "success")
                            }
                        }
                    };
                    head.insertBefore(script, head.firstChild)
                },
                abort: function () {
                    if (script) {
                        script.onload(0, 1)
                    }
                }
            }
        }
    });
    var xhrId = jQuery.now(),
        xhrCallbacks, testXHR;

    function xhrOnUnloadAbort() {
        jQuery(window).unload(function () {
            for (var key in xhrCallbacks) {
                xhrCallbacks[key](0, 1)
            }
        })
    }
    function createStandardXHR() {
        try {
            return new window.XMLHttpRequest()
        } catch (e) {}
    }
    function createActiveXHR() {
        try {
            return new window.ActiveXObject("Microsoft.XMLHTTP")
        } catch (e) {}
    }
    jQuery.ajaxSettings.xhr = window.ActiveXObject ?
    function () {
        return !this.isLocal && createStandardXHR() || createActiveXHR()
    } : createStandardXHR;
    testXHR = jQuery.ajaxSettings.xhr();
    jQuery.support.ajax = !! testXHR;
    jQuery.support.cors = testXHR && ("withCredentials" in testXHR);
    testXHR = undefined;
    if (jQuery.support.ajax) {
        jQuery.ajaxTransport(function (s) {
            if (!s.crossDomain || jQuery.support.cors) {
                var callback;
                return {
                    send: function (headers, complete) {
                        var xhr = s.xhr(),
                            handle, i;
                        if (s.username) {
                            xhr.open(s.type, s.url, s.async, s.username, s.password)
                        } else {
                            xhr.open(s.type, s.url, s.async)
                        }
                        if (s.xhrFields) {
                            for (i in s.xhrFields) {
                                xhr[i] = s.xhrFields[i]
                            }
                        }
                        if (s.mimeType && xhr.overrideMimeType) {
                            xhr.overrideMimeType(s.mimeType)
                        }
                        if (!s.crossDomain && !headers["X-Requested-With"]) {
                            headers["X-Requested-With"] = "XMLHttpRequest"
                        }
                        try {
                            for (i in headers) {
                                xhr.setRequestHeader(i, headers[i])
                            }
                        } catch (_) {}
                        xhr.send((s.hasContent && s.data) || null);
                        callback = function (_, isAbort) {
                            var status, statusText, responseHeaders, responses, xml;
                            try {
                                if (callback && (isAbort || xhr.readyState === 4)) {
                                    callback = undefined;
                                    if (handle) {
                                        xhr.onreadystatechange = jQuery.noop;
                                        delete xhrCallbacks[handle]
                                    }
                                    if (isAbort) {
                                        if (xhr.readyState !== 4) {
                                            xhr.abort()
                                        }
                                    } else {
                                        status = xhr.status;
                                        responseHeaders = xhr.getAllResponseHeaders();
                                        responses = {};
                                        xml = xhr.responseXML;
                                        if (xml && xml.documentElement) {
                                            responses.xml = xml
                                        }
                                        responses.text = xhr.responseText;
                                        try {
                                            statusText = xhr.statusText
                                        } catch (e) {
                                            statusText = ""
                                        }
                                        if (!status && s.isLocal && !s.crossDomain) {
                                            status = responses.text ? 200 : 404
                                        } else if (status === 1223) {
                                            status = 204
                                        }
                                    }
                                }
                            } catch (firefoxAccessException) {
                                if (!isAbort) {
                                    complete(-1, firefoxAccessException)
                                }
                            }
                            if (responses) {
                                complete(status, statusText, responses, responseHeaders)
                            }
                        };
                        if (!s.async || xhr.readyState === 4) {
                            callback()
                        } else {
                            if (!xhrCallbacks) {
                                xhrCallbacks = {};
                                xhrOnUnloadAbort()
                            }
                            handle = xhrId++;
                            xhr.onreadystatechange = xhrCallbacks[handle] = callback
                        }
                    },
                    abort: function () {
                        if (callback) {
                            callback(0, 1)
                        }
                    }
                }
            }
        })
    }
    var elemdisplay = {},
        rfxtypes = /^(?:toggle|show|hide)$/,
        rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
        timerId, fxAttrs = [
            ["height", "marginTop", "marginBottom", "paddingTop", "paddingBottom"],
            ["width", "marginLeft", "marginRight", "paddingLeft", "paddingRight"],
            ["opacity"]
        ];
    jQuery.fn.extend({
        show: function (speed, easing, callback) {
            var elem, display;
            if (speed || speed === 0) {
                return this.animate(genFx("show", 3), speed, easing, callback)
            } else {
                for (var i = 0, j = this.length; i < j; i++) {
                    elem = this[i];
                    display = elem.style.display;
                    if (!jQuery._data(elem, "olddisplay") && display === "none") {
                        display = elem.style.display = ""
                    }
                    if (display === "" && jQuery.css(elem, "display") === "none") {
                        jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName))
                    }
                }
                for (i = 0; i < j; i++) {
                    elem = this[i];
                    display = elem.style.display;
                    if (display === "" || display === "none") {
                        elem.style.display = jQuery._data(elem, "olddisplay") || ""
                    }
                }
                return this
            }
        },
        hide: function (speed, easing, callback) {
            if (speed || speed === 0) {
                return this.animate(genFx("hide", 3), speed, easing, callback)
            } else {
                for (var i = 0, j = this.length; i < j; i++) {
                    var display = jQuery.css(this[i], "display");
                    if (display !== "none" && !jQuery._data(this[i], "olddisplay")) {
                        jQuery._data(this[i], "olddisplay", display)
                    }
                }
                for (i = 0; i < j; i++) {
                    this[i].style.display = "none"
                }
                return this
            }
        },
        _toggle: jQuery.fn.toggle,
        toggle: function (fn, fn2, callback) {
            var bool = typeof fn === "boolean";
            if (jQuery.isFunction(fn) && jQuery.isFunction(fn2)) {
                this._toggle.apply(this, arguments)
            } else if (fn == null || bool) {
                this.each(function () {
                    var state = bool ? fn : jQuery(this).is(":hidden");
                    jQuery(this)[state ? "show" : "hide"]()
                })
            } else {
                this.animate(genFx("toggle", 3), fn, fn2, callback)
            }
            return this
        },
        fadeTo: function (speed, to, easing, callback) {
            return this.filter(":hidden").css("opacity", 0).show().end().animate({
                opacity: to
            }, speed, easing, callback)
        },
        animate: function (prop, speed, easing, callback) {
            var optall = jQuery.speed(speed, easing, callback);
            if (jQuery.isEmptyObject(prop)) {
                return this.each(optall.complete)
            }
            return this[optall.queue === false ? "each" : "queue"](function () {
                var opt = jQuery.extend({}, optall),
                    p, isElement = this.nodeType === 1,
                    hidden = isElement && jQuery(this).is(":hidden"),
                    self = this;
                for (p in prop) {
                    var name = jQuery.camelCase(p);
                    if (p !== name) {
                        prop[name] = prop[p];
                        delete prop[p];
                        p = name
                    }
                    if (prop[p] === "hide" && hidden || prop[p] === "show" && !hidden) {
                        return opt.complete.call(this)
                    }
                    if (isElement && (p === "height" || p === "width")) {
                        opt.overflow = [this.style.overflow, this.style.overflowX, this.style.overflowY];
                        if (jQuery.css(this, "display") === "inline" && jQuery.css(this, "float") === "none") {
                            if (!jQuery.support.inlineBlockNeedsLayout) {
                                this.style.display = "inline-block"
                            } else {
                                var display = defaultDisplay(this.nodeName);
                                if (display === "inline") {
                                    this.style.display = "inline-block"
                                } else {
                                    this.style.display = "inline";
                                    this.style.zoom = 1
                                }
                            }
                        }
                    }
                    if (jQuery.isArray(prop[p])) {
                        (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
                        prop[p] = prop[p][0]
                    }
                }
                if (opt.overflow != null) {
                    this.style.overflow = "hidden"
                }
                opt.curAnim = jQuery.extend({}, prop);
                jQuery.each(prop, function (name, val) {
                    var e = new jQuery.fx(self, opt, name);
                    if (rfxtypes.test(val)) {
                        e[val === "toggle" ? hidden ? "show" : "hide" : val](prop)
                    } else {
                        var parts = rfxnum.exec(val),
                            start = e.cur();
                        if (parts) {
                            var end = parseFloat(parts[2]),
                                unit = parts[3] || (jQuery.cssNumber[name] ? "" : "px");
                            if (unit !== "px") {
                                jQuery.style(self, name, (end || 1) + unit);
                                start = ((end || 1) / e.cur()) * start;
                                jQuery.style(self, name, start + unit)
                            }
                            if (parts[1]) {
                                end = ((parts[1] === "-=" ? -1 : 1) * end) + start
                            }
                            e.custom(start, end, unit)
                        } else {
                            e.custom(start, val, "")
                        }
                    }
                });
                return true
            })
        },
        stop: function (clearQueue, gotoEnd) {
            var timers = jQuery.timers;
            if (clearQueue) {
                this.queue([])
            }
            this.each(function () {
                for (var i = timers.length - 1; i >= 0; i--) {
                    if (timers[i].elem === this) {
                        if (gotoEnd) {
                            timers[i](true)
                        }
                        timers.splice(i, 1)
                    }
                }
            });
            if (!gotoEnd) {
                this.dequeue()
            }
            return this
        }
    });

    function genFx(type, num) {
        var obj = {};
        jQuery.each(fxAttrs.concat.apply([], fxAttrs.slice(0, num)), function () {
            obj[this] = type
        });
        return obj
    }
    jQuery.each({
        slideDown: genFx("show", 1),
        slideUp: genFx("hide", 1),
        slideToggle: genFx("toggle", 1),
        fadeIn: {
            opacity: "show"
        },
        fadeOut: {
            opacity: "hide"
        },
        fadeToggle: {
            opacity: "toggle"
        }
    }, function (name, props) {
        jQuery.fn[name] = function (speed, easing, callback) {
            return this.animate(props, speed, easing, callback)
        }
    });
    jQuery.extend({
        speed: function (speed, easing, fn) {
            var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {
                complete: fn || !fn && easing || jQuery.isFunction(speed) && speed,
                duration: speed,
                easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
            };
            opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;
            opt.old = opt.complete;
            opt.complete = function () {
                if (opt.queue !== false) {
                    jQuery(this).dequeue()
                }
                if (jQuery.isFunction(opt.old)) {
                    opt.old.call(this)
                }
            };
            return opt
        },
        easing: {
            linear: function (p, n, firstNum, diff) {
                return firstNum + diff * p
            },
            swing: function (p, n, firstNum, diff) {
                return ((-Math.cos(p * Math.PI) / 2) + 0.5) * diff + firstNum
            }
        },
        timers: [],
        fx: function (elem, options, prop) {
            this.options = options;
            this.elem = elem;
            this.prop = prop;
            if (!options.orig) {
                options.orig = {}
            }
        }
    });
    jQuery.fx.prototype = {
        update: function () {
            if (this.options.step) {
                this.options.step.call(this.elem, this.now, this)
            }(jQuery.fx.step[this.prop] || jQuery.fx.step._default)(this)
        },
        cur: function () {
            if (this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null)) {
                return this.elem[this.prop]
            }
            var parsed, r = jQuery.css(this.elem, this.prop);
            return isNaN(parsed = parseFloat(r)) ? !r || r === "auto" ? 0 : r : parsed
        },
        custom: function (from, to, unit) {
            var self = this,
                fx = jQuery.fx;
            this.startTime = jQuery.now();
            this.start = from;
            this.end = to;
            this.unit = unit || this.unit || (jQuery.cssNumber[this.prop] ? "" : "px");
            this.now = this.start;
            this.pos = this.state = 0;

            function t(gotoEnd) {
                return self.step(gotoEnd)
            }
            t.elem = this.elem;
            if (t() && jQuery.timers.push(t) && !timerId) {
                timerId = setInterval(fx.tick, fx.interval)
            }
        },
        show: function () {
            this.options.orig[this.prop] = jQuery.style(this.elem, this.prop);
            this.options.show = true;
            this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
            jQuery(this.elem).show()
        },
        hide: function () {
            this.options.orig[this.prop] = jQuery.style(this.elem, this.prop);
            this.options.hide = true;
            this.custom(this.cur(), 0)
        },
        step: function (gotoEnd) {
            var t = jQuery.now(),
                done = true;
            if (gotoEnd || t >= this.options.duration + this.startTime) {
                this.now = this.end;
                this.pos = this.state = 1;
                this.update();
                this.options.curAnim[this.prop] = true;
                for (var i in this.options.curAnim) {
                    if (this.options.curAnim[i] !== true) {
                        done = false
                    }
                }
                if (done) {
                    if (this.options.overflow != null && !jQuery.support.shrinkWrapBlocks) {
                        var elem = this.elem,
                            options = this.options;
                        jQuery.each(["", "X", "Y"], function (index, value) {
                            elem.style["overflow" + value] = options.overflow[index]
                        })
                    }
                    if (this.options.hide) {
                        jQuery(this.elem).hide()
                    }
                    if (this.options.hide || this.options.show) {
                        for (var p in this.options.curAnim) {
                            jQuery.style(this.elem, p, this.options.orig[p])
                        }
                    }
                    this.options.complete.call(this.elem)
                }
                return false
            } else {
                var n = t - this.startTime;
                this.state = n / this.options.duration;
                var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
                var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
                this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
                this.now = this.start + ((this.end - this.start) * this.pos);
                this.update()
            }
            return true
        }
    };
    jQuery.extend(jQuery.fx, {
        tick: function () {
            var timers = jQuery.timers;
            for (var i = 0; i < timers.length; i++) {
                if (!timers[i]()) {
                    timers.splice(i--, 1)
                }
            }
            if (!timers.length) {
                jQuery.fx.stop()
            }
        },
        interval: 13,
        stop: function () {
            clearInterval(timerId);
            timerId = null
        },
        speeds: {
            slow: 600,
            fast: 200,
            _default: 400
        },
        step: {
            opacity: function (fx) {
                jQuery.style(fx.elem, "opacity", fx.now)
            },
            _default: function (fx) {
                if (fx.elem.style && fx.elem.style[fx.prop] != null) {
                    fx.elem.style[fx.prop] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit
                } else {
                    fx.elem[fx.prop] = fx.now
                }
            }
        }
    });
    if (jQuery.expr && jQuery.expr.filters) {
        jQuery.expr.filters.animated = function (elem) {
            return jQuery.grep(jQuery.timers, function (fn) {
                return elem === fn.elem
            }).length
        }
    }
    function defaultDisplay(nodeName) {
        if (!elemdisplay[nodeName]) {
            var elem = jQuery("<" + nodeName + ">").appendTo("body"),
                display = elem.css("display");
            elem.remove();
            if (display === "none" || display === "") {
                display = "block"
            }
            elemdisplay[nodeName] = display
        }
        return elemdisplay[nodeName]
    }
    var rtable = /^t(?:able|d|h)$/i,
        rroot = /^(?:body|html)$/i;
    if ("getBoundingClientRect" in document.documentElement) {
        jQuery.fn.offset = function (options) {
            var elem = this[0],
                box;
            if (options) {
                return this.each(function (i) {
                    jQuery.offset.setOffset(this, options, i)
                })
            }
            if (!elem || !elem.ownerDocument) {
                return null
            }
            if (elem === elem.ownerDocument.body) {
                return jQuery.offset.bodyOffset(elem)
            }
            try {
                box = elem.getBoundingClientRect()
            } catch (e) {}
            var doc = elem.ownerDocument,
                docElem = doc.documentElement;
            if (!box || !jQuery.contains(docElem, elem)) {
                return box ? {
                    top: box.top,
                    left: box.left
                } : {
                    top: 0,
                    left: 0
                }
            }
            var body = doc.body,
                win = getWindow(doc),
                clientTop = docElem.clientTop || body.clientTop || 0,
                clientLeft = docElem.clientLeft || body.clientLeft || 0,
                scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop,
                scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
                top = box.top + scrollTop - clientTop,
                left = box.left + scrollLeft - clientLeft;
            return {
                top: top,
                left: left
            }
        }
    } else {
        jQuery.fn.offset = function (options) {
            var elem = this[0];
            if (options) {
                return this.each(function (i) {
                    jQuery.offset.setOffset(this, options, i)
                })
            }
            if (!elem || !elem.ownerDocument) {
                return null
            }
            if (elem === elem.ownerDocument.body) {
                return jQuery.offset.bodyOffset(elem)
            }
            jQuery.offset.initialize();
            var computedStyle, offsetParent = elem.offsetParent,
                prevOffsetParent = elem,
                doc = elem.ownerDocument,
                docElem = doc.documentElement,
                body = doc.body,
                defaultView = doc.defaultView,
                prevComputedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle,
                top = elem.offsetTop,
                left = elem.offsetLeft;
            while ((elem = elem.parentNode) && elem !== body && elem !== docElem) {
                if (jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed") {
                    break
                }
                computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
                top -= elem.scrollTop;
                left -= elem.scrollLeft;
                if (elem === offsetParent) {
                    top += elem.offsetTop;
                    left += elem.offsetLeft;
                    if (jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName))) {
                        top += parseFloat(computedStyle.borderTopWidth) || 0;
                        left += parseFloat(computedStyle.borderLeftWidth) || 0
                    }
                    prevOffsetParent = offsetParent;
                    offsetParent = elem.offsetParent
                }
                if (jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible") {
                    top += parseFloat(computedStyle.borderTopWidth) || 0;
                    left += parseFloat(computedStyle.borderLeftWidth) || 0
                }
                prevComputedStyle = computedStyle
            }
            if (prevComputedStyle.position === "relative" || prevComputedStyle.position === "static") {
                top += body.offsetTop;
                left += body.offsetLeft
            }
            if (jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed") {
                top += Math.max(docElem.scrollTop, body.scrollTop);
                left += Math.max(docElem.scrollLeft, body.scrollLeft)
            }
            return {
                top: top,
                left: left
            }
        }
    }
    jQuery.offset = {
        initialize: function () {
            var body = document.body,
                container = document.createElement("div"),
                innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat(jQuery.css(body, "marginTop")) || 0,
                html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
            jQuery.extend(container.style, {
                position: "absolute",
                top: 0,
                left: 0,
                margin: 0,
                border: 0,
                width: "1px",
                height: "1px",
                visibility: "hidden"
            });
            container.innerHTML = html;
            body.insertBefore(container, body.firstChild);
            innerDiv = container.firstChild;
            checkDiv = innerDiv.firstChild;
            td = innerDiv.nextSibling.firstChild.firstChild;
            this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
            this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
            checkDiv.style.position = "fixed";
            checkDiv.style.top = "20px";
            this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
            checkDiv.style.position = checkDiv.style.top = "";
            innerDiv.style.overflow = "hidden";
            innerDiv.style.position = "relative";
            this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
            this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
            body.removeChild(container);
            jQuery.offset.initialize = jQuery.noop
        },
        bodyOffset: function (body) {
            var top = body.offsetTop,
                left = body.offsetLeft;
            jQuery.offset.initialize();
            if (jQuery.offset.doesNotIncludeMarginInBodyOffset) {
                top += parseFloat(jQuery.css(body, "marginTop")) || 0;
                left += parseFloat(jQuery.css(body, "marginLeft")) || 0
            }
            return {
                top: top,
                left: left
            }
        },
        setOffset: function (elem, options, i) {
            var position = jQuery.css(elem, "position");
            if (position === "static") {
                elem.style.position = "relative"
            }
            var curElem = jQuery(elem),
                curOffset = curElem.offset(),
                curCSSTop = jQuery.css(elem, "top"),
                curCSSLeft = jQuery.css(elem, "left"),
                calculatePosition = (position === "absolute" || position === "fixed") && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1,
                props = {},
                curPosition = {},
                curTop, curLeft;
            if (calculatePosition) {
                curPosition = curElem.position()
            }
            curTop = calculatePosition ? curPosition.top : parseInt(curCSSTop, 10) || 0;
            curLeft = calculatePosition ? curPosition.left : parseInt(curCSSLeft, 10) || 0;
            if (jQuery.isFunction(options)) {
                options = options.call(elem, i, curOffset)
            }
            if (options.top != null) {
                props.top = (options.top - curOffset.top) + curTop
            }
            if (options.left != null) {
                props.left = (options.left - curOffset.left) + curLeft
            }
            if ("using" in options) {
                options.using.call(elem, props)
            } else {
                curElem.css(props)
            }
        }
    };
    jQuery.fn.extend({
        position: function () {
            if (!this[0]) {
                return null
            }
            var elem = this[0],
                offsetParent = this.offsetParent(),
                offset = this.offset(),
                parentOffset = rroot.test(offsetParent[0].nodeName) ? {
                    top: 0,
                    left: 0
                } : offsetParent.offset();
            offset.top -= parseFloat(jQuery.css(elem, "marginTop")) || 0;
            offset.left -= parseFloat(jQuery.css(elem, "marginLeft")) || 0;
            parentOffset.top += parseFloat(jQuery.css(offsetParent[0], "borderTopWidth")) || 0;
            parentOffset.left += parseFloat(jQuery.css(offsetParent[0], "borderLeftWidth")) || 0;
            return {
                top: offset.top - parentOffset.top,
                left: offset.left - parentOffset.left
            }
        },
        offsetParent: function () {
            return this.map(function () {
                var offsetParent = this.offsetParent || document.body;
                while (offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static")) {
                    offsetParent = offsetParent.offsetParent
                }
                return offsetParent
            })
        }
    });
    jQuery.each(["Left", "Top"], function (i, name) {
        var method = "scroll" + name;
        jQuery.fn[method] = function (val) {
            var elem = this[0],
                win;
            if (!elem) {
                return null
            }
            if (val !== undefined) {
                return this.each(function () {
                    win = getWindow(this);
                    if (win) {
                        win.scrollTo(!i ? val : jQuery(win).scrollLeft(), i ? val : jQuery(win).scrollTop())
                    } else {
                        this[method] = val
                    }
                })
            } else {
                win = getWindow(elem);
                return win ? ("pageXOffset" in win) ? win[i ? "pageYOffset" : "pageXOffset"] : jQuery.support.boxModel && win.document.documentElement[method] || win.document.body[method] : elem[method]
            }
        }
    });

    function getWindow(elem) {
        return jQuery.isWindow(elem) ? elem : elem.nodeType === 9 ? elem.defaultView || elem.parentWindow : false
    }
    jQuery.each(["Height", "Width"], function (i, name) {
        var type = name.toLowerCase();
        jQuery.fn["inner" + name] = function () {
            return this[0] ? parseFloat(jQuery.css(this[0], type, "padding")) : null
        };
        jQuery.fn["outer" + name] = function (margin) {
            return this[0] ? parseFloat(jQuery.css(this[0], type, margin ? "margin" : "border")) : null
        };
        jQuery.fn[type] = function (size) {
            var elem = this[0];
            if (!elem) {
                return size == null ? null : this
            }
            if (jQuery.isFunction(size)) {
                return this.each(function (i) {
                    var self = jQuery(this);
                    self[type](size.call(this, i, self[type]()))
                })
            }
            if (jQuery.isWindow(elem)) {
                var docElemProp = elem.document.documentElement["client" + name];
                return elem.document.compatMode === "CSS1Compat" && docElemProp || elem.document.body["client" + name] || docElemProp
            } else if (elem.nodeType === 9) {
                return Math.max(elem.documentElement["client" + name], elem.body["scroll" + name], elem.documentElement["scroll" + name], elem.body["offset" + name], elem.documentElement["offset" + name])
            } else if (size === undefined) {
                var orig = jQuery.css(elem, type),
                    ret = parseFloat(orig);
                return jQuery.isNaN(ret) ? orig : ret
            } else {
                return this.css(type, typeof size === "string" ? size : size + "px")
            }
        }
    });
    window.jQuery = window.$ = jQuery
})(window);
(function () {
    this.MooTools = {
        version: '1.3.1',
        build: 'af48c8d589f43f32212f9bb8ff68a127e6a3ba6c'
    };
    var typeOf = this.typeOf = function (item) {
            if (item == null) return 'null';
            if (item.$family) return item.$family();
            if (item.nodeName) {
                if (item.nodeType == 1) return 'element';
                if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace'
            } else if (typeof item.length == 'number') {
                if (item.callee) return 'arguments';
                if ('item' in item) return 'collection'
            }
            return typeof item
        };
    var instanceOf = this.instanceOf = function (item, object) {
            if (item == null) return false;
            var constructor = item.$constructor || item.constructor;
            while (constructor) {
                if (constructor === object) return true;
                constructor = constructor.parent
            }
            return item instanceof object
        };
    var Function = this.Function;
    var enumerables = true;
    for (var i in {
        toString: 1
    }) enumerables = null;
    if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'];
    Function.prototype.overloadSetter = function (usePlural) {
        var self = this;
        return function (a, b) {
            if (a == null) return this;
            if (usePlural || typeof a != 'string') {
                for (var k in a) self.call(this, k, a[k]);
                if (enumerables) for (var i = enumerables.length; i--;) {
                    k = enumerables[i];
                    if (a.hasOwnProperty(k)) self.call(this, k, a[k])
                }
            } else {
                self.call(this, a, b)
            }
            return this
        }
    };
    Function.prototype.overloadGetter = function (usePlural) {
        var self = this;
        return function (a) {
            var args, result;
            if (usePlural || typeof a != 'string') args = a;
            else if (arguments.length > 1) args = arguments;
            if (args) {
                result = {};
                for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i])
            } else {
                result = self.call(this, a)
            }
            return result
        }
    };
    Function.prototype.extend = function (key, value) {
        this[key] = value
    }.overloadSetter();
    Function.prototype.implement = function (key, value) {
        this.prototype[key] = value
    }.overloadSetter();
    var slice = Array.prototype.slice;
    Function.from = function (item) {
        return (typeOf(item) == 'function') ? item : function () {
            return item
        }
    };
    Array.from = function (item) {
        if (item == null) return [];
        return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item]
    };
    Number.from = function (item) {
        var number = parseFloat(item);
        return isFinite(number) ? number : null
    };
    String.from = function (item) {
        return item + ''
    };
    Function.implement({
        hide: function () {
            this.$hidden = true;
            return this
        },
        protect: function () {
            this.$protected = true;
            return this
        }
    });
    var Type = this.Type = function (name, object) {
            if (name) {
                var lower = name.toLowerCase();
                var typeCheck = function (item) {
                        return (typeOf(item) == lower)
                    };
                Type['is' + name] = typeCheck;
                if (object != null) {
                    object.prototype.$family = (function () {
                        return lower
                    }).hide();
                    object.type = typeCheck
                }
            }
            if (object == null) return null;
            object.extend(this);
            object.$constructor = Type;
            object.prototype.$constructor = object;
            return object
        };
    var toString = Object.prototype.toString;
    Type.isEnumerable = function (item) {
        return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]')
    };
    var hooks = {};
    var hooksOf = function (object) {
            var type = typeOf(object.prototype);
            return hooks[type] || (hooks[type] = [])
        };
    var implement = function (name, method) {
            if (method && method.$hidden) return;
            var hooks = hooksOf(this);
            for (var i = 0; i < hooks.length; i++) {
                var hook = hooks[i];
                if (typeOf(hook) == 'type') implement.call(hook, name, method);
                else hook.call(this, name, method)
            }
            var previous = this.prototype[name];
            if (previous == null || !previous.$protected) this.prototype[name] = method;
            if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function (item) {
                return method.apply(item, slice.call(arguments, 1))
            })
        };
    var extend = function (name, method) {
            if (method && method.$hidden) return;
            var previous = this[name];
            if (previous == null || !previous.$protected) this[name] = method
        };
    Type.implement({
        implement: implement.overloadSetter(),
        extend: extend.overloadSetter(),
        alias: function (name, existing) {
            implement.call(this, name, this.prototype[existing])
        }.overloadSetter(),
        mirror: function (hook) {
            hooksOf(this).push(hook);
            return this
        }
    });
    new Type('Type', Type);
    var force = function (name, object, methods) {
            var isType = (object != Object),
                prototype = object.prototype;
            if (isType) object = new Type(name, object);
            for (var i = 0, l = methods.length; i < l; i++) {
                var key = methods[i],
                    generic = object[key],
                    proto = prototype[key];
                if (generic) generic.protect();
                if (isType && proto) {
                    delete prototype[key];
                    prototype[key] = proto.protect()
                }
            }
            if (isType) object.implement(prototype);
            return force
        };
    force('String', String, ['charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search', 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase'])('Array', Array, ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', 'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight'])('Number', Number, ['toExponential', 'toFixed', 'toLocaleString', 'toPrecision'])('Function', Function, ['apply', 'call', 'bind'])('RegExp', RegExp, ['exec', 'test'])('Object', Object, ['create', 'defineProperty', 'defineProperties', 'keys', 'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', 'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen'])('Date', Date, ['now']);
    Object.extend = extend.overloadSetter();
    Date.extend('now', function () {
        return +(new Date)
    });
    new Type('Boolean', Boolean);
    Number.prototype.$family = function () {
        return isFinite(this) ? 'number' : 'null'
    }.hide();
    Number.extend('random', function (min, max) {
        return Math.floor(Math.random() * (max - min + 1) + min)
    });
    var hasOwnProperty = Object.prototype.hasOwnProperty;
    Object.extend('forEach', function (object, fn, bind) {
        for (var key in object) {
            if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object)
        }
    });
    Object.each = Object.forEach;
    Array.implement({
        forEach: function (fn, bind) {
            for (var i = 0, l = this.length; i < l; i++) {
                if (i in this) fn.call(bind, this[i], i, this)
            }
        },
        each: function (fn, bind) {
            Array.forEach(this, fn, bind);
            return this
        }
    });
    var cloneOf = function (item) {
            switch (typeOf(item)) {
            case 'array':
                return item.clone();
            case 'object':
                return Object.clone(item);
            default:
                return item
            }
        };
    Array.implement('clone', function () {
        var i = this.length,
            clone = new Array(i);
        while (i--) clone[i] = cloneOf(this[i]);
        return clone
    });
    var mergeOne = function (source, key, current) {
            switch (typeOf(current)) {
            case 'object':
                if (typeOf(source[key]) == 'object') Object.merge(source[key], current);
                else source[key] = Object.clone(current);
                break;
            case 'array':
                source[key] = current.clone();
                break;
            default:
                source[key] = current
            }
            return source
        };
    Object.extend({
        merge: function (source, k, v) {
            if (typeOf(k) == 'string') return mergeOne(source, k, v);
            for (var i = 1, l = arguments.length; i < l; i++) {
                var object = arguments[i];
                for (var key in object) mergeOne(source, key, object[key])
            }
            return source
        },
        clone: function (object) {
            var clone = {};
            for (var key in object) clone[key] = cloneOf(object[key]);
            return clone
        },
        append: function (original) {
            for (var i = 1, l = arguments.length; i < l; i++) {
                var extended = arguments[i] || {};
                for (var key in extended) original[key] = extended[key]
            }
            return original
        }
    });
    ['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function (name) {
        new Type(name)
    });
    var UID = Date.now();
    String.extend('uniqueID', function () {
        return (UID++).toString(36)
    });
    var Hash = this.Hash = new Type('Hash', function (object) {
        if (typeOf(object) == 'hash') object = Object.clone(object.getClean());
        for (var key in object) this[key] = object[key];
        return this
    });
    Hash.implement({
        forEach: function (fn, bind) {
            Object.forEach(this, fn, bind)
        },
        getClean: function () {
            var clean = {};
            for (var key in this) {
                if (this.hasOwnProperty(key)) clean[key] = this[key]
            }
            return clean
        },
        getLength: function () {
            var length = 0;
            for (var key in this) {
                if (this.hasOwnProperty(key)) length++
            }
            return length
        }
    });
    Hash.alias('each', 'forEach');
    Object.type = Type.isObject;
    var Native = this.Native = function (properties) {
            return new Type(properties.name, properties.initialize)
        };
    Native.type = Type.type;
    Native.implement = function (objects, methods) {
        for (var i = 0; i < objects.length; i++) objects[i].implement(methods);
        return Native
    };
    var arrayType = Array.type;
    Array.type = function (item) {
        return instanceOf(item, Array) || arrayType(item)
    };
    this.$A = function (item) {
        return Array.from(item).slice()
    };
    this.$arguments = function (i) {
        return function () {
            return arguments[i]
        }
    };
    this.$chk = function (obj) {
        return !!(obj || obj === 0)
    };
    this.$clear = function (timer) {
        clearTimeout(timer);
        clearInterval(timer);
        return null
    };
    this.$defined = function (obj) {
        return (obj != null)
    };
    this.$each = function (iterable, fn, bind) {
        var type = typeOf(iterable);
        ((type == 'arguments' || type == 'collection' || type == 'array' || type == 'elements') ? Array : Object).each(iterable, fn, bind)
    };
    this.$empty = function () {};
    this.$extend = function (original, extended) {
        return Object.append(original, extended)
    };
    this.$H = function (object) {
        return new Hash(object)
    };
    this.$merge = function () {
        var args = Array.slice(arguments);
        args.unshift({});
        return Object.merge.apply(null, args)
    };
    this.$lambda = Function.from;
    this.$mixin = Object.merge;
    this.$random = Number.random;
    this.$splat = Array.from;
    this.$time = Date.now;
    this.$type = function (object) {
        var type = typeOf(object);
        if (type == 'elements') return 'array';
        return (type == 'null') ? false : type
    };
    this.$unlink = function (object) {
        switch (typeOf(object)) {
        case 'object':
            return Object.clone(object);
        case 'array':
            return Array.clone(object);
        case 'hash':
            return new Hash(object);
        default:
            return object
        }
    }
}).call(this);
Array.implement({
    invoke: function (methodName) {
        var args = Array.slice(arguments, 1);
        return this.map(function (item) {
            return item[methodName].apply(item, args)
        })
    },
    every: function (fn, bind) {
        for (var i = 0, l = this.length; i < l; i++) {
            if ((i in this) && !fn.call(bind, this[i], i, this)) return false
        }
        return true
    },
    filter: function (fn, bind) {
        var results = [];
        for (var i = 0, l = this.length; i < l; i++) {
            if ((i in this) && fn.call(bind, this[i], i, this)) results.push(this[i])
        }
        return results
    },
    clean: function () {
        return this.filter(function (item) {
            return item != null
        })
    },
    indexOf: function (item, from) {
        var len = this.length;
        for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++) {
            if (this[i] === item) return i
        }
        return -1
    },
    map: function (fn, bind) {
        var results = [];
        for (var i = 0, l = this.length; i < l; i++) {
            if (i in this) results[i] = fn.call(bind, this[i], i, this)
        }
        return results
    },
    some: function (fn, bind) {
        for (var i = 0, l = this.length; i < l; i++) {
            if ((i in this) && fn.call(bind, this[i], i, this)) return true
        }
        return false
    },
    associate: function (keys) {
        var obj = {},
            length = Math.min(this.length, keys.length);
        for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
        return obj
    },
    link: function (object) {
        var result = {};
        for (var i = 0, l = this.length; i < l; i++) {
            for (var key in object) {
                if (object[key](this[i])) {
                    result[key] = this[i];
                    delete object[key];
                    break
                }
            }
        }
        return result
    },
    contains: function (item, from) {
        return this.indexOf(item, from) != -1
    },
    append: function (array) {
        this.push.apply(this, array);
        return this
    },
    getLast: function () {
        return (this.length) ? this[this.length - 1] : null
    },
    getRandom: function () {
        return (this.length) ? this[Number.random(0, this.length - 1)] : null
    },
    include: function (item) {
        if (!this.contains(item)) this.push(item);
        return this
    },
    combine: function (array) {
        for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
        return this
    },
    erase: function (item) {
        for (var i = this.length; i--;) {
            if (this[i] === item) this.splice(i, 1)
        }
        return this
    },
    empty: function () {
        this.length = 0;
        return this
    },
    flatten: function () {
        var array = [];
        for (var i = 0, l = this.length; i < l; i++) {
            var type = typeOf(this[i]);
            if (type == 'null') continue;
            array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i])
        }
        return array
    },
    pick: function () {
        for (var i = 0, l = this.length; i < l; i++) {
            if (this[i] != null) return this[i]
        }
        return null
    },
    hexToRgb: function (array) {
        if (this.length != 3) return null;
        var rgb = this.map(function (value) {
            if (value.length == 1) value += value;
            return value.toInt(16)
        });
        return (array) ? rgb : 'rgb(' + rgb + ')'
    },
    rgbToHex: function (array) {
        if (this.length < 3) return null;
        if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
        var hex = [];
        for (var i = 0; i < 3; i++) {
            var bit = (this[i] - 0).toString(16);
            hex.push((bit.length == 1) ? '0' + bit : bit)
        }
        return (array) ? hex : '#' + hex.join('')
    }
});
Array.alias('extend', 'append');
var $pick = function () {
        return Array.from(arguments).pick()
    };
String.implement({
    test: function (regex, params) {
        return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this)
    },
    contains: function (string, separator) {
        return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1
    },
    trim: function () {
        return this.replace(/^\s+|\s+$/g, '')
    },
    clean: function () {
        return this.replace(/\s+/g, ' ').trim()
    },
    camelCase: function () {
        return this.replace(/-\D/g, function (match) {
            return match.charAt(1).toUpperCase()
        })
    },
    hyphenate: function () {
        return this.replace(/[A-Z]/g, function (match) {
            return ('-' + match.charAt(0).toLowerCase())
        })
    },
    capitalize: function () {
        return this.replace(/\b[a-z]/g, function (match) {
            return match.toUpperCase()
        })
    },
    escapeRegExp: function () {
        return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1')
    },
    toInt: function (base) {
        return parseInt(this, base || 10)
    },
    toFloat: function () {
        return parseFloat(this)
    },
    hexToRgb: function (array) {
        var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
        return (hex) ? hex.slice(1).hexToRgb(array) : null
    },
    rgbToHex: function (array) {
        var rgb = this.match(/\d{1,3}/g);
        return (rgb) ? rgb.rgbToHex(array) : null
    },
    substitute: function (object, regexp) {
        return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function (match, name) {
            if (match.charAt(0) == '\\') return match.slice(1);
            return (object[name] != null) ? object[name] : ''
        })
    }
});
Number.implement({
    limit: function (min, max) {
        return Math.min(max, Math.max(min, this))
    },
    round: function (precision) {
        precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0);
        return Math.round(this * precision) / precision
    },
    times: function (fn, bind) {
        for (var i = 0; i < this; i++) fn.call(bind, i, this)
    },
    toFloat: function () {
        return parseFloat(this)
    },
    toInt: function (base) {
        return parseInt(this, base || 10)
    }
});
Number.alias('each', 'times');
(function (math) {
    var methods = {};
    math.each(function (name) {
        if (!Number[name]) methods[name] = function () {
            return Math[name].apply(null, [this].concat(Array.from(arguments)))
        }
    });
    Number.implement(methods)
})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);
Function.extend({
    attempt: function () {
        for (var i = 0, l = arguments.length; i < l; i++) {
            try {
                return arguments[i]()
            } catch (e) {}
        }
        return null
    }
});
Function.implement({
    attempt: function (args, bind) {
        try {
            return this.apply(bind, Array.from(args))
        } catch (e) {}
        return null
    },
    bind: function (bind) {
        var self = this,
            args = (arguments.length > 1) ? Array.slice(arguments, 1) : null;
        return function () {
            if (!args && !arguments.length) return self.call(bind);
            if (args && arguments.length) return self.apply(bind, args.concat(Array.from(arguments)));
            return self.apply(bind, args || arguments)
        }
    },
    pass: function (args, bind) {
        var self = this;
        if (args != null) args = Array.from(args);
        return function () {
            return self.apply(bind, args || arguments)
        }
    },
    delay: function (delay, bind, args) {
        return setTimeout(this.pass((args == null ? [] : args), bind), delay)
    },
    periodical: function (periodical, bind, args) {
        return setInterval(this.pass((args == null ? [] : args), bind), periodical)
    }
});
delete Function.prototype.bind;
Function.implement({
    create: function (options) {
        var self = this;
        options = options || {};
        return function (event) {
            var args = options.arguments;
            args = (args != null) ? Array.from(args) : Array.slice(arguments, (options.event) ? 1 : 0);
            if (options.event) args = [event || window.event].extend(args);
            var returns = function () {
                    return self.apply(options.bind || null, args)
                };
            if (options.delay) return setTimeout(returns, options.delay);
            if (options.periodical) return setInterval(returns, options.periodical);
            if (options.attempt) return Function.attempt(returns);
            return returns()
        }
    },
    bind: function (bind, args) {
        var self = this;
        if (args != null) args = Array.from(args);
        return function () {
            return self.apply(bind, args || arguments)
        }
    },
    bindWithEvent: function (bind, args) {
        var self = this;
        if (args != null) args = Array.from(args);
        return function (event) {
            return self.apply(bind, (args == null) ? arguments : [event].concat(args))
        }
    },
    run: function (args, bind) {
        return this.apply(bind, Array.from(args))
    }
});
var $try = Function.attempt;
(function () {
    var hasOwnProperty = Object.prototype.hasOwnProperty;
    Object.extend({
        subset: function (object, keys) {
            var results = {};
            for (var i = 0, l = keys.length; i < l; i++) {
                var k = keys[i];
                results[k] = object[k]
            }
            return results
        },
        map: function (object, fn, bind) {
            var results = {};
            for (var key in object) {
                if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object)
            }
            return results
        },
        filter: function (object, fn, bind) {
            var results = {};
            Object.each(object, function (value, key) {
                if (fn.call(bind, value, key, object)) results[key] = value
            });
            return results
        },
        every: function (object, fn, bind) {
            for (var key in object) {
                if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false
            }
            return true
        },
        some: function (object, fn, bind) {
            for (var key in object) {
                if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true
            }
            return false
        },
        keys: function (object) {
            var keys = [];
            for (var key in object) {
                if (hasOwnProperty.call(object, key)) keys.push(key)
            }
            return keys
        },
        values: function (object) {
            var values = [];
            for (var key in object) {
                if (hasOwnProperty.call(object, key)) values.push(object[key])
            }
            return values
        },
        getLength: function (object) {
            return Object.keys(object).length
        },
        keyOf: function (object, value) {
            for (var key in object) {
                if (hasOwnProperty.call(object, key) && object[key] === value) return key
            }
            return null
        },
        contains: function (object, value) {
            return Object.keyOf(object, value) != null
        },
        toQueryString: function (object, base) {
            var queryString = [];
            Object.each(object, function (value, key) {
                if (base) key = base + '[' + key + ']';
                var result;
                switch (typeOf(value)) {
                case 'object':
                    result = Object.toQueryString(value, key);
                    break;
                case 'array':
                    var qs = {};
                    value.each(function (val, i) {
                        qs[i] = val
                    });
                    result = Object.toQueryString(qs, key);
                    break;
                default:
                    result = key + '=' + encodeURIComponent(value)
                }
                if (value != null) queryString.push(result)
            });
            return queryString.join('&')
        }
    })
})();
Hash.implement({
    has: Object.prototype.hasOwnProperty,
    keyOf: function (value) {
        return Object.keyOf(this, value)
    },
    hasValue: function (value) {
        return Object.contains(this, value)
    },
    extend: function (properties) {
        Hash.each(properties || {}, function (value, key) {
            Hash.set(this, key, value)
        }, this);
        return this
    },
    combine: function (properties) {
        Hash.each(properties || {}, function (value, key) {
            Hash.include(this, key, value)
        }, this);
        return this
    },
    erase: function (key) {
        if (this.hasOwnProperty(key)) delete this[key];
        return this
    },
    get: function (key) {
        return (this.hasOwnProperty(key)) ? this[key] : null
    },
    set: function (key, value) {
        if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
        return this
    },
    empty: function () {
        Hash.each(this, function (value, key) {
            delete this[key]
        }, this);
        return this
    },
    include: function (key, value) {
        if (this[key] == null) this[key] = value;
        return this
    },
    map: function (fn, bind) {
        return new Hash(Object.map(this, fn, bind))
    },
    filter: function (fn, bind) {
        return new Hash(Object.filter(this, fn, bind))
    },
    every: function (fn, bind) {
        return Object.every(this, fn, bind)
    },
    some: function (fn, bind) {
        return Object.some(this, fn, bind)
    },
    getKeys: function () {
        return Object.keys(this)
    },
    getValues: function () {
        return Object.values(this)
    },
    toQueryString: function (base) {
        return Object.toQueryString(this, base)
    }
});
Hash.extend = Object.append;
Hash.alias({
    indexOf: 'keyOf',
    contains: 'hasValue'
});
(function () {
    var document = this.document;
    var window = document.window = this;
    var UID = 1;
    this.$uid = (window.ActiveXObject) ?
    function (item) {
        return (item.uid || (item.uid = [UID++]))[0]
    } : function (item) {
        return item.uid || (item.uid = UID++)
    };
    $uid(window);
    $uid(document);
    var ua = navigator.userAgent.toLowerCase(),
        platform = navigator.platform.toLowerCase(),
        UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0],
        mode = UA[1] == 'ie' && document.documentMode;
    var Browser = this.Browser = {
        extend: Function.prototype.extend,
        name: (UA[1] == 'version') ? UA[3] : UA[1],
        version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]),
        Platform: {
            name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0]
        },
        Features: {
            xpath: !! (document.evaluate),
            air: !! (window.runtime),
            query: !! (document.querySelector),
            json: !! (window.JSON)
        },
        Plugins: {}
    };
    Browser[Browser.name] = true;
    Browser[Browser.name + parseInt(Browser.version, 10)] = true;
    Browser.Platform[Browser.Platform.name] = true;
    Browser.Request = (function () {
        var XMLHTTP = function () {
                return new XMLHttpRequest()
            };
        var MSXML2 = function () {
                return new ActiveXObject('MSXML2.XMLHTTP')
            };
        var MSXML = function () {
                return new ActiveXObject('Microsoft.XMLHTTP')
            };
        return Function.attempt(function () {
            XMLHTTP();
            return XMLHTTP
        }, function () {
            MSXML2();
            return MSXML2
        }, function () {
            MSXML();
            return MSXML
        })
    })();
    Browser.Features.xhr = !! (Browser.Request);
    var version = (Function.attempt(function () {
        return navigator.plugins['Shockwave Flash'].description
    }, function () {
        return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version')
    }) || '0 r0').match(/\d+/g);
    Browser.Plugins.Flash = {
        version: Number(version[0] || '0.' + version[1]) || 0,
        build: Number(version[2]) || 0
    };
    Browser.exec = function (text) {
        if (!text) return text;
        if (window.execScript) {
            window.execScript(text)
        } else {
            var script = document.createElement('script');
            script.setAttribute('type', 'text/javascript');
            script.text = text;
            document.head.appendChild(script);
            document.head.removeChild(script)
        }
        return text
    };
    String.implement('stripScripts', function (exec) {
        var scripts = '';
        var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function (all, code) {
            scripts += code + '\n';
            return ''
        });
        if (exec === true) Browser.exec(scripts);
        else if (typeOf(exec) == 'function') exec(scripts, text);
        return text
    });
    Browser.extend({
        Document: this.Document,
        Window: this.Window,
        Element: this.Element,
        Event: this.Event
    });
    this.Window = this.$constructor = new Type('Window', function () {});
    this.$family = Function.from('window').hide();
    Window.mirror(function (name, method) {
        window[name] = method
    });
    this.Document = document.$constructor = new Type('Document', function () {});
    document.$family = Function.from('document').hide();
    Document.mirror(function (name, method) {
        document[name] = method
    });
    document.html = document.documentElement;
    document.head = document.getElementsByTagName('head')[0];
    if (document.execCommand) try {
        document.execCommand("BackgroundImageCache", false, true)
    } catch (e) {}
    if (this.attachEvent && !this.addEventListener) {
        var unloadEvent = function () {
                this.detachEvent('onunload', unloadEvent);
                document.head = document.html = document.window = null
            };
        this.attachEvent('onunload', unloadEvent)
    }
    var arrayFrom = Array.from;
    try {
        arrayFrom(document.html.childNodes)
    } catch (e) {
        Array.from = function (item) {
            if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array') {
                var i = item.length,
                    array = new Array(i);
                while (i--) array[i] = item[i];
                return array
            }
            return arrayFrom(item)
        };
        var prototype = Array.prototype,
            slice = prototype.slice;
        ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function (name) {
            var method = prototype[name];
            Array[name] = function (item) {
                return method.apply(Array.from(item), slice.call(arguments, 1))
            }
        })
    }
    if (Browser.Platform.ios) Browser.Platform.ipod = true;
    Browser.Engine = {};
    var setEngine = function (name, version) {
            Browser.Engine.name = name;
            Browser.Engine[name + version] = true;
            Browser.Engine.version = version
        };
    if (Browser.ie) {
        Browser.Engine.trident = true;
        switch (Browser.version) {
        case 6:
            setEngine('trident', 4);
            break;
        case 7:
            setEngine('trident', 5);
            break;
        case 8:
            setEngine('trident', 6)
        }
    }
    if (Browser.firefox) {
        Browser.Engine.gecko = true;
        if (Browser.version >= 3) setEngine('gecko', 19);
        else setEngine('gecko', 18)
    }
    if (Browser.safari || Browser.chrome) {
        Browser.Engine.webkit = true;
        switch (Browser.version) {
        case 2:
            setEngine('webkit', 419);
            break;
        case 3:
            setEngine('webkit', 420);
            break;
        case 4:
            setEngine('webkit', 525)
        }
    }
    if (Browser.opera) {
        Browser.Engine.presto = true;
        if (Browser.version >= 9.6) setEngine('presto', 960);
        else if (Browser.version >= 9.5) setEngine('presto', 950);
        else setEngine('presto', 925)
    }
    if (Browser.name == 'unknown') {
        switch ((ua.match(/(?:webkit|khtml|gecko)/) || [])[0]) {
        case 'webkit':
        case 'khtml':
            Browser.Engine.webkit = true;
            break;
        case 'gecko':
            Browser.Engine.gecko = true
        }
    }
    this.$exec = Browser.exec
}).call(this);
var Event = new Type('Event', function (event, win) {
    if (!win) win = window;
    var doc = win.document;
    event = event || win.event;
    if (event.$extended) return event;
    this.$extended = true;
    var type = event.type,
        target = event.target || event.srcElement,
        page = {},
        client = {},
        related = null,
        rightClick, wheel, code, key;
    while (target && target.nodeType == 3) target = target.parentNode;
    if (type.indexOf('key') != -1) {
        code = event.which || event.keyCode;
        key = Object.keyOf(Event.Keys, code);
        if (type == 'keydown') {
            var fKey = code - 111;
            if (fKey > 0 && fKey < 13) key = 'f' + fKey
        }
        if (!key) key = String.fromCharCode(code).toLowerCase()
    } else if ((/click|mouse|menu/i).test(type)) {
        doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
        page = {
            x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft,
            y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop
        };
        client = {
            x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX,
            y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY
        };
        if ((/DOMMouseScroll|mousewheel/).test(type)) {
            wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3
        }
        rightClick = (event.which == 3) || (event.button == 2);
        if ((/over|out/).test(type)) {
            related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element'];
            var testRelated = function () {
                    while (related && related.nodeType == 3) related = related.parentNode;
                    return true
                };
            var hasRelated = (Browser.firefox2) ? testRelated.attempt() : testRelated();
            related = (hasRelated) ? related : null
        }
    } else if ((/gesture|touch/i).test(type)) {
        this.rotation = event.rotation;
        this.scale = event.scale;
        this.targetTouches = event.targetTouches;
        this.changedTouches = event.changedTouches;
        var touches = this.touches = event.touches;
        if (touches && touches[0]) {
            var touch = touches[0];
            page = {
                x: touch.pageX,
                y: touch.pageY
            };
            client = {
                x: touch.clientX,
                y: touch.clientY
            }
        }
    }
    return Object.append(this, {
        event: event,
        type: type,
        page: page,
        client: client,
        rightClick: rightClick,
        wheel: wheel,
        relatedTarget: document.id(related),
        target: document.id(target),
        code: code,
        key: key,
        shift: event.shiftKey,
        control: event.ctrlKey,
        alt: event.altKey,
        meta: event.metaKey
    })
});
Event.Keys = {
    'enter': 13,
    'up': 38,
    'down': 40,
    'left': 37,
    'right': 39,
    'esc': 27,
    'space': 32,
    'backspace': 8,
    'tab': 9,
    'delete': 46
};
Event.Keys = new Hash(Event.Keys);
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
    }
});
(function () {
    var Class = this.Class = new Type('Class', function (params) {
        if (instanceOf(params, Function)) params = {
            initialize: params
        };
        var newClass = function () {
                reset(this);
                if (newClass.$prototyping) return this;
                this.$caller = null;
                var value = (this.initialize) ? this.initialize.apply(this, arguments) : this;
                this.$caller = this.caller = null;
                return value
            }.extend(this).implement(params);
        newClass.$constructor = Class;
        newClass.prototype.$constructor = newClass;
        newClass.prototype.parent = parent;
        return newClass
    });
    var parent = function () {
            if (!this.$caller) throw new Error('The method "parent" cannot be called.');
            var name = this.$caller.$name,
                parent = this.$caller.$owner.parent,
                previous = (parent) ? parent.prototype[name] : null;
            if (!previous) throw new Error('The method "' + name + '" has no parent.');
            return previous.apply(this, arguments)
        };
    var reset = function (object) {
            for (var key in object) {
                var value = object[key];
                switch (typeOf(value)) {
                case 'object':
                    var F = function () {};
                    F.prototype = value;
                    object[key] = reset(new F);
                    break;
                case 'array':
                    object[key] = value.clone();
                    break
                }
            }
            return object
        };
    var wrap = function (self, key, method) {
            if (method.$origin) method = method.$origin;
            var wrapper = function () {
                    if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.');
                    var caller = this.caller,
                        current = this.$caller;
                    this.caller = current;
                    this.$caller = wrapper;
                    var result = method.apply(this, arguments);
                    this.$caller = current;
                    this.caller = caller;
                    return result
                }.extend({
                    $owner: self,
                    $origin: method,
                    $name: key
                });
            return wrapper
        };
    var implement = function (key, value, retain) {
            if (Class.Mutators.hasOwnProperty(key)) {
                value = Class.Mutators[key].call(this, value);
                if (value == null) return this
            }
            if (typeOf(value) == 'function') {
                if (value.$hidden) return this;
                this.prototype[key] = (retain) ? value : wrap(this, key, value)
            } else {
                Object.merge(this.prototype, key, value)
            }
            return this
        };
    var getInstance = function (klass) {
            klass.$prototyping = true;
            var proto = new klass;
            delete klass.$prototyping;
            return proto
        };
    Class.implement('implement', implement.overloadSetter());
    Class.Mutators = {
        Extends: function (parent) {
            this.parent = parent;
            this.prototype = getInstance(parent)
        },
        Implements: function (items) {
            Array.from(items).each(function (item) {
                var instance = new item;
                for (var key in instance) implement.call(this, key, instance[key], true)
            }, this)
        }
    }
}).call(this);
(function () {
    this.Chain = new Class({
        $chain: [],
        chain: function () {
            this.$chain.append(Array.flatten(arguments));
            return this
        },
        callChain: function () {
            return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false
        },
        clearChain: function () {
            this.$chain.empty();
            return this
        }
    });
    var removeOn = function (string) {
            return string.replace(/^on([A-Z])/, function (full, first) {
                return first.toLowerCase()
            })
        };
    this.Events = new Class({
        $events: {},
        addEvent: function (type, fn, internal) {
            type = removeOn(type);
            if (fn == $empty) return this;
            this.$events[type] = (this.$events[type] || []).include(fn);
            if (internal) fn.internal = true;
            return this
        },
        addEvents: function (events) {
            for (var type in events) this.addEvent(type, events[type]);
            return this
        },
        fireEvent: function (type, args, delay) {
            type = removeOn(type);
            var events = this.$events[type];
            if (!events) return this;
            args = Array.from(args);
            events.each(function (fn) {
                if (delay) fn.delay(delay, this, args);
                else fn.apply(this, args)
            }, this);
            return this
        },
        removeEvent: function (type, fn) {
            type = removeOn(type);
            var events = this.$events[type];
            if (events && !fn.internal) {
                var index = events.indexOf(fn);
                if (index != -1) delete events[index]
            }
            return this
        },
        removeEvents: function (events) {
            var type;
            if (typeOf(events) == 'object') {
                for (type in events) this.removeEvent(type, events[type]);
                return this
            }
            if (events) events = removeOn(events);
            for (type in this.$events) {
                if (events && events != type) continue;
                var fns = this.$events[type];
                for (var i = fns.length; i--;) if (i in fns) {
                    this.removeEvent(type, fns[i])
                }
            }
            return this
        }
    });
    this.Options = new Class({
        setOptions: function () {
            var options = this.options = Object.merge.apply(null, [{},
            this.options].append(arguments));
            if (this.addEvent) for (var option in options) {
                if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
                this.addEvent(option, options[option]);
                delete options[option]
            }
            return this
        }
    })
}).call(this);
(function () {
    var parsed, separatorIndex, combinatorIndex, reversed, cache = {},
        reverseCache = {},
        reUnescape = /\\/g;
    var parse = function (expression, isReversed) {
            if (expression == null) return null;
            if (expression.Slick === true) return expression;
            expression = ('' + expression).replace(/^\s+|\s+$/g, '');
            reversed = !! isReversed;
            var currentCache = (reversed) ? reverseCache : cache;
            if (currentCache[expression]) return currentCache[expression];
            parsed = {
                Slick: true,
                expressions: [],
                raw: expression,
                reverse: function () {
                    return parse(this.raw, true)
                }
            };
            separatorIndex = -1;
            while (expression != (expression = expression.replace(regexp, parser)));
            parsed.length = parsed.expressions.length;
            return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed
        };
    var reverseCombinator = function (combinator) {
            if (combinator === '!') return ' ';
            else if (combinator === ' ') return '!';
            else if ((/^!/).test(combinator)) return combinator.replace(/^!/, '');
            else return '!' + combinator
        };
    var reverse = function (expression) {
            var expressions = expression.expressions;
            for (var i = 0; i < expressions.length; i++) {
                var exp = expressions[i];
                var last = {
                    parts: [],
                    tag: '*',
                    combinator: reverseCombinator(exp[0].combinator)
                };
                for (var j = 0; j < exp.length; j++) {
                    var cexp = exp[j];
                    if (!cexp.reverseCombinator) cexp.reverseCombinator = ' ';
                    cexp.combinator = cexp.reverseCombinator;
                    delete cexp.reverseCombinator
                }
                exp.reverse().push(last)
            }
            return expression
        };
    var escapeRegExp = function (string) {
            return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function (match) {
                return '\\' + match
            })
        };
    var regexp = new RegExp("^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)".replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']').replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])').replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])'));

    function parser(rawMatch, separator, combinator, combinatorChildren, tagName, id, className, attributeKey, attributeOperator, attributeQuote, attributeValue, pseudoMarker, pseudoClass, pseudoQuote, pseudoClassQuotedValue, pseudoClassValue) {
        if (separator || separatorIndex === -1) {
            parsed.expressions[++separatorIndex] = [];
            combinatorIndex = -1;
            if (separator) return ''
        }
        if (combinator || combinatorChildren || combinatorIndex === -1) {
            combinator = combinator || ' ';
            var currentSeparator = parsed.expressions[separatorIndex];
            if (reversed && currentSeparator[combinatorIndex]) currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator);
            currentSeparator[++combinatorIndex] = {
                combinator: combinator,
                tag: '*'
            }
        }
        var currentParsed = parsed.expressions[separatorIndex][combinatorIndex];
        if (tagName) {
            currentParsed.tag = tagName.replace(reUnescape, '')
        } else if (id) {
            currentParsed.id = id.replace(reUnescape, '')
        } else if (className) {
            className = className.replace(reUnescape, '');
            if (!currentParsed.classList) currentParsed.classList = [];
            if (!currentParsed.classes) currentParsed.classes = [];
            currentParsed.classList.push(className);
            currentParsed.classes.push({
                value: className,
                regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)')
            })
        } else if (pseudoClass) {
            pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue;
            pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null;
            if (!currentParsed.pseudos) currentParsed.pseudos = [];
            currentParsed.pseudos.push({
                key: pseudoClass.replace(reUnescape, ''),
                value: pseudoClassValue,
                type: pseudoMarker.length == 1 ? 'class' : 'element'
            })
        } else if (attributeKey) {
            attributeKey = attributeKey.replace(reUnescape, '');
            attributeValue = (attributeValue || '').replace(reUnescape, '');
            var test, regexp;
            switch (attributeOperator) {
            case '^=':
                regexp = new RegExp('^' + escapeRegExp(attributeValue));
                break;
            case '$=':
                regexp = new RegExp(escapeRegExp(attributeValue) + '$');
                break;
            case '~=':
                regexp = new RegExp('(^|\\s)' + escapeRegExp(attributeValue) + '(\\s|$)');
                break;
            case '|=':
                regexp = new RegExp('^' + escapeRegExp(attributeValue) + '(-|$)');
                break;
            case '=':
                test = function (value) {
                    return attributeValue == value
                };
                break;
            case '*=':
                test = function (value) {
                    return value && value.indexOf(attributeValue) > -1
                };
                break;
            case '!=':
                test = function (value) {
                    return attributeValue != value
                };
                break;
            default:
                test = function (value) {
                    return !!value
                }
            }
            if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function () {
                return false
            };
            if (!test) test = function (value) {
                return value && regexp.test(value)
            };
            if (!currentParsed.attributes) currentParsed.attributes = [];
            currentParsed.attributes.push({
                key: attributeKey,
                operator: attributeOperator,
                value: attributeValue,
                test: test
            })
        }
        return ''
    };
    var Slick = (this.Slick || {});
    Slick.parse = function (expression) {
        return parse(expression)
    };
    Slick.escapeRegExp = escapeRegExp;
    if (!this.Slick) this.Slick = Slick
}).apply((typeof exports != 'undefined') ? exports : this);
(function () {
    var local = {},
        featuresCache = {},
        toString = Object.prototype.toString;
    local.isNativeCode = function (fn) {
        return (/\{\s*\[native code\]\s*\}/).test('' + fn)
    };
    local.isXML = function (document) {
        return ( !! document.xmlVersion) || ( !! document.xml) || (toString.call(document) == '[object XMLDocument]') || (document.nodeType == 9 && document.documentElement.nodeName != 'HTML')
    };
    local.setDocument = function (document) {
        var nodeType = document.nodeType;
        if (nodeType == 9);
        else if (nodeType) document = document.ownerDocument;
        else if (document.navigator) document = document.document;
        else return;
        if (this.document === document) return;
        this.document = document;
        var root = document.documentElement,
            rootUid = this.getUIDXML(root),
            features = featuresCache[rootUid],
            feature;
        if (features) {
            for (feature in features) {
                this[feature] = features[feature]
            }
            return
        }
        features = featuresCache[rootUid] = {};
        features.root = root;
        features.isXMLDocument = this.isXML(document);
        features.brokenStarGEBTN = features.starSelectsClosedQSA = features.idGetsName = features.brokenMixedCaseQSA = features.brokenGEBCN = features.brokenCheckedQSA = features.brokenEmptyAttributeQSA = features.isHTMLDocument = features.nativeMatchesSelector = false;
        var starSelectsClosed, starSelectsComments, brokenSecondClassNameGEBCN, cachedGetElementsByClassName, brokenFormAttributeGetter;
        var selected, id = 'slick_uniqueid';
        var testNode = document.createElement('div');
        var testRoot = document.body || document.getElementsByTagName('body')[0] || root;
        testRoot.appendChild(testNode);
        try {
            testNode.innerHTML = '<a id="' + id + '"></a>';
            features.isHTMLDocument = !! document.getElementById(id)
        } catch (e) {};
        if (features.isHTMLDocument) {
            testNode.style.display = 'none';
            testNode.appendChild(document.createComment(''));
            starSelectsComments = (testNode.getElementsByTagName('*').length > 1);
            try {
                testNode.innerHTML = 'foo</foo>';
                selected = testNode.getElementsByTagName('*');
                starSelectsClosed = (selected && !! selected.length && selected[0].nodeName.charAt(0) == '/')
            } catch (e) {};
            features.brokenStarGEBTN = starSelectsComments || starSelectsClosed;
            try {
                testNode.innerHTML = '<a name="' + id + '"></a><b id="' + id + '"></b>';
                features.idGetsName = document.getElementById(id) === testNode.firstChild
            } catch (e) {};
            if (testNode.getElementsByClassName) {
                try {
                    testNode.innerHTML = '<a class="f"></a><a class="b"></a>';
                    testNode.getElementsByClassName('b').length;
                    testNode.firstChild.className = 'b';
                    cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2)
                } catch (e) {};
                try {
                    testNode.innerHTML = '<a class="a"></a><a class="f b a"></a>';
                    brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2)
                } catch (e) {};
                features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN
            }
            if (testNode.querySelectorAll) {
                try {
                    testNode.innerHTML = 'foo</foo>';
                    selected = testNode.querySelectorAll('*');
                    features.starSelectsClosedQSA = (selected && !! selected.length && selected[0].nodeName.charAt(0) == '/')
                } catch (e) {};
                try {
                    testNode.innerHTML = '<a class="MiX"></a>';
                    features.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiX').length
                } catch (e) {};
                try {
                    testNode.innerHTML = '<select><option selected="selected">a</option></select>';
                    features.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0)
                } catch (e) {};
                try {
                    testNode.innerHTML = '<a class=""></a>';
                    features.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0)
                } catch (e) {}
            }
            try {
                testNode.innerHTML = '<form action="s"><input id="action"/></form>';
                brokenFormAttributeGetter = (testNode.firstChild.getAttribute('action') != 's')
            } catch (e) {};
            features.nativeMatchesSelector = root.matchesSelector || root.mozMatchesSelector || root.webkitMatchesSelector;
            if (features.nativeMatchesSelector) try {
                features.nativeMatchesSelector.call(root, ':slick');
                features.nativeMatchesSelector = null
            } catch (e) {}
        }
        try {
            root.slick_expando = 1;
            delete root.slick_expando;
            features.getUID = this.getUIDHTML
        } catch (e) {
            features.getUID = this.getUIDXML
        }
        testRoot.removeChild(testNode);
        testNode = selected = testRoot = null;
        features.getAttribute = (features.isHTMLDocument && brokenFormAttributeGetter) ?
        function (node, name) {
            var method = this.attributeGetters[name];
            if (method) return method.call(node);
            var attributeNode = node.getAttributeNode(name);
            return (attributeNode) ? attributeNode.nodeValue : null
        } : function (node, name) {
            var method = this.attributeGetters[name];
            return (method) ? method.call(node) : node.getAttribute(name)
        };
        features.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ?
        function (node, attribute) {
            return node.hasAttribute(attribute)
        } : function (node, attribute) {
            node = node.getAttributeNode(attribute);
            return !!(node && (node.specified || node.nodeValue))
        };
        features.contains = (root && this.isNativeCode(root.contains)) ?
        function (context, node) {
            return context.contains(node)
        } : (root && root.compareDocumentPosition) ?
        function (context, node) {
            return context === node || !! (context.compareDocumentPosition(node) & 16)
        } : function (context, node) {
            if (node) do {
                if (node === context) return true
            } while ((node = node.parentNode));
            return false
        };
        features.documentSorter = (root.compareDocumentPosition) ?
        function (a, b) {
            if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0;
            return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1
        } : ('sourceIndex' in root) ?
        function (a, b) {
            if (!a.sourceIndex || !b.sourceIndex) return 0;
            return a.sourceIndex - b.sourceIndex
        } : (document.createRange) ?
        function (a, b) {
            if (!a.ownerDocument || !b.ownerDocument) return 0;
            var aRange = a.ownerDocument.createRange(),
                bRange = b.ownerDocument.createRange();
            aRange.setStart(a, 0);
            aRange.setEnd(a, 0);
            bRange.setStart(b, 0);
            bRange.setEnd(b, 0);
            return aRange.compareBoundaryPoints(Range.START_TO_END, bRange)
        } : null;
        root = null;
        for (feature in features) {
            this[feature] = features[feature]
        }
    };
    var reSimpleSelector = /^([#.]?)((?:[\w-]+|\*))$/,
        reEmptyAttribute = /\[.+[*$^]=(?:""|'')?\]/,
        qsaFailExpCache = {};
    local.search = function (context, expression, append, first) {
        var found = this.found = (first) ? null : (append || []);
        if (!context) return found;
        else if (context.navigator) context = context.document;
        else if (!context.nodeType) return found;
        var parsed, i, uniques = this.uniques = {},
            hasOthers = !! (append && append.length),
            contextIsDocument = (context.nodeType == 9);
        if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context);
        if (hasOthers) for (i = found.length; i--;) uniques[this.getUID(found[i])] = true;
        if (typeof expression == 'string') {
            var simpleSelector = expression.match(reSimpleSelector);
            simpleSelectors: if (simpleSelector) {
                var symbol = simpleSelector[1],
                    name = simpleSelector[2],
                    node, nodes;
                if (!symbol) {
                    if (name == '*' && this.brokenStarGEBTN) break simpleSelectors;
                    nodes = context.getElementsByTagName(name);
                    if (first) return nodes[0] || null;
                    for (i = 0; node = nodes[i++];) {
                        if (!(hasOthers && uniques[this.getUID(node)])) found.push(node)
                    }
                } else if (symbol == '#') {
                    if (!this.isHTMLDocument || !contextIsDocument) break simpleSelectors;
                    node = context.getElementById(name);
                    if (!node) return found;
                    if (this.idGetsName && node.getAttributeNode('id').nodeValue != name) break simpleSelectors;
                    if (first) return node || null;
                    if (!(hasOthers && uniques[this.getUID(node)])) found.push(node)
                } else if (symbol == '.') {
                    if (!this.isHTMLDocument || ((!context.getElementsByClassName || this.brokenGEBCN) && context.querySelectorAll)) break simpleSelectors;
                    if (context.getElementsByClassName && !this.brokenGEBCN) {
                        nodes = context.getElementsByClassName(name);
                        if (first) return nodes[0] || null;
                        for (i = 0; node = nodes[i++];) {
                            if (!(hasOthers && uniques[this.getUID(node)])) found.push(node)
                        }
                    } else {
                        var matchClass = new RegExp('(^|\\s)' + Slick.escapeRegExp(name) + '(\\s|$)');
                        nodes = context.getElementsByTagName('*');
                        for (i = 0; node = nodes[i++];) {
                            className = node.className;
                            if (!(className && matchClass.test(className))) continue;
                            if (first) return node;
                            if (!(hasOthers && uniques[this.getUID(node)])) found.push(node)
                        }
                    }
                }
                if (hasOthers) this.sort(found);
                return (first) ? null : found
            }
            querySelector: if (context.querySelectorAll) {
                if (!this.isHTMLDocument || this.brokenMixedCaseQSA || qsaFailExpCache[expression] || (this.brokenCheckedQSA && expression.indexOf(':checked') > -1) || (this.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression)) || Slick.disableQSA) break querySelector;
                var _expression = expression;
                if (!contextIsDocument) {
                    var currentId = context.getAttribute('id'),
                        slickid = 'slickid__';
                    context.setAttribute('id', slickid);
                    _expression = '#' + slickid + ' ' + _expression
                }
                try {
                    if (first) return context.querySelector(_expression) || null;
                    else nodes = context.querySelectorAll(_expression)
                } catch (e) {
                    qsaFailExpCache[expression] = 1;
                    break querySelector
                } finally {
                    if (!contextIsDocument) {
                        if (currentId) context.setAttribute('id', currentId);
                        else context.removeAttribute('id')
                    }
                }
                if (this.starSelectsClosedQSA) for (i = 0; node = nodes[i++];) {
                    if (node.nodeName > '@' && !(hasOthers && uniques[this.getUID(node)])) found.push(node)
                } else for (i = 0; node = nodes[i++];) {
                    if (!(hasOthers && uniques[this.getUID(node)])) found.push(node)
                }
                if (hasOthers) this.sort(found);
                return found
            }
            parsed = this.Slick.parse(expression);
            if (!parsed.length) return found
        } else if (expression == null) {
            return found
        } else if (expression.Slick) {
            parsed = expression
        } else if (this.contains(context.documentElement || context, expression)) {
            (found) ? found.push(expression) : found = expression;
            return found
        } else {
            return found
        }
        this.posNTH = {};
        this.posNTHLast = {};
        this.posNTHType = {};
        this.posNTHTypeLast = {};
        this.push = (!hasOthers && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID;
        if (found == null) found = [];
        var j, m, n;
        var combinator, tag, id, classList, classes, attributes, pseudos;
        var currentItems, currentExpression, currentBit, lastBit, expressions = parsed.expressions;
        search: for (i = 0;
        (currentExpression = expressions[i]); i++) for (j = 0;
        (currentBit = currentExpression[j]); j++) {
            combinator = 'combinator:' + currentBit.combinator;
            if (!this[combinator]) continue search;
            tag = (this.isXMLDocument) ? currentBit.tag : currentBit.tag.toUpperCase();
            id = currentBit.id;
            classList = currentBit.classList;
            classes = currentBit.classes;
            attributes = currentBit.attributes;
            pseudos = currentBit.pseudos;
            lastBit = (j === (currentExpression.length - 1));
            this.bitUniques = {};
            if (lastBit) {
                this.uniques = uniques;
                this.found = found
            } else {
                this.uniques = {};
                this.found = []
            }
            if (j === 0) {
                this[combinator](context, tag, id, classes, attributes, pseudos, classList);
                if (first && lastBit && found.length) break search
            } else {
                if (first && lastBit) for (m = 0, n = currentItems.length; m < n; m++) {
                    this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList);
                    if (found.length) break search
                } else for (m = 0, n = currentItems.length; m < n; m++) this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList)
            }
            currentItems = this.found
        }
        if (hasOthers || (parsed.expressions.length > 1)) this.sort(found);
        return (first) ? (found[0] || null) : found
    };
    local.uidx = 1;
    local.uidk = 'slick-uniqueid';
    local.getUIDXML = function (node) {
        var uid = node.getAttribute(this.uidk);
        if (!uid) {
            uid = this.uidx++;
            node.setAttribute(this.uidk, uid)
        }
        return uid
    };
    local.getUIDHTML = function (node) {
        return node.uniqueNumber || (node.uniqueNumber = this.uidx++)
    };
    local.sort = function (results) {
        if (!this.documentSorter) return results;
        results.sort(this.documentSorter);
        return results
    };
    local.cacheNTH = {};
    local.matchNTH = /^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/;
    local.parseNTHArgument = function (argument) {
        var parsed = argument.match(this.matchNTH);
        if (!parsed) return false;
        var special = parsed[2] || false;
        var a = parsed[1] || 1;
        if (a == '-') a = -1;
        var b = +parsed[3] || 0;
        parsed = (special == 'n') ? {
            a: a,
            b: b
        } : (special == 'odd') ? {
            a: 2,
            b: 1
        } : (special == 'even') ? {
            a: 2,
            b: 0
        } : {
            a: 0,
            b: a
        };
        return (this.cacheNTH[argument] = parsed)
    };
    local.createNTHPseudo = function (child, sibling, positions, ofType) {
        return function (node, argument) {
            var uid = this.getUID(node);
            if (!this[positions][uid]) {
                var parent = node.parentNode;
                if (!parent) return false;
                var el = parent[child],
                    count = 1;
                if (ofType) {
                    var nodeName = node.nodeName;
                    do {
                        if (el.nodeName != nodeName) continue;
                        this[positions][this.getUID(el)] = count++
                    } while ((el = el[sibling]))
                } else {
                    do {
                        if (el.nodeType != 1) continue;
                        this[positions][this.getUID(el)] = count++
                    } while ((el = el[sibling]))
                }
            }
            argument = argument || 'n';
            var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument);
            if (!parsed) return false;
            var a = parsed.a,
                b = parsed.b,
                pos = this[positions][uid];
            if (a == 0) return b == pos;
            if (a > 0) {
                if (pos < b) return false
            } else {
                if (b < pos) return false
            }
            return ((pos - b) % a) == 0
        }
    };
    local.pushArray = function (node, tag, id, classes, attributes, pseudos) {
        if (this.matchSelector(node, tag, id, classes, attributes, pseudos)) this.found.push(node)
    };
    local.pushUID = function (node, tag, id, classes, attributes, pseudos) {
        var uid = this.getUID(node);
        if (!this.uniques[uid] && this.matchSelector(node, tag, id, classes, attributes, pseudos)) {
            this.uniques[uid] = true;
            this.found.push(node)
        }
    };
    local.matchNode = function (node, selector) {
        if (this.isHTMLDocument && this.nativeMatchesSelector) {
            try {
                return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]'))
            } catch (matchError) {}
        }
        var parsed = this.Slick.parse(selector);
        if (!parsed) return true;
        var expressions = parsed.expressions,
            reversedExpressions, simpleExpCounter = 0,
            i;
        for (i = 0;
        (currentExpression = expressions[i]); i++) {
            if (currentExpression.length == 1) {
                var exp = currentExpression[0];
                if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true;
                simpleExpCounter++
            }
        }
        if (simpleExpCounter == parsed.length) return false;
        var nodes = this.search(this.document, parsed),
            item;
        for (i = 0; item = nodes[i++];) {
            if (item === node) return true
        }
        return false
    };
    local.matchPseudo = function (node, name, argument) {
        var pseudoName = 'pseudo:' + name;
        if (this[pseudoName]) return this[pseudoName](node, argument);
        var attribute = this.getAttribute(node, name);
        return (argument) ? argument == attribute : !! attribute
    };
    local.matchSelector = function (node, tag, id, classes, attributes, pseudos) {
        if (tag) {
            var nodeName = (this.isXMLDocument) ? node.nodeName : node.nodeName.toUpperCase();
            if (tag == '*') {
                if (nodeName < '@') return false
            } else {
                if (nodeName != tag) return false
            }
        }
        if (id && node.getAttribute('id') != id) return false;
        var i, part, cls;
        if (classes) for (i = classes.length; i--;) {
            cls = node.getAttribute('class') || node.className;
            if (!(cls && classes[i].regexp.test(cls))) return false
        }
        if (attributes) for (i = attributes.length; i--;) {
            part = attributes[i];
            if (part.operator ? !part.test(this.getAttribute(node, part.key)) : !this.hasAttribute(node, part.key)) return false
        }
        if (pseudos) for (i = pseudos.length; i--;) {
            part = pseudos[i];
            if (!this.matchPseudo(node, part.key, part.value)) return false
        }
        return true
    };
    var combinators = {
        ' ': function (node, tag, id, classes, attributes, pseudos, classList) {
            var i, item, children;
            if (this.isHTMLDocument) {
                getById: if (id) {
                    item = this.document.getElementById(id);
                    if ((!item && node.all) || (this.idGetsName && item && item.getAttributeNode('id').nodeValue != id)) {
                        children = node.all[id];
                        if (!children) return;
                        if (!children[0]) children = [children];
                        for (i = 0; item = children[i++];) {
                            var idNode = item.getAttributeNode('id');
                            if (idNode && idNode.nodeValue == id) {
                                this.push(item, tag, null, classes, attributes, pseudos);
                                break
                            }
                        }
                        return
                    }
                    if (!item) {
                        if (this.contains(this.root, node)) return;
                        else break getById
                    } else if (this.document !== node && !this.contains(node, item)) return;
                    this.push(item, tag, null, classes, attributes, pseudos);
                    return
                }
                getByClass: if (classes && node.getElementsByClassName && !this.brokenGEBCN) {
                    children = node.getElementsByClassName(classList.join(' '));
                    if (!(children && children.length)) break getByClass;
                    for (i = 0; item = children[i++];) this.push(item, tag, id, null, attributes, pseudos);
                    return
                }
            }
            getByTag: {
                children = node.getElementsByTagName(tag);
                if (!(children && children.length)) break getByTag;
                if (!this.brokenStarGEBTN) tag = null;
                for (i = 0; item = children[i++];) this.push(item, tag, id, classes, attributes, pseudos)
            }
        },
        '>': function (node, tag, id, classes, attributes, pseudos) {
            if ((node = node.firstChild)) do {
                if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos)
            } while ((node = node.nextSibling))
        },
        '+': function (node, tag, id, classes, attributes, pseudos) {
            while ((node = node.nextSibling)) if (node.nodeType == 1) {
                this.push(node, tag, id, classes, attributes, pseudos);
                break
            }
        },
        '^': function (node, tag, id, classes, attributes, pseudos) {
            node = node.firstChild;
            if (node) {
                if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
                else this['combinator:+'](node, tag, id, classes, attributes, pseudos)
            }
        },
        '~': function (node, tag, id, classes, attributes, pseudos) {
            while ((node = node.nextSibling)) {
                if (node.nodeType != 1) continue;
                var uid = this.getUID(node);
                if (this.bitUniques[uid]) break;
                this.bitUniques[uid] = true;
                this.push(node, tag, id, classes, attributes, pseudos)
            }
        },
        '++': function (node, tag, id, classes, attributes, pseudos) {
            this['combinator:+'](node, tag, id, classes, attributes, pseudos);
            this['combinator:!+'](node, tag, id, classes, attributes, pseudos)
        },
        '~~': function (node, tag, id, classes, attributes, pseudos) {
            this['combinator:~'](node, tag, id, classes, attributes, pseudos);
            this['combinator:!~'](node, tag, id, classes, attributes, pseudos)
        },
        '!': function (node, tag, id, classes, attributes, pseudos) {
            while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos)
        },
        '!>': function (node, tag, id, classes, attributes, pseudos) {
            node = node.parentNode;
            if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos)
        },
        '!+': function (node, tag, id, classes, attributes, pseudos) {
            while ((node = node.previousSibling)) if (node.nodeType == 1) {
                this.push(node, tag, id, classes, attributes, pseudos);
                break
            }
        },
        '!^': function (node, tag, id, classes, attributes, pseudos) {
            node = node.lastChild;
            if (node) {
                if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
                else this['combinator:!+'](node, tag, id, classes, attributes, pseudos)
            }
        },
        '!~': function (node, tag, id, classes, attributes, pseudos) {
            while ((node = node.previousSibling)) {
                if (node.nodeType != 1) continue;
                var uid = this.getUID(node);
                if (this.bitUniques[uid]) break;
                this.bitUniques[uid] = true;
                this.push(node, tag, id, classes, attributes, pseudos)
            }
        }
    };
    for (var c in combinators) local['combinator:' + c] = combinators[c];
    var pseudos = {
        'empty': function (node) {
            var child = node.firstChild;
            return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length
        },
        'not': function (node, expression) {
            return !this.matchNode(node, expression)
        },
        'contains': function (node, text) {
            return (node.innerText || node.textContent || '').indexOf(text) > -1
        },
        'first-child': function (node) {
            while ((node = node.previousSibling)) if (node.nodeType == 1) return false;
            return true
        },
        'last-child': function (node) {
            while ((node = node.nextSibling)) if (node.nodeType == 1) return false;
            return true
        },
        'only-child': function (node) {
            var prev = node;
            while ((prev = prev.previousSibling)) if (prev.nodeType == 1) return false;
            var next = node;
            while ((next = next.nextSibling)) if (next.nodeType == 1) return false;
            return true
        },
        'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'),
        'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'),
        'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true),
        'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true),
        'index': function (node, index) {
            return this['pseudo:nth-child'](node, '' + index + 1)
        },
        'even': function (node) {
            return this['pseudo:nth-child'](node, '2n')
        },
        'odd': function (node) {
            return this['pseudo:nth-child'](node, '2n+1')
        },
        'first-of-type': function (node) {
            var nodeName = node.nodeName;
            while ((node = node.previousSibling)) if (node.nodeName == nodeName) return false;
            return true
        },
        'last-of-type': function (node) {
            var nodeName = node.nodeName;
            while ((node = node.nextSibling)) if (node.nodeName == nodeName) return false;
            return true
        },
        'only-of-type': function (node) {
            var prev = node,
                nodeName = node.nodeName;
            while ((prev = prev.previousSibling)) if (prev.nodeName == nodeName) return false;
            var next = node;
            while ((next = next.nextSibling)) if (next.nodeName == nodeName) return false;
            return true
        },
        'enabled': function (node) {
            return !node.disabled
        },
        'disabled': function (node) {
            return node.disabled
        },
        'checked': function (node) {
            return node.checked || node.selected
        },
        'focus': function (node) {
            return this.isHTMLDocument && this.document.activeElement === node && (node.href || node.type || this.hasAttribute(node, 'tabindex'))
        },
        'root': function (node) {
            return (node === this.root)
        },
        'selected': function (node) {
            return node.selected
        }
    };
    for (var p in pseudos) local['pseudo:' + p] = pseudos[p];
    local.attributeGetters = {
        'class': function () {
            return this.getAttribute('class') || this.className
        },
        'for': function () {
            return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for')
        },
        'href': function () {
            return ('href' in this) ? this.getAttribute('href', 2) : this.getAttribute('href')
        },
        'style': function () {
            return (this.style) ? this.style.cssText : this.getAttribute('style')
        },
        'tabindex': function () {
            var attributeNode = this.getAttributeNode('tabindex');
            return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null
        },
        'type': function () {
            return this.getAttribute('type')
        }
    };
    var Slick = local.Slick = (this.Slick || {});
    Slick.version = '1.1.5';
    Slick.search = function (context, expression, append) {
        return local.search(context, expression, append)
    };
    Slick.find = function (context, expression) {
        return local.search(context, expression, null, true)
    };
    Slick.contains = function (container, node) {
        local.setDocument(container);
        return local.contains(container, node)
    };
    Slick.getAttribute = function (node, name) {
        return local.getAttribute(node, name)
    };
    Slick.match = function (node, selector) {
        if (!(node && selector)) return false;
        if (!selector || selector === node) return true;
        local.setDocument(node);
        return local.matchNode(node, selector)
    };
    Slick.defineAttributeGetter = function (name, fn) {
        local.attributeGetters[name] = fn;
        return this
    };
    Slick.lookupAttributeGetter = function (name) {
        return local.attributeGetters[name]
    };
    Slick.definePseudo = function (name, fn) {
        local['pseudo:' + name] = function (node, argument) {
            return fn.call(node, argument)
        };
        return this
    };
    Slick.lookupPseudo = function (name) {
        var pseudo = local['pseudo:' + name];
        if (pseudo) return function (argument) {
            return pseudo.call(this, argument)
        };
        return null
    };
    Slick.override = function (regexp, fn) {
        local.override(regexp, fn);
        return this
    };
    Slick.isXML = local.isXML;
    Slick.uidOf = function (node) {
        return local.getUIDHTML(node)
    };
    if (!this.Slick) this.Slick = Slick
}).apply((typeof exports != 'undefined') ? exports : this);
var Element = function (tag, props) {
        var konstructor = Element.Constructors[tag];
        if (konstructor) return konstructor(props);
        if (typeof tag != 'string') return document.id(tag).set(props);
        if (!props) props = {};
        if (!(/^[\w-]+$/).test(tag)) {
            var parsed = Slick.parse(tag).expressions[0][0];
            tag = (parsed.tag == '*') ? 'div' : parsed.tag;
            if (parsed.id && props.id == null) props.id = parsed.id;
            var attributes = parsed.attributes;
            if (attributes) for (var i = 0, l = attributes.length; i < l; i++) {
                var attr = attributes[i];
                if (attr.value != null && attr.operator == '=' && props[attr.key] == null) props[attr.key] = attr.value
            }
            if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' ')
        }
        return document.newElement(tag, props)
    };
if (Browser.Element) Element.prototype = Browser.Element.prototype;
new Type('Element', Element).mirror(function (name) {
    if (Array.prototype[name]) return;
    var obj = {};
    obj[name] = function () {
        var results = [],
            args = arguments,
            elements = true;
        for (var i = 0, l = this.length; i < l; i++) {
            var element = this[i],
                result = results[i] = element[name].apply(element, args);
            elements = (elements && typeOf(result) == 'element')
        }
        return (elements) ? new Elements(results) : results
    };
    Elements.implement(obj)
});
if (!Browser.Element) {
    Element.parent = Object;
    Element.Prototype = {
        '$family': Function.from('element').hide()
    };
    Element.mirror(function (name, method) {
        Element.Prototype[name] = method
    })
}
Element.Constructors = {};
Element.Constructors = new Hash;
var IFrame = new Type('IFrame', function () {
    var params = Array.link(arguments, {
        properties: Type.isObject,
        iframe: function (obj) {
            return (obj != null)
        }
    });
    var props = params.properties || {},
        iframe;
    if (params.iframe) iframe = document.id(params.iframe);
    var onload = props.onload ||
    function () {};
    delete props.onload;
    props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick();
    iframe = new Element(iframe || 'iframe', props);
    var onLoad = function () {
            onload.call(iframe.contentWindow)
        };
    if (window.frames[props.id]) onLoad();
    else iframe.addListener('load', onLoad);
    return iframe
});
var Elements = this.Elements = function (nodes) {
        if (nodes && nodes.length) {
            var uniques = {},
                node;
            for (var i = 0; node = nodes[i++];) {
                var uid = Slick.uidOf(node);
                if (!uniques[uid]) {
                    uniques[uid] = true;
                    this.push(node)
                }
            }
        }
    };
Elements.prototype = {
    length: 0
};
Elements.parent = Array;
new Type('Elements', Elements).implement({
    filter: function (filter, bind) {
        if (!filter) return this;
        return new Elements(Array.filter(this, (typeOf(filter) == 'string') ?
        function (item) {
            return item.match(filter)
        } : filter, bind))
    }.protect(),
    push: function () {
        var length = this.length;
        for (var i = 0, l = arguments.length; i < l; i++) {
            var item = document.id(arguments[i]);
            if (item) this[length++] = item
        }
        return (this.length = length)
    }.protect(),
    unshift: function () {
        var items = [];
        for (var i = 0, l = arguments.length; i < l; i++) {
            var item = document.id(arguments[i]);
            if (item) items.push(item)
        }
        return Array.prototype.unshift.apply(this, items)
    }.protect(),
    concat: function () {
        var newElements = new Elements(this);
        for (var i = 0, l = arguments.length; i < l; i++) {
            var item = arguments[i];
            if (Type.isEnumerable(item)) newElements.append(item);
            else newElements.push(item)
        }
        return newElements
    }.protect(),
    append: function (collection) {
        for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]);
        return this
    }.protect(),
    empty: function () {
        while (this.length) delete this[--this.length];
        return this
    }.protect()
});
Elements.alias('extend', 'append');
(function () {
    var splice = Array.prototype.splice,
        object = {
            '0': 0,
            '1': 1,
            length: 2
        };
    splice.call(object, 1, 1);
    if (object[1] == 1) Elements.implement('splice', function () {
        var length = this.length;
        splice.apply(this, arguments);
        while (length >= this.length) delete this[length--];
        return this
    }.protect());
    Elements.implement(Array.prototype);
    Array.mirror(Elements);
    var createElementAcceptsHTML;
    try {
        var x = document.createElement('<input name=x>');
        createElementAcceptsHTML = (x.name == 'x')
    } catch (e) {}
    var escapeQuotes = function (html) {
            return ('' + html).replace(/&/g, '&amp;').replace(/"/g, '&quot;')
        };
    Document.implement({
        newElement: function (tag, props) {
            if (props && props.checked != null) props.defaultChecked = props.checked;
            if (createElementAcceptsHTML && props) {
                tag = '<' + tag;
                if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"';
                if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"';
                tag += '>';
                delete props.name;
                delete props.type
            }
            return this.id(this.createElement(tag)).set(props)
        }
    })
})();
Document.implement({
    newTextNode: function (text) {
        return this.createTextNode(text)
    },
    getDocument: function () {
        return this
    },
    getWindow: function () {
        return this.window
    },
    id: (function () {
        var types = {
            string: function (id, nocash, doc) {
                id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1'));
                return (id) ? types.element(id, nocash) : null
            },
            element: function (el, nocash) {
                $uid(el);
                if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)) {
                    Object.append(el, Element.Prototype)
                }
                return el
            },
            object: function (obj, nocash, doc) {
                if (obj.toElement) return types.element(obj.toElement(doc), nocash);
                return null
            }
        };
        types.textnode = types.whitespace = types.window = types.document = function (zero) {
            return zero
        };
        return function (el, nocash, doc) {
            if (el && el.$family && el.uid) return el;
            var type = typeOf(el);
            return (types[type]) ? types[type](el, nocash, doc || document) : null
        }
    })()
});
if (window.$ == null) Window.implement('$', function (el, nc) {
    return document.id(el, nc, this.document)
});
Window.implement({
    getDocument: function () {
        return this.document
    },
    getWindow: function () {
        return this
    }
});
[Document, Element].invoke('implement', {
    getElements: function (expression) {
        return Slick.search(this, expression, new Elements)
    },
    getElement: function (expression) {
        return document.id(Slick.find(this, expression))
    }
});
(function (search, find, match) {
    this.Selectors = {};
    var pseudos = this.Selectors.Pseudo = new Hash();
    var addSlickPseudos = function () {
            for (var name in pseudos) if (pseudos.hasOwnProperty(name)) {
                Slick.definePseudo(name, pseudos[name]);
                delete pseudos[name]
            }
        };
    Slick.search = function (context, expression, append) {
        addSlickPseudos();
        return search.call(this, context, expression, append)
    };
    Slick.find = function (context, expression) {
        addSlickPseudos();
        return find.call(this, context, expression)
    };
    Slick.match = function (node, selector) {
        addSlickPseudos();
        return match.call(this, node, selector)
    }
})(Slick.search, Slick.find, Slick.match);
if (window.$$ == null) Window.implement('$$', function (selector) {
    var elements = new Elements;
    if (arguments.length == 1 && typeof selector == 'string') return Slick.search(this.document, selector, elements);
    var args = Array.flatten(arguments);
    for (var i = 0, l = args.length; i < l; i++) {
        var item = args[i];
        switch (typeOf(item)) {
        case 'element':
            elements.push(item);
            break;
        case 'string':
            Slick.search(this.document, item, elements)
        }
    }
    return elements
});
if (window.$$ == null) Window.implement('$$', function (selector) {
    if (arguments.length == 1) {
        if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements);
        else if (Type.isEnumerable(selector)) return new Elements(selector)
    }
    return new Elements(arguments)
});
(function () {
    var collected = {},
        storage = {};
    var formProps = {
        input: 'checked',
        option: 'selected',
        textarea: 'value'
    };
    var get = function (uid) {
            return (storage[uid] || (storage[uid] = {}))
        };
    var clean = function (item) {
            var uid = item.uid;
            if (item.removeEvents) item.removeEvents();
            if (item.clearAttributes) item.clearAttributes();
            if (uid != null) {
                delete collected[uid];
                delete storage[uid]
            }
            return item
        };
    var camels = ['defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly', 'rowSpan', 'tabIndex', 'useMap'];
    var bools = ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readOnly', 'multiple', 'selected', 'noresize', 'defer', 'defaultChecked'];
    var attributes = {
        'html': 'innerHTML',
        'class': 'className',
        'for': 'htmlFor',
        'text': (function () {
            var temp = document.createElement('div');
            return (temp.textContent == null) ? 'innerText' : 'textContent'
        })()
    };
    var readOnly = ['type'];
    var expandos = ['value', 'defaultValue'];
    var uriAttrs = /^(?:href|src|usemap)$/i;
    bools = bools.associate(bools);
    camels = camels.associate(camels.map(String.toLowerCase));
    readOnly = readOnly.associate(readOnly);
    Object.append(attributes, expandos.associate(expandos));
    var inserters = {
        before: function (context, element) {
            var parent = element.parentNode;
            if (parent) parent.insertBefore(context, element)
        },
        after: function (context, element) {
            var parent = element.parentNode;
            if (parent) parent.insertBefore(context, element.nextSibling)
        },
        bottom: function (context, element) {
            element.appendChild(context)
        },
        top: function (context, element) {
            element.insertBefore(context, element.firstChild)
        }
    };
    inserters.inside = inserters.bottom;
    Object.each(inserters, function (inserter, where) {
        where = where.capitalize();
        var methods = {};
        methods['inject' + where] = function (el) {
            inserter(this, document.id(el, true));
            return this
        };
        methods['grab' + where] = function (el) {
            inserter(document.id(el, true), this);
            return this
        };
        Element.implement(methods)
    });
    var injectCombinator = function (expression, combinator) {
            if (!expression) return combinator;
            expression = Object.clone(Slick.parse(expression));
            var expressions = expression.expressions;
            for (var i = expressions.length; i--;) expressions[i][0].combinator = combinator;
            return expression
        };
    Element.implement({
        set: function (prop, value) {
            var property = Element.Properties[prop];
            (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value)
        }.overloadSetter(),
        get: function (prop) {
            var property = Element.Properties[prop];
            return (property && property.get) ? property.get.apply(this) : this.getProperty(prop)
        }.overloadGetter(),
        erase: function (prop) {
            var property = Element.Properties[prop];
            (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop);
            return this
        },
        setProperty: function (attribute, value) {
            attribute = camels[attribute] || attribute;
            if (value == null) return this.removeProperty(attribute);
            var key = attributes[attribute];
            (key) ? this[key] = value : (bools[attribute]) ? this[attribute] = !! value : this.setAttribute(attribute, '' + value);
            return this
        },
        setProperties: function (attributes) {
            for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]);
            return this
        },
        getProperty: function (attribute) {
            attribute = camels[attribute] || attribute;
            var key = attributes[attribute] || readOnly[attribute];
            return (key) ? this[key] : (bools[attribute]) ? !! this[attribute] : (uriAttrs.test(attribute) ? this.getAttribute(attribute, 2) : (key = this.getAttributeNode(attribute)) ? key.nodeValue : null) || null
        },
        getProperties: function () {
            var args = Array.from(arguments);
            return args.map(this.getProperty, this).associate(args)
        },
        removeProperty: function (attribute) {
            attribute = camels[attribute] || attribute;
            var key = attributes[attribute];
            (key) ? this[key] = '' : (bools[attribute]) ? this[attribute] = false : this.removeAttribute(attribute);
            return this
        },
        removeProperties: function () {
            Array.each(arguments, this.removeProperty, this);
            return this
        },
        hasClass: function (className) {
            return this.className.clean().contains(className, ' ')
        },
        addClass: function (className) {
            if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
            return this
        },
        removeClass: function (className) {
            this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1');
            return this
        },
        toggleClass: function (className, force) {
            if (force == null) force = !this.hasClass(className);
            return (force) ? this.addClass(className) : this.removeClass(className)
        },
        adopt: function () {
            var parent = this,
                fragment, elements = Array.flatten(arguments),
                length = elements.length;
            if (length > 1) parent = fragment = document.createDocumentFragment();
            for (var i = 0; i < length; i++) {
                var element = document.id(elements[i], true);
                if (element) parent.appendChild(element)
            }
            if (fragment) this.appendChild(fragment);
            return this
        },
        appendText: function (text, where) {
            return this.grab(this.getDocument().newTextNode(text), where)
        },
        grab: function (el, where) {
            inserters[where || 'bottom'](document.id(el, true), this);
            return this
        },
        inject: function (el, where) {
            inserters[where || 'bottom'](this, document.id(el, true));
            return this
        },
        replaces: function (el) {
            el = document.id(el, true);
            el.parentNode.replaceChild(this, el);
            return this
        },
        wraps: function (el, where) {
            el = document.id(el, true);
            return this.replaces(el).grab(el, where)
        },
        getPrevious: function (expression) {
            return document.id(Slick.find(this, injectCombinator(expression, '!~')))
        },
        getAllPrevious: function (expression) {
            return Slick.search(this, injectCombinator(expression, '!~'), new Elements)
        },
        getNext: function (expression) {
            return document.id(Slick.find(this, injectCombinator(expression, '~')))
        },
        getAllNext: function (expression) {
            return Slick.search(this, injectCombinator(expression, '~'), new Elements)
        },
        getFirst: function (expression) {
            return document.id(Slick.search(this, injectCombinator(expression, '>'))[0])
        },
        getLast: function (expression) {
            return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast())
        },
        getParent: function (expression) {
            return document.id(Slick.find(this, injectCombinator(expression, '!')))
        },
        getParents: function (expression) {
            return Slick.search(this, injectCombinator(expression, '!'), new Elements)
        },
        getSiblings: function (expression) {
            return Slick.search(this, injectCombinator(expression, '~~'), new Elements)
        },
        getChildren: function (expression) {
            return Slick.search(this, injectCombinator(expression, '>'), new Elements)
        },
        getWindow: function () {
            return this.ownerDocument.window
        },
        getDocument: function () {
            return this.ownerDocument
        },
        getElementById: function (id) {
            return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1')))
        },
        getSelected: function () {
            this.selectedIndex;
            return new Elements(Array.from(this.options).filter(function (option) {
                return option.selected
            }))
        },
        toQueryString: function () {
            var queryString = [];
            this.getElements('input, select, textarea').each(function (el) {
                var type = el.type;
                if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return;
                var value = (el.get('tag') == 'select') ? el.getSelected().map(function (opt) {
                    return document.id(opt).get('value')
                }) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value');
                Array.from(value).each(function (val) {
                    if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val))
                })
            });
            return queryString.join('&')
        },
        destroy: function () {
            var children = clean(this).getElementsByTagName('*');
            Array.each(children, clean);
            Element.dispose(this);
            return null
        },
        empty: function () {
            Array.from(this.childNodes).each(Element.dispose);
            return this
        },
        dispose: function () {
            return (this.parentNode) ? this.parentNode.removeChild(this) : this
        },
        match: function (expression) {
            return !expression || Slick.match(this, expression)
        }
    });
    var cleanClone = function (node, element, keepid) {
            if (!keepid) node.setAttributeNode(document.createAttribute('id'));
            if (node.clearAttributes) {
                node.clearAttributes();
                node.mergeAttributes(element);
                node.removeAttribute('uid');
                if (node.options) {
                    var no = node.options,
                        eo = element.options;
                    for (var i = no.length; i--;) no[i].selected = eo[i].selected
                }
            }
            var prop = formProps[element.tagName.toLowerCase()];
            if (prop && element[prop]) node[prop] = element[prop]
        };
    Element.implement('clone', function (contents, keepid) {
        contents = contents !== false;
        var clone = this.cloneNode(contents),
            i;
        if (contents) {
            var ce = clone.getElementsByTagName('*'),
                te = this.getElementsByTagName('*');
            for (i = ce.length; i--;) cleanClone(ce[i], te[i], keepid)
        }
        cleanClone(clone, this, keepid);
        if (Browser.ie) {
            var co = clone.getElementsByTagName('object'),
                to = this.getElementsByTagName('object');
            for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML
        }
        return document.id(clone)
    });
    var contains = {
        contains: function (element) {
            return Slick.contains(this, element)
        }
    };
    if (!document.contains) Document.implement(contains);
    if (!document.createElement('div').contains) Element.implement(contains);
    Element.implement('hasChild', function (element) {
        return this !== element && this.contains(element)
    });
    [Element, Window, Document].invoke('implement', {
        addListener: function (type, fn) {
            if (type == 'unload') {
                var old = fn,
                    self = this;
                fn = function () {
                    self.removeListener('unload', fn);
                    old()
                }
            } else {
                collected[$uid(this)] = this
            }
            if (this.addEventListener) this.addEventListener(type, fn, !! arguments[2]);
            else this.attachEvent('on' + type, fn);
            return this
        },
        removeListener: function (type, fn) {
            if (this.removeEventListener) this.removeEventListener(type, fn, !! arguments[2]);
            else this.detachEvent('on' + type, fn);
            return this
        },
        retrieve: function (property, dflt) {
            var storage = get($uid(this)),
                prop = storage[property];
            if (dflt != null && prop == null) prop = storage[property] = dflt;
            return prop != null ? prop : null
        },
        store: function (property, value) {
            var storage = get($uid(this));
            storage[property] = value;
            return this
        },
        eliminate: function (property) {
            var storage = get($uid(this));
            delete storage[property];
            return this
        }
    });
    if (window.attachEvent && !window.addEventListener) window.addListener('unload', function () {
        Object.each(collected, clean);
        if (window.CollectGarbage) CollectGarbage()
    })
})();
Element.Properties = {};
Element.Properties = new Hash;
Element.Properties.style = {
    set: function (style) {
        this.style.cssText = style
    },
    get: function () {
        return this.style.cssText
    },
    erase: function () {
        this.style.cssText = ''
    }
};
Element.Properties.tag = {
    get: function () {
        return this.tagName.toLowerCase()
    }
};
(function (maxLength) {
    if (maxLength != null) Element.Properties.maxlength = Element.Properties.maxLength = {
        get: function () {
            var maxlength = this.getAttribute('maxLength');
            return maxlength == maxLength ? null : maxlength
        }
    }
})(document.createElement('input').getAttribute('maxLength'));
Element.Properties.html = (function () {
    var tableTest = Function.attempt(function () {
        var table = document.createElement('table');
        table.innerHTML = '<tr><td></td></tr>'
    });
    var wrapper = document.createElement('div');
    var translations = {
        table: [1, '<table>', '</table>'],
        select: [1, '<select>', '</select>'],
        tbody: [2, '<table><tbody>', '</tbody></table>'],
        tr: [3, '<table><tbody><tr>', '</tr></tbody></table>']
    };
    translations.thead = translations.tfoot = translations.tbody;
    var html = {
        set: function () {
            var html = Array.flatten(arguments).join('');
            var wrap = (!tableTest && translations[this.get('tag')]);
            if (wrap) {
                var first = wrapper;
                first.innerHTML = wrap[1] + html + wrap[2];
                for (var i = wrap[0]; i--;) first = first.firstChild;
                this.empty().adopt(first.childNodes)
            } else {
                this.innerHTML = html
            }
        }
    };
    html.erase = html.set;
    return html
})();
(function () {
    var html = document.html;
    Element.Properties.styles = {
        set: function (styles) {
            this.setStyles(styles)
        }
    };
    var hasOpacity = (html.style.opacity != null);
    var reAlpha = /alpha\(opacity=([\d.]+)\)/i;
    var setOpacity = function (element, opacity) {
            if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1;
            if (hasOpacity) {
                element.style.opacity = opacity
            } else {
                opacity = (opacity == 1) ? '' : 'alpha(opacity=' + opacity * 100 + ')';
                var filter = element.style.filter || element.getComputedStyle('filter') || '';
                element.style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity
            }
        };
    Element.Properties.opacity = {
        set: function (opacity) {
            var visibility = this.style.visibility;
            if (opacity == 0 && visibility != 'hidden') this.style.visibility = 'hidden';
            else if (opacity != 0 && visibility != 'visible') this.style.visibility = 'visible';
            setOpacity(this, opacity)
        },
        get: (hasOpacity) ?
        function () {
            var opacity = this.style.opacity || this.getComputedStyle('opacity');
            return (opacity == '') ? 1 : opacity
        } : function () {
            var opacity, filter = (this.style.filter || this.getComputedStyle('filter'));
            if (filter) opacity = filter.match(reAlpha);
            return (opacity == null || filter == null) ? 1 : (opacity[1] / 100)
        }
    };
    var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat';
    Element.implement({
        getComputedStyle: function (property) {
            if (this.currentStyle) return this.currentStyle[property.camelCase()];
            var defaultView = Element.getDocument(this).defaultView,
                computed = defaultView ? defaultView.getComputedStyle(this, null) : null;
            return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : null
        },
        setOpacity: function (value) {
            setOpacity(this, value);
            return this
        },
        getOpacity: function () {
            return this.get('opacity')
        },
        setStyle: function (property, value) {
            switch (property) {
            case 'opacity':
                return this.set('opacity', parseFloat(value));
            case 'float':
                property = floatName
            }
            property = property.camelCase();
            if (typeOf(value) != 'string') {
                var map = (Element.Styles[property] || '@').split(' ');
                value = Array.from(value).map(function (val, i) {
                    if (!map[i]) return '';
                    return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val
                }).join(' ')
            } else if (value == String(Number(value))) {
                value = Math.round(value)
            }
            this.style[property] = value;
            return this
        },
        getStyle: function (property) {
            switch (property) {
            case 'opacity':
                return this.get('opacity');
            case 'float':
                property = floatName
            }
            property = property.camelCase();
            var result = this.style[property];
            if (!result || property == 'zIndex') {
                result = [];
                for (var style in Element.ShortStyles) {
                    if (property != style) continue;
                    for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s));
                    return result.join(' ')
                }
                result = this.getComputedStyle(property)
            }
            if (result) {
                result = String(result);
                var color = result.match(/rgba?\([\d\s,]+\)/);
                if (color) result = result.replace(color[0], color[0].rgbToHex())
            }
            if (Browser.opera || (Browser.ie && isNaN(parseFloat(result)))) {
                if ((/^(height|width)$/).test(property)) {
                    var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'],
                        size = 0;
                    values.each(function (value) {
                        size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt()
                    }, this);
                    return this['offset' + property.capitalize()] - size + 'px'
                }
                if (Browser.opera && String(result).indexOf('px') != -1) return result;
                if ((/^border(.+)Width|margin|padding/).test(property)) return '0px'
            }
            return result
        },
        setStyles: function (styles) {
            for (var style in styles) this.setStyle(style, styles[style]);
            return this
        },
        getStyles: function () {
            var result = {};
            Array.flatten(arguments).each(function (key) {
                result[key] = this.getStyle(key)
            }, this);
            return result
        }
    });
    Element.Styles = {
        left: '@px',
        top: '@px',
        bottom: '@px',
        right: '@px',
        width: '@px',
        height: '@px',
        maxWidth: '@px',
        maxHeight: '@px',
        minWidth: '@px',
        minHeight: '@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.Styles = new Hash(Element.Styles);
    Element.ShortStyles = {
        margin: {},
        padding: {},
        border: {},
        borderWidth: {},
        borderStyle: {},
        borderColor: {}
    };
    ['Top', 'Right', 'Bottom', 'Left'].each(function (direction) {
        var Short = Element.ShortStyles;
        var All = Element.Styles;
        ['margin', 'padding'].each(function (style) {
            var sd = style + direction;
            Short[style][sd] = All[sd] = '@px'
        });
        var bd = 'border' + direction;
        Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)';
        var bdw = bd + 'Width',
            bds = bd + 'Style',
            bdc = bd + 'Color';
        Short[bd] = {};
        Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px';
        Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@';
        Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)'
    })
}).call(this);
(function () {
    Element.Properties.events = {
        set: function (events) {
            this.addEvents(events)
        }
    };
    [Element, Window, Document].invoke('implement', {
        addEvent: function (type, fn) {
            var events = this.retrieve('events', {});
            if (!events[type]) events[type] = {
                keys: [],
                values: []
            };
            if (events[type].keys.contains(fn)) return this;
            events[type].keys.push(fn);
            var realType = type,
                custom = Element.Events[type],
                condition = fn,
                self = this;
            if (custom) {
                if (custom.onAdd) custom.onAdd.call(this, fn);
                if (custom.condition) {
                    condition = function (event) {
                        if (custom.condition.call(this, event)) return fn.call(this, event);
                        return true
                    }
                }
                realType = custom.base || realType
            }
            var defn = function () {
                    return fn.call(self)
                };
            var nativeEvent = Element.NativeEvents[realType];
            if (nativeEvent) {
                if (nativeEvent == 2) {
                    defn = function (event) {
                        event = new Event(event, self.getWindow());
                        if (condition.call(self, event) === false) event.stop()
                    }
                }
                this.addListener(realType, defn, arguments[2])
            }
            events[type].values.push(defn);
            return this
        },
        removeEvent: function (type, fn) {
            var events = this.retrieve('events');
            if (!events || !events[type]) return this;
            var list = events[type];
            var index = list.keys.indexOf(fn);
            if (index == -1) return this;
            var value = list.values[index];
            delete list.keys[index];
            delete list.values[index];
            var custom = Element.Events[type];
            if (custom) {
                if (custom.onRemove) custom.onRemove.call(this, fn);
                type = custom.base || type
            }
            return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this
        },
        addEvents: function (events) {
            for (var event in events) this.addEvent(event, events[event]);
            return this
        },
        removeEvents: function (events) {
            var type;
            if (typeOf(events) == 'object') {
                for (type in events) this.removeEvent(type, events[type]);
                return this
            }
            var attached = this.retrieve('events');
            if (!attached) return this;
            if (!events) {
                for (type in attached) this.removeEvents(type);
                this.eliminate('events')
            } else if (attached[events]) {
                attached[events].keys.each(function (fn) {
                    this.removeEvent(events, fn)
                }, this);
                delete attached[events]
            }
            return this
        },
        fireEvent: function (type, args, delay) {
            var events = this.retrieve('events');
            if (!events || !events[type]) return this;
            args = Array.from(args);
            events[type].keys.each(function (fn) {
                if (delay) fn.delay(delay, this, args);
                else fn.apply(this, args)
            }, this);
            return this
        },
        cloneEvents: function (from, type) {
            from = document.id(from);
            var events = from.retrieve('events');
            if (!events) return this;
            if (!type) {
                for (var eventType in events) this.cloneEvents(from, eventType)
            } else if (events[type]) {
                events[type].keys.each(function (fn) {
                    this.addEvent(type, fn)
                }, 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,
        orientationchange: 2,
        touchstart: 2,
        touchmove: 2,
        touchend: 2,
        touchcancel: 2,
        gesturestart: 2,
        gesturechange: 2,
        gestureend: 2,
        focus: 2,
        blur: 2,
        change: 2,
        reset: 2,
        select: 2,
        submit: 2,
        load: 2,
        unload: 1,
        beforeunload: 2,
        resize: 1,
        move: 1,
        DOMContentLoaded: 1,
        readystatechange: 1,
        error: 1,
        abort: 1,
        scroll: 1
    };
    var check = function (event) {
            var related = event.relatedTarget;
            if (related == null) return true;
            if (!related) return false;
            return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related))
        };
    Element.Events = {
        mouseenter: {
            base: 'mouseover',
            condition: check
        },
        mouseleave: {
            base: 'mouseout',
            condition: check
        },
        mousewheel: {
            base: (Browser.firefox) ? 'DOMMouseScroll' : 'mousewheel'
        }
    };
    Element.Events = new Hash(Element.Events)
}).call(this);
(function () {
    var element = document.createElement('div'),
        child = document.createElement('div');
    element.style.height = '0';
    element.appendChild(child);
    var brokenOffsetParent = (child.offsetParent === element);
    element = child = null;
    var isOffset = function (el) {
            return styleString(el, 'position') != 'static' || isBody(el)
        };
    var isOffsetStatic = function (el) {
            return isOffset(el) || (/^(?:table|td|th)$/i).test(el.tagName)
        };
    Element.implement({
        scrollTo: function (x, y) {
            if (isBody(this)) {
                this.getWindow().scrollTo(x, y)
            } else {
                this.scrollLeft = x;
                this.scrollTop = y
            }
            return this
        },
        getSize: function () {
            if (isBody(this)) return this.getWindow().getSize();
            return {
                x: this.offsetWidth,
                y: this.offsetHeight
            }
        },
        getScrollSize: function () {
            if (isBody(this)) return this.getWindow().getScrollSize();
            return {
                x: this.scrollWidth,
                y: this.scrollHeight
            }
        },
        getScroll: function () {
            if (isBody(this)) return this.getWindow().getScroll();
            return {
                x: this.scrollLeft,
                y: this.scrollTop
            }
        },
        getScrolls: function () {
            var element = this.parentNode,
                position = {
                    x: 0,
                    y: 0
                };
            while (element && !isBody(element)) {
                position.x += element.scrollLeft;
                position.y += element.scrollTop;
                element = element.parentNode
            }
            return position
        },
        getOffsetParent: brokenOffsetParent ?
        function () {
            var element = this;
            if (isBody(element) || styleString(element, 'position') == 'fixed') return null;
            var isOffsetCheck = (styleString(element, 'position') == 'static') ? isOffsetStatic : isOffset;
            while ((element = element.parentNode)) {
                if (isOffsetCheck(element)) return element
            }
            return null
        } : function () {
            var element = this;
            if (isBody(element) || styleString(element, 'position') == 'fixed') return null;
            try {
                return element.offsetParent
            } catch (e) {}
            return null
        },
        getOffsets: function () {
            if (this.getBoundingClientRect && !Browser.Platform.ios) {
                var bound = this.getBoundingClientRect(),
                    html = document.id(this.getDocument().documentElement),
                    htmlScroll = html.getScroll(),
                    elemScrolls = this.getScrolls(),
                    isFixed = (styleString(this, 'position') == 'fixed');
                return {
                    x: bound.left.toInt() + elemScrolls.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft,
                    y: bound.top.toInt() + elemScrolls.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop
                }
            }
            var element = this,
                position = {
                    x: 0,
                    y: 0
                };
            if (isBody(this)) return position;
            while (element && !isBody(element)) {
                position.x += element.offsetLeft;
                position.y += element.offsetTop;
                if (Browser.firefox) {
                    if (!borderBox(element)) {
                        position.x += leftBorder(element);
                        position.y += topBorder(element)
                    }
                    var parent = element.parentNode;
                    if (parent && styleString(parent, 'overflow') != 'visible') {
                        position.x += leftBorder(parent);
                        position.y += topBorder(parent)
                    }
                } else if (element != this && Browser.safari) {
                    position.x += leftBorder(element);
                    position.y += topBorder(element)
                }
                element = element.offsetParent
            }
            if (Browser.firefox && !borderBox(this)) {
                position.x -= leftBorder(this);
                position.y -= topBorder(this)
            }
            return position
        },
        getPosition: function (relative) {
            if (isBody(this)) return {
                x: 0,
                y: 0
            };
            var offset = this.getOffsets(),
                scroll = this.getScrolls();
            var position = {
                x: offset.x - scroll.x,
                y: offset.y - scroll.y
            };
            if (relative && (relative = document.id(relative))) {
                var relativePosition = relative.getPosition();
                return {
                    x: position.x - relativePosition.x - leftBorder(relative),
                    y: position.y - relativePosition.y - topBorder(relative)
                }
            }
            return position
        },
        getCoordinates: function (element) {
            if (isBody(this)) return this.getWindow().getCoordinates();
            var position = this.getPosition(element),
                size = this.getSize();
            var obj = {
                left: position.x,
                top: position.y,
                width: size.x,
                height: size.y
            };
            obj.right = obj.left + obj.width;
            obj.bottom = obj.top + obj.height;
            return obj
        },
        computePosition: function (obj) {
            return {
                left: obj.x - styleNumber(this, 'margin-left'),
                top: obj.y - styleNumber(this, 'margin-top')
            }
        },
        setPosition: function (obj) {
            return this.setStyles(this.computePosition(obj))
        }
    });
    [Document, Window].invoke('implement', {
        getSize: function () {
            var doc = getCompatElement(this);
            return {
                x: doc.clientWidth,
                y: doc.clientHeight
            }
        },
        getScroll: function () {
            var win = this.getWindow(),
                doc = getCompatElement(this);
            return {
                x: win.pageXOffset || doc.scrollLeft,
                y: win.pageYOffset || doc.scrollTop
            }
        },
        getScrollSize: function () {
            var doc = getCompatElement(this),
                min = this.getSize(),
                body = this.getDocument().body;
            return {
                x: Math.max(doc.scrollWidth, body.scrollWidth, min.x),
                y: Math.max(doc.scrollHeight, body.scrollHeight, min.y)
            }
        },
        getPosition: function () {
            return {
                x: 0,
                y: 0
            }
        },
        getCoordinates: function () {
            var size = this.getSize();
            return {
                top: 0,
                left: 0,
                bottom: size.y,
                right: size.x,
                height: size.y,
                width: size.x
            }
        }
    });
    var styleString = Element.getComputedStyle;

    function styleNumber(element, style) {
        return styleString(element, style).toInt() || 0
    }
    function borderBox(element) {
        return styleString(element, '-moz-box-sizing') == 'border-box'
    }
    function topBorder(element) {
        return styleNumber(element, 'border-top-width')
    }
    function leftBorder(element) {
        return styleNumber(element, 'border-left-width')
    }
    function isBody(element) {
        return (/^(?:body|html)$/i).test(element.tagName)
    }
    function getCompatElement(element) {
        var doc = element.getDocument();
        return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body
    }
}).call(this);
Element.alias({
    position: 'setPosition'
});
[Window, Document, Element].invoke('implement', {
    getHeight: function () {
        return this.getSize().y
    },
    getWidth: function () {
        return this.getSize().x
    },
    getScrollTop: function () {
        return this.getScroll().y
    },
    getScrollLeft: function () {
        return this.getScroll().x
    },
    getScrollHeight: function () {
        return this.getScrollSize().y
    },
    getScrollWidth: function () {
        return this.getScrollSize().x
    },
    getTop: function () {
        return this.getPosition().y
    },
    getLeft: function () {
        return this.getPosition().x
    }
});
(function () {
    var Fx = this.Fx = new Class({
        Implements: [Chain, Events, Options],
        options: {
            fps: 60,
            unit: false,
            duration: 500,
            frames: null,
            frameSkip: true,
            link: 'ignore'
        },
        initialize: function (options) {
            this.subject = this.subject || this;
            this.setOptions(options)
        },
        getTransition: function () {
            return function (p) {
                return -(Math.cos(Math.PI * p) - 1) / 2
            }
        },
        step: function (now) {
            if (this.options.frameSkip) {
                var diff = (this.time != null) ? (now - this.time) : 0,
                    frames = diff / this.frameInterval;
                this.time = now;
                this.frame += frames
            } else {
                this.frame++
            }
            if (this.frame < this.frames) {
                var delta = this.transition(this.frame / this.frames);
                this.set(this.compute(this.from, this.to, delta))
            } else {
                this.frame = this.frames;
                this.set(this.compute(this.from, this.to, 1));
                this.stop()
            }
        },
        set: function (now) {
            return now
        },
        compute: function (from, to, delta) {
            return Fx.compute(from, to, delta)
        },
        check: function () {
            if (!this.isRunning()) return true;
            switch (this.options.link) {
            case 'cancel':
                this.cancel();
                return true;
            case 'chain':
                this.chain(this.caller.pass(arguments, this));
                return false
            }
            return false
        },
        start: function (from, to) {
            if (!this.check(from, to)) return this;
            this.from = from;
            this.to = to;
            this.frame = (this.options.frameSkip) ? 0 : -1;
            this.time = null;
            this.transition = this.getTransition();
            var frames = this.options.frames,
                fps = this.options.fps,
                duration = this.options.duration;
            this.duration = Fx.Durations[duration] || duration.toInt();
            this.frameInterval = 1000 / fps;
            this.frames = frames || Math.round(this.duration / this.frameInterval);
            this.fireEvent('start', this.subject);
            pushInstance.call(this, fps);
            return this
        },
        stop: function () {
            if (this.isRunning()) {
                this.time = null;
                pullInstance.call(this, this.options.fps);
                if (this.frames == this.frame) {
                    this.fireEvent('complete', this.subject);
                    if (!this.callChain()) this.fireEvent('chainComplete', this.subject)
                } else {
                    this.fireEvent('stop', this.subject)
                }
            }
            return this
        },
        cancel: function () {
            if (this.isRunning()) {
                this.time = null;
                pullInstance.call(this, this.options.fps);
                this.frame = this.frames;
                this.fireEvent('cancel', this.subject).clearChain()
            }
            return this
        },
        pause: function () {
            if (this.isRunning()) {
                this.time = null;
                pullInstance.call(this, this.options.fps)
            }
            return this
        },
        resume: function () {
            if ((this.frame < this.frames) && !this.isRunning()) pushInstance.call(this, this.options.fps);
            return this
        },
        isRunning: function () {
            var list = instances[this.options.fps];
            return list && list.contains(this)
        }
    });
    Fx.compute = function (from, to, delta) {
        return (to - from) * delta + from
    };
    Fx.Durations = {
        'short': 250,
        'normal': 500,
        'long': 1000
    };
    var instances = {},
        timers = {};
    var loop = function () {
            var now = Date.now();
            for (var i = this.length; i--;) {
                var instance = this[i];
                if (instance) instance.step(now)
            }
        };
    var pushInstance = function (fps) {
            var list = instances[fps] || (instances[fps] = []);
            list.push(this);
            if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list)
        };
    var pullInstance = function (fps) {
            var list = instances[fps];
            if (list) {
                list.erase(this);
                if (!list.length && timers[fps]) {
                    delete instances[fps];
                    timers[fps] = clearInterval(timers[fps])
                }
            }
        }
}).call(this);
Fx.CSS = new Class({
    Extends: Fx,
    prepare: function (element, property, values) {
        values = Array.from(values);
        if (values[1] == null) {
            values[1] = values[0];
            values[0] = element.getStyle(property)
        }
        var parsed = values.map(this.parse);
        return {
            from: parsed[0],
            to: parsed[1]
        }
    },
    parse: function (value) {
        value = Function.from(value)();
        value = (typeof value == 'string') ? value.split(' ') : Array.from(value);
        return value.map(function (val) {
            val = String(val);
            var found = false;
            Object.each(Fx.CSS.Parsers, function (parser, key) {
                if (found) return;
                var parsed = parser.parse(val);
                if (parsed || parsed === 0) found = {
                    value: parsed,
                    parser: parser
                }
            });
            found = found || {
                value: val,
                parser: Fx.CSS.Parsers.String
            };
            return found
        })
    },
    compute: function (from, to, delta) {
        var computed = [];
        (Math.min(from.length, to.length)).times(function (i) {
            computed.push({
                value: from[i].parser.compute(from[i].value, to[i].value, delta),
                parser: from[i].parser
            })
        });
        computed.$family = Function.from('fx:css:value');
        return computed
    },
    serve: function (value, unit) {
        if (typeOf(value) != 'fx:css:value') value = this.parse(value);
        var returned = [];
        value.each(function (bit) {
            returned = returned.concat(bit.parser.serve(bit.value, unit))
        });
        return returned
    },
    render: function (element, property, value, unit) {
        element.setStyle(property, this.serve(value, unit))
    },
    search: function (selector) {
        if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];
        var to = {},
            selectorTest = new RegExp('^' + selector.escapeRegExp() + '$');
        Array.each(document.styleSheets, function (sheet, j) {
            var href = sheet.href;
            if (href && href.contains('://') && !href.contains(document.domain)) return;
            var rules = sheet.rules || sheet.cssRules;
            Array.each(rules, function (rule, i) {
                if (!rule.style) return;
                var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function (m) {
                    return m.toLowerCase()
                }) : null;
                if (!selectorText || !selectorTest.test(selectorText)) return;
                Object.each(Element.Styles, function (value, style) {
                    if (!rule.style[style] || Element.ShortStyles[style]) return;
                    value = String(rule.style[style]);
                    to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value
                })
            })
        });
        return Fx.CSS.Cache[selector] = to
    }
});
Fx.CSS.Cache = {};
Fx.CSS.Parsers = {
    Color: {
        parse: function (value) {
            if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true);
            return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false
        },
        compute: function (from, to, delta) {
            return from.map(function (value, i) {
                return Math.round(Fx.compute(from[i], to[i], delta))
            })
        },
        serve: function (value) {
            return value.map(Number)
        }
    },
    Number: {
        parse: parseFloat,
        compute: Fx.compute,
        serve: function (value, unit) {
            return (unit) ? value + unit : value
        }
    },
    String: {
        parse: Function.from(false),
        compute: function (zero, one) {
            return one
        },
        serve: function (zero) {
            return zero
        }
    }
};
Fx.CSS.Parsers = new Hash(Fx.CSS.Parsers);
Fx.Tween = new Class({
    Extends: Fx.CSS,
    initialize: function (element, options) {
        this.element = this.subject = document.id(element);
        this.parent(options)
    },
    set: function (property, now) {
        if (arguments.length == 1) {
            now = property;
            property = this.property || this.options.property
        }
        this.render(this.element, property, now, this.options.unit);
        return this
    },
    start: function (property, from, to) {
        if (!this.check(property, from, to)) return this;
        var args = Array.flatten(arguments);
        this.property = this.options.property || args.shift();
        var parsed = this.prepare(this.element, this.property, args);
        return this.parent(parsed.from, parsed.to)
    }
});
Element.Properties.tween = {
    set: function (options) {
        this.get('tween').cancel().setOptions(options);
        return this
    },
    get: function () {
        var tween = this.retrieve('tween');
        if (!tween) {
            tween = new Fx.Tween(this, {
                link: 'cancel'
            });
            this.store('tween', tween)
        }
        return tween
    }
};
Element.implement({
    tween: function (property, from, to) {
        this.get('tween').start(arguments);
        return this
    },
    fade: function (how) {
        var fade = this.get('tween'),
            o = 'opacity',
            toggle;
        how = [how, 'toggle'].pick();
        switch (how) {
        case 'in':
            fade.start(o, 1);
            break;
        case 'out':
            fade.start(o, 0);
            break;
        case 'show':
            fade.set(o, 1);
            break;
        case 'hide':
            fade.set(o, 0);
            break;
        case 'toggle':
            var flag = this.retrieve('fade:flag', this.get('opacity') == 1);
            fade.start(o, (flag) ? 0 : 1);
            this.store('fade:flag', !flag);
            toggle = true;
            break;
        default:
            fade.start(o, arguments)
        }
        if (!toggle) this.eliminate('fade:flag');
        return this
    },
    highlight: function (start, end) {
        if (!end) {
            end = this.retrieve('highlight:original', this.getStyle('background-color'));
            end = (end == 'transparent') ? '#fff' : end
        }
        var tween = this.get('tween');
        tween.start('background-color', start || '#ffff88', end).chain(function () {
            this.setStyle('background-color', this.retrieve('highlight:original'));
            tween.callChain()
        }.bind(this));
        return this
    }
});
Fx.Morph = new Class({
    Extends: Fx.CSS,
    initialize: function (element, options) {
        this.element = this.subject = document.id(element);
        this.parent(options)
    },
    set: function (now) {
        if (typeof now == 'string') now = this.search(now);
        for (var p in now) this.render(this.element, p, now[p], this.options.unit);
        return this
    },
    compute: function (from, to, delta) {
        var now = {};
        for (var p in from) now[p] = this.parent(from[p], to[p], delta);
        return now
    },
    start: function (properties) {
        if (!this.check(properties)) return this;
        if (typeof properties == 'string') properties = this.search(properties);
        var from = {},
            to = {};
        for (var p in properties) {
            var parsed = this.prepare(this.element, p, properties[p]);
            from[p] = parsed.from;
            to[p] = parsed.to
        }
        return this.parent(from, to)
    }
});
Element.Properties.morph = {
    set: function (options) {
        this.get('morph').cancel().setOptions(options);
        return this
    },
    get: function () {
        var morph = this.retrieve('morph');
        if (!morph) {
            morph = new Fx.Morph(this, {
                link: 'cancel'
            });
            this.store('morph', morph)
        }
        return morph
    }
};
Element.implement({
    morph: function (props) {
        this.get('morph').start(props);
        return this
    }
});
Fx.implement({
    getTransition: function () {
        var trans = this.options.transition || Fx.Transitions.Sine.easeInOut;
        if (typeof trans == 'string') {
            var data = trans.split(':');
            trans = Fx.Transitions;
            trans = trans[data[0]] || trans[data[0].capitalize()];
            if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')]
        }
        return trans
    }
});
Fx.Transition = function (transition, params) {
    params = Array.from(params);
    var easeIn = function (pos) {
            return transition(pos, params)
        };
    return Object.append(easeIn, {
        easeIn: easeIn,
        easeOut: function (pos) {
            return 1 - transition(1 - pos, params)
        },
        easeInOut: function (pos) {
            return (pos <= 0.5 ? transition(2 * pos, params) : (2 - transition(2 * (1 - pos), params))) / 2
        }
    })
};
Fx.Transitions = {
    linear: function (zero) {
        return zero
    }
};
Fx.Transitions = new Hash(Fx.Transitions);
Fx.Transitions.extend = function (transitions) {
    for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition])
};
Fx.Transitions.extend({
    Pow: function (p, x) {
        return Math.pow(p, x && x[0] || 6)
    },
    Expo: function (p) {
        return Math.pow(2, 8 * (p - 1))
    },
    Circ: function (p) {
        return 1 - Math.sin(Math.acos(p))
    },
    Sine: function (p) {
        return 1 - Math.cos(p * Math.PI / 2)
    },
    Back: function (p, x) {
        x = x && x[0] || 1.618;
        return Math.pow(p, 2) * ((x + 1) * p - x)
    },
    Bounce: function (p) {
        var value;
        for (var a = 0, b = 1; 1; a += b, b /= 2) {
            if (p >= (7 - 4 * a) / 11) {
                value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2);
                break
            }
        }
        return value
    },
    Elastic: function (p, x) {
        return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3)
    }
});
['Quad', 'Cubic', 'Quart', 'Quint'].each(function (transition, i) {
    Fx.Transitions[transition] = new Fx.Transition(function (p) {
        return Math.pow(p, i + 2)
    })
});
(function () {
    var empty = function () {},
        progressSupport = ('onprogress' in new Browser.Request);
    var Request = this.Request = new Class({
        Implements: [Chain, Events, Options],
        options: {
            url: '',
            data: '',
            headers: {
                'X-Requested-With': 'XMLHttpRequest',
                'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
            },
            async: true,
            format: false,
            method: 'post',
            link: 'ignore',
            isSuccess: null,
            emulation: true,
            urlEncoded: true,
            encoding: 'utf-8',
            evalScripts: false,
            evalResponse: false,
            timeout: 0,
            noCache: false
        },
        initialize: function (options) {
            this.xhr = new Browser.Request();
            this.setOptions(options);
            this.headers = this.options.headers
        },
        onStateChange: function () {
            var xhr = this.xhr;
            if (xhr.readyState != 4 || !this.running) return;
            this.running = false;
            this.status = 0;
            Function.attempt(function () {
                var status = xhr.status;
                this.status = (status == 1223) ? 204 : status
            }.bind(this));
            xhr.onreadystatechange = empty;
            if (progressSupport) xhr.onprogress = xhr.onloadstart = empty;
            clearTimeout(this.timer);
            this.response = {
                text: this.xhr.responseText || '',
                xml: this.xhr.responseXML
            };
            if (this.options.isSuccess.call(this, this.status)) this.success(this.response.text, this.response.xml);
            else this.failure()
        },
        isSuccess: function () {
            var status = this.status;
            return (status >= 200 && status < 300)
        },
        isRunning: function () {
            return !!this.running
        },
        processScripts: function (text) {
            if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return Browser.exec(text);
            return text.stripScripts(this.options.evalScripts)
        },
        success: function (text, xml) {
            this.onSuccess(this.processScripts(text), xml)
        },
        onSuccess: function () {
            this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain()
        },
        failure: function () {
            this.onFailure()
        },
        onFailure: function () {
            this.fireEvent('complete').fireEvent('failure', this.xhr)
        },
        loadstart: function (event) {
            this.fireEvent('loadstart', [event, this.xhr])
        },
        progress: function (event) {
            this.fireEvent('progress', [event, this.xhr])
        },
        timeout: function () {
            this.fireEvent('timeout', this.xhr)
        },
        setHeader: function (name, value) {
            this.headers[name] = value;
            return this
        },
        getHeader: function (name) {
            return Function.attempt(function () {
                return this.xhr.getResponseHeader(name)
            }.bind(this))
        },
        check: function () {
            if (!this.running) return true;
            switch (this.options.link) {
            case 'cancel':
                this.cancel();
                return true;
            case 'chain':
                this.chain(this.caller.pass(arguments, this));
                return false
            }
            return false
        },
        send: function (options) {
            if (!this.check(options)) return this;
            this.options.isSuccess = this.options.isSuccess || this.isSuccess;
            this.running = true;
            var type = typeOf(options);
            if (type == 'string' || type == 'element') options = {
                data: options
            };
            var old = this.options;
            options = Object.append({
                data: old.data,
                url: old.url,
                method: old.method
            }, options);
            var data = options.data,
                url = String(options.url),
                method = options.method.toLowerCase();
            switch (typeOf(data)) {
            case 'element':
                data = document.id(data).toQueryString();
                break;
            case 'object':
            case 'hash':
                data = Object.toQueryString(data)
            }
            if (this.options.format) {
                var format = 'format=' + this.options.format;
                data = (data) ? format + '&' + data : format
            }
            if (this.options.emulation && !['get', 'post'].contains(method)) {
                var _method = '_method=' + method;
                data = (data) ? _method + '&' + data : _method;
                method = 'post'
            }
            if (this.options.urlEncoded && ['post', 'put'].contains(method)) {
                var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
                this.headers['Content-type'] = 'application/x-www-form-urlencoded' + encoding
            }
            if (!url) url = document.location.pathname;
            var trimPosition = url.lastIndexOf('/');
            if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition);
            if (this.options.noCache) url += (url.contains('?') ? '&' : '?') + String.uniqueID();
            if (data && method == 'get') {
                url += (url.contains('?') ? '&' : '?') + data;
                data = null
            }
            var xhr = this.xhr;
            if (progressSupport) {
                xhr.onloadstart = this.loadstart.bind(this);
                xhr.onprogress = this.progress.bind(this)
            }
            xhr.open(method.toUpperCase(), url, this.options.async, this.options.user, this.options.password);
            if (this.options.user && 'withCredentials' in xhr) xhr.withCredentials = true;
            xhr.onreadystatechange = this.onStateChange.bind(this);
            Object.each(this.headers, function (value, key) {
                try {
                    xhr.setRequestHeader(key, value)
                } catch (e) {
                    this.fireEvent('exception', [key, value])
                }
            }, this);
            this.fireEvent('request');
            xhr.send(data);
            if (!this.options.async) this.onStateChange();
            if (this.options.timeout) this.timer = this.timeout.delay(this.options.timeout, this);
            return this
        },
        cancel: function () {
            if (!this.running) return this;
            this.running = false;
            var xhr = this.xhr;
            xhr.abort();
            clearTimeout(this.timer);
            xhr.onreadystatechange = empty;
            if (progressSupport) xhr.onprogress = xhr.onloadstart = empty;
            this.xhr = new Browser.Request();
            this.fireEvent('cancel');
            return this
        }
    });
    var methods = {};
    ['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function (method) {
        methods[method] = function (data) {
            var object = {
                method: method
            };
            if (data != null) object.data = data;
            return this.send(object)
        }
    });
    Request.implement(methods);
    Element.Properties.send = {
        set: function (options) {
            var send = this.get('send').cancel();
            send.setOptions(options);
            return this
        },
        get: function () {
            var send = this.retrieve('send');
            if (!send) {
                send = new Request({
                    data: this,
                    link: 'cancel',
                    method: this.get('method') || 'post',
                    url: this.get('action')
                });
                this.store('send', send)
            }
            return send
        }
    };
    Element.implement({
        send: function (url) {
            var sender = this.get('send');
            sender.send({
                data: this,
                url: url || sender.options.url
            });
            return this
        }
    })
})();
Request.HTML = new Class({
    Extends: Request,
    options: {
        update: false,
        append: false,
        evalScripts: true,
        filter: false,
        headers: {
            Accept: 'text/html, application/xml, text/xml, */*'
        }
    },
    success: function (text) {
        var options = this.options,
            response = this.response;
        response.html = text.stripScripts(function (script) {
            response.javascript = script
        });
        var match = response.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
        if (match) response.html = match[1];
        var temp = new Element('div').set('html', response.html);
        response.tree = temp.childNodes;
        response.elements = temp.getElements('*');
        if (options.filter) response.tree = response.elements.filter(options.filter);
        if (options.update) document.id(options.update).empty().set('html', response.html);
        else if (options.append) document.id(options.append).adopt(temp.getChildren());
        if (options.evalScripts) Browser.exec(response.javascript);
        this.onSuccess(response.tree, response.elements, response.html, response.javascript)
    }
});
Element.Properties.load = {
    set: function (options) {
        var load = this.get('load').cancel();
        load.setOptions(options);
        return this
    },
    get: function () {
        var load = this.retrieve('load');
        if (!load) {
            load = new Request.HTML({
                data: this,
                link: 'cancel',
                update: this,
                method: 'get'
            });
            this.store('load', load)
        }
        return load
    }
};
Element.implement({
    load: function () {
        this.get('load').send(Array.link(arguments, {
            data: Type.isObject,
            url: Type.isString
        }));
        return this
    }
});
if (typeof JSON == 'undefined') this.JSON = {};
JSON = new Hash({
    stringify: JSON.stringify,
    parse: JSON.parse
});
(function () {
    var special = {
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '"': '\\"',
        '\\': '\\\\'
    };
    var escape = function (chr) {
            return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4)
        };
    JSON.validate = function (string) {
        string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, '');
        return (/^[\],:{}\s]*$/).test(string)
    };
    JSON.encode = JSON.stringify ?
    function (obj) {
        return JSON.stringify(obj)
    } : function (obj) {
        if (obj && obj.toJSON) obj = obj.toJSON();
        switch (typeOf(obj)) {
        case 'string':
            return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"';
        case 'array':
            return '[' + obj.map(JSON.encode).clean() + ']';
        case 'object':
        case 'hash':
            var string = [];
            Object.each(obj, function (value, key) {
                var json = JSON.encode(value);
                if (json) string.push(JSON.encode(key) + ':' + json)
            });
            return '{' + string + '}';
        case 'number':
        case 'boolean':
            return '' + obj;
        case 'null':
            return 'null'
        }
        return null
    };
    JSON.decode = function (string, secure) {
        if (!string || typeOf(string) != 'string') return null;
        if (secure || JSON.secure) {
            if (JSON.parse) return JSON.parse(string);
            if (!JSON.validate(string)) throw new Error('JSON could not decode the input; security is enabled and the value is not secure.')
        }
        return eval('(' + string + ')')
    }
}).call(this);
Request.JSON = new Class({
    Extends: Request,
    options: {
        secure: true
    },
    initialize: function (options) {
        this.parent(options);
        Object.append(this.headers, {
            'Accept': 'application/json',
            'X-Request': 'JSON'
        })
    },
    success: function (text) {
        var json;
        try {
            json = this.response.json = JSON.decode(text, this.options.secure)
        } catch (error) {
            this.fireEvent('error', [text, error]);
            return
        }
        if (json == null) this.onFailure();
        else this.onSuccess(json, text)
    }
});
var Cookie = new Class({
    Implements: Options,
    options: {
        path: '/',
        domain: false,
        duration: false,
        secure: false,
        document: document,
        encode: true
    },
    initialize: function (key, options) {
        this.key = key;
        this.setOptions(options)
    },
    write: function (value) {
        if (this.options.encode) value = encodeURIComponent(value);
        if (this.options.domain) value += '; domain=' + this.options.domain;
        if (this.options.path) value += '; path=' + this.options.path;
        if (this.options.duration) {
            var date = new Date();
            date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000);
            value += '; expires=' + date.toGMTString()
        }
        if (this.options.secure) value += '; secure';
        this.options.document.cookie = this.key + '=' + value;
        return this
    },
    read: function () {
        var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)');
        return (value) ? decodeURIComponent(value[1]) : null
    },
    dispose: function () {
        new Cookie(this.key, Object.merge({}, this.options, {
            duration: -1
        })).write('');
        return this
    }
});
Cookie.write = function (key, value, options) {
    return new Cookie(key, options).write(value)
};
Cookie.read = function (key) {
    return new Cookie(key).read()
};
Cookie.dispose = function (key, options) {
    return new Cookie(key, options).dispose()
};
(function (window, document) {
    var ready, loaded, checks = [],
        shouldPoll, timer, isFramed = true;
    try {
        isFramed = window.frameElement != null
    } catch (e) {}
    var domready = function () {
            clearTimeout(timer);
            if (ready) return;
            Browser.loaded = ready = true;
            document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check);
            document.fireEvent('domready');
            window.fireEvent('domready')
        };
    var check = function () {
            for (var i = checks.length; i--;) if (checks[i]()) {
                domready();
                return true
            }
            return false
        };
    var poll = function () {
            clearTimeout(timer);
            if (!check()) timer = setTimeout(poll, 10)
        };
    document.addListener('DOMContentLoaded', domready);
    var testElement = document.createElement('div');
    if (testElement.doScroll && !isFramed) {
        checks.push(function () {
            try {
                testElement.doScroll();
                return true
            } catch (e) {}
            return false
        });
        shouldPoll = true
    }
    if (document.readyState) checks.push(function () {
        var state = document.readyState;
        return (state == 'loaded' || state == 'complete')
    });
    if ('onreadystatechange' in document) document.addListener('readystatechange', check);
    else shouldPoll = true;
    if (shouldPoll) poll();
    Element.Events.domready = {
        onAdd: function (fn) {
            if (ready) fn.call(this)
        }
    };
    Element.Events.load = {
        base: 'load',
        onAdd: function (fn) {
            if (loaded && this == window) fn.call(this)
        },
        condition: function () {
            if (this == window) {
                domready();
                delete Element.Events.load
            }
            return true
        }
    };
    window.addEvent('load', function () {
        loaded = true
    })
})(window, document);
(function () {
    var Swiff = this.Swiff = new Class({
        Implements: Options,
        options: {
            id: null,
            height: 1,
            width: 1,
            container: null,
            properties: {},
            params: {
                quality: 'high',
                allowScriptAccess: 'always',
                wMode: 'window',
                swLiveConnect: true
            },
            callBacks: {},
            vars: {}
        },
        toElement: function () {
            return this.object
        },
        initialize: function (path, options) {
            this.instance = 'Swiff_' + String.uniqueID();
            this.setOptions(options);
            options = this.options;
            var id = this.id = options.id || this.instance;
            var container = document.id(options.container);
            Swiff.CallBacks[this.instance] = {};
            var params = options.params,
                vars = options.vars,
                callBacks = options.callBacks;
            var properties = Object.append({
                height: options.height,
                width: options.width
            }, options.properties);
            var self = this;
            for (var callBack in callBacks) {
                Swiff.CallBacks[this.instance][callBack] = (function (option) {
                    return function () {
                        return option.apply(self.object, arguments)
                    }
                })(callBacks[callBack]);
                vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack
            }
            params.flashVars = Object.toQueryString(vars);
            if (Browser.ie) {
                properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
                params.movie = path
            } else {
                properties.type = 'application/x-shockwave-flash'
            }
            properties.data = path;
            var build = '<object id="' + id + '"';
            for (var property in properties) build += ' ' + property + '="' + properties[property] + '"';
            build += '>';
            for (var param in params) {
                if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />'
            }
            build += '</object>';
            this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild
        },
        replaces: function (element) {
            element = document.id(element, true);
            element.parentNode.replaceChild(this.toElement(), element);
            return this
        },
        inject: function (element) {
            document.id(element, true).appendChild(this.toElement());
            return this
        },
        remote: function () {
            return Swiff.remote.apply(Swiff, [this.toElement()].append(arguments))
        }
    });
    Swiff.CallBacks = {};
    Swiff.remote = function (obj, fn) {
        var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>');
        return eval(rs)
    }
}).call(this);
var Prototype = {
    Version: '1.7',
    Browser: (function () {
        var ua = navigator.userAgent;
        var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
        return {
            IE: !! window.attachEvent && !isOpera,
            Opera: isOpera,
            WebKit: ua.indexOf('AppleWebKit/') > -1,
            Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
            MobileSafari: /Apple.*Mobile/.test(ua)
        }
    })(),
    BrowserFeatures: {
        XPath: !! document.evaluate,
        SelectorsAPI: !! document.querySelector,
        ElementExtensions: (function () {
            var constructor = window.Element || window.HTMLElement;
            return !!(constructor && constructor.prototype)
        })(),
        SpecificElementExtensions: (function () {
            if (typeof window.HTMLDivElement !== 'undefined') return true;
            var div = document.createElement('div'),
                form = document.createElement('form'),
                isSupported = false;
            if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
                isSupported = true
            }
            div = form = null;
            return isSupported
        })()
    },
    ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
    JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
    emptyFunction: function () {},
    K: function (x) {
        return x
    }
};
if (Prototype.Browser.MobileSafari) Prototype.BrowserFeatures.SpecificElementExtensions = false;
var Abstract = {};
var Try = {
    these: function () {
        var returnValue;
        for (var i = 0, length = arguments.length; i < length; i++) {
            var lambda = arguments[i];
            try {
                returnValue = lambda();
                break
            } catch (e) {}
        }
        return returnValue
    }
};
var Class = (function () {
    var IS_DONTENUM_BUGGY = (function () {
        for (var p in {
            toString: 1
        }) {
            if (p === 'toString') return false
        }
        return true
    })();

    function subclass() {};

    function create() {
        var parent = null,
            properties = $A(arguments);
        if (Object.isFunction(properties[0])) parent = properties.shift();

        function klass() {
            this.initialize.apply(this, arguments)
        }
        Object.extend(klass, Class.Methods);
        klass.superclass = parent;
        klass.subclasses = [];
        if (parent) {
            subclass.prototype = parent.prototype;
            klass.prototype = new subclass;
            parent.subclasses.push(klass)
        }
        for (var i = 0, length = properties.length; i < length; i++) klass.addMethods(properties[i]);
        if (!klass.prototype.initialize) klass.prototype.initialize = Prototype.emptyFunction;
        klass.prototype.constructor = klass;
        return klass
    }
    function addMethods(source) {
        var ancestor = this.superclass && this.superclass.prototype,
            properties = Object.keys(source);
        if (IS_DONTENUM_BUGGY) {
            if (source.toString != Object.prototype.toString) properties.push("toString");
            if (source.valueOf != Object.prototype.valueOf) properties.push("valueOf")
        }
        for (var i = 0, length = properties.length; i < length; i++) {
            var property = properties[i],
                value = source[property];
            if (ancestor && Object.isFunction(value) && value.argumentNames()[0] == "$super") {
                var method = value;
                value = (function (m) {
                    return function () {
                        return ancestor[m].apply(this, arguments)
                    }
                })(property).wrap(method);
                value.valueOf = method.valueOf.bind(method);
                value.toString = method.toString.bind(method)
            }
            this.prototype[property] = value
        }
        return this
    }
    return {
        create: create,
        Methods: {
            addMethods: addMethods
        }
    }
})();
(function () {
    var _toString = Object.prototype.toString,
        NULL_TYPE = 'Null',
        UNDEFINED_TYPE = 'Undefined',
        BOOLEAN_TYPE = 'Boolean',
        NUMBER_TYPE = 'Number',
        STRING_TYPE = 'String',
        OBJECT_TYPE = 'Object',
        FUNCTION_CLASS = '[object Function]',
        BOOLEAN_CLASS = '[object Boolean]',
        NUMBER_CLASS = '[object Number]',
        STRING_CLASS = '[object String]',
        ARRAY_CLASS = '[object Array]',
        DATE_CLASS = '[object Date]',
        NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON && typeof JSON.stringify === 'function' && JSON.stringify(0) === '0' && typeof JSON.stringify(Prototype.K) === 'undefined';

    function Type(o) {
        switch (o) {
        case null:
            return NULL_TYPE;
        case (void 0):
            return UNDEFINED_TYPE
        }
        var type = typeof o;
        switch (type) {
        case 'boolean':
            return BOOLEAN_TYPE;
        case 'number':
            return NUMBER_TYPE;
        case 'string':
            return STRING_TYPE
        }
        return OBJECT_TYPE
    }
    function extend(destination, source) {
        for (var property in source) destination[property] = source[property];
        return destination
    }
    function inspect(object) {
        try {
            if (isUndefined(object)) return 'undefined';
            if (object === null) return 'null';
            return object.inspect ? object.inspect() : String(object)
        } catch (e) {
            if (e instanceof RangeError) return '...';
            throw e
        }
    }
    function toJSON(value) {
        return Str('', {
            '': value
        }, [])
    }
    function Str(key, holder, stack) {
        var value = holder[key],
            type = typeof value;
        if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') {
            value = value.toJSON(key)
        }
        var _class = _toString.call(value);
        switch (_class) {
        case NUMBER_CLASS:
        case BOOLEAN_CLASS:
        case STRING_CLASS:
            value = value.valueOf()
        }
        switch (value) {
        case null:
            return 'null';
        case true:
            return 'true';
        case false:
            return 'false'
        }
        type = typeof value;
        switch (type) {
        case 'string':
            return value.inspect(true);
        case 'number':
            return isFinite(value) ? String(value) : 'null';
        case 'object':
            for (var i = 0, length = stack.length; i < length; i++) {
                if (stack[i] === value) {
                    throw new TypeError()
                }
            }
            stack.push(value);
            var partial = [];
            if (_class === ARRAY_CLASS) {
                for (var i = 0, length = value.length; i < length; i++) {
                    var str = Str(i, value, stack);
                    partial.push(typeof str === 'undefined' ? 'null' : str)
                }
                partial = '[' + partial.join(',') + ']'
            } else {
                var keys = Object.keys(value);
                for (var i = 0, length = keys.length; i < length; i++) {
                    var key = keys[i],
                        str = Str(key, value, stack);
                    if (typeof str !== "undefined") {
                        partial.push(key.inspect(true) + ':' + str)
                    }
                }
                partial = '{' + partial.join(',') + '}'
            }
            stack.pop();
            return partial
        }
    }
    function stringify(object) {
        return JSON.stringify(object)
    }
    function toQueryString(object) {
        return $H(object).toQueryString()
    }
    function toHTML(object) {
        return object && object.toHTML ? object.toHTML() : String.interpret(object)
    }
    function keys(object) {
        if (Type(object) !== OBJECT_TYPE) {
            throw new TypeError()
        }
        var results = [];
        for (var property in object) {
            if (object.hasOwnProperty(property)) {
                results.push(property)
            }
        }
        return results
    }
    function values(object) {
        var results = [];
        for (var property in object) results.push(object[property]);
        return results
    }
    function clone(object) {
        return extend({}, object)
    }
    function isElement(object) {
        return !!(object && object.nodeType == 1)
    }
    function isArray(object) {
        return _toString.call(object) === ARRAY_CLASS
    }
    var hasNativeIsArray = (typeof Array.isArray == 'function') && Array.isArray([]) && !Array.isArray({});
    if (hasNativeIsArray) {
        isArray = Array.isArray
    }
    function isHash(object) {
        return object instanceof Hash
    }
    function isFunction(object) {
        return _toString.call(object) === FUNCTION_CLASS
    }
    function isString(object) {
        return _toString.call(object) === STRING_CLASS
    }
    function isNumber(object) {
        return _toString.call(object) === NUMBER_CLASS
    }
    function isDate(object) {
        return _toString.call(object) === DATE_CLASS
    }
    function isUndefined(object) {
        return typeof object === "undefined"
    }
    extend(Object, {
        extend: extend,
        inspect: inspect,
        toJSON: NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,
        toQueryString: toQueryString,
        toHTML: toHTML,
        keys: Object.keys || keys,
        values: values,
        clone: clone,
        isElement: isElement,
        isArray: isArray,
        isHash: isHash,
        isFunction: isFunction,
        isString: isString,
        isNumber: isNumber,
        isDate: isDate,
        isUndefined: isUndefined
    })
})();
Object.extend(Function.prototype, (function () {
    var slice = Array.prototype.slice;

    function update(array, args) {
        var arrayLength = array.length,
            length = args.length;
        while (length--) array[arrayLength + length] = args[length];
        return array
    }
    function merge(array, args) {
        array = slice.call(array, 0);
        return update(array, args)
    }
    function argumentNames() {
        var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1].replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '').replace(/\s+/g, '').split(',');
        return names.length == 1 && !names[0] ? [] : names
    }
    function bind(context) {
        if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
        var __method = this,
            args = slice.call(arguments, 1);
        return function () {
            var a = merge(args, arguments);
            return __method.apply(context, a)
        }
    }
    function bindAsEventListener(context) {
        var __method = this,
            args = slice.call(arguments, 1);
        return function (event) {
            var a = update([event || window.event], args);
            return __method.apply(context, a)
        }
    }
    function curry() {
        if (!arguments.length) return this;
        var __method = this,
            args = slice.call(arguments, 0);
        return function () {
            var a = merge(args, arguments);
            return __method.apply(this, a)
        }
    }
    function delay(timeout) {
        var __method = this,
            args = slice.call(arguments, 1);
        timeout = timeout * 1000;
        return window.setTimeout(function () {
            return __method.apply(__method, args)
        }, timeout)
    }
    function defer() {
        var args = update([0.01], arguments);
        return this.delay.apply(this, args)
    }
    function wrap(wrapper) {
        var __method = this;
        return function () {
            var a = update([__method.bind(this)], arguments);
            return wrapper.apply(this, a)
        }
    }
    function methodize() {
        if (this._methodized) return this._methodized;
        var __method = this;
        return this._methodized = function () {
            var a = update([this], arguments);
            return __method.apply(null, a)
        }
    }
    return {
        argumentNames: argumentNames,
        bind: bind,
        bindAsEventListener: bindAsEventListener,
        curry: curry,
        delay: delay,
        defer: defer,
        wrap: wrap,
        methodize: methodize
    }
})());
(function (proto) {
    function toISOString() {
        return this.getUTCFullYear() + '-' + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + this.getUTCDate().toPaddedString(2) + 'T' + this.getUTCHours().toPaddedString(2) + ':' + this.getUTCMinutes().toPaddedString(2) + ':' + this.getUTCSeconds().toPaddedString(2) + 'Z'
    }
    function toJSON() {
        return this.toISOString()
    }
    if (!proto.toISOString) proto.toISOString = toISOString;
    if (!proto.toJSON) proto.toJSON = toJSON
})(Date.prototype);
RegExp.prototype.match = RegExp.prototype.test;
RegExp.escape = function (str) {
    return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1')
};
var PeriodicalExecuter = Class.create({
    initialize: function (callback, frequency) {
        this.callback = callback;
        this.frequency = frequency;
        this.currentlyExecuting = false;
        this.registerCallback()
    },
    registerCallback: function () {
        this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000)
    },
    execute: function () {
        this.callback(this)
    },
    stop: function () {
        if (!this.timer) return;
        clearInterval(this.timer);
        this.timer = null
    },
    onTimerEvent: function () {
        if (!this.currentlyExecuting) {
            try {
                this.currentlyExecuting = true;
                this.execute();
                this.currentlyExecuting = false
            } catch (e) {
                this.currentlyExecuting = false;
                throw e
            }
        }
    }
});
Object.extend(String, {
    interpret: function (value) {
        return value == null ? '' : String(value)
    },
    specialChar: {
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '\\': '\\\\'
    }
});
Object.extend(String.prototype, (function () {
    var NATIVE_JSON_PARSE_SUPPORT = window.JSON && typeof JSON.parse === 'function' && JSON.parse('{"test": true}').test;

    function prepareReplacement(replacement) {
        if (Object.isFunction(replacement)) return replacement;
        var template = new Template(replacement);
        return function (match) {
            return template.evaluate(match)
        }
    }
    function gsub(pattern, replacement) {
        var result = '',
            source = this,
            match;
        replacement = prepareReplacement(replacement);
        if (Object.isString(pattern)) pattern = RegExp.escape(pattern);
        if (!(pattern.length || pattern.source)) {
            replacement = replacement('');
            return replacement + source.split('').join(replacement) + replacement
        }
        while (source.length > 0) {
            if (match = source.match(pattern)) {
                result += source.slice(0, match.index);
                result += String.interpret(replacement(match));
                source = source.slice(match.index + match[0].length)
            } else {
                result += source, source = ''
            }
        }
        return result
    }
    function sub(pattern, replacement, count) {
        replacement = prepareReplacement(replacement);
        count = Object.isUndefined(count) ? 1 : count;
        return this.gsub(pattern, function (match) {
            if (--count < 0) return match[0];
            return replacement(match)
        })
    }
    function scan(pattern, iterator) {
        this.gsub(pattern, iterator);
        return String(this)
    }
    function truncate(length, truncation) {
        length = length || 30;
        truncation = Object.isUndefined(truncation) ? '...' : truncation;
        return this.length > length ? this.slice(0, length - truncation.length) + truncation : String(this)
    }
    function strip() {
        return this.replace(/^\s+/, '').replace(/\s+$/, '')
    }
    function stripTags() {
        return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '')
    }
    function stripScripts() {
        return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '')
    }
    function extractScripts() {
        var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),
            matchOne = new RegExp(Prototype.ScriptFragment, 'im');
        return (this.match(matchAll) || []).map(function (scriptTag) {
            return (scriptTag.match(matchOne) || ['', ''])[1]
        })
    }
    function evalScripts() {
        return this.extractScripts().map(function (script) {
            return eval(script)
        })
    }
    function escapeHTML() {
        return this.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
    }
    function unescapeHTML() {
        return this.stripTags().replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&')
    }
    function toQueryParams(separator) {
        var match = this.strip().match(/([^?#]*)(#.*)?$/);
        if (!match) return {};
        return match[1].split(separator || '&').inject({}, function (hash, pair) {
            if ((pair = pair.split('='))[0]) {
                var key = decodeURIComponent(pair.shift()),
                    value = pair.length > 1 ? pair.join('=') : pair[0];
                if (value != undefined) value = decodeURIComponent(value);
                if (key in hash) {
                    if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
                    hash[key].push(value)
                } else hash[key] = value
            }
            return hash
        })
    }
    function toArray() {
        return this.split('')
    }
    function succ() {
        return this.slice(0, this.length - 1) + String.fromCharCode(this.charCodeAt(this.length - 1) + 1)
    }
    function times(count) {
        return count < 1 ? '' : new Array(count + 1).join(this)
    }
    function camelize() {
        return this.replace(/-+(.)?/g, function (match, chr) {
            return chr ? chr.toUpperCase() : ''
        })
    }
    function capitalize() {
        return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase()
    }
    function underscore() {
        return this.replace(/::/g, '/').replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2').replace(/([a-z\d])([A-Z])/g, '$1_$2').replace(/-/g, '_').toLowerCase()
    }
    function dasherize() {
        return this.replace(/_/g, '-')
    }
    function inspect(useDoubleQuotes) {
        var escapedString = this.replace(/[\x00-\x1f\\]/g, function (character) {
            if (character in String.specialChar) {
                return String.specialChar[character]
            }
            return '\\u00' + character.charCodeAt().toPaddedString(2, 16)
        });
        if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
        return "'" + escapedString.replace(/'/g, '\\\'') + "'"
    }
    function unfilterJSON(filter) {
        return this.replace(filter || Prototype.JSONFilter, '$1')
    }
    function isJSON() {
        var str = this;
        if (str.blank()) return false;
        str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
        str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
        str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
        return (/^[\],:{}\s]*$/).test(str)
    }
    function evalJSON(sanitize) {
        var json = this.unfilterJSON(),
            cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
        if (cx.test(json)) {
            json = json.replace(cx, function (a) {
                return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4)
            })
        }
        try {
            if (!sanitize || json.isJSON()) return eval('(' + json + ')')
        } catch (e) {}
        throw new SyntaxError('Badly formed JSON string: ' + this.inspect())
    }
    function parseJSON() {
        var json = this.unfilterJSON();
        return JSON.parse(json)
    }
    function include(pattern) {
        return this.indexOf(pattern) > -1
    }
    function startsWith(pattern) {
        return this.lastIndexOf(pattern, 0) === 0
    }
    function endsWith(pattern) {
        var d = this.length - pattern.length;
        return d >= 0 && this.indexOf(pattern, d) === d
    }
    function empty() {
        return this == ''
    }
    function blank() {
        return /^\s*$/.test(this)
    }
    function interpolate(object, pattern) {
        return new Template(this, pattern).evaluate(object)
    }
    return {
        gsub: gsub,
        sub: sub,
        scan: scan,
        truncate: truncate,
        strip: String.prototype.trim || strip,
        stripTags: stripTags,
        stripScripts: stripScripts,
        extractScripts: extractScripts,
        evalScripts: evalScripts,
        escapeHTML: escapeHTML,
        unescapeHTML: unescapeHTML,
        toQueryParams: toQueryParams,
        parseQuery: toQueryParams,
        toArray: toArray,
        succ: succ,
        times: times,
        camelize: camelize,
        capitalize: capitalize,
        underscore: underscore,
        dasherize: dasherize,
        inspect: inspect,
        unfilterJSON: unfilterJSON,
        isJSON: isJSON,
        evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,
        include: include,
        startsWith: startsWith,
        endsWith: endsWith,
        empty: empty,
        blank: blank,
        interpolate: interpolate
    }
})());
var Template = Class.create({
    initialize: function (template, pattern) {
        this.template = template.toString();
        this.pattern = pattern || Template.Pattern
    },
    evaluate: function (object) {
        if (object && Object.isFunction(object.toTemplateReplacements)) object = object.toTemplateReplacements();
        return this.template.gsub(this.pattern, function (match) {
            if (object == null) return (match[1] + '');
            var before = match[1] || '';
            if (before == '\\') return match[2];
            var ctx = object,
                expr = match[3],
                pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
            match = pattern.exec(expr);
            if (match == null) return before;
            while (match != null) {
                var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
                ctx = ctx[comp];
                if (null == ctx || '' == match[3]) break;
                expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
                match = pattern.exec(expr)
            }
            return before + String.interpret(ctx)
        })
    }
});
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
var $break = {};
var Enumerable = (function () {
    function each(iterator, context) {
        var index = 0;
        try {
            this._each(function (value) {
                iterator.call(context, value, index++)
            })
        } catch (e) {
            if (e != $break) throw e
        }
        return this
    }
    function eachSlice(number, iterator, context) {
        var index = -number,
            slices = [],
            array = this.toArray();
        if (number < 1) return array;
        while ((index += number) < array.length) slices.push(array.slice(index, index + number));
        return slices.collect(iterator, context)
    }
    function all(iterator, context) {
        iterator = iterator || Prototype.K;
        var result = true;
        this.each(function (value, index) {
            result = result && !! iterator.call(context, value, index);
            if (!result) throw $break
        });
        return result
    }
    function any(iterator, context) {
        iterator = iterator || Prototype.K;
        var result = false;
        this.each(function (value, index) {
            if (result = !! iterator.call(context, value, index)) throw $break
        });
        return result
    }
    function collect(iterator, context) {
        iterator = iterator || Prototype.K;
        var results = [];
        this.each(function (value, index) {
            results.push(iterator.call(context, value, index))
        });
        return results
    }
    function detect(iterator, context) {
        var result;
        this.each(function (value, index) {
            if (iterator.call(context, value, index)) {
                result = value;
                throw $break
            }
        });
        return result
    }
    function findAll(iterator, context) {
        var results = [];
        this.each(function (value, index) {
            if (iterator.call(context, value, index)) results.push(value)
        });
        return results
    }
    function grep(filter, iterator, context) {
        iterator = iterator || Prototype.K;
        var results = [];
        if (Object.isString(filter)) filter = new RegExp(RegExp.escape(filter));
        this.each(function (value, index) {
            if (filter.match(value)) results.push(iterator.call(context, value, index))
        });
        return results
    }
    function include(object) {
        if (Object.isFunction(this.indexOf)) if (this.indexOf(object) != -1) return true;
        var found = false;
        this.each(function (value) {
            if (value == object) {
                found = true;
                throw $break
            }
        });
        return found
    }
    function inGroupsOf(number, fillWith) {
        fillWith = Object.isUndefined(fillWith) ? null : fillWith;
        return this.eachSlice(number, function (slice) {
            while (slice.length < number) slice.push(fillWith);
            return slice
        })
    }
    function inject(memo, iterator, context) {
        this.each(function (value, index) {
            memo = iterator.call(context, memo, value, index)
        });
        return memo
    }
    function invoke(method) {
        var args = $A(arguments).slice(1);
        return this.map(function (value) {
            return value[method].apply(value, args)
        })
    }
    function max(iterator, context) {
        iterator = iterator || Prototype.K;
        var result;
        this.each(function (value, index) {
            value = iterator.call(context, value, index);
            if (result == null || value >= result) result = value
        });
        return result
    }
    function min(iterator, context) {
        iterator = iterator || Prototype.K;
        var result;
        this.each(function (value, index) {
            value = iterator.call(context, value, index);
            if (result == null || value < result) result = value
        });
        return result
    }
    function partition(iterator, context) {
        iterator = iterator || Prototype.K;
        var trues = [],
            falses = [];
        this.each(function (value, index) {
            (iterator.call(context, value, index) ? trues : falses).push(value)
        });
        return [trues, falses]
    }
    function pluck(property) {
        var results = [];
        this.each(function (value) {
            results.push(value[property])
        });
        return results
    }
    function reject(iterator, context) {
        var results = [];
        this.each(function (value, index) {
            if (!iterator.call(context, value, index)) results.push(value)
        });
        return results
    }
    function sortBy(iterator, context) {
        return this.map(function (value, index) {
            return {
                value: value,
                criteria: iterator.call(context, value, index)
            }
        }).sort(function (left, right) {
            var a = left.criteria,
                b = right.criteria;
            return a < b ? -1 : a > b ? 1 : 0
        }).pluck('value')
    }
    function toArray() {
        return this.map()
    }
    function zip() {
        var iterator = Prototype.K,
            args = $A(arguments);
        if (Object.isFunction(args.last())) iterator = args.pop();
        var collections = [this].concat(args).map($A);
        return this.map(function (value, index) {
            return iterator(collections.pluck(index))
        })
    }
    function size() {
        return this.toArray().length
    }
    function inspect() {
        return '#<Enumerable:' + this.toArray().inspect() + '>'
    }
    return {
        each: each,
        eachSlice: eachSlice,
        all: all,
        every: all,
        any: any,
        some: any,
        collect: collect,
        map: collect,
        detect: detect,
        findAll: findAll,
        select: findAll,
        filter: findAll,
        grep: grep,
        include: include,
        member: include,
        inGroupsOf: inGroupsOf,
        inject: inject,
        invoke: invoke,
        max: max,
        min: min,
        partition: partition,
        pluck: pluck,
        reject: reject,
        sortBy: sortBy,
        toArray: toArray,
        entries: toArray,
        zip: zip,
        size: size,
        inspect: inspect,
        find: detect
    }
})();

function $A(iterable) {
    if (!iterable) return [];
    if ('toArray' in Object(iterable)) return iterable.toArray();
    var length = iterable.length || 0,
        results = new Array(length);
    while (length--) results[length] = iterable[length];
    return results
}
function $w(string) {
    if (!Object.isString(string)) return [];
    string = string.strip();
    return string ? string.split(/\s+/) : []
}
Array.from = $A;
(function () {
    var arrayProto = Array.prototype,
        slice = arrayProto.slice,
        _each = arrayProto.forEach;

    function each(iterator, context) {
        for (var i = 0, length = this.length >>> 0; i < length; i++) {
            if (i in this) iterator.call(context, this[i], i, this)
        }
    }
    if (!_each) _each = each;

    function clear() {
        this.length = 0;
        return this
    }
    function first() {
        return this[0]
    }
    function last() {
        return this[this.length - 1]
    }
    function compact() {
        return this.select(function (value) {
            return value != null
        })
    }
    function flatten() {
        return this.inject([], function (array, value) {
            if (Object.isArray(value)) return array.concat(value.flatten());
            array.push(value);
            return array
        })
    }
    function without() {
        var values = slice.call(arguments, 0);
        return this.select(function (value) {
            return !values.include(value)
        })
    }
    function reverse(inline) {
        return (inline === false ? this.toArray() : this)._reverse()
    }
    function uniq(sorted) {
        return this.inject([], function (array, value, index) {
            if (0 == index || (sorted ? array.last() != value : !array.include(value))) array.push(value);
            return array
        })
    }
    function intersect(array) {
        return this.uniq().findAll(function (item) {
            return array.detect(function (value) {
                return item === value
            })
        })
    }
    function clone() {
        return slice.call(this, 0)
    }
    function size() {
        return this.length
    }
    function inspect() {
        return '[' + this.map(Object.inspect).join(', ') + ']'
    }
    function indexOf(item, i) {
        i || (i = 0);
        var length = this.length;
        if (i < 0) i = length + i;
        for (; i < length; i++) if (this[i] === item) return i;
        return -1
    }
    function lastIndexOf(item, i) {
        i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
        var n = this.slice(0, i).reverse().indexOf(item);
        return (n < 0) ? n : i - n - 1
    }
    function concat() {
        var array = slice.call(this, 0),
            item;
        for (var i = 0, length = arguments.length; i < length; i++) {
            item = arguments[i];
            if (Object.isArray(item) && !('callee' in item)) {
                for (var j = 0, arrayLength = item.length; j < arrayLength; j++) array.push(item[j])
            } else {
                array.push(item)
            }
        }
        return array
    }
    Object.extend(arrayProto, Enumerable);
    if (!arrayProto._reverse) arrayProto._reverse = arrayProto.reverse;
    Object.extend(arrayProto, {
        _each: _each,
        clear: clear,
        first: first,
        last: last,
        compact: compact,
        flatten: flatten,
        without: without,
        reverse: reverse,
        uniq: uniq,
        intersect: intersect,
        clone: clone,
        toArray: clone,
        size: size,
        inspect: inspect
    });
    var CONCAT_ARGUMENTS_BUGGY = (function () {
        return [].concat(arguments)[0][0] !== 1
    })(1, 2) if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
    if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
    if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf
})();

function $H(object) {
    return new Hash(object)
};
var Hash = Class.create(Enumerable, (function () {
    function initialize(object) {
        this._object = Object.isHash(object) ? object.toObject() : Object.clone(object)
    }
    function _each(iterator) {
        for (var key in this._object) {
            var value = this._object[key],
                pair = [key, value];
            pair.key = key;
            pair.value = value;
            iterator(pair)
        }
    }
    function set(key, value) {
        return this._object[key] = value
    }
    function get(key) {
        if (this._object[key] !== Object.prototype[key]) return this._object[key]
    }
    function unset(key) {
        var value = this._object[key];
        delete this._object[key];
        return value
    }
    function toObject() {
        return Object.clone(this._object)
    }
    function keys() {
        return this.pluck('key')
    }
    function values() {
        return this.pluck('value')
    }
    function index(value) {
        var match = this.detect(function (pair) {
            return pair.value === value
        });
        return match && match.key
    }
    function merge(object) {
        return this.clone().update(object)
    }
    function update(object) {
        return new Hash(object).inject(this, function (result, pair) {
            result.set(pair.key, pair.value);
            return result
        })
    }
    function toQueryPair(key, value) {
        if (Object.isUndefined(value)) return key;
        return key + '=' + encodeURIComponent(String.interpret(value))
    }
    function toQueryString() {
        return this.inject([], function (results, pair) {
            var key = encodeURIComponent(pair.key),
                values = pair.value;
            if (values && typeof values == 'object') {
                if (Object.isArray(values)) {
                    var queryValues = [];
                    for (var i = 0, len = values.length, value; i < len; i++) {
                        value = values[i];
                        queryValues.push(toQueryPair(key, value))
                    }
                    return results.concat(queryValues)
                }
            } else results.push(toQueryPair(key, values));
            return results
        }).join('&')
    }
    function inspect() {
        return '#<Hash:{' + this.map(function (pair) {
            return pair.map(Object.inspect).join(': ')
        }).join(', ') + '}>'
    }
    function clone() {
        return new Hash(this)
    }
    return {
        initialize: initialize,
        _each: _each,
        set: set,
        get: get,
        unset: unset,
        toObject: toObject,
        toTemplateReplacements: toObject,
        keys: keys,
        values: values,
        index: index,
        merge: merge,
        update: update,
        toQueryString: toQueryString,
        inspect: inspect,
        toJSON: toObject,
        clone: clone
    }
})());
Hash.from = $H;
Object.extend(Number.prototype, (function () {
    function toColorPart() {
        return this.toPaddedString(2, 16)
    }
    function succ() {
        return this + 1
    }
    function times(iterator, context) {
        $R(0, this, true).each(iterator, context);
        return this
    }
    function toPaddedString(length, radix) {
        var string = this.toString(radix || 10);
        return '0'.times(length - string.length) + string
    }
    function abs() {
        return Math.abs(this)
    }
    function round() {
        return Math.round(this)
    }
    function ceil() {
        return Math.ceil(this)
    }
    function floor() {
        return Math.floor(this)
    }
    return {
        toColorPart: toColorPart,
        succ: succ,
        times: times,
        toPaddedString: toPaddedString,
        abs: abs,
        round: round,
        ceil: ceil,
        floor: floor
    }
})());

function $R(start, end, exclusive) {
    return new ObjectRange(start, end, exclusive)
}
var ObjectRange = Class.create(Enumerable, (function () {
    function initialize(start, end, exclusive) {
        this.start = start;
        this.end = end;
        this.exclusive = exclusive
    }
    function _each(iterator) {
        var value = this.start;
        while (this.include(value)) {
            iterator(value);
            value = value.succ()
        }
    }
    function include(value) {
        if (value < this.start) return false;
        if (this.exclusive) return value < this.end;
        return value <= this.end
    }
    return {
        initialize: initialize,
        _each: _each,
        include: include
    }
})());
var Ajax = {
    getTransport: function () {
        return Try.these(function () {
            return new XMLHttpRequest()
        }, function () {
            return new ActiveXObject('Msxml2.XMLHTTP')
        }, function () {
            return new ActiveXObject('Microsoft.XMLHTTP')
        }) || false
    },
    activeRequestCount: 0
};
Ajax.Responders = {
    responders: [],
    _each: function (iterator) {
        this.responders._each(iterator)
    },
    register: function (responder) {
        if (!this.include(responder)) this.responders.push(responder)
    },
    unregister: function (responder) {
        this.responders = this.responders.without(responder)
    },
    dispatch: function (callback, request, transport, json) {
        this.each(function (responder) {
            if (Object.isFunction(responder[callback])) {
                try {
                    responder[callback].apply(responder, [request, transport, json])
                } catch (e) {}
            }
        })
    }
};
Object.extend(Ajax.Responders, Enumerable);
Ajax.Responders.register({
    onCreate: function () {
        Ajax.activeRequestCount++
    },
    onComplete: function () {
        Ajax.activeRequestCount--
    }
});
Ajax.Base = Class.create({
    initialize: function (options) {
        this.options = {
            method: 'post',
            asynchronous: true,
            contentType: 'application/x-www-form-urlencoded',
            encoding: 'UTF-8',
            parameters: '',
            evalJSON: true,
            evalJS: true
        };
        Object.extend(this.options, options || {});
        this.options.method = this.options.method.toLowerCase();
        if (Object.isHash(this.options.parameters)) this.options.parameters = this.options.parameters.toObject()
    }
});
Ajax.Request = Class.create(Ajax.Base, {
    _complete: false,
    initialize: function ($super, url, options) {
        $super(options);
        this.transport = Ajax.getTransport();
        this.request(url)
    },
    request: function (url) {
        this.url = url;
        this.method = this.options.method;
        var params = Object.isString(this.options.parameters) ? this.options.parameters : Object.toQueryString(this.options.parameters);
        if (!['get', 'post'].include(this.method)) {
            params += (params ? '&' : '') + "_method=" + this.method;
            this.method = 'post'
        }
        if (params && this.method === 'get') {
            this.url += (this.url.include('?') ? '&' : '?') + params
        }
        this.parameters = params.toQueryParams();
        try {
            var response = new Ajax.Response(this);
            if (this.options.onCreate) this.options.onCreate(response);
            Ajax.Responders.dispatch('onCreate', this, response);
            this.transport.open(this.method.toUpperCase(), this.url, this.options.asynchronous);
            if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
            this.transport.onreadystatechange = this.onStateChange.bind(this);
            this.setRequestHeaders();
            this.body = this.method == 'post' ? (this.options.postBody || params) : null;
            this.transport.send(this.body);
            if (!this.options.asynchronous && this.transport.overrideMimeType) this.onStateChange()
        } catch (e) {
            this.dispatchException(e)
        }
    },
    onStateChange: function () {
        var readyState = this.transport.readyState;
        if (readyState > 1 && !((readyState == 4) && this._complete)) this.respondToReadyState(this.transport.readyState)
    },
    setRequestHeaders: function () {
        var headers = {
            'X-Requested-With': 'XMLHttpRequest',
            'X-Prototype-Version': Prototype.Version,
            'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
        };
        if (this.method == 'post') {
            headers['Content-type'] = this.options.contentType + (this.options.encoding ? '; charset=' + this.options.encoding : '');
            if (this.transport.overrideMimeType && (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0, 2005])[1] < 2005) headers['Connection'] = 'close'
        }
        if (typeof this.options.requestHeaders == 'object') {
            var extras = this.options.requestHeaders;
            if (Object.isFunction(extras.push)) for (var i = 0, length = extras.length; i < length; i += 2) headers[extras[i]] = extras[i + 1];
            else $H(extras).each(function (pair) {
                headers[pair.key] = pair.value
            })
        }
        for (var name in headers) this.transport.setRequestHeader(name, headers[name])
    },
    success: function () {
        var status = this.getStatus();
        return !status || (status >= 200 && status < 300) || status == 304
    },
    getStatus: function () {
        try {
            if (this.transport.status === 1223) return 204;
            return this.transport.status || 0
        } catch (e) {
            return 0
        }
    },
    respondToReadyState: function (readyState) {
        var state = Ajax.Request.Events[readyState],
            response = new Ajax.Response(this);
        if (state == 'Complete') {
            try {
                this._complete = true;
                (this.options['on' + response.status] || this.options['on' + (this.success() ? 'Success' : 'Failure')] || Prototype.emptyFunction)(response, response.headerJSON)
            } catch (e) {
                this.dispatchException(e)
            }
            var contentType = response.getHeader('Content-type');
            if (this.options.evalJS == 'force' || (this.options.evalJS && this.isSameOrigin() && contentType && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) this.evalResponse()
        }
        try {
            (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
            Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON)
        } catch (e) {
            this.dispatchException(e)
        }
        if (state == 'Complete') {
            this.transport.onreadystatechange = Prototype.emptyFunction
        }
    },
    isSameOrigin: function () {
        var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
        return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
            protocol: location.protocol,
            domain: document.domain,
            port: location.port ? ':' + location.port : ''
        }))
    },
    getHeader: function (name) {
        try {
            return this.transport.getResponseHeader(name) || null
        } catch (e) {
            return null
        }
    },
    evalResponse: function () {
        try {
            return eval((this.transport.responseText || '').unfilterJSON())
        } catch (e) {
            this.dispatchException(e)
        }
    },
    dispatchException: function (exception) {
        (this.options.onException || Prototype.emptyFunction)(this, exception);
        Ajax.Responders.dispatch('onException', this, exception)
    }
});
Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
Ajax.Response = Class.create({
    initialize: function (request) {
        this.request = request;
        var transport = this.transport = request.transport,
            readyState = this.readyState = transport.readyState;
        if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
            this.status = this.getStatus();
            this.statusText = this.getStatusText();
            this.responseText = String.interpret(transport.responseText);
            this.headerJSON = this._getHeaderJSON()
        }
        if (readyState == 4) {
            var xml = transport.responseXML;
            this.responseXML = Object.isUndefined(xml) ? null : xml;
            this.responseJSON = this._getResponseJSON()
        }
    },
    status: 0,
    statusText: '',
    getStatus: Ajax.Request.prototype.getStatus,
    getStatusText: function () {
        try {
            return this.transport.statusText || ''
        } catch (e) {
            return ''
        }
    },
    getHeader: Ajax.Request.prototype.getHeader,
    getAllHeaders: function () {
        try {
            return this.getAllResponseHeaders()
        } catch (e) {
            return null
        }
    },
    getResponseHeader: function (name) {
        return this.transport.getResponseHeader(name)
    },
    getAllResponseHeaders: function () {
        return this.transport.getAllResponseHeaders()
    },
    _getHeaderJSON: function () {
        var json = this.getHeader('X-JSON');
        if (!json) return null;
        json = decodeURIComponent(escape(json));
        try {
            return json.evalJSON(this.request.options.sanitizeJSON || !this.request.isSameOrigin())
        } catch (e) {
            this.request.dispatchException(e)
        }
    },
    _getResponseJSON: function () {
        var options = this.request.options;
        if (!options.evalJSON || (options.evalJSON != 'force' && !(this.getHeader('Content-type') || '').include('application/json')) || this.responseText.blank()) return null;
        try {
            return this.responseText.evalJSON(options.sanitizeJSON || !this.request.isSameOrigin())
        } catch (e) {
            this.request.dispatchException(e)
        }
    }
});
Ajax.Updater = Class.create(Ajax.Request, {
    initialize: function ($super, container, url, options) {
        this.container = {
            success: (container.success || container),
            failure: (container.failure || (container.success ? null : container))
        };
        options = Object.clone(options);
        var onComplete = options.onComplete;
        options.onComplete = (function (response, json) {
            this.updateContent(response.responseText);
            if (Object.isFunction(onComplete)) onComplete(response, json)
        }).bind(this);
        $super(url, options)
    },
    updateContent: function (responseText) {
        var receiver = this.container[this.success() ? 'success' : 'failure'],
            options = this.options;
        if (!options.evalScripts) responseText = responseText.stripScripts();
        if (receiver = $(receiver)) {
            if (options.insertion) {
                if (Object.isString(options.insertion)) {
                    var insertion = {};
                    insertion[options.insertion] = responseText;
                    receiver.insert(insertion)
                } else options.insertion(receiver, responseText)
            } else receiver.update(responseText)
        }
    }
});
Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
    initialize: function ($super, container, url, options) {
        $super(options);
        this.onComplete = this.options.onComplete;
        this.frequency = (this.options.frequency || 2);
        this.decay = (this.options.decay || 1);
        this.updater = {};
        this.container = container;
        this.url = url;
        this.start()
    },
    start: function () {
        this.options.onComplete = this.updateComplete.bind(this);
        this.onTimerEvent()
    },
    stop: function () {
        this.updater.options.onComplete = undefined;
        clearTimeout(this.timer);
        (this.onComplete || Prototype.emptyFunction).apply(this, arguments)
    },
    updateComplete: function (response) {
        if (this.options.decay) {
            this.decay = (response.responseText == this.lastText ? this.decay * this.options.decay : 1);
            this.lastText = response.responseText
        }
        this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency)
    },
    onTimerEvent: function () {
        this.updater = new Ajax.Updater(this.container, this.url, this.options)
    }
});

function $(element) {
    if (arguments.length > 1) {
        for (var i = 0, elements = [], length = arguments.length; i < length; i++) elements.push($(arguments[i]));
        return elements
    }
    if (Object.isString(element)) element = document.getElementById(element);
    return Element.extend(element)
}
if (Prototype.BrowserFeatures.XPath) {
    document._getElementsByXPath = function (expression, parentElement) {
        var results = [];
        var query = document.evaluate(expression, $(parentElement) || document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
        for (var i = 0, length = query.snapshotLength; i < length; i++) results.push(Element.extend(query.snapshotItem(i)));
        return results
    }
}
if (!Node) var Node = {};
if (!Node.ELEMENT_NODE) {
    Object.extend(Node, {
        ELEMENT_NODE: 1,
        ATTRIBUTE_NODE: 2,
        TEXT_NODE: 3,
        CDATA_SECTION_NODE: 4,
        ENTITY_REFERENCE_NODE: 5,
        ENTITY_NODE: 6,
        PROCESSING_INSTRUCTION_NODE: 7,
        COMMENT_NODE: 8,
        DOCUMENT_NODE: 9,
        DOCUMENT_TYPE_NODE: 10,
        DOCUMENT_FRAGMENT_NODE: 11,
        NOTATION_NODE: 12
    })
}(function (global) {
    function shouldUseCache(tagName, attributes) {
        if (tagName === 'select') return false;
        if ('type' in attributes) return false;
        return true
    }
    var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function () {
        try {
            var el = document.createElement('<input name="x">');
            return el.tagName.toLowerCase() === 'input' && el.name === 'x'
        } catch (err) {
            return false
        }
    })();
    var element = global.Element;
    global.Element = function (tagName, attributes) {
        attributes = attributes || {};
        tagName = tagName.toLowerCase();
        var cache = Element.cache;
        if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {
            tagName = '<' + tagName + ' name="' + attributes.name + '">';
            delete attributes.name;
            return Element.writeAttribute(document.createElement(tagName), attributes)
        }
        if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
        var node = shouldUseCache(tagName, attributes) ? cache[tagName].cloneNode(false) : document.createElement(tagName);
        return Element.writeAttribute(node, attributes)
    };
    Object.extend(global.Element, element || {});
    if (element) global.Element.prototype = element.prototype
})(this);
Element.idCounter = 1;
Element.cache = {};
Element._purgeElement = function (element) {
    var uid = element._prototypeUID;
    if (uid) {
        Element.stopObserving(element);
        element._prototypeUID = void 0;
        delete Element.Storage[uid]
    }
}
Element.Methods = {
    visible: function (element) {
        return $(element).style.display != 'none'
    },
    toggle: function (element) {
        element = $(element);
        Element[Element.visible(element) ? 'hide' : 'show'](element);
        return element
    },
    hide: function (element) {
        element = $(element);
        element.style.display = 'none';
        return element
    },
    show: function (element) {
        element = $(element);
        element.style.display = '';
        return element
    },
    remove: function (element) {
        element = $(element);
        element.parentNode.removeChild(element);
        return element
    },
    update: (function () {
        var SELECT_ELEMENT_INNERHTML_BUGGY = (function () {
            var el = document.createElement("select"),
                isBuggy = true;
            el.innerHTML = "<option value=\"test\">test</option>";
            if (el.options && el.options[0]) {
                isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"
            }
            el = null;
            return isBuggy
        })();
        var TABLE_ELEMENT_INNERHTML_BUGGY = (function () {
            try {
                var el = document.createElement("table");
                if (el && el.tBodies) {
                    el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
                    var isBuggy = typeof el.tBodies[0] == "undefined";
                    el = null;
                    return isBuggy
                }
            } catch (e) {
                return true
            }
        })();
        var LINK_ELEMENT_INNERHTML_BUGGY = (function () {
            try {
                var el = document.createElement('div');
                el.innerHTML = "<link>";
                var isBuggy = (el.childNodes.length === 0);
                el = null;
                return isBuggy
            } catch (e) {
                return true
            }
        })();
        var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;
        var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
            var s = document.createElement("script"),
                isBuggy = false;
            try {
                s.appendChild(document.createTextNode(""));
                isBuggy = !s.firstChild || s.firstChild && s.firstChild.nodeType !== 3
            } catch (e) {
                isBuggy = true
            }
            s = null;
            return isBuggy
        })();

        function update(element, content) {
            element = $(element);
            var purgeElement = Element._purgeElement;
            var descendants = element.getElementsByTagName('*'),
                i = descendants.length;
            while (i--) purgeElement(descendants[i]);
            if (content && content.toElement) content = content.toElement();
            if (Object.isElement(content)) return element.update().insert(content);
            content = Object.toHTML(content);
            var tagName = element.tagName.toUpperCase();
            if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
                element.text = content;
                return element
            }
            if (ANY_INNERHTML_BUGGY) {
                if (tagName in Element._insertionTranslations.tags) {
                    while (element.firstChild) {
                        element.removeChild(element.firstChild)
                    }
                    Element._getContentFromAnonymousElement(tagName, content.stripScripts()).each(function (node) {
                        element.appendChild(node)
                    })
                } else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {
                    while (element.firstChild) {
                        element.removeChild(element.firstChild)
                    }
                    var nodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts(), true);
                    nodes.each(function (node) {
                        element.appendChild(node)
                    })
                } else {
                    element.innerHTML = content.stripScripts()
                }
            } else {
                element.innerHTML = content.stripScripts()
            }
            content.evalScripts.bind(content).defer();
            return element
        }
        return update
    })(),
    replace: function (element, content) {
        element = $(element);
        if (content && content.toElement) content = content.toElement();
        else if (!Object.isElement(content)) {
            content = Object.toHTML(content);
            var range = element.ownerDocument.createRange();
            range.selectNode(element);
            content.evalScripts.bind(content).defer();
            content = range.createContextualFragment(content.stripScripts())
        }
        element.parentNode.replaceChild(content, element);
        return element
    },
    insert: function (element, insertions) {
        element = $(element);
        if (Object.isString(insertions) || Object.isNumber(insertions) || Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) insertions = {
            bottom: insertions
        };
        var content, insert, tagName, childNodes;
        for (var position in insertions) {
            content = insertions[position];
            position = position.toLowerCase();
            insert = Element._insertionTranslations[position];
            if (content && content.toElement) content = content.toElement();
            if (Object.isElement(content)) {
                insert(element, content);
                continue
            }
            content = Object.toHTML(content);
            tagName = ((position == 'before' || position == 'after') ? element.parentNode : element).tagName.toUpperCase();
            childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
            if (position == 'top' || position == 'after') childNodes.reverse();
            childNodes.each(insert.curry(element));
            content.evalScripts.bind(content).defer()
        }
        return element
    },
    wrap: function (element, wrapper, attributes) {
        element = $(element);
        if (Object.isElement(wrapper)) $(wrapper).writeAttribute(attributes || {});
        else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
        else wrapper = new Element('div', wrapper);
        if (element.parentNode) element.parentNode.replaceChild(wrapper, element);
        wrapper.appendChild(element);
        return wrapper
    },
    inspect: function (element) {
        element = $(element);
        var result = '<' + element.tagName.toLowerCase();
        $H({
            'id': 'id',
            'className': 'class'
        }).each(function (pair) {
            var property = pair.first(),
                attribute = pair.last(),
                value = (element[property] || '').toString();
            if (value) result += ' ' + attribute + '=' + value.inspect(true)
        });
        return result + '>'
    },
    recursivelyCollect: function (element, property, maximumLength) {
        element = $(element);
        maximumLength = maximumLength || -1;
        var elements = [];
        while (element = element[property]) {
            if (element.nodeType == 1) elements.push(Element.extend(element));
            if (elements.length == maximumLength) break
        }
        return elements
    },
    ancestors: function (element) {
        return Element.recursivelyCollect(element, 'parentNode')
    },
    descendants: function (element) {
        return Element.select(element, "*")
    },
    firstDescendant: function (element) {
        element = $(element).firstChild;
        while (element && element.nodeType != 1) element = element.nextSibling;
        return $(element)
    },
    immediateDescendants: function (element) {
        var results = [],
            child = $(element).firstChild;
        while (child) {
            if (child.nodeType === 1) {
                results.push(Element.extend(child))
            }
            child = child.nextSibling
        }
        return results
    },
    previousSiblings: function (element, maximumLength) {
        return Element.recursivelyCollect(element, 'previousSibling')
    },
    nextSiblings: function (element) {
        return Element.recursivelyCollect(element, 'nextSibling')
    },
    siblings: function (element) {
        element = $(element);
        return Element.previousSiblings(element).reverse().concat(Element.nextSiblings(element))
    },
    match: function (element, selector) {
        element = $(element);
        if (Object.isString(selector)) return Prototype.Selector.match(element, selector);
        return selector.match(element)
    },
    up: function (element, expression, index) {
        element = $(element);
        if (arguments.length == 1) return $(element.parentNode);
        var ancestors = Element.ancestors(element);
        return Object.isNumber(expression) ? ancestors[expression] : Prototype.Selector.find(ancestors, expression, index)
    },
    down: function (element, expression, index) {
        element = $(element);
        if (arguments.length == 1) return Element.firstDescendant(element);
        return Object.isNumber(expression) ? Element.descendants(element)[expression] : Element.select(element, expression)[index || 0]
    },
    previous: function (element, expression, index) {
        element = $(element);
        if (Object.isNumber(expression)) index = expression, expression = false;
        if (!Object.isNumber(index)) index = 0;
        if (expression) {
            return Prototype.Selector.find(element.previousSiblings(), expression, index)
        } else {
            return element.recursivelyCollect("previousSibling", index + 1)[index]
        }
    },
    next: function (element, expression, index) {
        element = $(element);
        if (Object.isNumber(expression)) index = expression, expression = false;
        if (!Object.isNumber(index)) index = 0;
        if (expression) {
            return Prototype.Selector.find(element.nextSiblings(), expression, index)
        } else {
            var maximumLength = Object.isNumber(index) ? index + 1 : 1;
            return element.recursivelyCollect("nextSibling", index + 1)[index]
        }
    },
    select: function (element) {
        element = $(element);
        var expressions = Array.prototype.slice.call(arguments, 1).join(', ');
        return Prototype.Selector.select(expressions, element)
    },
    adjacent: function (element) {
        element = $(element);
        var expressions = Array.prototype.slice.call(arguments, 1).join(', ');
        return Prototype.Selector.select(expressions, element.parentNode).without(element)
    },
    identify: function (element) {
        element = $(element);
        var id = Element.readAttribute(element, 'id');
        if (id) return id;
        do {
            id = 'anonymous_element_' + Element.idCounter++
        } while ($(id));
        Element.writeAttribute(element, 'id', id);
        return id
    },
    readAttribute: function (element, name) {
        element = $(element);
        if (Prototype.Browser.IE) {
            var t = Element._attributeTranslations.read;
            if (t.values[name]) return t.values[name](element, name);
            if (t.names[name]) name = t.names[name];
            if (name.include(':')) {
                return (!element.attributes || !element.attributes[name]) ? null : element.attributes[name].value
            }
        }
        return element.getAttribute(name)
    },
    writeAttribute: function (element, name, value) {
        element = $(element);
        var attributes = {},
            t = Element._attributeTranslations.write;
        if (typeof name == 'object') attributes = name;
        else attributes[name] = Object.isUndefined(value) ? true : value;
        for (var attr in attributes) {
            name = t.names[attr] || attr;
            value = attributes[attr];
            if (t.values[attr]) name = t.values[attr](element, value);
            if (value === false || value === null) element.removeAttribute(name);
            else if (value === true) element.setAttribute(name, name);
            else element.setAttribute(name, value)
        }
        return element
    },
    getHeight: function (element) {
        return Element.getDimensions(element).height
    },
    getWidth: function (element) {
        return Element.getDimensions(element).width
    },
    classNames: function (element) {
        return new Element.ClassNames(element)
    },
    hasClassName: function (element, className) {
        if (!(element = $(element))) return;
        var elementClassName = element.className;
        return (elementClassName.length > 0 && (elementClassName == className || new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)))
    },
    addClassName: function (element, className) {
        if (!(element = $(element))) return;
        if (!Element.hasClassName(element, className)) element.className += (element.className ? ' ' : '') + className;
        return element
    },
    removeClassName: function (element, className) {
        if (!(element = $(element))) return;
        element.className = element.className.replace(new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
        return element
    },
    toggleClassName: function (element, className) {
        if (!(element = $(element))) return;
        return Element[Element.hasClassName(element, className) ? 'removeClassName' : 'addClassName'](element, className)
    },
    cleanWhitespace: function (element) {
        element = $(element);
        var node = element.firstChild;
        while (node) {
            var nextNode = node.nextSibling;
            if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) element.removeChild(node);
            node = nextNode
        }
        return element
    },
    empty: function (element) {
        return $(element).innerHTML.blank()
    },
    descendantOf: function (element, ancestor) {
        element = $(element), ancestor = $(ancestor);
        if (element.compareDocumentPosition) return (element.compareDocumentPosition(ancestor) & 8) === 8;
        if (ancestor.contains) return ancestor.contains(element) && ancestor !== element;
        while (element = element.parentNode) if (element == ancestor) return true;
        return false
    },
    scrollTo: function (element) {
        element = $(element);
        var pos = Element.cumulativeOffset(element);
        window.scrollTo(pos[0], pos[1]);
        return element
    },
    getStyle: function (element, style) {
        element = $(element);
        style = style == 'float' ? 'cssFloat' : style.camelize();
        var value = element.style[style];
        if (!value || value == 'auto') {
            var css = document.defaultView.getComputedStyle(element, null);
            value = css ? css[style] : null
        }
        if (style == 'opacity') return value ? parseFloat(value) : 1.0;
        return value == 'auto' ? null : value
    },
    getOpacity: function (element) {
        return $(element).getStyle('opacity')
    },
    setStyle: function (element, styles) {
        element = $(element);
        var elementStyle = element.style,
            match;
        if (Object.isString(styles)) {
            element.style.cssText += ';' + styles;
            return styles.include('opacity') ? element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element
        }
        for (var property in styles) if (property == 'opacity') element.setOpacity(styles[property]);
        else elementStyle[(property == 'float' || property == 'cssFloat') ? (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : property] = styles[property];
        return element
    },
    setOpacity: function (element, value) {
        element = $(element);
        element.style.opacity = (value == 1 || value === '') ? '' : (value < 0.00001) ? 0 : value;
        return element
    },
    makePositioned: function (element) {
        element = $(element);
        var pos = Element.getStyle(element, 'position');
        if (pos == 'static' || !pos) {
            element._madePositioned = true;
            element.style.position = 'relative';
            if (Prototype.Browser.Opera) {
                element.style.top = 0;
                element.style.left = 0
            }
        }
        return element
    },
    undoPositioned: function (element) {
        element = $(element);
        if (element._madePositioned) {
            element._madePositioned = undefined;
            element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = ''
        }
        return element
    },
    makeClipping: function (element) {
        element = $(element);
        if (element._overflow) return element;
        element._overflow = Element.getStyle(element, 'overflow') || 'auto';
        if (element._overflow !== 'hidden') element.style.overflow = 'hidden';
        return element
    },
    undoClipping: function (element) {
        element = $(element);
        if (!element._overflow) return element;
        element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
        element._overflow = null;
        return element
    },
    clonePosition: function (element, source) {
        var options = Object.extend({
            setLeft: true,
            setTop: true,
            setWidth: true,
            setHeight: true,
            offsetTop: 0,
            offsetLeft: 0
        }, arguments[2] || {});
        source = $(source);
        var p = Element.viewportOffset(source),
            delta = [0, 0],
            parent = null;
        element = $(element);
        if (Element.getStyle(element, 'position') == 'absolute') {
            parent = Element.getOffsetParent(element);
            delta = Element.viewportOffset(parent)
        }
        if (parent == document.body) {
            delta[0] -= document.body.offsetLeft;
            delta[1] -= document.body.offsetTop
        }
        if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
        if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
        if (options.setWidth) element.style.width = source.offsetWidth + 'px';
        if (options.setHeight) element.style.height = source.offsetHeight + 'px';
        return element
    }
};
Object.extend(Element.Methods, {
    getElementsBySelector: Element.Methods.select,
    childElements: Element.Methods.immediateDescendants
});
Element._attributeTranslations = {
    write: {
        names: {
            className: 'class',
            htmlFor: 'for'
        },
        values: {}
    }
};
if (Prototype.Browser.Opera) {
    Element.Methods.getStyle = Element.Methods.getStyle.wrap(function (proceed, element, style) {
        switch (style) {
        case 'height':
        case 'width':
            if (!Element.visible(element)) return null;
            var dim = parseInt(proceed(element, style), 10);
            if (dim !== element['offset' + style.capitalize()]) return dim + 'px';
            var properties;
            if (style === 'height') {
                properties = ['border-top-width', 'padding-top', 'padding-bottom', 'border-bottom-width']
            } else {
                properties = ['border-left-width', 'padding-left', 'padding-right', 'border-right-width']
            }
            return properties.inject(dim, function (memo, property) {
                var val = proceed(element, property);
                return val === null ? memo : memo - parseInt(val, 10)
            }) + 'px';
        default:
            return proceed(element, style)
        }
    });
    Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(function (proceed, element, attribute) {
        if (attribute === 'title') return element.title;
        return proceed(element, attribute)
    })
} else if (Prototype.Browser.IE) {
    Element.Methods.getStyle = function (element, style) {
        element = $(element);
        style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
        var value = element.style[style];
        if (!value && element.currentStyle) value = element.currentStyle[style];
        if (style == 'opacity') {
            if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) if (value[1]) return parseFloat(value[1]) / 100;
            return 1.0
        }
        if (value == 'auto') {
            if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) return element['offset' + style.capitalize()] + 'px';
            return null
        }
        return value
    };
    Element.Methods.setOpacity = function (element, value) {
        function stripAlpha(filter) {
            return filter.replace(/alpha\([^\)]*\)/gi, '')
        }
        element = $(element);
        var currentStyle = element.currentStyle;
        if ((currentStyle && !currentStyle.hasLayout) || (!currentStyle && element.style.zoom == 'normal')) element.style.zoom = 1;
        var filter = element.getStyle('filter'),
            style = element.style;
        if (value == 1 || value === '') {
            (filter = stripAlpha(filter)) ? style.filter = filter : style.removeAttribute('filter');
            return element
        } else if (value < 0.00001) value = 0;
        style.filter = stripAlpha(filter) + 'alpha(opacity=' + (value * 100) + ')';
        return element
    };
    Element._attributeTranslations = (function () {
        var classProp = 'className',
            forProp = 'for',
            el = document.createElement('div');
        el.setAttribute(classProp, 'x');
        if (el.className !== 'x') {
            el.setAttribute('class', 'x');
            if (el.className === 'x') {
                classProp = 'class'
            }
        }
        el = null;
        el = document.createElement('label');
        el.setAttribute(forProp, 'x');
        if (el.htmlFor !== 'x') {
            el.setAttribute('htmlFor', 'x');
            if (el.htmlFor === 'x') {
                forProp = 'htmlFor'
            }
        }
        el = null;
        return {
            read: {
                names: {
                    'class': classProp,
                    'className': classProp,
                    'for': forProp,
                    'htmlFor': forProp
                },
                values: {
                    _getAttr: function (element, attribute) {
                        return element.getAttribute(attribute)
                    },
                    _getAttr2: function (element, attribute) {
                        return element.getAttribute(attribute, 2)
                    },
                    _getAttrNode: function (element, attribute) {
                        var node = element.getAttributeNode(attribute);
                        return node ? node.value : ""
                    },
                    _getEv: (function () {
                        var el = document.createElement('div'),
                            f;
                        el.onclick = Prototype.emptyFunction;
                        var value = el.getAttribute('onclick');
                        if (String(value).indexOf('{') > -1) {
                            f = function (element, attribute) {
                                attribute = element.getAttribute(attribute);
                                if (!attribute) return null;
                                attribute = attribute.toString();
                                attribute = attribute.split('{')[1];
                                attribute = attribute.split('}')[0];
                                return attribute.strip()
                            }
                        } else if (value === '') {
                            f = function (element, attribute) {
                                attribute = element.getAttribute(attribute);
                                if (!attribute) return null;
                                return attribute.strip()
                            }
                        }
                        el = null;
                        return f
                    })(),
                    _flag: function (element, attribute) {
                        return $(element).hasAttribute(attribute) ? attribute : null
                    },
                    style: function (element) {
                        return element.style.cssText.toLowerCase()
                    },
                    title: function (element) {
                        return element.title
                    }
                }
            }
        }
    })();
    Element._attributeTranslations.write = {
        names: Object.extend({
            cellpadding: 'cellPadding',
            cellspacing: 'cellSpacing'
        }, Element._attributeTranslations.read.names),
        values: {
            checked: function (element, value) {
                element.checked = !! value
            },
            style: function (element, value) {
                element.style.cssText = value ? value : ''
            }
        }
    };
    Element._attributeTranslations.has = {};
    $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + 'encType maxLength readOnly longDesc frameBorder').each(function (attr) {
        Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
        Element._attributeTranslations.has[attr.toLowerCase()] = attr
    });
    (function (v) {
        Object.extend(v, {
            href: v._getAttr2,
            src: v._getAttr2,
            type: v._getAttr,
            action: v._getAttrNode,
            disabled: v._flag,
            checked: v._flag,
            readonly: v._flag,
            multiple: v._flag,
            onload: v._getEv,
            onunload: v._getEv,
            onclick: v._getEv,
            ondblclick: v._getEv,
            onmousedown: v._getEv,
            onmouseup: v._getEv,
            onmouseover: v._getEv,
            onmousemove: v._getEv,
            onmouseout: v._getEv,
            onfocus: v._getEv,
            onblur: v._getEv,
            onkeypress: v._getEv,
            onkeydown: v._getEv,
            onkeyup: v._getEv,
            onsubmit: v._getEv,
            onreset: v._getEv,
            onselect: v._getEv,
            onchange: v._getEv
        })
    })(Element._attributeTranslations.read.values);
    if (Prototype.BrowserFeatures.ElementExtensions) {
        (function () {
            function _descendants(element) {
                var nodes = element.getElementsByTagName('*'),
                    results = [];
                for (var i = 0, node; node = nodes[i]; i++) if (node.tagName !== "!") results.push(node);
                return results
            }
            Element.Methods.down = function (element, expression, index) {
                element = $(element);
                if (arguments.length == 1) return element.firstDescendant();
                return Object.isNumber(expression) ? _descendants(element)[expression] : Element.select(element, expression)[index || 0]
            }
        })()
    }
} else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
    Element.Methods.setOpacity = function (element, value) {
        element = $(element);
        element.style.opacity = (value == 1) ? 0.999999 : (value === '') ? '' : (value < 0.00001) ? 0 : value;
        return element
    }
} else if (Prototype.Browser.WebKit) {
    Element.Methods.setOpacity = function (element, value) {
        element = $(element);
        element.style.opacity = (value == 1 || value === '') ? '' : (value < 0.00001) ? 0 : value;
        if (value == 1) if (element.tagName.toUpperCase() == 'IMG' && element.width) {
            element.width++;
            element.width--
        } else try {
            var n = document.createTextNode(' ');
            element.appendChild(n);
            element.removeChild(n)
        } catch (e) {}
        return element
    }
}
if ('outerHTML' in document.documentElement) {
    Element.Methods.replace = function (element, content) {
        element = $(element);
        if (content && content.toElement) content = content.toElement();
        if (Object.isElement(content)) {
            element.parentNode.replaceChild(content, element);
            return element
        }
        content = Object.toHTML(content);
        var parent = element.parentNode,
            tagName = parent.tagName.toUpperCase();
        if (Element._insertionTranslations.tags[tagName]) {
            var nextSibling = element.next(),
                fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
            parent.removeChild(element);
            if (nextSibling) fragments.each(function (node) {
                parent.insertBefore(node, nextSibling)
            });
            else fragments.each(function (node) {
                parent.appendChild(node)
            })
        } else element.outerHTML = content.stripScripts();
        content.evalScripts.bind(content).defer();
        return element
    }
}
Element._returnOffset = function (l, t) {
    var result = [l, t];
    result.left = l;
    result.top = t;
    return result
};
Element._getContentFromAnonymousElement = function (tagName, html, force) {
    var div = new Element('div'),
        t = Element._insertionTranslations.tags[tagName];
    var workaround = false;
    if (t) workaround = true;
    else if (force) {
        workaround = true;
        t = ['', '', 0]
    }
    if (workaround) {
        div.innerHTML = '&nbsp;' + t[0] + html + t[1];
        div.removeChild(div.firstChild);
        for (var i = t[2]; i--;) {
            div = div.firstChild
        }
    } else {
        div.innerHTML = html
    }
    return $A(div.childNodes)
};
Element._insertionTranslations = {
    before: function (element, node) {
        element.parentNode.insertBefore(node, element)
    },
    top: function (element, node) {
        element.insertBefore(node, element.firstChild)
    },
    bottom: function (element, node) {
        element.appendChild(node)
    },
    after: function (element, node) {
        element.parentNode.insertBefore(node, element.nextSibling)
    },
    tags: {
        TABLE: ['<table>', '</table>', 1],
        TBODY: ['<table><tbody>', '</tbody></table>', 2],
        TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
        TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
        SELECT: ['<select>', '</select>', 1]
    }
};
(function () {
    var tags = Element._insertionTranslations.tags;
    Object.extend(tags, {
        THEAD: tags.TBODY,
        TFOOT: tags.TBODY,
        TH: tags.TD
    })
})();
Element.Methods.Simulated = {
    hasAttribute: function (element, attribute) {
        attribute = Element._attributeTranslations.has[attribute] || attribute;
        var node = $(element).getAttributeNode(attribute);
        return !!(node && node.specified)
    }
};
Element.Methods.ByTag = {};
Object.extend(Element, Element.Methods);
(function (div) {
    if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) {
        window.HTMLElement = {};
        window.HTMLElement.prototype = div['__proto__'];
        Prototype.BrowserFeatures.ElementExtensions = true
    }
    div = null
})(document.createElement('div'));
Element.extend = (function () {
    function checkDeficiency(tagName) {
        if (typeof window.Element != 'undefined') {
            var proto = window.Element.prototype;
            if (proto) {
                var id = '_' + (Math.random() + '').slice(2),
                    el = document.createElement(tagName);
                proto[id] = 'x';
                var isBuggy = (el[id] !== 'x');
                delete proto[id];
                el = null;
                return isBuggy
            }
        }
        return false
    }
    function extendElementWith(element, methods) {
        for (var property in methods) {
            var value = methods[property];
            if (Object.isFunction(value) && !(property in element)) element[property] = value.methodize()
        }
    }
    var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');
    if (Prototype.BrowserFeatures.SpecificElementExtensions) {
        if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) {
            return function (element) {
                if (element && typeof element._extendedByPrototype == 'undefined') {
                    var t = element.tagName;
                    if (t && (/^(?:object|applet|embed)$/i.test(t))) {
                        extendElementWith(element, Element.Methods);
                        extendElementWith(element, Element.Methods.Simulated);
                        extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()])
                    }
                }
                return element
            }
        }
        return Prototype.K
    }
    var Methods = {},
        ByTag = Element.Methods.ByTag;
    var extend = Object.extend(function (element) {
        if (!element || typeof element._extendedByPrototype != 'undefined' || element.nodeType != 1 || element == window) return element;
        var methods = Object.clone(Methods),
            tagName = element.tagName.toUpperCase();
        if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
        extendElementWith(element, methods);
        element._extendedByPrototype = Prototype.emptyFunction;
        return element
    }, {
        refresh: function () {
            if (!Prototype.BrowserFeatures.ElementExtensions) {
                Object.extend(Methods, Element.Methods);
                Object.extend(Methods, Element.Methods.Simulated)
            }
        }
    });
    extend.refresh();
    return extend
})();
if (document.documentElement.hasAttribute) {
    Element.hasAttribute = function (element, attribute) {
        return element.hasAttribute(attribute)
    }
} else {
    Element.hasAttribute = Element.Methods.Simulated.hasAttribute
}
Element.addMethods = function (methods) {
    var F = Prototype.BrowserFeatures,
        T = Element.Methods.ByTag;
    if (!methods) {
        Object.extend(Form, Form.Methods);
        Object.extend(Form.Element, Form.Element.Methods);
        Object.extend(Element.Methods.ByTag, {
            "FORM": Object.clone(Form.Methods),
            "INPUT": Object.clone(Form.Element.Methods),
            "SELECT": Object.clone(Form.Element.Methods),
            "TEXTAREA": Object.clone(Form.Element.Methods),
            "BUTTON": Object.clone(Form.Element.Methods)
        })
    }
    if (arguments.length == 2) {
        var tagName = methods;
        methods = arguments[1]
    }
    if (!tagName) Object.extend(Element.Methods, methods || {});
    else {
        if (Object.isArray(tagName)) tagName.each(extend);
        else extend(tagName)
    }
    function extend(tagName) {
        tagName = tagName.toUpperCase();
        if (!Element.Methods.ByTag[tagName]) Element.Methods.ByTag[tagName] = {};
        Object.extend(Element.Methods.ByTag[tagName], methods)
    }
    function copy(methods, destination, onlyIfAbsent) {
        onlyIfAbsent = onlyIfAbsent || false;
        for (var property in methods) {
            var value = methods[property];
            if (!Object.isFunction(value)) continue;
            if (!onlyIfAbsent || !(property in destination)) destination[property] = value.methodize()
        }
    }
    function findDOMClass(tagName) {
        var klass;
        var trans = {
            "OPTGROUP": "OptGroup",
            "TEXTAREA": "TextArea",
            "P": "Paragraph",
            "FIELDSET": "FieldSet",
            "UL": "UList",
            "OL": "OList",
            "DL": "DList",
            "DIR": "Directory",
            "H1": "Heading",
            "H2": "Heading",
            "H3": "Heading",
            "H4": "Heading",
            "H5": "Heading",
            "H6": "Heading",
            "Q": "Quote",
            "INS": "Mod",
            "DEL": "Mod",
            "A": "Anchor",
            "IMG": "Image",
            "CAPTION": "TableCaption",
            "COL": "TableCol",
            "COLGROUP": "TableCol",
            "THEAD": "TableSection",
            "TFOOT": "TableSection",
            "TBODY": "TableSection",
            "TR": "TableRow",
            "TH": "TableCell",
            "TD": "TableCell",
            "FRAMESET": "FrameSet",
            "IFRAME": "IFrame"
        };
        if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
        if (window[klass]) return window[klass];
        klass = 'HTML' + tagName + 'Element';
        if (window[klass]) return window[klass];
        klass = 'HTML' + tagName.capitalize() + 'Element';
        if (window[klass]) return window[klass];
        var element = document.createElement(tagName),
            proto = element['__proto__'] || element.constructor.prototype;
        element = null;
        return proto
    }
    var elementPrototype = window.HTMLElement ? HTMLElement.prototype : Element.prototype;
    if (F.ElementExtensions) {
        copy(Element.Methods, elementPrototype);
        copy(Element.Methods.Simulated, elementPrototype, true)
    }
    if (F.SpecificElementExtensions) {
        for (var tag in Element.Methods.ByTag) {
            var klass = findDOMClass(tag);
            if (Object.isUndefined(klass)) continue;
            copy(T[tag], klass.prototype)
        }
    }
    Object.extend(Element, Element.Methods);
    delete Element.ByTag;
    if (Element.extend.refresh) Element.extend.refresh();
    Element.cache = {}
};
document.viewport = {
    getDimensions: function () {
        return {
            width: this.getWidth(),
            height: this.getHeight()
        }
    },
    getScrollOffsets: function () {
        return Element._returnOffset(window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop)
    }
};
(function (viewport) {
    var B = Prototype.Browser,
        doc = document,
        element, property = {};

    function getRootElement() {
        if (B.WebKit && !doc.evaluate) return document;
        if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) return document.body;
        return document.documentElement
    }
    function define(D) {
        if (!element) element = getRootElement();
        property[D] = 'client' + D;
        viewport['get' + D] = function () {
            return element[property[D]]
        };
        return viewport['get' + D]()
    }
    viewport.getWidth = define.curry('Width');
    viewport.getHeight = define.curry('Height')
})(document.viewport);
Element.Storage = {
    UID: 1
};
Element.addMethods({
    getStorage: function (element) {
        if (!(element = $(element))) return;
        var uid;
        if (element === window) {
            uid = 0
        } else {
            if (typeof element._prototypeUID === "undefined") element._prototypeUID = Element.Storage.UID++;
            uid = element._prototypeUID
        }
        if (!Element.Storage[uid]) Element.Storage[uid] = $H();
        return Element.Storage[uid]
    },
    store: function (element, key, value) {
        if (!(element = $(element))) return;
        if (arguments.length === 2) {
            Element.getStorage(element).update(key)
        } else {
            Element.getStorage(element).set(key, value)
        }
        return element
    },
    retrieve: function (element, key, defaultValue) {
        if (!(element = $(element))) return;
        var hash = Element.getStorage(element),
            value = hash.get(key);
        if (Object.isUndefined(value)) {
            hash.set(key, defaultValue);
            value = defaultValue
        }
        return value
    },
    clone: function (element, deep) {
        if (!(element = $(element))) return;
        var clone = element.cloneNode(deep);
        clone._prototypeUID = void 0;
        if (deep) {
            var descendants = Element.select(clone, '*'),
                i = descendants.length;
            while (i--) {
                descendants[i]._prototypeUID = void 0
            }
        }
        return Element.extend(clone)
    },
    purge: function (element) {
        if (!(element = $(element))) return;
        var purgeElement = Element._purgeElement;
        purgeElement(element);
        var descendants = element.getElementsByTagName('*'),
            i = descendants.length;
        while (i--) purgeElement(descendants[i]);
        return null
    }
});
(function () {
    function toDecimal(pctString) {
        var match = pctString.match(/^(\d+)%?$/i);
        if (!match) return null;
        return (Number(match[1]) / 100)
    }
    function getPixelValue(value, property, context) {
        var element = null;
        if (Object.isElement(value)) {
            element = value;
            value = element.getStyle(property)
        }
        if (value === null) {
            return null
        }
        if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) {
            return window.parseFloat(value)
        }
        var isPercentage = value.include('%'),
            isViewport = (context === document.viewport);
        if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {
            var style = element.style.left,
                rStyle = element.runtimeStyle.left;
            element.runtimeStyle.left = element.currentStyle.left;
            element.style.left = value || 0;
            value = element.style.pixelLeft;
            element.style.left = style;
            element.runtimeStyle.left = rStyle;
            return value
        }
        if (element && isPercentage) {
            context = context || element.parentNode;
            var decimal = toDecimal(value);
            var whole = null;
            var position = element.getStyle('position');
            var isHorizontal = property.include('left') || property.include('right') || property.include('width');
            var isVertical = property.include('top') || property.include('bottom') || property.include('height');
            if (context === document.viewport) {
                if (isHorizontal) {
                    whole = document.viewport.getWidth()
                } else if (isVertical) {
                    whole = document.viewport.getHeight()
                }
            } else {
                if (isHorizontal) {
                    whole = $(context).measure('width')
                } else if (isVertical) {
                    whole = $(context).measure('height')
                }
            }
            return (whole === null) ? 0 : whole * decimal
        }
        return 0
    }
    function toCSSPixels(number) {
        if (Object.isString(number) && number.endsWith('px')) {
            return number
        }
        return number + 'px'
    }
    function isDisplayed(element) {
        var originalElement = element;
        while (element && element.parentNode) {
            var display = element.getStyle('display');
            if (display === 'none') {
                return false
            }
            element = $(element.parentNode)
        }
        return true
    }
    var hasLayout = Prototype.K;
    if ('currentStyle' in document.documentElement) {
        hasLayout = function (element) {
            if (!element.currentStyle.hasLayout) {
                element.style.zoom = 1
            }
            return element
        }
    }
    function cssNameFor(key) {
        if (key.include('border')) key = key + '-width';
        return key.camelize()
    }
    Element.Layout = Class.create(Hash, {
        initialize: function ($super, element, preCompute) {
            $super();
            this.element = $(element);
            Element.Layout.PROPERTIES.each(function (property) {
                this._set(property, null)
            }, this);
            if (preCompute) {
                this._preComputing = true;
                this._begin();
                Element.Layout.PROPERTIES.each(this._compute, this);
                this._end();
                this._preComputing = false
            }
        },
        _set: function (property, value) {
            return Hash.prototype.set.call(this, property, value)
        },
        set: function (property, value) {
            throw "Properties of Element.Layout are read-only."
        },
        get: function ($super, property) {
            var value = $super(property);
            return value === null ? this._compute(property) : value
        },
        _begin: function () {
            if (this._prepared) return;
            var element = this.element;
            if (isDisplayed(element)) {
                this._prepared = true;
                return
            }
            var originalStyles = {
                position: element.style.position || '',
                width: element.style.width || '',
                visibility: element.style.visibility || '',
                display: element.style.display || ''
            };
            element.store('prototype_original_styles', originalStyles);
            var position = element.getStyle('position'),
                width = element.getStyle('width');
            if (width === "0px" || width === null) {
                element.style.display = 'block';
                width = element.getStyle('width')
            }
            var context = (position === 'fixed') ? document.viewport : element.parentNode;
            element.setStyle({
                position: 'absolute',
                visibility: 'hidden',
                display: 'block'
            });
            var positionedWidth = element.getStyle('width');
            var newWidth;
            if (width && (positionedWidth === width)) {
                newWidth = getPixelValue(element, 'width', context)
            } else if (position === 'absolute' || position === 'fixed') {
                newWidth = getPixelValue(element, 'width', context)
            } else {
                var parent = element.parentNode,
                    pLayout = $(parent).getLayout();
                newWidth = pLayout.get('width') - this.get('margin-left') - this.get('border-left') - this.get('padding-left') - this.get('padding-right') - this.get('border-right') - this.get('margin-right')
            }
            element.setStyle({
                width: newWidth + 'px'
            });
            this._prepared = true
        },
        _end: function () {
            var element = this.element;
            var originalStyles = element.retrieve('prototype_original_styles');
            element.store('prototype_original_styles', null);
            element.setStyle(originalStyles);
            this._prepared = false
        },
        _compute: function (property) {
            var COMPUTATIONS = Element.Layout.COMPUTATIONS;
            if (!(property in COMPUTATIONS)) {
                throw "Property not found."
            }
            return this._set(property, COMPUTATIONS[property].call(this, this.element))
        },
        toObject: function () {
            var args = $A(arguments);
            var keys = (args.length === 0) ? Element.Layout.PROPERTIES : args.join(' ').split(' ');
            var obj = {};
            keys.each(function (key) {
                if (!Element.Layout.PROPERTIES.include(key)) return;
                var value = this.get(key);
                if (value != null) obj[key] = value
            }, this);
            return obj
        },
        toHash: function () {
            var obj = this.toObject.apply(this, arguments);
            return new Hash(obj)
        },
        toCSS: function () {
            var args = $A(arguments);
            var keys = (args.length === 0) ? Element.Layout.PROPERTIES : args.join(' ').split(' ');
            var css = {};
            keys.each(function (key) {
                if (!Element.Layout.PROPERTIES.include(key)) return;
                if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return;
                var value = this.get(key);
                if (value != null) css[cssNameFor(key)] = value + 'px'
            }, this);
            return css
        },
        inspect: function () {
            return "#<Element.Layout>"
        }
    });
    Object.extend(Element.Layout, {
        PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'),
        COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'),
        COMPUTATIONS: {
            'height': function (element) {
                if (!this._preComputing) this._begin();
                var bHeight = this.get('border-box-height');
                if (bHeight <= 0) {
                    if (!this._preComputing) this._end();
                    return 0
                }
                var bTop = this.get('border-top'),
                    bBottom = this.get('border-bottom');
                var pTop = this.get('padding-top'),
                    pBottom = this.get('padding-bottom');
                if (!this._preComputing) this._end();
                return bHeight - bTop - bBottom - pTop - pBottom
            },
            'width': function (element) {
                if (!this._preComputing) this._begin();
                var bWidth = this.get('border-box-width');
                if (bWidth <= 0) {
                    if (!this._preComputing) this._end();
                    return 0
                }
                var bLeft = this.get('border-left'),
                    bRight = this.get('border-right');
                var pLeft = this.get('padding-left'),
                    pRight = this.get('padding-right');
                if (!this._preComputing) this._end();
                return bWidth - bLeft - bRight - pLeft - pRight
            },
            'padding-box-height': function (element) {
                var height = this.get('height'),
                    pTop = this.get('padding-top'),
                    pBottom = this.get('padding-bottom');
                return height + pTop + pBottom
            },
            'padding-box-width': function (element) {
                var width = this.get('width'),
                    pLeft = this.get('padding-left'),
                    pRight = this.get('padding-right');
                return width + pLeft + pRight
            },
            'border-box-height': function (element) {
                if (!this._preComputing) this._begin();
                var height = element.offsetHeight;
                if (!this._preComputing) this._end();
                return height
            },
            'border-box-width': function (element) {
                if (!this._preComputing) this._begin();
                var width = element.offsetWidth;
                if (!this._preComputing) this._end();
                return width
            },
            'margin-box-height': function (element) {
                var bHeight = this.get('border-box-height'),
                    mTop = this.get('margin-top'),
                    mBottom = this.get('margin-bottom');
                if (bHeight <= 0) return 0;
                return bHeight + mTop + mBottom
            },
            'margin-box-width': function (element) {
                var bWidth = this.get('border-box-width'),
                    mLeft = this.get('margin-left'),
                    mRight = this.get('margin-right');
                if (bWidth <= 0) return 0;
                return bWidth + mLeft + mRight
            },
            'top': function (element) {
                var offset = element.positionedOffset();
                return offset.top
            },
            'bottom': function (element) {
                var offset = element.positionedOffset(),
                    parent = element.getOffsetParent(),
                    pHeight = parent.measure('height');
                var mHeight = this.get('border-box-height');
                return pHeight - mHeight - offset.top
            },
            'left': function (element) {
                var offset = element.positionedOffset();
                return offset.left
            },
            'right': function (element) {
                var offset = element.positionedOffset(),
                    parent = element.getOffsetParent(),
                    pWidth = parent.measure('width');
                var mWidth = this.get('border-box-width');
                return pWidth - mWidth - offset.left
            },
            'padding-top': function (element) {
                return getPixelValue(element, 'paddingTop')
            },
            'padding-bottom': function (element) {
                return getPixelValue(element, 'paddingBottom')
            },
            'padding-left': function (element) {
                return getPixelValue(element, 'paddingLeft')
            },
            'padding-right': function (element) {
                return getPixelValue(element, 'paddingRight')
            },
            'border-top': function (element) {
                return getPixelValue(element, 'borderTopWidth')
            },
            'border-bottom': function (element) {
                return getPixelValue(element, 'borderBottomWidth')
            },
            'border-left': function (element) {
                return getPixelValue(element, 'borderLeftWidth')
            },
            'border-right': function (element) {
                return getPixelValue(element, 'borderRightWidth')
            },
            'margin-top': function (element) {
                return getPixelValue(element, 'marginTop')
            },
            'margin-bottom': function (element) {
                return getPixelValue(element, 'marginBottom')
            },
            'margin-left': function (element) {
                return getPixelValue(element, 'marginLeft')
            },
            'margin-right': function (element) {
                return getPixelValue(element, 'marginRight')
            }
        }
    });
    if ('getBoundingClientRect' in document.documentElement) {
        Object.extend(Element.Layout.COMPUTATIONS, {
            'right': function (element) {
                var parent = hasLayout(element.getOffsetParent());
                var rect = element.getBoundingClientRect(),
                    pRect = parent.getBoundingClientRect();
                return (pRect.right - rect.right).round()
            },
            'bottom': function (element) {
                var parent = hasLayout(element.getOffsetParent());
                var rect = element.getBoundingClientRect(),
                    pRect = parent.getBoundingClientRect();
                return (pRect.bottom - rect.bottom).round()
            }
        })
    }
    Element.Offset = Class.create({
        initialize: function (left, top) {
            this.left = left.round();
            this.top = top.round();
            this[0] = this.left;
            this[1] = this.top
        },
        relativeTo: function (offset) {
            return new Element.Offset(this.left - offset.left, this.top - offset.top)
        },
        inspect: function () {
            return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this)
        },
        toString: function () {
            return "[#{left}, #{top}]".interpolate(this)
        },
        toArray: function () {
            return [this.left, this.top]
        }
    });

    function getLayout(element, preCompute) {
        return new Element.Layout(element, preCompute)
    }
    function measure(element, property) {
        return $(element).getLayout().get(property)
    }
    function getDimensions(element) {
        element = $(element);
        var display = Element.getStyle(element, 'display');
        if (display && display !== 'none') {
            return {
                width: element.offsetWidth,
                height: element.offsetHeight
            }
        }
        var style = element.style;
        var originalStyles = {
            visibility: style.visibility,
            position: style.position,
            display: style.display
        };
        var newStyles = {
            visibility: 'hidden',
            display: 'block'
        };
        if (originalStyles.position !== 'fixed') newStyles.position = 'absolute';
        Element.setStyle(element, newStyles);
        var dimensions = {
            width: element.offsetWidth,
            height: element.offsetHeight
        };
        Element.setStyle(element, originalStyles);
        return dimensions
    }
    function getOffsetParent(element) {
        element = $(element);
        if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element)) return $(document.body);
        var isInline = (Element.getStyle(element, 'display') === 'inline');
        if (!isInline && element.offsetParent) return $(element.offsetParent);
        while ((element = element.parentNode) && element !== document.body) {
            if (Element.getStyle(element, 'position') !== 'static') {
                return isHtml(element) ? $(document.body) : $(element)
            }
        }
        return $(document.body)
    }
    function cumulativeOffset(element) {
        element = $(element);
        var valueT = 0,
            valueL = 0;
        if (element.parentNode) {
            do {
                valueT += element.offsetTop || 0;
                valueL += element.offsetLeft || 0;
                element = element.offsetParent
            } while (element)
        }
        return new Element.Offset(valueL, valueT)
    }
    function positionedOffset(element) {
        element = $(element);
        var layout = element.getLayout();
        var valueT = 0,
            valueL = 0;
        do {
            valueT += element.offsetTop || 0;
            valueL += element.offsetLeft || 0;
            element = element.offsetParent;
            if (element) {
                if (isBody(element)) break;
                var p = Element.getStyle(element, 'position');
                if (p !== 'static') break
            }
        } while (element);
        valueL -= layout.get('margin-top');
        valueT -= layout.get('margin-left');
        return new Element.Offset(valueL, valueT)
    }
    function cumulativeScrollOffset(element) {
        var valueT = 0,
            valueL = 0;
        do {
            valueT += element.scrollTop || 0;
            valueL += element.scrollLeft || 0;
            element = element.parentNode
        } while (element);
        return new Element.Offset(valueL, valueT)
    }
    function viewportOffset(forElement) {
        element = $(element);
        var valueT = 0,
            valueL = 0,
            docBody = document.body;
        var element = forElement;
        do {
            valueT += element.offsetTop || 0;
            valueL += element.offsetLeft || 0;
            if (element.offsetParent == docBody && Element.getStyle(element, 'position') == 'absolute') break
        } while (element = element.offsetParent);
        element = forElement;
        do {
            if (element != docBody) {
                valueT -= element.scrollTop || 0;
                valueL -= element.scrollLeft || 0
            }
        } while (element = element.parentNode);
        return new Element.Offset(valueL, valueT)
    }
    function absolutize(element) {
        element = $(element);
        if (Element.getStyle(element, 'position') === 'absolute') {
            return element
        }
        var offsetParent = getOffsetParent(element);
        var eOffset = element.viewportOffset(),
            pOffset = offsetParent.viewportOffset();
        var offset = eOffset.relativeTo(pOffset);
        var layout = element.getLayout();
        element.store('prototype_absolutize_original_styles', {
            left: element.getStyle('left'),
            top: element.getStyle('top'),
            width: element.getStyle('width'),
            height: element.getStyle('height')
        });
        element.setStyle({
            position: 'absolute',
            top: offset.top + 'px',
            left: offset.left + 'px',
            width: layout.get('width') + 'px',
            height: layout.get('height') + 'px'
        });
        return element
    }
    function relativize(element) {
        element = $(element);
        if (Element.getStyle(element, 'position') === 'relative') {
            return element
        }
        var originalStyles = element.retrieve('prototype_absolutize_original_styles');
        if (originalStyles) element.setStyle(originalStyles);
        return element
    }
    if (Prototype.Browser.IE) {
        getOffsetParent = getOffsetParent.wrap(function (proceed, element) {
            element = $(element);
            if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element)) return $(document.body);
            var position = element.getStyle('position');
            if (position !== 'static') return proceed(element);
            element.setStyle({
                position: 'relative'
            });
            var value = proceed(element);
            element.setStyle({
                position: position
            });
            return value
        });
        positionedOffset = positionedOffset.wrap(function (proceed, element) {
            element = $(element);
            if (!element.parentNode) return new Element.Offset(0, 0);
            var position = element.getStyle('position');
            if (position !== 'static') return proceed(element);
            var offsetParent = element.getOffsetParent();
            if (offsetParent && offsetParent.getStyle('position') === 'fixed') hasLayout(offsetParent);
            element.setStyle({
                position: 'relative'
            });
            var value = proceed(element);
            element.setStyle({
                position: position
            });
            return value
        })
    } else if (Prototype.Browser.Webkit) {
        cumulativeOffset = function (element) {
            element = $(element);
            var valueT = 0,
                valueL = 0;
            do {
                valueT += element.offsetTop || 0;
                valueL += element.offsetLeft || 0;
                if (element.offsetParent == document.body) if (Element.getStyle(element, 'position') == 'absolute') break;
                element = element.offsetParent
            } while (element);
            return new Element.Offset(valueL, valueT)
        }
    }
    Element.addMethods({
        getLayout: getLayout,
        measure: measure,
        getDimensions: getDimensions,
        getOffsetParent: getOffsetParent,
        cumulativeOffset: cumulativeOffset,
        positionedOffset: positionedOffset,
        cumulativeScrollOffset: cumulativeScrollOffset,
        viewportOffset: viewportOffset,
        absolutize: absolutize,
        relativize: relativize
    });

    function isBody(element) {
        return element.nodeName.toUpperCase() === 'BODY'
    }
    function isHtml(element) {
        return element.nodeName.toUpperCase() === 'HTML'
    }
    function isDocument(element) {
        return element.nodeType === Node.DOCUMENT_NODE
    }
    function isDetached(element) {
        return element !== document.body && !Element.descendantOf(element, document.body)
    }
    if ('getBoundingClientRect' in document.documentElement) {
        Element.addMethods({
            viewportOffset: function (element) {
                element = $(element);
                if (isDetached(element)) return new Element.Offset(0, 0);
                var rect = element.getBoundingClientRect(),
                    docEl = document.documentElement;
                return new Element.Offset(rect.left - docEl.clientLeft, rect.top - docEl.clientTop)
            }
        })
    }
})();
window.$$ = function () {
    var expression = $A(arguments).join(', ');
    return Prototype.Selector.select(expression, document)
};
Prototype.Selector = (function () {
    function select() {
        throw new Error('Method "Prototype.Selector.select" must be defined.')
    }
    function match() {
        throw new Error('Method "Prototype.Selector.match" must be defined.')
    }
    function find(elements, expression, index) {
        index = index || 0;
        var match = Prototype.Selector.match,
            length = elements.length,
            matchIndex = 0,
            i;
        for (i = 0; i < length; i++) {
            if (match(elements[i], expression) && index == matchIndex++) {
                return Element.extend(elements[i])
            }
        }
    }
    function extendElements(elements) {
        for (var i = 0, length = elements.length; i < length; i++) {
            Element.extend(elements[i])
        }
        return elements
    }
    var K = Prototype.K;
    return {
        select: select,
        match: match,
        find: find,
        extendElements: (Element.extend === K) ? K : extendElements,
        extendElement: Element.extend
    }
})();
Prototype._original_property = window.Sizzle;
(function () {
    var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
        done = 0,
        toString = Object.prototype.toString,
        hasDuplicate = false,
        baseHasDuplicate = true;
    [0, 0].sort(function () {
        baseHasDuplicate = false;
        return 0
    });
    var Sizzle = function (selector, context, results, seed) {
            results = results || [];
            var origContext = context = context || document;
            if (context.nodeType !== 1 && context.nodeType !== 9) {
                return []
            }
            if (!selector || typeof selector !== "string") {
                return results
            }
            var parts = [],
                m, set, checkSet, check, mode, extra, prune = true,
                contextXML = isXML(context),
                soFar = selector;
            while ((chunker.exec(""), m = chunker.exec(soFar)) !== null) {
                soFar = m[3];
                parts.push(m[1]);
                if (m[2]) {
                    extra = m[3];
                    break
                }
            }
            if (parts.length > 1 && origPOS.exec(selector)) {
                if (parts.length === 2 && Expr.relative[parts[0]]) {
                    set = posProcess(parts[0] + parts[1], context)
                } else {
                    set = Expr.relative[parts[0]] ? [context] : Sizzle(parts.shift(), context);
                    while (parts.length) {
                        selector = parts.shift();
                        if (Expr.relative[selector]) selector += parts.shift();
                        set = posProcess(selector, set)
                    }
                }
            } else {
                if (!seed && parts.length > 1 && context.nodeType === 9 && !contextXML && Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1])) {
                    var ret = Sizzle.find(parts.shift(), context, contextXML);
                    context = ret.expr ? Sizzle.filter(ret.expr, ret.set)[0] : ret.set[0]
                }
                if (context) {
                    var ret = seed ? {
                        expr: parts.pop(),
                        set: makeArray(seed)
                    } : Sizzle.find(parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML);
                    set = ret.expr ? Sizzle.filter(ret.expr, ret.set) : ret.set;
                    if (parts.length > 0) {
                        checkSet = makeArray(set)
                    } else {
                        prune = false
                    }
                    while (parts.length) {
                        var cur = parts.pop(),
                            pop = cur;
                        if (!Expr.relative[cur]) {
                            cur = ""
                        } else {
                            pop = parts.pop()
                        }
                        if (pop == null) {
                            pop = context
                        }
                        Expr.relative[cur](checkSet, pop, contextXML)
                    }
                } else {
                    checkSet = parts = []
                }
            }
            if (!checkSet) {
                checkSet = set
            }
            if (!checkSet) {
                throw "Syntax error, unrecognized expression: " + (cur || selector)
            }
            if (toString.call(checkSet) === "[object Array]") {
                if (!prune) {
                    results.push.apply(results, checkSet)
                } else if (context && context.nodeType === 1) {
                    for (var i = 0; checkSet[i] != null; i++) {
                        if (checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i]))) {
                            results.push(set[i])
                        }
                    }
                } else {
                    for (var i = 0; checkSet[i] != null; i++) {
                        if (checkSet[i] && checkSet[i].nodeType === 1) {
                            results.push(set[i])
                        }
                    }
                }
            } else {
                makeArray(checkSet, results)
            }
            if (extra) {
                Sizzle(extra, origContext, results, seed);
                Sizzle.uniqueSort(results)
            }
            return results
        };
    Sizzle.uniqueSort = function (results) {
        if (sortOrder) {
            hasDuplicate = baseHasDuplicate;
            results.sort(sortOrder);
            if (hasDuplicate) {
                for (var i = 1; i < results.length; i++) {
                    if (results[i] === results[i - 1]) {
                        results.splice(i--, 1)
                    }
                }
            }
        }
        return results
    };
    Sizzle.matches = function (expr, set) {
        return Sizzle(expr, null, null, set)
    };
    Sizzle.find = function (expr, context, isXML) {
        var set, match;
        if (!expr) {
            return []
        }
        for (var i = 0, l = Expr.order.length; i < l; i++) {
            var type = Expr.order[i],
                match;
            if ((match = Expr.leftMatch[type].exec(expr))) {
                var left = match[1];
                match.splice(1, 1);
                if (left.substr(left.length - 1) !== "\\") {
                    match[1] = (match[1] || "").replace(/\\/g, "");
                    set = Expr.find[type](match, context, isXML);
                    if (set != null) {
                        expr = expr.replace(Expr.match[type], "");
                        break
                    }
                }
            }
        }
        if (!set) {
            set = context.getElementsByTagName("*")
        }
        return {
            set: set,
            expr: expr
        }
    };
    Sizzle.filter = function (expr, set, inplace, not) {
        var old = expr,
            result = [],
            curLoop = set,
            match, anyFound, isXMLFilter = set && set[0] && isXML(set[0]);
        while (expr && set.length) {
            for (var type in Expr.filter) {
                if ((match = Expr.match[type].exec(expr)) != null) {
                    var filter = Expr.filter[type],
                        found, item;
                    anyFound = false;
                    if (curLoop == result) {
                        result = []
                    }
                    if (Expr.preFilter[type]) {
                        match = Expr.preFilter[type](match, curLoop, inplace, result, not, isXMLFilter);
                        if (!match) {
                            anyFound = found = true
                        } else if (match === true) {
                            continue
                        }
                    }
                    if (match) {
                        for (var i = 0;
                        (item = curLoop[i]) != null; i++) {
                            if (item) {
                                found = filter(item, match, i, curLoop);
                                var pass = not ^ !! found;
                                if (inplace && found != null) {
                                    if (pass) {
                                        anyFound = true
                                    } else {
                                        curLoop[i] = false
                                    }
                                } else if (pass) {
                                    result.push(item);
                                    anyFound = true
                                }
                            }
                        }
                    }
                    if (found !== undefined) {
                        if (!inplace) {
                            curLoop = result
                        }
                        expr = expr.replace(Expr.match[type], "");
                        if (!anyFound) {
                            return []
                        }
                        break
                    }
                }
            }
            if (expr == old) {
                if (anyFound == null) {
                    throw "Syntax error, unrecognized expression: " + expr
                } else {
                    break
                }
            }
            old = expr
        }
        return curLoop
    };
    var Expr = Sizzle.selectors = {
        order: ["ID", "NAME", "TAG"],
        match: {
            ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
            CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
            NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
            ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
            TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
            CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
            POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
            PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
        },
        leftMatch: {},
        attrMap: {
            "class": "className",
            "for": "htmlFor"
        },
        attrHandle: {
            href: function (elem) {
                return elem.getAttribute("href")
            }
        },
        relative: {
            "+": function (checkSet, part, isXML) {
                var isPartStr = typeof part === "string",
                    isTag = isPartStr && !/\W/.test(part),
                    isPartStrNotTag = isPartStr && !isTag;
                if (isTag && !isXML) {
                    part = part.toUpperCase()
                }
                for (var i = 0, l = checkSet.length, elem; i < l; i++) {
                    if ((elem = checkSet[i])) {
                        while ((elem = elem.previousSibling) && elem.nodeType !== 1) {}
                        checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ? elem || false : elem === part
                    }
                }
                if (isPartStrNotTag) {
                    Sizzle.filter(part, checkSet, true)
                }
            },
            ">": function (checkSet, part, isXML) {
                var isPartStr = typeof part === "string";
                if (isPartStr && !/\W/.test(part)) {
                    part = isXML ? part : part.toUpperCase();
                    for (var i = 0, l = checkSet.length; i < l; i++) {
                        var elem = checkSet[i];
                        if (elem) {
                            var parent = elem.parentNode;
                            checkSet[i] = parent.nodeName === part ? parent : false
                        }
                    }
                } else {
                    for (var i = 0, l = checkSet.length; i < l; i++) {
                        var elem = checkSet[i];
                        if (elem) {
                            checkSet[i] = isPartStr ? elem.parentNode : elem.parentNode === part
                        }
                    }
                    if (isPartStr) {
                        Sizzle.filter(part, checkSet, true)
                    }
                }
            },
            "": function (checkSet, part, isXML) {
                var doneName = done++,
                    checkFn = dirCheck;
                if (!/\W/.test(part)) {
                    var nodeCheck = part = isXML ? part : part.toUpperCase();
                    checkFn = dirNodeCheck
                }
                checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML)
            },
            "~": function (checkSet, part, isXML) {
                var doneName = done++,
                    checkFn = dirCheck;
                if (typeof part === "string" && !/\W/.test(part)) {
                    var nodeCheck = part = isXML ? part : part.toUpperCase();
                    checkFn = dirNodeCheck
                }
                checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML)
            }
        },
        find: {
            ID: function (match, context, isXML) {
                if (typeof context.getElementById !== "undefined" && !isXML) {
                    var m = context.getElementById(match[1]);
                    return m ? [m] : []
                }
            },
            NAME: function (match, context, isXML) {
                if (typeof context.getElementsByName !== "undefined") {
                    var ret = [],
                        results = context.getElementsByName(match[1]);
                    for (var i = 0, l = results.length; i < l; i++) {
                        if (results[i].getAttribute("name") === match[1]) {
                            ret.push(results[i])
                        }
                    }
                    return ret.length === 0 ? null : ret
                }
            },
            TAG: function (match, context) {
                return context.getElementsByTagName(match[1])
            }
        },
        preFilter: {
            CLASS: function (match, curLoop, inplace, result, not, isXML) {
                match = " " + match[1].replace(/\\/g, "") + " ";
                if (isXML) {
                    return match
                }
                for (var i = 0, elem;
                (elem = curLoop[i]) != null; i++) {
                    if (elem) {
                        if (not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0)) {
                            if (!inplace) result.push(elem)
                        } else if (inplace) {
                            curLoop[i] = false
                        }
                    }
                }
                return false
            },
            ID: function (match) {
                return match[1].replace(/\\/g, "")
            },
            TAG: function (match, curLoop) {
                for (var i = 0; curLoop[i] === false; i++) {}
                return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase()
            },
            CHILD: function (match) {
                if (match[1] == "nth") {
                    var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" || !/\D/.test(match[2]) && "0n+" + match[2] || match[2]);
                    match[2] = (test[1] + (test[2] || 1)) - 0;
                    match[3] = test[3] - 0
                }
                match[0] = done++;
                return match
            },
            ATTR: function (match, curLoop, inplace, result, not, isXML) {
                var name = match[1].replace(/\\/g, "");
                if (!isXML && Expr.attrMap[name]) {
                    match[1] = Expr.attrMap[name]
                }
                if (match[2] === "~=") {
                    match[4] = " " + match[4] + " "
                }
                return match
            },
            PSEUDO: function (match, curLoop, inplace, result, not) {
                if (match[1] === "not") {
                    if ((chunker.exec(match[3]) || "").length > 1 || /^\w/.test(match[3])) {
                        match[3] = Sizzle(match[3], null, null, curLoop)
                    } else {
                        var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
                        if (!inplace) {
                            result.push.apply(result, ret)
                        }
                        return false
                    }
                } else if (Expr.match.POS.test(match[0]) || Expr.match.CHILD.test(match[0])) {
                    return true
                }
                return match
            },
            POS: function (match) {
                match.unshift(true);
                return match
            }
        },
        filters: {
            enabled: function (elem) {
                return elem.disabled === false && elem.type !== "hidden"
            },
            disabled: function (elem) {
                return elem.disabled === true
            },
            checked: function (elem) {
                return elem.checked === true
            },
            selected: function (elem) {
                elem.parentNode.selectedIndex;
                return elem.selected === true
            },
            parent: function (elem) {
                return !!elem.firstChild
            },
            empty: function (elem) {
                return !elem.firstChild
            },
            has: function (elem, i, match) {
                return !!Sizzle(match[3], elem).length
            },
            header: function (elem) {
                return /h\d/i.test(elem.nodeName)
            },
            text: function (elem) {
                return "text" === elem.type
            },
            radio: function (elem) {
                return "radio" === elem.type
            },
            checkbox: function (elem) {
                return "checkbox" === elem.type
            },
            file: function (elem) {
                return "file" === elem.type
            },
            password: function (elem) {
                return "password" === elem.type
            },
            submit: function (elem) {
                return "submit" === elem.type
            },
            image: function (elem) {
                return "image" === elem.type
            },
            reset: function (elem) {
                return "reset" === elem.type
            },
            button: function (elem) {
                return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON"
            },
            input: function (elem) {
                return /input|select|textarea|button/i.test(elem.nodeName)
            }
        },
        setFilters: {
            first: function (elem, i) {
                return i === 0
            },
            last: function (elem, i, match, array) {
                return i === array.length - 1
            },
            even: function (elem, i) {
                return i % 2 === 0
            },
            odd: function (elem, i) {
                return i % 2 === 1
            },
            lt: function (elem, i, match) {
                return i < match[3] - 0
            },
            gt: function (elem, i, match) {
                return i > match[3] - 0
            },
            nth: function (elem, i, match) {
                return match[3] - 0 == i
            },
            eq: function (elem, i, match) {
                return match[3] - 0 == i
            }
        },
        filter: {
            PSEUDO: function (elem, match, i, array) {
                var name = match[1],
                    filter = Expr.filters[name];
                if (filter) {
                    return filter(elem, i, match, array)
                } else if (name === "contains") {
                    return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0
                } else if (name === "not") {
                    var not = match[3];
                    for (var i = 0, l = not.length; i < l; i++) {
                        if (not[i] === elem) {
                            return false
                        }
                    }
                    return true
                }
            },
            CHILD: function (elem, match) {
                var type = match[1],
                    node = elem;
                switch (type) {
                case 'only':
                case 'first':
                    while ((node = node.previousSibling)) {
                        if (node.nodeType === 1) return false
                    }
                    if (type == 'first') return true;
                    node = elem;
                case 'last':
                    while ((node = node.nextSibling)) {
                        if (node.nodeType === 1) return false
                    }
                    return true;
                case 'nth':
                    var first = match[2],
                        last = match[3];
                    if (first == 1 && last == 0) {
                        return true
                    }
                    var doneName = match[0],
                        parent = elem.parentNode;
                    if (parent && (parent.sizcache !== doneName || !elem.nodeIndex)) {
                        var count = 0;
                        for (node = parent.firstChild; node; node = node.nextSibling) {
                            if (node.nodeType === 1) {
                                node.nodeIndex = ++count
                            }
                        }
                        parent.sizcache = doneName
                    }
                    var diff = elem.nodeIndex - last;
                    if (first == 0) {
                        return diff == 0
                    } else {
                        return (diff % first == 0 && diff / first >= 0)
                    }
                }
            },
            ID: function (elem, match) {
                return elem.nodeType === 1 && elem.getAttribute("id") === match
            },
            TAG: function (elem, match) {
                return (match === "*" && elem.nodeType === 1) || elem.nodeName === match
            },
            CLASS: function (elem, match) {
                return (" " + (elem.className || elem.getAttribute("class")) + " ").indexOf(match) > -1
            },
            ATTR: function (elem, match) {
                var name = match[1],
                    result = Expr.attrHandle[name] ? Expr.attrHandle[name](elem) : elem[name] != null ? elem[name] : elem.getAttribute(name),
                    value = result + "",
                    type = match[2],
                    check = match[4];
                return result == null ? type === "!=" : type === "=" ? value === check : type === "*=" ? value.indexOf(check) >= 0 : type === "~=" ? (" " + value + " ").indexOf(check) >= 0 : !check ? value && result !== false : type === "!=" ? value != check : type === "^=" ? value.indexOf(check) === 0 : type === "$=" ? value.substr(value.length - check.length) === check : type === "|=" ? value === check || value.substr(0, check.length + 1) === check + "-" : false
            },
            POS: function (elem, match, i, array) {
                var name = match[2],
                    filter = Expr.setFilters[name];
                if (filter) {
                    return filter(elem, i, match, array)
                }
            }
        }
    };
    var origPOS = Expr.match.POS;
    for (var type in Expr.match) {
        Expr.match[type] = new RegExp(Expr.match[type].source + /(?![^\[]*\])(?![^\(]*\))/.source);
        Expr.leftMatch[type] = new RegExp(/(^(?:.|\r|\n)*?)/.source + Expr.match[type].source)
    }
    var makeArray = function (array, results) {
            array = Array.prototype.slice.call(array, 0);
            if (results) {
                results.push.apply(results, array);
                return results
            }
            return array
        };
    try {
        Array.prototype.slice.call(document.documentElement.childNodes, 0)
    } catch (e) {
        makeArray = function (array, results) {
            var ret = results || [];
            if (toString.call(array) === "[object Array]") {
                Array.prototype.push.apply(ret, array)
            } else {
                if (typeof array.length === "number") {
                    for (var i = 0, l = array.length; i < l; i++) {
                        ret.push(array[i])
                    }
                } else {
                    for (var i = 0; array[i]; i++) {
                        ret.push(array[i])
                    }
                }
            }
            return ret
        }
    }
    var sortOrder;
    if (document.documentElement.compareDocumentPosition) {
        sortOrder = function (a, b) {
            if (!a.compareDocumentPosition || !b.compareDocumentPosition) {
                if (a == b) {
                    hasDuplicate = true
                }
                return 0
            }
            var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
            if (ret === 0) {
                hasDuplicate = true
            }
            return ret
        }
    } else if ("sourceIndex" in document.documentElement) {
        sortOrder = function (a, b) {
            if (!a.sourceIndex || !b.sourceIndex) {
                if (a == b) {
                    hasDuplicate = true
                }
                return 0
            }
            var ret = a.sourceIndex - b.sourceIndex;
            if (ret === 0) {
                hasDuplicate = true
            }
            return ret
        }
    } else if (document.createRange) {
        sortOrder = function (a, b) {
            if (!a.ownerDocument || !b.ownerDocument) {
                if (a == b) {
                    hasDuplicate = true
                }
                return 0
            }
            var aRange = a.ownerDocument.createRange(),
                bRange = b.ownerDocument.createRange();
            aRange.setStart(a, 0);
            aRange.setEnd(a, 0);
            bRange.setStart(b, 0);
            bRange.setEnd(b, 0);
            var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
            if (ret === 0) {
                hasDuplicate = true
            }
            return ret
        }
    }(function () {
        var form = document.createElement("div"),
            id = "script" + (new Date).getTime();
        form.innerHTML = "<a name='" + id + "'/>";
        var root = document.documentElement;
        root.insertBefore(form, root.firstChild);
        if ( !! document.getElementById(id)) {
            Expr.find.ID = function (match, context, isXML) {
                if (typeof context.getElementById !== "undefined" && !isXML) {
                    var m = context.getElementById(match[1]);
                    return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []
                }
            };
            Expr.filter.ID = function (elem, match) {
                var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
                return elem.nodeType === 1 && node && node.nodeValue === match
            }
        }
        root.removeChild(form);
        root = form = null
    })();
    (function () {
        var div = document.createElement("div");
        div.appendChild(document.createComment(""));
        if (div.getElementsByTagName("*").length > 0) {
            Expr.find.TAG = function (match, context) {
                var results = context.getElementsByTagName(match[1]);
                if (match[1] === "*") {
                    var tmp = [];
                    for (var i = 0; results[i]; i++) {
                        if (results[i].nodeType === 1) {
                            tmp.push(results[i])
                        }
                    }
                    results = tmp
                }
                return results
            }
        }
        div.innerHTML = "<a href='#'></a>";
        if (div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && div.firstChild.getAttribute("href") !== "#") {
            Expr.attrHandle.href = function (elem) {
                return elem.getAttribute("href", 2)
            }
        }
        div = null
    })();
    if (document.querySelectorAll)(function () {
        var oldSizzle = Sizzle,
            div = document.createElement("div");
        div.innerHTML = "<p class='TEST'></p>";
        if (div.querySelectorAll && div.querySelectorAll(".TEST").length === 0) {
            return
        }
        Sizzle = function (query, context, extra, seed) {
            context = context || document;
            if (!seed && context.nodeType === 9 && !isXML(context)) {
                try {
                    return makeArray(context.querySelectorAll(query), extra)
                } catch (e) {}
            }
            return oldSizzle(query, context, extra, seed)
        };
        for (var prop in oldSizzle) {
            Sizzle[prop] = oldSizzle[prop]
        }
        div = null
    })();
    if (document.getElementsByClassName && document.documentElement.getElementsByClassName)(function () {
        var div = document.createElement("div");
        div.innerHTML = "<div class='test e'></div><div class='test'></div>";
        if (div.getElementsByClassName("e").length === 0) return;
        div.lastChild.className = "e";
        if (div.getElementsByClassName("e").length === 1) return;
        Expr.order.splice(1, 0, "CLASS");
        Expr.find.CLASS = function (match, context, isXML) {
            if (typeof context.getElementsByClassName !== "undefined" && !isXML) {
                return context.getElementsByClassName(match[1])
            }
        };
        div = null
    })();

    function dirNodeCheck(dir, cur, doneName, checkSet, nodeCheck, isXML) {
        var sibDir = dir == "previousSibling" && !isXML;
        for (var i = 0, l = checkSet.length; i < l; i++) {
            var elem = checkSet[i];
            if (elem) {
                if (sibDir && elem.nodeType === 1) {
                    elem.sizcache = doneName;
                    elem.sizset = i
                }
                elem = elem[dir];
                var match = false;
                while (elem) {
                    if (elem.sizcache === doneName) {
                        match = checkSet[elem.sizset];
                        break
                    }
                    if (elem.nodeType === 1 && !isXML) {
                        elem.sizcache = doneName;
                        elem.sizset = i
                    }
                    if (elem.nodeName === cur) {
                        match = elem;
                        break
                    }
                    elem = elem[dir]
                }
                checkSet[i] = match
            }
        }
    }
    function dirCheck(dir, cur, doneName, checkSet, nodeCheck, isXML) {
        var sibDir = dir == "previousSibling" && !isXML;
        for (var i = 0, l = checkSet.length; i < l; i++) {
            var elem = checkSet[i];
            if (elem) {
                if (sibDir && elem.nodeType === 1) {
                    elem.sizcache = doneName;
                    elem.sizset = i
                }
                elem = elem[dir];
                var match = false;
                while (elem) {
                    if (elem.sizcache === doneName) {
                        match = checkSet[elem.sizset];
                        break
                    }
                    if (elem.nodeType === 1) {
                        if (!isXML) {
                            elem.sizcache = doneName;
                            elem.sizset = i
                        }
                        if (typeof cur !== "string") {
                            if (elem === cur) {
                                match = true;
                                break
                            }
                        } else if (Sizzle.filter(cur, [elem]).length > 0) {
                            match = elem;
                            break
                        }
                    }
                    elem = elem[dir]
                }
                checkSet[i] = match
            }
        }
    }
    var contains = document.compareDocumentPosition ?
    function (a, b) {
        return a.compareDocumentPosition(b) & 16
    } : function (a, b) {
        return a !== b && (a.contains ? a.contains(b) : true)
    };
    var isXML = function (elem) {
            return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || !! elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML"
        };
    var posProcess = function (selector, context) {
            var tmpSet = [],
                later = "",
                match, root = context.nodeType ? [context] : context;
            while ((match = Expr.match.PSEUDO.exec(selector))) {
                later += match[0];
                selector = selector.replace(Expr.match.PSEUDO, "")
            }
            selector = Expr.relative[selector] ? selector + "*" : selector;
            for (var i = 0, l = root.length; i < l; i++) {
                Sizzle(selector, root[i], tmpSet)
            }
            return Sizzle.filter(later, tmpSet)
        };
    window.Sizzle = Sizzle
})();
(function (engine) {
    var extendElements = Prototype.Selector.extendElements;

    function select(selector, scope) {
        return extendElements(engine(selector, scope || document))
    }
    function match(element, selector) {
        return engine.matches(selector, [element]).length == 1
    }
    Prototype.Selector.engine = engine;
    Prototype.Selector.select = select;
    Prototype.Selector.match = match
})(Sizzle);
window.Sizzle = Prototype._original_property;
delete Prototype._original_property;
var Form = {
    reset: function (form) {
        form = $(form);
        form.reset();
        return form
    },
    serializeElements: function (elements, options) {
        if (typeof options != 'object') options = {
            hash: !! options
        };
        else if (Object.isUndefined(options.hash)) options.hash = true;
        var key, value, submitted = false,
            submit = options.submit,
            accumulator, initial;
        if (options.hash) {
            initial = {};
            accumulator = function (result, key, value) {
                if (key in result) {
                    if (!Object.isArray(result[key])) result[key] = [result[key]];
                    result[key].push(value)
                } else result[key] = value;
                return result
            }
        } else {
            initial = '';
            accumulator = function (result, key, value) {
                return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + encodeURIComponent(value)
            }
        }
        return elements.inject(initial, function (result, element) {
            if (!element.disabled && element.name) {
                key = element.name;
                value = $(element).getValue();
                if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && submit !== false && (!submit || key == submit) && (submitted = true)))) {
                    result = accumulator(result, key, value)
                }
            }
            return result
        })
    }
};
Form.Methods = {
    serialize: function (form, options) {
        return Form.serializeElements(Form.getElements(form), options)
    },
    getElements: function (form) {
        var elements = $(form).getElementsByTagName('*'),
            element, arr = [],
            serializers = Form.Element.Serializers;
        for (var i = 0; element = elements[i]; i++) {
            arr.push(element)
        }
        return arr.inject([], function (elements, child) {
            if (serializers[child.tagName.toLowerCase()]) elements.push(Element.extend(child));
            return elements
        })
    },
    getInputs: function (form, typeName, name) {
        form = $(form);
        var inputs = form.getElementsByTagName('input');
        if (!typeName && !name) return $A(inputs).map(Element.extend);
        for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
            var input = inputs[i];
            if ((typeName && input.type != typeName) || (name && input.name != name)) continue;
            matchingInputs.push(Element.extend(input))
        }
        return matchingInputs
    },
    disable: function (form) {
        form = $(form);
        Form.getElements(form).invoke('disable');
        return form
    },
    enable: function (form) {
        form = $(form);
        Form.getElements(form).invoke('enable');
        return form
    },
    findFirstElement: function (form) {
        var elements = $(form).getElements().findAll(function (element) {
            return 'hidden' != element.type && !element.disabled
        });
        var firstByIndex = elements.findAll(function (element) {
            return element.hasAttribute('tabIndex') && element.tabIndex >= 0
        }).sortBy(function (element) {
            return element.tabIndex
        }).first();
        return firstByIndex ? firstByIndex : elements.find(function (element) {
            return /^(?:input|select|textarea)$/i.test(element.tagName)
        })
    },
    focusFirstElement: function (form) {
        form = $(form);
        var element = form.findFirstElement();
        if (element) element.activate();
        return form
    },
    request: function (form, options) {
        form = $(form), options = Object.clone(options || {});
        var params = options.parameters,
            action = form.readAttribute('action') || '';
        if (action.blank()) action = window.location.href;
        options.parameters = form.serialize(true);
        if (params) {
            if (Object.isString(params)) params = params.toQueryParams();
            Object.extend(options.parameters, params)
        }
        if (form.hasAttribute('method') && !options.method) options.method = form.method;
        return new Ajax.Request(action, options)
    }
};
Form.Element = {
    focus: function (element) {
        $(element).focus();
        return element
    },
    select: function (element) {
        $(element).select();
        return element
    }
};
Form.Element.Methods = {
    serialize: function (element) {
        element = $(element);
        if (!element.disabled && element.name) {
            var value = element.getValue();
            if (value != undefined) {
                var pair = {};
                pair[element.name] = value;
                return Object.toQueryString(pair)
            }
        }
        return ''
    },
    getValue: function (element) {
        element = $(element);
        var method = element.tagName.toLowerCase();
        return Form.Element.Serializers[method](element)
    },
    setValue: function (element, value) {
        element = $(element);
        var method = element.tagName.toLowerCase();
        Form.Element.Serializers[method](element, value);
        return element
    },
    clear: function (element) {
        $(element).value = '';
        return element
    },
    present: function (element) {
        return $(element).value != ''
    },
    activate: function (element) {
        element = $(element);
        try {
            element.focus();
            if (element.select && (element.tagName.toLowerCase() != 'input' || !(/^(?:button|reset|submit)$/i.test(element.type)))) element.select()
        } catch (e) {}
        return element
    },
    disable: function (element) {
        element = $(element);
        element.disabled = true;
        return element
    },
    enable: function (element) {
        element = $(element);
        element.disabled = false;
        return element
    }
};
var Field = Form.Element;
var $F = Form.Element.Methods.getValue;
Form.Element.Serializers = (function () {
    function input(element, value) {
        switch (element.type.toLowerCase()) {
        case 'checkbox':
        case 'radio':
            return inputSelector(element, value);
        default:
            return valueSelector(element, value)
        }
    }
    function inputSelector(element, value) {
        if (Object.isUndefined(value)) return element.checked ? element.value : null;
        else element.checked = !! value
    }
    function valueSelector(element, value) {
        if (Object.isUndefined(value)) return element.value;
        else element.value = value
    }
    function select(element, value) {
        if (Object.isUndefined(value)) return (element.type === 'select-one' ? selectOne : selectMany)(element);
        var opt, currentValue, single = !Object.isArray(value);
        for (var i = 0, length = element.length; i < length; i++) {
            opt = element.options[i];
            currentValue = this.optionValue(opt);
            if (single) {
                if (currentValue == value) {
                    opt.selected = true;
                    return
                }
            } else opt.selected = value.include(currentValue)
        }
    }
    function selectOne(element) {
        var index = element.selectedIndex;
        return index >= 0 ? optionValue(element.options[index]) : null
    }
    function selectMany(element) {
        var values, length = element.length;
        if (!length) return null;
        for (var i = 0, values = []; i < length; i++) {
            var opt = element.options[i];
            if (opt.selected) values.push(optionValue(opt))
        }
        return values
    }
    function optionValue(opt) {
        return Element.hasAttribute(opt, 'value') ? opt.value : opt.text
    }
    return {
        input: input,
        inputSelector: inputSelector,
        textarea: valueSelector,
        select: select,
        selectOne: selectOne,
        selectMany: selectMany,
        optionValue: optionValue,
        button: valueSelector
    }
})();
Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
    initialize: function ($super, element, frequency, callback) {
        $super(callback, frequency);
        this.element = $(element);
        this.lastValue = this.getValue()
    },
    execute: function () {
        var value = this.getValue();
        if (Object.isString(this.lastValue) && Object.isString(value) ? this.lastValue != value : String(this.lastValue) != String(value)) {
            this.callback(this.element, value);
            this.lastValue = value
        }
    }
});
Form.Element.Observer = Class.create(Abstract.TimedObserver, {
    getValue: function () {
        return Form.Element.getValue(this.element)
    }
});
Form.Observer = Class.create(Abstract.TimedObserver, {
    getValue: function () {
        return Form.serialize(this.element)
    }
});
Abstract.EventObserver = Class.create({
    initialize: function (element, callback) {
        this.element = $(element);
        this.callback = callback;
        this.lastValue = this.getValue();
        if (this.element.tagName.toLowerCase() == 'form') this.registerFormCallbacks();
        else this.registerCallback(this.element)
    },
    onElementEvent: function () {
        var value = this.getValue();
        if (this.lastValue != value) {
            this.callback(this.element, value);
            this.lastValue = value
        }
    },
    registerFormCallbacks: function () {
        Form.getElements(this.element).each(this.registerCallback, this)
    },
    registerCallback: function (element) {
        if (element.type) {
            switch (element.type.toLowerCase()) {
            case 'checkbox':
            case 'radio':
                Event.observe(element, 'click', this.onElementEvent.bind(this));
                break;
            default:
                Event.observe(element, 'change', this.onElementEvent.bind(this));
                break
            }
        }
    }
});
Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
    getValue: function () {
        return Form.Element.getValue(this.element)
    }
});
Form.EventObserver = Class.create(Abstract.EventObserver, {
    getValue: function () {
        return Form.serialize(this.element)
    }
});
(function () {
    var Event = {
        KEY_BACKSPACE: 8,
        KEY_TAB: 9,
        KEY_RETURN: 13,
        KEY_ESC: 27,
        KEY_LEFT: 37,
        KEY_UP: 38,
        KEY_RIGHT: 39,
        KEY_DOWN: 40,
        KEY_DELETE: 46,
        KEY_HOME: 36,
        KEY_END: 35,
        KEY_PAGEUP: 33,
        KEY_PAGEDOWN: 34,
        KEY_INSERT: 45,
        cache: {}
    };
    var docEl = document.documentElement;
    var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl && 'onmouseleave' in docEl;
    var isIELegacyEvent = function (event) {
            return false
        };
    if (window.attachEvent) {
        if (window.addEventListener) {
            isIELegacyEvent = function (event) {
                return !(event instanceof window.Event)
            }
        } else {
            isIELegacyEvent = function (event) {
                return true
            }
        }
    }
    var _isButton;

    function _isButtonForDOMEvents(event, code) {
        return event.which ? (event.which === code + 1) : (event.button === code)
    }
    var legacyButtonMap = {
        0: 1,
        1: 4,
        2: 2
    };

    function _isButtonForLegacyEvents(event, code) {
        return event.button === legacyButtonMap[code]
    }
    function _isButtonForWebKit(event, code) {
        switch (code) {
        case 0:
            return event.which == 1 && !event.metaKey;
        case 1:
            return event.which == 2 || (event.which == 1 && event.metaKey);
        case 2:
            return event.which == 3;
        default:
            return false
        }
    }
    if (window.attachEvent) {
        if (!window.addEventListener) {
            _isButton = _isButtonForLegacyEvents
        } else {
            _isButton = function (event, code) {
                return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) : _isButtonForDOMEvents(event, code)
            }
        }
    } else if (Prototype.Browser.WebKit) {
        _isButton = _isButtonForWebKit
    } else {
        _isButton = _isButtonForDOMEvents
    }
    function isLeftClick(event) {
        return _isButton(event, 0)
    }
    function isMiddleClick(event) {
        return _isButton(event, 1)
    }
    function isRightClick(event) {
        return _isButton(event, 2)
    }
    function element(event) {
        event = Event.extend(event);
        var node = event.target,
            type = event.type,
            currentTarget = event.currentTarget;
        if (currentTarget && currentTarget.tagName) {
            if (type === 'load' || type === 'error' || (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' && currentTarget.type === 'radio')) node = currentTarget
        }
        if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
        return Element.extend(node)
    }
    function findElement(event, expression) {
        var element = Event.element(event);
        if (!expression) return element;
        while (element) {
            if (Object.isElement(element) && Prototype.Selector.match(element, expression)) {
                return Element.extend(element)
            }
            element = element.parentNode
        }
    }
    function pointer(event) {
        return {
            x: pointerX(event),
            y: pointerY(event)
        }
    }
    function pointerX(event) {
        var docElement = document.documentElement,
            body = document.body || {
                scrollLeft: 0
            };
        return event.pageX || (event.clientX + (docElement.scrollLeft || body.scrollLeft) - (docElement.clientLeft || 0))
    }
    function pointerY(event) {
        var docElement = document.documentElement,
            body = document.body || {
                scrollTop: 0
            };
        return event.pageY || (event.clientY + (docElement.scrollTop || body.scrollTop) - (docElement.clientTop || 0))
    }
    function stop(event) {
        Event.extend(event);
        event.preventDefault();
        event.stopPropagation();
        event.stopped = true
    }
    Event.Methods = {
        isLeftClick: isLeftClick,
        isMiddleClick: isMiddleClick,
        isRightClick: isRightClick,
        element: element,
        findElement: findElement,
        pointer: pointer,
        pointerX: pointerX,
        pointerY: pointerY,
        stop: stop
    };
    var methods = Object.keys(Event.Methods).inject({}, function (m, name) {
        m[name] = Event.Methods[name].methodize();
        return m
    });
    if (window.attachEvent) {
        function _relatedTarget(event) {
            var element;
            switch (event.type) {
            case 'mouseover':
            case 'mouseenter':
                element = event.fromElement;
                break;
            case 'mouseout':
            case 'mouseleave':
                element = event.toElement;
                break;
            default:
                return null
            }
            return Element.extend(element)
        }
        var additionalMethods = {
            stopPropagation: function () {
                this.cancelBubble = true
            },
            preventDefault: function () {
                this.returnValue = false
            },
            inspect: function () {
                return '[object Event]'
            }
        };
        Event.extend = function (event, element) {
            if (!event) return false;
            if (!isIELegacyEvent(event)) return event;
            if (event._extendedByPrototype) return event;
            event._extendedByPrototype = Prototype.emptyFunction;
            var pointer = Event.pointer(event);
            Object.extend(event, {
                target: event.srcElement || element,
                relatedTarget: _relatedTarget(event),
                pageX: pointer.x,
                pageY: pointer.y
            });
            Object.extend(event, methods);
            Object.extend(event, additionalMethods);
            return event
        }
    } else {
        Event.extend = Prototype.K
    }
    if (window.addEventListener) {
        Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
        Object.extend(Event.prototype, methods)
    }
    function _createResponder(element, eventName, handler) {
        var registry = Element.retrieve(element, 'prototype_event_registry');
        if (Object.isUndefined(registry)) {
            CACHE.push(element);
            registry = Element.retrieve(element, 'prototype_event_registry', $H())
        }
        var respondersForEvent = registry.get(eventName);
        if (Object.isUndefined(respondersForEvent)) {
            respondersForEvent = [];
            registry.set(eventName, respondersForEvent)
        }
        if (respondersForEvent.pluck('handler').include(handler)) return false;
        var responder;
        if (eventName.include(":")) {
            responder = function (event) {
                if (Object.isUndefined(event.eventName)) return false;
                if (event.eventName !== eventName) return false;
                Event.extend(event, element);
                handler.call(element, event)
            }
        } else {
            if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && (eventName === "mouseenter" || eventName === "mouseleave")) {
                if (eventName === "mouseenter" || eventName === "mouseleave") {
                    responder = function (event) {
                        Event.extend(event, element);
                        var parent = event.relatedTarget;
                        while (parent && parent !== element) {
                            try {
                                parent = parent.parentNode
                            } catch (e) {
                                parent = element
                            }
                        }
                        if (parent === element) return;
                        handler.call(element, event)
                    }
                }
            } else {
                responder = function (event) {
                    Event.extend(event, element);
                    handler.call(element, event)
                }
            }
        }
        responder.handler = handler;
        respondersForEvent.push(responder);
        return responder
    }
    function _destroyCache() {
        for (var i = 0, length = CACHE.length; i < length; i++) {
            Event.stopObserving(CACHE[i]);
            CACHE[i] = null
        }
    }
    var CACHE = [];
    if (Prototype.Browser.IE) window.attachEvent('onunload', _destroyCache);
    if (Prototype.Browser.WebKit) window.addEventListener('unload', Prototype.emptyFunction, false);
    var _getDOMEventName = Prototype.K,
        translations = {
            mouseenter: "mouseover",
            mouseleave: "mouseout"
        };
    if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) {
        _getDOMEventName = function (eventName) {
            return (translations[eventName] || eventName)
        }
    }
    function observe(element, eventName, handler) {
        element = $(element);
        var responder = _createResponder(element, eventName, handler);
        if (!responder) return element;
        if (eventName.include(':')) {
            if (element.addEventListener) element.addEventListener("dataavailable", responder, false);
            else {
                element.attachEvent("ondataavailable", responder);
                element.attachEvent("onlosecapture", responder)
            }
        } else {
            var actualEventName = _getDOMEventName(eventName);
            if (element.addEventListener) element.addEventListener(actualEventName, responder, false);
            else element.attachEvent("on" + actualEventName, responder)
        }
        return element
    }
    function stopObserving(element, eventName, handler) {
        element = $(element);
        var registry = Element.retrieve(element, 'prototype_event_registry');
        if (!registry) return element;
        if (!eventName) {
            registry.each(function (pair) {
                var eventName = pair.key;
                stopObserving(element, eventName)
            });
            return element
        }
        var responders = registry.get(eventName);
        if (!responders) return element;
        if (!handler) {
            responders.each(function (r) {
                stopObserving(element, eventName, r.handler)
            });
            return element
        }
        var i = responders.length,
            responder;
        while (i--) {
            if (responders[i].handler === handler) {
                responder = responders[i];
                break
            }
        }
        if (!responder) return element;
        if (eventName.include(':')) {
            if (element.removeEventListener) element.removeEventListener("dataavailable", responder, false);
            else {
                element.detachEvent("ondataavailable", responder);
                element.detachEvent("onlosecapture", responder)
            }
        } else {
            var actualEventName = _getDOMEventName(eventName);
            if (element.removeEventListener) element.removeEventListener(actualEventName, responder, false);
            else element.detachEvent('on' + actualEventName, responder)
        }
        registry.set(eventName, responders.without(responder));
        return element
    }
    function fire(element, eventName, memo, bubble) {
        element = $(element);
        if (Object.isUndefined(bubble)) bubble = true;
        if (element == document && document.createEvent && !element.dispatchEvent) element = document.documentElement;
        var event;
        if (document.createEvent) {
            event = document.createEvent('HTMLEvents');
            event.initEvent('dataavailable', bubble, true)
        } else {
            event = document.createEventObject();
            event.eventType = bubble ? 'ondataavailable' : 'onlosecapture'
        }
        event.eventName = eventName;
        event.memo = memo || {};
        if (document.createEvent) element.dispatchEvent(event);
        else element.fireEvent(event.eventType, event);
        return Event.extend(event)
    }
    Event.Handler = Class.create({
        initialize: function (element, eventName, selector, callback) {
            this.element = $(element);
            this.eventName = eventName;
            this.selector = selector;
            this.callback = callback;
            this.handler = this.handleEvent.bind(this)
        },
        start: function () {
            Event.observe(this.element, this.eventName, this.handler);
            return this
        },
        stop: function () {
            Event.stopObserving(this.element, this.eventName, this.handler);
            return this
        },
        handleEvent: function (event) {
            var element = Event.findElement(event, this.selector);
            if (element) this.callback.call(this.element, event, element)
        }
    });

    function on(element, eventName, selector, callback) {
        element = $(element);
        if (Object.isFunction(selector) && Object.isUndefined(callback)) {
            callback = selector, selector = null
        }
        return new Event.Handler(element, eventName, selector, callback).start()
    }
    Object.extend(Event, Event.Methods);
    Object.extend(Event, {
        fire: fire,
        observe: observe,
        stopObserving: stopObserving,
        on: on
    });
    Element.addMethods({
        fire: fire,
        observe: observe,
        stopObserving: stopObserving,
        on: on
    });
    Object.extend(document, {
        fire: fire.methodize(),
        observe: observe.methodize(),
        stopObserving: stopObserving.methodize(),
        on: on.methodize(),
        loaded: false
    });
    if (window.Event) Object.extend(window.Event, Event);
    else window.Event = Event
})();
(function () {
    var timer;

    function fireContentLoadedEvent() {
        if (document.loaded) return;
        if (timer) window.clearTimeout(timer);
        document.loaded = true;
        document.fire('dom:loaded')
    }
    function checkReadyState() {
        if (document.readyState === 'complete') {
            document.stopObserving('readystatechange', checkReadyState);
            fireContentLoadedEvent()
        }
    }
    function pollDoScroll() {
        try {
            document.documentElement.doScroll('left')
        } catch (e) {
            timer = pollDoScroll.defer();
            return
        }
        fireContentLoadedEvent()
    }
    if (document.addEventListener) {
        document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false)
    } else {
        document.observe('readystatechange', checkReadyState);
        if (window == top) timer = pollDoScroll.defer()
    }
    Event.observe(window, 'load', fireContentLoadedEvent)
})();
Element.addMethods();
Hash.toQueryString = Object.toQueryString;
var Toggle = {
    display: Element.toggle
};
Element.Methods.childOf = Element.Methods.descendantOf;
var Insertion = {
    Before: function (element, content) {
        return Element.insert(element, {
            before: content
        })
    },
    Top: function (element, content) {
        return Element.insert(element, {
            top: content
        })
    },
    Bottom: function (element, content) {
        return Element.insert(element, {
            bottom: content
        })
    },
    After: function (element, content) {
        return Element.insert(element, {
            after: content
        })
    }
};
var $continue = new Error('"throw $continue"is deprecated,use"return"instead');
var Position = {
    includeScrollOffsets: false,
    prepare: function () {
        this.deltaX = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
        this.deltaY = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
    },
    within: function (element, x, y) {
        if (this.includeScrollOffsets) return this.withinIncludingScrolloffsets(element, x, y);
        this.xcomp = x;
        this.ycomp = y;
        this.offset = Element.cumulativeOffset(element);
        return (y >= this.offset[1] && y < this.offset[1] + element.offsetHeight && x >= this.offset[0] && x < this.offset[0] + element.offsetWidth)
    },
    withinIncludingScrolloffsets: function (element, x, y) {
        var offsetcache = Element.cumulativeScrollOffset(element);
        this.xcomp = x + offsetcache[0] - this.deltaX;
        this.ycomp = y + offsetcache[1] - this.deltaY;
        this.offset = Element.cumulativeOffset(element);
        return (this.ycomp >= this.offset[1] && this.ycomp < this.offset[1] + element.offsetHeight && this.xcomp >= this.offset[0] && this.xcomp < this.offset[0] + element.offsetWidth)
    },
    overlap: function (mode, element) {
        if (!mode) return 0;
        if (mode == 'vertical') return ((this.offset[1] + element.offsetHeight) - this.ycomp) / element.offsetHeight;
        if (mode == 'horizontal') return ((this.offset[0] + element.offsetWidth) - this.xcomp) / element.offsetWidth
    },
    cumulativeOffset: Element.Methods.cumulativeOffset,
    positionedOffset: Element.Methods.positionedOffset,
    absolutize: function (element) {
        Position.prepare();
        return Element.absolutize(element)
    },
    relativize: function (element) {
        Position.prepare();
        return Element.relativize(element)
    },
    realOffset: Element.Methods.cumulativeScrollOffset,
    offsetParent: Element.Methods.getOffsetParent,
    page: Element.Methods.viewportOffset,
    clone: function (source, target, options) {
        options = options || {};
        return Element.clonePosition(target, source, options)
    }
};
if (!document.getElementsByClassName) document.getElementsByClassName = function (instanceMethods) {
    function iter(name) {
        return name.blank() ? null : "[contains(concat('', @class, ''), '" + name + "')]"
    }
    instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
    function (element, className) {
        className = className.toString().strip();
        var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
        return cond ? document._getElementsByXPath('.