/**
 * @description		prototype.js based context menu
 * @author        Juriy Zaytsev; kangax [at] gmail [dot] com; http://thinkweb2.com/projects/prototype/
 * @version       0.6
 * @date          12/03/07
 * @requires      prototype.js 1.6
*/

if (Object.isUndefined(Proto)) {
    var Proto = { }
}

Proto.Menu = Class.create({
    initialize: function() {
        var e = Prototype.emptyFunction;
        this.ie = Prototype.Browser.IE;
        this.options = Object.extend({
            selector: '.contextmenu',
            className: 'protoMenu',
            pageOffset: 25,
            fade: false,
            zIndex: 100,
            beforeShow: e,
            beforeHide: e,
            beforeSelect: e
        }, arguments[0] || { });

        this.shim = new Element('iframe', {
            style: 'position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);display:none',
            src: 'javascript:false;',
            frameborder: 0
        });

        this.options.fade = this.options.fade && !Object.isUndefined(Effect);
        this.container = new Element('div', {
            className: this.options.className,
            style: 'display:none'
        });
        var list = new Element('ul');
        this.options.menuItems.each(function(item) {
            list.insert(
                new Element('li', {
                    className: item.separator ? 'separator' : ''
                    }).insert(
                    item.separator
                    ? ''
                    : Object.extend(new Element('a', {
                        href: '#',
                        title: item.name,
                        className: (item.className || '') + (item.disabled ? ' disabled' : ' enabled')
                    }), {
                        _callback: item.callback
                    })
                    .observe('click', this.onClick.bind(this))
                    .observe('contextmenu', Event.stop)
                    .update(item.name)
                    )
                )
        }.bind(this));
        $(document.body).insert(this.container.insert(list).observe('contextmenu', Event.stop));
        if (this.ie) {
            $(document.body).insert(this.shim)
        }

        document.observe('click', function(e) {
            if (this.container.visible() && !e.isRightClick()) {
                this.options.beforeHide(e);
                if (this.ie) this.shim.hide();
                this.container.hide();
            }
        }.bind(this));

        $$(this.options.selector).invoke('observe', Prototype.Browser.Opera ? 'click' : 'contextmenu', function(e){
            if (Prototype.Browser.Opera && !e.ctrlKey) {
                return;
            }
            this.show(e);
        }.bind(this));
    },
    show: function(e) {
        e.stop();
        this.options.beforeShow(e);
        var x = Event.pointer(e).x,
        y = Event.pointer(e).y,
        vpDim = document.viewport.getDimensions(),
        vpOff = document.viewport.getScrollOffsets(),
        elDim = this.container.getDimensions(),
        elOff = {
            left: ((x + elDim.width + this.options.pageOffset) > vpDim.width
                ? (vpDim.width - elDim.width - this.options.pageOffset) : x) + 'px',
            top: ((y - vpOff.top + elDim.height) > vpDim.height && (y - vpOff.top) > elDim.height
                ? (y - elDim.height) : y) + 'px'
        };
        this.container.setStyle(elOff).setStyle({
            zIndex: this.options.zIndex
            });
        if (this.ie) {
            this.shim.setStyle(Object.extend(Object.extend(elDim, elOff), {
                zIndex: this.options.zIndex - 1
                })).show();
        }
        this.options.fade ? Effect.Appear(this.container, {
            duration: 0.25
        }) : this.container.show();
        this.event = e;
    },
    onClick: function(e) {
        e.stop();
        if (e.target._callback && !e.target.hasClassName('disabled')) {
            this.options.beforeSelect(e);
            if (this.ie) this.shim.hide();
            this.container.hide();
            e.target._callback(this.event);
        }
    }
})
