+2010-11-10 Stanislas Rolland <typo3@sjbr.ca>
+
+ * Added feature #8349: htmlArea RTE: Clean paste feature with three options
+
2010-11-09 Jeff Segars <jeff@webempoweredchurch.org>
* Fixed bug #16262: Link browser shows wrong title for pages and tt_content elements (Thanks to Reinhard Führicht)
+2010-11-10 Stanislas Rolland <typo3@sjbr.ca>
+
+ * Added feature #8349: htmlArea RTE: Clean paste feature with three options
+
2010-11-08 Stanislas Rolland <typo3@sjbr.ca>
* Fixed bug #16245: htmlArea RTE: When inserting link with IE8, trailing line break is also linked
bar, orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent, bar, lefttoright, righttoleft, language, showlanguagemarks,
bar, textcolor, bgcolor, textindicator,
bar, emoticon, insertcharacter, link, unlink, image, table,' . (($this->thisConfig['hideTableOperationsInToolbar'] && is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.']['toggleborders.']) && $this->thisConfig['buttons.']['toggleborders.']['keepInToolbar']) ? ' toggleborders,': '') . ' user, acronym, bar, findreplace, spellcheck,
- bar, chMode, inserttag, removeformat, bar, copy, cut, paste, pasteastext, bar, undo, redo, bar, showhelp, about, linebreak,
+ bar, chMode, inserttag, removeformat, bar, copy, cut, paste, pastetoggle, pastebehaviour, bar, undo, redo, bar, showhelp, about, linebreak,
' . ($this->thisConfig['hideTableOperationsInToolbar'] ? '': 'bar, toggleborders,') . ' bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar,
columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar,
cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge';
),
'suggests' => array(
'rtehtmlarea_api_manual' => '',
+ 'setup' => '',
),
),
'suggests' => array(
$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['PlainText']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/PlainText/class.tx_rtehtmlarea_plaintext.php:&tx_rtehtmlarea_plaintext';
$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['PlainText']['addIconsToSkin'] = 0;
$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['PlainText']['disableInFE'] = 0;
+$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['PlainText']['contextHelpFile'] = 'EXT:' . $_EXTKEY . '/extensions/PlainText/locallang_csh.xml';
$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['DefaultClean'] = array();
$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['DefaultClean']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/DefaultClean/class.tx_rtehtmlarea_defaultclean.php:&tx_rtehtmlarea_defaultclean';
$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TYPO3HtmlParser'] = array();
// Add static template for Click-enlarge rendering
t3lib_extMgm::addStaticFile($_EXTKEY,'static/clickenlarge/','Clickenlarge Rendering');
+ // Add acronyms table
$TCA['tx_rtehtmlarea_acronym'] = Array (
'ctrl' => Array (
'title' => 'LLL:EXT:rtehtmlarea/locallang_db.xml:tx_rtehtmlarea_acronym',
// Add contextual help files
foreach ($TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins'] as $pluginName => $config) {
if ($config['contextHelpFile']) {
- t3lib_extMgm::addLLrefForTCAdescr('xEXT_' . $_EXTKEY . '_' . $pluginName, $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['RemoveFormat']['contextHelpFile']);
+ t3lib_extMgm::addLLrefForTCAdescr('xEXT_' . $_EXTKEY . '_' . $pluginName, $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins'][$pluginName]['contextHelpFile']);
}
}
+
+ // Extend TYPO3 User Settings Configuration
+if (TYPO3_MODE === 'BE' && t3lib_extMgm::isLoaded('setup') && is_array($GLOBALS['TYPO3_USER_SETTINGS'])) {
+ $GLOBALS['TYPO3_USER_SETTINGS']['columns'] = array_merge(
+ $GLOBALS['TYPO3_USER_SETTINGS']['columns'],
+ array(
+ 'rteCleanPasteBehaviour' => array(
+ 'type' => 'select',
+ 'label' => 'LLL:EXT:rtehtmlarea/htmlarea/plugins/PlainText/locallang.xml:rteCleanPasteBehaviour',
+ 'items' => array(
+ 'plainText' => 'LLL:EXT:rtehtmlarea/htmlarea/plugins/PlainText/locallang.xml:plainText',
+ 'pasteStructure' => 'LLL:EXT:rtehtmlarea/htmlarea/plugins/PlainText/locallang.xml:pasteStructure',
+ 'pasteFormat' => 'LLL:EXT:rtehtmlarea/htmlarea/plugins/PlainText/locallang.xml:pasteFormat',
+ ),
+ 'csh' => 'xEXT_rtehtmlarea_PlainText:behaviour',
+ ),
+ )
+ );
+ $GLOBALS['TYPO3_USER_SETTINGS']['showitem'] .= ',--div--;LLL:EXT:rtehtmlarea/locallang.xml:rteSettings,rteResize,rteMaxHeight,rteCleanPasteBehaviour';
+}
?>
\ No newline at end of file
protected $thisConfig; // Reference to RTE PageTSConfig
protected $toolbar; // Reference to RTE toolbar array
protected $LOCAL_LANG; // Frontend language array
- protected $pluginButtons = 'pasteastext';
+ protected $pluginButtons = 'pastetoggle,pastebehaviour';
protected $convertToolbarForHtmlAreaArray = array (
- 'pasteastext' => 'PlainText',
+ 'pastetoggle' => 'PasteToggle',
+ 'pastebehaviour' => 'PasteBehaviour',
);
- public function main($parentObject) {
- // Opera has no onPaste event to hook on
+ public function main ($parentObject) {
+ // Opera has no onPaste event to handle
return parent::main($parentObject) && $this->htmlAreaRTE->client['browser'] != 'opera';
}
/**
*/
public function buildJavascriptConfiguration($RTEcounter) {
$registerRTEinJavascriptString = '';
+ $button = 'pastebehaviour';
+ // Get current TYPO3 User Setting, if available
+ if (TYPO3_MODE === 'BE' && t3lib_extMgm::isLoaded('setup') && is_array($GLOBALS['TYPO3_USER_SETTINGS']) && is_object($GLOBALS['BE_USER'])) {
+ if (!is_array($this->thisConfig['buttons.']) || !is_array($this->thisConfig['buttons.'][$button.'.'])) {
+ $registerRTEinJavascriptString .= '
+ RTEarea[' . $RTEcounter . '].buttons.' . $button . ' = new Object();';
+ }
+ $registerRTEinJavascriptString .= '
+ RTEarea[' . $RTEcounter . '].buttons.' . $button . '.current = "' . (isset($GLOBALS['BE_USER']->uc['rteCleanPasteBehaviour']) ? $GLOBALS['BE_USER']->uc['rteCleanPasteBehaviour'] : 'plainText') . '";';
+ }
return $registerRTEinJavascriptString;
}
+ /**
+ * Return an updated array of toolbar enabled buttons
+ *
+ * @param array $show: array of toolbar elements that will be enabled, unless modified here
+ *
+ * @return array toolbar button array, possibly updated
+ */
+ public function applyToolbarConstraints ($show) {
+ $removeButtons = array();
+ // Remove pastebehaviour button if pastetoggle is not configured
+ if (!in_array('pastetoggle', $show)) {
+ $removeButtons[] = 'pastebehaviour';
+ }
+ // Remove pastebehaviour button if TYPO3 User Settings are available
+ if (TYPO3_MODE === 'BE' && t3lib_extMgm::isLoaded('setup') && is_array($GLOBALS['TYPO3_USER_SETTINGS']) && is_object($GLOBALS['BE_USER'])) {
+ $removeButtons[] = 'pastebehaviour';
+ }
+ return array_diff($show, $removeButtons);
+ }
}
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/PlainText/class.tx_rtehtmlarea_plaintext.php']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/PlainText/class.tx_rtehtmlarea_plaintext.php']);
--- /dev/null
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<T3locallang>
+ <meta type="array">
+ <description>CSH for Plain Text Extension of htmlArea RTE</description>
+ <type>CSH</type>
+ <csh_table>xEXT_rtehtmlarea_PlainText</csh_table>
+ </meta>
+ <data type="array">
+ <languageKey index="default" type="array">
+ <label index=".alttitle">htmlArea RTE > Clean Paste</label>
+ <label index=".description">The Clean Paste feature offers options for cleaning content copied from external source before it gets pasted into the editing area.</label>
+ <label index=".details">This feature is useful when pasting text that was copied to the clipboard from some external source.
+
+The "Clean paste" button allows to toggle to clean paste mode and back to normal paste mode.
+Clicking on the "Clean paste" button puts the button "on". This action does not initiate any paste operation. But when the "clean paste" button is "on" in the RTE tool bar, whenever a paste operation is performed, content contained in the clipboard is transformed before being pasted into the editing area.
+Clicking again on the toggle button puts it "off". Any subsequent paste operation is performed as a normal paste.</label>
+ <label index=".image">EXT:rtehtmlarea/extensions/PlainText/skin/images/paste-toggle.gif,
+EXT:rtehtmlarea/extensions/PlainText/skin/images/paste-behaviour.gif</label>
+ <label index=".image_descr">"Clean paste" toggle icon in the editor tool bar. Clicking on it changes the behaviour of subsequent paste operations.
+"Clean Paste Behaviour" icon in the editor tool bar. Clicking on it opens a dialogue that allows to select an alternate paste behaviour.</label>
+ <label index=".seeAlso">xEXT_rtehtmlarea_PlainText:behaviour</label>
+ <label index="behaviour.alttitle">Select a paste behaviour</label>
+ <label index="behaviour.description">Select one of the three alternate paste behaviours.</label>
+ <label index="behaviour.details">When the "Clean paste" toggle is "on" in the RTE tool bar, the content may be tranformed according to the three following behaviours before being pasted:
+- plain text: all HTML markup is removed;
+- structure only: only structural HTML markup is retained, all format is removed;
+- structure and basic format: structural HTML markup is preserved as well as basic format provided by inline HTML elements.
+
+Which behaviour is activated when clicking the toggle button may be set either in the TYPO3 BE User Settings or in the "Clean Paste Behaviour" dialogue. If not set, it defaults to "Paste as plain text".
+The "Clean Paste Behaviour" dialogue is activated by clicking on the "Clean Paste Behaviour" button in the toolbar of the RTE.</label>
+ <label index="behaviour.seeAlso">xEXT_rtehtmlarea_PlainText:plainText,xEXT_rtehtmlarea_PlainText:pasteStructure,xEXT_rtehtmlarea_PlainText:pasteFormat,_MOD_user_setup</label>
+ <label index="plainText.alttitle">Paste as plain text</label>
+ <label index="plainText.description">When this paste behaviour is enabled, all HTML markup is removed before content is pasted in the editing area.</label>
+ <label index="plainText.seeAlso">xEXT_rtehtmlarea_PlainText:behaviour</label>
+ <label index="pasteStructure.alttitle">Paste structure only</label>
+ <label index="pasteStructure.description">When this paste behaviour is enabled and content is pasted in the editing area, only structural HTML markup is retained, all format is removed.</label>
+ <label index="pasteStructure.details">By default, "Structure only" means that:
+- only the following HTML elements are retained: a, p, h[0-6], pre, address, blockquote, div, hr, br, table, thead, tbody, tfoot, caption, tr, th, td, ul, ol, dl, li, dt, dd;
+- the following HTML attributes are removed: id, style, class, lang, align, valign, bgcolor, color, border, face, any attribute starting with "on", and any attribute containing ":".
+
+These defaults may be modified in Page TSConfig.</label>
+ <label index="pasteStructure.seeAlso">xEXT_rtehtmlarea_PlainText:behaviour</label>
+ <label index="pasteFormat.alttitle">Paste structure and basic format</label>
+ <label index="pasteFormat.description">When this paste behaviour is enabled and content is pasted in the editing area, structural HTML markup is preserved as well as basic format provided by inline HTML elements.</label>
+ <label index="pasteFormat.details">By default, "Structure and basic format" means that:
+- the following HTML structural elements are retained: a, p, h[0-6], pre, address, blockquote, div, hr, br, table, thead, tbody, tfoot, caption, tr, th, td, ul, ol, dl, li, dt, dd;
+- the following HTML inline elements are also retained: b, bdo, big, cite, code, del, dfn, em, i, ins, kbd, label, q, samp, small, strike, strong, sub, sup, tt, u, var;
+- the following HTML attributes are removed: id, style, class, lang, align, valign, bgcolor, color, border, face, any attribute starting with "on", and any attribute containing ":".
+
+These defaults may be modified in Page TSConfig.</label>
+ <label index="pasteFormat.seeAlso">xEXT_rtehtmlarea_PlainText:behaviour</label>
+ <label index="pasteInPastingPad.description">Contents pasted into this pasting pad will be cleaned. Click OK to insert the cleaned contents into the RTE editing area.</label>
+ <label index="pasteInPastingPad.details">When using Internet Explorer and when pasting behaviour "Paste structure only" or "Paste structure and format" is enabled, contents must first be pasted into this pasting pad so that they can be cleaned before being inserted into the RTE editing area.</label>
+ </languageKey>
+ </data>
+</T3locallang>
/* Selectors for the PlainText extension of htmlArea RTE */
/* TYPO3 SVN ID: $Id: htmlarea.css 8281 2010-07-26 23:18:50Z stan $ */
-.htmlarea-action-paste-as-plain-text {
- background-image: url('images/paste-as-plain-text.gif') !important;
+.htmlarea-action-paste-toggle {
+ background-image: url('images/paste-toggle.gif') !important;
+ background-position: 0 0 !important;
+}
+.htmlarea-action-paste-behaviour {
+ background-image: url('images/paste-behaviour.gif') !important;
background-position: 0 0 !important;
}
</meta>
<data type="array">
<languageKey index="default" type="array">
- <label index="PlainTextTooltip">Toggle Paste as Plain Text</label>
- <label index="Paste-as-Plain-Text">Paste as Plain Text</label>
+ <label index="PasteToggleTooltip">Toggle paste behaviour</label>
+ <label index="plainText">Paste as plain text</label>
+ <label index="pasteStructure">Paste structure only</label>
+ <label index="pasteFormat">Paste structure and basic format</label>
+ <label index="PasteBehaviourTooltip">Select alternate paste behaviour</label>
+ <label index="Paste-as-Plain-Text">Paste as plain text</label>
<label index="Access-to-clipboard-denied">Content could not be pasted as plain text because permission to access the clipboard was denied.</label>
+ <label index="enableplainText">Enable paste as plain text</label>
+ <label index="enablepasteStructure">Enable paste structure only</label>
+ <label index="enablepasteFormat">Enable paste structure and basic format</label>
+ <label index="disableplainText">Disable paste as plain text</label>
+ <label index="disablepasteStructure">Disable paste structure only</label>
+ <label index="disablepasteFormat">Disable paste structure and basic format</label>
+ <label index="pasteInPastingPad">Paste the content into this pasting pad and click OK.</label>
+ <label index="rteCleanPasteBehaviour">Clean paste behaviour</label>
</languageKey>
</data>
<orig_hash type="array">
* This function gets called by the class constructor
*/
configurePlugin: function(editor) {
+ this.buttonsConfiguration = this.editorConfiguration.buttons;
/*
* Registering plugin "About" information
*/
developer : 'Stanislas Rolland',
developerUrl : 'http://www.sjbr.ca/',
copyrightOwner : 'Stanislas Rolland',
- sponsor : 'SJBR',
- sponsorUrl : 'http://www.sjbr.ca/',
+ sponsor : 'Otto van Bruggen',
+ sponsorUrl : 'http://www.webspinnerij.nl',
license : 'GPL'
};
this.registerPluginInformation(pluginInformation);
/*
- * Registering the button
+ * Registering the buttons
*/
- var buttonId = 'PlainText';
- var buttonConfiguration = {
- id : buttonId,
- tooltip : this.localize(buttonId + 'Tooltip'),
- iconCls : 'htmlarea-action-paste-as-plain-text',
- action : 'onButtonPress'
- };
- this.registerButton(buttonConfiguration);
+ Ext.iterate(this.buttonList, function (buttonId, buttonConf) {
+ var buttonConfiguration = {
+ id : buttonId,
+ tooltip : this.localize(buttonId + 'Tooltip'),
+ iconCls : 'htmlarea-action-' + buttonConf[1],
+ action : 'onButtonPress',
+ dialog : buttonConf[2]
+ };
+ this.registerButton(buttonConfiguration);
+ }, this);
return true;
},
+ /*
+ * The list of buttons added by this plugin
+ */
+ buttonList: {
+ PasteToggle: ['pastetoggle', 'paste-toggle', false],
+ PasteBehaviour: ['pastebehaviour', 'paste-behaviour', true]
+ },
+ /*
+ * Cleaner configurations
+ */
+ cleanerConfig: {
+ pasteStructure: {
+ keepTags: /^(a|p|h[0-6]|pre|address|blockquote|div|hr|br|table|thead|tbody|tfoot|caption|tr|th|td|ul|ol|dl|li|dt|dd)$/i,
+ removeAttributes: /^(id|on*|style|class|className|lang|align|valign|bgcolor|color|border|face|.*:.*)$/i
+ },
+ pasteFormat: {
+ keepTags: /^(a|p|h[0-6]|pre|address|blockquote|div|hr|br|table|thead|tbody|tfoot|caption|tr|th|td|ul|ol|dl|li|dt|dd|b|bdo|big|cite|code|del|dfn|em|i|ins|kbd|label|q|samp|small|strike|strong|sub|sup|tt|u|var)$/i,
+ removeAttributes: /^(id|on*|style|class|className|lang|align|valign|bgcolor|color|border|face|.*:.*)$/i
+ }
+ },
/*
* This function gets called when the plugin is generated
*/
onGenerate: function () {
- // Initialize state of toggle
- this.togglePasteAsPlainText(false);
+ // Create cleaners
+ if (this.buttonsConfiguration && this.buttonsConfiguration['pastebehaviour']) {
+ this.pasteBehaviourConfiguration = this.buttonsConfiguration['pastebehaviour'];
+ }
+ this.cleaners = {};
+ Ext.iterate(this.cleanerConfig, function (behaviour) {
+ if (this.pasteBehaviourConfiguration && this.pasteBehaviourConfiguration[behaviour]) {
+ if (this.pasteBehaviourConfiguration[behaviour].keepTags) {
+ this.cleanerConfig[behaviour].keepTags = new RegExp( '^(' + this.pasteBehaviourConfiguration[behaviour].keepTags.split(',').join('|') + ')$', 'i');
+ }
+ if (this.pasteBehaviourConfiguration[behaviour].removeAttributes) {
+ this.cleanerConfig[behaviour].removeAttributes = new RegExp( '^(' + this.pasteBehaviourConfiguration[behaviour].removeAttributes.split(',').join('|') + ')$', 'i');
+ }
+ }
+ this.cleaners[behaviour] = new HTMLArea.DOM.Walker(this.cleanerConfig[behaviour]);
+ }, this);
+ // Initial behaviour
+ this.currentBehaviour = 'plainText';
+ // May be set in TYPO3 User Settings
+ if (this.buttonsConfiguration && this.buttonsConfiguration['pastebehaviour'] && this.buttonsConfiguration['pastebehaviour']['current']) {
+ this.currentBehaviour = this.buttonsConfiguration['pastebehaviour']['current'];
+ }
// Start monitoring paste events
this.editor.iframe.mon(Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement), 'paste', this.onPaste, this);
},
/*
- * This function toggles the state of Paste as Plain text
+ * This function toggles the state of a button
*
- * @param boolean state: if defined, the specified state to set
+ * @param string buttonId: id of button to be toggled
*
* @return void
*/
- togglePasteAsPlainText: function (state) {
+ toggleButton: function (buttonId) {
// Set new state
- this.pasteAsPlainTextActive = (typeof(state) != 'undefined') ? state : !this.pasteAsPlainTextActive;
+ var button = this.getButton(buttonId);
+ button.setInactive(!button.inactive);
},
/*
* This function gets called when a button was pressed.
// Could be a button or its hotkey
var buttonId = this.translateHotKey(id);
buttonId = buttonId ? buttonId : id;
- this.togglePasteAsPlainText();
+ switch (buttonId) {
+ case 'PasteBehaviour':
+ // Open dialogue window
+ this.openDialogue(
+ buttonId,
+ 'PasteBehaviourTooltip',
+ this.getWindowDimensions(
+ {
+ width: 260,
+ height:260
+ },
+ buttonId
+ )
+ );
+ break;
+ case 'PasteToggle':
+ this.toggleButton(buttonId);
+ this.editor.focus();
+ break;
+ }
return false;
},
/*
- * This function gets called when the toolbar is updated
+ * Open the dialogue window
+ *
+ * @param string buttonId: the button id
+ * @param string title: the window title
+ * @param object dimensions: the opening dimensions of the window
*
* @return void
*/
- onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
- if (this.getEditorMode() === 'wysiwyg' && this.editor.isEditable()) {
- button.setInactive(!this.pasteAsPlainTextActive);
- }
+ openDialogue: function (buttonId, title, dimensions) {
+ this.dialog = new Ext.Window({
+ title: this.localize(title),
+ cls: 'htmlarea-window',
+ border: false,
+ width: dimensions.width,
+ height: 'auto',
+ // As of ExtJS 3.1, JS error with IE when the window is resizable
+ resizable: !Ext.isIE,
+ iconCls: this.getButton(buttonId).iconCls,
+ listeners: {
+ close: {
+ fn: this.onClose,
+ scope: this
+ }
+ },
+ items: [{
+ xtype: 'fieldset',
+ defaultType: 'radio',
+ title: this.getHelpTip('behaviour', title),
+ labelWidth: 170,
+ defaults: {
+ labelSeparator: '',
+ name: buttonId
+ },
+ items: [{
+ itemId: 'plainText',
+ fieldLabel: this.getHelpTip('plainText', 'plainText'),
+ checked: (this.currentBehaviour === 'plainText')
+ },{
+ itemId: 'pasteStructure',
+ fieldLabel: this.getHelpTip('pasteStructure', 'pasteStructure'),
+ checked: (this.currentBehaviour === 'pasteStructure')
+ },{
+ itemId: 'pasteFormat',
+ fieldLabel: this.getHelpTip('pasteFormat', 'pasteFormat'),
+ checked: (this.currentBehaviour === 'pasteFormat')
+ }
+ ]
+ }
+ ],
+ buttons: [
+ this.buildButtonConfig('OK', this.onOK)
+ ]
+ });
+ this.show();
+ },
+ /*
+ * Handler invoked when the OK button of the Clean Paste Behaviour window is pressed
+ */
+ onOK: function () {
+ var fields = [
+ 'plainText',
+ 'pasteStructure',
+ 'pasteFormat'
+ ];
+ Ext.each(fields, function (field) {
+ if (this.dialog.find('itemId', field)[0].getValue()) {
+ this.currentBehaviour = field;
+ return false;
+ }
+ }, this);
+ this.close();
+ return false;
},
/*
* Handler for paste event
+ *
+ * @param object event: the paste event
+ *
+ * @return boolean false, if the event was handled, true otherwise
*/
onPaste: function (event) {
- if (this.pasteAsPlainTextActive) {
- this.grabClipboardText(event);
- if (this.clipboardText) {
- // Direct access to the clipboard text was possible
- this.pasteAsPlainText();
- } else {
- // Get the text content from the hidden section
- // after the paste operation is completed
- this.getClipboardText.defer(10, this);
+ if (!this.getButton('PasteToggle').inactive) {
+ switch (this.currentBehaviour) {
+ case 'plainText':
+ // Only IE and WebKit will allow access to the clipboard content, in plain text only however
+ if (Ext.isIE || Ext.isWebKit) {
+ var clipboardText = this.grabClipboardText(event);
+ if (clipboardText) {
+ this.editor.insertHTML(clipboardText);
+ }
+ return !this.clipboardText;
+ }
+ case 'pasteStructure':
+ case 'pasteFormat':
+ if (Ext.isIE) {
+ // Save the current selection
+ this.editor.focus();
+ this.bookmark = this.editor.getBookmark(this.editor._createRange(this.editor._getSelection()));
+ // Show the pasting pad
+ this.openPastingPad(
+ 'PasteToggle',
+ this.currentBehaviour,
+ this.getWindowDimensions(
+ {
+ width: 550,
+ height: 550
+ },
+ 'PasteToggle'
+ ));
+ event.browserEvent.returnValue = false;
+ return false;
+ } else {
+ // Redirect the paste operation to a hidden section
+ this.redirectPaste();
+ // Process the content of the hidden section after the paste operation is completed
+ // WebKit seems to be pondering a very long time over what is happenning here...
+ this.processPastedContent.defer(Ext.isWebKit ? 500 : 50, this);
+ }
+ break;
+ default:
+ break;
}
- return !this.clipboardText;
}
+ return true;
},
/*
- * Grab the text content directly from the clipboard or
- * redirect the paste operation towards a hidden section
+ * Grab the text content directly from the clipboard
+ * If successful, stop the paste event
*
* @param object event: the paste event
*
- * @return void
+ * @return string clipboard content, in plain text, if access was granted
*/
grabClipboardText: function (event) {
- this.clipboardText = null;
- // Check if browser supports direct plaintext access (IE and WebKit)
+ var clipboardText = '';
+ // Grab the text content
if (window.clipboardData || event.browserEvent.clipboardData || event.browserEvent.dataTransfer) {
- // Grab the text content
- this.clipboardText = (window.clipboardData || event.browserEvent.clipboardData || event.browserEvent.dataTransfer).getData('Text');
- if (this.clipboardText) {
- // Stop the event
- event.stopEvent();
- } else {
- TYPO3.Dialog.InformationDialog({
- title: this.localize('Paste-as-Plain-Text'),
- msg: this.localize('Access-to-clipboard-denied')
- });
- }
+ clipboardText = (window.clipboardData || event.browserEvent.clipboardData || event.browserEvent.dataTransfer).getData('text');
+ }
+ if (clipboardText) {
+ // Stop the event
+ event.stopEvent();
} else {
- // When direct access was not possible
- // Save the current selection
- var selection = this.editor._getSelection();
- var range = this.editor._createRange(selection);
- this.bookmark = this.editor.getBookmark(range);
- // Create and append hidden section
- this.hiddenSection = this.editor.document.createElement('div');
- this.hiddenSection.id = this.editorId + 'htmlarea-paste-hidden-section';
- this.hiddenSection.style.position = 'absolute';
- this.hiddenSection.style.left = -10000;
- this.hiddenSection.style.top = this.editor.document.body.scrollTop;
- this.hiddenSection.style.overflow = 'hidden';
- this.hiddenSection = this.editor.document.body.appendChild(this.hiddenSection);
- // Move the selection to the hidden section and
- // let the browser paste into the hidden section
- this.editor.selectNodeContents(this.hiddenSection, true);
+ // If the user denied access to the clipboard, let the browser paste without intervention
+ TYPO3.Dialog.InformationDialog({
+ title: this.localize('Paste-as-Plain-Text'),
+ msg: this.localize('Access-to-clipboard-denied')
+ });
+ }
+ return clipboardText;
+ },
+ /*
+ * Redirect the paste operation towards a hidden section
+ *
+ * @return void
+ */
+ redirectPaste: function () {
+ this.editor.focus();
+ // Save the current selection
+ this.bookmark = this.editor.getBookmark(this.editor._createRange(this.editor._getSelection()));
+ // Create and append hidden section
+ var hiddenSection = this.editor.document.createElement('div');
+ HTMLArea.DOM.addClass(hiddenSection, 'htmlarea-paste-hidden-section');
+ hiddenSection.setAttribute('style', 'position: absolute; left: -10000px; top: ' + this.editor.document.body.scrollTop + 'px; overflow: hidden;');
+ hiddenSection = this.editor.document.body.appendChild(hiddenSection);
+ if (Ext.isWebKit) {
+ hiddenSection.innerHTML = ' ';
}
+ // Move the selection to the hidden section and let the browser paste into the hidden section
+ this.editor.selectNodeContents(hiddenSection);
},
/*
- * If the paste operation was redirected towards a hidden section
- * get the text content from the section
+ * Process the pasted content that was redirected towards a hidden section
+ * and insert it at the original selection
*
* @return void
*/
- getClipboardText: function () {
- // Get the text content
- this.clipboardText = this.hiddenSection.textContent;
- // Delete the hidden section
- HTMLArea.removeFromParent(this.hiddenSection);
+ processPastedContent: function () {
+ this.editor.focus();
+ // Get the hidden section
+ var divs = this.editor.document.getElementsByClassName('htmlarea-paste-hidden-section');
+ var hiddenSection = divs[0];
+ // Delete any other hidden sections
+ for (var i = divs.length; --i >= 1;) {
+ HTMLArea.removeFromParent(divs[i]);
+ }
+ var content = '';
+ switch (this.currentBehaviour) {
+ case 'plainText':
+ // Get plain text content
+ content = hiddenSection.textContent;
+ break;
+ case 'pasteStructure':
+ case 'pasteFormat':
+ // Get clean content
+ content = this.cleaners[this.currentBehaviour].render(hiddenSection, false);
+ break;
+ }
+ // Remove the hidden section from the document
+ HTMLArea.removeFromParent(hiddenSection);
// Restore the selection
this.editor.selectRange(this.editor.moveToBookmark(this.bookmark));
- this.pasteAsPlainText();
+ // Insert the cleaned content
+ if (content) {
+ this.editor.execCommand('insertHTML', false, content);
+ }
+ },
+ /*
+ * Open the pasting pad window (for IE)
+ *
+ * @param string buttonId: the button id
+ * @param string title: the window title
+ * @param object dimensions: the opening dimensions of the window
+ *
+ * @return void
+ */
+ openPastingPad: function (buttonId, title, dimensions) {
+ this.dialog = new Ext.Window({
+ title: this.getHelpTip(title, title),
+ cls: 'htmlarea-window',
+ bodyCssClass: 'pasting-pad',
+ border: false,
+ width: dimensions.width,
+ height: 'auto',
+ // As of ExtJS 3.1, JS error with IE when the window is resizable
+ resizable: !Ext.isIE,
+ iconCls: this.getButton(buttonId).iconCls,
+ listeners: {
+ afterrender: {
+ // The document will not be immediately ready
+ fn: function (event) { this.onPastingPadAfterRender.defer(100, this, [event]); },
+ scope: this
+ },
+ close: {
+ fn: this.onClose,
+ scope: this
+ }
+ },
+ items: [{
+ xtype: 'tbtext',
+ text: this.getHelpTip('pasteInPastingPad', 'pasteInPastingPad'),
+ style: {
+ marginBottom: '5px'
+ }
+ },{
+ // The iframe
+ xtype: 'box',
+ itemId: 'pasting-pad-iframe',
+ autoEl: {
+ name: 'contentframe',
+ tag: 'iframe',
+ cls: 'contentframe',
+ src: Ext.isGecko ? 'javascript:void(0);' : HTMLArea.editorUrl + 'popups/blank.html'
+ }
+ }
+ ],
+ buttons: [
+ this.buildButtonConfig('OK', this.onPastingPadOK),
+ this.buildButtonConfig('Cancel', this.onCancel)
+ ]
+ });
+ this.show();
+ },
+ /*
+ * Handler invoked after the pasting pad iframe has been rendered
+ */
+ onPastingPadAfterRender: function () {
+ var iframe = this.dialog.getComponent('pasting-pad-iframe').getEl().dom;
+ var pastingPadDocument = iframe.contentWindow ? iframe.contentWindow.document : iframe.contentDocument;
+ this.pastingPadBody = pastingPadDocument.body;
+ this.pastingPadBody.contentEditable = true;
+ // Start monitoring paste events
+ this.dialog.mon(Ext.get(this.pastingPadBody), 'paste', this.onPastingPadPaste, this);
+ this.pastingPadBody.focus();
+ },
+ /*
+ * Handler invoked when content is pasted into the pasting pad
+ */
+ onPastingPadPaste: function (event) {
+ // Let the paste operation complete before cleaning
+ this.cleanPastingPadContents.defer(50, this);
},
/*
- * Paste as plain text
+ * Clean the contents of the pasting pad
*/
- pasteAsPlainText: function () {
- this.editor.insertHTML(this.clipboardText);
+ cleanPastingPadContents: function () {
+ this.pastingPadBody.innerHTML = this.cleaners[this.currentBehaviour].render(this.pastingPadBody, false);
+ this.pastingPadBody.focus();
+ },
+ /*
+ * Handler invoked when the OK button of the Pasting Pad window is pressed
+ */
+ onPastingPadOK: function () {
+ // Restore the selection
+ this.editor.focus();
+ this.restoreSelection();
+ // Insert the cleaned pasting pad content
+ this.editor.insertHTML(this.pastingPadBody.innerHTML);
+ this.close();
+ return false;
+ },
+ /*
+ * This function gets called when the toolbar is updated
+ */
+ onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
+ if (mode === 'wysiwyg' && this.editor.isEditable()) {
+ switch (button.itemId) {
+ case 'PasteToggle':
+ button.setTooltip({
+ title: this.localize((button.inactive ? 'enable' : 'disable') + this.currentBehaviour)
+ });
+ break;
+ }
+ }
}
});
background-position: 0 -15px;
}
/* Action icon selectors for toolbar, context menu and window headers */
-.htmlarea-action-abbreviation-edit { background-position: 0 0 !important; }
-.htmlarea-action-bidi-override { background-position: 0 -58px !important; }
-.htmlarea-action-big { background-position: 0 -116px !important; }
-.htmlarea-action-blockquote { background-position: 0 -174px !important; }
-.htmlarea-action-bold { background-position: 0 -232px !important; }
-.htmlarea-action-cell-delete { background-position: 0 -290px !important; }
-.htmlarea-action-cell-edit-properties { background-position: 0 -348px !important; }
-.htmlarea-action-cell-insert-after { background-position: 0 -406px !important; }
-.htmlarea-action-cell-insert-before { background-position: 0 -464px !important; }
-.htmlarea-action-cell-merge { background-position: 0 -522px !important; }
-.htmlarea-action-cell-split { background-position: 0 -580px !important; }
-.htmlarea-action-character-insert-from-map { background-position: 0 -638px !important; }
-.htmlarea-action-citation { background-position: 0 -696px !important; }
-.htmlarea-action-code { background-position: 0 -754px !important; }
-.htmlarea-action-color-background { background-position: 0 -812px !important; }
-.htmlarea-action-color-foreground { background-position: 0 -870px !important; }
-.htmlarea-action-column-delete { background-position: 0 -928px !important; }
-.htmlarea-action-column-edit-properties { background-position: 0 -986px !important; }
-.htmlarea-action-column-insert-after { background-position: 0 -1044px !important; }
-.htmlarea-action-column-insert-before { background-position: 0 -1102px !important; }
-.htmlarea-action-column-split { background-position: 0 -1160px !important; }
-.htmlarea-action-copy { background-position: 0 -1218px !important; }
-.htmlarea-action-cut { background-position: 0 -1276px !important; }
-.htmlarea-action-definition-list-item { background-position: 0 -1334px !important; }
-.htmlarea-action-definition-list { background-position: 0 -1392px !important; }
-.htmlarea-action-definition { background-position: 0 -1450px !important; }
-.htmlarea-action-delete-item { background-position: 0 -1508px !important; }
-.htmlarea-action-deleted-text { background-position: 0 -1566px !important; }
-.htmlarea-action-editor-show-about { background-position: 0 -1624px !important; }
-.htmlarea-action-editor-toggle-mode { background-position: 0 -1682px !important; }
-.htmlarea-action-emphasis { background-position: 0 -1740px !important; }
-.htmlarea-action-find-replace { background-position: 0 -1798px !important; }
-.htmlarea-action-horizontal-rule-insert { background-position: 0 -1856px !important; }
-.htmlarea-action-image-edit { background-position: 0 -1914px !important; }
-.htmlarea-action-indent { background-position: 0 -1972px !important; }
-.htmlarea-action-inserted-text { background-position: 0 -2030px !important; }
-.htmlarea-action-italic { background-position: 0 -2088px !important; }
-.htmlarea-action-justify-center { background-position: 0 -2146px !important; }
-.htmlarea-action-justify-full { background-position: 0 -2204px !important; }
-.htmlarea-action-justify-left { background-position: 0 -2262px !important; }
-.htmlarea-action-justify-right { background-position: 0 -2320px !important; }
-.htmlarea-action-keyboard { background-position: 0 -2378px !important; }
-.htmlarea-action-language-marks-show { background-position: 0 -2436px !important; }
-.htmlarea-action-link-edit { background-position: 0 -2494px !important; }
-.htmlarea-action-mono-spaced { background-position: 0 -2552px !important; }
-.htmlarea-action-ordered-list { background-position: 0 -2610px !important; }
-.htmlarea-action-outdent { background-position: 0 -2668px !important; }
-.htmlarea-action-paragraph-insert-after { background-position: 0 -2726px !important; }
-.htmlarea-action-paragraph-insert-before { background-position: 0 -2784px !important; }
-.htmlarea-action-paste-as-plain-text { background-position: 0 -2842px !important; }
-.htmlarea-action-paste { background-position: 0 -2900px !important; }
-.htmlarea-action-quotation { background-position: 0 -2958px !important; }
-.htmlarea-action-redo { background-position: 0 -3016px !important; }
-.htmlarea-action-remove-format { background-position: 0 -3074px !important; }
-.htmlarea-action-row-delete { background-position: 0 -3132px !important; }
-.htmlarea-action-row-edit-properties { background-position: 0 -3190px !important; }
-.htmlarea-action-row-insert-above { background-position: 0 -3248px !important; }
-.htmlarea-action-row-insert-under { background-position: 0 -3306px !important; }
-.htmlarea-action-row-split { background-position: 0 -3364px !important; }
-.htmlarea-action-sample { background-position: 0 -3422px !important; }
-.htmlarea-action-small { background-position: 0 -3480px !important; }
-.htmlarea-action-smiley-insert { background-position: 0 -3538px !important; }
-.htmlarea-action-span { background-position: 0 -3596px !important; }
-.htmlarea-action-spell-check { background-position: 0 -3654px !important; }
-.htmlarea-action-strike-through { background-position: 0 -3712px !important; }
-.htmlarea-action-strong { background-position: 0 -3770px !important; }
-.htmlarea-action-subscript { background-position: 0 -3828px !important; }
-.htmlarea-action-superscript { background-position: 0 -3886px !important; }
-.htmlarea-action-table-edit-properties { background-position: 0 -3944px !important; }
-.htmlarea-action-table-insert { background-position: 0 -4002px !important; }
-.htmlarea-action-table-restyle { background-position: 0 -4060px !important; }
-.htmlarea-action-table-show-borders { background-position: 0 -4118px !important; }
-.htmlarea-action-tag-insert { background-position: 0 -4176px !important; }
-.htmlarea-action-text-direction-left-to-right { background-position: 0 -4234px !important; }
-.htmlarea-action-text-direction-right-to-left { background-position: 0 -4292px !important; }
-.htmlarea-action-underline { background-position: 0 -4350px !important; }
-.htmlarea-action-undo { background-position: 0 -4408px !important; }
-.htmlarea-action-unlink { background-position: 0 -4466px !important; }
-.htmlarea-action-unordered-list { background-position: 0 -4524px !important; }
-.htmlarea-action-user-element-edit { background-position: 0 -4582px !important; }
-.htmlarea-action-variable { background-position: 0 -4640px !important; }
+.htmlarea-action-abbreviation-edit{ background-position: 0 0 !important; }
+.htmlarea-action-bidi-override{ background-position: 0 -58px !important; }
+.htmlarea-action-big{ background-position: 0 -116px !important; }
+.htmlarea-action-blockquote{ background-position: 0 -174px !important; }
+.htmlarea-action-bold{ background-position: 0 -232px !important; }
+.htmlarea-action-cell-delete{ background-position: 0 -290px !important; }
+.htmlarea-action-cell-edit-properties{ background-position: 0 -348px !important; }
+.htmlarea-action-cell-insert-after{ background-position: 0 -406px !important; }
+.htmlarea-action-cell-insert-before{ background-position: 0 -464px !important; }
+.htmlarea-action-cell-merge{ background-position: 0 -522px !important; }
+.htmlarea-action-cell-split{ background-position: 0 -580px !important; }
+.htmlarea-action-character-insert-from-map{ background-position: 0 -638px !important; }
+.htmlarea-action-citation{ background-position: 0 -696px !important; }
+.htmlarea-action-code{ background-position: 0 -754px !important; }
+.htmlarea-action-color-background{ background-position: 0 -812px !important; }
+.htmlarea-action-color-foreground{ background-position: 0 -870px !important; }
+.htmlarea-action-column-delete{ background-position: 0 -928px !important; }
+.htmlarea-action-column-edit-properties{ background-position: 0 -986px !important; }
+.htmlarea-action-column-insert-after{ background-position: 0 -1044px !important; }
+.htmlarea-action-column-insert-before{ background-position: 0 -1102px !important; }
+.htmlarea-action-column-split{ background-position: 0 -1160px !important; }
+.htmlarea-action-copy{ background-position: 0 -1218px !important; }
+.htmlarea-action-cut{ background-position: 0 -1276px !important; }
+.htmlarea-action-definition-list-item{ background-position: 0 -1334px !important; }
+.htmlarea-action-definition-list{ background-position: 0 -1392px !important; }
+.htmlarea-action-definition{ background-position: 0 -1450px !important; }
+.htmlarea-action-delete-item{ background-position: 0 -1508px !important; }
+.htmlarea-action-deleted-text{ background-position: 0 -1566px !important; }
+.htmlarea-action-editor-show-about{ background-position: 0 -1624px !important; }
+.htmlarea-action-editor-toggle-mode{ background-position: 0 -1682px !important; }
+.htmlarea-action-emphasis{ background-position: 0 -1740px !important; }
+.htmlarea-action-find-replace{ background-position: 0 -1798px !important; }
+.htmlarea-action-horizontal-rule-insert{ background-position: 0 -1856px !important; }
+.htmlarea-action-image-edit{ background-position: 0 -1914px !important; }
+.htmlarea-action-indent{ background-position: 0 -1972px !important; }
+.htmlarea-action-inserted-text{ background-position: 0 -2030px !important; }
+.htmlarea-action-italic{ background-position: 0 -2088px !important; }
+.htmlarea-action-justify-center{ background-position: 0 -2146px !important; }
+.htmlarea-action-justify-full{ background-position: 0 -2204px !important; }
+.htmlarea-action-justify-left{ background-position: 0 -2262px !important; }
+.htmlarea-action-justify-right{ background-position: 0 -2320px !important; }
+.htmlarea-action-keyboard{ background-position: 0 -2378px !important; }
+.htmlarea-action-language-marks-show{ background-position: 0 -2436px !important; }
+.htmlarea-action-link-edit{ background-position: 0 -2494px !important; }
+.htmlarea-action-mono-spaced{ background-position: 0 -2552px !important; }
+.htmlarea-action-ordered-list{ background-position: 0 -2610px !important; }
+.htmlarea-action-outdent{ background-position: 0 -2668px !important; }
+.htmlarea-action-paragraph-insert-after{ background-position: 0 -2726px !important; }
+.htmlarea-action-paragraph-insert-before{ background-position: 0 -2784px !important; }
+.htmlarea-action-paste-behaviour{ background-position: 0 -2842px !important; }
+.htmlarea-action-paste-toggle{ background-position: 0 -2900px !important; }
+.htmlarea-action-paste{ background-position: 0 -2958px !important; }
+.htmlarea-action-quotation{ background-position: 0 -3016px !important; }
+.htmlarea-action-redo{ background-position: 0 -3074px !important; }
+.htmlarea-action-remove-format{ background-position: 0 -3132px !important; }
+.htmlarea-action-row-delete{ background-position: 0 -3190px !important; }
+.htmlarea-action-row-edit-properties{ background-position: 0 -3248px !important; }
+.htmlarea-action-row-insert-above{ background-position: 0 -3306px !important; }
+.htmlarea-action-row-insert-under{ background-position: 0 -3364px !important; }
+.htmlarea-action-row-split{ background-position: 0 -3422px !important; }
+.htmlarea-action-sample{ background-position: 0 -3480px !important; }
+.htmlarea-action-small{ background-position: 0 -3538px !important; }
+.htmlarea-action-smiley-insert{ background-position: 0 -3596px !important; }
+.htmlarea-action-span{ background-position: 0 -3654px !important; }
+.htmlarea-action-spell-check{ background-position: 0 -3712px !important; }
+.htmlarea-action-strike-through{ background-position: 0 -3770px !important; }
+.htmlarea-action-strong{ background-position: 0 -3828px !important; }
+.htmlarea-action-subscript{ background-position: 0 -3886px !important; }
+.htmlarea-action-superscript{ background-position: 0 -3944px !important; }
+.htmlarea-action-table-edit-properties{ background-position: 0 -4002px !important; }
+.htmlarea-action-table-insert{ background-position: 0 -4060px !important; }
+.htmlarea-action-table-restyle{ background-position: 0 -4118px !important; }
+.htmlarea-action-table-show-borders{ background-position: 0 -4176px !important; }
+.htmlarea-action-tag-insert{ background-position: 0 -4234px !important; }
+.htmlarea-action-text-direction-left-to-right{ background-position: 0 -4292px !important; }
+.htmlarea-action-text-direction-right-to-left{ background-position: 0 -4350px !important; }
+.htmlarea-action-underline{ background-position: 0 -4408px !important; }
+.htmlarea-action-undo{ background-position: 0 -4466px !important; }
+.htmlarea-action-unlink{ background-position: 0 -4524px !important; }
+.htmlarea-action-unordered-list{ background-position: 0 -4582px !important; }
+.htmlarea-action-user-element-edit{ background-position: 0 -4640px !important; }
+.htmlarea-action-variable{ background-position: 0 -4698px !important; }
<label index="Address">Address</label>
<label index="No font">No font</label>
<label index="No size">No font size</label>
+ <label index="rteSettings">Rich Text Editor</label>
+ <label index="rteResize">Make RTE resizable</label>
+ <label index="rteMaxHeight">Maximal height of resizable RTE in pixels</label>
</languageKey>
</data>
<orig_hash type="array">
background-position: 0 -15px;
}
/* Action icon selectors for toolbar, context menu and window headers */
-.htmlarea-action-abbreviation-edit { background-position: 0 0 !important; }
-.htmlarea-action-bidi-override { background-position: 0 -58px !important; }
-.htmlarea-action-big { background-position: 0 -116px !important; }
-.htmlarea-action-blockquote { background-position: 0 -174px !important; }
-.htmlarea-action-bold { background-position: 0 -232px !important; }
-.htmlarea-action-cell-delete { background-position: 0 -290px !important; }
-.htmlarea-action-cell-edit-properties { background-position: 0 -348px !important; }
-.htmlarea-action-cell-insert-after { background-position: 0 -406px !important; }
-.htmlarea-action-cell-insert-before { background-position: 0 -464px !important; }
-.htmlarea-action-cell-merge { background-position: 0 -522px !important; }
-.htmlarea-action-cell-split { background-position: 0 -580px !important; }
-.htmlarea-action-character-insert-from-map { background-position: 0 -638px !important; }
-.htmlarea-action-citation { background-position: 0 -696px !important; }
-.htmlarea-action-code { background-position: 0 -754px !important; }
-.htmlarea-action-color-background { background-position: 0 -812px !important; }
-.htmlarea-action-color-foreground { background-position: 0 -870px !important; }
-.htmlarea-action-column-delete { background-position: 0 -928px !important; }
-.htmlarea-action-column-edit-properties { background-position: 0 -986px !important; }
-.htmlarea-action-column-insert-after { background-position: 0 -1044px !important; }
-.htmlarea-action-column-insert-before { background-position: 0 -1102px !important; }
-.htmlarea-action-column-split { background-position: 0 -1160px !important; }
-.htmlarea-action-copy { background-position: 0 -1218px !important; }
-.htmlarea-action-cut { background-position: 0 -1276px !important; }
-.htmlarea-action-definition-list-item { background-position: 0 -1334px !important; }
-.htmlarea-action-definition-list { background-position: 0 -1392px !important; }
-.htmlarea-action-definition { background-position: 0 -1450px !important; }
-.htmlarea-action-delete-item { background-position: 0 -1508px !important; }
-.htmlarea-action-deleted-text { background-position: 0 -1566px !important; }
-.htmlarea-action-editor-show-about { background-position: 0 -1624px !important; }
-.htmlarea-action-editor-toggle-mode { background-position: 0 -1682px !important; }
-.htmlarea-action-emphasis { background-position: 0 -1740px !important; }
-.htmlarea-action-find-replace { background-position: 0 -1798px !important; }
-.htmlarea-action-horizontal-rule-insert { background-position: 0 -1856px !important; }
-.htmlarea-action-image-edit { background-position: 0 -1914px !important; }
-.htmlarea-action-indent { background-position: 0 -1972px !important; }
-.htmlarea-action-inserted-text { background-position: 0 -2030px !important; }
-.htmlarea-action-italic { background-position: 0 -2088px !important; }
-.htmlarea-action-justify-center { background-position: 0 -2146px !important; }
-.htmlarea-action-justify-full { background-position: 0 -2204px !important; }
-.htmlarea-action-justify-left { background-position: 0 -2262px !important; }
-.htmlarea-action-justify-right { background-position: 0 -2320px !important; }
-.htmlarea-action-keyboard { background-position: 0 -2378px !important; }
-.htmlarea-action-language-marks-show { background-position: 0 -2436px !important; }
-.htmlarea-action-link-edit { background-position: 0 -2494px !important; }
-.htmlarea-action-mono-spaced { background-position: 0 -2552px !important; }
-.htmlarea-action-ordered-list { background-position: 0 -2610px !important; }
-.htmlarea-action-outdent { background-position: 0 -2668px !important; }
-.htmlarea-action-paragraph-insert-after { background-position: 0 -2726px !important; }
-.htmlarea-action-paragraph-insert-before { background-position: 0 -2784px !important; }
-.htmlarea-action-paste-as-plain-text { background-position: 0 -2842px !important; }
-.htmlarea-action-paste { background-position: 0 -2900px !important; }
-.htmlarea-action-quotation { background-position: 0 -2958px !important; }
-.htmlarea-action-redo { background-position: 0 -3016px !important; }
-.htmlarea-action-remove-format { background-position: 0 -3074px !important; }
-.htmlarea-action-row-delete { background-position: 0 -3132px !important; }
-.htmlarea-action-row-edit-properties { background-position: 0 -3190px !important; }
-.htmlarea-action-row-insert-above { background-position: 0 -3248px !important; }
-.htmlarea-action-row-insert-under { background-position: 0 -3306px !important; }
-.htmlarea-action-row-split { background-position: 0 -3364px !important; }
-.htmlarea-action-sample { background-position: 0 -3422px !important; }
-.htmlarea-action-small { background-position: 0 -3480px !important; }
-.htmlarea-action-smiley-insert { background-position: 0 -3538px !important; }
-.htmlarea-action-span { background-position: 0 -3596px !important; }
-.htmlarea-action-spell-check { background-position: 0 -3654px !important; }
-.htmlarea-action-strike-through { background-position: 0 -3712px !important; }
-.htmlarea-action-strong { background-position: 0 -3770px !important; }
-.htmlarea-action-subscript { background-position: 0 -3828px !important; }
-.htmlarea-action-superscript { background-position: 0 -3886px !important; }
-.htmlarea-action-table-edit-properties { background-position: 0 -3944px !important; }
-.htmlarea-action-table-insert { background-position: 0 -4002px !important; }
-.htmlarea-action-table-restyle { background-position: 0 -4060px !important; }
-.htmlarea-action-table-show-borders { background-position: 0 -4118px !important; }
-.htmlarea-action-tag-insert { background-position: 0 -4176px !important; }
-.htmlarea-action-text-direction-left-to-right { background-position: 0 -4234px !important; }
-.htmlarea-action-text-direction-right-to-left { background-position: 0 -4292px !important; }
-.htmlarea-action-underline { background-position: 0 -4350px !important; }
-.htmlarea-action-undo { background-position: 0 -4408px !important; }
-.htmlarea-action-unlink { background-position: 0 -4466px !important; }
-.htmlarea-action-unordered-list { background-position: 0 -4524px !important; }
-.htmlarea-action-user-element-edit { background-position: 0 -4582px !important; }
-.htmlarea-action-variable { background-position: 0 -4640px !important; }
+.htmlarea-action-abbreviation-edit{ background-position: 0 0 !important; }
+.htmlarea-action-bidi-override{ background-position: 0 -58px !important; }
+.htmlarea-action-big{ background-position: 0 -116px !important; }
+.htmlarea-action-blockquote{ background-position: 0 -174px !important; }
+.htmlarea-action-bold{ background-position: 0 -232px !important; }
+.htmlarea-action-cell-delete{ background-position: 0 -290px !important; }
+.htmlarea-action-cell-edit-properties{ background-position: 0 -348px !important; }
+.htmlarea-action-cell-insert-after{ background-position: 0 -406px !important; }
+.htmlarea-action-cell-insert-before{ background-position: 0 -464px !important; }
+.htmlarea-action-cell-merge{ background-position: 0 -522px !important; }
+.htmlarea-action-cell-split{ background-position: 0 -580px !important; }
+.htmlarea-action-character-insert-from-map{ background-position: 0 -638px !important; }
+.htmlarea-action-citation{ background-position: 0 -696px !important; }
+.htmlarea-action-code{ background-position: 0 -754px !important; }
+.htmlarea-action-color-background{ background-position: 0 -812px !important; }
+.htmlarea-action-color-foreground{ background-position: 0 -870px !important; }
+.htmlarea-action-column-delete{ background-position: 0 -928px !important; }
+.htmlarea-action-column-edit-properties{ background-position: 0 -986px !important; }
+.htmlarea-action-column-insert-after{ background-position: 0 -1044px !important; }
+.htmlarea-action-column-insert-before{ background-position: 0 -1102px !important; }
+.htmlarea-action-column-split{ background-position: 0 -1160px !important; }
+.htmlarea-action-copy{ background-position: 0 -1218px !important; }
+.htmlarea-action-cut{ background-position: 0 -1276px !important; }
+.htmlarea-action-definition-list-item{ background-position: 0 -1334px !important; }
+.htmlarea-action-definition-list{ background-position: 0 -1392px !important; }
+.htmlarea-action-definition{ background-position: 0 -1450px !important; }
+.htmlarea-action-delete-item{ background-position: 0 -1508px !important; }
+.htmlarea-action-deleted-text{ background-position: 0 -1566px !important; }
+.htmlarea-action-editor-show-about{ background-position: 0 -1624px !important; }
+.htmlarea-action-editor-toggle-mode{ background-position: 0 -1682px !important; }
+.htmlarea-action-emphasis{ background-position: 0 -1740px !important; }
+.htmlarea-action-find-replace{ background-position: 0 -1798px !important; }
+.htmlarea-action-horizontal-rule-insert{ background-position: 0 -1856px !important; }
+.htmlarea-action-image-edit{ background-position: 0 -1914px !important; }
+.htmlarea-action-indent{ background-position: 0 -1972px !important; }
+.htmlarea-action-inserted-text{ background-position: 0 -2030px !important; }
+.htmlarea-action-italic{ background-position: 0 -2088px !important; }
+.htmlarea-action-justify-center{ background-position: 0 -2146px !important; }
+.htmlarea-action-justify-full{ background-position: 0 -2204px !important; }
+.htmlarea-action-justify-left{ background-position: 0 -2262px !important; }
+.htmlarea-action-justify-right{ background-position: 0 -2320px !important; }
+.htmlarea-action-keyboard{ background-position: 0 -2378px !important; }
+.htmlarea-action-language-marks-show{ background-position: 0 -2436px !important; }
+.htmlarea-action-link-edit{ background-position: 0 -2494px !important; }
+.htmlarea-action-mono-spaced{ background-position: 0 -2552px !important; }
+.htmlarea-action-ordered-list{ background-position: 0 -2610px !important; }
+.htmlarea-action-outdent{ background-position: 0 -2668px !important; }
+.htmlarea-action-paragraph-insert-after{ background-position: 0 -2726px !important; }
+.htmlarea-action-paragraph-insert-before{ background-position: 0 -2784px !important; }
+.htmlarea-action-paste-behaviour{ background-position: 0 -2842px !important; }
+.htmlarea-action-paste-toggle{ background-position: 0 -2900px !important; }
+.htmlarea-action-paste{ background-position: 0 -2958px !important; }
+.htmlarea-action-quotation{ background-position: 0 -3016px !important; }
+.htmlarea-action-redo{ background-position: 0 -3074px !important; }
+.htmlarea-action-remove-format{ background-position: 0 -3132px !important; }
+.htmlarea-action-row-delete{ background-position: 0 -3190px !important; }
+.htmlarea-action-row-edit-properties{ background-position: 0 -3248px !important; }
+.htmlarea-action-row-insert-above{ background-position: 0 -3306px !important; }
+.htmlarea-action-row-insert-under{ background-position: 0 -3364px !important; }
+.htmlarea-action-row-split{ background-position: 0 -3422px !important; }
+.htmlarea-action-sample{ background-position: 0 -3480px !important; }
+.htmlarea-action-small{ background-position: 0 -3538px !important; }
+.htmlarea-action-smiley-insert{ background-position: 0 -3596px !important; }
+.htmlarea-action-span{ background-position: 0 -3654px !important; }
+.htmlarea-action-spell-check{ background-position: 0 -3712px !important; }
+.htmlarea-action-strike-through{ background-position: 0 -3770px !important; }
+.htmlarea-action-strong{ background-position: 0 -3828px !important; }
+.htmlarea-action-subscript{ background-position: 0 -3886px !important; }
+.htmlarea-action-superscript{ background-position: 0 -3944px !important; }
+.htmlarea-action-table-edit-properties{ background-position: 0 -4002px !important; }
+.htmlarea-action-table-insert{ background-position: 0 -4060px !important; }
+.htmlarea-action-table-restyle{ background-position: 0 -4118px !important; }
+.htmlarea-action-table-show-borders{ background-position: 0 -4176px !important; }
+.htmlarea-action-tag-insert{ background-position: 0 -4234px !important; }
+.htmlarea-action-text-direction-left-to-right{ background-position: 0 -4292px !important; }
+.htmlarea-action-text-direction-right-to-left{ background-position: 0 -4350px !important; }
+.htmlarea-action-underline{ background-position: 0 -4408px !important; }
+.htmlarea-action-undo{ background-position: 0 -4466px !important; }
+.htmlarea-action-unlink{ background-position: 0 -4524px !important; }
+.htmlarea-action-unordered-list{ background-position: 0 -4582px !important; }
+.htmlarea-action-user-element-edit{ background-position: 0 -4640px !important; }
+.htmlarea-action-variable{ background-position: 0 -4698px !important; }