/** * @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); } } })