accounts2/fas/fas/static/javascript DragAndDrop.js, NONE, 1.1 MochiKit.js, NONE, 1.1 New.js, NONE, 1.1 Sortable.js, NONE, 1.1 color.js, NONE, 1.1 draggable.js, NONE, 1.1 signal.js, NONE, 1.1 sortable_tables.js, NONE, 1.1 style.js, NONE, 1.1

Michael Patrick McGrath (mmcgrath) fedora-extras-commits at redhat.com
Thu Apr 26 14:28:22 UTC 2007


Author: mmcgrath

Update of /cvs/fedora/accounts2/fas/fas/static/javascript
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv18003/fas/static/javascript

Added Files:
	DragAndDrop.js MochiKit.js New.js Sortable.js color.js 
	draggable.js signal.js sortable_tables.js style.js 
Log Message:
UI changes


--- NEW FILE DragAndDrop.js ---
/***
MochiKit.DragAndDrop 1.4

See <http://mochikit.com/> for documentation, downloads, license, etc.

Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
    Mochi-ized By Thomas Herve (_firstname_ at nimail.org)

***/

if (typeof(dojo) != 'undefined') {
    dojo.provide('MochiKit.DragAndDrop');
    dojo.require('MochiKit.Base');
    dojo.require('MochiKit.DOM');
    dojo.require('MochiKit.Iter');
    dojo.require('MochiKit.Visual');
    dojo.require('MochiKit.Signal');
}

if (typeof(JSAN) != 'undefined') {
    JSAN.use("MochiKit.Base", []);
    JSAN.use("MochiKit.DOM", []);
    JSAN.use("MochiKit.Visual", []);
    JSAN.use("MochiKit.Iter", []);
    JSAN.use("MochiKit.Signal", []);
}

try {
    if (typeof(MochiKit.Base) == 'undefined' ||
        typeof(MochiKit.DOM) == 'undefined' ||
        typeof(MochiKit.Visual) == 'undefined' ||
        typeof(MochiKit.Signal) == 'undefined' ||
        typeof(MochiKit.Iter) == 'undefined') {
        throw "";
    }
} catch (e) {
    throw "MochiKit.DragAndDrop depends on MochiKit.Base, MochiKit.DOM, MochiKit.Visual, MochiKit.Signal and MochiKit.Iter!";
}

if (typeof(MochiKit.DragAndDrop) == 'undefined') {
    MochiKit.DragAndDrop = {};
}

MochiKit.DragAndDrop.NAME = 'MochiKit.DragAndDrop';
MochiKit.DragAndDrop.VERSION = '1.4';

MochiKit.DragAndDrop.__repr__ = function () {
    return '[' + this.NAME + ' ' + this.VERSION + ']';
};

MochiKit.DragAndDrop.toString = function () {
    return this.__repr__();
};

MochiKit.DragAndDrop.EXPORT = [
    "Droppable",
    "Draggable"
];

MochiKit.DragAndDrop.EXPORT_OK = [
    "Droppables",
    "Draggables"
];

MochiKit.DragAndDrop.Droppables = {
    /***

    Manage all droppables. Shouldn't be used, use the Droppable object instead.

    ***/
    drops: [],

    remove: function (element) {
        this.drops = MochiKit.Base.filter(function (d) {
            return d.element != MochiKit.DOM.getElement(element)
        }, this.drops);
    },

    register: function (drop) {
        this.drops.push(drop);
    },

    unregister: function (drop) {
        this.drops = MochiKit.Base.filter(function (d) {
            return d != drop;
        }, this.drops);
    },

    prepare: function (element) {
        MochiKit.Base.map(function (drop) {
            if (drop.isAccepted(element)) {
                if (drop.options.activeclass) {
                    MochiKit.DOM.addElementClass(drop.element,
                                                 drop.options.activeclass);
                }
                drop.options.onactive(drop.element, element);
            }
        }, this.drops);
    },

    findDeepestChild: function (drops) {
        deepest = drops[0];

        for (i = 1; i < drops.length; ++i) {
            if (MochiKit.DOM.isParent(drops[i].element, deepest.element)) {
                deepest = drops[i];
            }
        }
        return deepest;
    },

    show: function (point, element) {
        if (!this.drops.length) {
            return;
        }
        var affected = [];

        if (this.last_active) {
            this.last_active.deactivate();
        }
        MochiKit.Iter.forEach(this.drops, function (drop) {
            if (drop.isAffected(point, element)) {
                affected.push(drop);
            }
        });
        if (affected.length > 0) {
            drop = this.findDeepestChild(affected);
            MochiKit.Position.within(drop.element, point.page.x, point.page.y);
            drop.options.onhover(element, drop.element,
                MochiKit.Position.overlap(drop.options.overlap, drop.element));
            drop.activate();
        }
    },

    fire: function (event, element) {
        if (!this.last_active) {
            return;
        }
        MochiKit.Position.prepare();

        if (this.last_active.isAffected(event.mouse(), element)) {
            this.last_active.options.ondrop(element,
               this.last_active.element, event);
        }
    },

    reset: function (element) {
        MochiKit.Base.map(function (drop) {
            if (drop.options.activeclass) {
                MochiKit.DOM.removeElementClass(drop.element,
                                                drop.options.activeclass);
            }
            drop.options.ondesactive(drop.element, element);
        }, this.drops);
        if (this.last_active) {
            this.last_active.deactivate();
        }
    }
};

MochiKit.DragAndDrop.Droppable = function (element, options) {
    this.__init__(element, options);
};

MochiKit.DragAndDrop.Droppable.prototype = {
    /***

    A droppable object. Simple use is to create giving an element:

        new MochiKit.DragAndDrop.Droppable('myelement');

    Generally you'll want to define the 'ondrop' function and maybe the
    'accept' option to filter draggables.

    ***/
    __class__: MochiKit.DragAndDrop.Droppable,

    __init__: function (element, /* optional */options) {
        var d = MochiKit.DOM;
        var b = MochiKit.Base;
        this.element = d.getElement(element);
        this.options = b.update({
            greedy: true,
            hoverclass: null,
            activeclass: null,
            hoverfunc: b.noop,
            accept: null,
            onactive: b.noop,
            ondesactive: b.noop,
            onhover: b.noop,
            ondrop: b.noop,
            containment: [],
            tree: false
        }, options || {});

        // cache containers
        this.options._containers = [];
        b.map(MochiKit.Base.bind(function (c) {
            this.options._containers.push(d.getElement(c));
        }, this), this.options.containment);

        d.makePositioned(this.element); // fix IE

        MochiKit.DragAndDrop.Droppables.register(this);
    },

    isContained: function (element) {
        if (this._containers) {
            var containmentNode;
            if (this.options.tree) {
                containmentNode = element.treeNode;
            } else {
                containmentNode = element.parentNode;
            }
            return MochiKit.Iter.some(this._containers, function (c) {
                return containmentNode == c;
            });
        } else {
            return true;
        }
    },

    isAccepted: function (element) {
        return ((!this.options.accept) || MochiKit.Iter.some(
          this.options.accept, function (c) {
            return MochiKit.DOM.hasElementClass(element, c);
        }));
    },

    isAffected: function (point, element) {
        return ((this.element != element) &&
                this.isContained(element) &&
                this.isAccepted(element) &&
                MochiKit.Position.within(this.element, point.page.x,
                                                       point.page.y));
    },

    deactivate: function () {
        /***

        A droppable is deactivate when a draggable has been over it and left.

        ***/
        if (this.options.hoverclass) {
            MochiKit.DOM.removeElementClass(this.element,
                                            this.options.hoverclass);
        }
        this.options.hoverfunc(this.element, false);
        MochiKit.DragAndDrop.Droppables.last_active = null;
    },

    activate: function () {
        /***

        A droppable is active when a draggable is over it.

        ***/
        if (this.options.hoverclass) {
            MochiKit.DOM.addElementClass(this.element, this.options.hoverclass);
        }
        this.options.hoverfunc(this.element, true);
        MochiKit.DragAndDrop.Droppables.last_active = this;
    },

    destroy: function () {
        /***

        Delete this droppable.

        ***/
        MochiKit.DragAndDrop.Droppables.unregister(this);
    },

    repr: function () {
        return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
    }
};

