/**
*	RECTANGULAR MARQUEE TOOL 
*	allow you select rectangles and operate with selected space.
*	
*	Requirements: Prototype Library version 1.5.0 and higher (http://prototype.conio.net/)
*	Author:	Koksharov Sergey (sergey@marqueetool.net)
*	Version: 2.0.0
*
*	RECTANGULAR MARQUEE TOOL is freely distributable 
*	under the terms of an MIT-style license.
*	For details, see information on web site: http://marqueetool.net/
*/

var Marquee = Class.create();
Marquee.prototype = {
    BASE: 1,
    MARQUEE: 2,
    OPACITY: 4,
    EDGE: 8,

    items: [],
    options: {},
    maxZIndex: 1,
    ratio: 0,

    initialize: function(element) {
        this.onFinishDrag = this.finishDrag.bindAsEventListener(this);
        this.onUpdateDrag = this.updateDrag.bindAsEventListener(this);
        this.onWindResize = this.render.bindAsEventListener(this);
        this.onKeyPressed = this.keyPress.bindAsEventListener(this);

        Event.observe(document, "mouseup", this.onFinishDrag);
        Event.observe(document, "mousemove", this.onUpdateDrag);
        Event.observe(window, 'resize', this.onWindResize);

        if (element) {
            this.add(element, arguments[1]);
        };
    },

    add: function(element) {
        element = $(element);
        if (!element) return;

        var options = Object.extend({
            ratio: 0,
            preview: false,
            previewWidth: 120,
            previewHeight: 120,
            onUpdate: null,
            onBeforeUpdate: null,
            color: 'black',
            opacity: 0.75,
            type: 'crop', 	// window or crop, marquee or rect, other
            allowResize: true,
            allowHotKeys: true,
            hideEdges: false,
            coords: { x1: 0, y1: 0, x2: 0, y2: 0, width: 0, height: 0 }
        }, arguments[1] || {});
        var id = this.items.length;
        this.activeId = id;

        var landing = document.createElement('DIV');
        landing.className = "marquee-landing";
        landing.mtype = this.BASE;
        landing.id = 'rmt_landing_' + id;
        landing.onselectstart = this._bibb;

        var pos = Position.positionedOffset(element);

        Element.setStyle(landing, {
            width: element.offsetWidth + 'px',
            height: element.offsetHeight + 'px',
            zIndex: this.getMaxZIndex(),
            left: pos[0] + 'px',
            top: pos[1] + 'px'
        });

        var marquee = document.createElement('DIV');
        marquee.className = "marquee-element";
        marquee.mtype = this.MARQUEE;
        marquee.id = 'rmt_marquee_' + id;
        marquee.onselectstart = this._bibb;
        Element.hide(marquee);

        var wind = document.createElement('DIV');
        wind.className = "marquee-window";
        wind.id = 'rmt_window_' + id;
        wind.mtype = this.MARQUEE;
        wind.number = 5;
        wind.onselectstart = this._bibb;
        marquee.appendChild(wind);

        var o1 = document.createElement('DIV');
        o1.className = "marquee-opacity";
        o1.mtype = this.OPACITY;
        o1.onselectstart = this._bibb;
        var o2 = o1.cloneNode(true);
        o2.mtype = this.OPACITY;
        o2.onselectstart = this._bibb;
        Element.setStyle(o2, { left: 0 });

        var o3 = o1.cloneNode(true);
        o3.mtype = this.OPACITY;
        o3.onselectstart = this._bibb;
        Element.setStyle(o3, { right: 0 });

        var o4 = o1.cloneNode(true);
        o4.mtype = this.OPACITY;
        o4.onselectstart = this._bibb;
        Element.setStyle(o1, {
            top: 0,
            left: 0,
            width: "100%"
        });

        Element.setStyle(o4, {
            bottom: 0,
            left: 0,
            width: "100%"
        });

        marquee.o1 = o1;
        marquee.o2 = o2;
        marquee.o3 = o3;
        marquee.o4 = o4;

        var listener = document.createElement('INPUT');
        listener.className = "marquee-listener";
        listener.style.zIndex = this.getMaxZIndex();
        listener.onselectstart = this._bibb;
        listener.id = 'rmt_listener_' + id;
        Event.observe(listener, "keydown", this.onKeyPressed);

        var edge = document.createElement('DIV');
        edge.className = "marquee-edge";
        edge.onselectstart = this._bibb;

        var edge1 = edge.cloneNode(true);
        edge1.number = 1;
        edge1.mtype = this.EDGE;
        marquee.appendChild(edge1);
        Element.setStyle(edge1, { left: '0%', top: '0%', cursor: 'nw-resize' });
        var edge2 = edge.cloneNode(true);
        edge2.number = 2;
        edge2.mtype = this.EDGE;
        marquee.appendChild(edge2);
        Element.setStyle(edge2, { left: '50%', top: '0%', cursor: 'n-resize' });
        var edge3 = edge.cloneNode(true);
        edge3.number = 3;
        edge3.mtype = this.EDGE;
        marquee.appendChild(edge3);
        Element.setStyle(edge3, { left: '100%', top: '0%', cursor: 'ne-resize' });
        var edge4 = edge.cloneNode(true);
        edge4.number = 4;
        edge4.mtype = this.EDGE;
        marquee.appendChild(edge4);
        Element.setStyle(edge4, { left: '0%', top: '50%', cursor: 'w-resize' });
        var edge6 = edge.cloneNode(true);
        edge6.number = 6;
        edge6.mtype = this.EDGE;
        marquee.appendChild(edge6);
        Element.setStyle(edge6, { left: '100%', top: '50%', cursor: 'w-resize' });
        var edge7 = edge.cloneNode(true);
        edge7.mtype = this.EDGE;
        edge7.number = 7;
        marquee.appendChild(edge7);
        Element.setStyle(edge7, { left: '0%', top: '100%', cursor: 'ne-resize' });
        var edge8 = edge.cloneNode(true);
        edge8.number = 8;
        edge8.mtype = this.EDGE;
        Element.setStyle(edge8, { left: '50%', top: '100%', cursor: 'n-resize' });
        marquee.appendChild(edge8);
        var edge9 = edge.cloneNode(true);
        edge9.number = 9;
        edge9.mtype = this.EDGE;
        Element.setStyle(edge9, { left: '100%', top: '100%', cursor: 'nw-resize' });

        marquee.appendChild(edge9);
        marquee.number = 5;

        landing.appendChild(o1);
        landing.appendChild(o2);
        landing.appendChild(o3);
        landing.appendChild(o4);
        landing.appendChild(marquee);
        landing.appendChild(listener);
        element.parentNode.insertBefore(landing, element);

        var preview = $(options.preview);
        if (preview) {
            var pImage = new Image();
            pImage.src = element.tagName == 'IMG' ? element.src : element.style.backgroundImage;
            pImage.className = "marquee-preview";
            preview.appendChild(pImage);

            Element.setStyle(preview, {
                overflow: 'hidden',
                position: preview.style.position == 'absolute' ? 'absolute' : 'relative',
                width: 0, height: 0,
                fontSize: '1px', lineHeight: '0%'
            });
        };


        options.onLandClick = onLandClick;
        this.items.push({
            id: id,
            marquee: marquee,
            element: element,
            coords: options.coords,
            wind: wind,
            options: options,
            preview: preview,
            pImage: pImage,
            listener: listener,
            zIndex: this.getMaxZIndex()
        });

        this.setRatio(options.ratio);
        this.maxZIndex++;
        this.setOpacity(options.opacity);
        this.setColor(options.color);
        this.setType(options.type);
        if (options.hideEdges) this.hideEdges();
        if (options.coords.width || options.coords.x2)
            this.setCoords(
				options.coords.x1,
				options.coords.y1,
				options.coords.width ? options.coords.width : options.coords.x2 - options.coords.x1,
				options.coords.height ? options.coords.height : options.coords.y2 - options.coords.y1
			);

        var onLandClick = this.initDrag.bind(this, id);
        var onBeforeFocus = this.setFocus.bind(this, id);
        Event.observe(landing, 'mousedown', onLandClick);
        Event.observe(landing, 'mouseup', onBeforeFocus);
    },

    setFocus: function(id) {
        if (!this.getOption(id, 'allowHotKeys')) return;
        var listener = this.items[id].listener;
        listener.focus();
    },

    setRandomColor: function() {
        var numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
        var r1 = Math.round(Math.random() * 15);
        var r2 = Math.round(Math.random() * 15);
        var r3 = Math.round(Math.random() * 15);
        this.setColor('#' + numbers[r1] + numbers[r2] + numbers[r3]);
    },

    enable: function(id) {
        Event.observe(this.getMarquee(id).parentNode, "mousedown", this.getOption(id, 'onLandClick'));
    },

    disable: function(id) {
        Event.stopObserving(this.getMarquee(id).parentNode, "mousedown", this.getOption(id, 'onLandClick'));
    },

    getId: function() {
        return this.activeId;
    },

    accessResize: function(access, id) {
        access = (access == undefined) ? true : false;
        this.setOption(id, 'allowResize', access);
        if (access) this.showEdges(id); else this.hideEdges(id);
    },

    accessHotKeys: function(access, id) {
        access = (access == undefined) ? true : false;
        this.setOption(id, 'allowHotKeys', access);
    },

    getMaxZIndex: function() {
        return this.maxZIndex;
    },

    setRatio: function(ratio) {
        this.items[this.activeId].options.ratio = ratio;
        var marquee = this.items[this.activeId].marquee;
        if (!this.getOption(this.activeId, 'allowResize') || this.getOption(this.activeId, 'hideEdges')) return;
        $A(marquee.childNodes).each(function(item) {
            if (item.className && item.className == 'marquee-edge') {
                item.style.display = (item.number % 2 == 0) && ratio ? 'none' : 'block';
            };
        });
    },

    getRatio: function(id) {
        return this.ratio ? this.ratio : this.items[id || this.activeId].options.ratio;
    },

    initDrag: function(id, event) {
        event = event || window.event;
        if (!event) return;
        var element = Event.element(event);
        var marquee = this.getMarquee(id);
        if (!marquee || !element.mtype) return;

        var image = this.getElement(id);

        this.dragging = true;
        Position.prepare();
        Element.show(marquee);

        this.startPosition = Position.cumulativeOffset(image);
        this.startOffset = Position.positionedOffset(marquee);
        this.startDimension = Element.getDimensions(marquee);
        this.startMovingPoint = [Event.pointerX(event) - this.startPosition[0], Event.pointerY(event) - this.startPosition[1]];
        this.activeEdge = element.number;
        this.activeId = id;

        if (element.mtype & (this.OPACITY | this.BASE)) {
            this.startOffset = this.startMovingPoint;
        };

        Event.stop(event);
    },

    _bibb: function(event) {
        return false;
    },

    updateDrag: function(event) {
        if (!this.dragging) return;

        // fix for IE - onmousemove very frequent listening
        this._currentTime = new Date();
        if ((this._currentTime - this._lastUpdate) < 32) {
            return;
        };
        this._lastUpdate = new Date();

        var options = this.items[this.activeId].options;
        if (typeof options.onBeforeUpdate == 'function' && !options.onBeforeUpdate()) return;

        var ratio = this.getRatio();
        if (event.shiftKey && !ratio) {
            this.ratio = 1;
        };

        var pointer = [Event.pointerX(event) - this.startPosition[0], Event.pointerY(event) - this.startPosition[1]];
        var shifting = [pointer[0] - this.startMovingPoint[0], pointer[1] - this.startMovingPoint[1]];

        switch (this.activeEdge) {
            case 1:
                shifting = this.snap(shifting[0], shifting[1], 1);
                var newDimension = {
                    width: this.startDimension.width - shifting[0],
                    height: this.startDimension.height - shifting[1]
                };

                if (newDimension.width - 2 < 0)
                    shifting[0] += newDimension.width - 2;
                if (newDimension.height - 2 < 0)
                    shifting[1] += newDimension.height - 2;
                break;

            case 2:
                var newDimension = {
                    width: this.startDimension.width,
                    height: this.startDimension.height - shifting[1]
                };

                shifting[0] = 0;
                if (newDimension.height - 2 < 0)
                    shifting[1] += newDimension.height - 2;
                break;

            case 3:
                shifting = this.snap(shifting[0], shifting[1], -1);
                var newDimension = {
                    width: this.startDimension.width + shifting[0],
                    height: this.startDimension.height - shifting[1]
                };

                shifting[0] = 0;
                if (newDimension.width - 2 < 0)
                    shifting[0] += newDimension.width - 2;
                if (newDimension.height - 2 < 0)
                    shifting[1] += newDimension.height - 2;
                break;

            case 4:
                var newDimension = {
                    width: this.startDimension.width - shifting[0],
                    height: this.startDimension.height
                };

                shifting[1] = 0;
                if (newDimension.width - 2 < 0)
                    shifting[0] += newDimension.width - 2;
                break;

            case 6:
                var newDimension = {
                    width: this.startDimension.width + shifting[0],
                    height: this.startDimension.height
                };

                shifting[0] = 0;
                shifting[1] = 0;
                if (newDimension.width - 2 < 0)
                    shifting[0] += newDimension.width - 2;
                break;

            case 7:
                shifting = this.snap(shifting[0], shifting[1], -1);
                var newDimension = {
                    width: this.startDimension.width - shifting[0],
                    height: this.startDimension.height + shifting[1]
                };

                shifting[1] = 0;
                if (newDimension.width - 2 < 0)
                    shifting[0] += newDimension.width - 2;
                if (newDimension.height - 2 < 0)
                    shifting[1] += newDimension.height - 2;
                break;

            case 8:
                var newDimension = {
                    width: this.startDimension.width,
                    height: this.startDimension.height + shifting[1]
                };

                shifting[0] = 0;
                shifting[1] = 0;
                if (newDimension.height - 2 < 0)
                    shifting[1] += newDimension.height - 2;
                break;

            case 9:
                shifting = this.snap(shifting[0], shifting[1], 1);
                var newDimension = {
                    width: this.startDimension.width + shifting[0],
                    height: this.startDimension.height + shifting[1]
                };

                shifting[0] = 0;
                shifting[1] = 0;
                if (newDimension.width - 2 < 0)
                    shifting[0] += newDimension.width - 2;
                if (newDimension.height - 2 < 0)
                    shifting[1] += newDimension.height - 2;
                break;

            case 5:
                var newDimension = {
                    width: this.startDimension.width,
                    height: this.startDimension.height
                };

                break;

            default:
                shifting = this.snap(shifting[0], shifting[1], (shifting[1] && shifting[0] / shifting[1] < 0 ? -1 : 1));
                if (!this.getOption(this.activeId, 'allowResize')) return;

                var newDimension = {
                    width: shifting[0],
                    height: shifting[1]
                };

                if (newDimension.width - 2 >= 0)
                    shifting[0] = 0;
                if (newDimension.height - 2 >= 0)
                    shifting[1] = 0;

                newDimension.width += 2;
                newDimension.height += 2;
        };

        newDimension.width -= 2;
        newDimension.height -= 2;

        if (this.activeEdge != 5) {
            var element = this.getElement(this.activeId);
            if (this.startOffset[0] + shifting[0] +
				newDimension.width > element.offsetWidth) {
                newDimension.width = element.offsetWidth -
				this.startOffset[0] - shifting[0];
                if (ratio) {
                    newDimension.height = newDimension.width / ratio;
                };
            } else if (this.startOffset[0] + shifting[0] -
				newDimension.width > element.offsetWidth) {
                newDimension.width = element.offsetWidth -
				this.startOffset[0] - this.startDimension.width;
                if (ratio) {
                    newDimension.height = newDimension.width / ratio;
                };
            } else if (this.startOffset[0] + shifting[0] < 0 && newDimension.width > 0) {
                newDimension.width = this.startOffset[0] + this.startDimension.width - 2;
                if (ratio) {
                    newDimension.height = newDimension.width / ratio;
                };
            } else if (this.startOffset[0] + shifting[0] < 0 && newDimension.width < 0) {
                newDimension.width = this.startOffset[0];
                if (ratio) {
                    newDimension.height = newDimension.width / ratio;
                };
            }

            if (this.startOffset[1] + shifting[1] +
				newDimension.height > element.offsetHeight) {
                newDimension.height = element.offsetHeight -
				this.startOffset[1];
                if (ratio) {
                    newDimension.width = newDimension.height * ratio;
                };
            } else if (this.startOffset[1] + shifting[1] -
				newDimension.height > element.offsetHeight) {
                newDimension.height = element.offsetHeight -
				this.startOffset[1] - this.startDimension.height;
                if (ratio) {
                    newDimension.width = newDimension.height * ratio;
                };
            } else if (this.startOffset[1] + shifting[1] < 0 && newDimension.height > 0) {
                newDimension.height = this.startOffset[1] + this.startDimension.height - 2;
                if (ratio) {
                    newDimension.width = newDimension.height * ratio;
                };
            } else if (this.startOffset[1] + shifting[1] < 0 && newDimension.height < 0) {
                newDimension.height = this.startOffset[1];
                if (ratio) {
                    newDimension.width = newDimension.height * ratio;
                };
            };
        };

        this.setCoords(
			this.startOffset[0] + shifting[0],
			this.startOffset[1] + shifting[1],
			newDimension.width,
			newDimension.height
		);

        if (event.shiftKey) {
            this.ratio = 0;
        };

        Event.stop(event);

        if (typeof options.onUpdate == 'function')
            options.onUpdate();
    },

    setOpacity: function(value) {
        var item = this.items[this.activeId];
        Element.setOpacity(item.wind, value);
        Element.setOpacity(item.marquee.o1, value);
        Element.setOpacity(item.marquee.o2, value);
        Element.setOpacity(item.marquee.o3, value);
        Element.setOpacity(item.marquee.o4, value);
        this.setOption(item.id, 'opacity', value);
    },

    setColor: function(color) {
        var item = this.items[this.activeId];
        color = color || item.color;
        this.items[this.activeId].color = color;

        if (item.type == 'crop' || item.type == 'window') {
            Element.setStyle(item.marquee.o1, { backgroundColor: color });
            Element.setStyle(item.marquee.o2, { backgroundColor: color });
            Element.setStyle(item.marquee.o3, { backgroundColor: color });
            Element.setStyle(item.marquee.o4, { backgroundColor: color });
            Element.setStyle(item.wind, { backgroundColor: '' });
        } else if (item.type == 'rect' || item.type == 'marquee') {
            Element.setStyle(item.wind, { backgroundColor: color });
            Element.setStyle(item.marquee.o1, { backgroundColor: '' });
            Element.setStyle(item.marquee.o2, { backgroundColor: '' });
            Element.setStyle(item.marquee.o3, { backgroundColor: '' });
            Element.setStyle(item.marquee.o4, { backgroundColor: '' });
        } else {
            Element.setStyle(item.wind, { backgroundColor: '' });
            Element.setStyle(item.marquee.o1, { backgroundColor: '' });
            Element.setStyle(item.marquee.o2, { backgroundColor: '' });
            Element.setStyle(item.marquee.o3, { backgroundColor: '' });
            Element.setStyle(item.marquee.o4, { backgroundColor: '' });
        };
    },

    keyPress: function(event) {
        var key = event.keyCode || event.which || event.button;

        switch (key) {
            case 27:
                // escape
                this.unselectAll();
                break;
            case 37:
                // left arrow
                this.moveLeft(event.shiftKey ? 10 : 1, event.ctrlKey);
                break;
            case 38:
                // top arrow
                if (event.altKey) {
                    var opacity = this.getOption(this.activeId, 'opacity');
                    this.setOpacity(opacity < 0.95 ? opacity + 0.05 : 1);
                } else {
                    this.moveTop(event.shiftKey ? 10 : 1, event.ctrlKey);
                };
                break;
            case 39:
                // right arrow
                this.moveRight(event.shiftKey ? 10 : 1, event.ctrlKey);
                break;
            case 40:
                // down arrow
                if (event.altKey) {
                    var opacity = this.getOption(this.activeId, 'opacity');
                    this.setOpacity(opacity > 0.05 ? opacity - 0.05 : 0);
                } else {
                    this.moveBottom(event.shiftKey ? 10 : 1, event.ctrlKey);
                };
                break;
            case 65:
                // a - select all
                this.selectAll();
                break;
            case 69:
                // e - edges switching
                this.switchEdges();
                break;

            case 73:
                // i - inverse opacity type (selection)
                this.inverse();
                break;
            case 78:
                // n - new
                if (event.shiftKey)
                    this.add(this.getElement(), this.items[this.activeId].options);
                break;
            case 90:
                // z - zoom
                this.zoom(event.shiftKey ? 10 : 1, event.ctrlKey);
                break;
            case 82:
                // r - random color
                this.setRandomColor();
                break;
            case 83:
                // s - select next
                this.select();
                break;
            case 49: case 50: case 51:
            case 52: case 53: case 54:
            case 55: case 56: case 57: case 48:
                // numbers
                if (event.shiftKey) {
                    var colors = ['00f', '000', 'ffc', 'cfc', '0f0', '0ff', 'f00', 'f0f', 'ff0', 'fff'];
                    this.setColor('#' + colors[key - 48]);
                };
                break;
        }
    },

    setType: function(type) {
        this.items[this.activeId].type = type;
        this.setColor();
    },

    getType: function(id) {
        return this.items[id || this.activeId].type;
    },

    snap: function(x, y, k) {
        var ratio = this.getRatio();
        return ratio ? [y * ratio * k, y] : [x, y];
    },

    getWindow: function(id) {
        return this.items[id || this.activeId].wind;
    },

    getMarquee: function(id) {
        return this.items[id || this.activeId].marquee;
    },

    getElement: function(id) {
        return this.items[id || this.activeId].element;
    },

    getCoords: function(id) {
        return this.items[id || this.activeId].coords;
    },

    moveRight: function(amount, ctrlKey) {
        var coords = this.getCoords();
        this.setCoords(
			ctrlKey ? coords.x1 : coords.x1 + amount, coords.y1,
			ctrlKey ? coords.width + amount : coords.width, coords.height
		);
    },

    moveLeft: function(amount, ctrlKey) {
        var coords = this.getCoords();
        this.setCoords(
			ctrlKey ? coords.x1 : coords.x1 - amount, coords.y1,
			ctrlKey ? coords.width - amount : coords.width, coords.height
		);
    },

    moveTop: function(amount, ctrlKey) {
        var coords = this.getCoords();
        this.setCoords(
			coords.x1, ctrlKey ? coords.y1 : coords.y1 - amount,
			coords.width, ctrlKey ? coords.height - amount : coords.height
		);
    },

    moveBottom: function(amount, ctrlKey) {
        var coords = this.getCoords();
        this.setCoords(
			coords.x1, ctrlKey ? coords.y1 : coords.y1 + amount,
			coords.width, ctrlKey ? coords.height + amount : coords.height
		);
    },

    zoom: function(amount, ctrlKey) {
        var coords = this.getCoords();
        var k = ctrlKey ? 1 : -1;
        this.setCoords(
			coords.x1 + k * amount, coords.y1 + k * amount,
			coords.width - 2 * k * amount, coords.height - 2 * k * amount
		);
    },

    inverse: function() {
        var curr = this.getType();
        this.setType(curr == 'window' || curr == 'crop' ? 'rect' : 'crop');
    },

    unselectAll: function() {
        this.setCoords(0, 0, 0, 0);
        this.hideEdges();
    },

    selectAll: function() {
        var element = this.getElement();
        this.setCoords(0, 0, element.offsetWidth, element.offsetHeight);
        this.showEdges();
    },

    switchEdges: function() {
        var id = this.activeId;
        var edges = this.getOption(id, 'hideEdges');
        this.setOption(id, 'hideEdges', !edges);
        if (edges)
            this.showEdges();
        else
            this.hideEdges();
    },

    showEdges: function(id) {
        if (!this.getOption(id, 'allowResize') || this.getOption(id, 'hideEdges')) return;
        var marquee = this.getMarquee(id);
        $A(marquee.childNodes).each(function(item) {
            if (item.className && item.className == 'marquee-edge') {
                Element.setStyle(item, { display: '' });
            };
        });
    },

    hideEdges: function(id) {
        var marquee = this.getMarquee(id);
        $A(marquee.childNodes).each(function(item) {
            if (item.className && item.className == 'marquee-edge') {
                Element.setStyle(item, { display: 'none' });
            };
        });
    },

    select: function(id) {
        var currentObj = this.items[this.activeId];

        if (this.items[id]) {
            this.activeId = id;
        } else {
            var ids = [], max = 0, current = 0;
            $A(this.items).each((function(item) {
                if (item.id > max) max = item.id;
                if (this.activeId == item.id) current = ids.length;
                ids.push(item.id);
            }).bind(this));

            if (ids.length > 1) {
                this.activeId = (max == this.activeId) ? ids[0] : ids[current + 1];
            };
        };

        if (this.activeId !== id && this.items.length > 1) {
            var newObj = this.items[this.activeId];
            var maxz = currentObj.zIndex;

            this.items[currentObj.id].zIndex = newObj.zIndex;
            Element.setStyle(this.items[currentObj.id].marquee.parentNode, { zIndex: newObj.zIndex });

            var marquee = this.getMarquee();
            var wind = this.getWindow();
            this.items[this.activeId].zIndex = maxz;
            Element.setStyle(marquee.parentNode, { zIndex: maxz });
            Element.setStyle(wind, { border: '2px solid black' });
            setTimeout(function() { Element.setStyle(wind, { border: '' }); }, 250);
        };
    },

    hide: function(id) {
        var marquee = this.getMarquee(id);
        Element.hide(marquee.parentNode);
        this.setOption(id, 'hidden', true);
    },

    show: function(id) {
        var marquee = this.getMarquee(id);
        Element.show(marquee.parentNode);
        this.setOption(id, 'hidden', false);
    },

    setOption: function(id, option, value) {
        this.items[id || this.activeId].options[option] = value;
    },

    getOption: function(id, option) {
        return this.items[id || this.activeId].options[option];
    },

    render: function(event) {
        if (this.activeId == undefined) return;
        var element = this.getElement();
        var marquee = this.getMarquee();

        var pos = Position.positionedOffset(element);
        Element.setStyle(marquee.parentNode, {
            width: element.offsetWidth + 'px',
            height: element.offsetHeight + 'px',
            left: pos[0] + 'px',
            top: pos[1] + 'px'
        });
    },

    snapRatio: function(w, h) {
        var ratio;
        if (ratio = this.getRatio()) {
            if (w < h) {
                h = Math.floor(w / ratio);
            } else {
                w = Math.floor(h * ratio);
            };
        };
        return [w, h];
    },

    setCoords: function(x, y, w, h) {
        w = Math.abs(w);
        h = Math.abs(h);
        if (x < 0) x = 0;
        if (y < 0) y = 0;

        var element = this.getElement();
        if (w > element.offsetWidth) w = element.offsetWidth;
        if (h > element.offsetHeight) h = element.offsetHeight;

        if (x + w > element.offsetWidth)
            x = element.offsetWidth - w;
        if (y + h > element.offsetHeight)
            y = element.offsetHeight - h;

        var snap = this.snapRatio(w, h);
        w = snap[0]; h = snap[1];

        this.items[this.activeId].coords = {
            x1: x, y1: y,
            x2: x + w, y2: y + h,
            width: w, height: h
        };

        var marquee = this.getMarquee(this.activeId);
        Element.setStyle(marquee, {
            width: w + 'px',
            height: h + 'px',
            left: x + 'px',
            top: y + 'px',
            display: 'block'
        });

        Element.setStyle(this.getWindow(this.activeId), {
            height: h + 'px'
        });

        Element.setStyle(marquee.o1, { height: y + 1 + 'px' });
        Element.setStyle(marquee.o2, { height: h + 'px', width: x + 'px', top: y + 1 + 'px' });
        Element.setStyle(marquee.o3, {
            height: h + 'px',
            width: ((tmp = element.offsetWidth - x - w - 1) > 0 ? tmp : 0) + 'px',
            top: y + 1 + 'px'
        });
        Element.setStyle(marquee.o4, {
            top: h + y + 1 + 'px',
            height: ((tmp = element.offsetHeight - y - h - 1) > 0 ? tmp : 0) + 'px'
        });

        // preview
        if (this.items[this.activeId].options.preview) {
            var pw = this.items[this.activeId].options.previewWidth;
            var ph = this.items[this.activeId].options.previewHeight;
            var r = Math.min(w ? pw / w : 0, h ? ph / h : 0);
            if (r > 1) r = 1;

            Element.setStyle(this.items[this.activeId].preview, {
                width: w * r + 'px',
                height: h * r + 'px'
            });

            Element.setStyle(this.items[this.activeId].pImage, {
                width: this.items[this.activeId].element.offsetWidth * r + 'px',
                height: this.items[this.activeId].element.offsetHeight * r + 'px',
                left: -x * r + 'px',
                top: -y * r + 'px'
            });
        };

    },

    finishDrag: function() {
        if (!this.dragging) return;
        this.dragging = false;
        this.setRatio(this.getRatio());
        myMove();
    },

    setOnUpdateCallback: function(callback) {
        if (this.activeId == undefined) return;
        this.setOption(this.activeId, 'onUpdate', callback);
    },

    setOnBeforeUpdateCallback: function(callback) {
        if (this.activeId == undefined) return;
        this.setOption(this.activeId, 'onBeforeUpdate', callback);
    }
};

if (!Element.setOpacity) {
	Element.setOpacity = function(element, value) {
	  element= $(element);
		if (value == 1) {
			Element.setStyle(element, {
				opacity: (/Gecko/.test(navigator.userAgent) && 
						!/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : null 
			});
			
			if(/MSIE/.test(navigator.userAgent))  
				Element.setStyle(element, {
					filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')
				});
			
		} else {
				if(value < 0.00001) value = 0;
				Element.setStyle(element, {opacity: value});
				if(/MSIE/.test(navigator.userAgent))  
				Element.setStyle(element, { 
					filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + 'alpha(opacity='+value*100+')' 
				});
		};
	};
};

