188 lines
7.2 KiB
JavaScript
188 lines
7.2 KiB
JavaScript
/*****************************************************************************
|
|
*
|
|
* Copyright (c) 2003-2005 Kupu Contributors. All rights reserved.
|
|
*
|
|
* This software is distributed under the terms of the Kupu
|
|
* License. See LICENSE.txt for license text. For a list of Kupu
|
|
* Contributors see CREDITS.txt.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
// $Id: kupucontextmenu.js 9879 2005-03-18 12:04:00Z yuppie $
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// ContextMenu
|
|
//----------------------------------------------------------------------------
|
|
|
|
function ContextMenu() {
|
|
/* the contextmenu */
|
|
this.contextmenu = null;
|
|
this.seperator = 1;
|
|
|
|
this.initialize = function(editor) {
|
|
/* set the event handlers and such */
|
|
this.editor = editor;
|
|
// needs some work since it won't work for more than one editor
|
|
addEventHandler(this.editor.getInnerDocument(), "contextmenu", this.createContextMenu, this);
|
|
//addEventHandler(editor.getInnerDocument(), "focus", this.hideContextMenu, this);
|
|
addEventHandler(document, "focus", this.hideContextMenu, this);
|
|
addEventHandler(editor.getInnerDocument(), "mousedown", this.hideContextMenu, this);
|
|
addEventHandler(document, "mousedown", this.hideContextMenu, this);
|
|
};
|
|
|
|
this.createContextMenu = function(event) {
|
|
/* Create and show the context menu
|
|
|
|
The method will ask all tools for any (optional) elements they
|
|
want to add the menu and when done render it
|
|
*/
|
|
if (event.stopPropagation) {
|
|
event.stopPropagation();
|
|
};
|
|
event.returnValue = false;
|
|
if (this.editor.getBrowserName() == 'IE') {
|
|
this.editor._saveSelection();
|
|
};
|
|
// somehow Mozilla on Windows seems to generate the oncontextmenu event
|
|
// several times on each rightclick, here's a workaround
|
|
if (this.editor.getBrowserName() == 'Mozilla' && this.contextmenu) {
|
|
return false;
|
|
};
|
|
this.hideContextMenu();
|
|
var selNode = this.editor.getSelectedNode();
|
|
var elements = new Array();
|
|
for (var id in this.editor.tools) {
|
|
var tool = this.editor.tools[id];
|
|
// alas, some people seem to want backward compatibility ;)
|
|
if (tool.createContextMenuElements) {
|
|
var els = tool.createContextMenuElements(selNode, event);
|
|
elements = elements.concat(els);
|
|
};
|
|
};
|
|
// remove the last seperator
|
|
this._createNewContextMenu(elements, event);
|
|
this.last_event = event;
|
|
return false;
|
|
};
|
|
|
|
this.hideContextMenu = function(event) {
|
|
/* remove the context menu from view */
|
|
if (this.contextmenu) {
|
|
try {
|
|
window.document.getElementsByTagName('body')[0].removeChild(this.contextmenu);
|
|
} catch (e) {
|
|
// after some commands, the contextmenu will be removed by
|
|
// the browser, ignore those cases
|
|
};
|
|
this.contextmenu = null;
|
|
};
|
|
};
|
|
|
|
this._createNewContextMenu = function(elements, event) {
|
|
/* add the elements to the contextmenu and show it */
|
|
var doc = window.document;
|
|
var menu = doc.createElement('div');
|
|
menu.contentEditable = false;
|
|
menu.designMode = 'Off';
|
|
this._setMenuStyle(menu);
|
|
for (var i=0; i < elements.length; i++) {
|
|
var element = elements[i];
|
|
if (element !== this.seperator) {
|
|
var div = doc.createElement('div');
|
|
div.style.width = '100%';
|
|
var label = doc.createTextNode('\u00a0' + element.label);
|
|
div.appendChild(label);
|
|
menu.appendChild(div);
|
|
// set a reference to the div on the element
|
|
element.element = div;
|
|
addEventHandler(div, "mousedown", element.action, element.context);
|
|
addEventHandler(div, "mouseover", element.changeOverStyle, element);
|
|
addEventHandler(div, "mouseout", element.changeNormalStyle, element);
|
|
addEventHandler(div, "mouseup", this.hideContextMenu, this);
|
|
} else {
|
|
var hr = doc.createElement('hr');
|
|
menu.appendChild(hr);
|
|
};
|
|
};
|
|
// now move the menu to the right position
|
|
var iframe = this.editor.getDocument().getEditable();
|
|
var left = event.clientX;
|
|
var top = event.clientY;
|
|
var currnode = iframe;
|
|
if (this.editor.getBrowserName() == 'IE') {
|
|
while (currnode) {
|
|
left += currnode.offsetLeft + currnode.clientLeft;
|
|
top += currnode.offsetTop + currnode.clientTop;
|
|
currnode = currnode.offsetParent;
|
|
};
|
|
} else {
|
|
while (currnode) {
|
|
left += currnode.offsetLeft;
|
|
top += currnode.offsetTop;
|
|
currnode = currnode.offsetParent;
|
|
};
|
|
};
|
|
menu.style.left = left + 'px';
|
|
menu.style.top = top + 'px';
|
|
menu.style.visibility = 'visible';
|
|
addEventHandler(menu, 'focus', function() {this.blur}, menu)
|
|
doc.getElementsByTagName('body')[0].appendChild(menu);
|
|
this.contextmenu = menu;
|
|
};
|
|
|
|
this._setMenuStyle = function(menu) {
|
|
/* set the styles for the menu
|
|
|
|
to change the menu style, override this method
|
|
*/
|
|
menu.style.position = 'absolute';
|
|
menu.style.backgroundColor = 'white';
|
|
menu.style.fontFamily = 'Verdana, Arial, Helvetica, sans-serif';
|
|
menu.style.fontSize = '12px';
|
|
menu.style.lineHeight = '16px';
|
|
menu.style.borderWidth = '1px';
|
|
menu.style.borderStyle = 'solid';
|
|
menu.style.borderColor = 'black';
|
|
menu.style.cursor = 'default';
|
|
menu.style.width = "8em";
|
|
};
|
|
|
|
this._showOriginalMenu = function(event) {
|
|
window.document.dispatchEvent(this._last_event);
|
|
};
|
|
};
|
|
|
|
function ContextMenuElement(label, action, context) {
|
|
/* context menu element struct
|
|
|
|
should be returned (optionally in a list) by the tools'
|
|
createContextMenuElements methods
|
|
*/
|
|
this.label = label; // the text shown in the menu
|
|
this.action = action; // a reference to the method that should be called
|
|
this.context = context; // a reference to the object on which the method
|
|
// is defined
|
|
this.element = null; // the contextmenu machinery will add a reference
|
|
// to the element here
|
|
|
|
this.changeOverStyle = function(event) {
|
|
/* set the background of the element to 'mouseover' style
|
|
|
|
override only for the prototype, not for individual elements
|
|
so every element looks the same
|
|
*/
|
|
this.element.style.backgroundColor = 'blue';
|
|
};
|
|
|
|
this.changeNormalStyle = function(event) {
|
|
/* set the background of the element back to 'normal' style
|
|
|
|
override only for the prototype, not for individual elements
|
|
so every element looks the same
|
|
*/
|
|
this.element.style.backgroundColor = 'white';
|
|
};
|
|
};
|
|
|