MochiKit.DragAndDrop.Draggables = {
    /***

    Manage draggables elements. Not intended to direct use.

    ***/
    drags: [],

    observers: [],

    register: function (draggable) {
        if (this.drags.length === 0) {
            var conn = MochiKit.Signal.connect;
            this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag);
            this.eventMouseMove = conn(document, 'onmousemove', this,
                                       this.updateDrag);
            this.eventKeypress = conn(document, 'onkeypress', this,
                                      this.keyPress);
        }
        this.drags.push(draggable);
    },

    unregister: function (draggable) {
        this.drags = MochiKit.Base.filter(function (d) {
            return d != draggable;
        }, this.drags);
        if (this.drags.length === 0) {
            var disc = MochiKit.Signal.disconnect
            disc(this.eventMouseUp);
            disc(this.eventMouseMove);
            disc(this.eventKeypress);
        }
    },

    activate: function (draggable) {
        // allows keypress events if window is not currently focused
        // fails for Safari
        window.focus();
        this.activeDraggable = draggable;
    },

    deactivate: function () {
        this.activeDraggable = null;
    },

    updateDrag: function (event) {
        if (!this.activeDraggable) {
            return;
        }
        var pointer = event.mouse();
        // Mozilla-based browsers fire successive mousemove events with
        // the same coordinates, prevent needless redrawing (moz bug?)
        if (this._lastPointer && (MochiKit.Base.repr(this._lastPointer.page) ==
                                  MochiKit.Base.repr(pointer.page))) {
            return;
        }
        this._lastPointer = pointer;
        this.activeDraggable.updateDrag(event, pointer);
    },

    endDrag: function (event) {
        if (!this.activeDraggable) {
            return;
        }
        this._lastPointer = null;
        this.activeDraggable.endDrag(event);
        this.activeDraggable = null;
    },

    keyPress: function (event) {
        if (this.activeDraggable) {
            this.activeDraggable.keyPress(event);
        }
    },

    addObserver: function (observer) {
        this.observers.push(observer);
        this._cacheObserverCallbacks();
    },

    removeObserver: function (element) {
        // element instead of observer fixes mem leaks
        this.observers = MochiKit.Base.filter(function (o) {
            return o.element != element;
        }, this.observers);
        this._cacheObserverCallbacks();
    },

    notify: function (eventName, draggable, event) {
        // 'onStart', 'onEnd', 'onDrag'
        if (this[eventName + 'Count'] > 0) {
            MochiKit.Base.map(function (o) {
                if (o[eventName]) {
                    o[eventName](eventName, draggable, event);
                }
            }, this.observers);
        }
    },

    _cacheObserverCallbacks: function () {
        var b = MochiKit.Base;
        var self = MochiKit.DragAndDrop.Draggables;
        b.map(function (eventName) {
            self[eventName + 'Count'] = b.filter(function (o) {
                return o[eventName];
            }, self.observers).length;
        }, ['onStart', 'onEnd', 'onDrag']);
    }
};

MochiKit.DragAndDrop.Draggable = function (element, options) {
    this.__init__(element, options);
};

MochiKit.DragAndDrop.Draggable.prototype = {
    /***

    A draggable object. Simple instantiate :

        new MochiKit.DragAndDrop.Draggable('myelement');

    ***/
    __class__ : MochiKit.DragAndDrop.Draggable,

    __init__: function (element, /* optional */options) {
        var v = MochiKit.Visual;
        var b = MochiKit.Base;
        options = b.update({
            handle: false,
            starteffect: function (innerelement) {
                this._savedOpacity = MochiKit.DOM.getOpacity(innerelement) || 1.0;
                new v.Opacity(innerelement, {duration:0.2, from:this._savedOpacity, to:0.7});
            },
            reverteffect: function (innerelement, top_offset, left_offset) {
                var dur = Math.sqrt(Math.abs(top_offset^2) +
                          Math.abs(left_offset^2))*0.02;
                return new v.Move(innerelement,
                            {x: -left_offset, y: -top_offset, duration: dur});
            },
            endeffect: function (innerelement) {
                new v.Opacity(innerelement, {duration:0.2, from:0.7, to:this._savedOpacity});
            },
            onchange: b.noop,
            zindex: 1000,
            revert: false,
            scroll: false,
            scrollSensitivity: 20,
            scrollSpeed: 15,
            // false, or xy or [x, y] or function (x, y){return [x, y];}
            snap: false
        }, options || {});

        var d = MochiKit.DOM;
        this.element = d.getElement(element);

        if (options.handle && (typeof(options.handle) == 'string')) {
            this.handle = d.getFirstElementByTagAndClassName(null,
                                       options.handle, this.element);
        }
        if (!this.handle) {
            this.handle = d.getElement(options.handle);
        }
        if (!this.handle) {
            this.handle = this.element;
        }

        if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
            options.scroll = d.getElement(options.scroll);
        }

        d.makePositioned(this.element);  // fix IE

        this.delta = this.currentDelta();
        this.options = options;
        this.dragging = false;

        this.eventMouseDown = MochiKit.Signal.connect(this.handle,
                              'onmousedown', this, this.initDrag);
        MochiKit.DragAndDrop.Draggables.register(this);
    },

    destroy: function () {
        MochiKit.Signal.disconnect(this.eventMouseDown);
        MochiKit.DragAndDrop.Draggables.unregister(this);
    },

    currentDelta: function () {
        var s = MochiKit.DOM.getStyle;
        return [
          parseInt(s(this.element, 'left') || '0'),
          parseInt(s(this.element, 'top') || '0')];
    },

    initDrag: function (event) {
        if (!event.mouse().button.left) {
            return;
        }
        // abort on form elements, fixes a Firefox issue
        var src = event.target;
        if (src.tagName && (
            src.tagName == 'INPUT' || src.tagName == 'SELECT' ||
            src.tagName == 'OPTION' || src.tagName == 'BUTTON' ||
            src.tagName == 'TEXTAREA')) {
            return;
        }

        if (this._revert) {
            this._revert.cancel();
            this._revert = null;
        }

        var pointer = event.mouse();
        var pos = MochiKit.Position.cumulativeOffset(this.element);
        this.offset = [pointer.page.x - pos.x, pointer.page.y - pos.y]

        MochiKit.DragAndDrop.Draggables.activate(this);
        event.stop();
    },

    startDrag: function (event) {
        this.dragging = true;
        if (this.options.selectclass) {
            MochiKit.DOM.addElementClass(this.element,
                                         this.options.selectclass);
        }
        if (this.options.zindex) {
            this.originalZ = parseInt(MochiKit.DOM.getStyle(this.element,
                                      'z-index') || '0');
            this.element.style.zIndex = this.options.zindex;
        }

        if (this.options.ghosting) {
            this._clone = this.element.cloneNode(true);
            this.ghostPosition = MochiKit.Position.absolutize(this.element);
            this.element.parentNode.insertBefore(this._clone, this.element);
        }

        if (this.options.scroll) {
            if (this.options.scroll == window) {
                var where = this._getWindowScroll(this.options.scroll);
                this.originalScrollLeft = where.left;
                this.originalScrollTop = where.top;
            } else {
                this.originalScrollLeft = this.options.scroll.scrollLeft;
                this.originalScrollTop = this.options.scroll.scrollTop;
            }
        }

        MochiKit.DragAndDrop.Droppables.prepare(this.element);
        MochiKit.DragAndDrop.Draggables.notify('onStart', this, event);
        if (this.options.starteffect) {
            this.options.starteffect(this.element);
        }
    },

    updateDrag: function (event, pointer) {
        if (!this.dragging) {
            this.startDrag(event);
        }
        MochiKit.Position.prepare();
        MochiKit.DragAndDrop.Droppables.show(pointer, this.element);
        MochiKit.DragAndDrop.Draggables.notify('onDrag', this, event);
        this.draw(pointer);
        this.options.onchange(this);

        if (this.options.scroll) {
            this.stopScrolling();
            var p, q;
            if (this.options.scroll == window) {
                var s = this._getWindowScroll(this.options.scroll);
                p = new MochiKit.Style.Coordinates(s.left, s.top);
                q = new MochiKit.Style.Coordinates(s.left + s.width,
                                                   s.top + s.height);
            } else {
                p = MochiKit.Position.page(this.options.scroll);
                p.x += this.options.scroll.scrollLeft;
                p.y += this.options.scroll.scrollTop;
                q = new MochiKit.Style.Coordinates(p.x + this.options.scroll.offsetWidth,
                                                   p.y + this.options.scroll.offsetHeight);
            }
            var speed = [0, 0];
            if (pointer.page.x > (q.x - this.options.scrollSensitivity)) {
                speed[0] = pointer.page.x - (q.x - this.options.scrollSensitivity);
            } else if (pointer.page.x < (p.x + this.options.scrollSensitivity)) {
                speed[0] = pointer.page.x - (p.x + this.options.scrollSensitivity);
            }
            if (pointer.page.y > (q.y - this.options.scrollSensitivity)) {
                speed[1] = pointer.page.y - (q.y - this.options.scrollSensitivity);
            } else if (pointer.page.y < (p.y + this.options.scrollSensitivity)) {
                speed[1] = pointer.page.y - (p.y + this.options.scrollSensitivity);
            }
            this.startScrolling(speed);
        }

        // fix AppleWebKit rendering
        if (MochiKit.Base.isSafari()) {
            window.scrollBy(0, 0);
        }
        event.stop();
    },

    finishDrag: function (event, success) {
        var dr = MochiKit.DragAndDrop;
        this.dragging = false;
        if (this.options.selectclass) {
            MochiKit.DOM.removeElementClass(this.element,
                                            this.options.selectclass);
        }

        if (this.options.ghosting) {
            // XXX: from a user point of view, it would be better to remove
            // the node only *after* the MochiKit.Visual.Move end when used
            // with revert.
            MochiKit.Position.relativize(this.element, this.ghostPosition);
            MochiKit.DOM.removeElement(this._clone);
            this._clone = null;
        }

        if (success) {
            dr.Droppables.fire(event, this.element);
        }
        dr.Draggables.notify('onEnd', this, event);

        var revert = this.options.revert;
        if (revert && typeof(revert) == 'function') {
            revert = revert(this.element);
        }

        var d = this.currentDelta();
        if (revert && this.options.reverteffect) {
            this._revert = this.options.reverteffect(this.element,
                d[1] - this.delta[1], d[0] - this.delta[0]);
        } else {
            this.delta = d;
        }

        if (this.options.zindex) {
            this.element.style.zIndex = this.originalZ;
        }

        if (this.options.endeffect) {
            this.options.endeffect(this.element);
        }

        dr.Draggables.deactivate();
        dr.Droppables.reset(this.element);
    },

    keyPress: function (event) {
        if (event.keyString != "KEY_ESCAPE") {
            return;
        }
        this.finishDrag(event, false);
        event.stop();
    },

    endDrag: function (event) {
        if (!this.dragging) {
            return;
        }
        this.stopScrolling();
        this.finishDrag(event, true);
        event.stop();
    },

    draw: function (point) {
        var pos = MochiKit.Position.cumulativeOffset(this.element);
        var d = this.currentDelta();
        pos.x -= d[0];
        pos.y -= d[1];

        if (this.options.scroll && !this.options.scroll.scrollTo) {
            pos.x -= this.options.scroll.scrollLeft - this.originalScrollLeft;
            pos.y -= this.options.scroll.scrollTop - this.originalScrollTop;
        }

        var p = [point.page.x - pos.x - this.offset[0],
                 point.page.y - pos.y - this.offset[1]]

        if (this.options.snap) {
            if (typeof(this.options.snap) == 'function') {
                p = this.options.snap(p[0], p[1]);
            } else {
                if (this.options.snap instanceof Array) {
                    var i = -1;
                    p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
                            i += 1;
                            return Math.round(v/this.options.snap[i]) *
                                   this.options.snap[i]
                        }, this), p)
                } else {
                    p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
                        return Math.round(v/this.options.snap) *
                               this.options.snap
                        }, this), p)
                }
            }
        }
        var style = this.element.style;
        if ((!this.options.constraint) ||
            (this.options.constraint == 'horizontal')) {
            style.left = p[0] + 'px';
        }
        if ((!this.options.constraint) ||
            (this.options.constraint == 'vertical')) {
            style.top = p[1] + 'px';
        }
        if (style.visibility == 'hidden') {
            style.visibility = '';  // fix gecko rendering
        }
    },

    stopScrolling: function () {
        if (this.scrollInterval) {
            clearInterval(this.scrollInterval);
            this.scrollInterval = null;
        }
    },

    startScrolling: function (speed) {
        if (!speed[0] || !speed[1]) {
            return;
        }
        this.scrollSpeed = [speed[0] * this.options.scrollSpeed,
                            speed[1] * this.options.scrollSpeed];
        this.lastScrolled = new Date();
        this.scrollInterval = setInterval(MochiKit.Base.bind(this.scroll, this), 10);
    },

    scroll: function () {
        var current = new Date();
        var delta = current - this.lastScrolled;
        this.lastScrolled = current;

        if (this.options.scroll == window) {
            var s = this._getWindowScroll(this.options.scroll);
            if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
                var d = delta / 1000;
                this.options.scroll.scrollTo(s.left + d * this.scrollSpeed[0],
                                             s.top + d * this.scrollSpeed[1]);
            }
        } else {
            this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
            this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
        }

        var d = MochiKit.DragAndDrop;

        MochiKit.Position.prepare();
        d.Droppables.show(d.Draggables._lastPointer, this.element);
        this.draw(d.Draggables._lastPointer);
        this.options.onchange(this);
    },

    _getWindowScroll: function (w) {
        var T, L, W, H;
        with (w.document) {
            if (w.document.documentElement && documentElement.scrollTop) {
                T = documentElement.scrollTop;
                L = documentElement.scrollLeft;
            } else if (w.document.body) {
                T = body.scrollTop;
                L = body.scrollLeft;
            }
            if (w.innerWidth) {
                W = w.innerWidth;
                H = w.innerHeight;
            } else if (w.document.documentElement && documentElement.clientWidth) {
                W = documentElement.clientWidth;
                H = documentElement.clientHeight;
            } else {
                W = body.offsetWidth;
                H = body.offsetHeight
            }
        }
        return {top: T, left: L, width: W, height: H};
    },

    repr: function () {
        return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
    }
};

