--- /dev/null
+<?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!
+***************************************************************/
+/**
+ * Copy Paste plugin for htmlArea RTE
+ *
+ * @author Stanislas Rolland <typo3(arobas)sjbr.ca>
+ *
+ * TYPO3 SVN ID: $Id: class.tx_rtehtmlarea_copypaste.php $
+ *
+ */
+
+require_once(t3lib_extMgm::extPath('rtehtmlarea').'class.tx_rtehtmlareaapi.php');
+
+class tx_rtehtmlarea_copypaste extends tx_rtehtmlareaapi {
+
+ protected $extensionKey = 'rtehtmlarea'; // The key of the extension that is extending htmlArea RTE
+ protected $pluginName = 'CopyPaste'; // 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 = 'extensions/CopyPaste/skin/htmlarea.css'; // 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 = 'copy, cut, paste';
+ protected $convertToolbarForHtmlAreaArray = array (
+ 'copy' => 'Copy',
+ 'cut' => 'Cut',
+ 'paste' => 'Paste',
+ );
+ protected $hideButtonsFromClient = array ( // Hide buttons not implemented in client browsers
+ 'safari' => array('paste'),
+ );
+
+ public function main($parentObject) {
+ $enabled = parent::main($parentObject) && $this->htmlAreaRTE->client['BROWSER'] != 'opera';
+ // Hiding some buttons
+ if ($enabled && is_array($this->hideButtonsFromClient[$this->htmlAreaRTE->client['BROWSER']])) {
+ $this->pluginButtons = implode(',', array_diff(t3lib_div::trimExplode(',', $this->pluginButtons, 1), $this->hideButtonsFromClient[$this->htmlAreaRTE->client['BROWSER']]));
+ }
+ return $enabled;
+ }
+
+ /**
+ * 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) {
+ global $TSFE, $LANG;
+
+ $registerRTEinJavascriptString = '';
+ return $registerRTEinJavascriptString;
+ }
+
+} // end of class
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/CopyPaste/class.tx_rtehtmlarea_copypaste.php']) {
+ include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/CopyPaste/class.tx_rtehtmlarea_copypaste.php']);
+}
+
+?>
\ No newline at end of file
this.btnList = {
InsertHorizontalRule: ["Horizontal Rule", "ed_hr.gif",false, function(editor) {editor.execCommand("InsertHorizontalRule");}],
HtmlMode: ["Toggle HTML Source", "ed_html.gif", true, function(editor) {editor.execCommand("HtmlMode");}],
- SelectAll: ["SelectAll", "", true, function(editor) {editor.execCommand("SelectAll");}, null, true, false],
- Cut: ["Cut selection", "ed_cut.gif", false, function(editor) {editor.execCommand("Cut");}],
- Copy: ["Copy selection", "ed_copy.gif", false, function(editor) {editor.execCommand("Copy");}],
- Paste: ["Paste from clipboard", "ed_paste.gif", false, function(editor) {editor.execCommand("Paste");}]
+ SelectAll: ["SelectAll", "", true, function(editor) {editor.execCommand("SelectAll");}, null, true, false]
};
// Default hotkeys
this.hotKeyList = {
- a: { cmd: "SelectAll", action: null},
- v: { cmd: "Paste", action: null}
+ a: { cmd: "SelectAll", action: null}
};
// Initialize tooltips from the I18N module, generate correct image path
HTMLArea._addEvent((this._iframe.contentWindow ? this._iframe.contentWindow : this._iframe.contentDocument), "unload", HTMLArea.removeEditorEvents);
}
- // set enableWordClean and intercept paste, dragdrop and drop events for wordClean
- //if (this.config.enableWordClean) HTMLArea._addEvents((HTMLArea.is_ie ? doc.body : doc), ["paste","dragdrop","drop"], HTMLArea.wordClean, true);
-
window.setTimeout("HTMLArea.generatePlugins(" + this._editorNumber + ");", 100);
};
if (this.config.pathToPluginDirectory[pluginId]) {
url = this.config.pathToPluginDirectory[pluginId] + "popups/" + popup;
} else {
- url = _editor_url + "plugins/" + pluginId + "/popups/" + popup;
+ url = _typo3_host_url + _editor_url + "plugins/" + pluginId + "/popups/" + popup;
}
} else {
url = _typo3_host_url + _editor_url + this.config.popupURL + file;
case "HtmlMode":
btn.state("active", text);
break;
- case "Paste":
- if (!text) {
- try {
- btn.state("enabled", doc.queryCommandEnabled('Paste'));
- } catch(e) {
- btn.state("enabled", false);
- }
- }
- break;
default:
break;
}
case "HtmlMode" :
this.setMode();
break;
- case "Cut" :
- case "Copy" :
- case "Paste" :
- try {
- this._doc.execCommand(cmdID, false, null);
- // In FF3, the paste operation will indeed trigger the paste event
- if (HTMLArea.is_gecko && cmdID == "Paste" && this._toolbarObjects.CleanWord && navigator.productSub < 2008020514) {
- this._toolbarObjects.CleanWord.cmd(this, "CleanWord");
- }
- } catch (e) {
- if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
- this._mozillaPasteException(cmdID, UI, param);
- }
- }
- break;
default :
try {
this._doc.execCommand(cmdID, UI, param);
HTMLArea._stopEvent(ev);
return false;
break;
- case "Paste" :
- if (HTMLArea.is_ie || HTMLArea.is_safari) {
- cmd = editor.config.hotKeyList[key].cmd;
- editor.execCommand(cmd, false, null);
- HTMLArea._stopEvent(ev);
- return false;
- // In FF3, the paste operation will indeed trigger the paste event
- } else if (HTMLArea.is_opera || (HTMLArea.is_gecko && navigator.productSub < 2008020514)) {
- if (editor._toolbarObjects.CleanWord) {
- var cleanLaterFunctRef = editor.plugins.DefaultClean ? editor.plugins.DefaultClean.instance.cleanLaterFunctRef : (editor.plugins.TYPO3HtmlParser ? editor.plugins.TYPO3HtmlParser.instance.cleanLaterFunctRef : null);
- if (cleanLaterFunctRef) {
- window.setTimeout(cleanLaterFunctRef, 50);
- }
- }
- }
- break;
default:
if (editor.config.hotKeyList[key] && editor.config.hotKeyList[key].action) {
if (!editor.config.hotKeyList[key].action(editor, key)) {
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") {
return false;
}
}
--- /dev/null
+/***************************************************************
+* 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.
+* A copy is found in the textfile GPL.txt and important notices to the license
+* from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+* 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!
+***************************************************************/
+/*
+ * Copy Paste for TYPO3 htmlArea RTE
+ *
+ * TYPO3 SVN ID: $Id: copy-paste.js $
+ */
+CopyPaste = HTMLArea.Plugin.extend({
+
+ constructor : function(editor, pluginName) {
+ this.base(editor, pluginName);
+ },
+
+ /*
+ * This function gets called by the class constructor
+ */
+ configurePlugin : function (editor) {
+
+ /*
+ * Setting up some properties from PageTSConfig
+ */
+ this.buttonsConfiguration = this.editorConfiguration.buttons;
+
+ /*
+ * Registering plugin "About" information
+ */
+ var pluginInformation = {
+ version : "1.0",
+ developer : "Stanislas Rolland",
+ developerUrl : "http://www.sjbr.ca/",
+ copyrightOwner : "Stanislas Rolland",
+ sponsor : this.localize("Technische Universitat Ilmenau"),
+ sponsorUrl : "http://www.tu-ilmenau.de/",
+ license : "GPL"
+ };
+ this.registerPluginInformation(pluginInformation);
+
+ /*
+ * Registering the buttons
+ */
+ for (var buttonId in this.buttonList) {
+ if (this.buttonList.hasOwnProperty(buttonId)) {
+ var button = this.buttonList[buttonId];
+ var buttonConfiguration = {
+ id : buttonId,
+ tooltip : this.localize(buttonId.toLowerCase()),
+ action : "onButtonPress",
+ context : button[0],
+ hotKey : (this.buttonsConfiguration[button[2]] ? this.buttonsConfiguration[button[2]].hotKey : (button[1] ? button[1] : null))
+ };
+ this.registerButton(buttonConfiguration);
+ }
+ }
+
+ return true;
+ },
+
+ /*
+ * The list of buttons added by this plugin
+ */
+ buttonList : {
+ Copy : [null, "c", "copy"],
+ Cut : [null, "x", "cut"],
+ Paste : [null, "v", "paste"]
+ },
+
+ /*
+ * This function gets called when a button or a hotkey was pressed.
+ *
+ * @param object editor: the editor instance
+ * @param string id: the button id or the key
+ * @param object target: the target element of the contextmenu event, when invoked from the context menu
+ *
+ * @return boolean false if action is completed
+ */
+ onButtonPress : function (editor, id, target) {
+ // Could be a button or its hotkey
+ var buttonId = this.translateHotKey(id);
+ buttonId = buttonId ? buttonId : id;
+ this.editor.focusEditor();
+ if (!this.applyToTable(buttonId, target)) {
+ switch (buttonId) {
+ case "Copy":
+ case "Cut" :
+ this.applyBrowserCommand(buttonId);
+ break;
+ case "Paste":
+ if (!HTMLArea.is_opera) {
+ this.applyBrowserCommand(buttonId, (buttonId != id));
+ }
+ // In FF3, the paste operation will indeed trigger the paste event
+ if (HTMLArea.is_opera || (HTMLArea.is_gecko && navigator.productSub < 2008020514)) {
+ if (this.editor._toolbarObjects.CleanWord) {
+ var cleanLaterFunctRef = this.editor.plugins.DefaultClean ? this.editor.plugins.DefaultClean.instance.cleanLaterFunctRef : (this.editor.plugins.TYPO3HtmlParser ? this.editor.plugins.TYPO3HtmlParser.instance.cleanLaterFunctRef : null);
+ if (cleanLaterFunctRef) {
+ window.setTimeout(cleanLaterFunctRef, 50);
+ }
+ }
+ }
+ break;
+ }
+ }
+ return false;
+ },
+
+ applyBrowserCommand : function (buttonId, buttonPress) {
+ try {
+ this.editor._doc.execCommand(buttonId, false, null);
+ } catch (e) {
+ if (buttonId == "Paste" && HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
+ this.editor._mozillaPasteException(buttonId, buttonPress, null);
+ }
+ }
+ },
+
+ /*
+ * This function gets called by the main editor when a copy/cut/paste operation is to be performed
+ */
+ applyToTable : function (buttonId, target) {
+ var selection = this.editor._getSelection();
+ var range = this.editor._createRange(selection);
+ var parent = this.editor.getParentElement(selection, range);
+ var endBlocks = this.editor.getEndBlocks(selection);
+ switch (buttonId) {
+ case "Copy":
+ case "Cut" :
+ HTMLArea.copiedCells = null;
+ var endBlocks = this.editor.getEndBlocks(selection);
+ if ((/^(tr)$/i.test(parent.nodeName) && HTMLArea.is_gecko) || (/^(td|th)$/i.test(endBlocks.start.nodeName) && /^(td|th)$/i.test(endBlocks.end.nodeName) && (HTMLArea.is_ie || HTMLArea.is_safari || HTMLArea.is_opera) && endBlocks.start != endBlocks.end)) {
+ HTMLArea.copiedCells = this.collectCells(buttonId, selection, endBlocks);
+ if (buttonId === "Cut") return true;
+ }
+ break;
+ case "Paste":
+ if (/^(tr|td|th)$/i.test(parent.nodeName) && HTMLArea.copiedCells) {
+ return this.pasteCells(selection, endBlocks);
+ }
+ break;
+ }
+ return false;
+ },
+
+ pasteCells : function (selection, endBlocks) {
+ var cell = null;
+ if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
+ range = selection.getRangeAt(0);
+ cell = range.startContainer.childNodes[range.startOffset];
+ while (cell && !HTMLArea.isBlockElement(cell)) {
+ cell = cell.parentNode;
+ }
+ }
+ if (!cell && /^(td|th)$/i.test(endBlocks.start.nodeName)) {
+ cell = endBlocks.start;
+ }
+ if (!cell) return false;
+ var tableParts = ["thead", "tbody", "tfoot"];
+ var tablePartsIndex = { thead : 0, tbody : 1, tfoot : 2 };
+ var tablePart = cell.parentNode.parentNode;
+ var tablePartIndex = tablePartsIndex[tablePart.nodeName.toLowerCase()]
+ var rows = HTMLArea.copiedCells[tablePartIndex];
+ if (rows && rows[0]) {
+ for (var i = 0, rowIndex = cell.parentNode.sectionRowIndex-1; i < rows.length && ++rowIndex < tablePart.rows.length; ++i) {
+ var cells = rows[i];
+ if (!cells) break;
+ var row = tablePart.rows[rowIndex];
+ for (var j = 0, cellIndex = cell.cellIndex-1; j < cells.length && ++cellIndex < row.cells.length; ++j) {
+ row.cells[cellIndex].innerHTML = cells[j];
+ }
+ }
+ }
+ var table = tablePart.parentNode;
+ for (var k = tablePartIndex +1; k < 3; ++k) {
+ tablePart = table.getElementsByTagName(tableParts[k])[0];
+ if (tablePart) {
+ var rows = HTMLArea.copiedCells[k];
+ for (var i = 0; i < rows.length && i < tablePart.rows.length; ++i) {
+ var cells = rows[i];
+ if (!cells) break;
+ var row = tablePart.rows[i];
+ for (var j = 0, cellIndex = cell.cellIndex-1; j < cells.length && ++cellIndex < row.cells.length; ++j) {
+ row.cells[cellIndex].innerHTML = cells[j];
+ }
+ }
+ }
+ }
+ return true;
+ },
+
+ /*
+ * This function collects the selected table cells for copy/cut operations
+ */
+ collectCells : function (operation, selection, endBlocks) {
+ var tableParts = ["thead", "tbody", "tfoot"];
+ var tablePartsIndex = { thead : 0, tbody : 1, tfoot : 2 };
+ var selection = this.editor._getSelection();
+ var range, i = 0, cell, cells = null;
+ var rows = new Array();
+ for (var k = tableParts.length; --k >= 0;) {
+ rows[k] = [];
+ }
+ var row = null;
+ var cutRows = [];
+ if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) { // Firefox
+ if (selection.rangeCount == 1) { // Collect the cells in the selected row
+ cells = [];
+ for (var i = 0, n = endBlocks.start.cells.length; i < n; ++i) {
+ cell = endBlocks.start.cells[i];
+ cells.push(cell.innerHTML);
+ if (operation === "Cut") {
+ cell.innerHTML = "<br />";
+ }
+ if (operation === "Cut") {
+ cutRows.push(endBlocks.start);
+ }
+ }
+ rows[tablePartsIndex[endBlocks.start.parentNode.nodeName.toLowerCase()]].push(cells);
+ } else {
+ try { // Collect the cells in some region of the table
+ var firstCellOfRow = false;
+ var lastCellOfRow = false;
+ while (range = selection.getRangeAt(i++)) {
+ cell = range.startContainer.childNodes[range.startOffset];
+ if (cell.parentNode != row) {
+ (cells) && rows[tablePartsIndex[row.parentNode.nodeName.toLowerCase()]].push(cells);
+ if (operation === "Cut" && firstCellOfRow && lastCellOfRow) cutRows.push(row);
+ row = cell.parentNode;
+ cells = [];
+ firstCellOfRow = false;
+ lastCellOfRow = false;
+ }
+ cells.push(cell.innerHTML);
+ if (operation === "Cut") {
+ cell.innerHTML = "<br />";
+ }
+ if (!cell.previousSibling) firstCellOfRow = true;
+ if (!cell.nextSibling) lastCellOfRow = true;
+ }
+ } catch(e) {
+ /* finished walking through selection */
+ }
+ try { rows[tablePartsIndex[row.parentNode.nodeName.toLowerCase()]].push(cells); } catch(e) { }
+ if (row && operation === "Cut" && firstCellOfRow && lastCellOfRow) {
+ cutRows.push(row);
+ }
+ }
+ } else { // Internet Explorer, Safari and Opera
+ var firstRow = endBlocks.start.parentNode;
+ var lastRow = endBlocks.end.parentNode;
+ cells = [];
+ var firstCellOfRow = false;
+ var lastCellOfRow = false;
+ if (firstRow == lastRow) { // Collect the selected cells on the row
+ cell = endBlocks.start;
+ while (cell) {
+ cells.push(cell.innerHTML);
+ if (operation === "Cut") {
+ cell.innerHTML = "";
+ }
+ if (!cell.previousSibling) firstCellOfRow = true;
+ if (!cell.nextSibling) lastCellOfRow = true;
+ if (cell == endBlocks.end) break;
+ cell = cell.nextSibling;
+ }
+ rows[tablePartsIndex[firstRow.parentNode.nodeName.toLowerCase()]].push(cells);
+ if (operation === "Cut" && firstCellOfRow && lastCellOfRow) cutRows.push(firstRow);
+ } else { // Collect all cells on selected rows
+ row = firstRow;
+ while (row) {
+ cells = [];
+ for (var i = 0, n = row.cells.length; i < n ; ++i) {
+ cells.push(row.cells[i].innerHTML);
+ if (operation === "Cut") {
+ row.cells[i].innerHTML = "";
+ }
+ }
+ rows[tablePartsIndex[row.parentNode.nodeName.toLowerCase()]].push(cells);
+ if (operation === "Cut") cutRows.push(row);
+ if (row == lastRow) break;
+ row = row.nextSibling;
+ }
+ }
+ }
+ for (var i = 0, n = cutRows.length; i < n; ++i) {
+ if (i == n-1) {
+ var tablePart = cutRows[i].parentNode;
+ var next = cutRows[i].nextSibling;
+ cutRows[i].parentNode.removeChild(cutRows[i]);
+ if (next) {
+ this.editor.selectNodeContents(next.cells[0], true);
+ } else if (tablePart.parentNode.rows.length) {
+ this.editor.selectNodeContents(tablePart.parentNode.rows[0].cells[0], true);
+ }
+ } else {
+ cutRows[i].parentNode.removeChild(cutRows[i]);
+ }
+ }
+ return rows;
+ },
+
+ /*
+ * This function gets called when the toolbar is updated
+ */
+ onUpdateToolbar : function () {
+ if (this.editor.getMode() === "wysiwyg" || this.editor.isEditable()) {
+ var buttonId = "Paste";
+ if (typeof(this.editor._toolbarObjects[buttonId]) !== "undefined") {
+ try {
+ this.editor._toolbarObjects[buttonId].state("enabled", this.editor._doc.queryCommandEnabled(buttonId));
+ } catch(e) {
+ this.editor._toolbarObjects[buttonId].state("enabled", false);
+ }
+ }
+ }
+ }
+});
+