Project

General

Profile

Bug #18769 ยป rtehtmlarea_bugfix_8368_v2.patch

Administrator Admin, 2008-06-28 15:42

View differences:

typo3/sysext/rtehtmlarea/class.tx_rtehtmlarea_base.php (working copy)
'redo' => 'Redo',
);
var $pluginList = 'ContextMenu';
var $pluginList;
var $pluginButton = array();
var $pluginLabel = array();
......
// htmlArea plugins list
$this->pluginEnabledArray = t3lib_div::trimExplode(',', $this->pluginList, 1);
$this->enableRegisteredPlugins();
$hidePlugins = array();
if ($this->client['BROWSER'] == 'msie') {
$this->thisConfig['keepButtonGroupTogether'] = 0;
}
if ($this->client['BROWSER'] == 'opera') {
$hidePlugins[] = 'ContextMenu';
$this->thisConfig['keepButtonGroupTogether'] = 0;
}
if ($this->client['BROWSER'] == 'gecko' && $this->client['VERSION'] == '1.3') {
$this->thisConfig['keepButtonGroupTogether'] = 0;
}
$this->pluginEnabledArray = array_diff($this->pluginEnabledArray, $hidePlugins);
// Toolbar
$this->setToolbar();
......
// Process overrides
$hidePlugins = array();
foreach ($this->registeredPlugins as $pluginId => $plugin) {
if (!$this->pluginButton[$pluginId]) {
if ($plugin->addsButtons() && !$this->pluginButton[$pluginId]) {
$hidePlugins[] = $pluginId;
}
}
......
* Disable some plugins
*
*/
function setPlugins() {
global $TYPO3_CONF_VARS;
$hideButtons = array();
// Disabling the plugins if their buttons are not in the toolbar
// Disabling a plugin that adds buttons if none of its buttons is in the toolbar
$hidePlugins = array();
foreach ($this->pluginButton as $pluginId => $buttonList) {
$showPlugin = false;
$buttonArray = t3lib_div::trimExplode(',', $buttonList, 1);
foreach ($buttonArray as $button) {
if (in_array($button, $this->toolbar)) {
$showPlugin = true;
if ($this->registeredPlugins[$pluginId]->addsButtons()) {
$showPlugin = false;
$buttonArray = t3lib_div::trimExplode(',', $buttonList, 1);
foreach ($buttonArray as $button) {
if (in_array($button, $this->toolbar)) {
$showPlugin = true;
}
}
if (!$showPlugin) {
$hidePlugins[] = $pluginId;
}
}
if (!$showPlugin) {
$hidePlugins[] = $pluginId;
}
}
if ($this->thisConfig['disableContextMenu'] || $this->thisConfig['disableRightClick']) $hidePlugins[] = 'ContextMenu';
$this->pluginEnabledArray = array_diff($this->pluginEnabledArray, $hidePlugins);
// Hiding labels of disabled plugins
$hideLabels = array();
foreach ($this->pluginLabel as $pluginId => $label) {
if (!$this->isPluginEnabled($pluginId)) {
$hideButtons[] = $label;
$hideLabels[] = $label;
}
}
$this->toolbar = array_diff($this->toolbar, $hideButtons);
$this->toolbar = array_diff($this->toolbar, $hideLabels);
// Completing the toolbar converion array for htmlArea
foreach ($this->registeredPlugins as $pluginId => $plugin) {
typo3/sysext/rtehtmlarea/class.tx_rtehtmlareaapi.php (working copy)
protected $LOCAL_LANG; // Frontend language array
protected $pluginButtons = ''; // The comma-separated list of button names that the registered plugin is adding to the htmlArea RTE toolbar
protected $pluginLabels = ''; // The comma-separated list of label names that the registered plugin is adding to the htmlArea RTE toolbar
protected $pluginAddsButtons = true; // Boolean indicating whether the plugin is adding buttons or not
protected $convertToolbarForHtmlAreaArray = array(); // The name-converting array, converting the button names used in the RTE PageTSConfing to the button id's used by the JS scripts
protected $requiresClassesConfiguration = false; // True if the registered plugin requires the PageTSConfig Classes configuration
......
$this->thisConfig =& $this->htmlAreaRTE->thisConfig;
$this->toolbar =& $this->htmlAreaRTE->toolbar;
$this->LOCAL_LANG =& $this->htmlAreaRTE->LOCAL_LANG;
// Set the value of this boolean based on the initial value of $this->pluginButtons
$this->pluginAddsButtons = !empty($this->pluginButtons);
// Check if the plugin should be disabled in frontend
if ($this->htmlAreaRTE->is_FE() && $TYPO3_CONF_VARS['EXTCONF'][$this->rteExtensionKey]['plugins'][$this->pluginName]['disableInFE']) {
......
public function getPathToPluginDirectory() {
return ($this->relativePathToPluginDirectory ? $this->htmlAreaRTE->httpTypo3Path . t3lib_extMgm::siteRelPath($this->extensionKey) . $this->relativePathToPluginDirectory : '');
}
/**
* Returns a boolean indicating whether the plugin adds buttons or not to the toolbar
*
* @return boolean
*/
public function addsButtons() {
return $this->pluginAddsButtons;
}
/**
* Returns the list of buttons implemented by the plugin
typo3/sysext/rtehtmlarea/ext_localconf.php (working copy)
$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['AboutEditor']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/AboutEditor/class.tx_rtehtmlarea_abouteditor.php:&tx_rtehtmlarea_abouteditor';
$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['AboutEditor']['addIconsToSkin'] = 0;
$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['AboutEditor']['disableInFE'] = 0;
$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['ContextMenu'] = array();
$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['ContextMenu']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php:&tx_rtehtmlarea_contextmenu';
$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['ContextMenu']['addIconsToSkin'] = 0;
$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['ContextMenu']['disableInFE'] = 0;
$_EXTCONF = unserialize($_EXTCONF); // unserializing the configuration so we can use it here:
typo3/sysext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php (revision 0)
<?php
/***************************************************************
* Copyright notice
*
* (c) 2008 Stanislas Rolland <typo3(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* About Editor plugin for htmlArea RTE
*
* @author Stanislas Rolland <typo3(arobas)sjbr.ca>
*
* TYPO3 SVN ID: $Id: class.tx_rtehtmlarea_abouteditor.php 2985 2008-01-31 11:37:57Z ingmars $
*
*/
require_once(t3lib_extMgm::extPath('rtehtmlarea').'class.tx_rtehtmlareaapi.php');
class tx_rtehtmlarea_contextmenu extends tx_rtehtmlareaapi {
protected $extensionKey = 'rtehtmlarea'; // The key of the extension that is extending htmlArea RTE
protected $pluginName = 'ContextMenu'; // The name of the plugin registered by the extension
protected $relativePathToLocallangFile = ''; // Path to this main locallang file of the extension relative to the extension dir.
protected $relativePathToSkin = ''; // Path to the skin (css) file relative to the extension dir.
protected $htmlAreaRTE; // Reference to the invoking object
protected $thisConfig; // Reference to RTE PageTSConfig
protected $toolbar; // Reference to RTE toolbar array
protected $LOCAL_LANG; // Frontend language array
protected $pluginButtons;
protected $convertToolbarForHtmlAreaArray = array ();
public function main($parentObject) {
return parent::main($parentObject) && !($this->htmlAreaRTE->client['BROWSER'] == 'opera' || $this->thisConfig['disableContextMenu'] || $this->thisConfig['disableRightClick']);
}
/**
* Return JS configuration of the htmlArea plugins registered by the extension
*
* @param integer Relative id of the RTE editing area in the form
*
* @return string JS configuration for registered plugins
*
* The returned string will be a set of JS instructions defining the configuration that will be provided to the plugin(s)
* Each of the instructions should be of the form:
* RTEarea['.$RTEcounter.']["buttons"]["button-id"]["property"] = "value";
*/
public function buildJavascriptConfiguration($RTEcounter) {
$registerRTEinJavascriptString = '';
return $registerRTEinJavascriptString;
}
} // end of class
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php']);
}
?>
typo3/sysext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php (revision 0)
<?php
/***************************************************************
* Copyright notice
*
* (c) 2008 Stanislas Rolland <typo3(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the Typo3 project. The Typo3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* About Editor plugin for htmlArea RTE
*
* @author Stanislas Rolland <typo3(arobas)sjbr.ca>
*
* TYPO3 SVN ID: $Id: class.tx_rtehtmlarea_abouteditor.php 2985 2008-01-31 11:37:57Z ingmars $
*
*/
require_once(t3lib_extMgm::extPath('rtehtmlarea').'class.tx_rtehtmlareaapi.php');
class tx_rtehtmlarea_contextmenu extends tx_rtehtmlareaapi {
protected $extensionKey = 'rtehtmlarea'; // The key of the extension that is extending htmlArea RTE
protected $pluginName = 'ContextMenu'; // The name of the plugin registered by the extension
protected $relativePathToLocallangFile = ''; // Path to this main locallang file of the extension relative to the extension dir.
protected $relativePathToSkin = ''; // Path to the skin (css) file relative to the extension dir.
protected $htmlAreaRTE; // Reference to the invoking object
protected $thisConfig; // Reference to RTE PageTSConfig
protected $toolbar; // Reference to RTE toolbar array
protected $LOCAL_LANG; // Frontend language array
protected $pluginButtons;
protected $convertToolbarForHtmlAreaArray = array ();
public function main($parentObject) {
return parent::main($parentObject) && !($this->htmlAreaRTE->client['BROWSER'] == 'opera' || $this->thisConfig['disableContextMenu'] || $this->thisConfig['disableRightClick']);
}
/**
* Return JS configuration of the htmlArea plugins registered by the extension
*
* @param integer Relative id of the RTE editing area in the form
*
* @return string JS configuration for registered plugins
*
* The returned string will be a set of JS instructions defining the configuration that will be provided to the plugin(s)
* Each of the instructions should be of the form:
* RTEarea['.$RTEcounter.']["buttons"]["button-id"]["property"] = "value";
*/
public function buildJavascriptConfiguration($RTEcounter) {
$registerRTEinJavascriptString = '';
return $registerRTEinJavascriptString;
}
} // end of class
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php']);
}
?>
typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js (working copy)
HTMLArea.allElementsAreDisplayed = function(elements) {
for (var i=0, length=elements.length; i < length; i++) {
if (document.getElementById(elements[i]).style.display == 'none') {
if (document.getElementById(elements[i]).style.display == "none" || elements[i]).style.display == "") {
return false;
}
}
typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/context-menu.js (working copy)
* Copyright notice
*
* Copyright (c) 2003 dynarch.com. Authored by Mihai Bazon. Sponsored by www.americanbible.org.
* Copyright (c) 2004-2008 Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
* Copyright (c) 2004-2008 Stanislas Rolland <typo3(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
......
* TYPO3 SVN ID: $Id$
*/
ContextMenu = function(editor) {
this.editor = editor;
this.currentMenu = null;
this.keys = [];
this.eventHandlers = {};
};
ContextMenu.I18N = ContextMenu_langArray;
ContextMenu._pluginInfo = {
name : "ContextMenu",
version : "1.9",
developer : "Mihai Bazon & Stanislas Rolland",
developer_url : "http://www.fructifor.ca/",
c_owner : "dynarch.com & Stanislas Rolland",
sponsor : "American Bible Society & Fructifor Inc.",
sponsor_url : "http://www.fructifor.ca/",
license : "GPL"
};
ContextMenu.prototype.onGenerate = function() {
if (!HTMLArea.is_opera) {
this.editor.eventHandlers["contextMenu"] = ContextMenu.contextMenuHandler(this);
HTMLArea._addEvent((HTMLArea.is_ie ? this.editor._doc.body : this.editor._doc), "contextmenu", this.editor.eventHandlers["contextMenu"]);
} else {
this.editor.eventHandlers["mousedown"] = ContextMenu.contextMenuHandler(this);
HTMLArea._addEvent(this.editor._doc, "mousedown", this.editor.eventHandlers["mousedown"]);
ContextMenu = HTMLArea.Plugin.extend({
constructor : function(editor, pluginName) {
this.base(editor, pluginName);
},
/*
* This function gets called by the class constructor
*/
configurePlugin : function(editor) {
this.currentMenu = null;
this.keys = [];
this.eventHandlers = {};
/*
* Registering plugin "About" information
*/
var pluginInformation = {
version : "2.0",
developer : "Mihai Bazon & Stanislas Rolland",
developerUrl : "http://www.sjbr.ca/",
copyrightOwner : "dynarch.com & Stanislas Rolland",
sponsor : "American Bible Society & SJBR",
sponsorUrl : "http://www.sjbr.ca/",
license : "GPL"
};
this.registerPluginInformation(pluginInformation);
return true;
},
/*
* This function gets called when the editor gets generated
*/
onGenerate : function() {
this.editor.eventHandlers["contextMenu"] = this.makeFunctionReference("popupMenu");
HTMLArea._addEvent((HTMLArea.is_ie ? this.editor._doc.body : this.editor._doc), (HTMLArea.is_opera ? "mousedown" : "contextmenu"), this.editor.eventHandlers["contextMenu"]);
},
popupMenu : function(ev, target) {
if (HTMLArea.is_opera && ev.button < 2) {
return false;
}
var editor = this.editor;
if (!ev) var ev = window.event;
if (!target) var target = (ev.target) ? ev.target : ev.srcElement;
if (this.currentMenu) this.currentMenu.parentNode.removeChild(this.currentMenu);
this.keys = [];
var ifpos = ContextMenu.getPos(this.editor._iframe);
var x = ev.clientX + ifpos.x;
var y = ev.clientY + ifpos.y;
var doc, list, separator = false;
if (!HTMLArea.is_ie) {
doc = document;
} else {
var popup = this.iePopup = window.createPopup();
doc = popup.document;
var head = doc.getElementsByTagName("head")[0];
var link = doc.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
if ( _editor_CSS.indexOf("http") == -1 ) link.href = _typo3_host_url + _editor_CSS;
else link.href = _editor_CSS;
head.appendChild(link);
}
list = doc.createElement("ul");
list.className = "htmlarea-context-menu";
doc.body.appendChild(list);
var options = this.getContextMenu(target);
var n = options.length;
for (var i=0; i < n; ++i) {
var option = options[i];
if (!option){
separator = true;
} else {
var item = doc.createElement("li");
list.appendChild(item);
var label = option[0];
if (separator) {
item.className += " separator";
separator = false;
}
item.__msh = {
item: item,
label: label,
action: option[1],
tooltip: option[2] || null,
icon: option[3] || null,
activate: ContextMenu.activateHandler(item, this),
cmd: option[4] || null
};
label = label.replace(/_([a-zA-Z0-9])/, "<u>$1</u>");
if (label != option[0]) this.keys.push([ RegExp.$1, item ]);
label = label.replace(/__/, "_");
var button = doc.createElement("button");
button.className = "button";
if(item.__msh.cmd) {
button.className += " " + item.__msh.cmd;
if(typeof(editor.plugins["TYPO3Browsers"]) != "undefined" && (item.__msh.cmd == "CreateLink" || item.__msh.cmd == "UnLink" || item.__msh.cmd == "InsertImage")) button.className += "-TYPO3Browsers";
button.innerHTML = label;
} else if(item.__msh.icon) {
button.innerHTML = "<img src='" + item.__msh.icon + "' />" + label;
} else {
button.innerHTML = label;
}
item.appendChild(button);
item.__msh.mouseover = ContextMenu.mouseOverHandler(editor, item);
HTMLArea._addEvent(item, "mouseover", item.__msh.mouseover);
item.__msh.mouseout = ContextMenu.mouseOutHandler(item);
HTMLArea._addEvent(item, "mouseout", item.__msh.mouseout);
item.__msh.contextmenu = ContextMenu.itemContextMenuHandler(item);
HTMLArea._addEvent(item, "contextmenu", item.__msh.contextmenu);
if(!HTMLArea.is_ie) {
item.__msh.mousedown = ContextMenu.mouseDownHandler(item);
HTMLArea._addEvent(item, "mousedown", item.__msh.mousedown);
}
item.__msh.mouseup = ContextMenu.mouseUpHandler(item, this);
HTMLArea._addEvent(item, "mouseup", item.__msh.mouseup);
}
}
if (n) {
if(!HTMLArea.is_ie) {
var dx = x + list.offsetWidth - window.innerWidth - window.pageXOffset + 4;
var dy = y + list.offsetHeight - window.innerHeight - window.pageYOffset + 4;
if(dx > 0) x -= dx;
if(dy > 0) y -= dy;
list.style.left = x + "px";
list.style.top = y + "px";
} else {
// determine the size
list.style.left = "0px";
list.style.top = "0px";
var foobar = document.createElement("ul");
foobar.className = "htmlarea-context-menu";
foobar.innerHTML = list.innerHTML;
editor._iframe.contentWindow.parent.document.body.appendChild(foobar);
this.iePopup.show(ev.screenX, ev.screenY, foobar.clientWidth+2, foobar.clientHeight+2);
editor._iframe.contentWindow.parent.document.body.removeChild(foobar);
}
this.currentMenu = list;
this.timeStamp = (new Date()).getTime();
this.eventHandlers["documentClick"] = this.makeFunctionReference("documentClickHandler");
HTMLArea._addEvent((HTMLArea.is_ie ? document.body : document), "mousedown", this.eventHandlers["documentClick"]);
HTMLArea._addEvent((HTMLArea.is_ie ? editor._doc.body : editor._doc), "mousedown", this.eventHandlers["documentClick"]);
if (this.keys.length > 0) {
this.eventHandlers["keyPress"] = ContextMenu.keyPressHandler(this);
HTMLArea._addEvents((HTMLArea.is_ie ? editor._doc.body : editor._doc), ["keypress", "keydown"], this.eventHandlers["keyPress"]);
}
}
HTMLArea._stopEvent(ev);
return false;
},
pushOperations : function (opcodes, elmenus, pluginId) {
var editor = this.editor;
var pluginInstance = this.editor.plugins[pluginId];
if (pluginInstance) {
pluginInstance = pluginInstance.instance;
}
var toolbarObjects = editor._toolbarObjects;
var btnList = editor.config.btnList;
var enabled = false, opcode, opEnabled = [], i = opcodes.length;
for (i; i > 0;) {
opcode = opcodes[--i];
opEnabled[opcode] = toolbarObjects[opcode] && toolbarObjects[opcode].enabled;
enabled = enabled || opEnabled[opcode];
}
if (enabled && elmenus.length) {
elmenus.push(null);
}
for (i = opcodes.length; i > 0;) {
opcode = opcodes[--i];
if (opEnabled[opcode]) {
switch (pluginId) {
case "TableOperations" :
elmenus.push([this.localize(opcode + "-title"),
ContextMenu.tableOperationsHandler(editor, pluginInstance, opcode),
this.localize(opcode + "-tooltip"),
btnList[opcode][1], opcode]);
break;
case "BlockElements" :
elmenus.push([this.localize(opcode + "-title"),
ContextMenu.blockElementsHandler(editor, null, opcode),
this.localize(opcode + "-tooltip"),
btnList[opcode][1], opcode]);
break;
default :
elmenus.push([this.localize(opcode + "-title"),
ContextMenu.execCommandHandler(editor, opcode),
this.localize(opcode + "-tooltip"),
btnList[opcode][1], opcode]);
break;
}
}
}
},
getContextMenu : function(target) {
var editor = this.editor;
var toolbarObjects = editor._toolbarObjects;
var config = editor.config;
var btnList = config.btnList;
var menu = [], opcode;
var tbo = this.editor.plugins["TableOperations"];
if (tbo) tbo = "TableOperations";
var selection = editor.hasSelectedText();
if(selection) {
if (toolbarObjects['Cut'] && toolbarObjects['Cut'].enabled) {
opcode = "Cut";
menu.push([this.localize(opcode), ContextMenu.execCommandHandler(editor, opcode), null, btnList[opcode][1], opcode]);
}
if (toolbarObjects['Copy'] && toolbarObjects['Copy'].enabled) {
opcode = "Copy";
menu.push([this.localize(opcode), ContextMenu.execCommandHandler(editor, opcode), null, btnList[opcode][1], opcode]);
}
}
if (toolbarObjects['Paste'] && toolbarObjects['Paste'].enabled) {
opcode = "Paste";
menu.push([this.localize(opcode), ContextMenu.execCommandHandler(editor, opcode), null, btnList[opcode][1], opcode]);
}
var currentTarget = target,
tmp, tag, link = false,
table = null, tr = null, td = null, img = null, list = null, div = null;
for(; target; target = target.parentNode) {
tag = target.nodeName;
if(!tag) continue;
tag = tag.toLowerCase();
switch (tag) {
case "img":
img = target;
if (toolbarObjects["InsertImage"] && toolbarObjects["InsertImage"].enabled) {
if (menu.length) menu.push(null);
menu.push(
[this.localize("Image Properties"),
ContextMenu.imageHandler(editor, img),
this.localize("Show the image properties dialog"),
btnList["InsertImage"][1], "InsertImage"]
);
}
break;
case "a":
link = target;
if (toolbarObjects["CreateLink"]) {
if (menu.length) menu.push(null);
menu.push(
[this.localize("Modify Link"),
this.linkHandler(link, "ModifyLink"),
this.localize("Current URL is") + ': ' + link.href,
btnList["CreateLink"][1], "CreateLink"],
[this.localize("Check Link"),
this.linkHandler(link, "CheckLink"),
this.localize("Opens this link in a new window"),
null, null],
[this.localize("Remove Link"),
this.linkHandler(link, "RemoveLink"),
this.localize("Unlink the current element"),
editor.imgURL("ed_unlink.gif"), "UnLink"]
);
}
break;
case "td":
case "th":
td = target;
if(!tbo) break;
this.pushOperations(["TO-cell-split", "TO-cell-delete", "TO-cell-insert-after", "TO-cell-insert-before", "TO-cell-prop"], menu, tbo);
break;
case "tr":
tr = target;
if(!tbo) break;
opcode = "TO-cell-merge";
if (toolbarObjects[opcode] && toolbarObjects[opcode].enabled) {
menu.push([this.localize(opcode + "-title"),
ContextMenu.tableOperationsHandler(editor, this.editor.plugins.TableOperations.instance, opcode),
this.localize(opcode + "-tooltip"),
btnList[opcode][1], opcode]);
}
this.pushOperations(["TO-row-split", "TO-row-delete", "TO-row-insert-under", "TO-row-insert-above", "TO-row-prop"], menu, tbo);
break;
case "table":
table = target;
if(!tbo) break;
this.pushOperations(["TO-col-split", "TO-col-delete", "TO-col-insert-after", "TO-col-insert-before", "TO-col-prop"], menu, tbo);
this.pushOperations(["TO-toggle-borders", "TO-table-restyle", "TO-table-prop"], menu, tbo);
break;
case "ol":
case "ul":
case "dl":
list = target;
break;
case "div":
div = target;
break;
case "body":
this.pushOperations(["JustifyFull", "JustifyRight", "JustifyCenter", "JustifyLeft"], menu, "BlockElements");
break;
}
}
if (selection && !link) {
if (menu.length) menu.push(null);
menu.push([this.localize("Make link"),
this.linkHandler(link, "MakeLink"),
this.localize("Create a link"),
btnList["CreateLink"][1],"CreateLink"]);
}
if (!/^(html|body)$/i.test(currentTarget.nodeName)) {
if (/^(table|thead|tbody|tr|td|th|tfoot)$/i.test(currentTarget.nodeName)) {
tmp = table;
table = null;
} else if(list) {
tmp = list;
list = null;
} else {
tmp = currentTarget;
}
if (menu.length) menu.push(null);
menu.push(
[this.localize("Remove the") + " &lt;" + tmp.tagName.toLowerCase() + "&gt; " + this.localize("Element"),
this.deleteElementHandler(tmp, table), this.localize("Remove this node from the document")],
[this.localize("Insert paragraph before"),
ContextMenu.blockElementsHandler(editor, tmp, "InsertParagraphBefore"), this.localize("Insert a paragraph before the current node"), null, "InsertParagraphBefore"],
[this.localize("Insert paragraph after"),
ContextMenu.blockElementsHandler(editor, tmp, "InsertParagraphAfter"), this.localize("Insert a paragraph after the current node"), null, "InsertParagraphAfter"]
);
}
return menu;
},
closeMenu : function() {
HTMLArea._removeEvent((HTMLArea.is_ie ? document.body : document), "mousedown", this.eventHandlers["documentClick"]);
HTMLArea._removeEvent((HTMLArea.is_ie ? this.editor._doc.body : this.editor._doc), "mousedown", this.eventHandlers["documentClick"]);
if (this.keys.length > 0) HTMLArea._removeEvent((HTMLArea.is_ie ? this.editor._doc.body : this.editor._doc), "keypress", this.eventHandlers["keyPress"]);
for (var handler in this.eventHandlers) this.eventHandlers[handler] = null;
var e, items = document.getElementsByTagName("li");
if (HTMLArea.is_ie) items = this.iePopup.document.getElementsByTagName("li");;
for (var i = items.length; --i >= 0 ;) {
e = items[i];
if ( e.__msh ) {
HTMLArea._removeEvent(e, "mouseover", e.__msh.mouseover);
e.__msh.mouseover = null;
HTMLArea._removeEvent(e, "mouseout", e.__msh.mouseout);
e.__msh.mouseout = null;
HTMLArea._removeEvent(e, "contextmenu", e.__msh.contextmenu);
e.__msh.contextmenu = null;
if (!HTMLArea.is_ie) HTMLArea._removeEvent(e, "mousedown", e.__msh.mousedown);
e.__msh.mousedown = null;
HTMLArea._removeEvent(e, "mouseup", e.__msh.mouseup);
e.__msh.mouseup = null;
e.__msh.action = null;
e.__msh.activate = null;
e.__msh = null;
}
}
this.currentMenu.parentNode.removeChild(this.currentMenu);
this.currentMenu = null;
this.keys = [];
if (HTMLArea.is_ie) this.iePopup.hide();
},
linkHandler : function (link, opcode) {
var editor = this.editor;
var self = this;
switch (opcode) {
case "MakeLink":
case "ModifyLink":
return (function() {
var obj = editor._toolbarObjects.CreateLink;
obj.cmd(editor, "CreateLink", link);
});
case "CheckLink":
return (function() {
window.open(link.href);
});
case "RemoveLink":
return (function() {
if (confirm(self.localize("Please confirm unlink") + "\n" +
self.localize("Link points to:") + " " + link.href)) {
var obj = editor._toolbarObjects.CreateLink;
obj.cmd(editor, "UnLink", link);
}
});
}
},
deleteElementHandler : function (tmp,table) {
var editor = this.editor;
var self = this;
return (function() {
if(confirm(self.localize("Please confirm remove") + " " + tmp.tagName.toLowerCase())) {
var el = tmp;
var p = el.parentNode;
p.removeChild(el);
if(HTMLArea.is_gecko) {
if(p.tagName.toLowerCase() == "td" && !p.hasChildNodes()) p.appendChild(editor._doc.createElement("br"));
editor.forceRedraw();
editor.focusEditor();
editor.updateToolbar();
if(table) {
var save_collapse = table.style.borderCollapse;
table.style.borderCollapse = "collapse";
table.style.borderCollapse = "separate";
table.style.borderCollapse = save_collapse;
}
}
}
});
},
documentClickHandler : function (ev) {
if (!ev) var ev = window.event;
if (!this.currentMenu) {
alert(this.localize("How did you get here? (Please report!)"));
return false;
}
var el = (ev.target) ? ev.target : ev.srcElement;
for (; el != null && el != this.currentMenu; el = el.parentNode);
if (el == null) {
this.closeMenu();
this.editor.updateToolbar();
}
}
};
});
ContextMenu.contextMenuHandler = function(instance) {
return (function(ev) {
if (!HTMLArea.is_opera || (HTMLArea.is_opera && ev.button >= 2)) instance.popupMenu(ev);
else return false;
});
};
ContextMenu.tableOperationsHandler = function(editor,tbo,opcode) {
return (function() {
tbo.onButtonPress(editor,opcode);
......
});
};
ContextMenu.linkHandler = function(editor, link, opcode) {
switch (opcode) {
case "MakeLink":
case "ModifyLink":
return (function() {
var obj = editor._toolbarObjects.CreateLink;
obj.cmd(editor, "CreateLink", link);
});
case "CheckLink":
return (function() {
window.open(link.href);
});
case "RemoveLink":
return (function() {
if (confirm(ContextMenu.I18N["Please confirm unlink"] + "\n" +
ContextMenu.I18N["Link points to:"] + " " + link.href)) {
var obj = editor._toolbarObjects.CreateLink;
obj.cmd(editor, "UnLink", link);
}
});
}
};
ContextMenu.execCommandHandler = function(editor,opcode) {
return (function() {
editor.execCommand(opcode);
......
});
};
ContextMenu.deleteElementHandler = function(editor,tmp,table) {
return (function() {
if(confirm(ContextMenu.I18N["Please confirm remove"] + " " + tmp.tagName.toLowerCase())) {
var el = tmp;
var p = el.parentNode;
p.removeChild(el);
if(HTMLArea.is_gecko) {
if(p.tagName.toLowerCase() == "td" && !p.hasChildNodes()) p.appendChild(editor._doc.createElement("br"));
editor.forceRedraw();
editor.focusEditor();
editor.updateToolbar();
if(table) {
var save_collapse = table.style.borderCollapse;
table.style.borderCollapse = "collapse";
table.style.borderCollapse = "separate";
table.style.borderCollapse = save_collapse;
}
}
}
});
};
ContextMenu.prototype.pushOperations = function(opcodes, elmenus, pluginId) {
var editor = this.editor;
var pluginInstance = this.editor.plugins[pluginId];
if (pluginInstance) {
pluginInstance = pluginInstance.instance;
}
var toolbarObjects = editor._toolbarObjects;
var i18n = ContextMenu.I18N;
var btnList = editor.config.btnList;
var enabled = false, opcode, opEnabled = [], i = opcodes.length;
for (i; i > 0;) {
opcode = opcodes[--i];
opEnabled[opcode] = toolbarObjects[opcode] && toolbarObjects[opcode].enabled;
enabled = enabled || opEnabled[opcode];
}
if (enabled && elmenus.length) elmenus.push(null);
for (i = opcodes.length; i > 0;) {
opcode = opcodes[--i];
if(opEnabled[opcode]) {
switch (pluginId) {
case "TableOperations" :
elmenus.push([i18n[opcode + "-title"],
ContextMenu.tableOperationsHandler(editor, pluginInstance, opcode),
i18n[opcode + "-tooltip"],
btnList[opcode][1], opcode]);
break;
case "BlockElements" :
elmenus.push([i18n[opcode + "-title"],
ContextMenu.blockElementsHandler(editor, null, opcode),
i18n[opcode + "-tooltip"],
btnList[opcode][1], opcode]);
break;
default :
elmenus.push([i18n[opcode + "-title"],
ContextMenu.execCommandHandler(editor, opcode),
i18n[opcode + "-tooltip"],
btnList[opcode][1], opcode]);
break;
}
}
}
};
ContextMenu.prototype.getContextMenu = function(target) {
var editor = this.editor;
var toolbarObjects = editor._toolbarObjects;
var i18n = ContextMenu.I18N;
var config = editor.config;
var btnList = config.btnList;
var menu = [], opcode;
var tbo = this.editor.plugins["TableOperations"];
if (tbo) tbo = "TableOperations";
var selection = editor.hasSelectedText();
if(selection) {
if (toolbarObjects['Cut'] && toolbarObjects['Cut'].enabled) {
opcode = "Cut";
menu.push([i18n[opcode], ContextMenu.execCommandHandler(editor, opcode), null, btnList[opcode][1], opcode]);
}
if (toolbarObjects['Copy'] && toolbarObjects['Copy'].enabled) {
opcode = "Copy";
menu.push([i18n[opcode], ContextMenu.execCommandHandler(editor, opcode), null, btnList[opcode][1], opcode]);
}
}
if (toolbarObjects['Paste'] && toolbarObjects['Paste'].enabled) {
opcode = "Paste";
menu.push([i18n[opcode], ContextMenu.execCommandHandler(editor, opcode), null, btnList[opcode][1], opcode]);
}
var currentTarget = target,
tmp, tag, link = false,
table = null, tr = null, td = null, img = null, list = null, div = null;
for(; target; target = target.parentNode) {
tag = target.nodeName;
if(!tag) continue;
tag = tag.toLowerCase();
switch (tag) {
case "img":
img = target;
if (toolbarObjects["InsertImage"] && toolbarObjects["InsertImage"].enabled) {
if (menu.length) menu.push(null);
menu.push(
[i18n["Image Properties"],
ContextMenu.imageHandler(editor, img),
i18n["Show the image properties dialog"],
btnList["InsertImage"][1], "InsertImage"]
);
}
break;
case "a":
link = target;
if (toolbarObjects["CreateLink"]) {
if (menu.length) menu.push(null);
menu.push(
[i18n["Modify Link"],
ContextMenu.linkHandler(editor, link, "ModifyLink"),
i18n["Current URL is"] + ': ' + link.href,
btnList["CreateLink"][1], "CreateLink"],
[i18n["Check Link"],
ContextMenu.linkHandler(editor, link, "CheckLink"),
i18n["Opens this link in a new window"],
null, null],
[i18n["Remove Link"],
ContextMenu.linkHandler(editor, link, "RemoveLink"),
i18n["Unlink the current element"],
editor.imgURL("ed_unlink.gif"), "UnLink"]
);
}
break;
case "td":
case "th":
td = target;
if(!tbo) break;
this.pushOperations(["TO-cell-split", "TO-cell-delete", "TO-cell-insert-after", "TO-cell-insert-before", "TO-cell-prop"], menu, tbo);
break;
case "tr":
tr = target;
if(!tbo) break;
opcode = "TO-cell-merge";
if(toolbarObjects[opcode] && toolbarObjects[opcode].enabled)
menu.push([i18n[opcode + "-title"],
ContextMenu.tableOperationsHandler(editor, this.editor.plugins.TableOperations.instance, opcode),
i18n[opcode + "-tooltip"],
btnList[opcode][1], opcode]);
this.pushOperations(["TO-row-split", "TO-row-delete", "TO-row-insert-under", "TO-row-insert-above", "TO-row-prop"], menu, tbo);
break;
case "table":
table = target;
if(!tbo) break;
this.pushOperations(["TO-col-split", "TO-col-delete", "TO-col-insert-after", "TO-col-insert-before", "TO-col-prop"], menu, tbo);
this.pushOperations(["TO-toggle-borders", "TO-table-restyle", "TO-table-prop"], menu, tbo);
break;
case "ol":
case "ul":
case "dl":
list = target;
break;
case "div":
div = target;
break;
case "body":
this.pushOperations(["JustifyFull", "JustifyRight", "JustifyCenter", "JustifyLeft"], menu, "BlockElements");
break;
}
}
if (selection && !link) {
if (menu.length) menu.push(null);
menu.push([i18n["Make link"],
ContextMenu.linkHandler(editor, link, "MakeLink"),
i18n["Create a link"],
btnList["CreateLink"][1],"CreateLink"]);
}
if (!/^(html|body)$/i.test(currentTarget.nodeName)) {
if (/^(table|thead|tbody|tr|td|th|tfoot)$/i.test(currentTarget.nodeName)) {
tmp = table;
table = null;
} else if(list) {
tmp = list;
list = null;
} else {
tmp = currentTarget;
}
if (menu.length) menu.push(null);
menu.push(
[i18n["Remove the"] + " &lt;" + tmp.tagName.toLowerCase() + "&gt; " + i18n["Element"],
ContextMenu.deleteElementHandler(editor, tmp, table), i18n["Remove this node from the document"]],
[i18n["Insert paragraph before"],
ContextMenu.blockElementsHandler(editor, tmp, "InsertParagraphBefore"), i18n["Insert a paragraph before the current node"], null, "InsertParagraphBefore"],
[i18n["Insert paragraph after"],
ContextMenu.blockElementsHandler(editor, tmp, "InsertParagraphAfter"), i18n["Insert a paragraph after the current node"], null, "InsertParagraphAfter"]
);
}
return menu;
};
ContextMenu.mouseOverHandler = function(editor,item) {
return (function() {
item.className += " hover";
......
});
};
ContextMenu.documentClickHandler = function(instance) {
return (function(ev) {
if (!ev) var ev = window.event;
if (!instance.currentMenu) {
alert(ContextMenu.I18N["How did you get here? (Please report!)"]);
return false;
}
var el = (ev.target) ? ev.target : ev.srcElement;
for (; el != null && el != instance.currentMenu; el = el.parentNode);
if (el == null) {
instance.closeMenu();
instance.editor.updateToolbar();
}
});
};
ContextMenu.keyPressHandler = function(instance) {
return (function(ev) {
if (!ev) var ev = window.event;
......
});
};
ContextMenu.prototype.closeMenu = function() {
HTMLArea._removeEvent((HTMLArea.is_ie ? document.body : document), "mousedown", this.eventHandlers["documentClick"]);
HTMLArea._removeEvent((HTMLArea.is_ie ? this.editor._doc.body : this.editor._doc), "mousedown", this.eventHandlers["documentClick"]);
if (this.keys.length > 0) HTMLArea._removeEvent((HTMLArea.is_ie ? this.editor._doc.body : this.editor._doc), "keypress", this.eventHandlers["keyPress"]);
for (var handler in this.eventHandlers) this.eventHandlers[handler] = null;
var e, items = document.getElementsByTagName("li");
if (HTMLArea.is_ie) items = this.iePopup.document.getElementsByTagName("li");;
for (var i = items.length; --i >= 0 ;) {
e = items[i];
if ( e.__msh ) {
HTMLArea._removeEvent(e, "mouseover", e.__msh.mouseover);
e.__msh.mouseover = null;
HTMLArea._removeEvent(e, "mouseout", e.__msh.mouseout);
e.__msh.mouseout = null;
HTMLArea._removeEvent(e, "contextmenu", e.__msh.contextmenu);
e.__msh.contextmenu = null;
if (!HTMLArea.is_ie) HTMLArea._removeEvent(e, "mousedown", e.__msh.mousedown);
e.__msh.mousedown = null;
HTMLArea._removeEvent(e, "mouseup", e.__msh.mouseup);
e.__msh.mouseup = null;
e.__msh.action = null;
e.__msh.activate = null;
e.__msh = null;
}
}
this.currentMenu.parentNode.removeChild(this.currentMenu);
this.currentMenu = null;
this.keys = [];
if (HTMLArea.is_ie) this.iePopup.hide();
};
ContextMenu.getPos = function(el) {
var r = { x: el.offsetLeft, y: el.offsetTop };
if (el.offsetParent) {
......
return r;
};
ContextMenu.prototype.popupMenu = function(ev,target) {
var editor = this.editor;
if (!ev) var ev = window.event;
if (!target) var target = (ev.target) ? ev.target : ev.srcElement;
if (this.currentMenu) this.currentMenu.parentNode.removeChild(this.currentMenu);
this.keys = [];
var ifpos = ContextMenu.getPos(this.editor._iframe);
var x = ev.clientX + ifpos.x;
var y = ev.clientY + ifpos.y;
var doc, list, separator = false;
if (!HTMLArea.is_ie) {
doc = document;
} else {
var popup = this.iePopup = window.createPopup();
doc = popup.document;
var head = doc.getElementsByTagName("head")[0];
var link = doc.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
if ( _editor_CSS.indexOf("http") == -1 ) link.href = _typo3_host_url + _editor_CSS;
else link.href = _editor_CSS;
head.appendChild(link);
}
list = doc.createElement("ul");
list.className = "htmlarea-context-menu";
doc.body.appendChild(list);
var options = this.getContextMenu(target);
var n = options.length;
for (var i=0; i < n; ++i) {
var option = options[i];
if (!option){
separator = true;
} else {
var item = doc.createElement("li");
list.appendChild(item);
var label = option[0];
if(separator) {
item.className += " separator";
separator = false;
}
item.__msh = {
item: item,
label: label,
action: option[1],
tooltip: option[2] || null,
icon: option[3] || null,
activate: ContextMenu.activateHandler(item, this),
cmd: option[4] || null
};
label = label.replace(/_([a-zA-Z0-9])/, "<u>$1</u>");
if (label != option[0]) this.keys.push([ RegExp.$1, item ]);
label = label.replace(/__/, "_");
var button = doc.createElement("button");
button.className = "button";
if(item.__msh.cmd) {
button.className += " " + item.__msh.cmd;
if(typeof(editor.plugins["TYPO3Browsers"]) != "undefined" && (item.__msh.cmd == "CreateLink" || item.__msh.cmd == "UnLink" || item.__msh.cmd == "InsertImage")) button.className += "-TYPO3Browsers";
button.innerHTML = label;
} else if(item.__msh.icon) {
button.innerHTML = "<img src='" + item.__msh.icon + "' />" + label;
} else {
button.innerHTML = label;
}
item.appendChild(button);
item.__msh.mouseover = ContextMenu.mouseOverHandler(editor, item);
HTMLArea._addEvent(item, "mouseover", item.__msh.mouseover);
item.__msh.mouseout = ContextMenu.mouseOutHandler(item);
HTMLArea._addEvent(item, "mouseout", item.__msh.mouseout);
item.__msh.contextmenu = ContextMenu.itemContextMenuHandler(item);
HTMLArea._addEvent(item, "contextmenu", item.__msh.contextmenu);
if(!HTMLArea.is_ie) {
item.__msh.mousedown = ContextMenu.mouseDownHandler(item);
HTMLArea._addEvent(item, "mousedown", item.__msh.mousedown);
}
item.__msh.mouseup = ContextMenu.mouseUpHandler(item, this);
HTMLArea._addEvent(item, "mouseup", item.__msh.mouseup);
}
}
if (n) {
if(!HTMLArea.is_ie) {
var dx = x + list.offsetWidth - window.innerWidth - window.pageXOffset + 4;
var dy = y + list.offsetHeight - window.innerHeight - window.pageYOffset + 4;
if(dx > 0) x -= dx;
if(dy > 0) y -= dy;
list.style.left = x + "px";
list.style.top = y + "px";
} else {
// determine the size
list.style.left = "0px";
list.style.top = "0px";
var foobar = document.createElement("ul");
foobar.className = "htmlarea-context-menu";
foobar.innerHTML = list.innerHTML;
editor._iframe.contentWindow.parent.document.body.appendChild(foobar);
this.iePopup.show(ev.screenX, ev.screenY, foobar.clientWidth+2, foobar.clientHeight+2);
editor._iframe.contentWindow.parent.document.body.removeChild(foobar);
}
this.currentMenu = list;
this.timeStamp = (new Date()).getTime();
this.eventHandlers["documentClick"] = ContextMenu.documentClickHandler(this);
HTMLArea._addEvent((HTMLArea.is_ie ? document.body : document), "mousedown", this.eventHandlers["documentClick"]);
HTMLArea._addEvent((HTMLArea.is_ie ? editor._doc.body : editor._doc), "mousedown", this.eventHandlers["documentClick"]);
if (this.keys.length > 0) {
this.eventHandlers["keyPress"] = ContextMenu.keyPressHandler(this);
HTMLArea._addEvents((HTMLArea.is_ie ? editor._doc.body : editor._doc), ["keypress", "keydown"], this.eventHandlers["keyPress"]);
}
}
HTMLArea._stopEvent(ev);
return false;
};
    (1-1/1)