MochiKit.DragAndDrop.__new__ = function () {
    MochiKit.Base.nameFunctions(this);

    this.EXPORT_TAGS = {
        ":common": this.EXPORT,
        ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK)
    };
};

MochiKit.DragAndDrop.__new__();

MochiKit.Base._exportSymbols(this, MochiKit.DragAndDrop);



--- NEW FILE MochiKit.js ---
/***

    MochiKit.MochiKit 1.4 : PACKED VERSION

    THIS FILE IS AUTOMATICALLY GENERATED.  If creating patches, please
    diff against the source tree, not this file.

    See <http://mochikit.com/> for documentation, downloads, license, etc.

    (c) 2005 Bob Ippolito.  All rights Reserved.

***/

if(typeof (dojo)!="undefined"){
dojo.provide("MochiKit.Base");
}
if(typeof (MochiKit)=="undefined"){
MochiKit={};
}
if(typeof (MochiKit.Base)=="undefined"){
MochiKit.Base={};
}
MochiKit.Base.VERSION="1.4";
MochiKit.Base.NAME="MochiKit.Base";
MochiKit.Base.update=function(_1,_2){
if(_1===null){
_1={};
}
for(var i=1;i<arguments.length;i++){
var o=arguments[i];
if(typeof (o)!="undefined"&&o!==null){
for(var k in o){
_1[k]=o[k];
}
}
}
return _1;
};
MochiKit.Base.update(MochiKit.Base,{__repr__:function(){
return "["+this.NAME+" "+this.VERSION+"]";
},toString:function(){
return this.__repr__();
},camelize:function(_6){
var _7=_6.split("-");
var cc=_7[0];
for(var i=1;i<_7.length;i++){
cc+=_7[i].charAt(0).toUpperCase()+_7[i].substring(1);
}
return cc;
},counter:function(n){
if(arguments.length===0){
n=1;
}
return function(){
return n++;
};
},clone:function(obj){
var me=arguments.callee;
if(arguments.length==1){
me.prototype=obj;
return new me();
}
},_flattenArray:function(res,lst){
for(var i=0;i<lst.length;i++){
var o=lst[i];
if(o instanceof Array){
arguments.callee(res,o);
}else{
res.push(o);
}
}
return res;
},flattenArray:function(lst){
return MochiKit.Base._flattenArray([],lst);
},flattenArguments:function(lst){
var res=[];
var m=MochiKit.Base;
var _15=m.extend(null,arguments);
while(_15.length){
var o=_15.shift();
if(o&&typeof (o)=="object"&&typeof (o.length)=="number"){
for(var i=o.length-1;i>=0;i--){
_15.unshift(o[i]);
}
}else{
res.push(o);
}
}
return res;
},extend:function(_16,obj,_17){
if(!_17){
_17=0;
}
if(obj){
var l=obj.length;
if(typeof (l)!="number"){
if(typeof (MochiKit.Iter)!="undefined"){
obj=MochiKit.Iter.list(obj);
l=obj.length;
}else{
throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
}
}
if(!_16){
_16=[];
}
for(var i=_17;i<l;i++){
_16.push(obj[i]);
}
}
return _16;
},updatetree:function(_19,obj){
if(_19===null){
_19={};
}
for(var i=1;i<arguments.length;i++){
var o=arguments[i];
if(typeof (o)!="undefined"&&o!==null){
for(var k in o){
var v=o[k];
if(typeof (_19[k])=="object"&&typeof (v)=="object"){
arguments.callee(_19[k],v);
}else{
_19[k]=v;
}
}
}
}
return _19;
},setdefault:function(_21,obj){
if(_21===null){
_21={};
}
for(var i=1;i<arguments.length;i++){
var o=arguments[i];
for(var k in o){
if(!(k in _21)){
_21[k]=o[k];
}
}
}
return _21;
},keys:function(obj){
var _22=[];
for(var _23 in obj){
_22.push(_23);
}
return _22;
},items:function(obj){
var _24=[];
var e;
for(var _26 in obj){
var v;
try{
v=obj[_26];
}
catch(e){
continue;
}
_24.push([_26,v]);
}
return _24;
},_newNamedError:function(_27,_28,_29){
_29.prototype=new MochiKit.Base.NamedError(_27.NAME+"."+_28);
_27[_28]=_29;
},operator:{truth:function(a){
return !!a;
},lognot:function(a){
return !a;
},identity:function(a){
return a;
},not:function(a){
return ~a;
},neg:function(a){
return -a;
},add:function(a,b){
return a+b;
},sub:function(a,b){
return a-b;
},div:function(a,b){
return a/b;
},mod:function(a,b){
return a%b;
},mul:function(a,b){
return a*b;
},and:function(a,b){
return a&b;
},or:function(a,b){
return a|b;
},xor:function(a,b){
return a^b;
},lshift:function(a,b){
return a<<b;
},rshift:function(a,b){
return a>>b;
},zrshift:function(a,b){
return a>>>b;
},eq:function(a,b){
return a==b;
[...5374 lines suppressed...]
d.undoPositioned(_770.effects[0].element);
d.setStyle(_770.effects[0].element,_764);
}},_763||{});
return new v.Move(_762,{x:_766,y:initialMoveY,duration:0.01,beforeSetupInternal:function(_771){
MochiKit.Style.hideElement(_771.element);
d.makeClipping(_771.element);
d.makePositioned(_771.element);
},afterFinishInternal:function(_772){
new v.Parallel([new v.Opacity(_772.element,{sync:true,to:1,from:0,transition:_763.opacityTransition}),new v.Move(_772.element,{x:_767,y:moveY,sync:true,transition:_763.moveTransition}),new v.Scale(_772.element,100,{scaleMode:{originalHeight:dims.h,originalWidth:dims.w},sync:true,scaleFrom:MochiKit.Base.isOpera()?1:0,transition:_763.scaleTransition,restoreAfterFinish:true})],_768);
}});
};
MochiKit.Visual.shrink=function(_773,_774){
var d=MochiKit.DOM;
var v=MochiKit.Visual;
_773=d.getElement(_773);
_774=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.none},_774||{});
var _775={top:_773.style.top,left:_773.style.left,height:_773.style.height,width:_773.style.width,opacity:d.getInlineOpacity(_773)};
var dims=MochiKit.Style.getElementDimensions(_773);
var _776,moveY;
switch(_774.direction){
case "top-left":
_776=moveY=0;
break;
case "top-right":
_776=dims.w;
moveY=0;
break;
case "bottom-left":
_776=0;
moveY=dims.h;
break;
case "bottom-right":
_776=dims.w;
moveY=dims.h;
break;
case "center":
_776=dims.w/2;
moveY=dims.h/2;
break;
}
var _777=MochiKit.Base.update({beforeStartInternal:function(_778){
d.makePositioned(_778.effects[0].element);
d.makeClipping(_778.effects[0].element);
},afterFinishInternal:function(_779){
MochiKit.Style.hideElement(_779.effects[0].element);
d.undoClipping(_779.effects[0].element);
d.undoPositioned(_779.effects[0].element);
d.setStyle(_779.effects[0].element,_775);
}},_774||{});
return new v.Parallel([new v.Opacity(_773,{sync:true,to:0,from:1,transition:_774.opacityTransition}),new v.Scale(_773,MochiKit.Base.isOpera()?1:0,{sync:true,transition:_774.scaleTransition,restoreAfterFinish:true}),new v.Move(_773,{x:_776,y:moveY,sync:true,transition:_774.moveTransition})],_777);
};
MochiKit.Visual.pulsate=function(_780,_781){
var d=MochiKit.DOM;
var v=MochiKit.Visual;
var b=MochiKit.Base;
_780=d.getElement(_780);
var _782=d.getInlineOpacity(_780);
_781=b.update({duration:3,from:0,afterFinishInternal:function(_783){
d.setStyle(_783.element,{opacity:_782});
}},_781||{});
var _784=_781.transition||v.Transitions.sinoidal;
var _785=b.bind(function(pos){
return _784(1-v.Transitions.pulse(pos));
},_784);
b.bind(_785,_784);
return new v.Opacity(_780,b.update({transition:_785},_781));
};
MochiKit.Visual.fold=function(_786,_787){
var d=MochiKit.DOM;
var v=MochiKit.Visual;
_786=d.getElement(_786);
var _788={top:_786.style.top,left:_786.style.left,width:_786.style.width,height:_786.style.height};
d.makeClipping(_786);
_787=MochiKit.Base.update({scaleContent:false,scaleX:false,afterFinishInternal:function(_789){
new v.Scale(_786,1,{scaleContent:false,scaleY:false,afterFinishInternal:function(_789){
MochiKit.Style.hideElement(_789.element);
d.undoClipping(_789.element);
d.setStyle(_789.element,_788);
}});
}},_787||{});
return new v.Scale(_786,5,_787);
};
MochiKit.Visual.Color=MochiKit.Color.Color;
MochiKit.Visual.getElementsComputedStyle=MochiKit.DOM.computedStyle;
MochiKit.Visual.__new__=function(){
var m=MochiKit.Base;
m.nameFunctions(this);
this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
};
MochiKit.Visual.EXPORT=["roundElement","roundClass","tagifyText","multiple","toggle","Base","Parallel","Opacity","Move","Scale","Highlight","ScrollTo","fade","appear","puff","blindUp","blindDown","switchOff","dropOut","shake","slideDown","slideUp","squish","grow","shrink","pulsate","fold"];
MochiKit.Visual.EXPORT_OK=["PAIRS"];
MochiKit.Visual.__new__();
MochiKit.Base._exportSymbols(this,MochiKit.Visual);
if(typeof (MochiKit)=="undefined"){
MochiKit={};
}
if(typeof (MochiKit.MochiKit)=="undefined"){
MochiKit.MochiKit={};
}
MochiKit.MochiKit.NAME="MochiKit.MochiKit";
MochiKit.MochiKit.VERSION="1.4";
MochiKit.MochiKit.__repr__=function(){
return "["+this.NAME+" "+this.VERSION+"]";
};
MochiKit.MochiKit.toString=function(){
return this.__repr__();
};
MochiKit.MochiKit.SUBMODULES=["Base","Iter","Logging","DateTime","Format","Async","DOM","Style","LoggingPane","Color","Signal","Visual"];
if(typeof (JSAN)!="undefined"||typeof (dojo)!="undefined"){
if(typeof (dojo)!="undefined"){
dojo.provide("MochiKit.MochiKit");
dojo.require("MochiKit.*");
}
if(typeof (JSAN)!="undefined"){
(function(lst){
for(var i=0;i<lst.length;i++){
JSAN.use("MochiKit."+lst[i],[]);
}
})(MochiKit.MochiKit.SUBMODULES);
}
(function(){
var _790=MochiKit.Base.extend;
var self=MochiKit.MochiKit;
var _791=self.SUBMODULES;
var _792=[];
var _793=[];
var _794={};
var i,k,m,all;
for(i=0;i<_791.length;i++){
m=MochiKit[_791[i]];
_790(_792,m.EXPORT);
_790(_793,m.EXPORT_OK);
for(k in m.EXPORT_TAGS){
_794[k]=_790(_794[k],m.EXPORT_TAGS[k]);
}
all=m.EXPORT_TAGS[":all"];
if(!all){
all=_790(null,m.EXPORT,m.EXPORT_OK);
}
var j;
for(j=0;j<all.length;j++){
k=all[j];
self[k]=m[k];
}
}
self.EXPORT=_792;
self.EXPORT_OK=_793;
self.EXPORT_TAGS=_794;
}());
}else{
if(typeof (MochiKit.__compat__)=="undefined"){
MochiKit.__compat__=true;
}
(function(){
if(typeof (document)=="undefined"){
return;
}
var _795=document.getElementsByTagName("script");
var _796="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var base=null;
var _797=null;
var _798={};
var i;
for(i=0;i<_795.length;i++){
var src=_795[i].getAttribute("src");
if(!src){
continue;
}
_798[src]=true;
if(src.match(/MochiKit.js$/)){
base=src.substring(0,src.lastIndexOf("MochiKit.js"));
_797=_795[i];
}
}
if(base===null){
return;
}
var _799=MochiKit.MochiKit.SUBMODULES;
for(var i=0;i<_799.length;i++){
if(MochiKit[_799[i]]){
continue;
}
var uri=base+_799[i]+".js";
if(uri in _798){
continue;
}
if(document.documentElement&&document.documentElement.namespaceURI==_796){
var s=document.createElementNS(_796,"script");
s.setAttribute("id","MochiKit_"+base+_799[i]);
s.setAttribute("src",uri);
s.setAttribute("type","application/x-javascript");
_797.parentNode.appendChild(s);
}else{
document.write("<script src=\""+uri+"\" type=\"text/javascript\"></script>");
}
}
})();
}




