//MooTools More, <http://mootools.net/more>. Copyright (c) 2006-2009 Aaron Newton <http://clientcide.com/>, Valerio Proietti <http://mad4milk.net> & the MooTools team <http://mootools.net/developers>, MIT Style License.

MooTools.More = { version: "1.2.4.4", build: "6f6057dc645fdb7547689183b2311063bd653ddf" }; Element.implement({ measure: function(e) {
    var g = function(h) {
        return !!(!h || h.offsetHeight || h.offsetWidth);
    }; if (g(this)) { return e.apply(this); } var d = this.getParent(), f = [], b = []; while (!g(d) && d != document.body) { b.push(d.expose()); d = d.getParent(); } var c = this.expose();
    var a = e.apply(this); c(); b.each(function(h) { h(); }); return a;
}, expose: function() {
    if (this.getStyle("display") != "none") { return $empty; } var a = this.style.cssText;
    this.setStyles({ display: "block", position: "absolute", visibility: "hidden" }); return function() { this.style.cssText = a; } .bind(this);
}, getDimensions: function(a) {
    a = $merge({ computeSize: false }, a);
    var f = {}; var d = function(g, e) { return (e.computeSize) ? g.getComputedSize(e) : g.getSize(); }; var b = this.getParent("body"); if (b && this.getStyle("display") == "none") {
        f = this.measure(function() {
            return d(this, a);
        });
    } else { if (b) { try { f = d(this, a); } catch (c) { } } else { f = { x: 0, y: 0 }; } } return $chk(f.x) ? $extend(f, { width: f.x, height: f.y }) : $extend(f, { x: f.width, y: f.height });
}, getComputedSize: function(a) {
    a = $merge({ styles: ["padding", "border"], plains: { height: ["top", "bottom"], width: ["left", "right"] }, mode: "both" }, a);
    var c = { width: 0, height: 0 }; switch (a.mode) {
        case "vertical": delete c.width; delete a.plains.width; break; case "horizontal": delete c.height; delete a.plains.height;
            break;
    } var b = []; $each(a.plains, function(g, f) { g.each(function(h) { a.styles.each(function(i) { b.push((i == "border") ? i + "-" + h + "-width" : i + "-" + h); }); }); }); var e = {};
    b.each(function(f) { e[f] = this.getComputedStyle(f); }, this); var d = []; $each(a.plains, function(g, f) {
        var h = f.capitalize(); c["total" + h] = c["computed" + h] = 0; g.each(function(i) {
            c["computed" + i.capitalize()] = 0;
            b.each(function(k, j) {
                if (k.test(i)) { e[k] = e[k].toInt() || 0; c["total" + h] = c["total" + h] + e[k]; c["computed" + i.capitalize()] = c["computed" + i.capitalize()] + e[k]; } if (k.test(i) && f != k && (k.test("border") || k.test("padding")) && !d.contains(k)) {
                    d.push(k);
                    c["computed" + h] = c["computed" + h] - e[k];
                } 
            });
        });
    }); ["Width", "Height"].each(function(g) {
        var f = g.toLowerCase(); if (!$chk(c[f])) { return; } c[f] = c[f] + this["offset" + g] + c["computed" + g];
        c["total" + g] = c[f] + c["total" + g]; delete c["computed" + g];
    }, this); return $extend(e, c);
} 
}); Fx.Scroll = new Class({ Extends: Fx, options: { offset: { x: 0, y: 0 }, wheelStops: true }, initialize: function(b, a) {
    this.element = this.subject = document.id(b);
    this.parent(a); var d = this.cancel.bind(this, false); if ($type(this.element) != "element") { this.element = document.id(this.element.getDocument().body); } var c = this.element;
    if (this.options.wheelStops) {
        this.addEvent("start", function() { c.addEvent("mousewheel", d); }, true); this.addEvent("complete", function() {
            c.removeEvent("mousewheel", d);
        }, true);
    } 
}, set: function() {
    var a = Array.flatten(arguments); if (Browser.Engine.gecko) { a = [Math.round(a[0]), Math.round(a[1])]; } this.element.scrollTo(a[0], a[1]);
}, compute: function(c, b, a) { return [0, 1].map(function(d) { return Fx.compute(c[d], b[d], a); }); }, start: function(c, g) {
    if (!this.check(c, g)) { return this; } var e = this.element.getScrollSize(), b = this.element.getScroll(), d = { x: c, y: g };
    for (var f in d) { var a = e[f]; if ($chk(d[f])) { d[f] = ($type(d[f]) == "number") ? d[f] : a; } else { d[f] = b[f]; } d[f] += this.options.offset[f]; } return this.parent([b.x, b.y], [d.x, d.y]);
}, toTop: function() { return this.start(false, 0); }, toLeft: function() { return this.start(0, false); }, toRight: function() { return this.start("right", false); }, toBottom: function() {
    return this.start(false, "bottom");
}, toElement: function(b) { var a = document.id(b).getPosition(this.element); return this.start(a.x, a.y); }, scrollIntoView: function(c, e, d) {
    e = e ? $splat(e) : ["x", "y"];
    var h = {}; c = document.id(c); var f = c.getPosition(this.element); var i = c.getSize(); var g = this.element.getScroll(); var a = this.element.getSize(); var b = { x: f.x + i.x, y: f.y + i.y };
    ["x", "y"].each(function(j) {
        if (e.contains(j)) { if (b[j] > g[j] + a[j]) { h[j] = b[j] - a[j]; } if (f[j] < g[j]) { h[j] = f[j]; } } if (h[j] == null) { h[j] = g[j]; } if (d && d[j]) {
            h[j] = h[j] + d[j];
        } 
    }, this); if (h.x != g.x || h.y != g.y) { this.start(h.x, h.y); } return this;
}, scrollToCenter: function(c, e, d) {
    e = e ? $splat(e) : ["x", "y"]; c = $(c); var h = {}, f = c.getPosition(this.element), i = c.getSize(), g = this.element.getScroll(), a = this.element.getSize(), b = { x: f.x + i.x, y: f.y + i.y };
    ["x", "y"].each(function(j) { if (e.contains(j)) { h[j] = f[j] - (a[j] - i[j]) / 2; } if (h[j] == null) { h[j] = g[j]; } if (d && d[j]) { h[j] = h[j] + d[j]; } }, this); if (h.x != g.x || h.y != g.y) {
        this.start(h.x, h.y);
    } return this;
} 
}); var Drag = new Class({ Implements: [Events, Options], options: { snap: 6, unit: "px", grid: false, style: true, limit: false, handle: false, invert: false, preventDefault: false, stopPropagation: false, modifiers: { x: "left", y: "top"} }, initialize: function() {
    var b = Array.link(arguments, { options: Object.type, element: $defined });
    this.element = document.id(b.element); this.document = this.element.getDocument(); this.setOptions(b.options || {}); var a = $type(this.options.handle); this.handles = ((a == "array" || a == "collection") ? $$(this.options.handle) : document.id(this.options.handle)) || this.element;
    this.mouse = { now: {}, pos: {} }; this.value = { start: {}, now: {} }; this.selection = (Browser.Engine.trident) ? "selectstart" : "mousedown"; this.bound = { start: this.start.bind(this), check: this.check.bind(this), drag: this.drag.bind(this), stop: this.stop.bind(this), cancel: this.cancel.bind(this), eventStop: $lambda(false) };
    this.attach();
}, attach: function() { this.handles.addEvent("mousedown", this.bound.start); return this; }, detach: function() {
    this.handles.removeEvent("mousedown", this.bound.start);
    return this;
}, start: function(c) {
    if (c.rightClick) { return; } if (this.options.preventDefault) { c.preventDefault(); } if (this.options.stopPropagation) {
        c.stopPropagation();
    } this.mouse.start = c.page; this.fireEvent("beforeStart", this.element); var a = this.options.limit; this.limit = { x: [], y: [] }; for (var d in this.options.modifiers) {
        if (!this.options.modifiers[d]) {
            continue;
        } if (this.options.style) { this.value.now[d] = this.element.getStyle(this.options.modifiers[d]).toInt(); } else {
            this.value.now[d] = this.element[this.options.modifiers[d]];
        } if (this.options.invert) { this.value.now[d] *= -1; } this.mouse.pos[d] = c.page[d] - this.value.now[d]; if (a && a[d]) {
            for (var b = 2; b--; b) {
                if ($chk(a[d][b])) {
                    this.limit[d][b] = $lambda(a[d][b])();
                } 
            } 
        } 
    } if ($type(this.options.grid) == "number") { this.options.grid = { x: this.options.grid, y: this.options.grid }; } this.document.addEvents({ mousemove: this.bound.check, mouseup: this.bound.cancel });
    this.document.addEvent(this.selection, this.bound.eventStop);
}, check: function(a) {
    if (this.options.preventDefault) { a.preventDefault(); } var b = Math.round(Math.sqrt(Math.pow(a.page.x - this.mouse.start.x, 2) + Math.pow(a.page.y - this.mouse.start.y, 2)));
    if (b > this.options.snap) {
        this.cancel(); this.document.addEvents({ mousemove: this.bound.drag, mouseup: this.bound.stop }); this.fireEvent("start", [this.element, a]).fireEvent("snap", this.element);
    } 
}, drag: function(a) {
    if (this.options.preventDefault) { a.preventDefault(); } this.mouse.now = a.page; for (var b in this.options.modifiers) {
        if (!this.options.modifiers[b]) {
            continue;
        } this.value.now[b] = this.mouse.now[b] - this.mouse.pos[b]; if (this.options.invert) { this.value.now[b] *= -1; } if (this.options.limit && this.limit[b]) {
            if ($chk(this.limit[b][1]) && (this.value.now[b] > this.limit[b][1])) {
                this.value.now[b] = this.limit[b][1];
            } else { if ($chk(this.limit[b][0]) && (this.value.now[b] < this.limit[b][0])) { this.value.now[b] = this.limit[b][0]; } } 
        } if (this.options.grid[b]) {
            this.value.now[b] -= ((this.value.now[b] - (this.limit[b][0] || 0)) % this.options.grid[b]);
        } if (this.options.style) { this.element.setStyle(this.options.modifiers[b], this.value.now[b] + this.options.unit); } else {
            this.element[this.options.modifiers[b]] = this.value.now[b];
        } 
    } this.fireEvent("drag", [this.element, a]);
}, cancel: function(a) {
    this.document.removeEvent("mousemove", this.bound.check); this.document.removeEvent("mouseup", this.bound.cancel);
    if (a) { this.document.removeEvent(this.selection, this.bound.eventStop); this.fireEvent("cancel", this.element); } 
}, stop: function(a) {
    this.document.removeEvent(this.selection, this.bound.eventStop);
    this.document.removeEvent("mousemove", this.bound.drag); this.document.removeEvent("mouseup", this.bound.stop); if (a) {
        this.fireEvent("complete", [this.element, a]);
    } 
} 
}); Element.implement({ makeResizable: function(a) {
    var b = new Drag(this, $merge({ modifiers: { x: "width", y: "height"} }, a)); this.store("resizer", b); return b.addEvent("drag", function() {
        this.fireEvent("resize", b);
    } .bind(this));
} 
}); Drag.Move = new Class({ Extends: Drag, options: { droppables: [], container: false, precalculate: false, includeMargins: true, checkDroppables: true }, initialize: function(b, a) {
    this.parent(b, a);
    b = this.element; this.droppables = $$(this.options.droppables); this.container = document.id(this.options.container); if (this.container && $type(this.container) != "element") {
        this.container = document.id(this.container.getDocument().body);
    } var c = b.getStyles("left", "top", "position"); if (c.left == "auto" || c.top == "auto") { b.setPosition(b.getPosition(b.getOffsetParent())); } if (c.position == "static") {
        b.setStyle("position", "absolute");
    } this.addEvent("start", this.checkDroppables, true); this.overed = null;
}, start: function(a) {
    if (this.container) { this.options.limit = this.calculateLimit(); } if (this.options.precalculate) {
        this.positions = this.droppables.map(function(b) {
            return b.getCoordinates();
        });
    } this.parent(a);
}, calculateLimit: function() {
    var d = this.element.getOffsetParent(), g = this.container.getCoordinates(d), f = {}, c = {}, b = {}, i = {}, k = {}; ["top", "right", "bottom", "left"].each(function(o) {
        f[o] = this.container.getStyle("border-" + o).toInt();
        b[o] = this.element.getStyle("border-" + o).toInt(); c[o] = this.element.getStyle("margin-" + o).toInt(); i[o] = this.container.getStyle("margin-" + o).toInt(); k[o] = d.getStyle("padding-" + o).toInt();
    }, this); var e = this.element.offsetWidth + c.left + c.right, n = this.element.offsetHeight + c.top + c.bottom, h = 0, j = 0, m = g.right - f.right - e, a = g.bottom - f.bottom - n; if (this.options.includeMargins) {
        h += c.left;
        j += c.top;
    } else { m += c.right; a += c.bottom; } if (this.element.getStyle("position") == "relative") {
        var l = this.element.getCoordinates(d); l.left -= this.element.getStyle("left").toInt();
        l.top -= this.element.getStyle("top").toInt(); h += f.left - l.left; j += f.top - l.top; m += c.left - l.left; a += c.top - l.top; if (this.container != d) {
            h += i.left + k.left; j += (Browser.Engine.trident4 ? 0 : i.top) + k.top;
        } 
    } else { h -= c.left; j -= c.top; if (this.container == d) { m -= f.left; a -= f.top; } else { h += g.left + f.left; j += g.top + f.top; } } return { x: [h, m], y: [j, a] };
}, checkAgainst: function(c, b) {
    c = (this.positions) ? this.positions[b] : c.getCoordinates();
    var a = this.mouse.now; return (a.x > c.left && a.x < c.right && a.y < c.bottom && a.y > c.top);
}, checkDroppables: function() {
    var a = this.droppables.filter(this.checkAgainst, this).getLast();
    if (this.overed != a) { if (this.overed) { this.fireEvent("leave", [this.element, this.overed]); } if (a) { this.fireEvent("enter", [this.element, a]); } this.overed = a; } 
}, drag: function(a) {
    this.parent(a);
    if (this.options.checkDroppables && this.droppables.length) { this.checkDroppables(); } 
}, stop: function(a) {
    this.checkDroppables(); this.fireEvent("drop", [this.element, this.overed, a]);
    this.overed = null; return this.parent(a);
} 
}); Element.implement({ makeDraggable: function(a) { var b = new Drag.Move(this, a); this.store("dragger", b); return b; } });
var Sortables = new Class({ Implements: [Events, Options], options: { snap: 4, opacity: 1, clone: false, revert: false, handle: false, constrain: false }, initialize: function(a, b) {
    this.setOptions(b);
    this.elements = []; this.lists = []; this.idle = true; this.addLists($$(document.id(a) || a)); if (!this.options.clone) { this.options.revert = false; } if (this.options.revert) {
        this.effect = new Fx.Morph(null, $merge({ duration: 250, link: "cancel" }, this.options.revert));
    } 
}, attach: function() { this.addLists(this.lists); return this; }, detach: function() { this.lists = this.removeLists(this.lists); return this; }, addItems: function() {
    Array.flatten(arguments).each(function(a) {
        this.elements.push(a);
        var b = a.retrieve("sortables:start", this.start.bindWithEvent(this, a)); (this.options.handle ? a.getElement(this.options.handle) || a : a).addEvent("mousedown", b);
    }, this); return this;
}, addLists: function() {
    Array.flatten(arguments).each(function(a) { this.lists.push(a); this.addItems(a.getChildren()); }, this); return this;
}, removeItems: function() {
    return $$(Array.flatten(arguments).map(function(a) {
        this.elements.erase(a); var b = a.retrieve("sortables:start"); (this.options.handle ? a.getElement(this.options.handle) || a : a).removeEvent("mousedown", b);
        return a;
    }, this));
}, removeLists: function() {
    return $$(Array.flatten(arguments).map(function(a) {
        this.lists.erase(a); this.removeItems(a.getChildren()); return a;
    }, this));
}, getClone: function(b, a) {
    if (!this.options.clone) { return new Element("div").inject(document.body); } if ($type(this.options.clone) == "function") {
        return this.options.clone.call(this, b, a, this.list);
    } var c = a.clone(true).setStyles({ margin: "0px", position: "absolute", visibility: "hidden", width: a.getStyle("width") }); if (c.get("html").test("radio")) {
        c.getElements("input[type=radio]").each(function(d, e) {
            d.set("name", "clone_" + e);
        });
    } return c.inject(this.list).setPosition(a.getPosition(a.getOffsetParent()));
}, getDroppables: function() {
    var a = this.list.getChildren(); if (!this.options.constrain) {
        a = this.lists.concat(a).erase(this.list);
    } return a.erase(this.clone).erase(this.element);
}, insert: function(c, b) {
    var a = "inside"; if (this.lists.contains(b)) {
        this.list = b; this.drag.droppables = this.getDroppables();
    } else { a = this.element.getAllPrevious().contains(b) ? "before" : "after"; } this.element.inject(b, a); this.fireEvent("sort", [this.element, this.clone]);
}, start: function(b, a) {
    if (!this.idle) {
        return;
    } this.idle = false; this.element = a; this.opacity = a.get("opacity"); this.list = a.getParent(); this.clone = this.getClone(b, a); this.drag = new Drag.Move(this.clone, { snap: this.options.snap, container: this.options.constrain && this.element.getParent(), droppables: this.getDroppables(), onSnap: function() {
        b.stop();
        this.clone.setStyle("visibility", "visible"); this.element.set("opacity", this.options.opacity || 0); this.fireEvent("start", [this.element, this.clone]);
    } .bind(this), onEnter: this.insert.bind(this), onCancel: this.reset.bind(this), onComplete: this.end.bind(this)
    });
    this.clone.inject(this.element, "before"); this.drag.start(b);
}, end: function() {
    this.drag.detach(); this.element.set("opacity", this.opacity); if (this.effect) {
        var a = this.element.getStyles("width", "height");
        var b = this.clone.computePosition(this.element.getPosition(this.clone.offsetParent)); this.effect.element = this.clone; this.effect.start({ top: b.top, left: b.left, width: a.width, height: a.height, opacity: 0.25 }).chain(this.reset.bind(this));
    } else { this.reset(); } 
}, reset: function() { this.idle = true; this.clone.destroy(); this.fireEvent("complete", this.element); }, serialize: function() {
    var c = Array.link(arguments, { modifier: Function.type, index: $defined });
    var b = this.lists.map(function(d) { return d.getChildren().map(c.modifier || function(e) { return e.get("id"); }, this); }, this); var a = c.index; if (this.lists.length == 1) {
        a = 0;
    } return $chk(a) && a >= 0 && a < this.lists.length ? b[a] : b;
} 
});
