* (major) Feature: Improved behaviour and configuration options of formatblock and...
authorStanislas Rolland <typo3@sjbr.ca>
Sat, 5 Jan 2008 19:32:58 +0000 (19:32 +0000)
committerStanislas Rolland <typo3@sjbr.ca>
Sat, 5 Jan 2008 19:32:58 +0000 (19:32 +0000)
* Feature:  Added buttons insertparagraphbefore, insertparagraphafter and blockquote
* Feature:  Added Page TSConfig RTE sub-array mutuallyExclusiveClasses
* Fixed issue 5952 (partial): Usability Issue with classes wrapped with <> in select lists
* Fixed issue 5951: Disturbing behaviour of indent/outdent and TAB
* Added feature 3708 (partial): support for <blockquote>
* Fixed issue 5977: align="center" (right or left) not any more supported by W3C
* Fixed issue 6837: Strange layout for header N except the first one (Safari)

git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@2862 709f56b5-9817-0410-a4d7-c38de5d9e867

59 files changed:
ChangeLog
typo3/sysext/rtehtmlarea/ChangeLog
typo3/sysext/rtehtmlarea/class.tx_rtehtmlarea_base.php
typo3/sysext/rtehtmlarea/class.tx_rtehtmlareaapi.php
typo3/sysext/rtehtmlarea/doc/manual.sxw
typo3/sysext/rtehtmlarea/ext_emconf.php
typo3/sysext/rtehtmlarea/ext_localconf.php
typo3/sysext/rtehtmlarea/extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/BlockElements/locallang.xml [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/htmlarea.css [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/blockquote.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/indent.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/insertParagraphAfter.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/insertParagraphBefore.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyCenter.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyFull.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyLeft.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyRight.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/outdent.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/BlockStyle/class.tx_rtehtmlarea_blockstyle.php [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/BlockStyle/locallang.xml [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/DefaultInline/class.tx_rtehtmlarea_defaultinline.php
typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/htmlarea.css
typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/bold.gif [deleted file]
typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/italic.gif [deleted file]
typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/strikethrough.gif [deleted file]
typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/subscript.gif [deleted file]
typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/superscript.gif [deleted file]
typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/underline.gif [deleted file]
typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/bold.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/italic.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/strikethrough.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/subscript.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/superscript.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/underline.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/DynamicCSS/class.tx_rtehtmlarea_dynamiccss.php [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/DynamicCSS/locallang.xml [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineCSS/class.tx_rtehtmlarea_inlinecss.php
typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js
typo3/sysext/rtehtmlarea/htmlarea/htmlarea-ie.js
typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js
typo3/sysext/rtehtmlarea/htmlarea/locallang_dialogs.xml
typo3/sysext/rtehtmlarea/htmlarea/locallang_tooltips.xml
typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/block-elements.js [new file with mode: 0644]
typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/locallang.xml [new file with mode: 0644]
typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/block-style.js [new file with mode: 0644]
typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/locallang.xml [new file with mode: 0644]
typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/context-menu.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultInline/default-inline.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/DynamicCSS/dynamiccss.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineCSS/inlinecss.js
typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Browsers/typo3browsers.js
typo3/sysext/rtehtmlarea/locallang.xml
typo3/sysext/rtehtmlarea/pi2/class.tx_rtehtmlarea_pi2.php
typo3/sysext/rtehtmlarea/res/contentcss/default.css [new file with mode: 0644]
typo3/sysext/rtehtmlarea/res/contentcss/img/red_arrow_bullet.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/res/demo/pageTSConfig.txt
typo3/sysext/rtehtmlarea/res/proc/pageTSConfig.txt
typo3/sysext/rtehtmlarea/res/typical/pageTSConfig.txt

index 68e664c..14175ba 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2008-01-05  Stanislas Rolland  <stanislas.rolland@fructifor.ca>
+
+       * (major) Feature: Improved behaviour and configuration options of formatblock and blockstyle drop-down lists
+       * Feature:  Added buttons insertparagraphbefore, insertparagraphafter and blockquote
+       * Feature:  Added Page TSConfig RTE sub-array mutuallyExclusiveClasses
+       * Fixed issue 5952 (partial): Usability Issue with classes wrapped with <> in select lists
+       * Fixed issue 5951: Disturbing behaviour of indent/outdent and TAB
+       * Added feature 3708 (partial): support for <blockquote>
+       * Fixed issue 5977: align="center" (right or left) not any more supported by W3C
+       * Fixed issue 6837: Strange layout for header N except the first one (Safari)
+
 2007-12-30  Stanislas Rolland  <stanislas.rolland@fructifor.ca>
 
        * Feature/bugfix: Fixing icons for Opera and adding new icons in default skin of htmlArea RTE and in t3skin/rtehtmlarea
index 573e636..333124c 100644 (file)
@@ -1,3 +1,14 @@
+2008-01-05  Stanislas Rolland  <stanislas.rolland@fructifor.ca>
+
+       * (major) Feature: Improved behaviour and configuration options of formatblock and blockstyle drop-down lists
+       * Feature:  Added buttons insertparagraphbefore, insertparagraphafter and blockquote
+       * Feature:  Added Page TSConfig RTE sub-array mutuallyExclusiveClasses
+       * Fixed issue 5952 (partial): Usability Issue with classes wrapped with <> in select lists
+       * Fixed issue 5951: Disturbing behaviour of indent/outdent and TAB
+       * Added feature 3708 (partial): support for <blockquote>
+       * Fixed issue 5977: align="center" (right or left) not any more supported by W3C
+       * Fixed issue 6837: Strange layout for header N except the first one (Safari)
+
 2007-12-30  Stanislas Rolland  <stanislas.rolland@fructifor.ca>
 
        * Feature/bugfix: Fixing icons for Opera and adding new icons in default skin of htmlArea RTE and in t3skin/rtehtmlarea
index 27fda05..c0ba8b1 100644 (file)
@@ -88,7 +88,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
        var $defaultToolbarOrder;
 
                // The default hotkeys: the name is the TYPO3-button name
-       var $defaultHotKeyList = 'selectall, bold, italic, underline, strikethrough, left, center, right, justifyfull, formatblock, paste, cleanword, undo, redo';
+       var $defaultHotKeyList = 'selectall, cleanword, undo, redo';
 
                // Conversion array: TYPO3 button names to htmlArea button names
        var $convertToolbarForHtmlAreaArray = array (
@@ -97,13 +97,8 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                'fontsize'              => 'FontSize',
                'textcolor'             => 'ForeColor',
                'bgcolor'               => 'HiliteColor',
-               'left'                  => 'JustifyLeft',
-               'center'                => 'JustifyCenter',
-               'right'                 => 'JustifyRight',
                'orderedlist'           => 'InsertOrderedList',
                'unorderedlist'         => 'InsertUnorderedList',
-               'outdent'               => 'Outdent',
-               'indent'                => 'Indent',
                'emoticon'              => 'InsertSmiley',
                'line'                  => 'InsertHorizontalRule',
                'link'                  => 'CreateLink',
@@ -112,14 +107,12 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                'cut'                   => 'Cut',
                'copy'                  => 'Copy',
                'paste'                 => 'Paste',
-               'formatblock'           => 'FormatBlock',
                'chMode'                => 'HtmlMode',
                'user'                  => 'UserElements',
                
                        // htmlArea extra buttons
                'lefttoright'           => 'LeftToRight',
                'righttoleft'           => 'RightToLeft',
-               'justifyfull'           => 'JustifyFull',
                'showhelp'              => 'ShowHelp',
                'insertcharacter'       => 'InsertCharacter',
                'findreplace'           => 'FindReplace',
@@ -128,8 +121,6 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                'inserttag'             => 'InsertTag',
                'acronym'               => 'Acronym',
                'splitblock'            => 'SplitBlock',
-               'blockstylelabel'       => 'I[style]',
-               'blockstyle'            => 'DynamicCSS-class',
                'toggleborders'         => 'TO-toggle-borders',
                'tableproperties'       => 'TO-table-prop',
                'rowproperties'         => 'TO-row-prop',
@@ -160,18 +151,6 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                'about'                 => 'About',
                );
        
-       var $defaultParagraphs = array(
-               'p'             => 'Normal',
-               'h1'            => 'Heading 1',
-               'h2'            => 'Heading 2',
-               'h3'            => 'Heading 3',
-               'h4'            => 'Heading 4',
-               'h5'            => 'Heading 5',
-               'h6'            => 'Heading 6',
-               'pre'           => 'Preformatted',
-               'address'       => 'Address',
-               );
-       
        var $defaultFontFaces = array(
                'Arial'                 => 'Arial,sans-serif',
                'Arial Black'           => 'Arial Black,sans-serif',
@@ -204,10 +183,9 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                '7'     =>      'xxx-large (48px)',
                );
        
-       var $pluginList = 'TableOperations, ContextMenu, SpellChecker, SelectColor, TYPO3Browsers, InsertSmiley, FindReplace, RemoveFormat, CharacterMap, QuickTag, DynamicCSS, UserElements, Acronym, TYPO3HtmlParser';
+       var $pluginList = 'TableOperations, ContextMenu, SpellChecker, SelectColor, TYPO3Browsers, InsertSmiley, FindReplace, RemoveFormat, CharacterMap, QuickTag, UserElements, Acronym, TYPO3HtmlParser';
        
        var $pluginButton = array(
-               'DynamicCSS'            => 'blockstyle',
                'SpellChecker'          => 'spellcheck',
                'InsertSmiley'          => 'emoticon',
                'FindReplace'           => 'findreplace',
@@ -222,9 +200,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                'SelectColor'           => 'textcolor,bgcolor',
                );
 
-       var $pluginLabel = array(
-               'DynamicCSS'    => 'blockstylelabel',
-               );
+       var $pluginLabel = array();
 
        var $spellCheckerModes = array( 'ultra', 'fast', 'normal', 'bad-spellers');
 
@@ -314,7 +290,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                        if (!$rteIsAvailable) {
                                $this->errorLog[] = 'rte: Browser not supported. Only msie Version 5 or higher and Mozilla based client 1. and higher.';
                        }
-                       if (t3lib_div::int_from_ver(TYPO3_version) < 3007000) {
+                       if (t3lib_div::int_from_ver(TYPO3_version) < 4000000) {
                                $rteIsAvailable = 0;
                                $this->errorLog[] = 'rte: This version of htmlArea RTE cannot run under this version of TYPO3.';
                        }
@@ -457,11 +433,20 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                        $this->pluginEnabledArray = t3lib_div::trimExplode(',', $this->pluginList, 1);
                        $this->enableRegisteredPlugins();
                        $hidePlugins = array();
-                       if(!t3lib_extMgm::isLoaded('static_info_tables') || in_array($this->language, t3lib_div::trimExplode(',', $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['noSpellCheckLanguages']))) $hidePlugins[] = 'SpellChecker';
-                       if ($this->client['BROWSER'] == 'msie') $hidePlugins[] = 'Acronym';
+                       if (!t3lib_extMgm::isLoaded('static_info_tables') || in_array($this->language, t3lib_div::trimExplode(',', $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['noSpellCheckLanguages']))) $hidePlugins[] = 'SpellChecker';
+                       if ($this->client['BROWSER'] == 'msie') {
+                               //if ($this->client['VERSION'] < 7) {
+                                       $hidePlugins[] = 'Acronym';
+                               //}
+                               $this->thisConfig['keepButtonGroupTogether'] = 0;
+                       }
                        if ($this->client['BROWSER'] == 'opera') {
                                $hidePlugins[] = 'ContextMenu';
                                $this->thisConfig['hideTableOperationsInToolbar'] = 0;
+                               $this->thisConfig['keepButtonGroupTogether'] = 0;
+                       }
+                       if ($this->client['BROWSER'] == 'gecko' && $this->client['VERSION'] == '1.3')  {
+                               $this->thisConfig['keepButtonGroupTogether'] = 0;
                        }
                        $this->pluginEnabledArray = array_diff($this->pluginEnabledArray, $hidePlugins);
 
@@ -525,7 +510,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                         */
 
                                // Preloading the pageStyle
-                       $filename = trim($this->thisConfig['contentCSS']) ? trim($this->thisConfig['contentCSS']) : 'EXT:' . $this->ID . '/htmlarea/plugins/DynamicCSS/dynamiccss.css';
+                       $filename = trim($this->thisConfig['contentCSS']) ? trim($this->thisConfig['contentCSS']) : 'EXT:' . $this->ID . '/res/contentcss/default.css';
                        $this->TCEform->additionalCode_pre['loadCSS'] = '
                <link rel="alternate stylesheet" type="text/css" href="' . $this->getFullFileName($filename) . '" title="HTMLArea RTE Content CSS" />';
 
@@ -552,6 +537,10 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                        $this->TCEform->additionalCode_pre['loadCSS'] .= '
                <link rel="alternate stylesheet" type="text/css" href="' . $this->editedContentCSS . '" />';
                        
+                               // Main skin
+                       $this->TCEform->additionalCode_pre['loadCSS'] .= '
+               <link rel="stylesheet" type="text/css" href="' . $this->editorCSS . '" />';
+                       
                                // Additional icons from registered plugins
                        foreach ($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] as $pluginId) {
                                if (is_object($this->registeredPlugins[$pluginId])) {
@@ -562,9 +551,6 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                                        }
                                }
                        }
-                               // Main skin
-                       $this->TCEform->additionalCode_pre['loadCSS'] .= '
-               <link rel="stylesheet" type="text/css" href="' . $this->editorCSS . '" />';
                        
                                // Loading JavaScript files and code
                        $this->TCEform->additionalCode_pre['loadJSfiles'] = $this->loadJSfiles($this->TCEform->RTEcounter);
@@ -583,7 +569,8 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                                        $value = $plugin->transformContent($value);
                                }
                        }
-                       if ($this->client['BROWSER'] == 'msie') {
+                       //if ($this->client['BROWSER'] == 'msie') {
+                       if ($this->client['BROWSER'] == 'msie' && $this->client['VERSION'] < 7) {
                                        // change <abbr> to <acronym>
                                $value = preg_replace('/<(\/?)abbr/i', "<$1acronym", $value);
                        }
@@ -673,10 +660,11 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                global $BE_USER;
                
                $this->defaultToolbarOrder = 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak,
-                       bar, fontstyle, space, fontsize, space, formatblock,
-                       bar, bold, italic, underline, strikethrough, subscript, superscript,
-                       bar, lefttoright, righttoleft, bar, left, center, right, justifyfull,
-                       bar, orderedlist, unorderedlist, outdent, indent, bar, textcolor, bgcolor, textindicator,
+                       bar, inlineelement, bold,  strong, italic, emphasis, big, small, insertedtext, deletedtext, citation, code, definition, keyboard, monospaced, quotation, sample, variable, bidioverride, strikethrough, subscript, superscript, underline, span,
+                       bar, fontstyle, space, fontsize, bar, formatblock, insertparagraphbefore, insertparagraphafter, blockquote,
+                       bar, left, center, right, justifyfull,
+                       bar, orderedlist, unorderedlist, outdent, indent,  bar, lefttoright, righttoleft,
+                       bar, textcolor, bgcolor, textindicator,
                        bar, emoticon, insertcharacter, line, link, 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, bar, undo, redo, bar, showhelp, about, linebreak, 
                        ' . ($this->thisConfig['hideTableOperationsInToolbar'] ? '': 'bar, toggleborders,') . ' bar, tableproperties, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar,
@@ -686,7 +674,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                        // Special toolbar for Mozilla Wamcom on Mac OS 9
                if($this->client['BROWSER'] == 'gecko' && $this->client['VERSION'] == '1.3')  {
                        $this->defaultToolbarOrder = $this->TCEform->docLarge ? 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak,
-                               bar, fontstyle, space, fontsize, space, formatblock, bar, bold, italic, underline, strikethrough,
+                               bar, fontstyle, space, fontsize, space, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, bar, bold, italic, underline, strikethrough,
                                subscript, superscript, lefttoright, righttoleft, bar, left, center, right, justifyfull, linebreak,
                                bar, orderedlist, unorderedlist, outdent, indent, bar, textcolor, bgcolor, textindicator, bar, emoticon,
                                insertcharacter, line, link, image, table, user, acronym, bar, findreplace, spellcheck, bar, chMode, inserttag,
@@ -695,7 +683,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                                columninsertbefore, columninsertafter, columndelete, columnsplit, bar,
                                cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge'
                                : 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak,
-                               bar, fontstyle, space, fontsize, space, formatblock, bar, bold, italic, underline, strikethrough,
+                               bar, fontstyle, space, fontsize, space, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, bar, bold, italic, underline, strikethrough,
                                subscript, superscript, linebreak, bar, lefttoright, righttoleft, bar, left, center, right, justifyfull,
                                orderedlist, unorderedlist, outdent, indent, bar, textcolor, bgcolor, textindicator, bar, emoticon,
                                insertcharacter, line, link, image, table, user, acronym, linebreak, bar, findreplace, spellcheck, bar, chMode, inserttag,
@@ -1097,7 +1085,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                        RTEarea['.$RTEcounter.']["defaultPageStyle"] = "' . $this->hostURL . $this->writeTemporaryFile('', 'defaultPageStyle', 'css', $this->buildStyleSheet()) . '";';
                        
                        // Setting the pageStyle
-               $filename = trim($this->thisConfig['contentCSS']) ? trim($this->thisConfig['contentCSS']) : 'EXT:' . $this->ID . '/htmlarea/plugins/DynamicCSS/dynamiccss.css';
+               $filename = trim($this->thisConfig['contentCSS']) ? trim($this->thisConfig['contentCSS']) : 'EXT:' . $this->ID . '/res/contentcss/default.css';
                $configureRTEInJavascriptString .= '
                        RTEarea['.$RTEcounter.']["pageStyle"] = "' . $this->getFullFileName($filename) .'";';
                
@@ -1107,7 +1095,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                }
                
                        // Process classes configuration
-               $classesConfigurationRequired = $this->isPluginEnabled('DynamicCSS');
+               $classesConfigurationRequired = false;
                foreach ($this->registeredPlugins as $pluginId => $plugin) {
                        if ($this->isPluginEnabled($pluginId)) {
                                $classesConfigurationRequired = $classesConfigurationRequired || $plugin->requiresClassesConfiguration();
@@ -1122,11 +1110,6 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                        $configureRTEInJavascriptString .= $this->buildJSFontFacesConfig($RTEcounter);
                }
                
-                       // Process paragraphs configuration
-               if (in_array('formatblock',$this->toolbar)) {
-                       $configureRTEInJavascriptString .= $this->buildJSParagraphsConfig($RTEcounter);
-               }
-               
                        // Process font sizes configuration
                if (in_array('fontsize',$this->toolbar)) {
                        $configureRTEInJavascriptString .= $this->buildJSFontSizesConfig($RTEcounter);
@@ -1242,47 +1225,6 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                        
                return $configureRTEInJavascriptString;
        }
-       /**
-        * Return Javascript configuration of block elements
-        *
-        * @param       integer         $RTEcounter: The index number of the current RTE editing area within the form.
-        *
-        * @return      string          Javascript configuration of block elements
-        */
-       function buildJSParagraphsConfig($RTEcounter) {
-               global $TSFE, $LANG;
-               $configureRTEInJavascriptString = '';
-               
-                       // Paragraphs
-               $HTMLAreaParagraphs = $this->defaultParagraphs;
-               if ($this->thisConfig['hidePStyleItems']) {
-                       $hidePStyleItems =  t3lib_div::trimExplode(',', $this->cleanList($this->thisConfig['hidePStyleItems']), 1);
-                       foreach($hidePStyleItems as $item)  unset($HTMLAreaParagraphs[strtolower($item)]);
-               }
-               $HTMLAreaJSParagraph = '{';
-               if ($this->cleanList($this->thisConfig['hidePStyleItems']) != '*') {
-                       $HTMLAreaParagraphIndex = 0;
-                       foreach ($HTMLAreaParagraphs as $PStyleItem => $PStyleLabel) {
-                               if($HTMLAreaParagraphIndex) { 
-                                       $HTMLAreaJSParagraph .= ',';
-                               }
-                               if ($this->is_FE()) {
-                                       $HTMLAreaJSParagraph .= '
-                               "' . $TSFE->csConvObj->conv($TSFE->getLLL($PStyleLabel,$this->LOCAL_LANG), $TSFE->labelsCharset, $TSFE->renderCharset) . '" : "' . $PStyleItem . '"';
-
-                               } else {
-                                       $HTMLAreaJSParagraph .= '
-                               "' . $LANG->getLL($PStyleLabel) . '" : "' . $PStyleItem . '"';
-                               }
-                               $HTMLAreaParagraphIndex++;
-                       }
-               }
-               $HTMLAreaJSParagraph .= '};';
-               $configureRTEInJavascriptString .= '
-                       RTEarea['.$RTEcounter.']["paragraphs"] = '. $HTMLAreaJSParagraph;
-                       
-               return $configureRTEInJavascriptString;
-       }
        
        /**
         * Return Javascript configuration of font faces
@@ -1507,6 +1449,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                $JSClassesLabelsArray = 'HTMLArea.classesLabels = { ' . $linebreak;
                $JSClassesValuesArray = 'HTMLArea.classesValues = { ' . $linebreak;
                $JSClassesNoShowArray = 'HTMLArea.classesNoShow = { ' . $linebreak;
+               $JSClassesXORArray = 'HTMLArea.classesXOR = { ' . $linebreak;
                
                        // Scanning the list of classes if specified in the RTE config
                if (is_array($RTEProperties['classes.']))  {
@@ -1517,14 +1460,23 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                                $JSClassesLabelsArray .= (($index)?',':'') . '"' . $className . '": ' . $classLabel . $linebreak;
                                $JSClassesValuesArray .= (($index)?',':'') . '"' . $className . '":"' . str_replace('"', '\"', str_replace('\\\'', '\'', $conf['value'])) . '"' . $linebreak;
                                $JSClassesNoShowArray .= (($index)?',':'') . '"' . $className . '":' . ($conf['noShow']?'true':'false') . $linebreak;
+                               if (is_array($RTEProperties['mutuallyExclusiveClasses.']))  {
+                                       foreach ($RTEProperties['mutuallyExclusiveClasses.'] as $listName => $conf) {
+                                               if (t3lib_div::inList($conf, $className)) {
+                                                       $JSClassesXORArray .= (($index)?',':'') . '"' . $className . '": /^(' . implode('|', t3lib_div::trimExplode(',', t3lib_div::rmFromList($className, $conf), 1)) . ')$/i' . $linebreak;
+                                                       break;
+                                               }
+                                       }
+                               }
                                $index++;
                        }
                }
                $JSClassesLabelsArray .= '};' . $linebreak;
                $JSClassesValuesArray .= '};' . $linebreak;
                $JSClassesNoShowArray .= '};' . $linebreak;
+               $JSClassesXORArray .= '};' . $linebreak;
                
-               return $JSClassesLabelsArray . $JSClassesValuesArray . $JSClassesNoShowArray;
+               return $JSClassesLabelsArray . $JSClassesValuesArray . $JSClassesNoShowArray . $JSClassesXORArray;
        }
        
        /**
index 35b4f32..434fb9a 100644 (file)
@@ -35,16 +35,18 @@ require_once(PATH_t3lib.'class.t3lib_div.php');
 abstract class tx_rtehtmlareaapi {
        
        protected $extensionKey;                                // The key of the extension that is extending htmlArea RTE
-       protected $relativePathToLocallangFile;                 // Path to this main locallang file of the extension relative to the extension dir.
-       protected $relativePathToSkin;                          // Path to the skin (css) file relative to the extension dir.
+       protected $pluginName;                                  // The name of the plugin registered by the extension
+       protected $relativePathToLocallangFile;                 // Path to the localization file for this script, relative to the extension dir
+       protected $relativePathToSkin;                          // Path to the skin (css) file that should be added to the RTE skin when the registered plugin is enabled, relative to the extension dir
        protected $htmlAreaRTE;                                 // Reference to the invoking object
+       protected $rteExtensionKey;                             // The extension key of the RTE
        protected $thisConfig;                                  // Reference to RTE PageTSConfig
        protected $toolbar;                                     // Refrence to RTE toolbar array
        protected $LOCAL_LANG;                                  // Frontend language array
-       protected $pluginButtons = '';                          // The comma-seperated list of button names that the extension id adding to the htmlArea RTE tollbar
-       protected $pluginLabels = '';                           // The comma-seperated list of label names that the extension id adding to the htmlArea RTE tollbar
+       protected $pluginButtons = '';                          // The comma-separated list of button names that the registered plugin is adding to the htmlArea RTE toolbar
+       protected $pluginLabels = '';                           // The comma-separated list of label names that the registered plugin is adding to the htmlArea RTE toolbar
        protected $convertToolbarForHtmlAreaArray = array();    // The name-converting array, converting the button names used in the RTE PageTSConfing to the button id's used by the JS scripts
-       protected $requiresClassesConfiguration = false;        // True if the extension requires the PageTSConfig Classes configuration
+       protected $requiresClassesConfiguration = false;        // True if the registered plugin requires the PageTSConfig Classes configuration
        
        /**
         * Returns true if the plugin is available and correctly initialized
@@ -57,19 +59,21 @@ abstract class tx_rtehtmlareaapi {
                global $TYPO3_CONF_VARS, $LANG;
                
                $this->htmlAreaRTE =& $parentObject;
+               $this->rteExtensionKey =& $this->htmlAreaRTE->ID;
                $this->thisConfig =& $this->htmlAreaRTE->thisConfig;
                $this->toolbar =& $this->htmlAreaRTE->toolbar;
                
                        // Check if the plugin should be disabled in frontend
-               if ($this->htmlAreaRTE->is_FE() && is_array($TYPO3_CONF_VARS['EXTCONF'][$this->extensionKey]) && $TYPO3_CONF_VARS['EXTCONF'][$this->extensionKey]['disableInFE']) {
+               if ($this->htmlAreaRTE->is_FE() && $TYPO3_CONF_VARS['EXTCONF'][$this->rteExtensionKey]['plugins'][$this->pluginName]['disableInFE']) {
                        return false;
                }
-               
                        // Localization array must be initialized here
-               if ($this->htmlAreaRTE->is_FE()) {
-                       $this->LOCAL_LANG = t3lib_div::readLLfile('EXT:' . $this->extensionKey . '/' . $this->relativePathToLocallangFile, $this->htmlAreaRTE->language);
-               } else {
-                       $LANG->includeLLFile('EXT:' . $this->extensionKey . '/' . $this->relativePathToLocallangFile);
+               if ($this->relativePathToLocallangFile) {
+                       if ($this->htmlAreaRTE->is_FE()) {
+                               $this->LOCAL_LANG = t3lib_div::readLLfile('EXT:' . $this->extensionKey . '/' . $this->relativePathToLocallangFile, $this->htmlAreaRTE->language);
+                       } else {
+                               $LANG->includeLLFile('EXT:' . $this->extensionKey . '/' . $this->relativePathToLocallangFile);
+                       }
                }
                return true;
        }
@@ -92,7 +96,7 @@ abstract class tx_rtehtmlareaapi {
         */
        public function getPathToSkin() {
                global $TYPO3_CONF_VARS;
-               if (is_array($TYPO3_CONF_VARS['EXTCONF'][$this->extensionKey]) && $TYPO3_CONF_VARS['EXTCONF'][$this->extensionKey]['addIconsToSkin']) {
+               if ($TYPO3_CONF_VARS['EXTCONF'][$this->rteExtensionKey]['plugins'][$this->pluginName]['addIconsToSkin']) {
                        return $this->relativePathToSkin;
                } else {
                        return '';
index 4db4d36..2ea15f9 100644 (file)
Binary files a/typo3/sysext/rtehtmlarea/doc/manual.sxw and b/typo3/sysext/rtehtmlarea/doc/manual.sxw differ
index fca12ef..4f0ef61 100644 (file)
@@ -3,7 +3,7 @@
 ########################################################################
 # Extension Manager/Repository config file for ext: "rtehtmlarea"
 #
-# Auto generated 28-03-2007 12:29
+# Auto generated 05-01-2008 13:47
 #
 # Manual updates:
 # Only the data in the array - anything else is removed by next write.
@@ -28,17 +28,17 @@ $EM_CONF[$_EXTKEY] = array(
        'clearCacheOnLoad' => 0,
        'lockType' => '',
        'author' => 'Stanislas Rolland',
-       'author_email' => 'stanislas.rolland@fructifor.ca',
+       'author_email' => 'stanislas.rolland(arobas)fructifor.ca',
        'author_company' => 'Fructifor Inc.',
        'CGLcompliance' => '',
        'CGLcompliance_note' => '',
-       'version' => '1.6.3dev',
-       '_md5_values_when_last_written' => 'a:231:{s:9:"ChangeLog";s:4:"7e2b";s:29:"class.tx_rtehtmlarea_base.php";s:4:"1f01";s:21:"ext_conf_template.txt";s:4:"1ed2";s:12:"ext_icon.gif";s:4:"2f41";s:17:"ext_localconf.php";s:4:"ab92";s:14:"ext_tables.php";s:4:"36b2";s:14:"ext_tables.sql";s:4:"a400";s:13:"locallang.xml";s:4:"3ce9";s:16:"locallang_db.xml";s:4:"1c39";s:7:"tca.php";s:4:"7748";s:14:"doc/manual.sxw";s:4:"1a4d";s:16:"htmlarea/ESC.wsf";s:4:"7a43";s:29:"htmlarea/HTMLAREA_LICENSE.txt";s:4:"f260";s:31:"htmlarea/htmlarea-compressed.js";s:4:"35af";s:37:"htmlarea/htmlarea-gecko-compressed.js";s:4:"a144";s:26:"htmlarea/htmlarea-gecko.js";s:4:"6435";s:34:"htmlarea/htmlarea-ie-compressed.js";s:4:"9873";s:23:"htmlarea/htmlarea-ie.js";s:4:"4b1c";s:20:"htmlarea/htmlarea.js";s:4:"8e50";s:30:"htmlarea/locallang_dialogs.xml";s:4:"3a6f";s:26:"htmlarea/locallang_msg.xml";s:4:"a4f2";s:31:"htmlarea/locallang_tooltips.xml";s:4:"5de7";s:31:"htmlarea/popupwin-compressed.js";s:4:"f169";s:20:"htmlarea/popupwin.js";s:4:"6408";s:46:"htmlarea/plugins/Acronym/acronym-compressed.js";s:4:"5671";s:35:"htmlarea/plugins/Acronym/acronym.js";s:4:"b56b";s:38:"htmlarea/plugins/Acronym/locallang.xml";s:4:"4fcb";s:57:"htmlarea/plugins/CharacterMap/character-map-compressed.js";s:4:"9a41";s:46:"htmlarea/plugins/CharacterMap/character-map.js";s:4:"4327";s:43:"htmlarea/plugins/CharacterMap/locallang.xml";s:4:"3c2d";s:58:"htmlarea/plugins/CharacterMap/popups/select_character.html";s:4:"e258";s:55:"htmlarea/plugins/ContextMenu/context-menu-compressed.js";s:4:"2dff";s:44:"htmlarea/plugins/ContextMenu/context-menu.js";s:4:"fa6d";s:42:"htmlarea/plugins/ContextMenu/locallang.xml";s:4:"ece7";s:52:"htmlarea/plugins/DynamicCSS/dynamiccss-compressed.js";s:4:"94e3";s:42:"htmlarea/plugins/DynamicCSS/dynamiccss.css";s:4:"aca2";s:41:"htmlarea/plugins/DynamicCSS/dynamiccss.js";s:4:"8ca5";s:41:"htmlarea/plugins/DynamicCSS/locallang.xml";s:4:"662e";s:52:"htmlarea/plugins/DynamicCSS/img/red_arrow_bullet.gif";s:4:"82d6";s:55:"htmlarea/plugins/FindReplace/find-replace-compressed.js";s:4:"0c37";s:44:"htmlarea/plugins/FindReplace/find-replace.js";s:4:"aaf8";s:41:"htmlarea/plugins/FindReplace/fr_engine.js";s:4:"64a4";s:42:"htmlarea/plugins/FindReplace/locallang.xml";s:4:"f7f5";s:53:"htmlarea/plugins/FindReplace/popups/find_replace.html";s:4:"5de1";s:50:"htmlarea/plugins/InlineCSS/inlinecss-compressed.js";s:4:"5d03";s:39:"htmlarea/plugins/InlineCSS/inlinecss.js";s:4:"1a98";s:40:"htmlarea/plugins/InlineCSS/locallang.xml";s:4:"505d";s:57:"htmlarea/plugins/InsertSmiley/insert-smiley-compressed.js";s:4:"fdbb";s:46:"htmlarea/plugins/InsertSmiley/insert-smiley.js";s:4:"6914";s:43:"htmlarea/plugins/InsertSmiley/locallang.xml";s:4:"9022";s:54:"htmlarea/plugins/InsertSmiley/popups/insertsmiley.html";s:4:"50b4";s:46:"htmlarea/plugins/InsertSmiley/smileys/0001.gif";s:4:"4aff";s:46:"htmlarea/plugins/InsertSmiley/smileys/0002.gif";s:4:"02c4";s:46:"htmlarea/plugins/InsertSmiley/smileys/0003.gif";s:4:"834f";s:46:"htmlarea/plugins/InsertSmiley/smileys/0004.gif";s:4:"fb6a";s:46:"htmlarea/plugins/InsertSmiley/smileys/0005.gif";s:4:"2a48";s:46:"htmlarea/plugins/InsertSmiley/smileys/0006.gif";s:4:"f970";s:46:"htmlarea/plugins/InsertSmiley/smileys/0007.gif";s:4:"97ee";s:46:"htmlarea/plugins/InsertSmiley/smileys/0008.gif";s:4:"10a6";s:46:"htmlarea/plugins/InsertSmiley/smileys/0009.gif";s:4:"1907";s:46:"htmlarea/plugins/InsertSmiley/smileys/0010.gif";s:4:"9ee6";s:46:"htmlarea/plugins/InsertSmiley/smileys/0011.gif";s:4:"ae73";s:46:"htmlarea/plugins/InsertSmiley/smileys/0012.gif";s:4:"f058";s:46:"htmlarea/plugins/InsertSmiley/smileys/0013.gif";s:4:"3ed8";s:46:"htmlarea/plugins/InsertSmiley/smileys/0014.gif";s:4:"a948";s:46:"htmlarea/plugins/InsertSmiley/smileys/0015.gif";s:4:"218d";s:46:"htmlarea/plugins/InsertSmiley/smileys/0016.gif";s:4:"3539";s:46:"htmlarea/plugins/InsertSmiley/smileys/0017.gif";s:4:"ee2e";s:46:"htmlarea/plugins/InsertSmiley/smileys/0018.gif";s:4:"8c66";s:46:"htmlarea/plugins/InsertSmiley/smileys/0019.gif";s:4:"ac36";s:46:"htmlarea/plugins/InsertSmiley/smileys/0020.gif";s:4:"71ef";s:39:"htmlarea/plugins/QuickTag/locallang.xml";s:4:"ad89";s:49:"htmlarea/plugins/QuickTag/quick-tag-compressed.js";s:4:"c5b6";s:38:"htmlarea/plugins/QuickTag/quick-tag.js";s:4:"a119";s:36:"htmlarea/plugins/QuickTag/tag-lib.js";s:4:"b0f1";s:46:"htmlarea/plugins/QuickTag/popups/quicktag.html";s:4:"34b4";s:43:"htmlarea/plugins/RemoveFormat/locallang.xml";s:4:"8a2d";s:57:"htmlarea/plugins/RemoveFormat/remove-format-compressed.js";s:4:"c02e";s:46:"htmlarea/plugins/RemoveFormat/remove-format.js";s:4:"cecb";s:54:"htmlarea/plugins/RemoveFormat/popups/removeformat.html";s:4:"d900";s:42:"htmlarea/plugins/SelectColor/locallang.xml";s:4:"d938";s:55:"htmlarea/plugins/SelectColor/select-color-compressed.js";s:4:"1b6f";s:44:"htmlarea/plugins/SelectColor/select-color.js";s:4:"1179";s:43:"htmlarea/plugins/SpellChecker/locallang.xml";s:4:"46e5";s:51:"htmlarea/plugins/SpellChecker/spell-check-logic.php";s:4:"9772";s:51:"htmlarea/plugins/SpellChecker/spell-check-style.css";s:4:"7910";s:49:"htmlarea/plugins/SpellChecker/spell-check-ui.html";s:4:"bba6";s:47:"htmlarea/plugins/SpellChecker/spell-check-ui.js";s:4:"dcab";s:57:"htmlarea/plugins/SpellChecker/spell-checker-compressed.js";s:4:"e545";s:46:"htmlarea/plugins/SpellChecker/spell-checker.js";s:4:"9167";s:67:"htmlarea/plugins/SpellChecker/popups/spell-check-ui-iso-8859-1.html";s:4:"0aac";s:56:"htmlarea/plugins/SpellChecker/popups/spell-check-ui.html";s:4:"e300";s:46:"htmlarea/plugins/TableOperations/locallang.xml";s:4:"83bc";s:63:"htmlarea/plugins/TableOperations/table-operations-compressed.js";s:4:"94c1";s:52:"htmlarea/plugins/TableOperations/table-operations.js";s:4:"f236";s:44:"htmlarea/plugins/TYPO3Browsers/locallang.xml";s:4:"f1c9";s:58:"htmlarea/plugins/TYPO3Browsers/typo3browsers-compressed.js";s:4:"00d9";s:47:"htmlarea/plugins/TYPO3Browsers/typo3browsers.js";s:4:"d1bc";s:47:"htmlarea/plugins/TYPO3Browsers/img/download.gif";s:4:"f6d9";s:52:"htmlarea/plugins/TYPO3Browsers/img/external_link.gif";s:4:"9e48";s:63:"htmlarea/plugins/TYPO3Browsers/img/external_link_new_window.gif";s:4:"6e8d";s:52:"htmlarea/plugins/TYPO3Browsers/img/internal_link.gif";s:4:"12b9";s:63:"htmlarea/plugins/TYPO3Browsers/img/internal_link_new_window.gif";s:4:"402a";s:43:"htmlarea/plugins/TYPO3Browsers/img/mail.gif";s:4:"d5a2";s:46:"htmlarea/plugins/TYPO3HtmlParser/locallang.xml";s:4:"9da8";s:63:"htmlarea/plugins/TYPO3HtmlParser/typo3html-parser-compressed.js";s:4:"24b3";s:52:"htmlarea/plugins/TYPO3HtmlParser/typo3html-parser.js";s:4:"dcb2";s:43:"htmlarea/plugins/UserElements/locallang.xml";s:4:"e8e3";s:57:"htmlarea/plugins/UserElements/user-elements-compressed.js";s:4:"048f";s:46:"htmlarea/plugins/UserElements/user-elements.js";s:4:"b4fd";s:26:"htmlarea/popups/about.html";s:4:"b441";s:26:"htmlarea/popups/blank.html";s:4:"0883";s:32:"htmlarea/popups/editor_help.html";s:4:"72f5";s:33:"htmlarea/popups/insert_image.html";s:4:"236f";s:33:"htmlarea/popups/insert_table.html";s:4:"4fa3";s:25:"htmlarea/popups/link.html";s:4:"655f";s:24:"htmlarea/popups/popup.js";s:4:"e6c6";s:33:"htmlarea/popups/select_color.html";s:4:"301f";s:50:"htmlarea/skins/default/htmlarea-edited-content.css";s:4:"3268";s:35:"htmlarea/skins/default/htmlarea.css";s:4:"5f6c";s:42:"htmlarea/skins/default/images/ed_about.gif";s:4:"2763";s:49:"htmlarea/skins/default/images/ed_align_center.gif";s:4:"419a";s:50:"htmlarea/skins/default/images/ed_align_justify.gif";s:4:"9c31";s:47:"htmlarea/skins/default/images/ed_align_left.gif";s:4:"9c22";s:48:"htmlarea/skins/default/images/ed_align_right.gif";s:4:"9386";s:42:"htmlarea/skins/default/images/ed_blank.gif";s:4:"0208";s:45:"htmlarea/skins/default/images/ed_color_bg.gif";s:4:"c6e2";s:45:"htmlarea/skins/default/images/ed_color_fg.gif";s:4:"5d7f";s:41:"htmlarea/skins/default/images/ed_copy.gif";s:4:"4f55";s:43:"htmlarea/skins/default/images/ed_custom.gif";s:4:"e7b2";s:40:"htmlarea/skins/default/images/ed_cut.gif";s:4:"1b00";s:43:"htmlarea/skins/default/images/ed_delete.gif";s:4:"926b";s:48:"htmlarea/skins/default/images/ed_format_bold.gif";s:4:"f4f6";s:50:"htmlarea/skins/default/images/ed_format_italic.gif";s:4:"a800";s:50:"htmlarea/skins/default/images/ed_format_strike.gif";s:4:"3aa0";s:47:"htmlarea/skins/default/images/ed_format_sub.gif";s:4:"a840";s:47:"htmlarea/skins/default/images/ed_format_sup.gif";s:4:"cad7";s:53:"htmlarea/skins/default/images/ed_format_underline.gif";s:4:"505a";s:41:"htmlarea/skins/default/images/ed_help.gif";s:4:"e7fc";s:39:"htmlarea/skins/default/images/ed_hr.gif";s:4:"ff70";s:41:"htmlarea/skins/default/images/ed_html.gif";s:4:"fa6e";s:42:"htmlarea/skins/default/images/ed_image.gif";s:4:"f91c";s:48:"htmlarea/skins/default/images/ed_indent_less.gif";s:4:"8503";s:48:"htmlarea/skins/default/images/ed_indent_more.gif";s:4:"3835";s:50:"htmlarea/skins/default/images/ed_left_to_right.gif";s:4:"a0f9";s:41:"htmlarea/skins/default/images/ed_link.gif";s:4:"44fe";s:48:"htmlarea/skins/default/images/ed_list_bullet.gif";s:4:"236b";s:45:"htmlarea/skins/default/images/ed_list_num.gif";s:4:"48d3";s:42:"htmlarea/skins/default/images/ed_paste.gif";s:4:"fbd2";s:41:"htmlarea/skins/default/images/ed_redo.gif";s:4:"e9e8";s:50:"htmlarea/skins/default/images/ed_right_to_left.gif";s:4:"5149";s:41:"htmlarea/skins/default/images/ed_save.gif";s:4:"07ad";s:47:"htmlarea/skins/default/images/ed_splitblock.gif";s:4:"503e";s:45:"htmlarea/skins/default/images/ed_splitcel.gif";s:4:"2c04";s:41:"htmlarea/skins/default/images/ed_undo.gif";s:4:"b9ba";s:43:"htmlarea/skins/default/images/ed_unlink.gif";s:4:"a416";s:53:"htmlarea/skins/default/images/fullscreen_maximize.gif";s:4:"2118";s:53:"htmlarea/skins/default/images/fullscreen_minimize.gif";s:4:"91d6";s:46:"htmlarea/skins/default/images/insert_table.gif";s:4:"bf88";s:52:"htmlarea/skins/default/images/Acronym/ed_acronym.gif";s:4:"a2c5";s:57:"htmlarea/skins/default/images/CharacterMap/ed_charmap.gif";s:4:"5aa6";s:53:"htmlarea/skins/default/images/FindReplace/ed_find.gif";s:4:"d01c";s:56:"htmlarea/skins/default/images/InsertSmiley/ed_smiley.gif";s:4:"810e";s:54:"htmlarea/skins/default/images/QuickTag/ed_quicktag.gif";s:4:"b783";s:55:"htmlarea/skins/default/images/RemoveFormat/ed_clean.gif";s:4:"c936";s:58:"htmlarea/skins/default/images/SelectColor/CO-forecolor.gif";s:4:"5d7f";s:60:"htmlarea/skins/default/images/SelectColor/CO-hilitecolor.gif";s:4:"c6e2";s:58:"htmlarea/skins/default/images/SpellChecker/spell-check.gif";s:4:"15cf";s:61:"htmlarea/skins/default/images/TableOperations/cell-delete.gif";s:4:"031c";s:67:"htmlarea/skins/default/images/TableOperations/cell-insert-after.gif";s:4:"4d36";s:68:"htmlarea/skins/default/images/TableOperations/cell-insert-before.gif";s:4:"9ead";s:60:"htmlarea/skins/default/images/TableOperations/cell-merge.gif";s:4:"a2d2";s:59:"htmlarea/skins/default/images/TableOperations/cell-prop.gif";s:4:"bf67";s:60:"htmlarea/skins/default/images/TableOperations/cell-split.gif";s:4:"d87c";s:60:"htmlarea/skins/default/images/TableOperations/col-delete.gif";s:4:"b0f6";s:66:"htmlarea/skins/default/images/TableOperations/col-insert-after.gif";s:4:"f5f7";s:67:"htmlarea/skins/default/images/TableOperations/col-insert-before.gif";s:4:"5711";s:59:"htmlarea/skins/default/images/TableOperations/col-split.gif";s:4:"eacc";s:62:"htmlarea/skins/default/images/TableOperations/insert_table.gif";s:4:"c1db";s:60:"htmlarea/skins/default/images/TableOperations/row-delete.gif";s:4:"7cdb";s:66:"htmlarea/skins/default/images/TableOperations/row-insert-above.gif";s:4:"d034";s:66:"htmlarea/skins/default/images/TableOperations/row-insert-under.gif";s:4:"59f9";s:58:"htmlarea/skins/default/images/TableOperations/row-prop.gif";s:4:"b11e";s:59:"htmlarea/skins/default/images/TableOperations/row-split.gif";s:4:"a712";s:60:"htmlarea/skins/default/images/TableOperations/table-prop.gif";s:4:"2a21";s:64:"htmlarea/skins/default/images/TableOperations/toggle-borders.gif";s:4:"ae22";s:56:"htmlarea/skins/default/images/TYPO3Browsers/ed_image.gif";s:4:"f91c";s:55:"htmlarea/skins/default/images/TYPO3Browsers/ed_link.gif";s:4:"9a55";s:59:"htmlarea/skins/default/images/TYPO3ViewHelp/module_help.gif";s:4:"a500";s:54:"htmlarea/skins/default/images/UserElements/ed_user.gif";s:4:"a294";s:16:"mod2/acronym.php";s:4:"562d";s:37:"mod2/class.tx_rtehtmlarea_acronym.php";s:4:"a3c8";s:14:"mod2/clear.gif";s:4:"cc11";s:13:"mod2/conf.php";s:4:"a85e";s:18:"mod2/locallang.xml";s:4:"c657";s:21:"mod3/browse_links.php";s:4:"38d6";s:42:"mod3/class.tx_rtehtmlarea_browse_links.php";s:4:"438a";s:14:"mod3/clear.gif";s:4:"cc11";s:13:"mod3/conf.php";s:4:"eddf";s:18:"mod3/locallang.xml";s:4:"33de";s:46:"mod4/class.tx_rtehtmlarea_dam_browse_media.php";s:4:"a599";s:42:"mod4/class.tx_rtehtmlarea_select_image.php";s:4:"9542";s:14:"mod4/clear.gif";s:4:"cc11";s:13:"mod4/conf.php";s:4:"bee5";s:18:"mod4/locallang.xml";s:4:"3a28";s:21:"mod4/select_image.php";s:4:"0a02";s:34:"mod5/class.tx_rtehtmlarea_user.php";s:4:"6bdf";s:14:"mod5/clear.gif";s:4:"cc11";s:13:"mod5/conf.php";s:4:"d6be";s:18:"mod5/locallang.xml";s:4:"df76";s:13:"mod5/user.php";s:4:"2b02";s:40:"mod6/class.tx_rtehtmlarea_parse_html.php";s:4:"a917";s:13:"mod6/conf.php";s:4:"4a45";s:19:"mod6/parse_html.php";s:4:"c36b";s:32:"pi1/class.tx_rtehtmlarea_pi1.php";s:4:"a603";s:17:"pi1/locallang.xml";s:4:"fec8";s:32:"pi2/class.tx_rtehtmlarea_pi2.php";s:4:"a165";s:17:"pi2/locallang.xml";s:4:"9fbe";s:32:"pi3/class.tx_rtehtmlarea_pi3.php";s:4:"288e";s:39:"res/accessibilityicons/pageTSConfig.txt";s:4:"93a0";s:40:"res/accessibilityicons/pageTSConfig2.txt";s:4:"5683";s:29:"res/advanced/pageTSConfig.txt";s:4:"2ace";s:29:"res/advanced/userTSConfig.txt";s:4:"a017";s:33:"res/clickenlarge/pageTSConfig.txt";s:4:"0a2d";s:25:"res/demo/pageTSConfig.txt";s:4:"1009";s:25:"res/demo/userTSConfig.txt";s:4:"a8c3";s:26:"res/image/pageTSConfig.txt";s:4:"e07c";s:25:"res/proc/pageTSConfig.txt";s:4:"1b18";s:28:"res/typical/pageTSConfig.txt";s:4:"bc69";s:28:"res/typical/userTSConfig.txt";s:4:"0a64";s:29:"static/clickenlarge/setup.txt";s:4:"9439";}',
+       'version' => '1.6.3',
+       '_md5_values_when_last_written' => 'a:281:{s:9:"ChangeLog";s:4:"656b";s:29:"class.tx_rtehtmlarea_base.php";s:4:"e923";s:27:"class.tx_rtehtmlareaapi.php";s:4:"da50";s:21:"ext_conf_template.txt";s:4:"d75b";s:12:"ext_icon.gif";s:4:"2f41";s:17:"ext_localconf.php";s:4:"03f4";s:14:"ext_tables.php";s:4:"08e9";s:14:"ext_tables.sql";s:4:"2d74";s:13:"locallang.xml";s:4:"3cca";s:16:"locallang_db.xml";s:4:"a2a2";s:7:"tca.php";s:4:"3756";s:32:"pi1/class.tx_rtehtmlarea_pi1.php";s:4:"e7fc";s:17:"pi1/locallang.xml";s:4:"2e58";s:16:"mod2/acronym.php";s:4:"3b29";s:37:"mod2/class.tx_rtehtmlarea_acronym.php";s:4:"ec04";s:14:"mod2/clear.gif";s:4:"cc11";s:13:"mod2/conf.php";s:4:"28d3";s:18:"mod2/locallang.xml";s:4:"7dee";s:29:"htmlarea/HTMLAREA_LICENSE.txt";s:4:"a10f";s:26:"htmlarea/htmlarea-gecko.js";s:4:"3343";s:23:"htmlarea/htmlarea-ie.js";s:4:"adb3";s:20:"htmlarea/htmlarea.js";s:4:"2d51";s:30:"htmlarea/locallang_dialogs.xml";s:4:"42e9";s:26:"htmlarea/locallang_msg.xml";s:4:"7b6f";s:31:"htmlarea/locallang_tooltips.xml";s:4:"7e14";s:20:"htmlarea/popupwin.js";s:4:"08e9";s:50:"htmlarea/skins/default/htmlarea-edited-content.css";s:4:"6bd1";s:35:"htmlarea/skins/default/htmlarea.css";s:4:"4c05";s:42:"htmlarea/skins/default/images/ed_about.gif";s:4:"2763";s:42:"htmlarea/skins/default/images/ed_blank.gif";s:4:"0208";s:45:"htmlarea/skins/default/images/ed_color_bg.gif";s:4:"c6e2";s:45:"htmlarea/skins/default/images/ed_color_fg.gif";s:4:"5d7f";s:41:"htmlarea/skins/default/images/ed_copy.gif";s:4:"4f55";s:43:"htmlarea/skins/default/images/ed_custom.gif";s:4:"e7b2";s:40:"htmlarea/skins/default/images/ed_cut.gif";s:4:"1b00";s:43:"htmlarea/skins/default/images/ed_delete.gif";s:4:"926b";s:41:"htmlarea/skins/default/images/ed_help.gif";s:4:"e7fc";s:39:"htmlarea/skins/default/images/ed_hr.gif";s:4:"f384";s:41:"htmlarea/skins/default/images/ed_html.gif";s:4:"fa6e";s:42:"htmlarea/skins/default/images/ed_image.gif";s:4:"c0f0";s:50:"htmlarea/skins/default/images/ed_left_to_right.gif";s:4:"1a1f";s:41:"htmlarea/skins/default/images/ed_link.gif";s:4:"44fe";s:48:"htmlarea/skins/default/images/ed_list_bullet.gif";s:4:"5620";s:45:"htmlarea/skins/default/images/ed_list_num.gif";s:4:"eb1c";s:42:"htmlarea/skins/default/images/ed_paste.gif";s:4:"fbd2";s:41:"htmlarea/skins/default/images/ed_redo.gif";s:4:"e9e8";s:50:"htmlarea/skins/default/images/ed_right_to_left.gif";s:4:"2a38";s:41:"htmlarea/skins/default/images/ed_save.gif";s:4:"07ad";s:47:"htmlarea/skins/default/images/ed_splitblock.gif";s:4:"503e";s:45:"htmlarea/skins/default/images/ed_splitcel.gif";s:4:"2c04";s:41:"htmlarea/skins/default/images/ed_undo.gif";s:4:"b9ba";s:43:"htmlarea/skins/default/images/ed_unlink.gif";s:4:"a416";s:53:"htmlarea/skins/default/images/fullscreen_maximize.gif";s:4:"2118";s:53:"htmlarea/skins/default/images/fullscreen_minimize.gif";s:4:"91d6";s:46:"htmlarea/skins/default/images/insert_table.gif";s:4:"c01b";s:58:"htmlarea/skins/default/images/BlockElements/blockquote.gif";s:4:"34dc";s:54:"htmlarea/skins/default/images/BlockElements/indent.gif";s:4:"57df";s:68:"htmlarea/skins/default/images/BlockElements/insertParagraphAfter.gif";s:4:"e335";s:69:"htmlarea/skins/default/images/BlockElements/insertParagraphBefore.gif";s:4:"9c42";s:61:"htmlarea/skins/default/images/BlockElements/justifyCenter.gif";s:4:"420d";s:59:"htmlarea/skins/default/images/BlockElements/justifyFull.gif";s:4:"b129";s:59:"htmlarea/skins/default/images/BlockElements/justifyLeft.gif";s:4:"3799";s:60:"htmlarea/skins/default/images/BlockElements/justifyRight.gif";s:4:"0662";s:55:"htmlarea/skins/default/images/BlockElements/outdent.gif";s:4:"4786";s:52:"htmlarea/skins/default/images/Acronym/ed_acronym.gif";s:4:"1eaa";s:57:"htmlarea/skins/default/images/CharacterMap/ed_charmap.gif";s:4:"af19";s:54:"htmlarea/skins/default/images/UserElements/ed_user.gif";s:4:"bbb4";s:54:"htmlarea/skins/default/images/QuickTag/ed_quicktag.gif";s:4:"a463";s:58:"htmlarea/skins/default/images/SelectColor/CO-forecolor.gif";s:4:"dbc8";s:60:"htmlarea/skins/default/images/SelectColor/CO-hilitecolor.gif";s:4:"d97c";s:56:"htmlarea/skins/default/images/DefaultInline/citation.gif";s:4:"5b20";s:52:"htmlarea/skins/default/images/DefaultInline/code.gif";s:4:"faa8";s:58:"htmlarea/skins/default/images/DefaultInline/definition.gif";s:4:"4fe4";s:56:"htmlarea/skins/default/images/DefaultInline/keyboard.gif";s:4:"88e2";s:57:"htmlarea/skins/default/images/DefaultInline/quotation.gif";s:4:"6061";s:54:"htmlarea/skins/default/images/DefaultInline/sample.gif";s:4:"f781";s:56:"htmlarea/skins/default/images/DefaultInline/variable.gif";s:4:"a417";s:55:"htmlarea/skins/default/images/RemoveFormat/ed_clean.gif";s:4:"2a0f";s:53:"htmlarea/skins/default/images/FindReplace/ed_find.gif";s:4:"827f";s:61:"htmlarea/skins/default/images/TableOperations/cell-delete.gif";s:4:"f371";s:67:"htmlarea/skins/default/images/TableOperations/cell-insert-after.gif";s:4:"2dd2";s:68:"htmlarea/skins/default/images/TableOperations/cell-insert-before.gif";s:4:"5d13";s:60:"htmlarea/skins/default/images/TableOperations/cell-merge.gif";s:4:"a2d2";s:59:"htmlarea/skins/default/images/TableOperations/cell-prop.gif";s:4:"ca41";s:60:"htmlarea/skins/default/images/TableOperations/cell-split.gif";s:4:"d87c";s:60:"htmlarea/skins/default/images/TableOperations/col-delete.gif";s:4:"da78";s:66:"htmlarea/skins/default/images/TableOperations/col-insert-after.gif";s:4:"80d8";s:67:"htmlarea/skins/default/images/TableOperations/col-insert-before.gif";s:4:"d47d";s:59:"htmlarea/skins/default/images/TableOperations/col-split.gif";s:4:"eacc";s:62:"htmlarea/skins/default/images/TableOperations/insert_table.gif";s:4:"c1db";s:60:"htmlarea/skins/default/images/TableOperations/row-delete.gif";s:4:"a289";s:66:"htmlarea/skins/default/images/TableOperations/row-insert-above.gif";s:4:"1ef1";s:66:"htmlarea/skins/default/images/TableOperations/row-insert-after.gif";s:4:"5e98";s:66:"htmlarea/skins/default/images/TableOperations/row-insert-under.gif";s:4:"9ad6";s:58:"htmlarea/skins/default/images/TableOperations/row-prop.gif";s:4:"5344";s:59:"htmlarea/skins/default/images/TableOperations/row-split.gif";s:4:"a712";s:60:"htmlarea/skins/default/images/TableOperations/table-prop.gif";s:4:"0a5c";s:64:"htmlarea/skins/default/images/TableOperations/toggle-borders.gif";s:4:"50cb";s:59:"htmlarea/skins/default/images/TYPO3ViewHelp/module_help.gif";s:4:"a500";s:56:"htmlarea/skins/default/images/InsertSmiley/ed_smiley.gif";s:4:"c331";s:56:"htmlarea/skins/default/images/TYPO3Browsers/ed_image.gif";s:4:"c0f0";s:55:"htmlarea/skins/default/images/TYPO3Browsers/ed_link.gif";s:4:"db9a";s:57:"htmlarea/skins/default/images/TYPO3Browsers/ed_unlink.gif";s:4:"86c4";s:58:"htmlarea/skins/default/images/SpellChecker/spell-check.gif";s:4:"6e0a";s:61:"htmlarea/skins/default/images/InlineElements/bidioverride.gif";s:4:"f38b";s:52:"htmlarea/skins/default/images/InlineElements/big.gif";s:4:"779b";s:53:"htmlarea/skins/default/images/InlineElements/bold.gif";s:4:"06ac";s:57:"htmlarea/skins/default/images/InlineElements/citation.gif";s:4:"b6eb";s:53:"htmlarea/skins/default/images/InlineElements/code.gif";s:4:"6057";s:59:"htmlarea/skins/default/images/InlineElements/definition.gif";s:4:"692d";s:60:"htmlarea/skins/default/images/InlineElements/deletedtext.gif";s:4:"4eec";s:57:"htmlarea/skins/default/images/InlineElements/emphasis.gif";s:4:"04c9";s:61:"htmlarea/skins/default/images/InlineElements/insertedtext.gif";s:4:"a624";s:55:"htmlarea/skins/default/images/InlineElements/italic.gif";s:4:"be83";s:57:"htmlarea/skins/default/images/InlineElements/keyboard.gif";s:4:"53ac";s:59:"htmlarea/skins/default/images/InlineElements/monospaced.gif";s:4:"78c0";s:58:"htmlarea/skins/default/images/InlineElements/quotation.gif";s:4:"7c62";s:55:"htmlarea/skins/default/images/InlineElements/sample.gif";s:4:"667c";s:54:"htmlarea/skins/default/images/InlineElements/small.gif";s:4:"e013";s:53:"htmlarea/skins/default/images/InlineElements/span.gif";s:4:"0dfa";s:62:"htmlarea/skins/default/images/InlineElements/strikethrough.gif";s:4:"73b1";s:55:"htmlarea/skins/default/images/InlineElements/strong.gif";s:4:"7f50";s:58:"htmlarea/skins/default/images/InlineElements/subscript.gif";s:4:"36c0";s:60:"htmlarea/skins/default/images/InlineElements/superscript.gif";s:4:"40c4";s:58:"htmlarea/skins/default/images/InlineElements/underline.gif";s:4:"dfac";s:57:"htmlarea/skins/default/images/InlineElements/variable.gif";s:4:"da61";s:34:"htmlarea/plugins/default-inline.js";s:4:"14a8";s:48:"htmlarea/plugins/BlockElements/block-elements.js";s:4:"1d1d";s:44:"htmlarea/plugins/BlockElements/locallang.xml";s:4:"865c";s:35:"htmlarea/plugins/Acronym/acronym.js";s:4:"8379";s:38:"htmlarea/plugins/Acronym/locallang.xml";s:4:"7221";s:46:"htmlarea/plugins/CharacterMap/character-map.js";s:4:"52ad";s:43:"htmlarea/plugins/CharacterMap/locallang.xml";s:4:"1feb";s:58:"htmlarea/plugins/CharacterMap/popups/select_character.html";s:4:"25c5";s:43:"htmlarea/plugins/UserElements/locallang.xml";s:4:"33f9";s:46:"htmlarea/plugins/UserElements/user-elements.js";s:4:"7410";s:39:"htmlarea/plugins/QuickTag/locallang.xml";s:4:"2f53";s:38:"htmlarea/plugins/QuickTag/quick-tag.js";s:4:"a5ad";s:36:"htmlarea/plugins/QuickTag/tag-lib.js";s:4:"ba71";s:46:"htmlarea/plugins/QuickTag/popups/quicktag.html";s:4:"c6e5";s:39:"htmlarea/plugins/InlineCSS/inlinecss.js";s:4:"b6f6";s:40:"htmlarea/plugins/InlineCSS/locallang.xml";s:4:"5dec";s:46:"htmlarea/plugins/TYPO3HtmlParser/locallang.xml";s:4:"e98e";s:52:"htmlarea/plugins/TYPO3HtmlParser/typo3html-parser.js";s:4:"6f66";s:42:"htmlarea/plugins/SelectColor/locallang.xml";s:4:"9f9e";s:44:"htmlarea/plugins/SelectColor/select-color.js";s:4:"749b";s:48:"htmlarea/plugins/DefaultInline/default-inline.js";s:4:"5aa0";s:44:"htmlarea/plugins/DefaultInline/locallang.xml";s:4:"3add";s:43:"htmlarea/plugins/RemoveFormat/locallang.xml";s:4:"aa85";s:46:"htmlarea/plugins/RemoveFormat/remove-format.js";s:4:"1ee8";s:54:"htmlarea/plugins/RemoveFormat/popups/removeformat.html";s:4:"4599";s:44:"htmlarea/plugins/FindReplace/find-replace.js";s:4:"846c";s:41:"htmlarea/plugins/FindReplace/fr_engine.js";s:4:"3482";s:42:"htmlarea/plugins/FindReplace/locallang.xml";s:4:"f836";s:53:"htmlarea/plugins/FindReplace/popups/find_replace.html";s:4:"f3b3";s:46:"htmlarea/plugins/TableOperations/locallang.xml";s:4:"8377";s:52:"htmlarea/plugins/TableOperations/table-operations.js";s:4:"c54c";s:42:"htmlarea/plugins/BlockStyle/block-style.js";s:4:"8375";s:41:"htmlarea/plugins/BlockStyle/locallang.xml";s:4:"32ed";s:46:"htmlarea/plugins/InsertSmiley/insert-smiley.js";s:4:"6585";s:43:"htmlarea/plugins/InsertSmiley/locallang.xml";s:4:"ed64";s:46:"htmlarea/plugins/InsertSmiley/smileys/0001.gif";s:4:"4aff";s:46:"htmlarea/plugins/InsertSmiley/smileys/0002.gif";s:4:"02c4";s:46:"htmlarea/plugins/InsertSmiley/smileys/0003.gif";s:4:"834f";s:46:"htmlarea/plugins/InsertSmiley/smileys/0004.gif";s:4:"fb6a";s:46:"htmlarea/plugins/InsertSmiley/smileys/0005.gif";s:4:"2a48";s:46:"htmlarea/plugins/InsertSmiley/smileys/0006.gif";s:4:"f970";s:46:"htmlarea/plugins/InsertSmiley/smileys/0007.gif";s:4:"97ee";s:46:"htmlarea/plugins/InsertSmiley/smileys/0008.gif";s:4:"10a6";s:46:"htmlarea/plugins/InsertSmiley/smileys/0009.gif";s:4:"1907";s:46:"htmlarea/plugins/InsertSmiley/smileys/0010.gif";s:4:"9ee6";s:46:"htmlarea/plugins/InsertSmiley/smileys/0011.gif";s:4:"ae73";s:46:"htmlarea/plugins/InsertSmiley/smileys/0012.gif";s:4:"f058";s:46:"htmlarea/plugins/InsertSmiley/smileys/0013.gif";s:4:"3ed8";s:46:"htmlarea/plugins/InsertSmiley/smileys/0014.gif";s:4:"a948";s:46:"htmlarea/plugins/InsertSmiley/smileys/0015.gif";s:4:"218d";s:46:"htmlarea/plugins/InsertSmiley/smileys/0016.gif";s:4:"3539";s:46:"htmlarea/plugins/InsertSmiley/smileys/0017.gif";s:4:"ee2e";s:46:"htmlarea/plugins/InsertSmiley/smileys/0018.gif";s:4:"8c66";s:46:"htmlarea/plugins/InsertSmiley/smileys/0019.gif";s:4:"ac36";s:46:"htmlarea/plugins/InsertSmiley/smileys/0020.gif";s:4:"71ef";s:54:"htmlarea/plugins/InsertSmiley/popups/insertsmiley.html";s:4:"43f3";s:44:"htmlarea/plugins/TYPO3Browsers/locallang.xml";s:4:"89b8";s:47:"htmlarea/plugins/TYPO3Browsers/typo3browsers.js";s:4:"34b9";s:47:"htmlarea/plugins/TYPO3Browsers/img/download.gif";s:4:"f6d9";s:52:"htmlarea/plugins/TYPO3Browsers/img/external_link.gif";s:4:"9e48";s:63:"htmlarea/plugins/TYPO3Browsers/img/external_link_new_window.gif";s:4:"6e8d";s:52:"htmlarea/plugins/TYPO3Browsers/img/internal_link.gif";s:4:"12b9";s:63:"htmlarea/plugins/TYPO3Browsers/img/internal_link_new_window.gif";s:4:"402a";s:43:"htmlarea/plugins/TYPO3Browsers/img/mail.gif";s:4:"d5a2";s:43:"htmlarea/plugins/SpellChecker/locallang.xml";s:4:"20d8";s:51:"htmlarea/plugins/SpellChecker/spell-check-logic.php";s:4:"b9ad";s:51:"htmlarea/plugins/SpellChecker/spell-check-style.css";s:4:"82bd";s:49:"htmlarea/plugins/SpellChecker/spell-check-ui.html";s:4:"c4e3";s:47:"htmlarea/plugins/SpellChecker/spell-check-ui.js";s:4:"7d97";s:46:"htmlarea/plugins/SpellChecker/spell-checker.js";s:4:"a384";s:67:"htmlarea/plugins/SpellChecker/popups/spell-check-ui-iso-8859-1.html";s:4:"fd14";s:56:"htmlarea/plugins/SpellChecker/popups/spell-check-ui.html";s:4:"48f6";s:42:"htmlarea/plugins/DynamicCSS/dynamiccss.css";s:4:"8e7b";s:41:"htmlarea/plugins/DynamicCSS/dynamiccss.js";s:4:"feea";s:41:"htmlarea/plugins/DynamicCSS/locallang.xml";s:4:"b6bf";s:52:"htmlarea/plugins/DynamicCSS/img/red_arrow_bullet.gif";s:4:"82d6";s:44:"htmlarea/plugins/ContextMenu/context-menu.js";s:4:"faec";s:42:"htmlarea/plugins/ContextMenu/locallang.xml";s:4:"59f5";s:26:"htmlarea/popups/about.html";s:4:"48fe";s:26:"htmlarea/popups/blank.html";s:4:"e697";s:32:"htmlarea/popups/editor_help.html";s:4:"398a";s:33:"htmlarea/popups/insert_image.html";s:4:"bfc1";s:33:"htmlarea/popups/insert_table.html";s:4:"983d";s:25:"htmlarea/popups/link.html";s:4:"c122";s:24:"htmlarea/popups/popup.js";s:4:"4861";s:33:"htmlarea/popups/select_color.html";s:4:"ceba";s:46:"mod4/class.tx_rtehtmlarea_dam_browse_media.php";s:4:"f25e";s:42:"mod4/class.tx_rtehtmlarea_select_image.php";s:4:"08de";s:14:"mod4/clear.gif";s:4:"cc11";s:13:"mod4/conf.php";s:4:"5a84";s:18:"mod4/locallang.xml";s:4:"9910";s:21:"mod4/select_image.php";s:4:"a0bb";s:32:"pi2/class.tx_rtehtmlarea_pi2.php";s:4:"93d3";s:17:"pi2/locallang.xml";s:4:"a0a7";s:63:"extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php";s:4:"da43";s:38:"extensions/BlockElements/locallang.xml";s:4:"c1c4";s:42:"extensions/BlockElements/skin/htmlarea.css";s:4:"f913";s:51:"extensions/BlockElements/skin/images/blockquote.gif";s:4:"34dc";s:47:"extensions/BlockElements/skin/images/indent.gif";s:4:"57df";s:61:"extensions/BlockElements/skin/images/insertParagraphAfter.gif";s:4:"e335";s:62:"extensions/BlockElements/skin/images/insertParagraphBefore.gif";s:4:"9c42";s:54:"extensions/BlockElements/skin/images/justifyCenter.gif";s:4:"420d";s:52:"extensions/BlockElements/skin/images/justifyFull.gif";s:4:"b129";s:52:"extensions/BlockElements/skin/images/justifyLeft.gif";s:4:"3799";s:53:"extensions/BlockElements/skin/images/justifyRight.gif";s:4:"0662";s:48:"extensions/BlockElements/skin/images/outdent.gif";s:4:"4786";s:61:"extensions/CharacterMap/class.tx_rtehtmlarea_charactermap.php";s:4:"dbcd";s:37:"extensions/CharacterMap/locallang.xml";s:4:"c9d1";s:41:"extensions/CharacterMap/skin/htmlarea.css";s:4:"9de6";s:55:"extensions/CharacterMap/skin/images/insertCharacter.gif";s:4:"af19";s:55:"extensions/InlineCSS/class.tx_rtehtmlarea_inlinecss.php";s:4:"be0d";s:34:"extensions/InlineCSS/locallang.xml";s:4:"82ed";s:63:"extensions/DefaultInline/class.tx_rtehtmlarea_defaultinline.php";s:4:"0947";s:38:"extensions/DefaultInline/locallang.xml";s:4:"e592";s:42:"extensions/DefaultInline/skin/htmlarea.css";s:4:"bbff";s:45:"extensions/DefaultInline/skin/images/bold.gif";s:4:"94f2";s:47:"extensions/DefaultInline/skin/images/italic.gif";s:4:"f60c";s:54:"extensions/DefaultInline/skin/images/strikethrough.gif";s:4:"3fd0";s:50:"extensions/DefaultInline/skin/images/subscript.gif";s:4:"cedd";s:52:"extensions/DefaultInline/skin/images/superscript.gif";s:4:"8aea";s:50:"extensions/DefaultInline/skin/images/underline.gif";s:4:"81e6";s:57:"extensions/BlockStyle/class.tx_rtehtmlarea_blockstyle.php";s:4:"c3fc";s:35:"extensions/BlockStyle/locallang.xml";s:4:"ef65";s:57:"extensions/DynamicCSS/class.tx_rtehtmlarea_dynamiccss.php";s:4:"0f7a";s:35:"extensions/DynamicCSS/locallang.xml";s:4:"ef65";s:21:"mod3/browse_links.php";s:4:"4663";s:42:"mod3/class.tx_rtehtmlarea_browse_links.php";s:4:"c00a";s:14:"mod3/clear.gif";s:4:"cc11";s:13:"mod3/conf.php";s:4:"15d8";s:18:"mod3/locallang.xml";s:4:"4393";s:34:"mod5/class.tx_rtehtmlarea_user.php";s:4:"aaf0";s:14:"mod5/clear.gif";s:4:"cc11";s:13:"mod5/conf.php";s:4:"2102";s:14:"mod5/error_log";s:4:"8279";s:18:"mod5/locallang.xml";s:4:"7a78";s:13:"mod5/user.php";s:4:"ae33";s:32:"pi3/class.tx_rtehtmlarea_pi3.php";s:4:"0c14";s:14:"doc/manual.sxw";s:4:"6a26";s:40:"mod6/class.tx_rtehtmlarea_parse_html.php";s:4:"64d7";s:13:"mod6/conf.php";s:4:"a136";s:14:"mod6/error_log";s:4:"74f7";s:19:"mod6/parse_html.php";s:4:"5b65";s:29:"static/clickenlarge/setup.txt";s:4:"5681";s:26:"res/contentcss/default.css";s:4:"7446";s:39:"res/contentcss/img/red_arrow_bullet.gif";s:4:"82d6";s:25:"res/demo/pageTSConfig.txt";s:4:"e8ca";s:25:"res/demo/userTSConfig.txt";s:4:"90fd";s:33:"res/clickenlarge/pageTSConfig.txt";s:4:"c92c";s:28:"res/typical/pageTSConfig.txt";s:4:"98dd";s:28:"res/typical/userTSConfig.txt";s:4:"40dc";s:26:"res/image/pageTSConfig.txt";s:4:"41a1";s:25:"res/proc/pageTSConfig.txt";s:4:"6564";s:29:"res/advanced/pageTSConfig.txt";s:4:"52cd";s:29:"res/advanced/userTSConfig.txt";s:4:"f8c3";s:39:"res/accessibilityicons/pageTSConfig.txt";s:4:"2802";}',
        'constraints' => array(
                'depends' => array(
                        'cms' => '',
-                       'php' => '5.0-',
-                       'typo3' => '4.1-',
+                       'php' => '5.0-0.0.0',
+                       'typo3' => '4.1-0.0.0',
                ),
                'conflicts' => array(
                        'rte_conf' => '',
index 70d530e..acea33b 100644 (file)
@@ -49,8 +49,16 @@ $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins'] = array();
 // Registering plugin from "inner" extensions:
 $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['DefaultInline'] = array();
 $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['DefaultInline']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/DefaultInline/class.tx_rtehtmlarea_defaultinline.php:&tx_rtehtmlarea_defaultinline';
+$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['DefaultInline']['addIconsToSkin'] = 1;
 $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['InlineCSS'] = array();
 $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['InlineCSS']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/InlineCSS/class.tx_rtehtmlarea_inlinecss.php:&tx_rtehtmlarea_inlinecss';
+$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']['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();
+$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['BlockStyle']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/BlockStyle/class.tx_rtehtmlarea_blockstyle.php:&tx_rtehtmlarea_blockstyle';
 
 $_EXTCONF = unserialize($_EXTCONF);    // unserializing the configuration so we can use it here:
 
@@ -113,4 +121,4 @@ if (t3lib_extMgm::isLoaded('lorem_ipsum') && (TYPO3_MODE == 'BE')) {
     $TYPO3_CONF_VARS['EXTCONF']['lorem_ipsum']['RTE_insert'][] = 'tx_rtehtmlarea_base->loremIpsumInsert';
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/typo3/sysext/rtehtmlarea/extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php b/typo3/sysext/rtehtmlarea/extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php
new file mode 100644 (file)
index 0000000..d44edff
--- /dev/null
@@ -0,0 +1,169 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2007 Stanislas Rolland <stanislas.rolland(arobas)fructifor.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!
+***************************************************************/
+/**
+ * BlockElements extension for htmlArea RTE
+ *
+ * @author Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
+ *
+ * TYPO3 SVN ID: $Id$
+ *
+ */
+
+require_once(t3lib_extMgm::extPath('rtehtmlarea').'class.tx_rtehtmlareaapi.php');
+
+class tx_rtehtmlarea_blockelements extends tx_rtehtmlareaapi {
+
+       protected $extensionKey = 'rtehtmlarea';                // The key of the extension that is extending htmlArea RTE
+       protected $pluginName = 'BlockElements';                // The name of the plugin registered by the extension
+       protected $relativePathToLocallangFile = 'extensions/BlockElements/locallang.xml';      // Path to this main locallang file of the extension relative to the extension dir.
+       protected $relativePathToSkin = 'extensions/BlockElements/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 = 'formatblock, indent, outdent, blockquote, insertparagraphbefore, insertparagraphafter, left, center, right, justifyfull';
+       protected $convertToolbarForHtmlAreaArray = array (
+               'formatblock'           => 'FormatBlock',
+               'indent'                => 'Indent',
+               'outdent'               => 'Outdent',
+               'blockquote'            => 'Blockquote',
+               'insertparagraphbefore' => 'InsertParagraphBefore',
+               'insertparagraphafter'  => 'InsertParagraphAfter',
+               'left'                  => 'JustifyLeft',
+               'center'                => 'JustifyCenter',
+               'right'                 => 'JustifyRight',
+               'justifyfull'           => 'JustifyFull',
+               );
+       
+       private $defaultBlockElements = array(
+               'none'          => 'No block',
+               'p'             => 'Paragraph',
+               'h1'            => 'Heading 1',
+               'h2'            => 'Heading 2',
+               'h3'            => 'Heading 3',
+               'h4'            => 'Heading 4',
+               'h5'            => 'Heading 5',
+               'h6'            => 'Heading 6',
+               'pre'           => 'Preformatted',
+               'address'       => 'Address',
+               'blockquote'    => 'Quotation',
+               'div'           => 'Section',
+       );
+       
+       private $defaultBlockElementsOrder = 'none, p, h1, h2, h3, h4, h5, h6, pre, address, blockquote, div';
+       
+       /**
+        * 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, in this case, JS configuration of block elements
+        *
+        * 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 = '';
+               if (in_array('formatblock', $this->toolbar)) {
+                       if (!is_array( $this->thisConfig['buttons.']) || !is_array( $this->thisConfig['buttons.']['formatblock.'])) {
+                               $registerRTEinJavascriptString .= '
+                       RTEarea['.$RTEcounter.'].buttons.formatblock = new Object();';
+                       }
+                               // Default block elements
+                       $hideItems = array();
+                       $restrictTo = array('*');
+                       $blockElementsOrder = $this->defaultBlockElementsOrder;
+                       $prefixLabelWithTag = false;
+                       $postfixLabelWithTag = false;
+                       
+                               // Processing PageTSConfig
+                       if (is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.']['formatblock.'])) {
+                                       // Removing elements
+                               if ($this->thisConfig['buttons.']['formatblock.']['removeItems']) {
+                                       $hideItems =  t3lib_div::trimExplode(',', $this->htmlAreaRTE->cleanList($this->thisConfig['buttons.']['formatblock.']['removeItems']), 1);
+                               }
+                                       // Restriction clause
+                               if ($this->thisConfig['buttons.']['formatblock.']['restrictToItems']) {
+                                       $restrictTo =  t3lib_div::trimExplode(',', $this->htmlAreaRTE->cleanList('none,'.$this->thisConfig['buttons.']['formatblock.']['restrictTo']), 1);
+                               }
+                                       // Elements order
+                               if ($this->thisConfig['buttons.']['formatblock.']['orderItems']) {
+                                       $blockElementsOrder = 'none,'.$this->thisConfig['buttons.']['formatblock.']['orderItems'];
+                               }
+                               $prefixLabelWithTag = ($this->thisConfig['buttons.']['formatblock.']['prefixLabelWithTag']) ? true : $prefixLabelWithTag;
+                               $postfixLabelWithTag = ($this->thisConfig['buttons.']['formatblock.']['postfixLabelWithTag']) ? true : $postfixLabelWithTag;
+                       }
+                               // Processing old style configuration for hiding paragraphs
+                       if ($this->thisConfig['hidePStyleItems']) {
+                               $hideItems = array_merge($hideItems, t3lib_div::trimExplode(',', $this->htmlAreaRTE->cleanList($this->thisConfig['hidePStyleItems']), 1));
+                       }
+                               // Applying User TSConfig restriction
+                       $blockElementsOrder = array_diff(t3lib_div::trimExplode(',', $this->htmlAreaRTE->cleanList($blockElementsOrder), 1), $hideItems);
+                       if (!in_array('*', $restrictTo)) {
+                               $blockElementsOrder = array_intersect($blockElementsOrder, $restrictTo);
+                       }
+                               // Localizing the options
+                       $blockElementsOptions = array();
+                       if ($this->htmlAreaRTE->cleanList($this->thisConfig['hidePStyleItems']) != '*') {
+                               foreach ($blockElementsOrder as $item) {
+                                       if ($this->htmlAreaRTE->is_FE()) {
+                                               $blockElementsOptions[$item] = $TSFE->csConvObj->conv($TSFE->getLLL($this->defaultBlockElements[$item],$this->LOCAL_LANG), $TSFE->labelsCharset, $TSFE->renderCharset);
+                                       } else {
+                                               $blockElementsOptions[$item] = $LANG->getLL($this->defaultBlockElements[$item]);
+                                       }
+                                       $blockElementsOptions[$item] = (($prefixLabelWithTag && $item != 'none')?($item . ' - '):'') . $blockElementsOptions[$item] . (($postfixLabelWithTag && $item != 'none')?(' - ' . $item):'');
+                               }
+                       }
+                       
+                       $first = array_shift($blockElementsOptions);
+                               // Sorting the options
+                       if (!is_array($this->thisConfig['buttons.']) || !is_array($this->thisConfig['buttons.']['formatblock.']) || !$this->thisConfig['buttons.']['formatblock.']['orderItems']) {
+                               asort($blockElementsOptions);
+                       }
+                               // Generating the javascript options
+                       $JSBlockElements = '{
+                       "'. $first.'" : "none"';
+                       foreach ($blockElementsOptions as $item => $label) {
+                               $JSBlockElements .= ',
+                       "' . $label . '" : "' . $item . '"';
+                       }
+                       $JSBlockElements .= '};';
+                       
+                       $registerRTEinJavascriptString .= '
+                       RTEarea['.$RTEcounter.'].buttons.formatblock.dropDownOptions = '. $JSBlockElements;
+               }
+               return $registerRTEinJavascriptString;
+       }
+
+} // end of class
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php']) {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/rtehtmlarea/extensions/BlockElements/locallang.xml b/typo3/sysext/rtehtmlarea/extensions/BlockElements/locallang.xml
new file mode 100644 (file)
index 0000000..5855f3a
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- TYPO3 SVN ID: $Id$ -->
+<T3locallang>
+       <meta type="array">
+               <description>Labels for BlockElements extension of htmlArea RTE</description>
+               <type>module</type>
+       </meta>
+       <data type="array">
+               <languageKey index="default" type="array">
+                       <label index="No block">No block format</label>
+                       <label index="Paragraph">Paragraph</label>
+                       <label index="Heading 1">Heading 1</label>
+                       <label index="Heading 2">Heading 2</label>
+                       <label index="Heading 3">Heading 3</label>
+                       <label index="Heading 4">Heading 4</label>
+                       <label index="Heading 5">Heading 5</label>
+                       <label index="Heading 6">Heading 6</label>
+                       <label index="Preformatted">Preformatted</label>
+                       <label index="Quotation">Quotation</label>
+                       <label index="Address">Address</label>
+                       <label index="Section">Container</label>
+               </languageKey>
+       </data>
+       <orig_hash type="array">
+               <languageKey index="default" type="array">
+               </languageKey>
+       </orig_hash>
+       <orig_text type="array">
+               <languageKey index="default" type="array">
+               </languageKey>
+       </orig_text>
+</T3locallang>
\ No newline at end of file
diff --git a/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/htmlarea.css b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/htmlarea.css
new file mode 100644 (file)
index 0000000..288ecfc
--- /dev/null
@@ -0,0 +1,11 @@
+/* Selectors for the BlockElements extension of htmlArea RTE */
+/* TYPO3 SVN ID: $Id$ */
+.htmlarea .toolbar .Indent {background-image:url("images/indent.gif");}
+.htmlarea .toolbar .Outdent {background-image:url("images/outdent.gif");}
+.htmlarea .toolbar .Blockquote {background-image:url("images/blockquote.gif");}
+.htmlarea .toolbar .InsertParagraphBefore, .htmlarea-context-menu .InsertParagraphBefore {background-image:url("images/insertParagraphBefore.gif");}
+.htmlarea .toolbar .InsertParagraphAfter, .htmlarea-context-menu .InsertParagraphAfter {background-image:url("images/insertParagraphAfter.gif");}
+.htmlarea .toolbar .JustifyLeft, .htmlarea-context-menu .JustifyLeft {background-image:url("images/justifyLeft.gif");}
+.htmlarea .toolbar .JustifyCenter, .htmlarea-context-menu .JustifyCenter {background-image:url("images/justifyCenter.gif");}
+.htmlarea .toolbar .JustifyRight, .htmlarea-context-menu .JustifyRight {background-image:url("images/justifyRight.gif");}
+.htmlarea .toolbar .JustifyFull, .htmlarea-context-menu .JustifyFull {background-image:url("images/justifyFull.gif");}
diff --git a/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/blockquote.gif b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/blockquote.gif
new file mode 100644 (file)
index 0000000..4b83c85
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/blockquote.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/indent.gif b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/indent.gif
new file mode 100644 (file)
index 0000000..a3d5621
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/indent.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/insertParagraphAfter.gif b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/insertParagraphAfter.gif
new file mode 100644 (file)
index 0000000..05fe508
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/insertParagraphAfter.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/insertParagraphBefore.gif b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/insertParagraphBefore.gif
new file mode 100644 (file)
index 0000000..f8dcf87
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/insertParagraphBefore.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyCenter.gif b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyCenter.gif
new file mode 100644 (file)
index 0000000..53758b4
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyCenter.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyFull.gif b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyFull.gif
new file mode 100644 (file)
index 0000000..bbe305d
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyFull.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyLeft.gif b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyLeft.gif
new file mode 100644 (file)
index 0000000..a0cfb02
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyLeft.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyRight.gif b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyRight.gif
new file mode 100644 (file)
index 0000000..5509ac6
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/justifyRight.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/outdent.gif b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/outdent.gif
new file mode 100644 (file)
index 0000000..872320c
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/outdent.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/BlockStyle/class.tx_rtehtmlarea_blockstyle.php b/typo3/sysext/rtehtmlarea/extensions/BlockStyle/class.tx_rtehtmlarea_blockstyle.php
new file mode 100644 (file)
index 0000000..aea69b9
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2007 Stanislas Rolland <stanislas.rolland(arobas)fructifor.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!
+***************************************************************/
+/**
+ * Block Style extension for htmlArea RTE
+ *
+ * @author Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
+ *
+ * TYPO3 SVN ID: $Id$
+ *
+ */
+
+require_once(t3lib_extMgm::extPath('rtehtmlarea').'class.tx_rtehtmlareaapi.php');
+
+class tx_rtehtmlarea_blockstyle extends tx_rtehtmlareaapi {
+
+       protected $extensionKey = 'rtehtmlarea';                // The key of the extension that is extending htmlArea RTE
+       protected $pluginName = 'BlockStyle';                   // The name of the plugin registered by the extension
+       protected $relativePathToLocallangFile = 'extensions/BlockStyle/locallang.xml'; // Path to this main locallang file of the extension relative to the extension dir.
+       protected $relativePathToSkin = '';                     // Path to the skin (css) file relative to the extension dir.
+       protected $htmlAreaRTE;                                 // Reference to the invoking object
+       protected $thisConfig;                                  // Reference to RTE PageTSConfig
+       protected $toolbar;                                     // Reference to RTE toolbar array
+       protected $LOCAL_LANG;                                  // Frontend language array
+       
+       protected $pluginButtons = 'blockstyle';                // The comma-seperated list of button names that the extension id adding to the htmlArea RTE tollbar
+       protected $pluginLabels = 'blockstylelabel';            // The comma-seperated list of label names that the extension id adding to the htmlArea RTE tollbar
+                                                               // The name-converting array, converting the button names used in the RTE PageTSConfing to the button id's used by the JS scripts
+       protected $convertToolbarForHtmlAreaArray = array (
+               'blockstylelabel'       => 'I[Block style label]',
+               'blockstyle'            => 'BlockStyle',
+               );
+       protected $requiresClassesConfiguration = true;         // True if the extension requires the PageTSConfig Classes configuration
+
+} // end of class
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/BlockStyle/class.tx_rtehtmlarea_blockstyle.php']) {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/BlockStyle/class.tx_rtehtmlarea_blockstyle.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/rtehtmlarea/extensions/BlockStyle/locallang.xml b/typo3/sysext/rtehtmlarea/extensions/BlockStyle/locallang.xml
new file mode 100644 (file)
index 0000000..4c8c60f
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- TYPO3 SVN ID: $Id$ -->
+<T3locallang>
+       <meta type="array">
+               <description>Labels for the DynamicCSS extension of htmlArea RTE</description>
+               <type>module</type>
+       </meta>
+       <data type="array">
+               <languageKey index="default" type="array">
+               </languageKey>
+       </data>
+       <orig_hash type="array">
+               <languageKey index="default" type="array">
+               </languageKey>
+       </orig_hash>
+       <orig_text type="array">
+               <languageKey index="default" type="array">
+               </languageKey>
+       </orig_text>
+</T3locallang>
\ No newline at end of file
index e795c41..094b673 100644 (file)
@@ -34,13 +34,14 @@ require_once(t3lib_extMgm::extPath('rtehtmlarea').'class.tx_rtehtmlareaapi.php')
 
 class tx_rtehtmlarea_defaultinline extends tx_rtehtmlareaapi {
 
-       protected $extensionKey = 'rtehtmlarea';                // The key of the extension that is extending htmlArea RTE
+       protected $extensionKey = 'rtehtmlarea';        // The key of the extension that is extending htmlArea RTE
+       protected $pluginName = 'DefaultInline';        // The name of the plugin registered by the extension
        protected $relativePathToLocallangFile = 'extensions/DefaultInline/locallang.xml';      // Path to this main locallang file of the extension relative to the extension dir.
-       protected $relativePathToSkin = '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 $relativePathToSkin = 'extensions/DefaultInline/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 = 'bold,italic,strikethrough,subscript,superscript,underline';
        protected $convertToolbarForHtmlAreaArray = array (
index f59a533..22df4ab 100644 (file)
@@ -1,8 +1,8 @@
 /* Selectors for the DefaultInline plugin of htmlArea RTE */
 /* TYPO3 SVN ID: $Id$ */
-.htmlarea .toolbar .Bold {background-image:url("images/InlineElements/bold.gif");}
-.htmlarea .toolbar .Italic {background-image:url("images/InlineElements/italic.gif");}
-.htmlarea .toolbar .StrikeThrough {background-image:url("images/InlineElements/strikethrough.gif");}
-.htmlarea .toolbar .Subscript {background-image:url("images/InlineElements/subscript.gif");}
-.htmlarea .toolbar .Superscript {background-image:url("images/InlineElements/superscript.gif");}
-.htmlarea .toolbar .Underline {background-image:url("images/InlineElements/underline.gif");}
+.htmlarea .toolbar .Bold {background-image:url("images/bold.gif");}
+.htmlarea .toolbar .Italic {background-image:url("images/italic.gif");}
+.htmlarea .toolbar .StrikeThrough {background-image:url("images/strikethrough.gif");}
+.htmlarea .toolbar .Subscript {background-image:url("images/subscript.gif");}
+.htmlarea .toolbar .Superscript {background-image:url("images/superscript.gif");}
+.htmlarea .toolbar .Underline {background-image:url("images/underline.gif");}
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/bold.gif b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/bold.gif
deleted file mode 100644 (file)
index 99a3abd..0000000
Binary files a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/bold.gif and /dev/null differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/italic.gif b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/italic.gif
deleted file mode 100644 (file)
index 6b90006..0000000
Binary files a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/italic.gif and /dev/null differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/strikethrough.gif b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/strikethrough.gif
deleted file mode 100644 (file)
index 48f0ca5..0000000
Binary files a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/strikethrough.gif and /dev/null differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/subscript.gif b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/subscript.gif
deleted file mode 100644 (file)
index 57fec04..0000000
Binary files a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/subscript.gif and /dev/null differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/superscript.gif b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/superscript.gif
deleted file mode 100644 (file)
index 8035cfd..0000000
Binary files a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/superscript.gif and /dev/null differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/underline.gif b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/underline.gif
deleted file mode 100644 (file)
index 964c845..0000000
Binary files a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/DefaultInline/underline.gif and /dev/null differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/bold.gif b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/bold.gif
new file mode 100644 (file)
index 0000000..a5ac7af
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/bold.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/italic.gif b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/italic.gif
new file mode 100644 (file)
index 0000000..7cbab9b
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/italic.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/strikethrough.gif b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/strikethrough.gif
new file mode 100644 (file)
index 0000000..def20e7
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/strikethrough.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/subscript.gif b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/subscript.gif
new file mode 100644 (file)
index 0000000..6f3445a
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/subscript.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/superscript.gif b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/superscript.gif
new file mode 100644 (file)
index 0000000..f3b4adb
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/superscript.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/underline.gif b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/underline.gif
new file mode 100644 (file)
index 0000000..1d6ece1
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/DefaultInline/skin/images/underline.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/DynamicCSS/class.tx_rtehtmlarea_dynamiccss.php b/typo3/sysext/rtehtmlarea/extensions/DynamicCSS/class.tx_rtehtmlarea_dynamiccss.php
new file mode 100644 (file)
index 0000000..8e92bc6
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2007 Stanislas Rolland <stanislas.rolland(arobas)fructifor.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!
+***************************************************************/
+/**
+ * DynamicCSS extension for htmlArea RTE
+ *
+ * @author Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
+ *
+ * TYPO3 SVN ID: $Id$
+ *
+ */
+
+require_once(t3lib_extMgm::extPath('rtehtmlarea').'class.tx_rtehtmlareaapi.php');
+
+class tx_rtehtmlarea_dynamiccss extends tx_rtehtmlareaapi {
+
+       protected $extensionKey = 'rtehtmlarea';                // The key of the extension that is extending htmlArea RTE
+       protected $pluginName = 'DynamicCSS';                   // The name of the plugin registered by the extension
+       protected $relativePathToLocallangFile = 'extensions/DynamicCSS/locallang.xml'; // Path to this main locallang file of the extension relative to the extension dir.
+       protected $relativePathToSkin = '';                     // Path to the skin (css) file relative to the extension dir.
+       protected $htmlAreaRTE;                                 // Reference to the invoking object
+       protected $thisConfig;                                  // Reference to RTE PageTSConfig
+       protected $toolbar;                                     // Reference to RTE toolbar array
+       protected $LOCAL_LANG;                                  // Frontend language array
+       
+       protected $pluginButtons = 'blockstyle';                // The comma-seperated list of button names that the extension id adding to the htmlArea RTE tollbar
+       protected $pluginLabels = 'blockstylelabel';            // The comma-seperated list of label names that the extension id adding to the htmlArea RTE tollbar
+                                                               // The name-converting array, converting the button names used in the RTE PageTSConfing to the button id's used by the JS scripts
+       protected $convertToolbarForHtmlAreaArray = array (
+               'blockstylelabel'       => 'I[style]',
+               'blockstyle'            => 'DynamicCSS-class',
+               );
+       protected $requiresClassesConfiguration = true;         // True if the extension requires the PageTSConfig Classes configuration
+
+} // end of class
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/DynamicCSS/class.tx_rtehtmlarea_dynamiccss.php']) {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/DynamicCSS/class.tx_rtehtmlarea_dynamiccss.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/rtehtmlarea/extensions/DynamicCSS/locallang.xml b/typo3/sysext/rtehtmlarea/extensions/DynamicCSS/locallang.xml
new file mode 100644 (file)
index 0000000..4c8c60f
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- TYPO3 SVN ID: $Id$ -->
+<T3locallang>
+       <meta type="array">
+               <description>Labels for the DynamicCSS extension of htmlArea RTE</description>
+               <type>module</type>
+       </meta>
+       <data type="array">
+               <languageKey index="default" type="array">
+               </languageKey>
+       </data>
+       <orig_hash type="array">
+               <languageKey index="default" type="array">
+               </languageKey>
+       </orig_hash>
+       <orig_text type="array">
+               <languageKey index="default" type="array">
+               </languageKey>
+       </orig_text>
+</T3locallang>
\ No newline at end of file
index 9ed6d8e..7d8a2b9 100644 (file)
@@ -22,7 +22,7 @@
 *  This copyright notice MUST APPEAR in all copies of the script!
 ***************************************************************/
 /**
- * DefaultInline plugin for htmlArea RTE
+ * InlineCSS extension of htmlArea RTE
  *
  * @author Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
  *
@@ -34,22 +34,23 @@ require_once(t3lib_extMgm::extPath('rtehtmlarea').'class.tx_rtehtmlareaapi.php')
 
 class tx_rtehtmlarea_inlinecss extends tx_rtehtmlareaapi {
 
-       protected $extensionKey = 'rtehtmlarea';                        // The key of the extension that is extending htmlArea RTE
+       protected $extensionKey = 'rtehtmlarea';                // The key of the extension that is extending htmlArea RTE
+       protected $pluginName = 'InlineCSS';                    // The name of the plugin registered by the extension
        protected $relativePathToLocallangFile = 'extensions/InlineCSS/locallang.xml';  // Path to this main locallang file of the extension relative to the extension dir.
-       protected $relativePathToSkin = '';                             // Path to the skin (css) file relative to the extension dir.
-       protected $htmlAreaRTE;                                         // Reference to the invoking object
-       protected $thisConfig;                                          // Reference to RTE PageTSConfig
-       protected $toolbar;                                             // Reference to RTE toolbar array
-       protected $LOCAL_LANG;                                          // Frontend language array
+       protected $relativePathToSkin = '';                     // Path to the skin (css) file relative to the extension dir.
+       protected $htmlAreaRTE;                                 // Reference to the invoking object
+       protected $thisConfig;                                  // Reference to RTE PageTSConfig
+       protected $toolbar;                                     // Reference to RTE toolbar array
+       protected $LOCAL_LANG;                                  // Frontend language array
        
-       protected $pluginButtons = 'textstyle';                         // The comma-seperated list of button names that the extension id adding to the htmlArea RTE tollbar
-       protected $pluginLabels = 'textstylelabel';                     // The comma-seperated list of label names that the extension id adding to the htmlArea RTE tollbar
-                                                                       // The name-converting array, converting the button names used in the RTE PageTSConfing to the button id's used by the JS scripts
+       protected $pluginButtons = 'textstyle';                 // The comma-seperated list of button names that the extension id adding to the htmlArea RTE tollbar
+       protected $pluginLabels = 'textstylelabel';             // The comma-seperated list of label names that the extension id adding to the htmlArea RTE tollbar
+                                                               // The name-converting array, converting the button names used in the RTE PageTSConfing to the button id's used by the JS scripts
        protected $convertToolbarForHtmlAreaArray = array (
                'textstylelabel'        => 'I[text_style]',
                'textstyle'             => 'InlineCSS-class',
                );
-       protected $requiresClassesConfiguration = true;                 // True if the extension requires the PageTSConfig Classes configuration
+       protected $requiresClassesConfiguration = true;         // True if the extension requires the PageTSConfig Classes configuration
 
 } // end of class
 
index d024519..25deb54 100644 (file)
@@ -99,6 +99,9 @@ HTMLArea.prototype.emptySelection = function(selection) {
        } else {
                selection.removeAllRanges();
        }
+       if (HTMLArea.is_opera) {
+               this._iframe.focus();
+       }
 };
 
 /*
@@ -145,28 +148,89 @@ HTMLArea.prototype._createRange = function(sel) {
 /*
  * Select a node AND the contents inside the node
  */
-HTMLArea.prototype.selectNode = function(node,pos) {
+HTMLArea.prototype.selectNode = function(node, endPoint) {
        this.focusEditor();
-       var sel = this._getSelection();
+       var selection = this._getSelection();
        var range = this._doc.createRange();
-       if (node.nodeType == 1 && node.tagName.toLowerCase() == "body") range.selectNodeContents(node);
-               else range.selectNode(node);
-       if ((typeof(pos) != "undefined")) range.collapse(pos);
-       this.emptySelection(sel);
-       this.addRangeToSelection(sel, range);
+       if (node.nodeType == 1 && node.nodeName.toLowerCase() == "body") {
+               range.selectNodeContents(node);
+       } else {
+               range.selectNode(node);
+       }
+       if (typeof(endPoint) != "undefined") {
+               range.collapse(endPoint);
+       }
+       this.emptySelection(selection);
+       this.addRangeToSelection(selection, range);
 };
 
 /*
  * Select ONLY the contents inside the given node
  */
-HTMLArea.prototype.selectNodeContents = function(node,pos) {
+HTMLArea.prototype.selectNodeContents = function(node, endPoint) {
        this.focusEditor();
-       var sel = this._getSelection();
+       var selection = this._getSelection();
        var range = this._doc.createRange();
        range.selectNodeContents(node);
-       if ((typeof(pos) != "undefined")) range.collapse(pos);
-       this.emptySelection(sel);
-       this.addRangeToSelection(sel, range);
+       if (typeof(endPoint) !== "undefined") {
+               range.collapse(endPoint);
+       }
+       this.emptySelection(selection);
+       this.addRangeToSelection(selection, range);
+};
+
+HTMLArea.prototype.rangeIntersectsNode = function(range, node) {
+       var nodeRange = this._doc.createRange();
+       try {
+               nodeRange.selectNode(node);
+       } catch (e) {
+               nodeRange.selectNodeContents(node);
+       }
+       return (range.compareBoundaryPoints(range.END_TO_START, nodeRange) == -1 && range.compareBoundaryPoints(range.START_TO_END, nodeRange) == 1);
+};
+
+/*
+ * Get the selection type
+ */
+HTMLArea.prototype.getSelectionType = function(selection) {
+               // By default set the type to "Text".
+       var type = "Text";
+       if (!selection) {
+               var selection = this._getSelection();
+       }
+                       // Check if the actual selection is a Control
+       if (selection && selection.rangeCount == 1) {
+               var range = selection.getRangeAt(0) ;
+               if (range.startContainer == range.endContainer
+                               && (range.endOffset - range.startOffset) == 1
+                               && range.startContainer.nodeType == 1
+                               && /^(img|hr|li|table|tr|td|embed|object|ol|ul)$/i.test(range.startContainer.childNodes[range.startOffset].nodeName)) {
+                       type = "Control";
+               }
+       }
+       return type;
+};
+
+/*
+ * Retrieves the selected element (if any), just in the case that a single element (object like and image or a table) is selected.
+ */
+HTMLArea.prototype.getSelectedElement = function(selection) {
+       var selectedElement = null;
+       if (!selection) {
+               var selection = this._getSelection();
+       }
+       if (selection && selection.anchorNode && selection.anchorNode.nodeType == 1) {
+               if (this.getSelectionType(selection) == "Control") {
+                       selectedElement = selection.anchorNode.childNodes[selection.anchorOffset];
+                               // For Safari, the anchor node for a control selection is the control itself
+                       if (!selectedElement) {
+                               selectedElement = selection.anchorNode;
+                       } else if (selectedElement.nodeType != 1) {
+                               return null;
+                       }
+               }
+       }
+       return selectedElement;
 };
 
 /*
@@ -196,6 +260,9 @@ HTMLArea.prototype.getParentElement = function(selection, range) {
        if (!selection) {
                var selection = this._getSelection();
        }
+       if (this.getSelectionType(selection) === "Control") {
+               return this.getSelectedElement(selection);
+       }
        if (typeof(range) === "undefined") {
                var range = this._createRange(selection);
        }
@@ -229,6 +296,99 @@ HTMLArea.prototype._selectionEmpty = function(sel) {
        return sel.isCollapsed;
 };
 
+/*
+ * Get a bookmark
+ * Adapted from FCKeditor
+ * This is an "intrusive" way to create a bookmark. It includes <span> tags
+ * in the range boundaries. The advantage of it is that it is possible to
+ * handle DOM mutations when moving back to the bookmark.
+ */
+HTMLArea.prototype.getBookmark = function (range) {
+               // For performance, includeNodes=true if intended to SelectBookmark.
+               // Create the bookmark info (random IDs).
+       var bookmark = {
+               startId : (new Date()).valueOf() + Math.floor(Math.random()*1000) + 'S',
+               endId   : (new Date()).valueOf() + Math.floor(Math.random()*1000) + 'E'
+       };
+       
+       var startSpan;
+       var endSpan;
+       var rangeClone = range.cloneRange();
+       
+               // For collapsed ranges, add just the start marker.
+       if (!range.collapsed ) {
+               endSpan = this._doc.createElement("span");
+               endSpan.style.display = "none";
+               endSpan.id = bookmark.endId;
+               endSpan.setAttribute("HTMLArea_bookmark", true);
+               endSpan.innerHTML = "&nbsp;";
+               rangeClone.collapse(false);
+               rangeClone.insertNode(endSpan);
+       }
+       
+       startSpan = this._doc.createElement("span");
+       startSpan.style.display = "none";
+       startSpan.id = bookmark.startId;
+       startSpan.setAttribute("HTMLArea_bookmark", true);
+       startSpan.innerHTML = "&nbsp;";
+       var rangeClone = range.cloneRange();
+       rangeClone.collapse(true);
+       rangeClone.insertNode(startSpan);
+       bookmark.startNode = startSpan;
+       bookmark.endNode = endSpan;
+               // Update the range position.
+       if (endSpan) {
+               range.setEndBefore(endSpan);
+               range.setStartAfter(startSpan);
+       } else {
+               range.setEndAfter(startSpan);
+               range.collapse(false);
+       }
+       return bookmark;
+};
+
+/*
+ * Get the end point of the bookmark
+ * Adapted from FCKeditor
+ */
+HTMLArea.prototype.getBookmarkNode = function(bookmark, endPoint) {
+       if (endPoint) {
+               return bookmark.startNode || this._doc.getElementById(bookmark.startId);
+       } else {
+               return bookmark.endNode || this._doc.getElementById(bookmark.endId);
+       }
+};
+
+/*
+ * Move the range to the bookmark
+ * Adapted from FCKeditor
+ */
+HTMLArea.prototype.moveToBookmark = function (bookmark) {
+       var startSpan  = this.getBookmarkNode(bookmark, true);
+       var endSpan    = this.getBookmarkNode(bookmark, false);
+       
+       var range = this._createRange();
+       range.setStartBefore(startSpan);
+       HTMLArea.removeFromParent(startSpan);
+               // If collapsed, the end span will not be available.
+       if (endSpan) {
+               range.setEndBefore(endSpan);
+               HTMLArea.removeFromParent(endSpan);
+       } else {
+               range.collapse(true);
+       }
+       return range;
+};
+
+/*
+ * Select range
+ */
+HTMLArea.prototype.selectRange = function (range) {
+       var selection = this._getSelection();
+       this.emptySelection(selection);
+       this.addRangeToSelection(selection, range);
+};
+
 /***************************************************
  *  DOM TREE MANIPULATION
  ***************************************************/
@@ -346,7 +506,7 @@ HTMLArea.statusBarHandler = function (ev) {
        var target = (ev.target) ? ev.target : ev.srcElement;
        var editor = target.editor;
        target.blur();
-       editor.selectNode(target.el);
+       editor.selectNodeContents(target.el);
        editor._statusBarTree.selected = target.el;
        editor.updateToolbar(true);
        switch (ev.type) {
@@ -450,7 +610,6 @@ HTMLArea.prototype._checkInsertP = function() {
                block   = null,
                a       = null,
                doc     = this._doc;
-       
        for (i = 0; i < p.length; ++i) {
                if (HTMLArea.isBlockElement(p[i]) && !/^(html|body|table|tbody|thead|tr)$/i.test(p[i].nodeName)) {
                        block = p[i];
@@ -480,8 +639,8 @@ HTMLArea.prototype._checkInsertP = function() {
                                left = block.appendChild(left);
                        }
                        left.normalize();
-                       range.setStartAfter(left);
                        range.setEndAfter(block.lastChild);
+                       range.setStartAfter(left);
                                // Working around Safari issue: The following gives a range exception
                                // range.surroundContents(right = doc.createElement("p"));
                        right = doc.createElement("p");
@@ -495,7 +654,7 @@ HTMLArea.prototype._checkInsertP = function() {
                        var first = block.firstChild;
                        if (first) block.removeChild(first);
                        right = doc.createElement("p");
-                       if (HTMLArea.is_opera) {
+                       if (HTMLArea.is_safari || HTMLArea.is_opera) {
                                right.innerHTML = "<br />";
                        }
                        right = block.appendChild(right);
index 1397e0e..b14cea5 100644 (file)
@@ -3,7 +3,7 @@
 *
 *  (c) 2002-2004, interactivetools.com, inc.
 *  (c) 2003-2004 dynarch.com
-*  (c) 2004, 2005, 2006 Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
+*  (c) 2004-2007 Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -136,13 +136,14 @@ HTMLArea.prototype.selectNode = function(node) {
 /*
  * Select ONLY the contents inside the given node
  */
-HTMLArea.prototype.selectNodeContents = function(node,pos) {
+HTMLArea.prototype.selectNodeContents = function(node, endPoint) {
        this.focusEditor();
        this.forceRedraw();
-       var collapsed = (typeof(pos) != "undefined");
        var range = this._doc.body.createTextRange();
        range.moveToElementText(node);
-       (collapsed) && range.collapse(pos);
+       if (typeof(endPoint) !== "undefined") {
+               range.collapse(endPoint);
+       }
        range.select();
 };
 
@@ -212,11 +213,36 @@ HTMLArea.prototype._activeElement = function(sel) {
 /*
  * Determine if the current selection is empty or not.
  */
-HTMLArea.prototype._selectionEmpty = function(sel) {
-       if (!sel) return true;
-       return this._createRange(sel).htmlText == '';
+HTMLArea.prototype._selectionEmpty = function(selection) {
+       if (!selection || selection.type.toLowerCase() === "none") return true;
+       if (selection.type.toLowerCase() === "text") {
+               return !this._createRange(selection).text;
+       }
+       return !this._createRange(selection).htmlText;
+};
+
+/*
+ * Get a bookmark
+ */
+HTMLArea.prototype.getBookmark = function (range) {
+       return range.getBookmark();
+};
+
+/*
+ * Move the range to the bookmark
+ */
+HTMLArea.prototype.moveToBookmark = function (bookmark) {
+       var range = this._createRange();
+       range.moveToBookmark(bookmark);
+       return range;
 };
 
+/*
+ * Select range
+ */
+HTMLArea.prototype.selectRange = function (range) {
+       range.select();
+};
 /***************************************************
  *  DOM TREE MANIPULATION
  ***************************************************/
index 2addd14..f4852b1 100644 (file)
@@ -74,6 +74,8 @@ var HTMLArea = function(textarea, config) {
        }
 };
 
+HTMLArea.editorCSS = _editor_CSS;
+
 /*
  * Browser identification
  */
@@ -242,7 +244,7 @@ HTMLArea.RE_doctype = /(<!doctype((.|\n)*?)>)\n?/i;
 HTMLArea.RE_head    = /<head>((.|\n)*?)<\/head>/i;
 HTMLArea.RE_body    = /<body>((.|\n)*?)<\/body>/i;
 HTMLArea.Reg_body = new RegExp("<\/?(body)[^>]*>", "gi");
-HTMLArea.Reg_entities = new RegExp("&amp;([0-9]+);", "gi");
+HTMLArea.Reg_entities = new RegExp("&amp;#([0-9]+);", "gi");
 HTMLArea.reservedClassNames = /htmlarea/;
 HTMLArea.RE_email    = /([0-9a-z]+([a-z0-9_-]*[0-9a-z])*){1}(\.[0-9a-z]+([a-z0-9_-]*[0-9a-z])*)*@([0-9a-z]+([a-z0-9_-]*[0-9a-z])*\.)+[a-z]{2,9}/i;
 HTMLArea.RE_url      = /(https?:\/\/)?(([a-z0-9_]+:[a-z0-9_]+@)?[a-z0-9_-]{2,}(\.[a-z0-9_-]{2,})+\.[a-z]{2,5}(:[0-9]+)?(\/\S+)*)/i;
@@ -252,7 +254,6 @@ HTMLArea.RE_url      = /(https?:\/\/)?(([a-z0-9_]+:[a-z0-9_]+@)?[a-z0-9_-]{2,}(\
  */
 
 HTMLArea.Config = function () {
-       this.version = "3.0";
        this.width = "auto";
        this.height = "auto";
                // enable creation of a status bar?
@@ -277,7 +278,7 @@ HTMLArea.Config = function () {
                // content style
        this.pageStyle = "";
                // set to true if you want Word code to be cleaned upon Paste
-       this.cleanWordOnPaste = true;
+       this.enableWordClean = true;
                // enable the 'Target' field in the Make Link dialog
        this.makeLinkShowsTarget = true;
                // remove tags (these have to be a regexp, or null if this functionality is not desired)
@@ -296,14 +297,8 @@ HTMLArea.Config = function () {
        this.popupURL = "popups/";
 
        this.btnList = {
-               JustifyLeft:            ["Justify Left", "ed_align_left.gif", false, function(editor) {editor.execCommand("JustifyLeft");}],
-               JustifyCenter:          ["Justify Center", "ed_align_center.gif", false, function(editor) {editor.execCommand("JustifyCenter");}],
-               JustifyRight:           ["Justify Right", "ed_align_right.gif", false, function(editor) {editor.execCommand("JustifyRight");}],
-               JustifyFull:            ["Justify Full", "ed_align_justify.gif", false, function(editor) {editor.execCommand("JustifyFull");}],
                InsertOrderedList:      ["Ordered List", "ed_list_num.gif", false, function(editor) {editor.execCommand("InsertOrderedList");}],
                InsertUnorderedList:    ["Bulleted List", "ed_list_bullet", false, function(editor) {editor.execCommand("InsertUnorderedList");}],
-               Outdent:                ["Decrease Indent", "ed_indent_less.gif", false, function(editor) {editor.execCommand("Outdent");}],
-               Indent:                 ["Increase Indent", "ed_indent_more.gif", false, function(editor) {editor.execCommand("Indent");}],
                ForeColor:              ["Font Color", "ed_color_fg.gif",false, function(editor) {editor.execCommand("ForeColor");}],
                HiliteColor:            ["Background Color", "ed_color_bg.gif",false, function(editor) {editor.execCommand("HiliteColor");}],
                InsertHorizontalRule:   ["Horizontal Rule", "ed_hr.gif",false, function(editor) {editor.execCommand("InsertHorizontalRule");}],
@@ -314,11 +309,11 @@ HTMLArea.Config = function () {
                SelectAll:              ["SelectAll", "", true, function(editor) {editor.execCommand("SelectAll");}, null, true, false],
                SplitBlock:             ["Toggle Container Block", "ed_splitblock.gif", false, function(editor) {editor.execCommand("SplitBlock");}],
                About:                  ["About this editor", "ed_about.gif", true, function(editor) {editor.execCommand("About");}],
-               Undo:                   ["Undoes your last action", "ed_undo.gif", false, function(editor) {editor.execCommand("Undo");}],
-               Redo:                   ["Redoes your last action", "ed_redo.gif", false, function(editor) {editor.execCommand("Redo");}],
-               Cut:                    ["Cut selection", "ed_cut.gif", false, function(editor,command,obj) {editor.execCommand("Cut");}],
-               Copy:                   ["Copy selection", "ed_copy.gif", false, function(editor,command,obj) {editor.execCommand("Copy");}],
-               Paste:                  ["Paste from clipboard", "ed_paste.gif", false, function(editor,command,obj) {editor.execCommand("Paste");}],
+               Undo:                   ["Undo the last action", "ed_undo.gif", false, function(editor) {editor.execCommand("Undo");}],
+               Redo:                   ["Redo the last action", "ed_redo.gif", false, function(editor) {editor.execCommand("Redo");}],
+               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],
                LeftToRight:            ["Direction left to right", "ed_left_to_right.gif", false, function(editor) {editor.execCommand("LeftToRight");}],
                RightToLeft:            ["Direction right to left", "ed_right_to_left.gif", false, function(editor) {editor.execCommand("RightToLeft");}]
@@ -326,11 +321,6 @@ HTMLArea.Config = function () {
                // Default hotkeys
        this.hotKeyList = {
                a:      { cmd:  "SelectAll",            action: null},
-               l:      { cmd:  "JustifyLeft",          action: null},
-               e:      { cmd:  "JustifyCenter",        action: null},
-               r:      { cmd:  "JustifyRight",         action: null},
-               j:      { cmd:  "JustifyFull",          action: null},
-               n:      { cmd:  "FormatBlock",          action: null},
                v:      { cmd:  "Paste",                action: null},
                0:      { cmd:  "CleanWord",            action: null},
                z:      { cmd:  "Undo",                 action: null},
@@ -372,9 +362,10 @@ HTMLArea.Config = function () {
  *     context         : "p"                   // will be disabled if not inside a <p> element
  *     hide            : false                 // hide in menu and show only in context menu
  *     selection       : false                 // will be disabled if there is no selection
+ *     dialog          : true                  // the button opens a dialog
  *    });
  */
-HTMLArea.Config.prototype.registerButton = function(id,tooltip,image,textMode,action,context,hide,selection) {
+HTMLArea.Config.prototype.registerButton = function(id,tooltip,image,textMode,action,context,hide,selection, dialog) {
        var buttonId;
        switch (typeof(id)) {
                case "string": buttonId = id; break;
@@ -394,12 +385,14 @@ HTMLArea.Config.prototype.registerButton = function(id,tooltip,image,textMode,ac
                case "string":
                        if (typeof(hide) === "undefined") var hide = false;
                        if (typeof(selection) === "undefined") var selection = false;
-                       this.btnList[id] = [tooltip, image, textMode, action, context, hide, selection];
+                       if (typeof(dialog) === "undefined") var dialog = true;
+                       this.btnList[id] = [tooltip, image, textMode, action, context, hide, selection, dialog];
                        break;
                case "object":
                        if (typeof(id.hide) === "undefined") id.hide = false;
                        if (typeof(id.selection) === "undefined") id.selection = false;
-                       this.btnList[id.id] = [id.tooltip, id.image, id.textMode, id.action, id.context, id.hide, id.selection];
+                       if (typeof(id.dialog) === "undefined") id.dialog = true;
+                       this.btnList[id.id] = [id.tooltip, id.image, id.textMode, id.action, id.context, id.hide, id.selection, id.dialog];
                        break;
        }
        return true;
@@ -530,8 +523,7 @@ HTMLArea.prototype.createSelect = function(txt,tb_line,first_cell_on_line,labelO
        switch (txt) {
                case "FontSize":
                case "FontName":
-               case "FormatBlock":
-                       options = this.config[txt];
+                       options = this.config[txt.toLowerCase()];
                        tooltip = HTMLArea.I18N.tooltips[txt.toLowerCase()];
                        cmd = txt;
                        break;
@@ -795,25 +787,35 @@ HTMLArea.toolBarButtonHandler = function(ev) {
                                HTMLArea._removeClass(target.parentNode, "buttonActive");
                                HTMLArea._removeClass(target, "buttonHover");
                                HTMLArea._removeClass(target.parentNode, "buttonHover");
-                               obj.cmd(editor, obj.name, obj);
+                               obj.cmd(editor, obj.name);
                                HTMLArea._stopEvent(ev);
+                               if (HTMLArea.is_opera) {
+                                       editor._iframe.focus();
+                               }
+                               if (!editor.config.btnList[obj.name][7]) {
+                                       editor.updateToolbar();
+                               }
                                break;
                        case "change":
                                editor.focusEditor();
                                var value = target.options[target.selectedIndex].value;
                                switch (obj.name) {
                                        case "FontName":
-                                       case "FontSize": 
-                                               editor.execCommand(obj.name, false, value);
-                                               break;
-                                       case "FormatBlock":
-                                               (HTMLArea.is_ie || HTMLArea.is_safari) && (value = "<" + value + ">");
+                                       case "FontSize":
                                                editor.execCommand(obj.name, false, value);
                                                break;
                                        default:
                                                var dropdown = editor.config.customSelects[obj.name];
-                                               if (typeof(dropdown) !== "undefined") dropdown.action(editor, obj.name);
-                                                       else HTMLArea._appendToLog("ERROR [HTMLArea::toolBarButtonHandler]: Combo box " + obj.name + " not registered.");
+                                               if (typeof(dropdown) !== "undefined") {
+                                                       dropdown.action(editor, obj.name);
+                                                       HTMLArea._stopEvent(ev);
+                                                       if (HTMLArea.is_opera) {
+                                                               editor._iframe.focus();
+                                                       }
+                                                       editor.updateToolbar();
+                                               } else {
+                                                       HTMLArea._appendToLog("ERROR [HTMLArea::toolBarButtonHandler]: Combo box " + obj.name + " not registered.");
+                                               }
                                }
                }
        }
@@ -1174,8 +1176,8 @@ HTMLArea.prototype.stylesLoaded = function() {
                HTMLArea._addEvent((this._iframe.contentWindow ? this._iframe.contentWindow : this._iframe.contentDocument), "unload", HTMLArea.removeEditorEvents);
        }
 
-               // set cleanWordOnPaste and intercept paste, dragdrop and drop events for wordClean
-       if (this.config.cleanWordOnPaste) HTMLArea._addEvents((HTMLArea.is_ie ? doc.body : doc), ["paste","dragdrop","drop"], HTMLArea.cleanWordOnPaste, true);
+               // 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);
 };
@@ -1310,6 +1312,13 @@ HTMLArea.prototype.setMode = function(mode) {
 };
 
 /*
+ * Get editor mode
+ */
+HTMLArea.prototype.getMode = function() {
+       return this._editMode;
+};
+
+/*
  * Initialize iframe content when in full page mode
  */
 HTMLArea.prototype.setFullHTML = function(html) {
@@ -1411,11 +1420,6 @@ HTMLArea.loadStyle = function(style, plugin, url) {
 };
 
 /*
- * Load the editor skin
- */
-HTMLArea.loadStyle('','',_editor_CSS);
-
-/*
  * Get the url of some image
  */
 HTMLArea.prototype.imgURL = function(file, plugin) {
@@ -1513,7 +1517,7 @@ HTMLArea.wordCleanLater = function(editorNumber,doUpdateToolbar) {
 /*
  * Handler for paste, dragdrop and drop events
  */
-HTMLArea.cleanWordOnPaste = function(ev) {
+HTMLArea.wordClean = function(ev) {
        if(!ev) var ev = window.event;
        var target = (ev.target) ? ev.target : ev.srcElement;
        var owner = (target.ownerDocument) ? target.ownerDocument : target;
@@ -1544,7 +1548,7 @@ HTMLArea.prototype.focusEditor = function() {
                                } else {
                                        this._iframe.contentWindow.focus();
                                }
-                       } catch(e) { };
+                       } catch(e) { }
                        break;
                case "textmode":
                        this._textArea.focus();
@@ -1640,7 +1644,7 @@ HTMLArea.prototype.updateToolbar = function(noStatus) {
                ancestors = null, cls = new Array(),
                txt, txtClass, i, inContext, match, matchAny, k, j, n, commandState;
        if(!text) {
-               selection = this.hasSelectedText();
+               selection = !this._selectionEmpty(this._getSelection());
                ancestors = this.getAllAncestors();
                if(this.config.statusBar && !noStatus) {
                                // Unhook previous events handlers
@@ -1741,7 +1745,7 @@ HTMLArea.prototype.updateToolbar = function(noStatus) {
                                                        break;
                                                }
                                                        // We rely on the fact that the variable in config has the same name as button name in the toolbar.
-                                               var options = this.config[cmd];
+                                               var options = this.config[cmd.toLowerCase()];
                                                k = 0;
                                                for (var j in options) {
                                                        if (options.hasOwnProperty(j)) {
@@ -1757,24 +1761,6 @@ HTMLArea.prototype.updateToolbar = function(noStatus) {
                                                document.getElementById(btn.elementId).selectedIndex = 0;
                                        } catch(e) {}
                                        break;
-                               case "FormatBlock":
-                                       if (!text) {
-                                               var blocks = [ ];
-                                               for (var j in this.config['FormatBlock']) {
-                                                       if (this.config['FormatBlock'].hasOwnProperty(j)) {
-                                                               blocks[blocks.length] = this.config['FormatBlock'][j];
-                                                       }
-                                               }
-                                               var deepestAncestor = this._getFirstAncestor(this._getSelection(), blocks);
-                                               if(deepestAncestor) {
-                                                       for(var x= 0; x < blocks.length; x++) {
-                                                               if(blocks[x].toLowerCase() == deepestAncestor.tagName.toLowerCase()) document.getElementById(btn.elementId).selectedIndex = x;
-                                                       }
-                                               } else {
-                                                       document.getElementById(btn.elementId).selectedIndex = 0;
-                                               }
-                                       }
-                                       break;
                                case "TextIndicator":
                                        if(!text) {
                                                try {with (document.getElementById(btn.elementId).style) {
@@ -1803,16 +1789,14 @@ HTMLArea.prototype.updateToolbar = function(noStatus) {
                                        }
                                        break;
                                case "Paste":
-                                       if(!text) {
-                                               btn.state("enabled", doc.queryCommandEnabled('Paste'));
+                                       if (!text) {
+                                               try {
+                                                       btn.state("enabled", doc.queryCommandEnabled('Paste'));
+                                               } catch(e) {
+                                                       btn.state("enabled", false);
+                                               }
                                        }
                                        break;
-                               case "JustifyLeft":
-                               case "JustifyCenter":
-                               case "JustifyRight":
-                               case "JustifyFull":
-                               case "Indent":
-                               case "Outdent":
                                case "InsertOrderedList":
                                case "InsertUnorderedList":
                                        commandState = false;
@@ -1869,32 +1853,6 @@ HTMLArea.getElementObject = function(el,tagName) {
        return oEl;
 };
 
-/*
- * Make XHTML-compliant nested list
- */
-HTMLArea.prototype.makeNestedList = function(el) {
-       var previous, clone;
-       for (var i = el.firstChild; i; i = i.nextSibling) {
-               if (/^li$/i.test(i.tagName)) {
-                       for (var j = i.firstChild; j; j = j.nextSibling) {
-                               if (/^(ol|ul)$/i.test(j.tagName)) this.makeNestedList(j);
-                       }
-               } else if (/^(ol|ul)$/i.test(i.tagName)) {
-                       previous = i.previousSibling;
-                       var clone = i.cloneNode(true);
-                       if (!previous) {
-                               previous = el.insertBefore(this._doc.createElement("li"),i);
-                               previous.appendChild(clone);
-                       } else {
-                               previous.appendChild(clone);
-                       }
-                       HTMLArea.removeFromParent(i);
-                       this.makeNestedList(el);
-                       break;
-               }
-       }
-};
-
 /***************************************************
  *  SELECTIONS AND RANGES
  ***************************************************/
@@ -1921,6 +1879,37 @@ HTMLArea.prototype.getAllAncestors = function() {
 };
 
 /*
+ * Get the block elements containing the start and the end points of the selection
+ */
+HTMLArea.prototype.getEndBlocks = function(selection) {
+       var range = this._createRange(selection);
+       if (HTMLArea.is_gecko) {
+               var parentStart = range.startContainer;
+               var parentEnd = range.endContainer;
+       } else {
+               if (selection.type !== "Control" ) {
+                       var rangeEnd = range.duplicate();
+                       range.collapse(true);
+                       var parentStart = range.parentElement();
+                       rangeEnd.collapse(false);
+                       var parentEnd = rangeEnd.parentElement();
+               } else {
+                       var parentStart = range.item(0);
+                       var parentEnd = parentStart;
+               }
+       }
+       while (parentStart && !HTMLArea.isBlockElement(parentStart)) {
+               parentStart = parentStart.parentNode;
+       }
+       while (parentEnd && !HTMLArea.isBlockElement(parentEnd)) {
+               parentEnd = parentEnd.parentNode;
+       }
+       return {        start   : parentStart,
+                       end     : parentEnd
+       };
+};
+
+/*
  * Get the deepest ancestor of the selection that is of the specified type
  * Borrowed from Xinha (is not htmlArea) - http://xinha.gogo.co.nz/
  */
@@ -2234,7 +2223,8 @@ HTMLArea.prototype.execCommand = function(cmdID, UI, param) {
        switch (cmdID) {
            case "HtmlMode"     : this.setMode(); break;
            case "SplitBlock"   : this._doc.execCommand('FormatBlock',false,((HTMLArea.is_ie || HTMLArea.is_safari) ? "<div>" : "div")); break;
-           case "HiliteColor"  : (HTMLArea.is_ie || HTMLArea.is_safari) && (cmdID = "BackColor");
+           case "HiliteColor"  :
+               if (HTMLArea.is_ie || HTMLArea.is_safari) { cmdID = "BackColor"; }
            case "ForeColor"    :
                var colorDialogFunctRef = HTMLArea.selectColorDialog(this, cmdID);
                this._popupDialog("select_color.html", colorDialogFunctRef, HTMLArea._colorToRgb(this._doc.queryCommandValue(cmdID)), 200, 182);
@@ -2254,7 +2244,7 @@ HTMLArea.prototype.execCommand = function(cmdID, UI, param) {
            case "Paste"        :
                try {
                        this._doc.execCommand(cmdID, false, null);
-                       if (cmdID == "Paste" && this.config.cleanWordOnPaste) HTMLArea._wordClean(this, this._doc.body);
+                       if (cmdID == "Paste" && this.config.enableWordClean) HTMLArea._wordClean(this, this._doc.body);
                } catch (e) {
                        if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) this._mozillaPasteException(cmdID, UI, param);
                }
@@ -2269,16 +2259,6 @@ HTMLArea.prototype.execCommand = function(cmdID, UI, param) {
                                else el.style.direction = dir;
                }
                break;
-           case "Indent"       :
-               var el = this.getParentElement();
-               while (el && (!HTMLArea.isBlockElement(el) || /^li$/i.test(el.nodeName))) el = el.parentNode;
-               try { this._doc.execCommand(cmdID, UI, param); }
-                       catch(e) { if (this.config.debug) alert(e + "\n\nby execCommand(" + cmdID + ");"); }
-               if (/^(ol|ul)$/i.test(el.nodeName)) {
-                       this.makeNestedList(el);
-                       this.selectNodeContents(el);
-               }
-               break;
            case "FontSize"     :
            case "FontName"     :
                if (param) {
@@ -2338,7 +2318,6 @@ HTMLArea._editorEvent = function(ev) {
                                        }
                                }
                        }
-                       onUpdateToolbar();
                }
                if(ev.ctrlKey) {
                        if(!ev.altKey) {
@@ -2348,19 +2327,6 @@ HTMLArea._editorEvent = function(ev) {
                                var cmd = null;
                                var value = null;
                                switch (key) {
-                                               // headings
-                                       case '1':
-                                       case '2':
-                                       case '3':
-                                       case '4':
-                                       case '5':
-                                       case '6':
-                                               if (editor._toolbarObjects["FormatBlock"]) { 
-                                                       cmd = "FormatBlock";
-                                                       value = "h" + key;
-                                                       if(HTMLArea.is_ie || HTMLArea.is_safari) value = "<" + value + ">";
-                                               }
-                                               break;
                                        case ' ':
                                                editor.insertHTML("&nbsp;");
                                                editor.updateToolbar();
@@ -2377,19 +2343,18 @@ HTMLArea._editorEvent = function(ev) {
                                                                case "Paste":
                                                                        if (HTMLArea.is_ie || HTMLArea.is_safari) {
                                                                                cmd = editor.config.hotKeyList[key].cmd;
-                                                                       } else if (editor.config.cleanWordOnPaste) {
+                                                                       } else if (editor.config.enableWordClean) {
                                                                                window.setTimeout("HTMLArea.wordCleanLater(" + owner._editorNo + ", false);", 50);
                                                                        }
                                                                        break;
                                                                default:
                                                                        if (editor._toolbarObjects[editor.config.hotKeyList[key].cmd]) {
                                                                                cmd = editor.config.hotKeyList[key].cmd;
-                                                                               if(cmd == "FormatBlock") value = (HTMLArea.is_ie || HTMLArea.is_safari) ? "<p>" : "p";
                                                                        }
                                                        }
                                                }
                                }
-                               if(cmd && !editor.config.hotKeyList[key].action) {
+                               if(cmd && !(editor.config.hotKeyList[key] && editor.config.hotKeyList[key].action)) {
                                        editor.execCommand(cmd, false, value);
                                        HTMLArea._stopEvent(ev);
                                        return false;
@@ -2453,10 +2418,12 @@ HTMLArea._editorEvent = function(ev) {
                                        editor._timerToolbar = window.setTimeout("HTMLArea.updateToolbar(" + editor._editorNumber + ");", 50);
                                        break;
                                case 9: // KEY horizontal tab
-                                       if (HTMLArea.is_gecko) {
-                                               editor.execCommand( (ev.shiftKey ? "Outdent" : "Indent"), false, null);
-                                               HTMLArea._stopEvent(ev);
-                                               return false;
+                                       var newkey = (ev.shiftKey ? "SHIFT-" : "") + "TAB";
+                                       if (editor.config.hotKeyList[newkey] && editor.config.hotKeyList[newkey].action) {
+                                               if (!editor.config.hotKeyList[newkey].action(editor, newkey)) {
+                                                       HTMLArea._stopEvent(ev);
+                                                       return false;
+                                               }
                                        }
                                        break;
                                case 37: // LEFT arrow key
@@ -2665,6 +2632,14 @@ HTMLArea._removeClass = function(el, removeClassName) {
  */
 HTMLArea._addClass = function(el, addClassName) {
        HTMLArea._removeClass(el, addClassName);
+       if (el.className && HTMLArea.classesXOR) {
+               var classNames = el.className.trim().split(" ");
+               for (var i = classNames.length; --i >= 0;) {
+                       if (HTMLArea.classesXOR[addClassName] && HTMLArea.classesXOR[addClassName].test(classNames[i])) {
+                               HTMLArea._removeClass(el, classNames[i]);
+                       }
+               }
+       }
        if (el.className) el.className += " " + addClassName;
                else el.className = addClassName;
 };
@@ -2680,10 +2655,9 @@ HTMLArea._hasClass = function(el, className) {
        }
        return false;
 };
-
-HTMLArea.RE_blockTags = /^(body|p|h1|h2|h3|h4|h5|h6|ul|ol|pre|dl|dt|dd|div|noscript|blockquote|form|hr|table|caption|fieldset|address|td|tr|th|li|tbody|thead|tfoot|iframe|object)$/;
+HTMLArea.RE_blockTags = /^(body|p|h1|h2|h3|h4|h5|h6|ul|ol|pre|dl|dt|dd|div|noscript|blockquote|form|hr|table|caption|fieldset|address|td|tr|th|li|tbody|thead|tfoot|iframe)$/;
 HTMLArea.isBlockElement = function(el) { return el && el.nodeType == 1 && HTMLArea.RE_blockTags.test(el.nodeName.toLowerCase()); };
-HTMLArea.RE_closingTags = /^(p|span|a|li|ol|ul|dl|dt|td|th|tr|tbody|thead|tfoot|caption|colgroup|table|div|em|i|strong|b|code|cite|blockquote|q|dfn|abbr|acronym|font|center|object|embed|tt|style|script|title|head|clickenlarge)$/;
+HTMLArea.RE_closingTags = /^(p|blockquote|a|li|ol|ul|dl|dt|td|th|tr|tbody|thead|tfoot|caption|colgroup|table|div|b|bdo|big|cite|code|del|dfn|em|i|ins|kbd|label|q|samp|small|span|strike|strong|sub|sup|tt|u|var|abbr|acronym|font|center|object|embed|style|script|title|head|clickenlarge)$/;
 HTMLArea.RE_noClosingTag = /^(img|br|hr|col|input|area|base|link|meta|param)$/;
 HTMLArea.needsClosingTag = function(el) { return el && el.nodeType == 1 && !HTMLArea.RE_noClosingTag.test(el.tagName.toLowerCase()); };
 
@@ -2702,7 +2676,7 @@ HTMLArea.htmlDecode = function(str) {
 HTMLArea.htmlEncode = function(str) {
        if (typeof(str) != 'string') str = str.toString(); // we don't need regexp for that, but.. so be it for now.
                // Let's not do it twice
-       str = HTMLArea.htmlDecode(str);
+       //str = HTMLArea.htmlDecode(str);
        str = str.replace(/&/g, "&amp;");
        str = str.replace(/</g, "&lt;").replace(/>/g, "&gt;");
        str = str.replace(/\xA0/g, "&nbsp;"); // Decimal 160, non-breaking-space
@@ -2736,7 +2710,10 @@ HTMLArea.getHTMLWrapper = function(root, outputRoot, editor) {
           case 9:      // DOCUMENT_NODE
                var closed, i, config = editor.config;
                var root_tag = (root.nodeType == 1) ? root.tagName.toLowerCase() : '';
-               if (root_tag == 'br' && config.removeTrailingBR && !root.nextSibling && HTMLArea.isBlockElement(root.parentNode) && (!root.previousSibling || root.previousSibling.nodeName.toLowerCase() != 'br')) break;
+               if (root_tag == "br" && config.removeTrailingBR && !root.nextSibling && HTMLArea.isBlockElement(root.parentNode) && (!root.previousSibling || root.previousSibling.nodeName.toLowerCase() != "br")) {
+                       if (!root.previousSibling && root.parentNode && root.parentNode.nodeName.toLowerCase() == "p" && root.parentNode.className) html += "&nbsp;";
+                       break;
+               }
                if (config.htmlRemoveTagsAndContents && config.htmlRemoveTagsAndContents.test(root_tag)) break;
                var custom_tag = (config.customTags && config.customTags.test(root_tag));
                var empty_root = (root_tag == "clickenlarge" && !(root.firstChild && root.firstChild.nodeName.toLowerCase() == "img"));
@@ -3115,60 +3092,37 @@ HTMLArea.initEditor = function(editorNumber) {
                        HTMLArea.initTimer[editorNumber] = window.setTimeout( "HTMLArea.initEditor(" + editorNumber + ");", 150);
                } else {
                        var RTE = RTEarea[editorNumber];
+                       
+                               // Get the configuration properties
                        var config = new HTMLArea.Config();
-
-                               // Get the toolbar config
-                       config.toolbar = RTE["toolbar"];
-
-                               // create an editor for the textarea
-                       RTE["editor"] = new HTMLArea(RTE["id"], config);
-                       var editor = RTE["editor"];
-
+                       for (var property in RTE) {
+                               if (RTE.hasOwnProperty(property)) {
+                                       config[property] = RTE[property] ? RTE[property] : false;
+                               }
+                       }
+                               // Create an editor for the textarea
+                       var editor = new HTMLArea(RTE.id, config);
+                       RTE.editor = editor;
+                       
                                // Save the editornumber in the object
                        editor._typo3EditerNumber = editorNumber;
                        editor._editorNumber = editorNumber;
-                       config = editor.config;
-
-                       config.buttons = RTE["buttons"];
-                       config.hideTableOperationsInToolbar = RTE["hideTableOperationsInToolbar"] ? RTE["hideTableOperationsInToolbar"] : false;
-                       config.disableLayoutFieldsetInTableOperations = RTE["disableLayoutFieldsetInTableOperations"] ? RTE["disableLayoutFieldsetInTableOperations"] : false;
-                       config.disableAlignmentFieldsetInTableOperations = RTE["disableAlignmentFieldsetInTableOperations"] ? RTE["disableAlignmentFieldsetInTableOperations"] : false;
-                       config.disableSpacingFieldsetInTableOperations = RTE["disableSpacingFieldsetInTableOperations"] ? RTE["disableSpacingFieldsetInTableOperations"] : false;
-                       config.disableBordersFieldsetInTableOperations = RTE["disableBordersFieldsetInTableOperations"] ? RTE["disableBordersFieldsetInTableOperations"] : false;
-                       config.disableColorFieldsetInTableOperations = RTE["disableColorFieldsetInTableOperations"] ? RTE["disableColorFieldsetInTableOperations"] : false;
-                       config.disablePCexamples = RTE["disablePCexamples"] ? RTE["disablePCexamples"] : false;
-                       if(RTE["defaultPageStyle"]) config.defaultPageStyle = RTE["defaultPageStyle"];
-                       if(RTE["pageStyle"]) config.pageStyle = RTE["pageStyle"];
-                       if(RTE["fontname"]) config.FontName = RTE["fontname"];
-                       if(RTE["fontsize"]) config.FontSize = RTE["fontsize"];
-                       if(RTE["colors"]) config.colors = RTE["colors"];
-                       if(RTE["disableColorPicker"]) config.disableColorPicker = RTE["disableColorPicker"];
-                       if(RTE["paragraphs"]) config.FormatBlock = RTE["paragraphs"];
-                       config.width = "auto";
-                       config.height = "auto";
-                       config.sizeIncludesToolbar = true;
-                       config.fullPage = false;
-                       config.useHTTPS = RTE["useHTTPS"] ? RTE["useHTTPS"] : false;
-                       config.disableEnterParagraphs = RTE["disableEnterParagraphs"] ? RTE["disableEnterParagraphs"] : false;
-                       config.removeTrailingBR = RTE["removeTrailingBR"] ? RTE["removeTrailingBR"] : false;
-                       config.keepButtonGroupTogether = (RTE["keepButtonGroupTogether"] && HTMLArea.is_gecko && !HTMLArea.is_wamcom && !HTMLArea.is_opera) ? RTE["keepButtonGroupTogether"] : false;
-                       config.useCSS = RTE["useCSS"] ? RTE["useCSS"] : false;
-                       config.enableMozillaExtension = RTE["enableMozillaExtension"] ? RTE["enableMozillaExtension"] : false;
-                       config.statusBar = RTE["statusBar"] ? RTE["statusBar"] : false;
-                       config.cleanWordOnPaste = RTE["enableWordClean"] ? true : false;
-                       config.htmlRemoveTags = RTE["htmlRemoveTags"] ? RTE["htmlRemoveTags"] : null;
-                       config.htmlRemoveTagsAndContents = RTE["htmlRemoveTagsAndContents"] ? RTE["htmlRemoveTagsAndContents"] : null;
-                       config.htmlRemoveComments = RTE["htmlRemoveComments"] ? true : false;
-                       config.classesUrl = RTE["classesUrl"] ? RTE["classesUrl"] : null;
                        
-                       for (var plugin in RTE.plugin) {
-                               if (RTE.plugin.hasOwnProperty(plugin) && RTE.plugin[plugin]) {
+                               // Override these settings if they were ever modified
+                       editor.config.width = "auto";
+                       editor.config.height = "auto";
+                       editor.config.sizeIncludesToolbar = true;
+                       editor.config.fullPage = false;
+                       
+                               // Register the plugins included in the configuration
+                       for (var plugin in editor.config.plugin) {
+                               if (editor.config.plugin.hasOwnProperty(plugin) && editor.config.plugin[plugin]) {
                                        editor.registerPlugin(plugin);
                                }
                        }
                        
                        editor.onGenerate = HTMLArea.onGenerateHandler(editorNumber);
-
+                       
                        editor.generate();
                        return false;
                } 
@@ -3295,15 +3249,21 @@ HTMLArea.Base.implement = function(_interface) {
 };
 
 /**
- * HTMLArea. plugin constructor
+ * HTMLArea.plugin class
  *
- * @param      object          editor: instance of RTE
- * @param      string          pluginName: name of the plugin
+ * Every plugin should be a subclass of this class
  *
- * @return     boolean         true if the plugin was configured
  */
-HTMLArea.plugin = HTMLArea.Base.extend({
-
+HTMLArea.Plugin = HTMLArea.Base.extend({
+       
+       /**
+        * HTMLArea.plugin constructor
+        *
+        * @param       object          editor: instance of RTE
+        * @param       string          pluginName: name of the plugin
+        *
+        * @return      boolean         true if the plugin was configured
+        */
        constructor : function(editor, pluginName) {
                this.editor = editor;
                this.editorNumber = editor._editorNumber;
@@ -3403,6 +3363,7 @@ HTMLArea.plugin = HTMLArea.Base.extend({
         *                                      hide            : hide in menu and show only in context menu?
         *                                      selection       : will be disabled if there is no selection?
         *                                      hotkey          : hotkey character
+        *                                      dialog          : if true, the button opens a dialog
         *
         * @return      boolean         true if the button was successfully registered
         */
@@ -3412,10 +3373,17 @@ HTMLArea.plugin = HTMLArea.Base.extend({
                                var hotKeyAction = buttonConfiguration.action;
                                var actionFunctionReference = this.makeFunctionReference(buttonConfiguration.action);
                                buttonConfiguration.action = actionFunctionReference;
+                               if (!buttonConfiguration.textMode) {
+                                       buttonConfiguration.textMode = false;
+                               }
+                               if (!buttonConfiguration.dialog) {
+                                       buttonConfiguration.dialog = false;
+                               }
                                if (this.editorConfiguration.registerButton(buttonConfiguration)) {
-                                       if (buttonConfiguration.hotKey) {
+                                       var hotKey = buttonConfiguration.hotKey ? buttonConfiguration.hotKey : ((this.editorConfiguration.buttons[buttonConfiguration.id.toLowerCase()] && this.editorConfiguration.buttons[buttonConfiguration.id.toLowerCase()].hotKey) ? this.editorConfiguration.buttons[buttonConfiguration.id.toLowerCase()].hotKey : null);
+                                       if (hotKey) {
                                                var hotKeyConfiguration = {
-                                                       id      : buttonConfiguration.hotKey,
+                                                       id      : hotKey,
                                                        cmd     : buttonConfiguration.id,
                                                        action  : hotKeyAction
                                                };
@@ -3448,6 +3416,9 @@ HTMLArea.plugin = HTMLArea.Base.extend({
                        if (typeof((dropDownConfiguration.action) === "string") && (typeof(this[dropDownConfiguration.action]) === "function")) {
                                var actionFunctionReference = this.makeFunctionReference(dropDownConfiguration.action);
                                dropDownConfiguration.action = actionFunctionReference;
+                               if (!dropDownConfiguration.textMode) {
+                                       dropDownConfiguration.textMode = false;
+                               }
                                if (typeof(dropDownConfiguration.refresh) === "string") {
                                        if (typeof(this[dropDownConfiguration.refresh]) === "function") {
                                                var refreshFunctionReference = this.makeFunctionReference(dropDownConfiguration.refresh);
@@ -3516,6 +3487,21 @@ HTMLArea.plugin = HTMLArea.Base.extend({
        },
        
        /**
+        * Returns the hotkey configuration
+        *
+        * @param       string          key: the hotkey
+        *
+        * @return      object          the hotkey configuration object
+        */
+       getHotKeyConfiguration : function(key) {
+               if (typeof(this.editorConfiguration.hotKeyList[key]) !== "undefined") {
+                       return this.editorConfiguration.hotKeyList[key];
+               } else {
+                       return null;
+               }
+       },
+       
+       /**
         * The toolbar refresh handler of the plugin
         * This function may be defined by the plugin subclass.
         * If defined, the function will be invoked whenever the toolbar state is refreshed.
@@ -3527,7 +3513,7 @@ HTMLArea.plugin = HTMLArea.Base.extend({
        /**
         * The keyPress event handler
         * This function may be defined by the plugin subclass.
-        * If defined, the function will be invoked whenever a key is pressed.
+        * If defined, the function is invoked whenever a key is pressed.
         *
         * @param       event           keyEvent: the event that was triggered when a key was pressed
         *
@@ -3538,7 +3524,7 @@ HTMLArea.plugin = HTMLArea.Base.extend({
        /**
         * The hotKey event handler
         * This function may be defined by the plugin subclass.
-        * If defined, the function will be invoked whenever a hot key is pressed.
+        * If defined, the function is invoked whenever a hot key is pressed.
         *
         * @param       event           key: the hot key that was pressed
         *
@@ -3548,19 +3534,23 @@ HTMLArea.plugin = HTMLArea.Base.extend({
        
        /**
         * The onMode event handler
-        * This function may be defined by the plugin subclass.
-        * If defined, the function will invoked whenever the editor changes mode.
+        * This function may be redefined by the plugin subclass.
+        * The function is invoked whenever the editor changes mode.
         *
         * @param       string          mode: "wysiwyg" or "textmode"
         *
         * @return      boolean
         */
-       onMode : null,
+       onMode : function(mode) {
+               if (this.dialog && mode === "textmode" && !this.editorConfiguration.btnList[this.dialog.buttonId].textMode) {
+                       this.dialog.close();
+               }
+       },
        
        /**
         * The onGenerate event handler
         * This function may be defined by the plugin subclass.
-        * If defined, the function will invoked when the editor is initialized
+        * If defined, the function is invoked when the editor is initialized
         *
         * @return      boolean
         */
@@ -3571,12 +3561,12 @@ HTMLArea.plugin = HTMLArea.Base.extend({
         *
         * @param       string          functionName: the name of the plugin function to be invoked
         *
-        * @return      function        function definition invoking the specified funcion of the plugin
+        * @return      function        function definition invoking the specified function of the plugin
         */
        makeFunctionReference : function (functionName) {
                var self = this;
-               return (function(editor, buttonId) {
-                       self[functionName](editor, buttonId);});
+               return (function(arg1, arg2) {
+                       self[functionName](arg1, arg2);});
        },
        
        /**
@@ -3597,15 +3587,19 @@ HTMLArea.plugin = HTMLArea.Base.extend({
         *
         * @return      boolean         true on success
         */
-       getJavascriptFile : function (url) {
+       getJavascriptFile : function (url, noEval) {
                var script = HTMLArea._getScript(0, false, url);
                if (script) {
-                       try {
-                               eval(script);
-                               return true;
-                       } catch(e) {
-                               this.appendToLog("getJavascriptFile", "Error evaluating contents of Javascript file: " + url);
-                               return false;
+                       if (noEval) {
+                               return script;
+                       } else {
+                               try {
+                                       eval(script);
+                                       return true;
+                               } catch(e) {
+                                       this.appendToLog("getJavascriptFile", "Error evaluating contents of Javascript file: " + url);
+                                       return false;
+                               }
                        }
                } else {
                        return false;
@@ -3613,6 +3607,66 @@ HTMLArea.plugin = HTMLArea.Base.extend({
        },
        
        /**
+        * Open a dialog window or bring focus to it if is already opened
+        *
+        * @param       string          buttonId: buttonId requesting the opening of the dialog
+        * @param       string          url: name, without extension, of the html file to be loaded into the dialog window
+        * @param       string          action: name of the plugin function to be invoked when the dialog ends
+        * @param       object          arguments: object of variable type to be passed to the dialog
+        * @param       object          dimensions: object giving the width and height of the dialog window
+        * @param       string          showScrollbars: specifies by "yes" or "no" whether or not the dialog window should have scrollbars
+        *
+        * @return      object          the dialog window
+        */
+       openDialog : function (buttonId, url, action, arguments, dimensions, showScrollbars) {
+               if (this.dialog && this.dialog.hasOpenedWindow() && this.dialog.buttonId === buttonId) {
+                       this.dialog.focus();
+                       return this.dialog;
+               } else {
+                       var actionFunctionReference = action;
+                       if (typeof(action) === "string") {
+                               if (typeof(this[action]) === "function") {
+                                       var actionFunctionReference = this.makeFunctionReference(action);
+                               } else {
+                                       this.appendToLog("openDialog", "Function " + action + " was not defined when opening dialog for " + buttonId);
+                               }
+                       }
+                       return new HTMLArea.Dialog(
+                                       this,
+                                       buttonId,
+                                       url,
+                                       actionFunctionReference,
+                                       arguments,
+                                       {width: (dimensions.width?dimensions.width:100), height: (dimensions.height?dimensions.height:100)},
+                                       (showScrollbars?showScrollbars:"no")
+                               );
+               }
+       },
+       
+       /**
+        * Make url from the name of a popup of the plugin
+        *
+        * @param       string          popupName: name, without extension, of the html file to be loaded into the dialog window
+        *
+        * @return      string          the url
+        */
+       makeUrlFromPopupName : function(popupName) {
+               return this.editor.popupURL("plugin://" + this.name + "/" + popupName);
+       },
+       
+       /**
+        * Make url from module path
+        *
+        * @param       string          modulePath: module path
+        * @param       string          parameters: additional parameters
+        *
+        * @return      string          the url
+        */
+       makeUrlFromModulePath : function(modulePath, parameters) {
+               return this.editor.popupURL(modulePath + "?" + RTEarea[this.editorNumber]["RTEtsConfigParams"] + parameters);
+       },
+       
+       /**
         * Append an entry at the end of the troubleshooting log
         *
         * @param       string          functionName: the name of the plugin function writing to the log
@@ -3625,3 +3679,327 @@ HTMLArea.plugin = HTMLArea.Base.extend({
        }
 });
 
+/**
+ * HTMLArea.Dialog class
+ *
+ * Every dialog should be an instance of this class
+ *
+ */
+HTMLArea.Dialog = HTMLArea.Base.extend({
+       
+       /**
+        * HTMLArea.Dialog constructor
+        *
+        * @param       object          plugin: reference to the invoking plugin
+        * @param       string          buttonId: buttonId triggering the opening of the dialog
+        * @param       string          url: url of the html document to load into the dialog window
+        * @param       function        action: function to be executed when the the dialog ends
+        * @param       object          arguments: object of variable type to be passed to the dialog
+        * @param       object          dimensions: object giving the width and height of the dialog window
+        * @param       string          showScrollbars: specifies by "yes" or "no" whether or not the dialog window should have scrollbars
+        *
+        * @return      boolean         true if the dialog window was opened
+        */
+       constructor : function (plugin, buttonId, url, action, arguments, dimensions, showScrollbars) {
+               this.window = window.window ? window.window : window.self;
+               this.plugin = plugin;
+               this.buttonId = buttonId;
+               this.action = action;
+               if (typeof(arguments) !== "undefined") {
+                       this.arguments = arguments;
+               }
+               this.plugin.dialog = this;
+               
+               if (HTMLArea.Dialog[this.plugin.name] && HTMLArea.Dialog[this.plugin.name].hasOpenedWindow() && HTMLArea.Dialog[this.plugin.name].plugin != this.plugin) {
+                       HTMLArea.Dialog[this.plugin.name].close();
+               }
+               HTMLArea.Dialog[this.plugin.name] = this;
+               
+               this.dialogWindow = window.open(url, this.plugin.name + "Dialog", "toolbar=no,location=no,directories=no,menubar=no,resizable=yes,top=100,left=100,dependent=yes,dialog=yes,chrome=no,width=" + dimensions.width + ",height=" + dimensions.height + ",scrollbars=" + showScrollbars);
+               if (!this.dialogWindow) {
+                       this.plugin.appendToLog("openDialog", "Dialog window could not be opened with url " + url);
+                       return false;
+               }
+               if (!this.dialogWindow.opener) {
+                       this.dialogWindow.opener = this.window;
+               }
+               return true;
+       },
+       
+       hasOpenedWindow : function () {
+               return this.dialogWindow && !this.dialogWindow.closed;
+       },
+       
+       /**
+        * Initialize the dialog window: load the stylesheets, localize labels, resize if required, etc.
+        * This function MUST be invoked from the dialog window in the onLoad event handler
+        *
+        * @param       boolean         noResize: if true the window in not resized, but may be centered
+        *
+        * @return      void
+        */
+       initialize : function (noLocalize, noResize) {
+               this.dialogWindow.HTMLArea = HTMLArea;
+               this.dialogWindow.dialog = this;
+                       // Get stylesheets for the dialog window
+               this.loadStyle();
+                       // Localize the labels of the popup window
+               if (!noLocalize) this.localize();
+                       // Resize the dialog window to its contents
+               if (!noResize) this.resize(noResize);
+                       // Capture unload and escape events
+               this.captureEvents();
+       },
+       
+       /**
+        * Load the stylesheets in the dialog window
+        *
+        * @return      void
+        */
+       loadStyle : function () {
+               var head = this.dialogWindow.document.getElementsByTagName("head")[0];
+               var link = this.dialogWindow.document.createElement("link");
+               link.rel = "stylesheet";
+               link.type = "text/css";
+               link.href = HTMLArea.editorCSS;
+               head.appendChild(link);
+       },
+       
+       /**
+        * Localize the labels contained in the dialog window
+        *
+        * @return      void
+        */
+       localize : function () {
+               var label;
+               var types = ["input", "label", "option", "select", "legend", "span", "td", "button", "div", "h1", "h2", "a"];
+               for (var type = 0; type < types.length; ++type) {
+                       var elements = this.dialogWindow.document.getElementsByTagName(types[type]);
+                       for (var i = elements.length; --i >= 0;) {
+                               var element = elements[i];
+                               if (element.firstChild && element.firstChild.data) {
+                                       label = this.plugin.localize(element.firstChild.data);
+                                       if (label) element.firstChild.data = label;
+                               }
+                               if (element.title) {
+                                       element.title = this.plugin.localize(element.title);
+                               }
+                                       // resetting the selected option for Mozilla
+                               if (types[type] == "option" && element.selected ) {
+                                       element.selected = false;
+                                       element.selected = true;
+                               }
+                       }
+               }
+               this.dialogWindow.document.title = this.plugin.localize(this.dialogWindow.document.title);
+       },
+       
+       /**
+        * Resize the dialog window to its contents
+        *
+        * @param       boolean         noResize: if true the window in not resized, but may be centered
+        *
+        * @return      void
+        */
+       resize : function (noResize) {
+                       // resize if allowed
+               var dialogWindow = this.dialogWindow;
+               var content = dialogWindow.document.getElementById("content");
+               if ((HTMLArea.is_gecko && !HTMLArea.is_opera && !HTMLArea.is_safari) || (HTMLArea.is_opera && content)) {
+                       var self = this;
+                       setTimeout( function() {
+                               try {
+                                       if (!noResize) {
+                                               dialogWindow.sizeToContent();
+                                       }
+                               } catch(e) {
+                                       self.resizeToContent(content);
+                               }
+                                       // center on parent if allowed
+                               var x = dialogWindow.opener.screenX + (dialogWindow.opener.outerWidth - dialogWindow.outerWidth) / 2;
+                               var y = dialogWindow.opener.screenY + (dialogWindow.opener.outerHeight - dialogWindow.outerHeight) / 2;
+                               try {
+                                       dialogWindow.moveTo(x, y);
+                               } catch(e) { }
+                       }, 25);
+               } else {
+                       var innerX, innerY;
+                       if (dialogWindow.innerHeight) {
+                                       // all except Explorer
+                               innerX = dialogWindow.innerWidth;
+                               innerY = dialogWindow.innerHeight;
+                       } else if (dialogWindow.document.documentElement && dialogWindow.document.documentElement.clientHeight) {
+                                       // Explorer 6 Strict Mode
+                               innerX = dialogWindow.document.documentElement.clientWidth;
+                               innerY = dialogWindow.document.documentElement.clientHeight;
+                       } else if (document.body) {
+                                       // other Explorers
+                               innerX = dialogWindow.document.body.clientWidth;
+                               innerY = dialogWindow.document.body.clientHeight;
+                       }
+                       
+                       var pageX, pageY;
+                       var test1 = dialogWindow.document.body.scrollHeight;
+                       var test2 = dialogWindow.document.body.offsetHeight
+                       if (test1 > test2) {
+                                       // all but Explorer Mac
+                               pageX = dialogWindow.document.body.scrollWidth;
+                               pageY = dialogWindow.document.body.scrollHeight;
+                       } else {
+                                       // Explorer Mac;
+                                       //would also work in Explorer 6 Strict, Mozilla and Safari
+                               pageX = dialogWindow.document.body.offsetWidth;
+                               pageY = dialogWindow.document.body.offsetHeight;
+                       }
+                       dialogWindow.resizeBy(pageX - innerX, pageY - innerY);
+                       
+                               // center on parent if allowed
+                       var W = dialogWindow.document.body.offsetWidth;
+                       var H = dialogWindow.document.body.offsetHeight;
+                       var x = (screen.availWidth - W) / 2;
+                       var y = (screen.availHeight - H) / 2;
+                       dialogWindow.moveTo(x, y);
+               }
+       },
+       
+       /**
+        * Resize the Opera dialog window to its contents, based on size of content div
+        *
+        * @param       object          content: reference to the div section containing the contents of the dialog window
+        *
+        * @return      void
+        */
+       resizeToContent : function(content) {
+               var dialogWindow = this.dialogWindow;
+               var doc = dialogWindow.document;
+               var docElement = doc.documentElement;
+               var body = doc.body;
+               var width = 0, height = 0;
+       
+               var contentWidth = content.offsetWidth;
+               var contentHeight = content.offsetHeight;
+               dialogWindow.resizeTo( contentWidth + 200, contentHeight + 200 );
+               
+               if (dialogWindow.innerWidth) {
+                       width = dialogWindow.innerWidth;
+                       height = dialogWindow.innerHeight;
+               } else if (docElement && docElement.clientWidth) {
+                       width = docElement.clientWidth;
+                       height = docElement.clientHeight;
+               } else if (body && body.clientWidth) {
+                       width = body.clientWidth;
+                       height = body.clientHeight;
+               }
+               dialogWindow.resizeTo( contentWidth + ( ( contentWidth + 200 ) - width ), contentHeight + ( (contentHeight + 200 ) - (height - 16) ) );
+       },
+       
+       /**
+        * Perform the action function when the dialog end
+        *
+        * @return      void
+        */
+       performAction : function (val) {
+               if (val && this.action) {
+                       this.action(val);
+               }
+       },
+       
+       /**
+        * Bring the focus on the dialog window
+        *
+        * @return      void
+        */
+       focus : function () {
+               this.dialogWindow.focus();
+       },
+       
+       /**
+        * Close the dialog window
+        *
+        * @return      void
+        */
+       close : function () {
+               if (this.hasOpenedWindow()) {
+                       if (this.dialogWindow.opener && !this.dialogWindow.opener.closed) {
+                               this.releaseEvents();
+                       }
+                       this.releaseEvents(this.dialogWindow);
+                       HTMLArea.Dialog[this.plugin.name] = null;
+                       this.dialogWindow.close();
+                       this.dialogWindow.dialog = null;
+                       this.plugin.editor.updateToolbar();
+               }
+               return false;
+       },
+       
+       /**
+        * Make function reference in order to avoid memory leakage in IE
+        *
+        * @param       string          functionName: the name of the dialog function to be invoked
+        *
+        * @return      function        function definition invoking the specified function of the dialog
+        */
+       makeFunctionReference : function (functionName) {
+               var self = this;
+               return (function(arg1, arg2) {
+                       self[functionName](arg1, arg2);});
+       },
+       
+       /**
+        * Escape event handler
+        *
+        * @param       object          ev: the event
+        *
+        * @return      boolean         false if the event was handled
+        */
+       closeOnEscape : function(ev) {
+               if (!ev) var ev = window.event;
+               if (ev.keyCode == 27) {
+                       if (HTMLArea.is_gecko) {
+                               var parentWindow = ev.currentTarget.defaultView;
+                       } else {
+                               var parentWindow = ev.srcElement.parentNode.parentNode.parentWindow;
+                       }
+                       if (parentWindow && parentWindow.dialog) {
+                               parentWindow.dialog.close();
+                               return false;
+                       }
+               }
+               return true;
+       },
+       
+       /**
+        *Capture unload and escape events
+        *
+        * @return      void
+        */     
+       captureEvents : function () {
+               this.unloadFunctionReference = this.makeFunctionReference("close");
+               HTMLArea._addEvent(this.dialogWindow.opener, "unload", this.unloadFunctionReference);
+               if (HTMLArea.is_gecko && this.plugin.editor._iframe.contentWindow) {
+                       HTMLArea._addEvent(this.plugin.editor._iframe.contentWindow, "unload", this.unloadFunctionReference);
+               }
+               HTMLArea._addEvent(this.dialogWindow, "unload", this.unloadFunctionReference);
+               this.escapeFunctionReference = this.makeFunctionReference("closeOnEscape");
+               HTMLArea._addEvent(this.dialogWindow.document, "keypress", this.escapeFunctionReference);
+        },
+       
+       /**
+        * Release all event handlers that were set when the dialog window was opened
+        *
+        * @return      void
+        */
+       releaseEvents : function() {
+               var opener = this.dialogWindow.opener;
+               if (opener && !opener.closed) {
+                               // release the capturing of events
+                       HTMLArea._removeEvent(opener, "unload", this.unloadFunctionReference);
+                       HTMLArea._removeEvent(this.dialogWindow, "unload", this.unloadFunctionReference);
+                       if (HTMLArea.is_gecko && this.plugin.editor._iframe.contentWindow) {
+                               HTMLArea._removeEvent(this.plugin.editor._iframe.contentWindow, "unload", this.unloadFunctionReference);
+                       }
+                       HTMLArea._removeEvent(this.dialogWindow.document, "keypress", this.escapeFunctionReference);
+               }
+       }
+});
+
index 14dbaee..450668b 100644 (file)
@@ -86,7 +86,7 @@
                        <label index="About HTMLArea">About htmlArea RTE</label>
                        <label index="About">About</label>
                        <label index="free_editor">A free and open-source editor for &lt;textarea&gt; fields, featuring integration with TYPO3.</label>
-                       <label index="Mozilla_or_IE">For Mozilla 1.3.1+, Firefox 0.8+ and Netscape 7.1+ on any platform, and for Internet Explorer 5.5+ on Windows.</label>
+                       <label index="Mozilla_or_IE">For Mozilla 1.3.1+, Firefox 0.8+, Netscape 7.1+ and Safari 3.0.4 on any platform, and for Internet Explorer 5.5+ on Windows.</label>
                        <label index="product_documentation">For more information, please visit:</label>
                        <label index="All rights reserved.">All Rights Reserved.</label>
                        <label index="License">License</label>
@@ -99,7 +99,8 @@
                        <label index="No plugins have been loaded.">No plugins have been loaded.</label>
                        <label index="User agent reports:">User agent reports:</label>
                        <label index="style">Paragraph:</label>
-                       <label index="text_style">Text:</label>
+                       <label index="Block style label">Block style:</label>
+                       <label index="text_style">Text style:</label>
                </languageKey>
        </data>
        <orig_hash type="array">
index 5e4b684..89791ea 100644 (file)
                        <label index="insertimage">Insert/Modify Image</label>
                        <label index="inserttable">Insert Table</label>
                        <label index="htmlmode">Toggle HTML Source</label>
-                       <label index="popupeditor">Enlarge Editor</label>
+                       <label index="popupeditor">Enlarge the editor</label>
                        <label index="about">About this editor</label>
                        <label index="showhelp">Help using editor</label>
                        <label index="textindicator">Current style</label>
-                       <label index="undo">Undoes your last action</label>
-                       <label index="redo">Redoes your last action</label>
+                       <label index="undo">Undo the last action</label>
+                       <label index="redo">Redo the last action</label>
                        <label index="cut">Cut selection</label>
                        <label index="copy">Copy selection</label>
                        <label index="paste">Paste from clipboard</label>
diff --git a/typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/block-elements.js b/typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/block-elements.js
new file mode 100644 (file)
index 0000000..e75d98e
--- /dev/null
@@ -0,0 +1,806 @@
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2007-2008 Stanislas Rolland <stanislas.rolland(arobas)fructifor.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!
+***************************************************************/
+/*
+ * BlockElements Plugin for TYPO3 htmlArea RTE
+ *
+ * TYPO3 SVN ID: $Id$
+ */
+BlockElements = 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.useClass = {
+                       Indent          : "indent",
+                       JustifyLeft     : "align-left",
+                       JustifyCenter   : "align-center",
+                       JustifyRight    : "align-right",
+                       JustifyFull     : "align-justify"
+               };
+               this.useAlignAttribute = false;
+               for (var buttonId in this.useClass ) {
+                       if (this.useClass.hasOwnProperty(buttonId)) {
+                               if (this.editorConfiguration.buttons[buttonId.toLowerCase()]) {
+                                       this.useClass[buttonId] = this.editorConfiguration.buttons[buttonId.toLowerCase()].useClass ? this.editorConfiguration.buttons[buttonId.toLowerCase()].useClass : this.useClass[buttonId];
+                                       if (buttonId === "Indent") {
+                                               this.useBlockquote = this.editorConfiguration.buttons.indent.useBlockquote ? this.editorConfiguration.buttons.indent.useBlockquote : false;
+                                       } else {
+                                               if (this.editorConfiguration.buttons[buttonId.toLowerCase()].useAlignAttribute) {
+                                                       this.useAlignAttribute = true;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               this.allowedAttributes = new Array("id", "title", "lang", "xml:lang", "dir", (HTMLArea.is_gecko?"class":"className"));
+               this.indentedList = null;
+               
+               /*
+                * Registering plugin "About" information
+                */
+               var pluginInformation = {
+                       version         : "1.0",
+                       developer       : "Stanislas Rolland",
+                       developerUrl    : "http://www.fructifor.ca/",
+                       copyrightOwner  : "Stanislas Rolland",
+                       sponsor         : this.localize("Technische Universitat Ilmenau"),
+                       sponsorUrl      : "http://www.tu-ilmenau.de/",
+                       license         : "GPL"
+               };
+               this.registerPluginInformation(pluginInformation);
+               
+               /*
+                * Registering the dropdown list
+                */
+               var buttonId = "FormatBlock";
+               var dropDownConfiguration = {
+                       id              : buttonId,
+                       tooltip         : this.localize(buttonId + "-Tooltip"),
+                       options         : ((this.editorConfiguration.buttons[buttonId.toLowerCase()] && this.editorConfiguration.buttons[buttonId.toLowerCase()].dropDownOptions) ? this.editorConfiguration.buttons[buttonId.toLowerCase()].dropDownOptions : null),
+                       action          : "onChange",
+                       refresh         : null,
+                       context         : null
+               };
+               this.registerDropDown(dropDownConfiguration);
+               
+               /*
+                * Establishing the list of allowed block elements
+                */
+               var blockElements = new Array();
+               for (var option in dropDownConfiguration.options) {
+                       if (dropDownConfiguration.options.hasOwnProperty(option)) {
+                               blockElements.push(dropDownConfiguration.options[option]);
+                       }
+               }
+               this.allowedBlockElements = new RegExp( "^(" + blockElements.join("|") + ")$", "i");
+               
+               /*
+                * Registering hot keys
+                */
+               for (var i = 0; i < blockElements.length; ++i) {
+                       var configuredHotKey = this.defaultHotKeys[blockElements[i]];
+                       if (this.editorConfiguration.buttons.formatblock
+                                       && this.editorConfiguration.buttons.formatblock.items
+                                       && this.editorConfiguration.buttons.formatblock.items[blockElements[i]]
+                                       && this.editorConfiguration.buttons.formatblock.items[blockElements[i]].hotKey) {
+                               configuredHotKey = this.editorConfiguration.buttons.formatblock.items[blockElements[i]].hotKey;
+                       }
+                       if (configuredHotKey) {
+                               var hotKeyConfiguration = {
+                                       id              : configuredHotKey,
+                                       cmd             : buttonId,
+                                       action          : "onHotKey",
+                                       element         : blockElements[i]
+                               };
+                               this.registerHotKey(hotKeyConfiguration);
+                       }
+               }
+               
+               /*
+                * Registering the buttons
+                */
+               var buttonList = this.buttonList;
+               for (var i = 0; i < buttonList.length; ++i) {
+                       var button = buttonList[i];
+                       buttonId = button[0];
+                       var buttonConfiguration = {
+                               id              : buttonId,
+                               tooltip         : this.localize(buttonId + "-Tooltip"),
+                               action          : "onButtonPress",
+                               context         : button[1],
+                               hotKey          : button[2]
+                       };
+                       this.registerButton(buttonConfiguration);
+               }
+               
+               return true;
+        },
+        
+       /*
+        * The list of buttons added by this plugin
+        */
+       buttonList : [
+               ["Indent", null, "TAB"],
+               ["Outdent", null, "SHIFT-TAB"],
+               ["Blockquote", null, null],
+               ["InsertParagraphBefore", null, null],
+               ["InsertParagraphAfter", null, null],
+               ["JustifyLeft", null, "l"],
+               ["JustifyCenter", null, "e"],
+               ["JustifyRight", null, "r"],
+               ["JustifyFull", null, "j"]
+       ],
+       
+       /*
+        * The list of hotkeys associated with block elements and registered by default by this plugin
+        */
+       defaultHotKeys : {
+                       "p"     : "n",
+                       "h1"    : "1",
+                       "h2"    : "2",
+                       "h3"    : "3",
+                       "h4"    : "4",
+                       "h5"    : "5",
+                       "h6"    : "6"
+       },
+       
+       /*
+        * This function gets called when some block element was selected in the drop-down list
+        */
+       onChange : function (editor, buttonId) {
+               var tbobj = this.editor._toolbarObjects[buttonId];
+               var blockElement = document.getElementById(tbobj.elementId).value;
+               this.applyBlockElement(buttonId, blockElement);
+       },
+       
+       applyBlockElement : function(buttonId, blockElement) {
+               switch (blockElement) {
+                       case "blockquote" :
+                               this.onButtonPress(this.editor, "Blockquote");
+                               break;
+                       case "div"     :
+                       case "address" :
+                       case "none"    :
+                               this.onButtonPress(this.editor, blockElement);
+                               break;
+                       default :
+                               var element = blockElement;
+                               if (HTMLArea.is_ie) {
+                                       element = "<" + element + ">";
+                               }
+                               this.editor.focusEditor();
+                               if (HTMLArea.is_safari && !this.editor._doc.body.hasChildNodes()) {
+                                       this.editor._doc.body.appendChild((this.editor._doc.createElement("br")));
+                               }
+                               try {
+                                       this.editor._doc.execCommand(buttonId, false, element);
+                               } catch(e) {
+                                       this.appendToLog("applyBlockElement", e + "\n\nby execCommand(" + buttonId + ");");
+                               }
+               }
+       },
+       
+       /*
+        * This function gets called when a button 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();
+               var selection = editor._getSelection();
+               var range = editor._createRange(selection);
+               var parentElement = this.editor._statusBarTree.selected ? this.editor._statusBarTree.selected : this.editor.getParentElement(selection, range);
+               if (typeof(target) !== "undefined") {
+                       parentElement = target;
+               }
+               while (parentElement && (!HTMLArea.isBlockElement(parentElement) || /^li$/i.test(parentElement.nodeName))) {
+                       parentElement = parentElement.parentNode;
+               }
+               var blockAncestors = this.getBlockAncestors(parentElement);
+               var tableCell = null;
+               
+               if (id === "TAB" || id === "SHIFT-TAB") {
+                       for (var i = blockAncestors.length; --i >= 0;) {
+                               if (/^(td|th)$/i.test(blockAncestors[i].nodeName)) {
+                                       tableCell = blockAncestors[i];
+                                       break;
+                               }
+                       }
+               }
+               var fullNodeTextSelected = (HTMLArea.is_gecko && parentElement.textContent === range.toString()) || (HTMLArea.is_ie && parentElement.innerText === range.text);
+
+               switch (buttonId) {
+                       case "Indent" :
+                               if (/^(ol|ul)$/i.test(parentElement.nodeName) && !(fullNodeTextSelected && !/^(li)$/i.test(parentElement.parentNode.nodeName))) {
+                                       try {
+                                               this.editor._doc.execCommand(buttonId, false, null);
+                                       } catch(e) {
+                                               this.appendToLog("onButtonPress", e + "\n\nby execCommand(" + buttonId + ");");
+                                       }
+                                       this.indentedList = parentElement;
+                                       this.makeNestedList(parentElement);
+                                       this.editor.selectNodeContents(this.indentedList.lastChild, false);
+                               } else if (tableCell) {
+                                       var nextCell = tableCell.nextSibling ? tableCell.nextSibling : (tableCell.parentNode.nextSibling ? tableCell.parentNode.nextSibling.firstChild : null);
+                                       if (!nextCell) {
+                                               nextCell = tableCell.parentNode.parentNode.firstChild.firstChild;
+                                       }
+                                       if (nextCell) {
+                                               this.editor.selectNodeContents(nextCell, true);
+                                       }
+                               } else  if (this.useBlockquote) {
+                                       try {
+                                               this.editor._doc.execCommand(buttonId, false, null);
+                                       } catch(e) {
+                                               this.appendToLog("onButtonPress", e + "\n\nby execCommand(" + buttonId + ");");
+                                       }
+                               } else if (this.allowedBlockElements.test("div")) {
+                                       if (/^div$/i.test(parentElement.nodeName) && !HTMLArea._hasClass(parentElement, this.useClass[buttonId])) {
+                                               HTMLArea._addClass(parentElement, this.useClass[buttonId]);
+                                       } else if (!/^div$/i.test(parentElement.nodeName) && /^div$/i.test(parentElement.parentNode.nodeName) && !HTMLArea._hasClass(parentElement.parentNode, this.useClass[buttonId])) {
+                                               HTMLArea._addClass(parentElement.parentNode, this.useClass[buttonId]);
+                                       } else {
+                                               var bookmark = this.editor.getBookmark(range);
+                                               var newBlock = this.wrapSelectionInBlockElement("div", this.useClass[buttonId]);
+                                               var range = this.editor.moveToBookmark(bookmark);
+                                               this.editor.selectRange(range);
+                                       }
+                               } else {
+                                       this.addClassOnBlockElements(buttonId);
+                               }
+                               break;
+                       case "Outdent" :
+                               if (/^(ol|ul)$/i.test(parentElement.nodeName) && !HTMLArea._hasClass(parentElement, this.useClass.Indent)) {
+                                       try {
+                                               this.editor._doc.execCommand(buttonId, false, null);
+                                       } catch(e) {
+                                               this.appendToLog("onButtonPress", e + "\n\nby execCommand(" + buttonId + ");");
+                                       }
+                               } else if (tableCell) {
+                                       var previousCell = tableCell.previousSibling ? tableCell.previousSibling : (tableCell.parentNode.previousSibling ? tableCell.parentNode.previousSibling.lastChild : null);
+                                       if (!previousCell) {
+                                               previousCell = tableCell.parentNode.parentNode.lastChild.lastChild;
+                                       }
+                                       if (previousCell) {
+                                               this.editor.selectNodeContents(previousCell, true);
+                                       }
+                               } else  if (this.useBlockquote) {
+                                       try {
+                                               this.editor._doc.execCommand(buttonId, false, null);
+                                       } catch(e) {
+                                               this.appendToLog("onButtonPress", e + "\n\nby execCommand(" + buttonId + ");");
+                                       }
+                               } else if (this.allowedBlockElements.test("div")) {
+                                       for (var i = blockAncestors.length; --i >= 0;) {
+                                               if (HTMLArea._hasClass(blockAncestors[i], this.useClass.Indent)) {
+                                                       var bookmark = this.editor.getBookmark(range);
+                                                       var newBlock = this.wrapSelectionInBlockElement("div", false, blockAncestors[i]);
+                                                               // If not directly under the div, we need to backtrack
+                                                       if (newBlock.parentNode !== blockAncestors[i]) {
+                                                               var parent = newBlock.parentNode;
+                                                               this.removeElement(newBlock);
+                                                               while (parent.parentNode !== blockAncestors[i]) {
+                                                                       parent = parent.parentNode;
+                                                               }
+                                                               blockAncestors[i].insertBefore(newBlock, parent);
+                                                               newBlock.appendChild(parent);
+                                                       }
+                                                       newBlock.className = blockAncestors[i].className;
+                                                       HTMLArea._removeClass(newBlock, this.useClass.Indent);
+                                                       if (!newBlock.previousSibling) {
+                                                               while (newBlock.hasChildNodes()) {
+                                                                       if (newBlock.firstChild.nodeType == 1) {
+                                                                               newBlock.firstChild.className = newBlock.className;
+                                                                       }
+                                                                       blockAncestors[i].parentNode.insertBefore(newBlock.firstChild, blockAncestors[i]);
+                                                               }
+                                                       } else if (!newBlock.nextSibling) {
+                                                               if (blockAncestors[i].nextSibling) {
+                                                                       while (newBlock.hasChildNodes()) {
+                                                                               if (newBlock.firstChild.nodeType == 1) {
+                                                                                       newBlock.lastChild.className = newBlock.className;
+                                                                               }
+                                                                               blockAncestors[i].parentNode.insertBefore(newBlock.lastChild, blockAncestors[i].nextSibling);
+                                                                       }
+                                                               } else {
+                                                                       while (newBlock.hasChildNodes()) {
+                                                                               if (newBlock.firstChild.nodeType == 1) {
+                                                                                       newBlock.firstChild.className = newBlock.className;
+                                                                               }
+                                                                               blockAncestors[i].parentNode.appendChild(newBlock.firstChild);
+                                                                       }
+                                                               }
+                                                       } else {
+                                                               var clone = blockAncestors[i].cloneNode(false);
+                                                               if (blockAncestors[i].nextSibling) {
+                                                                       blockAncestors[i].parentNode.insertBefore(clone, blockAncestors[i].nextSibling);
+                                                               } else {
+                                                                       blockAncestors[i].parentNode.appendChild(clone);
+                                                               }
+                                                               while (newBlock.nextSibling) {
+                                                                       clone.appendChild(newBlock.nextSibling);
+                                                               }
+                                                               while (newBlock.hasChildNodes()) {
+                                                                       if (newBlock.firstChild.nodeType == 1) {
+                                                                               newBlock.firstChild.className = newBlock.className;
+                                                                       }
+                                                                       blockAncestors[i].parentNode.insertBefore(newBlock.firstChild, clone);
+                                                               }
+                                                       }
+                                                       blockAncestors[i].removeChild(newBlock);
+                                                       if (!blockAncestors[i].hasChildNodes()) {
+                                                               blockAncestors[i].parentNode.removeChild(blockAncestors[i]);
+                                                       }
+                                                       var range = this.editor.moveToBookmark(bookmark);
+                                                       this.editor.selectRange(range);
+                                                       break;
+                                               }
+                                       }
+                               } else {
+                                       this.addClassOnBlockElements(buttonId);
+                               }
+                               break;
+                       case "InsertParagraphBefore" :
+                       case "InsertParagraphAfter"  :
+                               this.insertParagraph(buttonId === "InsertParagraphAfter");
+                               break;
+                       case "Blockquote" :
+                               var commandState = false;
+                               for (var i = blockAncestors.length; --i >= 0;) {
+                                       if (/^blockquote$/i.test(blockAncestors[i].nodeName)) {
+                                               commandState = true;
+                                               this.removeElement(blockAncestors[i]);
+                                               break;
+                                       }
+                               }
+                               if (!commandState) {
+                                       var bookmark = this.editor.getBookmark(range);
+                                       var newBlock = this.wrapSelectionInBlockElement("blockquote", null);
+                                       var range = this.editor.moveToBookmark(bookmark);
+                                       this.editor.selectRange(range);
+                               }
+                               break;
+                       case "address" :
+                       case "div"     :
+                               var bookmark = this.editor.getBookmark(range);
+                               var newBlock = this.wrapSelectionInBlockElement(buttonId, null);
+                               var range = this.editor.moveToBookmark(bookmark);
+                               this.editor.selectRange(range);
+                               break;
+                       case "JustifyLeft"   :
+                       case "JustifyCenter" :
+                       case "JustifyRight"  :
+                       case "JustifyFull"   :
+                               if (this.useAlignAttribute) {
+                                       try {
+                                               this.editor._doc.execCommand(buttonId, false, null);
+                                       } catch(e) {
+                                               this.appendToLog("onButtonPress", e + "\n\nby execCommand(" + buttonId + ");");
+                                       }
+                               } else {
+                                       this.addClassOnBlockElements(buttonId);
+                               }
+                               break;
+                       case "none" :
+                               if (this.allowedBlockElements.test(parentElement.nodeName)) {
+                                       this.removeElement(parentElement);
+                               }
+                               break;
+                       default :
+                               break;
+               }
+               return false;
+       },
+       
+       /*
+       * Get the block ancestors of an element within a given block
+       */
+       getBlockAncestors : function(element, withinBlock) {
+               var ancestors = new Array();
+               var ancestor = element;
+               while (ancestor && (ancestor.nodeType === 1) && !/^(body)$/i.test(ancestor.nodeName) && ancestor != withinBlock) {
+                       if (HTMLArea.isBlockElement(ancestor)) {
+                               ancestors.unshift(ancestor);
+                       }
+                       ancestor = ancestor.parentNode;
+               }
+               ancestors.unshift(ancestor);
+               return ancestors;
+       },
+       
+       /*
+        * This function wraps the block elements intersecting the current selection in a block element of the given type
+        */
+       wrapSelectionInBlockElement : function(blockName, useClass, withinBlock) {
+               var endBlocks = this.editor.getEndBlocks(this.editor._getSelection());
+               var startAncestors = this.getBlockAncestors(endBlocks.start, withinBlock);
+               var endAncestors = this.getBlockAncestors(endBlocks.end, withinBlock);
+               var i = 0;
+               while (i < startAncestors.length && i < endAncestors.length && startAncestors[i] === endAncestors[i]) {
+                       ++i;
+               }
+               
+               if ((endBlocks.start === endBlocks.end && /^(body)$/i.test(endBlocks.start.nodeName)) || !startAncestors[i] || !endAncestors[i]) {
+                       --i;
+               }
+               var blockElement = this.editor._doc.createElement(blockName);
+               if (useClass) {
+                       HTMLArea._addClass(blockElement, useClass);
+               }
+               var contextElement = endAncestors[0];
+               if (i) {
+                       contextElement = endAncestors[i-1];
+               }
+               var nextElement = endAncestors[i].nextSibling;
+               var block = startAncestors[i], sibling;
+               if (!/^(body|td|th)$/i.test(block.nodeName) && block != withinBlock) {
+                       while (block && block != nextElement) {
+                               sibling = block.nextSibling;
+                               blockElement.appendChild(block);
+                               block = sibling;
+                       }
+                       if (nextElement) {
+                               blockElement = nextElement.parentNode.insertBefore(blockElement, nextElement);
+                       } else {
+                               blockElement = contextElement.appendChild(blockElement);
+                       }
+               } else {
+                       contextElement = block;
+                       block = block.firstChild;
+                       while (block) {
+                               sibling = block.nextSibling;
+                               blockElement.appendChild(block);
+                               block = sibling;
+                       }
+                       blockElement = contextElement.appendChild(blockElement);
+               }
+                       // Things go wrong in some browsers when the node is empty
+               if (HTMLArea.is_safari && !blockElement.hasChildNodes()) {
+                       blockElement = blockElement.appendChild(this.editor._doc.createElement("br"));
+               }
+               return blockElement;
+       },
+       
+       /*
+        * This function adds a class attribute on blocks sibling of the block containing the start container of the selection
+        */
+       addClassOnBlockElements : function(buttonId) {
+               var selection = this.editor._getSelection();
+               var endBlocks = this.editor.getEndBlocks(selection);
+               var startAncestors = this.getBlockAncestors(endBlocks.start);
+               var endAncestors = this.getBlockAncestors(endBlocks.end);
+               var index = 0;
+               while (index < startAncestors.length && index < endAncestors.length && startAncestors[index] === endAncestors[index]) {
+                       ++index;
+               }
+               if (endBlocks.start === endBlocks.end) {
+                       --index;
+               }
+               for (var block = startAncestors[index]; block; block = block.nextSibling) {
+                       if (HTMLArea.isBlockElement(block)) {
+                               switch (buttonId) {
+                                       case "Indent" :
+                                               if (!HTMLArea._hasClass(block, this.useClass[buttonId])) {
+                                                       HTMLArea._addClass(block, this.useClass[buttonId]);
+                                               }
+                                               break;
+                                       case "Outdent" :
+                                               if (HTMLArea._hasClass(block, this.useClass["Indent"])) {
+                                                       HTMLArea._removeClass(block, this.useClass["Indent"]);
+                                               }
+                                               break;
+                                       case "JustifyLeft"   :
+                                       case "JustifyCenter" :
+                                       case "JustifyRight"  :
+                                       case "JustifyFull"   :
+                                               this.toggleAlignmentClass(block, buttonId);
+                                               break;
+                                       default :
+                                               break;
+                               }
+                       }
+                       if (block == endAncestors[index]) {
+                               break;
+                       }
+               }
+       },
+       
+       /*
+        * This function toggles the alignment class on the given block
+        */
+       toggleAlignmentClass : function(block, buttonId) {
+               for (var alignmentButtonId in this.useClass) {
+                       if (this.useClass.hasOwnProperty(alignmentButtonId) && alignmentButtonId !== "Indent") {
+                               if (HTMLArea._hasClass(block, this.useClass[alignmentButtonId])) {
+                                       HTMLArea._removeClass(block, this.useClass[alignmentButtonId]);
+                               } else if (alignmentButtonId === buttonId) {
+                                       HTMLArea._addClass(block, this.useClass[alignmentButtonId]);
+                               }
+                       }
+               }
+               if (/^div$/i.test(block.nodeName) && !this.hasAllowedAttributes(block)) {
+                       this.removeElement(block);
+               }
+       },
+       
+       /*
+        * This function verifies if the element has any of the allowed attributes
+        */
+       hasAllowedAttributes : function(element) {
+               for (var i = 0; i < this.allowedAttributes.length; ++i) {
+                       if (element.getAttribute(this.allowedAttributes[i])) {
+                               return true;
+                       }
+               }
+               return false;
+       },
+       
+       /*
+        * This function removes the given element but keeps its contents
+        */
+       removeElement : function(element) {
+               var selection = this.editor._getSelection();
+               var range = this.editor._createRange(selection);
+               var lastChild;
+               var bookmark = this.editor.getBookmark(range);
+               var parent = element.parentNode;
+               while (element.firstChild) {
+                       lastChild = parent.insertBefore(element.firstChild, element);
+               }
+               parent.removeChild(element);
+               var range = this.editor.moveToBookmark(bookmark);
+               this.editor.selectRange(range);
+       },
+       
+       /*
+        * Make XHTML-compliant nested list
+        */
+       makeNestedList : function(el) {
+               var previous;
+               for (var i = el.firstChild; i; i = i.nextSibling) {
+                       if (/^li$/i.test(i.nodeName)) {
+                               if (HTMLArea.is_safari) {
+                                       if (i.hasChildNodes() && /^span$/i.test(i.firstChild.nodeName)) {
+                                               this.removeElement(i.firstChild);
+                                       }
+                               }
+                               for (var j = i.firstChild; j; j = j.nextSibling) {
+                                       if (/^(ol|ul)$/i.test(j.nodeName)) {
+                                               this.makeNestedList(j);
+                                       }
+                               }
+                       } else if (/^(ol|ul)$/i.test(i.nodeName)) {
+                               previous = i.previousSibling;
+                               this.indentedList = i.cloneNode(true);
+                               if (!previous) {
+                                       previous = el.insertBefore(this.editor._doc.createElement("li"), i);
+                                       this.indentedList = previous.appendChild(this.indentedList);
+                               } else {
+                                       this.indentedList = previous.appendChild(this.indentedList);
+                               }
+                               HTMLArea.removeFromParent(i);
+                               this.makeNestedList(el);
+                               break;
+                       }
+               }
+       },
+       
+       /*
+        * Insert a paragraph
+        */
+       insertParagraph : function(after) {
+               var endBlocks = this.editor.getEndBlocks(this.editor._getSelection());
+               var ancestors = after ? this.getBlockAncestors(endBlocks.end) : this.getBlockAncestors(endBlocks.start);
+               var endElement = ancestors[ancestors.length-1];
+               for (var i = ancestors.length; --i >= 0;) {
+                       if (/^(table|div|ul|ol|dl|blockquote|address|pre)$/i.test(ancestors[i].nodeName) && !/^(li)$/i.test(ancestors[i].parentNode.nodeName)) {
+                               endElement = ancestors[i];
+                               break;
+                       }
+               }
+               if (endElement) {
+                       var parent = endElement.parentNode;
+                       var paragraph = this.editor._doc.createElement("p");
+                       paragraph.appendChild(this.editor._doc.createElement("br"));
+                       if (HTMLArea.is_opera) paragraph.innerHTML = "&nbsp";
+                       parent.insertBefore(paragraph, after ? endElement.nextSibling : endElement);
+                       if (HTMLArea.is_opera) {
+                               this.editor.selectNodeContents(paragraph);
+                       } else {
+                               this.editor.selectNodeContents(paragraph, true);
+                       }
+               }
+       },
+       
+       /*
+        * This function gets called when the toolbar is updated
+        */
+       onUpdateToolbar : function () {
+               if (this.editor._editMode === "textmode") {
+                       return false;
+               }
+               var parentElement = this.editor._statusBarTree.selected ? this.editor._statusBarTree.selected : this.editor.getParentElement();
+               while (!HTMLArea.isBlockElement(parentElement) || /^li$/i.test(parentElement.nodeName)) {
+                       parentElement = parentElement.parentNode;
+               }
+               var blockAncestors = this.getBlockAncestors(parentElement);
+               
+               var selection = this.editor._getSelection();
+               var endBlocks = this.editor.getEndBlocks(selection);
+               var startAncestors = this.getBlockAncestors(endBlocks.start);
+               var endAncestors = this.getBlockAncestors(endBlocks.end);
+               var index = 0;
+               while (index < startAncestors.length && index < endAncestors.length && startAncestors[index] === endAncestors[index]) {
+                       ++index;
+               }
+               if (endBlocks.start === endBlocks.end || !startAncestors[index]) {
+                       --index;
+               }
+               var dropDownConfiguration = this.getDropDownConfiguration("FormatBlock");
+               if ((typeof(dropDownConfiguration) !== "undefined") && this.isButtonInToolbar(dropDownConfiguration.id)) {
+                       this.updateDropDown(dropDownConfiguration, blockAncestors[blockAncestors.length-1], startAncestors[index]);
+               }
+               
+               var buttonList = this.buttonList;
+               var buttonId, n = buttonList.length, commandState;
+               for (var i = 0; i < n; ++i) {
+                       buttonId = buttonList[i][0];
+                       commandState = false;
+                       if (this.isButtonInToolbar(buttonId)) {
+                               switch (buttonId) {
+                                       case "Outdent" :
+                                               if (this.useBlockquote) {
+                                                       for (var j = blockAncestors.length; --j >= 0;) {
+                                                               if (/^blockquote$/i.test(blockAncestors[j].nodeName)) {
+                                                                       commandState = true;
+                                                                       break;
+                                                               }
+                                                       }
+                                               } else if (/^(ol|ul)$/i.test(parentElement.nodeName)) {
+                                                       commandState = true;
+                                               } else {
+                                                       for (var j = blockAncestors.length; --j >= 0;) {
+                                                               if (HTMLArea._hasClass(blockAncestors[j], this.useClass.Indent)) {
+                                                                       commandState = true;
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                               this.editor._toolbarObjects[buttonId].state("enabled", commandState);
+                                               break;
+                                       case "Indent" :
+                                               break;
+                                       case "InsertParagraphBefore" :
+                                       case "InsertParagraphAfter"  :
+                                               this.editor._toolbarObjects[buttonId].state("enabled", !(/^(body)$/i.test(startAncestors[index].nodeName)));
+                                               break;
+                                       case "Blockquote" :
+                                               for (var j = blockAncestors.length; --j >= 0;) {
+                                                       if (/^blockquote$/i.test(blockAncestors[j].nodeName)) {
+                                                               commandState = true;
+                                                               break;
+                                                       }
+                                               }
+                                               this.editor._toolbarObjects[buttonId].state("active", commandState);
+                                               break;
+                                       case "JustifyLeft"   :
+                                       case "JustifyCenter" :
+                                       case "JustifyRight"  :
+                                       case "JustifyFull"   :
+                                               if (this.useAlignAttribute) {
+                                                       try {
+                                                               commandState = this.editor._doc.queryCommandState(buttonId);
+                                                       } catch(e) {
+                                                               commandState = false;
+                                                       }
+                                               } else {
+                                                       if (/^(body)$/i.test(startAncestors[index].nodeName)) {
+                                                               this.editor._toolbarObjects[buttonId].state("enabled", false);
+                                                       } else {
+                                                               this.editor._toolbarObjects[buttonId].state("enabled", true);
+                                                               commandState = true;
+                                                               for (var block = startAncestors[index]; block; block = block.nextSibling) {
+                                                                       commandState = commandState && HTMLArea._hasClass(block, this.useClass[buttonId]);
+                                                                       if (block == endAncestors[index]) {
+                                                                               break;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                               this.editor._toolbarObjects[buttonId].state("active", commandState);
+                                               break;
+                                       default :
+                                               break;
+                               }
+                       }
+               }
+       },
+       
+       /*
+       * This function updates the drop-down list of block elemenents
+       */
+       updateDropDown : function(dropDownConfiguration, deepestBlockAncestor, startAncestor) {
+               
+               var select = document.getElementById(this.editor._toolbarObjects[dropDownConfiguration.id].elementId);
+               var options = select.options;
+               for (var i = options.length; --i >= 0;) {
+                       options[i].selected = false;
+               }
+               select.selectedIndex = 0;
+               options[0].selected = true;
+               options[0].style.display = "list-item";
+               options[0].text = this.localize("No block");
+               
+               if (deepestBlockAncestor) {
+                       if (!/^(body|div|address|blockquote)$/i.test(deepestBlockAncestor.nodeName) && deepestBlockAncestor.parentNode && !/^(li|td|th)$/i.test(deepestBlockAncestor.parentNode.nodeName)) {
+                               options[0].style.display = "none";
+                       }
+                       var nodeName = deepestBlockAncestor.nodeName.toLowerCase();
+                       for (i = options.length; --i >= 0;) {
+                               if (nodeName === options[i].value.toLowerCase()) {
+                                       options[i].selected = true;
+                                       select.selectedIndex = i;
+                                       options[0].text = this.localize("Remove block");
+                                       break;
+                               }
+                       }
+               }
+       },
+       
+       /*
+       * This function handles the hotkey events registered on elements of the dropdown list
+       */      
+       onHotKey : function(editor, key) {
+               var blockElement;
+               var hotKeyConfiguration = this.getHotKeyConfiguration(key);
+               if (hotKeyConfiguration) {
+                       var blockElement = hotKeyConfiguration.element;
+               }
+               if (blockElement && this.allowedBlockElements.test(blockElement)) {
+                       this.applyBlockElement(this.translateHotKey(key), blockElement);
+                       return false;
+               }
+               return true;
+       }
+});
+
diff --git a/typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/locallang.xml b/typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/locallang.xml
new file mode 100644 (file)
index 0000000..e01a800
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- TYPO3 SVN ID: $Id$ -->
+<T3locallang>
+       <meta type="array">
+               <description>Labels for BlockElements plugin of htmlArea RTE</description>
+               <type>module</type>
+       </meta>
+       <data type="array">
+               <languageKey index="default" type="array">
+                       <label index="Indent-Tooltip">Increase indent</label>
+                       <label index="Outdent-Tooltip">Reduce indent</label>
+                       <label index="Blockquote-Tooltip">Large quotation</label>
+                       <label index="FormatBlock-Tooltip">Type of block</label>
+                       <label index="InsertParagraphBefore-Tooltip">Insert a paragraph before the current block</label>
+                       <label index="InsertParagraphAfter-Tooltip">Insert a paragraph after the current block</label>
+                       <label index="JustifyLeft-Tooltip">Justify left</label>
+                       <label index="JustifyCenter-Tooltip">Center</label>
+                       <label index="JustifyRight-Tooltip">Justify right</label>
+                       <label index="JustifyFull-Tooltip">Justify left and right</label>
+                       <label index="Left-Tooltip">Left</label>
+                       <label index="No block">No block format</label>
+                       <label index="Remove block">Remove block format</label>
+                       <label index="Technische Universitat Ilmenau">Technische Universit├Ąt Ilmenau</label>
+               </languageKey>
+       </data>
+       <orig_hash type="array">
+               <languageKey index="default" type="array">
+               </languageKey>
+       </orig_hash>
+       <orig_text type="array">
+               <languageKey index="default" type="array">
+               </languageKey>
+       </orig_text>
+</T3locallang>
\ No newline at end of file
diff --git a/typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/block-style.js b/typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/block-style.js
new file mode 100644 (file)
index 0000000..660eda7
--- /dev/null
@@ -0,0 +1,497 @@
+/***************************************************************
+*  Copyright notice
+*
+* (c) 2007 Stanislas Rolland <stanislas.rolland(arobas)fructifor.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 script is a modified version of a script published under the htmlArea License.
+*  A copy of the htmlArea License may be found in the textfile HTMLAREA_LICENSE.txt.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/*
+ * Block Style Plugin for TYPO3 htmlArea RTE
+ *
+ * TYPO3 CVS ID: $Id$
+ */
+BlockStyle = HTMLArea.Plugin.extend({
+               
+       constructor : function(editor, pluginName) {
+               this.base(editor, pluginName);
+       },
+       
+               /*
+        * This function gets called by the class constructor
+        */
+       configurePlugin : function(editor) {
+               this.cssLoaded = false;
+               this.cssTimeout = null;
+               this.cssParseCount = 0;
+               this.cssArray = new Object();
+               
+               this.classesUrl = this.editorConfiguration.classesUrl;
+               this.pageTSconfiguration = this.editorConfiguration.buttons.blockstyle;
+               this.tags = this.pageTSconfiguration.tags;
+               if (!this.tags) {
+                       this.tags = new Object();
+               }
+               if (typeof(this.editorConfiguration.classesTag) !== "undefined") {
+                       if (this.editorConfiguration.classesTag.p) {
+                               if (!this.tags.p) {
+                                       this.tags.p = new Object();
+                               }
+                               if (!this.tags.p.allowedClasses) {
+                                       this.tags.p.allowedClasses = this.editorConfiguration.classesTag.p;
+                               }
+                       }
+                       if (this.editorConfiguration.classesTag.td) {
+                               if (!this.tags.td) {
+                                       this.tags.td = new Object();
+                               }
+                               if (!this.tags.td.allowedClasses) {
+                                       this.tags.td.allowedClasses = this.editorConfiguration.classesTag.td;
+                               }
+                       }
+                       if (this.editorConfiguration.classesTag.table) {
+                               if (!this.tags.table) {
+                                       this.tags.table = new Object();
+                               }
+                               if (!this.tags.table.allowedClasses) {
+                                       this.tags.table.allowedClasses = this.editorConfiguration.classesTag.table;
+                               }
+                       }
+               }
+               this.showTagFreeClasses = this.pageTSconfiguration.showTagFreeClasses || this.editorConfiguration.showTagFreeClasses;
+               this.prefixLabelWithClassName = this.pageTSconfiguration.prefixLabelWithClassName;
+               this.postfixLabelWithClassName = this.pageTSconfiguration.postfixLabelWithClassName;
+               
+                       /* Registering plugin "About" information */
+               var pluginInformation = {
+                       version         : "1.0",
+                       developer       : "Stanislas Rolland",
+                       developerUrl    : "http://www.fructifor.ca/",
+                       copyrightOwner  : "Stanislas Rolland",
+                       sponsor         : "Fructifor Inc. " + this.localize("Technische Universitat Ilmenau"),
+                       sponsorUrl      : "http://www.tu-ilmenau.de/",
+                       license         : "GPL"
+               };
+               this.registerPluginInformation(pluginInformation);
+               
+                       /* Registering the dropdown list */
+               var dropDownId = "BlockStyle";
+               var dropDownConfiguration = {
+                       id              : dropDownId,
+                       tooltip         : this.localize(dropDownId + "-Tooltip"),
+                       textMode        : false,
+                       options         : {"":""},
+                       action          : "onChange",
+                       refresh         : "generate",
+                       context         : null
+               };
+               this.registerDropDown(dropDownConfiguration);
+               
+               return true;
+       },
+       
+       /*
+        * This function gets called when some block style was selected in the drop-down list
+        */
+       onChange : function(editor, dropDownId) {
+               var select = document.getElementById(this.editor._toolbarObjects[dropDownId].elementId);
+               var className = select.value;
+               
+               this.editor.focusEditor();
+               var blocks = this.getSelectedBlocks();
+               for (var k = 0; k < blocks.length; ++k) {
+                       var parent = blocks[k];
+                       while (parent && !HTMLArea.isBlockElement(parent) && parent.nodeName.toLowerCase() != "img") {
+                               parent = parent.parentNode;
+                       }
+                       if (!k) {
+                               var tagName = parent.tagName.toLowerCase();
+                       }
+                       if (parent.tagName.toLowerCase() == tagName) {
+                               if (className == "none") {
+                                       var classNames = parent.className.trim().split(" ");
+                                       for (var i = classNames.length; --i >= 0;) {
+                                               if (!HTMLArea.reservedClassNames.test(classNames[i])) {
+                                                       HTMLArea._removeClass(parent, classNames[i]);
+                                                       break;
+                                               }
+                                       }
+                               } else {
+                                       HTMLArea._addClass(parent, className);
+                               }
+                       }
+               }
+       },
+       
+       getSelectedBlocks : function() {
+               var block, range, i = 0, blocks = [];
+               if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
+                       var selection = this.editor._getSelection();
+                       try {
+                               while (range = selection.getRangeAt(i++)) {
+                                       block = this.editor.getParentElement(selection, range);
+                                       blocks.push(block);
+                               }
+                       } catch(e) {
+                               /* finished walking through selection */
+                       }
+               } else {
+                       blocks.push(this.editor.getParentElement());
+               }
+               return blocks;
+       },
+       
+       onGenerate : function() {
+               if (HTMLArea.is_gecko) {
+                       this.generate(this.editor, "BlockStyle");
+               }
+       },
+       
+       /*
+        * This function gets called when the toolbar is being updated
+        */
+       onUpdateToolbar : function() {
+               if (this.editor._editMode === "wysiwyg") {
+                       this.generate(this.editor, "BlockStyle");
+               }
+       },
+       
+       /*
+        * This function gets called when the editor has changed its mode to "wysiwyg"
+        */
+       onMode : function(mode) {
+               if (mode === "wysiwyg") {
+                       this.generate(this.editor, "BlockStyle");
+               }
+       },
+       
+       /*
+        * This function gets called on plugin generation, on toolbar update and  on change mode
+        * Re-initiate the parsing of the style sheets, if not yet completed, and refresh our toolbar components
+        */
+       generate : function(editor, dropDownId) {
+               if (this.cssLoaded) {
+                       this.updateValue(dropDownId);
+               } else {
+                       if (this.cssTimeout) {
+                               if (editor._iframe.contentWindow) {
+                                       editor._iframe.contentWindow.clearTimeout(this.cssTimeout);
+                               } else {
+                                       window.clearTimeout(this.cssTimeout);
+                               }
+                               this.cssTimeout = null;
+                       }
+                       if (this.classesUrl && (typeof(HTMLArea.classesLabels) === "undefined")) {
+                               this.getJavascriptFile(this.classesUrl);
+                       }
+                       this.buildCssArray(editor, dropDownId);
+               }
+       },
+       
+       updateValue : function(dropDownId) {
+               var select = document.getElementById(this.editor._toolbarObjects[dropDownId].elementId);
+               while(select.options.length > 0) {
+                       select.options[select.length-1] = null;
+               }
+               select.options[0] = new Option(this.localize("No style"),"none");
+               select.disabled = true;
+               
+               var classNames = new Array();
+               var tagName = null;
+               var parent = this.editor.getParentElement();
+               while (parent && !HTMLArea.isBlockElement(parent) && parent.nodeName.toLowerCase() != "img") {
+                       parent = parent.parentNode;
+               }
+               
+               if (parent.className && /\S/.test(parent.className)) {
+                       classNames = parent.className.trim().split(" ");
+               }
+               if (parent) {
+                       tagName = parent.nodeName.toLowerCase();
+                       if (parent.className && /\S/.test(parent.className)) {
+                               classNames = parent.className.trim().split(" ");
+                       }
+                       if (HTMLArea.reservedClassNames.test(parent.className)) {
+                               var cleanClassNames = new Array();
+                               var j = -1;
+                               for (var i = 0; i < classNames.length; ++i) {
+                                       if (HTMLArea.reservedClassNames.test(classNames[i])) {
+                                               cleanClassNames[++j] = classNames[i];
+                                       }
+                               }
+                               classNames = cleanClassNames;
+                       }
+               }
+               if (tagName && tagName !== "body"){
+                       this.buildDropDownOptions(select, tagName);
+                       select.selectedIndex = 0;
+                       if (classNames.length) {
+                               for (var i = select.options.length; --i >= 0;) {
+                                       if (classNames[classNames.length-1] == select.options[i].value) {
+                                               select.options[i].selected = true;
+                                               select.selectedIndex = i;
+                                               select.options[0].text = this.localize("Remove style");
+                                               break;
+                                       }
+                               }
+                               if (select.selectedIndex == 0) {
+                                       select.options[select.options.length] = new Option(this.localize("Unknown style"), classNames[classNames.length-1]);
+                                       select.options[select.options.length-1].selected = true;
+                                       select.selectedIndex = select.options.length-1;
+                               }
+                               for (var i = select.options.length; --i >= 0;) {
+                                       if (("," + classNames.join(",") + ",").indexOf("," + select.options[i].value + ",") !== -1) {
+                                               if (select.selectedIndex != i) {
+                                                       select.options[i] = null;
+                                               }
+                                       }
+                               }
+                       }
+                       if (select.options.length > 1) {
+                               select.disabled = false;
+                       } else {
+                               select.disabled = true;
+                       }
+               }
+               select.className = "";
+               if (select.disabled) {
+                       select.className = "buttonDisabled";
+               }
+       },
+       
+       buildDropDownOptions : function(select, tagName) {
+               var cssArray = new Array();
+               while(select.options.length > 0) {
+                       select.options[select.length-1] = null;
+               }
+               select.options[0] = new Option(this.localize("No style"),"none");
+                       // Get classes allowed for all tags
+               if (typeof(this.cssArray.all) !== "undefined") {
+                       if (this.tags && this.tags[tagName]) {
+                               var allowedClasses = this.tags[tagName].allowedClasses;
+                               for (var cssClass in this.cssArray.all) {
+                                       if (allowedClasses.indexOf(cssClass) !== -1) {
+                                               cssArray[cssClass] = this.cssArray.all[cssClass];
+                                       }
+                               }
+                       } else {
+                               for (var cssClass in this.cssArray.all) {
+                                       if (this.cssArray.all.hasOwnProperty(cssClass)) {
+                                               cssArray[cssClass] = this.cssArray.all[cssClass];
+                                       }
+                               }
+                       }
+               }
+                       // Merge classes allowed for tagName and sort the array
+               if (typeof(this.cssArray[tagName]) !== "undefined") {
+                       if (this.tags && this.tags[tagName]) {
+                               var allowedClasses = this.tags[tagName].allowedClasses;
+                               for (var cssClass in this.cssArray[tagName]) {
+                                       if (allowedClasses.indexOf(cssClass) !== -1) {
+                                               cssArray[cssClass] = this.cssArray[tagName][cssClass];
+                                       }
+                               }
+                       } else {
+                               for (var cssClass in this.cssArray[tagName]) {
+                                       if (this.cssArray[tagName].hasOwnProperty(cssClass)) {
+                                               cssArray[cssClass] = this.cssArray[tagName][cssClass];
+                                       }
+                               }
+                       }
+                       var sortedCssArray = new Object();
+                       var cssArrayKeys = new Array();
+                       for (var cssClass in cssArray) {
+                               if (cssArray.hasOwnProperty(cssClass)) {
+                                       cssArrayKeys.push(cssClass);
+                               }
+                       }
+                       function compare(a, b) {
+                               x = cssArray[a];
+                               y = cssArray[b];
+                               return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+                       }
+                       cssArrayKeys = cssArrayKeys.sort(compare);
+                       for (var i = 0; i < cssArrayKeys.length; ++i) {
+                               sortedCssArray[cssArrayKeys[i]] = cssArray[cssArrayKeys[i]];
+                       }
+                       cssArray = sortedCssArray;
+               }
+               for (var cssClass in cssArray) {
+                       if (cssArray.hasOwnProperty(cssClass) && cssArray[cssClass]) {
+                               if (cssClass == "none") {
+                                       select.options[0] = new Option(cssArray[cssClass], cssClass);
+                               } else {
+                                       select.options[select.options.length] = new Option(cssArray[cssClass], cssClass);
+                                       if (!this.editor.config.disablePCexamples && HTMLArea.classesValues && HTMLArea.classesValues[cssClass] && !HTMLArea.classesNoShow[cssClass]) {
+                                               select.options[select.options.length-1].setAttribute("style", HTMLArea.classesValues[cssClass]);
+                                       }
+                               }
+                       }
+               }
+       },
+       
+       buildCssArray : function(editor, dropDownId) {
+               this.cssArray = this.parseStyleSheet();
+               if (!this.cssLoaded && (this.cssParseCount < 17)) {
+                       var buildCssArrayLaterFunctRef = this.makeFunctionReference("buildCssArray");
+                       this.cssTimeout = editor._iframe.contentWindow ? editor._iframe.contentWindow.setTimeout(buildCssArrayLaterFunctRef, 200) : window.setTimeout(buildCssArrayLaterFunctRef, 200);
+                       this.cssParseCount++;
+               } else {
+                       this.cssTimeout = null;
+                       this.cssLoaded = true;
+                       this.cssArray = this.sortCssArray(this.cssArray);
+                       this.updateValue(dropDownId);
+               }
+       },
+       
+       parseStyleSheet : function() {
+               var iframe = this.editor._iframe.contentWindow ? this.editor._iframe.contentWindow.document : this.editor._iframe.contentDocument;
+               var newCssArray = new Object();
+               this.cssLoaded = true;
+               for (var i = 0; i < iframe.styleSheets.length; i++) {
+                       if (HTMLArea.is_gecko) {
+                               try {
+                                       newCssArray = this.parseCssRule(iframe.styleSheets[i].cssRules, newCssArray);
+                               } catch(e) {
+                                       this.cssLoaded = false;
+                               }
+                       } else {
+                               try{
+                                               // @import StyleSheets (IE)
+                                       if (iframe.styleSheets[i].imports) {
+                                               newCssArray = this.parseCssIEImport(iframe.styleSheets[i].imports, newCssArray);
+                                       }
+                                       if (iframe.styleSheets[i].rules) {
+                                               newCssArray = this.parseCssRule(iframe.styleSheets[i].rules, newCssArray);
+                                       }
+                               } catch(e) {
+                                       this.cssLoaded = false;
+                               }
+                       }
+               }
+               return newCssArray;
+       },
+       
+       parseCssIEImport : function(cssIEImport, cssArray) {
+               var newCssArray = new Object();
+               newCssArray = cssArray;
+               for (var i=0; i < cssIEImport.length; i++) {
+                       if (cssIEImport[i].imports) {
+                               newCssArray = this.parseCssIEImport(cssIEImport[i].imports, newCssArray);
+                       }
+                       if (cssIEImport[i].rules) {
+                               newCssArray = this.parseCssRule(cssIEImport[i].rules, newCssArray);
+                       }
+               }
+               return newCssArray;
+       },
+       
+       parseCssRule : function(cssRules, cssArray) {
+               var newCssArray = new Object();
+               newCssArray = cssArray;
+               for (var rule = 0; rule < cssRules.length; rule++) {
+                               // StyleRule
+                       if (cssRules[rule].selectorText) {
+                               newCssArray = this.parseSelectorText(cssRules[rule].selectorText, newCssArray);
+                       } else {
+                                       // ImportRule (Mozilla)
+                               if (cssRules[rule].styleSheet) {
+                                       newCssArray = this.parseCssRule(cssRules[rule].styleSheet.cssRules, newCssArray);
+                               }
+                                       // MediaRule (Mozilla)
+                               if (cssRules[rule].cssRules) {
+                                       newCssArray = this.parseCssRule(cssRules[rule].cssRules, newCssArray);
+                               }
+                       }
+               }
+               return newCssArray;
+       },
+       
+       parseSelectorText : function(selectorText, cssArray) {
+               var cssElements = new Array();
+               var cssElement = new Array();
+               var tagName, className;
+               var newCssArray = new Object();
+               newCssArray = cssArray;
+               if (selectorText.search(/:+/) == -1) {
+                               // split equal Styles (Mozilla-specific) e.q. head, body {border:0px}
+                               // for ie not relevant. returns allways one element
+                       cssElements = selectorText.split(",");
+                       for (var k = 0; k < cssElements.length; k++) {
+                               cssElement = cssElements[k].split(".");
+                               tagName = cssElement[0].toLowerCase().trim();
+                               if (!tagName) {
+                                       tagName = "all";
+                               }
+                               className = cssElement[1];
+                               if (!HTMLArea.reservedClassNames.test(className)) {
+                                       if (((tagName != "all") && (!this.tags || !this.tags[tagName]))
+                                               || ((tagName == "all") && (!this.tags || !this.tags[tagName]) && this.showTagFreeClasses)
+                                               || (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses.indexOf(className) != -1)) {
+                                                       if (!newCssArray[tagName]) {
+                                                               newCssArray[tagName] = new Object();
+                                                       }
+                                                       if (className) {
+                                                               cssName = className;
+                                                               if (HTMLArea.classesLabels && HTMLArea.classesLabels[className]) {
+                                                                       cssName = this.prefixLabelWithClassName ? (className + " - " + HTMLArea.classesLabels[className]) : HTMLArea.classesLabels[className];
+                                                                       cssName = this.postfixLabelWithClassName ? (cssName + " - " + className) : cssName;
+                                                               }
+                                                       } else {
+                                                               className = "none";
+                                                               cssName = this.localize("Element style");
+                                                       }
+                                                       newCssArray[tagName][className] = cssName;
+                                       }
+                               }
+                       }
+               }
+               return newCssArray;
+       },
+       
+       sortCssArray : function(cssArray) {
+               var newCssArray = new Object();
+               for (var tagName in cssArray) {
+                       if (cssArray.hasOwnProperty(tagName)) {
+                               newCssArray[tagName] = new Object();
+                               var tagArrayKeys = new Array();
+                               for (var cssClass in cssArray[tagName]) {
+                                       if (cssArray[tagName].hasOwnProperty(cssClass)) {
+                                               tagArrayKeys.push(cssClass);
+                                       }
+                               }
+                               function compare(a, b) {
+                                       x = cssArray[tagName][a];
+                                       y = cssArray[tagName][b];
+                                       return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+                               }
+                               tagArrayKeys = tagArrayKeys.sort(compare);
+                               for (var i = 0; i < tagArrayKeys.length; ++i) {
+                                       newCssArray[tagName][tagArrayKeys[i]] = cssArray[tagName][tagArrayKeys[i]];
+                               }
+                       }
+               }
+               return newCssArray;
+       }
+});
+
diff --git a/typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/locallang.xml b/typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/locallang.xml
new file mode 100644 (file)
index 0000000..a023713
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<T3locallang>
+       <meta type="array">
+               <description>Labels for Block Style plugin of htmlArea RTE</description>
+               <type>module</type>
+       </meta>
+       <data type="array">
+               <languageKey index="default" type="array">
+                       <label index="No style">No block style</label>
+                       <label index="Remove style">Remove block style</label>
+                       <label index="Unknown style">Unknown block style</label>
+                       <label index="Element style">Block element style</label>
+                       <label index="BlockStyle-Tooltip">Apply style to the containing block</label>
+                       <label index="frame-frame1">Frame with grey background</label>
+                       <label index="frame-frame2">Frame with yellow background</label>
+                       <label index="important">Important</label>
+                       <label index="name-of-person">Name of person</label>
+                       <label index="detail">Detail</label>
+                       <label index="component-items">Component items</label>
+                       <label index="action-items">Action items</label>
+                       <label index="Technische Universitat Ilmenau">Technische Universit├Ąt Ilmenau</label>
+               </languageKey>
+       </data>
+       <orig_hash type="array">
+               <languageKey index="default" type="array">
+               </languageKey>
+       </orig_hash>
+       <orig_text type="array">
+               <languageKey index="default" type="array">
+               </languageKey>
+       </orig_text>
+</T3locallang>
\ No newline at end of file
index 735317a..bdbe14b 100644 (file)
@@ -2,7 +2,7 @@
 *  Copyright notice
 *
 *  Copyright (c) 2003 dynarch.com. Authored by Mihai Bazon. Sponsored by www.americanbible.org.
-*  Copyright (c) 2004, 2005 Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
+*  Copyright (c) 2004-2007 Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -44,7 +44,7 @@ ContextMenu.I18N = ContextMenu_langArray;
 
 ContextMenu._pluginInfo = {
        name          : "ContextMenu",
-       version       : "1.8",
+       version       : "1.9",
        developer     : "Mihai Bazon & Stanislas Rolland",
        developer_url : "http://www.fructifor.ca/",
        c_owner       : "dynarch.com & Stanislas Rolland",
@@ -114,29 +114,22 @@ ContextMenu.execCommandHandler = function(editor,opcode) {
        });
 };
 
-ContextMenu.insertParagraphHandler = function(editor,currentTarget,after) {
+ContextMenu.blockElementsHandler = function(editor, currentTarget, buttonId) {
        return (function() {
-               var el = currentTarget;
-               var par = el.parentNode;
-               var p = editor._doc.createElement("p");
-               p.appendChild(editor._doc.createElement("br"));
-               par.insertBefore(p, after ? el.nextSibling : el);
-               var sel = editor._getSelection();
-               var range = editor._createRange(sel);
-               if(HTMLArea.is_gecko) {
-                       range.selectNodeContents(p);
-                       range.collapse(true);
-                       if(HTMLArea.is_safari) {
-                               sel.empty();
-                               sel.setBaseAndExtent(range.startContainer,range.startOffset,range.endContainer,range.endOffset);
-                       } else {
-                               sel.removeAllRanges();
-                               sel.addRange(range);
-                       }
+               var blockElements = editor.plugins.BlockElements;
+               if (blockElements) {
+                       blockElements = blockElements.instance;
+                       blockElements.onButtonPress(editor, buttonId, currentTarget);
                } else {
-                       range.moveToElementText(p);
-                       range.collapse(true);
-                       range.select();
+                       var el = currentTarget;
+                       var par = el.parentNode;
+                       var p = editor._doc.createElement("p");
+                       var after = (buttonId === "InsertParagraphAfter");
+                       p.appendChild(editor._doc.createElement("br"));
+                       par.insertBefore(p, after ? el.nextSibling : el);
+                       var sel = editor._getSelection();
+                       var range = editor._createRange(sel);
+                       editor.selectNodeContents(p, true);
                }
        });
 };
@@ -163,8 +156,12 @@ ContextMenu.deleteElementHandler = function(editor,tmp,table) {
        });
 };
 
-ContextMenu.prototype.pushOperations = function(opcodes,elmenus,tbo) {
+ContextMenu.prototype.pushOperations = function(opcodes, elmenus, pluginId) {
        var editor = this.editor;
+       var pluginInstance = this.editor.plugins[pluginId];
+       if (pluginInstance) {
+               pluginInstance = pluginInstance.instance;
+       }
        var toolbarObjects = editor._toolbarObjects;
        var i18n = ContextMenu.I18N;
        var btnList = editor.config.btnList;
@@ -177,10 +174,28 @@ ContextMenu.prototype.pushOperations = function(opcodes,elmenus,tbo) {
        if (enabled && elmenus.length) elmenus.push(null);
        for (i = opcodes.length; i > 0;) {
                opcode = opcodes[--i];
-               if(opEnabled[opcode]) elmenus.push([i18n[opcode + "-title"],
-                               (tbo ? ContextMenu.tableOperationsHandler(editor, tbo, opcode) : ContextMenu.execCommandHandler(editor, opcode)),
-                               i18n[opcode + "-tooltip"],
-                               btnList[opcode][1], opcode]);
+               if(opEnabled[opcode]) {
+                       switch (pluginId) {
+                               case "TableOperations" :
+                                       elmenus.push([i18n[opcode + "-title"],
+                                               ContextMenu.tableOperationsHandler(editor, pluginInstance, opcode),
+                                               i18n[opcode + "-tooltip"],
+                                               btnList[opcode][1], opcode]);
+                                       break;
+                               case "BlockElements" :
+                                       elmenus.push([i18n[opcode + "-title"],
+                                               ContextMenu.blockElementsHandler(editor, null, opcode),
+                                               i18n[opcode + "-tooltip"],
+                                               btnList[opcode][1], opcode]);
+                                       break;
+                               default :
+                                       elmenus.push([i18n[opcode + "-title"],
+                                               ContextMenu.execCommandHandler(editor, opcode),
+                                               i18n[opcode + "-tooltip"],
+                                               btnList[opcode][1], opcode]);
+                                       break;
+                       }
+               }
        }
 };
 
@@ -192,8 +207,8 @@ ContextMenu.prototype.getContextMenu = function(target) {
        var btnList = config.btnList;
        var menu = [], opcode;
        var tbo = this.editor.plugins["TableOperations"];
-       if(tbo) tbo = tbo.instance;
-
+       if (tbo) tbo = "TableOperations";
+       
        var selection = editor.hasSelectedText();
        if(selection) {
                if (toolbarObjects['Cut'] && toolbarObjects['Cut'].enabled)  {
@@ -263,7 +278,7 @@ ContextMenu.prototype.getContextMenu = function(target) {
                        opcode = "TO-cell-merge";
                        if(toolbarObjects[opcode]  && toolbarObjects[opcode].enabled)
                                menu.push([i18n[opcode + "-title"],
-                               ContextMenu.tableOperationsHandler(editor,tbo,opcode),
+                               ContextMenu.tableOperationsHandler(editor, this.editor.plugins.TableOperations.instance, opcode),
                                i18n[opcode + "-tooltip"],
                                btnList[opcode][1], opcode]);
                        this.pushOperations(["TO-row-split", "TO-row-delete", "TO-row-insert-under", "TO-row-insert-above", "TO-row-prop"], menu, tbo);
@@ -282,7 +297,7 @@ ContextMenu.prototype.getContextMenu = function(target) {
                        div = target;
                        break;
                    case "body":
-                       this.pushOperations(["JustifyFull", "JustifyRight", "JustifyCenter", "JustifyLeft"], menu, null);
+                       this.pushOperations(["JustifyFull", "JustifyRight", "JustifyCenter", "JustifyLeft"], menu, "BlockElements");
                        break;
                }
        }
@@ -310,9 +325,9 @@ ContextMenu.prototype.getContextMenu = function(target) {
                  [i18n["Remove the"] + " &lt;" + tmp.tagName.toLowerCase() + "&gt; " + i18n["Element"],
                        ContextMenu.deleteElementHandler(editor, tmp, table), i18n["Remove this node from the document"]],
                  [i18n["Insert paragraph before"],
-                       ContextMenu.insertParagraphHandler(editor, tmp, false), i18n["Insert a paragraph before the current node"]],
+                       ContextMenu.blockElementsHandler(editor, tmp, "InsertParagraphBefore"), i18n["Insert a paragraph before the current node"], null, "InsertParagraphBefore"],
                  [i18n["Insert paragraph after"],
-                       ContextMenu.insertParagraphHandler(editor, tmp, true), i18n["Insert a paragraph after the current node"]]
+                       ContextMenu.blockElementsHandler(editor, tmp, "InsertParagraphAfter"), i18n["Insert a paragraph after the current node"], null, "InsertParagraphAfter"]
                );
        }
        return menu;
index ada24ea..24ccb73 100644 (file)
@@ -29,7 +29,7 @@
  *
  * TYPO3 SVN ID: $Id$
  */
-DefaultInline = HTMLArea.plugin.extend({
+DefaultInline = HTMLArea.Plugin.extend({
                
        constructor : function(editor, pluginName) {
                this.base(editor, pluginName);
@@ -79,18 +79,17 @@ DefaultInline = HTMLArea.plugin.extend({
        /*
         * This function gets called when some inline element button was pressed.
         */
-       onButtonPress : function (editor, id, UI, param) {
+       onButtonPress : function (editor, id) {
                        // Could be a button or its hotkey
                var buttonId = this.translateHotKey(id);
                buttonId = buttonId ? buttonId : id;
                editor.focusEditor();
                try {
-                       editor._doc.execCommand(buttonId, UI, param);
+                       editor._doc.execCommand(buttonId, false, null);
                }
                catch(e) {
                        this.appendToLog("onButtonPress", e + "\n\nby execCommand(" + buttonId + ");");
                }
-               editor.updateToolbar();
                return false;
        },
        
index 0e73503..8f2d852 100644 (file)
@@ -2,7 +2,7 @@
 *  Copyright notice
 *
 * (c) 2004 systemconcept.de. Authored by Holger Hees, sponsored by http://www.systemconcept.de.
-* (c) 2004, 2005 Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
+* (c) 2004-2007 Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
  *
  * TYPO3 CVS ID: $Id$
  */
-
-DynamicCSS = function(editor,args) {
-       this.editor = editor; 
-       var cfg = editor.config;
-       var toolbar = cfg.toolbar;
-       var editorNumber = editor._editorNumber;
-
-       var obj = {
-               id                      : "DynamicCSS-class",
-               tooltip                 : DynamicCSS_langArray["DynamicCSSStyleTooltip"],
-               options                 : {"":""},
-               action                  : null,
-               refresh                 : null,
-               context                 : "*",
-               cssArray                : new Object(),
-               parseCount              : 1,
-               loaded                  : false,
-               timeout                 : null,
-               lastTag                 : "",
-               lastClass               : "",
-               showTagFreeClasses      : RTEarea[editorNumber]["showTagFreeClasses"],
-               classesUrl              : RTEarea[editorNumber]["classesUrl"],
-               classesTag              : RTEarea[editorNumber]["classesTag"]
-       };
-       var actionHandlerFunctRef = DynamicCSS.actionHandler(this, obj);
-       obj.action = actionHandlerFunctRef;
-       var refreshHandlerFunctRef = DynamicCSS.refreshHandler(this);
-       obj.refresh = refreshHandlerFunctRef;
-
-       cfg.registerDropdown(obj);
-};
-
-DynamicCSS.actionHandler = function(instance,obj) {
-       return (function(editor) {
-               instance.onSelect(editor, obj);
-       });
-};
-
-DynamicCSS.refreshHandler = function(instance) {
-       return (function(editor) {
-               instance.generate(editor);
-       });
-};
-
-DynamicCSS.I18N = DynamicCSS_langArray;
-
-DynamicCSS.parseStyleSheet = function(editor) {
-       var obj = editor.config.customSelects["DynamicCSS-class"];
-       var iframe = editor._iframe.contentWindow ? editor._iframe.contentWindow.document : editor._iframe.contentDocument;
-       var newCssArray = new Object();
-       obj.loaded = true;
-       for (var i = 0; i < iframe.styleSheets.length; i++) {
-                       // Mozilla
-            if(HTMLArea.is_gecko){
-                       try { newCssArray = DynamicCSS.applyCSSRule(editor,DynamicCSS.I18N,iframe.styleSheets[i].cssRules,newCssArray); }
-                       catch (e) { obj.loaded = false; }
-               } else {
-                       try{
-                                       // @import StyleSheets (IE)
-                               if (iframe.styleSheets[i].imports) newCssArray = DynamicCSS.applyCSSIEImport(editor,DynamicCSS.I18N,iframe.styleSheets[i].imports,newCssArray);
-                               if (iframe.styleSheets[i].rules) newCssArray = DynamicCSS.applyCSSRule(editor,DynamicCSS.I18N,iframe.styleSheets[i].rules,newCssArray);
-                       } catch (e) { obj.loaded = false; }
+DynamicCSS = HTMLArea.Plugin.extend({
+               
+       constructor : function(editor, pluginName) {
+               this.base(editor, pluginName);
+       },
+       
+               /*
+        * This function gets called by the class constructor
+        */
+       configurePlugin : function(editor) {
+               var editorNumber = editor._editorNumber;
+               
+                       /* Registering plugin "About" information */
+               var pluginInformation = {
+                       version         : "1.9",
+                       developer       : "Holger Hees & Stanislas Rolland",
+                       developerUrl    : "http://www.fructifor.ca/",
+                       copyrightOwner  : "Holger Hees & Stanislas Rolland",
+                       sponsor         : "Fructifor Inc.",
+                       sponsorUrl      : "System Concept GmbH & Fructifor Inc.",
+                       license         : "GPL"
+               };
+               this.registerPluginInformation(pluginInformation);
+               
+                       /* Registering the dropdown list */
+               var buttonId = "DynamicCSS-class";
+               var dropDownConfiguration = {
+                       id                      : buttonId,
+                       tooltip                 : this.localize("DynamicCSSStyleTooltip"),
+                       options                 : {"":""},
+                       action                  : "onSelect",
+                       refresh                 : "generate",
+                       context                 : "*",
+                       cssArray                : new Object(),
+                       parseCount              : 1,
+                       loaded                  : false,
+                       timeout                 : null,
+                       lastTag                 : "",
+                       lastClass               : "",
+                       showTagFreeClasses      : RTEarea[editorNumber]["showTagFreeClasses"],
+                       classesUrl              : RTEarea[editorNumber]["classesUrl"],
+                       classesTag              : RTEarea[editorNumber]["classesTag"]
+               };
+               this.registerDropDown(dropDownConfiguration);
+               
+               return true;
+       },
+       
+       onSelect : function(editor, buttonId) {
+               var obj = this.editorConfiguration.customSelects[buttonId];
+               var tbobj = editor._toolbarObjects[buttonId];
+               var index = document.getElementById(tbobj.elementId).selectedIndex;
+               var className = document.getElementById(tbobj.elementId).value;
+               
+               editor.focusEditor();
+               var blocks = this.getSelectedBlocks(editor);
+               for (var k = 0; k < blocks.length; ++k) {
+                       var parent = blocks[k];
+                       while (typeof(parent) != "undefined" && !HTMLArea.isBlockElement(parent) && parent.nodeName.toLowerCase() != "img") parent = parent.parentNode;
+                       if (!k) var tagName = parent.tagName.toLowerCase();
+                       if (parent.tagName.toLowerCase() == tagName) {
+                               var cls = parent.className.trim().split(" ");
+                               for (var i = cls.length; i > 0;) if(!HTMLArea.reservedClassNames.test(cls[--i])) HTMLArea._removeClass(parent,cls[i]);
+                               if(className != 'none'){
+                                       HTMLArea._addClass(parent,className);
+                                       obj.lastClass = className;
+                               }
+                       }
                }
-       }
-       return newCssArray;
-};
-
-DynamicCSS.applyCSSRule=function(editor,i18n,cssRules,cssArray){
-       var cssElements = new Array(),
-               cssElement = new Array(),
-               newCssArray = new Object(),
-               classParts = new Array(),
-               tagName, className, rule, k,
-               obj = editor.config.customSelects["DynamicCSS-class"];
-       newCssArray = cssArray;
+       },
        
-       for (rule = 0; rule < cssRules.length; rule++) {
-                       // StyleRule
-               if (cssRules[rule].selectorText) {
-                       if (cssRules[rule].selectorText.search(/:+/) == -1) {
-                                       // split equal Styles e.g. head, body {border:0px}
-                               cssElements = cssRules[rule].selectorText.split(",");
-                               for (k = 0; k < cssElements.length; k++) {
-                                       cssElement = cssElements[k].split(".");
-                                       tagName = cssElement[0].toLowerCase().trim();
-                                       if (!tagName) tagName = "all";
-                                       className = cssElement[1];
-                                       if (className) {
-                                               classParts = className.trim().split(" ");
-                                               className = classParts[0];
-                                       }
-                                       if (!HTMLArea.reservedClassNames.test(className) && ((tagName == "all" && obj["showTagFreeClasses"] == true) || (tagName != "all" && (!obj["classesTag"] || !obj["classesTag"][tagName])) || (tagName != "all" && obj["classesTag"][tagName].indexOf(className) != -1)) ) {
-                                               if (!newCssArray[tagName]) newCssArray[tagName] = new Object();
-                                               if (className) {
-                                                       cssName = className;
-                                                       if (HTMLArea.classesLabels) cssName = HTMLArea.classesLabels[className] ? HTMLArea.classesLabels[className] : cssName ;
-                                                       if (tagName != 'all') cssName = '<'+cssName+'>';
-                                               } else {
-                                                       className='none';
-                                                       if (tagName=='all') cssName=i18n["Default"];
-                                                               else cssName='<'+i18n["Default"]+'>';
-                                               }
-                                               newCssArray[tagName][className]=cssName;
-                                       }
+       getSelectedBlocks : function(editor) {
+               var block, range, i = 0, blocks = [];
+               if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
+                       var sel = editor._getSelection();
+                       try {
+                               while (range = sel.getRangeAt(i++)) {
+                                       block = editor.getParentElement(sel, range);
+                                       blocks.push(block);
                                }
+                       } catch(e) {
+                               /* finished walking through selection */
                        }
                } else {
-                               // ImportRule (Mozilla)
-                       if (cssRules[rule].styleSheet) {
-                               newCssArray = DynamicCSS.applyCSSRule(editor, i18n, cssRules[rule].styleSheet.cssRules, newCssArray);
-                       }
-                               // MediaRule (Mozilla)
-                       if (cssRules[rule].cssRules) {
-                               newCssArray = DynamicCSS.applyCSSRule(editor, i18n, cssRules[rule].cssRules, newCssArray);
-                       }
-               }
-       }
-       return newCssArray;
-};
-
-DynamicCSS.applyCSSIEImport = function(editor,i18n,cssIEImport,cssArray){
-       var newCssArray = new Object();
-       newCssArray = cssArray;
-       for (var i=0;i<cssIEImport.length;i++){
-               if(cssIEImport[i].imports){
-                       newCssArray = DynamicCSS.applyCSSIEImport(editor,i18n,cssIEImport[i].imports,newCssArray);
+                       blocks.push(editor.getParentElement());
                }
-               if(cssIEImport[i].rules){
-                       newCssArray = DynamicCSS.applyCSSRule(editor,i18n,cssIEImport[i].rules,newCssArray);
-               }
-       }
-       return newCssArray;
-};
-
-DynamicCSS._pluginInfo = {
-       name          : "DynamicCSS",
-       version       : "1.9",
-       developer     : "Holger Hees & Stanislas Rolland",
-       developer_url : "http://www.fructifor.ca/",
-       c_owner       : "Holger Hees & Stanislas Rolland",
-       sponsor       : "System Concept GmbH & Fructifor Inc.",
-       sponsor_url   : "http://www.fructifor.ca/",
-       license       : "GPL"
-};
-
-DynamicCSS.prototype.getSelectedBlocks = function(editor) {
-       var block, range, i = 0, blocks = [];
-       if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
-               var sel = editor._getSelection();
-               try {
-                       while (range = sel.getRangeAt(i++)) {
-                               block = editor.getParentElement(sel, range);
-                               blocks.push(block);
+               return blocks;
+       },
+       
+       onGenerate : function() {
+               var editor = this.editor;
+               var obj = editor.config.customSelects["DynamicCSS-class"];
+               if(HTMLArea.is_gecko) this.generate(editor);
+       },
+       
+       onUpdateToolbar : function() {
+               var editor = this.editor;
+               var obj = editor.config.customSelects["DynamicCSS-class"];
+               if (HTMLArea.is_gecko && editor._editMode != "textmode") {
+                       if(obj.loaded) { 
+                               this.updateValue(editor,obj);
+                       } else {
+                               if(obj.timeout) {
+                                       if(editor._iframe.contentWindow) { editor._iframe.contentWindow.clearTimeout(obj.timeout); } else { window.clearTimeout(obj.timeout); }
+                                       obj.timeout = null;
+                               }
+                               this.generate(editor);
                        }
-               } catch(e) {
-                       /* finished walking through selection */
+               } else if (editor._editMode == "textmode") {
+                       var select = document.getElementById(editor._toolbarObjects[obj.id].elementId);
+                       select.disabled = true;
+                       select.className = "buttonDisabled";
                }
-       } else {
-               blocks.push(editor.getParentElement());
-       }
-       return blocks;
-};
-
-DynamicCSS.prototype.onSelect = function(editor, obj) {
-       var tbobj = editor._t