--- NEW FILE New.js ---

MochiKit.Base.update(MochiKit.Base, {
    isIE: function () {
        return /MSIE/.test(navigator.userAgent);
    },

    isGecko: function () {
        return /Gecko/.test(navigator.userAgent);
    },

    isKHTML: function () {
        return /Konqueror|Safari|KHTML/.test(navigator.userAgent)
    },

    isSafari: function () {
        return navigator.appVersion.indexOf('AppleWebKit') > 0;
    },

    isOpera: function () {
        return navigator.userAgent.indexOf('Opera') > 0;
    }
});

MochiKit.Base.update(MochiKit.DOM, {
    getStyle: function (element, style) {
        element = MochiKit.DOM.getElement(element);
        var value = element.style[MochiKit.Base.camelize(style)];
        if (!value) {
            if (document.defaultView && document.defaultView.getComputedStyle) {
                var css = document.defaultView.getComputedStyle(element, null);
                value = css ? css.getPropertyValue(style) : null;
            } else if (element.currentStyle) {
                value = element.currentStyle[MochiKit.Base.camelize(style)];
            }
        }

        if (MochiKit.Base.isOpera() && (MochiKit.Base.find(['left', 'top', 'right', 'bottom'], style))) {
            if (MochiKit.DOM.getStyle(element, 'position') == 'static') {
                value = 'auto';
            }
        }

        return value == 'auto' ? null : value;
    },

    setStyle: function (element, style) {
        element = MochiKit.DOM.getElement(element);
        for (name in style) {
            element.style[MochiKit.Base.camelize(name)] = style[name];
        }
    },

    getOpacity: function (element) {
        var opacity;
        if (opacity = MochiKit.DOM.getStyle(element, 'opacity')) {
            return parseFloat(opacity);
        }
        if (opacity = (MochiKit.DOM.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/)) {
            if (opacity[1]) {
                return parseFloat(opacity[1]) / 100;
            }
        }
        return 1.0;
    },

    getInlineOpacity: function (element) {
        return MochiKit.DOM.getElement(element).style.opacity || '';
    },

    setOpacity: function (element, value) {
        element = MochiKit.DOM.getElement(element);
        if (value == 1) {
            MochiKit.DOM.setStyle(element, {opacity:
                (MochiKit.Base.isGecko() && !MochiKit.Base.isKHTML()) ?
                0.999999 : null});
            if (MochiKit.Base.isIE())
                MochiKit.DOM.setStyle(element, {filter:
                MochiKit.DOM.getStyle(element, 'filter').replace(/alpha\([^\)]*\)/gi, '')});
        } else {
            if (value < 0.00001) {
                value = 0;
            }
            MochiKit.DOM.setStyle(element, {opacity: value});
            if (MochiKit.Base.isIE()) {
                MochiKit.DOM.setStyle(element,
                    {filter: MochiKit.DOM.getStyle(element, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + value * 100 + ')' });
            }
        }
    },

    isVisible: function (element) {
        return MochiKit.DOM.getElement(element).style.display != 'none';
    },

    makeClipping: function (element) {
        element = MochiKit.DOM.getElement(element);
        if (element._overflow) {
            return;
        }
        element._overflow = element.style.overflow;
        if ((MochiKit.DOM.getStyle(element, 'overflow') || 'visible') != 'hidden') {
            element.style.overflow = 'hidden';
        }
    },

    undoClipping: function (element) {
        element = MochiKit.DOM.getElement(element);
        if (!element._overflow) {
            return;
        }
        element.style.overflow = element._overflow;
        element._overflow = undefined;
    },

    makePositioned: function (element) {
        element = MochiKit.DOM.getElement(element);
        /*if (!element.style) {
            alert(element);
        }*/
        var pos = MochiKit.DOM.getStyle(element, 'position');
        if ((pos == 'static' || !pos) && !element._madePositioned) {
            element._madePositioned = true;
            element.style.position = 'relative';
            // Opera returns the offset relative to the positioning context,
            // when an element is position relative but top and left have
            // not been defined
            if (MochiKit.Base.isOpera()) {
                element.style.top = 0;
                element.style.left = 0;
            }
        }
    },

    undoPositioned: function (element) {
        element = MochiKit.DOM.getElement(element);
        if (element._madePositioned) {
            element._madePositioned = undefined;
            element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = '';
        }
    },

    getFirstElementByTagAndClassName: function (tagName, className,
            /* optional */parent) {
        var self = MochiKit.DOM;
        if (typeof(tagName) == 'undefined' || tagName === null) {
            tagName = '*';
        }
        if (typeof(parent) == 'undefined' || parent === null) {
            parent = self._document;
        }
        parent = self.getElement(parent);
        var children = (parent.getElementsByTagName(tagName)
            || self._document.all);
        if (typeof(className) == 'undefined' || className === null) {
            return MochiKit.Base.extend(null, children);
        }

        for (var i = 0; i < children.length; i++) {
            var child = children[i];
            var classNames = child.className.split(' ');
            for (var j = 0; j < classNames.length; j++) {
                if (classNames[j] == className) {
                    return child;
                }
            }
        }
    },

    isParent: function (child, element) {
        if (!child.parentNode || child == element) {
            return false;
        }

        if (child.parentNode == element) {
            return true;
        }

        return MochiKit.DOM.isParent(child.parentNode, element);
    }
});

