Added feature #9201: Integrate support for definition list into htmlArea RTE
authorStanislas Rolland <typo3@sjbr.ca>
Wed, 20 Aug 2008 16:08:11 +0000 (16:08 +0000)
committerStanislas Rolland <typo3@sjbr.ca>
Wed, 20 Aug 2008 16:08:11 +0000 (16:08 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@4013 709f56b5-9817-0410-a4d7-c38de5d9e867

ChangeLog
typo3/sysext/rtehtmlarea/ChangeLog
typo3/sysext/rtehtmlarea/doc/manual.sxw
typo3/sysext/rtehtmlarea/ext_localconf.php
typo3/sysext/rtehtmlarea/extensions/DefinitionList/class.tx_rtehtmlarea_definitionlist.php [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/DefinitionList/skin/htmlarea.css [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/DefinitionList/skin/images/definitionItem.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/DefinitionList/skin/images/definitionList.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/htmlarea/plugins/DefinitionList/definition-list.js [new file with mode: 0644]
typo3/sysext/rtehtmlarea/htmlarea/plugins/DefinitionList/locallang.xml [new file with mode: 0644]
typo3/sysext/rtehtmlarea/res/proc/pageTSConfig.txt

index 865e618..d52ca7b 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2008-08-20  Stanislas Rolland  <typo3@sjbr.ca>
+
+       * Added feature #9201: Integrate support for definition list into htmlArea RTE
+
 2008-08-20  Dmitry Dulepov  <dmitry@typo3.org>
 
        * Fixed bug #5205: pi_loadLL() + no language file == full path disclosure
index 1e3c1fb..e15fafd 100644 (file)
@@ -1,3 +1,7 @@
+2008-08-20  Stanislas Rolland  <typo3@sjbr.ca>
+
+       * Added feature #9201: Integrate support for definition list into htmlArea RTE
+
 2008-08-19  Stanislas Rolland  <typo3@sjbr.ca>
 
        * Follow-up for issue #9185: Incorrect initialization when hooks are present
index 9c1e3ef..2741e55 100644 (file)
Binary files a/typo3/sysext/rtehtmlarea/doc/manual.sxw and b/typo3/sysext/rtehtmlarea/doc/manual.sxw differ
index c16a0f2..7438c1b 100644 (file)
@@ -65,6 +65,9 @@ $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['InlineCSS']['objectRefere
 $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['BlockElements'] = array();
 $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['BlockElements']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php:&tx_rtehtmlarea_blockelements';
 $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['BlockElements']['addIconsToSkin'] = 0;
+$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['DefinitionList'] = array();
+$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['DefinitionList']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/DefinitionList/class.tx_rtehtmlarea_definitionlist.php:&tx_rtehtmlarea_definitionlist';
+$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['DefinitionList']['addIconsToSkin'] = 0;
 $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['DynamicCSS'] = array();
 $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['DynamicCSS']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/DynamicCSS/class.tx_rtehtmlarea_dynamiccss.php:&tx_rtehtmlarea_dynamiccss';
 $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['BlockStyle'] = array();
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefinitionList/class.tx_rtehtmlarea_definitionlist.php b/typo3/sysext/rtehtmlarea/extensions/DefinitionList/class.tx_rtehtmlarea_definitionlist.php
new file mode 100644 (file)
index 0000000..0f8cae2
--- /dev/null
@@ -0,0 +1,102 @@
+<?php\r
+/***************************************************************\r
+*  Copyright notice\r
+*\r
+*  (c) 2008 Stanislas Rolland <typo3(arobas)sjbr.ca>\r
+*  All rights reserved\r
+*\r
+*  This script is part of the Typo3 project. The Typo3 project is\r
+*  free software; you can redistribute it and/or modify\r
+*  it under the terms of the GNU General Public License as published by\r
+*  the Free Software Foundation; either version 2 of the License, or\r
+*  (at your option) any later version.\r
+*\r
+*  The GNU General Public License can be found at\r
+*  http://www.gnu.org/copyleft/gpl.html.\r
+*\r
+*  This script is distributed in the hope that it will be useful,\r
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*  GNU General Public License for more details.\r
+*\r
+*  This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/**\r
+ * Definition List plugin for htmlArea RTE\r
+ *\r
+ * @author Stanislas Rolland <typo3(arobas)sjbr.ca>\r
+ *\r
+ * TYPO3 SVN ID: $Id: class.tx_rtehtmlarea_definitionlist.php  $\r
+ *\r
+ */\r
+\r
+require_once(t3lib_extMgm::extPath('rtehtmlarea').'class.tx_rtehtmlareaapi.php');\r
+\r
+class tx_rtehtmlarea_definitionlist extends tx_rtehtmlareaapi {\r
+\r
+       protected $extensionKey = 'rtehtmlarea';                // The key of the extension that is extending htmlArea RTE\r
+       protected $pluginName = 'DefinitionList';                       // The name of the plugin registered by the extension\r
+       protected $relativePathToLocallangFile = '';                    // Path to this main locallang file of the extension relative to the extension dir.\r
+       protected $relativePathToSkin = 'extensions/DefinitionList/skin/htmlarea.css';          // Path to the skin (css) file relative to the extension dir.\r
+       protected $htmlAreaRTE;                                         // Reference to the invoking object\r
+       protected $thisConfig;                                          // Reference to RTE PageTSConfig\r
+       protected $toolbar;                                             // Reference to RTE toolbar array\r
+       protected $LOCAL_LANG;                                          // Frontend language array\r
+       \r
+       protected $pluginButtons = 'definitionlist, definitionitem';\r
+               \r
+       protected $convertToolbarForHtmlAreaArray = array (\r
+               'definitionlist'        => 'DefinitionList',\r
+               'definitionitem'        => 'DefinitionItem',\r
+               );\r
+       \r
+       public function main($parentObject) {\r
+               global $TYPO3_CONF_VARS;\r
+               \r
+               return parent::main($parentObject) && $this->htmlAreaRTE->isPluginEnabled('BlockElements');\r
+       }\r
+       \r
+       /**\r
+        * Return JS configuration of the htmlArea plugins registered by the extension\r
+        *\r
+        * @param       integer         Relative id of the RTE editing area in the form\r
+        *\r
+        * @return string               JS configuration for registered plugins\r
+        *\r
+        * The returned string will be a set of JS instructions defining the configuration that will be provided to the plugin(s)\r
+        * Each of the instructions should be of the form:\r
+        *      RTEarea['.$RTEcounter.'].buttons.button-id.property = "value";\r
+        */\r
+       public function buildJavascriptConfiguration($RTEcounter) {\r
+               global $TSFE, $LANG;\r
+               \r
+               $registerRTEinJavascriptString = '';\r
+               return $registerRTEinJavascriptString;\r
+       }\r
+       \r
+       /**\r
+        * Return an updated array of toolbar enabled buttons\r
+        *\r
+        * @param       array           $show: array of toolbar elements that will be enabled, unless modified here\r
+        *\r
+        * @return      array           toolbar button array, possibly updated\r
+        */\r
+       public function applyToolbarConstraints($show) {\r
+               $blockElementsButtons = 'formatblock, indent, outdent, blockquote, insertparagraphbefore, insertparagraphafter, left, center, right, justifyfull, orderedlist, unorderedlist';\r
+               $notRemoved = array_intersect(t3lib_div::trimExplode(',', $blockElementsButtons, 1), $show);\r
+                       // DefinitionList plugin requires BlockElements plugin\r
+                       // We will not allow any definition lists operations if all block elements buttons were disabled\r
+               if (empty($notRemoved)) {\r
+                       return array_diff($show, t3lib_div::trimExplode(',', $this->pluginButtons));\r
+               } else {\r
+                       return $show;\r
+               }\r
+       }\r
+\r
+} // end of class\r
+\r
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/DefinitionList/class.tx_rtehtmlarea_definitionlist.php']) {\r
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/DefinitionList/class.tx_rtehtmlarea_definitionlist.php']);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefinitionList/skin/htmlarea.css b/typo3/sysext/rtehtmlarea/extensions/DefinitionList/skin/htmlarea.css
new file mode 100644 (file)
index 0000000..048a0e8
--- /dev/null
@@ -0,0 +1,4 @@
+/* Selectors for the Definition List extension of htmlArea RTE */\r
+/* TYPO3 SVN ID: $Id htmlarea.css $ */\r
+.htmlarea .toolbar .DefinitionList, .htmlarea-context-menu .DefinitionList {background-image:url("images/definitionList.gif");}\r
+.htmlarea .toolbar .DefinitionItem, .htmlarea-context-menu .DefinitionItem {background-image:url("images/definitionItem.gif");}\r
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefinitionList/skin/images/definitionItem.gif b/typo3/sysext/rtehtmlarea/extensions/DefinitionList/skin/images/definitionItem.gif
new file mode 100644 (file)
index 0000000..9181d39
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/DefinitionList/skin/images/definitionItem.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefinitionList/skin/images/definitionList.gif b/typo3/sysext/rtehtmlarea/extensions/DefinitionList/skin/images/definitionList.gif
new file mode 100644 (file)
index 0000000..2550fa4
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/DefinitionList/skin/images/definitionList.gif differ
diff --git a/typo3/sysext/rtehtmlarea/htmlarea/plugins/DefinitionList/definition-list.js b/typo3/sysext/rtehtmlarea/htmlarea/plugins/DefinitionList/definition-list.js
new file mode 100644 (file)
index 0000000..e730645
--- /dev/null
@@ -0,0 +1,340 @@
+/***************************************************************\r
+*  Copyright notice\r
+*\r
+*  (c) 2008 Stanislas Rolland <typo3(arobas)sjbr.ca>\r
+*  All rights reserved\r
+*\r
+*  This script is part of the TYPO3 project. The TYPO3 project is\r
+*  free software; you can redistribute it and/or modify\r
+*  it under the terms of the GNU General Public License as published by\r
+*  the Free Software Foundation; either version 2 of the License, or\r
+*  (at your option) any later version.\r
+*\r
+*  The GNU General Public License can be found at\r
+*  http://www.gnu.org/copyleft/gpl.html.\r
+*  A copy is found in the textfile GPL.txt and important notices to the license\r
+*  from the author is found in LICENSE.txt distributed with these scripts.\r
+*\r
+*\r
+*  This script is distributed in the hope that it will be useful,\r
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*  GNU General Public License for more details.\r
+*\r
+*\r
+*  This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/*\r
+ * DefinitionList Plugin for TYPO3 htmlArea RTE\r
+ *\r
+ * TYPO3 SVN ID: $Id: definition-list.js $\r
+ */\r
+DefinitionList = BlockElements.extend({\r
+               \r
+       constructor : function(editor, pluginName) {\r
+               this.base(editor, pluginName);\r
+       },\r
+       \r
+       /*\r
+        * This function gets called by the class constructor\r
+        */\r
+       configurePlugin : function (editor) {\r
+               \r
+               /*\r
+                * Setting up some properties from PageTSConfig\r
+                */\r
+               this.buttonsConfiguration = this.editorConfiguration.buttons;\r
+               var parentPlugin = this.editor.plugins.BlockElements.instance;\r
+               this.tags = parentPlugin.tags;\r
+               this.useClass = parentPlugin.useClass;\r
+               this.useBlockquote = parentPlugin.useBlockquote;\r
+               this.useAlignAttribute = parentPlugin.useAlignAttribute;\r
+               this.allowedBlockElements = parentPlugin.allowedBlockElements;\r
+               this.indentedList = null;\r
+               \r
+               /*\r
+                * Registering plugin "About" information\r
+                */\r
+               var pluginInformation = {\r
+                       version         : "0.4",\r
+                       developer       : "Stanislas Rolland",\r
+                       developerUrl    : "http://www.sjbr.ca/",\r
+                       copyrightOwner  : "Stanislas Rolland",\r
+                       sponsor         : this.localize("Technische Universitat Ilmenau"),\r
+                       sponsorUrl      : "http://www.tu-ilmenau.de/",\r
+                       license         : "GPL"\r
+               };\r
+               this.registerPluginInformation(pluginInformation);\r
+               \r
+               /*\r
+                * Registering the buttons\r
+                */\r
+               for (var buttonId in this.buttonList) {\r
+                       if (this.buttonList.hasOwnProperty(buttonId)) {\r
+                               var button = this.buttonList[buttonId];\r
+                               var buttonConfiguration = {\r
+                                       id              : buttonId,\r
+                                       tooltip         : this.localize(buttonId + "-Tooltip"),\r
+                                       action          : "onButtonPress",\r
+                                       context         : button[0],\r
+                                       hotKey          : (this.buttonsConfiguration[button[2]] ? this.buttonsConfiguration[button[2]].hotKey : (button[1] ? button[1] : null))\r
+                               };\r
+                               this.registerButton(buttonConfiguration);\r
+                       }\r
+               }\r
+               \r
+               return true;\r
+        },\r
+        \r
+       /*\r
+        * The list of buttons added by this plugin\r
+        */\r
+       buttonList : {\r
+               Indent                  : [null, "TAB", "indent"],\r
+               Outdent                 : [null, "SHIFT-TAB", "outdent"],\r
+               DefinitionList          : [null, null, "definitionlist"],\r
+               DefinitionItem          : ["dd,dt", null, "definitionitem"]\r
+       },\r
+       \r
+       /*\r
+        * This function gets called when a button was pressed.\r
+        *\r
+        * @param       object          editor: the editor instance\r
+        * @param       string          id: the button id or the key\r
+        * @param       object          target: the target element of the contextmenu event, when invoked from the context menu\r
+        *\r
+        * @return      boolean         false if action is completed\r
+        */\r
+       onButtonPress : function (editor, id, target) {\r
+                       // Could be a button or its hotkey\r
+               var buttonId = this.translateHotKey(id);\r
+               buttonId = buttonId ? buttonId : id;\r
+               this.editor.focusEditor();\r
+               var selection = editor._getSelection();\r
+               var range = editor._createRange(selection);\r
+               var parentElement = this.editor._statusBarTree.selected ? this.editor._statusBarTree.selected : this.editor.getParentElement(selection, range);\r
+               if (target) {\r
+                       parentElement = target;\r
+               }\r
+               while (parentElement && (!HTMLArea.isBlockElement(parentElement) || /^(li)$/i.test(parentElement.nodeName))) {\r
+                       parentElement = parentElement.parentNode;\r
+               }\r
+               \r
+               switch (buttonId) {\r
+                       case "Indent" :\r
+                               if (/^(dd|dt)$/i.test(parentElement.nodeName) && this.indentDefinitionList(parentElement, range)) {\r
+                                       break;\r
+                               } else {\r
+                                       this.base(editor, id, target);\r
+                               }\r
+                               break;\r
+                       case "Outdent" :\r
+                               if (/^(dt)$/i.test(parentElement.nodeName) && this.outdentDefinitionList(selection, range)) {\r
+                                       break;\r
+                               } else {\r
+                                       this.base(editor, id, target);\r
+                               }\r
+                               break;\r
+                       case "DefinitionList":\r
+                               var bookmark = this.editor.getBookmark(range);\r
+                               this.insertDefinitionList();\r
+                               this.editor.selectRange(this.editor.moveToBookmark(bookmark));\r
+                               break;\r
+                       case "DefinitionItem":\r
+                               var bookmark = this.editor.getBookmark(range);\r
+                               this.remapNode(parentElement, (parentElement.nodeName.toLowerCase() === "dt") ? "dd" : "dt");\r
+                               this.editor.selectRange(this.editor.moveToBookmark(bookmark));\r
+                               break;\r
+                       default:\r
+                               this.base(editor, id, target);\r
+               }\r
+               return false;\r
+       },\r
+       \r
+       /*\r
+        * This function remaps a node to the specified node name\r
+        */\r
+       remapNode : function(node, nodeName) {\r
+               var newNode = this.editor.convertNode(node, nodeName);\r
+               var attributes = node.attributes, attributeName, attributeValue;\r
+               for (var i = attributes.length; --i >= 0;) {\r
+                       attributeName = attributes.item(i).nodeName;\r
+                       attributeValue = node.getAttribute(attributeName);\r
+                       if (attributeValue) newNode.setAttribute(attributeName, attributeValue);\r
+               }\r
+                       // In IE, the above fails to update the classname and style attributes.\r
+               if (HTMLArea.is_ie) {\r
+                       if (node.style.cssText) {\r
+                               newNode.style.cssText = node.style.cssText;\r
+                       }\r
+                       if (node.className) {\r
+                               newNode.setAttribute("className", node.className);\r
+                       } else {\r
+                               newNode.removeAttribute("className");\r
+                       }\r
+               }\r
+               \r
+               if (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses) {\r
+                       if (newNode.className && /\S/.test(newNode.className)) {\r
+                               var allowedClasses = this.tags[nodeName].allowedClasses;\r
+                               var classNames = newNode.className.trim().split(" ");\r
+                               for (var i = classNames.length; --i >= 0;) {\r
+                                       if (!allowedClasses.test(classNames[i])) {\r
+                                               HTMLArea._removeClass(newNode, classNames[i]);\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               return newNode;\r
+       },\r
+       \r
+       /*\r
+        * Insert a definition list\r
+        */\r
+       insertDefinitionList : function () {\r
+               var selection = this.editor._getSelection();\r
+               var endBlocks = this.editor.getEndBlocks(selection);\r
+               var list = null;\r
+               if (this.editor._selectionEmpty(selection)) {\r
+                       if (/^(body|div|address|pre|blockquote|li|td|dd)$/i.test(endBlocks.start.nodeName)) {\r
+                               list = this.editor._doc.createElement("dl");\r
+                               var term = list.appendChild(this.editor._doc.createElement("dt"));\r
+                               while (endBlocks.start.firstChild) {\r
+                                       term.appendChild(endBlocks.start.firstChild);\r
+                               }\r
+                               list = endBlocks.start.appendChild(list);\r
+                       } else if (/^(p|h[1-6])$/i.test(endBlocks.start.nodeName)) {\r
+                               var list = endBlocks.start.parentNode.insertBefore(this.editor._doc.createElement("dl"), endBlocks.start);\r
+                               endBlocks.start = list.appendChild(endBlocks.start);\r
+                               endBlocks.start = this.remapNode(endBlocks.start, "dt");\r
+                       }\r
+               } else if (endBlocks.start != endBlocks.end && /^(p|h[1-6])$/i.test(endBlocks.start.nodeName)) {\r
+                               // We wrap the selected elements in a dl element\r
+                       var paragraphs = endBlocks.start.nodeName.toLowerCase() === "p";\r
+                       list = this.wrapSelectionInBlockElement("dl");\r
+                       var items = list.childNodes;\r
+                       for (var i = 0, n = items.length; i < n; ++i) {\r
+                               var paragraphItem = items[i].nodeName.toLowerCase() === "p";\r
+                               this.remapNode(items[i],  paragraphs ? ((i % 2) ? "dd" : "dt") : (paragraphItem ? "dd" : "dt"));\r
+                       }\r
+               }\r
+               return list;\r
+       },\r
+       \r
+       /*\r
+        * Indent a definition list\r
+        */\r
+       indentDefinitionList : function (parentElement, range) {\r
+               var selection = this.editor._getSelection();\r
+               var endBlocks = this.editor.getEndBlocks(selection);\r
+               if (this.editor._selectionEmpty(selection) && /^dd$/i.test(parentElement.nodeName)) {\r
+                       var list = parentElement.appendChild(this.editor._doc.createElement("dl"));\r
+                       var term = list.appendChild(this.editor._doc.createElement("dt"));\r
+                       if (HTMLArea.is_gecko) {\r
+                               if (HTMLArea.is_safari) {\r
+                                       term.innerHTML = "<br />";\r
+                               } else {\r
+                                       term.appendChild(this.editor._doc.createTextNode(""));\r
+                               }\r
+                       } else {\r
+                               term.innerHTML = "\x20";\r
+                       }\r
+                       this.editor.selectNodeContents(term, false);\r
+                       return true;\r
+               } else if (endBlocks.start && /^dt$/i.test(endBlocks.start.nodeName) && endBlocks.start.previousSibling) {\r
+                       var sibling = endBlocks.start.previousSibling;\r
+                       var bookmark = this.editor.getBookmark(range);\r
+                       if (/^dd$/i.test(sibling.nodeName)) {\r
+                               var list = this.wrapSelectionInBlockElement("dl");\r
+                               list = sibling.appendChild(list);\r
+                                       // May need to merge the list if it has a previous sibling\r
+                               if (list.previousSibling && /^dl$/i.test(list.previousSibling.nodeName)) {\r
+                                       while (list.firstChild) {\r
+                                               list.previousSibling.appendChild(list.firstChild);\r
+                                       }\r
+                                       HTMLArea.removeFromParent(list);\r
+                               }\r
+                       } else if (/^dt$/i.test(sibling.nodeName)) {\r
+                               var definition = this.editor._doc.createElement("dd");\r
+                               definition.appendChild(this.wrapSelectionInBlockElement("dl"));\r
+                               sibling.parentNode.insertBefore(definition, sibling.nextSibling);\r
+                       }\r
+                       this.editor.selectRange(this.editor.moveToBookmark(bookmark));\r
+                       return true;\r
+               }\r
+               return false;\r
+       },\r
+       \r
+       /*\r
+        * Outdent a definition list\r
+        */\r
+       outdentDefinitionList : function (selection, range) {\r
+               var endBlocks = this.editor.getEndBlocks(selection);\r
+               if (/^dt$/i.test(endBlocks.start.nodeName)\r
+                               && /^dl$/i.test(endBlocks.start.parentNode.nodeName)\r
+                               && /^dd$/i.test(endBlocks.start.parentNode.parentNode.nodeName)\r
+                               && !endBlocks.end.nextSibling) {\r
+                       var bookmark = this.editor.getBookmark(range);\r
+                       var dl = endBlocks.start.parentNode;\r
+                       var dd = dl.parentNode;\r
+                       if (this.editor._selectionEmpty(selection)) {\r
+                               dd.parentNode.insertBefore(endBlocks.start, dd.nextSibling);\r
+                       } else {\r
+                               var selected = this.wrapSelectionInBlockElement("dl");\r
+                               while (selected.lastChild) {\r
+                                       dd.parentNode.insertBefore(selected.lastChild, dd.nextSibling);\r
+                               }\r
+                               selected.parentNode.removeChild(selected);\r
+                       }\r
+                               // We may have outdented all the child nodes of a list\r
+                       if (!dl.hasChildNodes()) {\r
+                               dd.removeChild(dl);\r
+                               if (!dd.hasChildNodes()) {\r
+                                       dd.parentNode.removeChild(dd);\r
+                               }\r
+                       }\r
+                       this.editor.selectRange(this.editor.moveToBookmark(bookmark));\r
+                       return true;\r
+               }\r
+               return false;\r
+       },\r
+       \r
+       /*\r
+        * This function gets called when the toolbar is updated\r
+        */\r
+       onUpdateToolbar : function () {\r
+               if (this.editor.getMode() === "textmode" || !this.editor.isEditable()) {\r
+                       return false;\r
+               }\r
+               var parentElement = this.editor._statusBarTree.selected ? this.editor._statusBarTree.selected : this.editor.getParentElement();\r
+               if (parentElement.nodeName.toLowerCase() === "body") return false;\r
+               while (parentElement && (!HTMLArea.isBlockElement(parentElement) || /^(li)$/i.test(parentElement.nodeName))) {\r
+                       parentElement = parentElement.parentNode;\r
+               }\r
+               var blockAncestors = this.getBlockAncestors(parentElement);\r
+               var selection = this.editor._getSelection();\r
+               var endBlocks = this.editor.getEndBlocks(selection);\r
+               for (var buttonId in this.buttonList) {\r
+                       commandState = false;\r
+                       if (this.buttonList.hasOwnProperty(buttonId) && this.isButtonInToolbar(buttonId)) {\r
+                               switch (buttonId) {\r
+                                       case "Outdent" :\r
+                                               if (/^(dt)$/i.test(endBlocks.start.nodeName)\r
+                                                               && /^(dl)$/i.test(endBlocks.start.parentNode.nodeName)\r
+                                                               && /^(dd)$/i.test(endBlocks.start.parentNode.parentNode.nodeName)\r
+                                                               && !endBlocks.end.nextSibling) {\r
+                                                       this.editor._toolbarObjects[buttonId].state("enabled", true);\r
+                                               } else {\r
+                                                       this.base();\r
+                                               }\r
+                                               break;\r
+                                       case "DefinitionList" :\r
+                                               this.editor._toolbarObjects[buttonId].state("enabled", (this.editor._selectionEmpty() && /^(p|div|address|pre|blockquote|h[1-6]|li|td|dd)$/i.test(endBlocks.start.nodeName))\r
+                                                                                                       || (endBlocks.start != endBlocks.end && /^(p|h[1-6])$/i.test(endBlocks.start.nodeName)));\r
+                                               break;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+});\r
+\r
diff --git a/typo3/sysext/rtehtmlarea/htmlarea/plugins/DefinitionList/locallang.xml b/typo3/sysext/rtehtmlarea/htmlarea/plugins/DefinitionList/locallang.xml
new file mode 100644 (file)
index 0000000..1666397
--- /dev/null
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\r
+<!-- TYPO3 SVN ID: $Id: locallang.xml 2975 2008-01-29 23:01:39Z stanrolland $ -->\r
+<T3locallang>\r
+       <meta type="array">\r
+               <description>Labels for Definition List plugin of htmlArea RTE</description>\r
+               <type>module</type>\r
+       </meta>\r
+       <data type="array">\r
+               <languageKey index="default" type="array">\r
+                       <label index="Indent-Tooltip">Increase indent</label>\r
+                       <label index="Outdent-Tooltip">Reduce indent</label>\r
+                       <label index="DefinitionList-Tooltip">Definition list</label>\r
+                       <label index="DefinitionItem-Tooltip">Toggle term and definition</label>\r
+                       <label index="No block">No block format</label>\r
+                       <label index="Remove block">Remove block format</label>\r
+                       <label index="Technische Universitat Ilmenau">Technische Universit├Ąt Ilmenau</label>\r
+               </languageKey>\r
+       </data>\r
+       <orig_hash type="array">\r
+               <languageKey index="default" type="array">\r
+               </languageKey>\r
+       </orig_hash>\r
+       <orig_text type="array">\r
+               <languageKey index="default" type="array">\r
+               </languageKey>\r
+       </orig_text>\r
+</T3locallang>
\ No newline at end of file
index 11c4742..ffa248a 100644 (file)
@@ -40,7 +40,7 @@ RTE.default.proc {
                ## b and i will be remapped on exit (see below).
                ## Note that the link accessibility feature of htmlArea RTE does insert img tags.
        allowTags (
-               a, abbr, acronym, address, b, bdo, big, blockquote, br, caption, center, cite, code, col, colgroup, del, dfn, div, em, font,
+               a, abbr, acronym, address, b, bdo, big, blockquote, br, caption, center, cite, code, col, colgroup, dd, del, dfn, dl, div, dt, em, font,
                h1, h2, h3, h4, h5, h6, hr, i, img, ins, kbd, label, li, link, meta, ol, p, pre, q, samp, sdfield, small,
                span, strike, strong, style, sub, sup, table, thead, tbody, tfoot, td, th, tr, title, tt, u, ul, var
                )