MochiKit.Position = {
    // set to true if needed, warning: firefox performance problems
    // NOT neeeded for page scrolling, only if draggable contained in
    // scrollable elements
    includeScrollOffsets: false,

    prepare: function () {
        var deltaX =  window.pageXOffset
                   || document.documentElement.scrollLeft
                   || document.body.scrollLeft
                   || 0;
        var deltaY =  window.pageYOffset
                   || document.documentElement.scrollTop
                   || document.body.scrollTop
                   || 0;
        this.windowOffset = new MochiKit.Style.Coordinates(deltaX, deltaY);
    },

    cumulativeOffset: function (element) {
        var valueT = 0;
        var valueL = 0;
        do {
            valueT += element.offsetTop  || 0;
            valueL += element.offsetLeft || 0;
            element = element.offsetParent;
        } while (element);
        return new MochiKit.Style.Coordinates(valueL, valueT);
    },

    realOffset: function (element) {
        var valueT = 0;
        var valueL = 0;
        do {
            valueT += element.scrollTop  || 0;
            valueL += element.scrollLeft || 0;
            element = element.parentNode;
        } while (element);
        return new MochiKit.Style.Coordinates(valueL, valueT);
    },

    within: function (element, x, y) {
        if (this.includeScrollOffsets) {
            return this.withinIncludingScrolloffsets(element, x, y);
        }
        this.xcomp = x;
        this.ycomp = y;
        this.offset = this.cumulativeOffset(element);
        if (element.style.position == "fixed") {
            this.offset.x += this.windowOffset.x;
            this.offset.y += this.windowOffset.y;
        }

        return (y >= this.offset.y &&
                y <  this.offset.y + element.offsetHeight &&
                x >= this.offset.x &&
                x <  this.offset.x + element.offsetWidth);
    },

    withinIncludingScrolloffsets: function (element, x, y) {
        var offsetcache = this.realOffset(element);

        this.xcomp = x + offsetcache.x - this.windowOffset.x;
        this.ycomp = y + offsetcache.y - this.windowOffset.y;
        this.offset = this.cumulativeOffset(element);

        return (this.ycomp >= this.offset.y &&
                this.ycomp <  this.offset.y + element.offsetHeight &&
                this.xcomp >= this.offset.x &&
                this.xcomp <  this.offset.x + element.offsetWidth);
    },

    // within must be called directly before
    overlap: function (mode, element) {
        if (!mode) {
            return 0;
        }
        if (mode == 'vertical') {
          return ((this.offset.y + element.offsetHeight) - this.ycomp) /
                 element.offsetHeight;
        }
        if (mode == 'horizontal') {
          return ((this.offset.x + element.offsetWidth) - this.xcomp) /
                 element.offsetWidth;
        }
    },

    absolutize: function (element) {
        element = MochiKit.DOM.getElement(element);
        if (element.style.position == 'absolute') {
            return;
        }
        MochiKit.Position.prepare();

        var offsets = MochiKit.Position.positionedOffset(element);
        var width = element.clientWidth;
        var height = element.clientHeight;

        var oldStyle = {
            'position': element.style.position,
            'left': offsets.x - parseFloat(element.style.left  || 0),
            'top': offsets.y - parseFloat(element.style.top || 0),
            'width': element.style.width,
            'height': element.style.height
        };

        element.style.position = 'absolute';
        element.style.top = offsets.y + 'px';
        element.style.left = offsets.x + 'px';
        element.style.width = width + 'px';
        element.style.height = height + 'px';

        return oldStyle;
    },

    positionedOffset: function (element) {
        var valueT = 0, valueL = 0;
        do {
            valueT += element.offsetTop  || 0;
            valueL += element.offsetLeft || 0;
            element = element.offsetParent;
            if (element) {
                p = MochiKit.DOM.getStyle(element, 'position');
                if (p == 'relative' || p == 'absolute') {
                    break;
                }
            }
        } while (element);
        return new MochiKit.Style.Coordinates(valueL, valueT);
    },

    relativize: function (element, oldPos) {
        element = MochiKit.DOM.getElement(element);
        if (element.style.position == 'relative') {
            return;
        }
        MochiKit.Position.prepare();

        var top = parseFloat(element.style.top || 0) -
                  (oldPos['top'] || 0);
        var left = parseFloat(element.style.left || 0) -
                   (oldPos['left'] || 0);

        element.style.position = oldPos['position'];
        element.style.top = top + 'px';
        element.style.left = left + 'px';
        element.style.width = oldPos['width'];
        element.style.height = oldPos['height'];
    },

    clone: function (source, target) {
        source = MochiKit.DOM.getElement(source);
        target = MochiKit.DOM.getElement(target);
        target.style.position = 'absolute';
        var offsets = this.cumulativeOffset(source);
        target.style.top = offsets.y + 'px';
        target.style.left = offsets.x + 'px';
        target.style.width = source.offsetWidth + 'px';
        target.style.height = source.offsetHeight + 'px';
    },

    page: function (forElement) {
        var valueT = 0;
        var valueL = 0;

        var element = forElement;
        do {
            valueT += element.offsetTop  || 0;
            valueL += element.offsetLeft || 0;

            // Safari fix
            if (element.offsetParent == document.body && MochiKit.DOM.getStyle(element, 'position') == 'absolute') {
                break;
            }
        } while (element = element.offsetParent);

        element = forElement;
        do {
            valueT -= element.scrollTop  || 0;
            valueL -= element.scrollLeft || 0;
        } while (element = element.parentNode);

        return new MochiKit.Style.Coordinates(valueL, valueT);
    }
};



--- NEW FILE Sortable.js ---
/***
Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
    Mochi-ized By Thomas Herve (_firstname_ at nimail.org)

See scriptaculous.js for full license.

***/

if (typeof(dojo) != 'undefined') {
    dojo.provide('MochiKit.DragAndDrop');
    dojo.require('MochiKit.Base');
    dojo.require('MochiKit.DOM');
    dojo.require('MochiKit.Iter');
}

if (typeof(JSAN) != 'undefined') {
    JSAN.use("MochiKit.Base", []);
    JSAN.use("MochiKit.DOM", []);
    JSAN.use("MochiKit.Iter", []);
}

try {
    if (typeof(MochiKit.Base) == 'undefined' ||
        typeof(MochiKit.DOM) == 'undefined' ||
        typeof(MochiKit.Iter) == 'undefined') {
        throw "";
    }
} catch (e) {
    throw "MochiKit.DragAndDrop depends on MochiKit.Base, MochiKit.DOM and MochiKit.Iter!";
}

if (typeof(MochiKit.Sortable) == 'undefined') {
    MochiKit.Sortable = {};
}

MochiKit.Sortable.NAME = 'MochiKit.Sortable';
MochiKit.Sortable.VERSION = '1.4';

MochiKit.Sortable.__repr__ = function () {
    return '[' + this.NAME + ' ' + this.VERSION + ']';
};

MochiKit.Sortable.toString = function () {
    return this.__repr__();
};

MochiKit.Sortable.EXPORT = [
    "SortableObserver"
];

MochiKit.DragAndDrop.EXPORT_OK = [
    "Sortable"
];

MochiKit.Sortable.SortableObserver = function (element, observer) {
    this.__init__(element, observer);
};

MochiKit.Sortable.SortableObserver.prototype = {
    /***

    Observe events of drag and drop sortables.

    ***/
    __init__: function (element, observer) {
        this.element = MochiKit.DOM.getElement(element);
        this.observer = observer;
        this.lastValue = MochiKit.Sortable.Sortable.serialize(this.element);
    },

    onStart: function () {
        this.lastValue = MochiKit.Sortable.Sortable.serialize(this.element);
    },

    onEnd: function () {
        MochiKit.Sortable.Sortable.unmark();
        if (this.lastValue != MochiKit.Sortable.Sortable.serialize(this.element)) {
            this.observer(this.element)
        }
    }
};

MochiKit.Sortable.Sortable = {
    /***

    Manage sortables. Mainly use the create function to add a sortable.

    ***/
    sortables: {},

    _findRootElement: function (element) {
        while (element.tagName != "BODY") {
            if (element.id && MochiKit.Sortable.Sortable.sortables[element.id]) {
                return element;
            }
            element = element.parentNode;
        }
    },

    options: function (element) {
        element = MochiKit.Sortable.Sortable._findRootElement(MochiKit.DOM.getElement(element));
        if (!element) {
            return;
        }
        return MochiKit.Sortable.Sortable.sortables[element.id];
    },

    destroy: function (element){
        var s = MochiKit.Sortable.Sortable.options(element);
        var b = MochiKit.Base;
        var d = MochiKit.DragAndDrop;

        if (s) {
            d.Draggables.removeObserver(s.element);
            b.map(function (dr) {
                d.Droppables.remove(dr);
            }, s.droppables);
            b.map(function (dr) {
                dr.destroy();
            }, s.draggables);

            delete MochiKit.Sortable.Sortable.sortables[s.element.id];
        }
    },

    create: function (element, options) {
        element = MochiKit.DOM.getElement(element);
        var self = MochiKit.Sortable.Sortable;
        options = MochiKit.Base.update({
            element: element,
            tag: 'li',  // assumes li children, override with tag: 'tagname'
            dropOnEmpty: false,
            tree: false,
            treeTag: 'ul',
            overlap: 'vertical',  // one of 'vertical', 'horizontal'
            constraint: 'vertical',  // one of 'vertical', 'horizontal', false
            // also takes array of elements (or ids); or false
            containment: [element],
            handle: false,  // or a CSS class
            only: false,
            hoverclass: null,
            ghosting: false,
            scroll: false,
            scrollSensitivity: 20,
            scrollSpeed: 15,
            format: /^[^_]*_(.*)$/,
            onChange: MochiKit.Base.noop,
            onUpdate: MochiKit.Base.noop,
            accept: null
        }, options);

        // clear any old sortable with same element
        self.destroy(element);

        // build options for the draggables
        var options_for_draggable = {
            revert: true,
            ghosting: options.ghosting,
            scroll: options.scroll,
            scrollSensitivity: options.scrollSensitivity,
            scrollSpeed: options.scrollSpeed,
            constraint: options.constraint,
            handle: options.handle
        };

        if (options.starteffect) {
            options_for_draggable.starteffect = options.starteffect;
        }

        if (options.reverteffect) {
            options_for_draggable.reverteffect = options.reverteffect;
        } else if (options.ghosting) {
            options_for_draggable.reverteffect = function (innerelement) {
                innerelement.style.top = 0;
                innerelement.style.left = 0;
            };
        }

        if (options.endeffect) {
            options_for_draggable.endeffect = options.endeffect;
        }

        if (options.zindex) {
            options_for_draggable.zindex = options.zindex;
        }

        // build options for the droppables
        var options_for_droppable = {
            overlap: options.overlap,
            containment: options.containment,
            hoverclass: options.hoverclass,
            onhover: self.onHover,
            tree: options.tree,
            accept: options.accept
        }

        var options_for_tree = {
            onhover: self.onEmptyHover,
            overlap: options.overlap,
            containment: options.containment,
            hoverclass: options.hoverclass,
            accept: options.accept
        }

        // fix for gecko engine
        MochiKit.DOM.removeEmptyTextNodes(element);

        options.draggables = [];
        options.droppables = [];

        // drop on empty handling
        if (options.dropOnEmpty || options.tree) {
            new MochiKit.DragAndDrop.Droppable(element, options_for_tree);
            options.droppables.push(element);
        }
        MochiKit.Base.map(function (e) {
            // handles are per-draggable
            var handle = options.handle ?
                MochiKit.DOM.getFirstElementByTagAndClassName(null,
                    options.handle, e) : e;
            options.draggables.push(
                new MochiKit.DragAndDrop.Draggable(e,
                    MochiKit.Base.update(options_for_draggable,
                                         {handle: handle})));
            new MochiKit.DragAndDrop.Droppable(e, options_for_droppable);
            if (options.tree) {
                e.treeNode = element;
            }
            options.droppables.push(e);
        }, (self.findElements(element, options) || []));

        if (options.tree) {
            MochiKit.Base.map(function (e) {
                new MochiKit.DragAndDrop.Droppable(e, options_for_tree);
                e.treeNode = element;
                options.droppables.push(e);
            }, (self.findTreeElements(element, options) || []));
        }

        // keep reference
        self.sortables[element.id] = options;

        // for onupdate
        MochiKit.DragAndDrop.Draggables.addObserver(
            new MochiKit.Sortable.SortableObserver(element, options.onUpdate));
    },

    // return all suitable-for-sortable elements in a guaranteed order
    findElements: function (element, options) {
        return MochiKit.Sortable.Sortable.findChildren(
            element, options.only, options.tree ? true : false, options.tag);
    },

    findTreeElements: function (element, options) {
        return MochiKit.Sortable.Sortable.findChildren(
            element, options.only, options.tree ? true : false, options.treeTag);
    },

    findChildren: function (element, only, recursive, tagName) {
        if (!element.hasChildNodes()) {
            return null;
        }
        tagName = tagName.toUpperCase();
        if (only) {
            only = MochiKit.Base.flattenArray([only]);
        }
        var elements = [];
        MochiKit.Base.map(function (e) {
            if (e.tagName &&
                e.tagName.toUpperCase() == tagName &&
               (!only ||
                MochiKit.Iter.some(only, function (c) {
                    return MochiKit.DOM.hasElementClass(e, c);
                }))) {
                elements.push(e);
            }
            if (recursive) {
                var grandchildren = MochiKit.Sortable.Sortable.findChildren(e, only, recursive, tagName);
                if (grandchildren && grandchildren.length > 0) {
                    elements = elements.concat(grandchildren);
                }
            }
        }, element.childNodes);
        return elements;
    },

    onHover: function (element, dropon, overlap) {
        if (MochiKit.DOM.isParent(dropon, element)) {
            return;
        }
        var self = MochiKit.Sortable.Sortable;

        if (overlap > .33 && overlap < .66 && self.options(dropon).tree) {
            return;
        } else if (overlap > 0.5) {
            self.mark(dropon, 'before');
            if (dropon.previousSibling != element) {
                var oldParentNode = element.parentNode;
                element.style.visibility = 'hidden';  // fix gecko rendering
                dropon.parentNode.insertBefore(element, dropon);
                if (dropon.parentNode != oldParentNode) {
                    self.options(oldParentNode).onChange(element);
                }
                self.options(dropon.parentNode).onChange(element);
            }
        } else {
            self.mark(dropon, 'after');
            var nextElement = dropon.nextSibling || null;
            if (nextElement != element) {
                var oldParentNode = element.parentNode;
                element.style.visibility = 'hidden';  // fix gecko rendering
                dropon.parentNode.insertBefore(element, nextElement);
                if (dropon.parentNode != oldParentNode) {
                    self.options(oldParentNode).onChange(element);
                }
                self.options(dropon.parentNode).onChange(element);
            }
        }
    },

    _offsetSize: function (element, type) {
        if (type == 'vertical' || type == 'height') {
            return element.offsetHeight;
        } else {
            return element.offsetWidth;
        }
    },

    onEmptyHover: function (element, dropon, overlap) {
        var oldParentNode = element.parentNode;
        var self = MochiKit.Sortable.Sortable;
        var droponOptions = self.options(dropon);

        if (!MochiKit.DOM.isParent(dropon, element)) {
            var index;

            var children = self.findElements(dropon, {tag: droponOptions.tag,
                                                      only: droponOptions.only});
            var child = null;

            if (children) {
                var offset = self._offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);

                for (index = 0; index < children.length; index += 1) {
                    if (offset - self._offsetSize(children[index], droponOptions.overlap) >= 0) {
                        offset -= self._offsetSize(children[index], droponOptions.overlap);
                    } else if (offset - (self._offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
                        child = index + 1 < children.length ? children[index + 1] : null;
                        break;
                    } else {
                        child = children[index];
                        break;
                    }
                }
            }

            dropon.insertBefore(element, child);

            self.options(oldParentNode).onChange(element);
            droponOptions.onChange(element);
        }
    },

    unmark: function () {
        var m = MochiKit.Sortable.Sortable._marker;
        if (m) {
            MochiKit.Style.hideElement(m);
        }
    },

    mark: function (dropon, position) {
        // mark on ghosting only
        var d = MochiKit.DOM;
        var self = MochiKit.Sortable.Sortable;
        var sortable = self.options(dropon.parentNode);
        if (sortable && !sortable.ghosting) {
            return;
        }

        if (!self._marker) {
            self._marker = d.getElement('dropmarker') ||
                        document.createElement('DIV');
            MochiKit.Style.hideElement(self._marker);
            d.addElementClass(self._marker, 'dropmarker');
            self._marker.style.position = 'absolute';
            document.getElementsByTagName('body').item(0).appendChild(self._marker);
        }
        var offsets = MochiKit.Position.cumulativeOffset(dropon);
        self._marker.style.left = offsets.x + 'px';
        self._marker.style.top = offsets.y + 'px';

        if (position == 'after') {
            if (sortable.overlap == 'horizontal') {
                self._marker.style.left = (offsets.x + dropon.clientWidth) + 'px';
            } else {
                self._marker.style.top = (offsets.y + dropon.clientHeight) + 'px';
            }
        }
        MochiKit.Style.showElement(self._marker);
    },

    _tree: function (element, options, parent) {
        var self = MochiKit.Sortable.Sortable;
        var children = self.findElements(element, options) || [];

        for (var i = 0; i < children.length; ++i) {
            var match = children[i].id.match(options.format);

            if (!match) {
                continue;
            }

            var child = {
                id: encodeURIComponent(match ? match[1] : null),
                element: element,
                parent: parent,
                children: [],
                position: parent.children.length,
                container: self._findChildrenElement(children[i], options.treeTag.toUpperCase())
            }

            /* Get the element containing the children and recurse over it */
            if (child.container) {
                self._tree(child.container, options, child)
            }

            parent.children.push (child);
        }

        return parent;
    },

    /* Finds the first element of the given tag type within a parent element.
       Used for finding the first LI[ST] within a L[IST]I[TEM].*/
    _findChildrenElement: function (element, containerTag) {
        if (element && element.hasChildNodes) {
            for (var i = 0; i < element.childNodes.length; ++i) {
                if (element.childNodes[i].tagName == containerTag) {
                    return element.childNodes[i];
                }
            }
        }
        return null;
    },

    tree: function (element, options) {
        element = MochiKit.DOM.getElement(element);
        var sortableOptions = MochiKit.Sortable.Sortable.options(element);
        options = MochiKit.Base.update({
            tag: sortableOptions.tag,
            treeTag: sortableOptions.treeTag,
            only: sortableOptions.only,
            name: element.id,
            format: sortableOptions.format
        }, options || {});

        var root = {
            id: null,
            parent: null,
            children: new Array,
            container: element,
            position: 0
        }

        return MochiKit.Sortable.Sortable._tree(element, options, root);
    },

    setSequence: function (element, newSequence, options) {
        var self = MochiKit.Sortable.Sortable;
        var b = MochiKit.Base;
        element = MochiKit.DOM.getElement(element);
        options = b.update(self.options(element), options || {});

        var nodeMap = {};
        b.map(function (n) {
            var m = n.id.match(options.format);
            if (m) {
                nodeMap[m[1]] = [n, n.parentNode];
            }
            n.parentNode.removeChild(n);
        }, self.findElements(element, options));

        b.map(function (ident) {
            var n = nodeMap[ident];
            if (n) {
                n[1].appendChild(n[0]);
                delete nodeMap[ident];
            }
        }, newSequence);
    },

    /* Construct a [i] index for a particular node */
    _constructIndex: function (node) {
        var index = '';
        do {
            if (node.id) {
                index = '[' + node.position + ']' + index;
            }
        } while ((node = node.parent) != null);
        return index;
    },

    sequence: function (element, options) {
        element = MochiKit.DOM.getElement(element);
        var self = MochiKit.Sortable.Sortable;
        var options = MochiKit.Base.update(self.options(element), options || {});

        return MochiKit.Base.map(function (item) {
            return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
        }, MochiKit.DOM.getElement(self.findElements(element, options) || []));
    },

    serialize: function (element, options) {
        element = MochiKit.DOM.getElement(element);
        var self = MochiKit.Sortable.Sortable;
        options = MochiKit.Base.update(self.options(element), options || {});
        var name = encodeURIComponent(options.name || element.id);

        if (options.tree) {
            return MochiKit.Base.flattenArray(MochiKit.Base.map(function (item) {
                return [name + self._constructIndex(item) + "[id]=" +
                encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
            }, self.tree(element, options).children)).join('&');
        } else {
            return MochiKit.Base.map(function (item) {
                return name + "[]=" + encodeURIComponent(item);
            }, self.sequence(element, options)).join('&');
        }
    }
};



--- NEW FILE color.js ---
function getSelected() {
    return getElement("foreback").value;
}

function updateDisplay() {
    var textbox = getElement("as_string");
    var current = getSelected();
    
    if (current == "Foreground") {
        textbox.value = Color.fromText("sample").toString();
    } else {
        textbox.value = Color.fromBackground("sample").toString();
    }
}

function setSampleFromElement(elem, toSet) {
    var elem = getElement(elem);
    var samplediv = getElement("sample");
    var color = Color.fromString(elem.value);
    if (color == null) {
        alert("Unknown color string");
        return;
    }
    samplediv.style[toSet] = color;
    updateDisplay();
}

function setColor() {
    var current = getSelected();
    if (current == "Foreground") {
        setSampleFromElement("as_string", "color");
    } else {
        setSampleFromElement("as_string", "background");
    }
}

function setForeground() {
    setSampleFromElement("foreground", "color");
}

function setBackground() {
    setSampleFromElement("background", "background");
}

function cloneColor() {
    var samplediv = getElement("sample");
    var current = getSelected();
    
    if (current == "Foreground") {
        samplediv.style.color = Color.fromText("header");
    } else {
        samplediv.style.background = Color.fromBackground("header");
    }
    
    updateDisplay();
    
}


--- NEW FILE draggable.js ---
/*

    Drag: A Really Simple Drag Handler
    
*/

            var nextInChain = [];
            
            RollingSign = function(element, newstring, options) {
                this.__init__(element, newstring, options);
            }

            RollingSign.prototype = new Base();

            update(RollingSign.prototype, {

                __init__ : function(element, newstring, options) {
                    this.element = getElement(element);

                    options = update(
                        {
                            charSpaceSize: 26,
                            startingChar: 65
                        }, options || {});

                    this.newstring = newstring;
                    this.oldstring = this.element.innerHTML;

                    this.start(options);
                },

                update: function(position) {
                    curchar = this.newstring.length * position;
                    toMake = this.newstring.length - curchar;

                    ending = "";
                    for (i = 0; i < toMake; i++) {
                        ending += String.fromCharCode(
                            Math.random() * this.options.charSpaceSize +
                            this.options.startingChar);
                    }

                    this.element.innerHTML = this.newstring.substr(0, curchar) +
                        ending;
                },

                finish: function() {
                    this.element.innerHTML = this.newstring;
                }
            }
        );

Drag = {
    _move: null,
    _down: null,
    
    start: function(e) {
        e.stop();
        
        // We need to remember what we're dragging.
        Drag._target = e.target();
        
        /*
            There's no cross-browser way to get offsetX and offsetY, so we
            have to do it ourselves. For performance, we do this once and
            cache it.
        */
        Drag._offset = Drag._diff(
            e.mouse().page,
            getElementPosition(Drag._target));
        
        Drag._move = connect(document, 'onmousemove', Drag._drag);
        Drag._down = connect(document, 'onmouseup', Drag._stop);
    },

    _offset: null,
    _target: null,
    
    _diff: function(lhs, rhs) {
        return new MochiKit.Style.Coordinates(lhs.x - rhs.x, lhs.y - rhs.y);
    },
        
    _drag: function(e) {
        e.stop();
        setElementPosition(
            Drag._target,
            Drag._diff(e.mouse().page, Drag._offset));
    },
    
    _stop: function(e) {
        disconnect(Drag._move);
        disconnect(Drag._down);
    }
};

connect(window, 'onload',   
    function() {
        /*
            Find all DIVs tagged with the draggable class, and connect them to
            the Drag handler.
        */
        var d = getElementsByTagAndClassName('DIV', 'draggable');
        forEach(d,
            function(elem) {
                connect(elem, 'onmousedown', Drag.start);
            });
                        
    });
    
connect(window, 'onload',
    function() {
        var elems = getElementsByTagAndClassName("A", "view-source");
        var page = "draggable/";
        for (var i = 0; i < elems.length; i++) {
            var elem = elems[i];
            var href = elem.href.split(/\//).pop();
            elem.target = "_blank";
            elem.href = "../view-source/view-source.html#" + page + href;
        } 
    });


--- NEW FILE signal.js ---
var currentSelected = null;

function changeSelected(e) {
    if (currentSelected != null) {
        logDebug("Disconnecting " + currentSelected);
        disconnectAll(currentSelected);
    }
    var es = getElement("elemselect");
    currentSelected = es.value;
    var ev = getElement("eventselect").value;
    logDebug("Connecting " + currentSelected + " for event " + ev);
    connect(currentSelected, ev, log);
}


--- NEW FILE sortable_tables.js ---
/*

On page load, the SortableManager:

- Finds the table by its id (sortable_table).
- Parses its thead for columns with a "mochi:format" attribute.
- Parses the data out of the tbody based upon information given in the
  "mochi:format" attribute, and clones the tr elements for later re-use.
- Clones the column header th elements for use as a template when drawing 
  sort arrow columns.
- Stores away a reference to the tbody, as it will be replaced on each sort.
- Performs the first sort.


On sort request:

- Sorts the data based on the given key and direction
- Creates a new tbody from the rows in the new ordering
- Replaces the column header th elements with clickable versions, adding an
   indicator (&uarr; or &darr;) to the most recently sorted column.

*/

SortableManager = function () {
    this.thead = null;
    this.tbody = null;
    this.columns = [];
    this.rows = [];
    this.sortState = {};
    this.sortkey = 0;
};

mouseOverFunc = function () {
    addElementClass(this, "over");
};

mouseOutFunc = function () {
    removeElementClass(this, "over");
};

ignoreEvent = function (ev) {
    if (ev && ev.preventDefault) {
        ev.preventDefault();
        ev.stopPropagation();
    } else if (typeof(event) != 'undefined') {
        event.cancelBubble = false;
        event.returnValue = false;
    }
};


update(SortableManager.prototype, {

    "initWithTable": function (table) {
        /***

            Initialize the SortableManager with a table object
        
        ***/
        // Ensure that it's a DOM element
        table = getElement(table);
        // Find the thead
        this.thead = table.getElementsByTagName('thead')[0];
        // get the mochi:format key and contents for each column header
        var cols = this.thead.getElementsByTagName('th');
        for (var i = 0; i < cols.length; i++) {
            var node = cols[i];
            var attr = null;
            try {
                attr = node.getAttribute("mochi:format");
            } catch (err) {
                // pass
            }
            var o = node.childNodes;
            this.columns.push({
                "format": attr,
                "element": node,
                "proto": node.cloneNode(true)
            });
        }
        // scrape the tbody for data
        this.tbody = table.getElementsByTagName('tbody')[0];
        // every row
        var rows = this.tbody.getElementsByTagName('tr');
        for (var i = 0; i < rows.length; i++) {
            // every cell
            var row = rows[i];
            var cols = row.getElementsByTagName('td');
            var rowData = [];
            for (var j = 0; j < cols.length; j++) {
                // scrape the text and build the appropriate object out of it
                var cell = cols[j];
                var obj = scrapeText(cell);
                switch (this.columns[j].format) {
                    case 'isodate':
                        obj = isoDate(obj);
                        break;
                    case 'str':
                        break;
                    case 'istr':
                        obj = obj.toLowerCase();
                        break;
                    // cases for numbers, etc. could be here
                    default:
                        break;
                }
                rowData.push(obj);
            }
            // stow away a reference to the TR and save it
            rowData.row = row.cloneNode(true);
            this.rows.push(rowData);

        }

        // do initial sort on first column
        this.drawSortedRows(this.sortkey, true, false);

    },

    "onSortClick": function (name) {
        /***

            Return a sort function for click events

        ***/
        return method(this, function () {
            log('onSortClick', name);
            var order = this.sortState[name];
            if (order == null) {
                order = true;
            } else if (name == this.sortkey) {
                order = !order;
            }
            this.drawSortedRows(name, order, true);
        });
    },

    "drawSortedRows": function (key, forward, clicked) {
        /***

            Draw the new sorted table body, and modify the column headers
            if appropriate

        ***/
        log('drawSortedRows', key, forward);
        this.sortkey = key;
        // sort based on the state given (forward or reverse)
        var cmp = (forward ? keyComparator : reverseKeyComparator);
        this.rows.sort(cmp(key));
        // save it so we can flip next time
        this.sortState[key] = forward;
        // get every "row" element from this.rows and make a new tbody
        var newBody = TBODY(null, map(itemgetter("row"), this.rows));
        // swap in the new tbody
        this.tbody = swapDOM(this.tbody, newBody);
        for (var i = 0; i < this.columns.length; i++) {
            var col = this.columns[i];
            var node = col.proto.cloneNode(true);
            // remove the existing events to minimize IE leaks
            col.element.onclick = null;
            col.element.onmousedown = null;
            col.element.onmouseover = null;
            col.element.onmouseout = null;
            // set new events for the new node
            node.onclick = this.onSortClick(i);
            node.onmousedown = ignoreEvent;
            node.onmouseover = mouseOverFunc;
            node.onmouseout = mouseOutFunc;
            // if this is the sorted column
            if (key == i) {
                // \u2193 is down arrow, \u2191 is up arrow
                // forward sorts mean the rows get bigger going down
                var arrow = (forward ? "\u2193" : "\u2191");
                // add the character to the column header
                node.appendChild(SPAN(null, arrow));
                if (clicked) {
                    node.onmouseover();
                }
            }
 
            // swap in the new th
            col.element = swapDOM(col.element, node);
        }
    }
});

sortableManager = new SortableManager();

addLoadEvent(function () {
    sortableManager.initWithTable('sortable_table');
});

// rewrite the view-source links
addLoadEvent(function () {
    var elems = getElementsByTagAndClassName("A", "view-source");
    var page = "sortable_tables/";
    for (var i = 0; i < elems.length; i++) {
        var elem = elems[i];
        var href = elem.href.split(/\//).pop();
        elem.target = "_blank";
        elem.href = "../view-source/view-source.html#" + page + href;
    }
});


--- NEW FILE style.js ---
// getElementDimensions, getElementPosition

function updateStatus() {
    var e = getElement("thetestelem");
    
    var dim = getElementDimensions(e);
    var pos = getElementPosition(e);
    
    getElement("dimensions").innerHTML = repr(dim);
    getElement("coordinates").innerHTML = repr(pos);

    getElement("width").value = dim.w;
    getElement("height").value = dim.h;
    
    getElement("x").value = pos.x;
    getElement("y").value = pos.y;
}

// showElement and hideElement

function hideTheTestElem() {
    // Toggles our guinea testelem element
    
    var button = getElement("hidebutton");
    if (button.value == "Hide Element") {
        hideElement("thetestelem");
        button.value = "Show Element";
    } else {
        showElement("thetestelem");
        button.value = "Hide Element";
    }
    updateStatus();
}

// setElementDimensions

function setTestElemDimensions() {
    var e = getElement("thetestelem");
    var dim = new Dimensions(getElement("width").value,
                         getElement("height").value);
    setElementDimensions(e, dim);
    updateStatus();
}

// setElementPosition

function setTestElemPosition() {
    var e = getElement("thetestelem");
    var pos = new Coordinates(getElement("x").value,
                         getElement("y").value);
    setElementPosition(e, pos);
    updateStatus();
}

// setOpacity

function setTestElemOpacity() {
    setOpacity("thetestelem", getElement("opacity").value);
}

// computedStyle

function getTestElemStyle() {
    var prop = getElement("testelemprop").value;
    var style = computedStyle("thetestelem", prop);
    getElement("testelemstyle").innerHTML = style;
}




More information about the scm-commits mailing list