* (major) Feature: Improved behaviour and configuration options for inline elements...
authorStanislas Rolland <typo3@sjbr.ca>
Sun, 6 Jan 2008 08:40:23 +0000 (08:40 +0000)
committerStanislas Rolland <typo3@sjbr.ca>
Sun, 6 Jan 2008 08:40:23 +0000 (08:40 +0000)
* Added feature 3708 (complete): support for <q>
* Fixed issue 5952 (complete): Usability Issue with classes wrapped with <> in select lists
* Added feature 6034: Improvements of inlineCSS: adding classes to inline elements without additional span
* Fixed issue 6839: sub and sup are added via CSS instead of tags in Safari

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

36 files changed:
ChangeLog
typo3/sysext/rtehtmlarea/ChangeLog
typo3/sysext/rtehtmlarea/doc/manual.sxw
typo3/sysext/rtehtmlarea/ext_localconf.php
typo3/sysext/rtehtmlarea/extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/locallang.xml [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/htmlarea.css [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/bidioverride.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/big.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/bold.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/citation.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/code.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/definition.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/deletedtext.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/emphasis.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/insertedtext.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/italic.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/keyboard.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/monospaced.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/quotation.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/sample.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/small.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/span.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/strikethrough.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/strong.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/subscript.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/superscript.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/underline.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/variable.gif [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/TextStyle/class.tx_rtehtmlarea_textstyle.php [new file with mode: 0644]
typo3/sysext/rtehtmlarea/extensions/TextStyle/locallang.xml [new file with mode: 0644]
typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js [new file with mode: 0644]
typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/locallang.xml [new file with mode: 0644]
typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/locallang.xml [new file with mode: 0644]
typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/text-style.js [new file with mode: 0644]
typo3/sysext/rtehtmlarea/res/proc/pageTSConfig.txt

index e8bce82..68d0f47 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,12 @@
        * Feature/Cleanup: Acronym plugin of htmlArea RTE using new plugin API and enabled in IE7
        * Fixed issue 6154: Plugin Acronym enables class abbr for span
        * Added feature 1927: Activate Acronym Plugin for IE
+       * (major) Feature: Improved behaviour and configuration options for inline elements and text styling
+       * Added feature 3708 (complete): support for <q>
+       * Fixed issue 5952 (complete): Usability Issue with classes wrapped with <> in select lists
+       * Added feature 6034: Improvements of inlineCSS: adding classes to inline elements without additional span
+       * Fixed issue 6839: sub and sup are added via CSS instead of tags in Safari
+       
 
 2008-01-05  Stanislas Rolland  <stanislas.rolland@fructifor.ca>
 
index 9fc9456..7457bc6 100644 (file)
@@ -3,6 +3,11 @@
        * Feature/Cleanup: Acronym plugin of htmlArea RTE using new plugin API and enabled in IE7
        * Fixed issue 6154: Plugin Acronym enables class abbr for span
        * Added feature 1927: Activate Acronym Plugin for IE
+       * (major) Feature: Improved behaviour and configuration options for inline elements and text styling
+       * Added feature 3708 (complete): support for <q>
+       * Fixed issue 5952 (complete): Usability Issue with classes wrapped with <> in select lists
+       * Added feature 6034: Improvements of inlineCSS: adding classes to inline elements without additional span
+       * Fixed issue 6839: sub and sup are added via CSS instead of tags in Safari
 
 2008-01-05  Stanislas Rolland  <stanislas.rolland@fructifor.ca>
 
index 6c3429e..69756b4 100644 (file)
Binary files a/typo3/sysext/rtehtmlarea/doc/manual.sxw and b/typo3/sysext/rtehtmlarea/doc/manual.sxw differ
index 7bb4caf..7ed167c 100644 (file)
@@ -66,10 +66,10 @@ $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['Acronym'] = array();
 $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['Acronym']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/Acronym/class.tx_rtehtmlarea_acronym.php:&tx_rtehtmlarea_acronym';
 $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['Acronym']['addIconsToSkin'] = 0;
 $TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['Acronym']['disableInFE'] = 1;
-//$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['InlineElements'] = array();
-//$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['InlineElements']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php:&tx_rtehtmlarea_inlineelements';
-//$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['TextStyle'] = array();
-//$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['TextStyle']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/TextStyle/class.tx_rtehtmlarea_textstyle.php:&tx_rtehtmlarea_textstyle';
+$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['InlineElements'] = array();
+$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['InlineElements']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php:&tx_rtehtmlarea_inlineelements';
+$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['TextStyle'] = array();
+$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['plugins']['TextStyle']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/TextStyle/class.tx_rtehtmlarea_textstyle.php:&tx_rtehtmlarea_textstyle';
 
 $_EXTCONF = unserialize($_EXTCONF);    // unserializing the configuration so we can use it here:
 
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php b/typo3/sysext/rtehtmlarea/extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php
new file mode 100644 (file)
index 0000000..fecb4db
--- /dev/null
@@ -0,0 +1,220 @@
+<?php
+/***************************************************************
+*  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.
+*
+*  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!
+***************************************************************/
+/**
+ * InlineElements plugin for htmlArea RTE
+ *
+ * @author Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
+ *
+ * TYPO3 CVS ID: $Id: class.tx_rtehtmlarea_pi1.php 2449 2007-08-15 08:12:19Z ingorenner $
+ *
+ */
+
+require_once(t3lib_extMgm::extPath('rtehtmlarea').'class.tx_rtehtmlareaapi.php');
+
+class tx_rtehtmlarea_inlineelements extends tx_rtehtmlareaapi {
+
+       protected $extensionKey = 'rtehtmlarea';                        // The key of the extension that is extending htmlArea RTE
+       protected $pluginName = 'InlineElements';                       // The name of the plugin registered by the extension
+       protected $relativePathToLocallangFile = 'extensions/InlineElements/locallang.xml';     // Path to this main locallang file of the extension relative to the extension dir.
+       protected $relativePathToSkin = 'extensions/InlineElements/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 = 'formattext, bidioverride, big, bold, citation, code, definition, deletedtext, emphasis, insertedtext, italic, keyboard, quotation, sample, small, span, strikethrough, strong, subscript, superscript, underline, variable';
+               
+       protected $convertToolbarForHtmlAreaArray = array (
+               'formattext'            => 'FormatText',
+               'bidioverride'          => 'BiDiOverride',
+               'big'                   => 'Big',
+               'bold'                  => 'Bold',
+               'citation'              => 'Citation',
+               'code'                  => 'Code',
+               'definition'            => 'Definition',
+               'deletedtext'           => 'DeletedText',
+               'emphasis'              => 'Emphasis',
+               'insertedtext'          => 'InsertedText',
+               'italic'                => 'Italic',
+               'keyboard'              => 'Keyboard',
+               'monospaced'            => 'MonoSpaced',
+               'quotation'             => 'Quotation',
+               'sample'                => 'Sample',
+               'small'                 => 'Small',
+               'span'                  => 'Span',
+               'strikethrough'         => 'StrikeThrough',
+               'strong'                => 'Strong',
+               'subscript'             => 'Subscript',
+               'superscript'           => 'Superscript',
+               'underline'             => 'Underline',
+               'variable'              => 'Variable',
+               );
+       
+       private $defaultInlineElements = array(
+               'none'          => 'No markup',
+               'b'             => 'Bold',
+               'bdo'           => 'BiDi override',
+               'big'           => 'Large text',
+               'cite'          => 'Citation',
+               'code'          => 'Code',
+               'del'           => 'Deleted text',
+               'dfn'           => 'Definition',
+               'em'            => 'Emphasis',
+               'i'             => 'Italic',
+               'ins'           => 'Inserted text',
+               'kbd'           => 'Keyboard',
+               //'label'               => 'Label',
+               'q'             => 'Quotation',
+               'samp'          => 'Sample',
+               'small'         => 'Small text',
+               'span'          => 'Style container',
+               'strike'        => 'Strike-through',
+               'strong'        => 'Strong emphasis',
+               'sub'           => 'Subscript',
+               'sup'           => 'Superscript',
+               'tt'            => 'Monospaced text',
+               'u'             => 'Underline',
+               'var'           => 'Variable',
+               );
+       
+       private $defaultInlineElementsOrder = 'none, bidioverride, big, bold, citation, code, definition, deletedtext, emphasis, insertedtext, italic, keyboard,
+                                               monospaced, quotation, sample, small, span, strikethrough, strong, subscript, superscript, underline, variable';
+       
+       private $buttonToInlineElement = array(
+               'none'          => 'none',
+               'bidioverride'  => 'bdo',
+               'big'           => 'big',
+               'bold'          => 'b',
+               'citation'      => 'cite',
+               'code'          => 'code',
+               'definition'    => 'dfn',
+               'deletedtext'   => 'del',
+               'emphasis'      => 'em',
+               'insertedtext'  => 'ins',
+               'italic'        => 'i',
+               'keyboard'      => 'kbd',
+               //'label'               => 'label',
+               'monospaced'    => 'tt',
+               'quotation'     => 'q',
+               'sample'        => 'samp',
+               'small'         => 'small',
+               'span'          => 'span',
+               'strikethrough' => 'strike',
+               'strong'        => 'strong',
+               'subscript'     => 'sub',
+               'superscript'   => 'sup',
+               'underline'     => 'u',
+               'variable'      => 'var',
+               );
+       
+       /**
+        * Return JS configuration of the htmlArea plugins registered by the extension
+        *
+        * @param       integer         Relative id of the RTE editing area in the form
+        *
+        * @return string               JS configuration for registered plugins
+        *
+        * The returned string will be a set of JS instructions defining the configuration that will be provided to the plugin(s)
+        * Each of the instructions should be of the form:
+        *      RTEarea['.$RTEcounter.']["buttons"]["button-id"]["property"] = "value";
+        */
+       public function buildJavascriptConfiguration($RTEcounter) {
+               global $TSFE, $LANG;
+               
+               $registerRTEinJavascriptString = '';
+               if (in_array('formattext', $this->toolbar)) {
+                       if (!is_array( $this->thisConfig['buttons.']) || !is_array( $this->thisConfig['buttons.']['formattext.'])) {
+                               $registerRTEinJavascriptString .= '
+                       RTEarea['.$RTEcounter.']["buttons"]["formattext"] = new Object();';
+                       }
+                       
+                               // Default inline elements
+                       $hideItems = array();
+                       $restrictTo = array('*');
+                       $inlineElementsOrder = $this->defaultInlineElementsOrder;
+                       $prefixLabelWithTag = false;
+                       $postfixLabelWithTag = false;
+                       
+                               // Processing PageTSConfig
+                       if (is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.']['formattext.'])) {
+                                       // Removing elements
+                               if ($this->thisConfig['buttons.']['formattext.']['removeItems']) {
+                                       $hideItems =  t3lib_div::trimExplode(',', $this->htmlAreaRTE->cleanList($this->thisConfig['buttons.']['formattext.']['removeItems']), 1);
+                               }
+                                       // Restriction clause
+                               if ($this->thisConfig['buttons.']['formattext.']['restrictToItems']) {
+                                       $restrictTo =  t3lib_div::trimExplode(',', $this->htmlAreaRTE->cleanList('none,'.$this->thisConfig['buttons.']['formattext.']['restrictTo']), 1);
+                               }
+                                       // Elements order
+                               if ($this->thisConfig['buttons.']['formattext.']['orderItems']) {
+                                       $inlineElementsOrder = 'none,'.$this->thisConfig['buttons.']['formattext.']['orderItems'];
+                               }
+                               $prefixLabelWithTag = ($this->thisConfig['buttons.']['formattext.']['prefixLabelWithTag'])?true:$prefixLabelWithTag;
+                               $postfixLabelWithTag = ($this->thisConfig['buttons.']['formattext.']['postfixLabelWithTag'])?true:$postfixLabelWithTag;
+                       }
+                       
+                       $inlineElementsOrder = array_diff(t3lib_div::trimExplode(',', $this->htmlAreaRTE->cleanList($inlineElementsOrder), 1), $hideItems);
+                       if (!in_array('*', $restrictTo)) {
+                               $inlineElementsOrder = array_intersect($inlineElementsOrder, $restrictTo);
+                       }
+                       
+                               // Localizing the options
+                       $inlineElementsOptions = array();
+                       foreach ($inlineElementsOrder as $item) {
+                               if ($this->htmlAreaRTE->is_FE()) {
+                                       $inlineElementsOptions[$this->buttonToInlineElement[$item]] = $TSFE->csConvObj->conv($TSFE->getLLL($this->defaultInlineElements[$this->buttonToInlineElement[$item]],$this->LOCAL_LANG), $TSFE->labelsCharset, $TSFE->renderCharset);
+                               } else {
+                                       $inlineElementsOptions[$this->buttonToInlineElement[$item]] = $LANG->getLL($this->defaultInlineElements[$this->buttonToInlineElement[$item]]);
+                               }
+                               $inlineElementsOptions[$this->buttonToInlineElement[$item]] = (($prefixLabelWithTag && $item != 'none')?($this->buttonToInlineElement[$item].' - '):'') . $inlineElementsOptions[$this->buttonToInlineElement[$item]] . (($postfixLabelWithTag && $item != 'none')?(' - '.$this->buttonToInlineElement[$item]):'');
+                       }
+                       
+                       $first = array_shift($inlineElementsOptions);
+                               // Sorting the options
+                       if (!is_array($this->thisConfig['buttons.']) || !is_array($this->thisConfig['buttons.']['formattext.']) || !$this->thisConfig['buttons.']['formattext.']['orderItems']) {
+                               asort($inlineElementsOptions);
+                       }
+                               // Generating the javascript options
+                       $JSInlineElements = '{
+                       "'. $first.'" : "none"';
+                       foreach ($inlineElementsOptions as $item => $label) {
+                               $JSInlineElements .= ',
+                       "' . $label . '" : "' . $item . '"';
+                       }
+                       $JSInlineElements .= '};';
+                       
+                       $registerRTEinJavascriptString .= '
+                       RTEarea['.$RTEcounter.'].buttons.formattext.dropDownOptions = '. $JSInlineElements;
+               }
+               return $registerRTEinJavascriptString;
+        }
+
+
+} // end of class
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php']) {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/locallang.xml b/typo3/sysext/rtehtmlarea/extensions/InlineElements/locallang.xml
new file mode 100644 (file)
index 0000000..440e550
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<T3locallang>
+       <meta type="array">
+               <description>Labels for Inline Elements plugin of htmlArea RTE</description>
+               <type>module</type>
+       </meta>
+       <data type="array">
+               <languageKey index="default" type="array">
+                       <label index="No markup">No text format</label>
+                       <label index="Bold">Bold</label>
+                       <label index="BiDi override">BiDi override</label>
+                       <label index="Large text">Large text</label>
+                       <label index="Citation">Citation</label>
+                       <label index="Code">Code</label>
+                       <label index="Definition">Definition</label>
+                       <label index="Deleted text">Deleted text</label>
+                       <label index="Emphasis">Emphasis</label>
+                       <label index="Inserted text">Inserted text</label>
+                       <label index="Italic">Italic</label>
+                       <label index="Keyboard">Keyboard</label>
+                       <label index="Label">Label</label>
+                       <label index="Monospaced text">Monospaced text</label>
+                       <label index="Quotation">Quotation</label>
+                       <label index="Sample">Sample</label>
+                       <label index="Small text">Small text</label>
+                       <label index="Style container">Style container</label>
+                       <label index="Strike-through">Strike-through</label>
+                       <label index="Strong emphasis">Strong emphasis</label>
+                       <label index="Subscript">Subscript</label>
+                       <label index="Superscript">Superscript</label>
+                       <label index="Underline">Underline</label>
+                       <label index="Variable">Variable</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/InlineElements/skin/htmlarea.css b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/htmlarea.css
new file mode 100644 (file)
index 0000000..706dbda
--- /dev/null
@@ -0,0 +1,23 @@
+/* Selectors for the InlineElements plugin of htmlArea RTE */
+.htmlarea .toolbar .BiDiOverride {background-image:url("images/bidioverride.gif");}
+.htmlarea .toolbar .Big {background-image:url("images/big.gif");}
+.htmlarea .toolbar .Bold {background-image:url("images/bold.gif");}
+.htmlarea .toolbar .Citation {background-image:url("images/citation.gif");}
+.htmlarea .toolbar .Code {background-image:url("images/code.gif");}
+.htmlarea .toolbar .Definition {background-image:url("images/definition.gif");}
+.htmlarea .toolbar .DeletedText {background-image:url("images/deletedtext.gif");}
+.htmlarea .toolbar .Emphasis {background-image:url("images/emphasis.gif");}
+.htmlarea .toolbar .InsertedText {background-image:url("images/insertedtext.gif");}
+.htmlarea .toolbar .Italic {background-image:url("images/italic.gif");}
+.htmlarea .toolbar .Keyboard {background-image:url("images/keyboard.gif");}
+.htmlarea .toolbar .MonoSpaced {background-image:url("images/monospaced.gif");}
+.htmlarea .toolbar .Quotation {background-image:url("images/quotation.gif");}
+.htmlarea .toolbar .Sample {background-image:url("images/sample.gif");}
+.htmlarea .toolbar .Small {background-image:url("images/small.gif");}
+.htmlarea .toolbar .Span {background-image:url("images/span.gif");}
+.htmlarea .toolbar .StrikeThrough {background-image:url("images/strikethrough.gif");}
+.htmlarea .toolbar .Strong {background-image:url("images/strong.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");}
+.htmlarea .toolbar .Variable {background-image:url("images/variable.gif");}
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/bidioverride.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/bidioverride.gif
new file mode 100644 (file)
index 0000000..46b5028
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/bidioverride.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/big.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/big.gif
new file mode 100644 (file)
index 0000000..dd33ac2
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/big.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/bold.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/bold.gif
new file mode 100644 (file)
index 0000000..10df931
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/bold.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/citation.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/citation.gif
new file mode 100644 (file)
index 0000000..4b4267c
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/citation.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/code.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/code.gif
new file mode 100644 (file)
index 0000000..05c4c73
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/code.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/definition.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/definition.gif
new file mode 100644 (file)
index 0000000..d026228
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/definition.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/deletedtext.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/deletedtext.gif
new file mode 100644 (file)
index 0000000..9cbe871
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/deletedtext.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/emphasis.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/emphasis.gif
new file mode 100644 (file)
index 0000000..d87caf5
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/emphasis.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/insertedtext.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/insertedtext.gif
new file mode 100644 (file)
index 0000000..6d33f98
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/insertedtext.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/italic.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/italic.gif
new file mode 100644 (file)
index 0000000..b118ec1
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/italic.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/keyboard.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/keyboard.gif
new file mode 100644 (file)
index 0000000..9f56ce5
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/keyboard.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/monospaced.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/monospaced.gif
new file mode 100644 (file)
index 0000000..93b586a
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/monospaced.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/quotation.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/quotation.gif
new file mode 100644 (file)
index 0000000..2ae3f9d
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/quotation.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/sample.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/sample.gif
new file mode 100644 (file)
index 0000000..efefac9
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/sample.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/small.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/small.gif
new file mode 100644 (file)
index 0000000..f222a2a
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/small.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/span.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/span.gif
new file mode 100644 (file)
index 0000000..f09920d
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/span.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/strikethrough.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/strikethrough.gif
new file mode 100644 (file)
index 0000000..e533be7
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/strikethrough.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/strong.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/strong.gif
new file mode 100644 (file)
index 0000000..b78fc9c
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/strong.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/subscript.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/subscript.gif
new file mode 100644 (file)
index 0000000..dbd399c
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/subscript.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/superscript.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/superscript.gif
new file mode 100644 (file)
index 0000000..1a5e4d0
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/superscript.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/underline.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/underline.gif
new file mode 100644 (file)
index 0000000..e65b215
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/underline.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/variable.gif b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/variable.gif
new file mode 100644 (file)
index 0000000..9f955f8
Binary files /dev/null and b/typo3/sysext/rtehtmlarea/extensions/InlineElements/skin/images/variable.gif differ
diff --git a/typo3/sysext/rtehtmlarea/extensions/TextStyle/class.tx_rtehtmlarea_textstyle.php b/typo3/sysext/rtehtmlarea/extensions/TextStyle/class.tx_rtehtmlarea_textstyle.php
new file mode 100644 (file)
index 0000000..bcae77f
--- /dev/null
@@ -0,0 +1,61 @@
+<?php\r
+/***************************************************************\r
+*  Copyright notice\r
+*\r
+*  (c) 2007-2008 Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>\r
+*  All rights reserved\r
+*\r
+*  This script is part of the Typo3 project. The Typo3 project is\r
+*  free software; you can redistribute it and/or modify\r
+*  it under the terms of the GNU General Public License as published by\r
+*  the Free Software Foundation; either version 2 of the License, or\r
+*  (at your option) any later version.\r
+*\r
+*  The GNU General Public License can be found at\r
+*  http://www.gnu.org/copyleft/gpl.html.\r
+*\r
+*  This script is distributed in the hope that it will be useful,\r
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*  GNU General Public License for more details.\r
+*\r
+*  This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/**\r
+ * TextStyle plugin for htmlArea RTE\r
+ *\r
+ * @author Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>\r
+ *\r
+ * TYPO3 SVN ID: $Id$\r
+ *\r
+ */\r
+\r
+require_once(t3lib_extMgm::extPath('rtehtmlarea').'class.tx_rtehtmlareaapi.php');\r
+\r
+class tx_rtehtmlarea_textstyle extends tx_rtehtmlareaapi {\r
+\r
+       protected $extensionKey = 'rtehtmlarea';                        // The key of the extension that is extending htmlArea RTE\r
+       protected $pluginName = 'TextStyle';                            // The name of the plugin registered by the extension\r
+       protected $relativePathToLocallangFile = 'extensions/TextStyle/locallang.xml';  // Path to this main locallang file of the extension relative to the extension dir.\r
+       protected $relativePathToSkin = '';                             // Path to the skin (css) file relative to the extension dir.\r
+       protected $htmlAreaRTE;                                         // Reference to the invoking object\r
+       protected $thisConfig;                                          // Reference to RTE PageTSConfig\r
+       protected $toolbar;                                             // Reference to RTE toolbar array\r
+       protected $LOCAL_LANG;                                          // Frontend language array\r
+       \r
+       protected $pluginButtons = 'textstyle';                         // The comma-seperated list of button names that the extension id adding to the htmlArea RTE tollbar\r
+       protected $pluginLabels = 'textstylelabel';                     // The comma-seperated list of label names that the extension id adding to the htmlArea RTE tollbar\r
+                                                                       // The name-converting array, converting the button names used in the RTE PageTSConfing to the button id's used by the JS scripts\r
+       protected $convertToolbarForHtmlAreaArray = array (\r
+               'textstylelabel'        => 'I[text_style]',\r
+               'textstyle'             => 'TextStyle',\r
+               );\r
+       protected $requiresClassesConfiguration = true;                 // True if the extension requires the PageTSConfig Classes configuration\r
+\r
+} // end of class\r
+\r
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/TextStyle/class.tx_rtehtmlarea_textstyle.php']) {\r
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/TextStyle/class.tx_rtehtmlarea_textstyle.php']);\r
+}\r
+\r
+?>
\ No newline at end of file
diff --git a/typo3/sysext/rtehtmlarea/extensions/TextStyle/locallang.xml b/typo3/sysext/rtehtmlarea/extensions/TextStyle/locallang.xml
new file mode 100644 (file)
index 0000000..7fda2e4
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<T3locallang>
+       <meta type="array">
+               <description>Labels for Text Style plugin of htmlArea RTE</description>
+               <type>module</type>
+       </meta>
+       <data type="array">
+               <languageKey index="default" type="array">
+                       <label index="No style">No text style</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/InlineElements/inline-elements.js b/typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js
new file mode 100644 (file)
index 0000000..8d4965a
--- /dev/null
@@ -0,0 +1,529 @@
+/***************************************************************
+*  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!
+***************************************************************/
+/*
+ * Inline Elements Plugin for TYPO3 htmlArea RTE
+ *
+ * TYPO3 SVN ID: $Id$
+ */
+/*
+ * Creation of the class of InlineElements plugins
+ */
+InlineElements = HTMLArea.Plugin.extend({
+       /*
+        * Let the base class do some initialization work
+        */
+       constructor : function(editor, pluginName) {
+               this.base(editor, pluginName);
+       },
+       
+       /*
+        * This function gets called by the base constructor
+        */
+       configurePlugin : function (editor) {
+               
+               this.allowedAttributes = new Array("id", "title", "lang", "xml:lang", "dir", (HTMLArea.is_gecko?"class":"className"));
+               
+               if (this.editorConfiguration.buttons.textstyle) {
+                       this.tags = this.editorConfiguration.buttons.textstyle.tags;
+               }
+               
+               /*
+                * 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 = "FormatText";
+               var dropDownConfiguration = {
+                       id              : buttonId,
+                       tooltip         : this.localize(buttonId + "-Tooltip"),
+                       options         : (this.editorConfiguration.buttons[buttonId.toLowerCase()]?this.editorConfiguration.buttons[buttonId.toLowerCase()]["dropDownOptions"]:null),
+                       action          : "onChange",
+                       refresh         : null
+               };
+               this.registerDropDown(dropDownConfiguration);
+               
+               /*
+                * Registering the buttons
+                */
+               var n = this.buttonList.length;
+               for (var i = 0; i < n; ++i) {
+                       var button = this.buttonList[i];
+                       buttonId = button[0];
+                       var buttonConfiguration = {
+                               id              : buttonId,
+                               tooltip         : this.localize(buttonId + "-Tooltip"),
+                               action          : "onButtonPress",
+                               context         : button[1],
+                               hide            : false,
+                               selection       : false
+                       };
+                       this.registerButton(buttonConfiguration);
+               }
+       },
+       
+       /*
+        * The list of buttons added by this plugin
+        */
+       buttonList : [
+               ["BiDiOverride", null],
+               ["Big", null],
+               ["Bold", null],
+               ["Citation", null],
+               ["Code", null],
+               ["Definition", null],
+               ["DeletedText", null],
+               ["Emphasis", null],
+               ["InsertedText", null],
+               ["Italic", null],
+               ["Keyboard", null],
+               //["Label", null],
+               ["MonoSpaced", null],
+               ["Quotation", null],
+               ["Sample", null],
+               ["Small", null],
+               ["Span", null],
+               ["StrikeThrough", null],
+               ["Strong", null],
+               ["Subscript", null],
+               ["Superscript", null],
+               ["Underline", null],
+               ["Variable", null]
+       ],
+       
+       /*
+        * Conversion object: button names to corresponding tag names
+        */
+       convertBtn : {
+               BiDiOverride    : "bdo",
+               Big             : "big",
+               Bold            : "b",
+               Citation        : "cite",
+               Code            : "code",
+               Definition      : "dfn",
+               DeletedText     : "del",
+               Emphasis        : "em",
+               InsertedText    : "ins",
+               Italic          : "i",
+               Keyboard        : "kbd",
+               //Label         : "label",
+               MonoSpaced      : "tt",
+               Quotation       : "q",
+               Sample          : "samp",
+               Small           : "small",
+               Span            : "span",
+               StrikeThrough   : "strike",
+               Strong          : "strong",
+               Subscript       : "sub",
+               Superscript     : "sup",
+               Underline       : "u",
+               Variable        : "var"
+        },
+       
+       /*
+        * Regular expression to check if an element is an inline elment
+        */
+       REInlineElements : /^(b|bdo|big|cite|code|del|dfn|em|i|ins|kbd|label|q|samp|small|span|strike|strong|sub|sup|tt|u|var)$/,
+       
+       /*
+        * Function to check if an element is an inline elment
+        */
+       isInlineElement : function (el) {
+               return el && (el.nodeType === 1) && this.REInlineElements.test(el.nodeName.toLowerCase());
+       },
+       
+       /*
+        * This function gets called when some inline element button was pressed.
+        */
+       onButtonPress : function (editor, id) {
+                       // Could be a button or its hotkey
+               var buttonId = this.translateHotKey(id);
+               buttonId = buttonId ? buttonId : id;
+               var obj = editor._toolbarObjects[buttonId];
+               var element = this.convertBtn[buttonId];
+               if (element) {
+                       this.applyInlineElement(editor, element);
+                       return false;
+               } else {
+                       this.appendToLog("onButtonPress", "No element corresponding to button: " + buttonId);
+               }
+       },
+       
+       /*
+        * This function gets called when some inline element was selected in the drop-down list
+        */
+       onChange : function (editor, buttonId) {
+               var tbobj = editor._toolbarObjects[buttonId];
+               var element = document.getElementById(tbobj.elementId).value;
+               this.applyInlineElement(editor, element, false);
+       },
+       
+       /*
+        * This function applies to the selection the markup chosen in the drop-down list or corresponding to the button pressed
+        */
+       applyInlineElement : function (editor, element) {
+               editor.focusEditor();
+               var selection = editor._getSelection();
+               var range = editor._createRange(selection);
+               var parent = editor.getParentElement(selection, range);
+               var ancestors = editor.getAllAncestors();
+               var elementIsAncestor = false;
+               var selectionEmpty = editor._selectionEmpty(selection);
+               if (HTMLArea.is_ie) {
+                       var bookmark = range.getBookmark();
+               }
+                       // Check if the chosen element is among the ancestors
+               for (var i = 0; i < ancestors.length; ++i) {
+                       if ((ancestors[i].nodeType == 1) && (ancestors[i].nodeName.toLowerCase() == element)) {
+                               elementIsAncestor = true;
+                               var elementAncestorIndex = i;
+                               break;
+                       }
+               }
+               if (!selectionEmpty) {
+                               // The selection is not empty.
+                       for (var i = 0; i < ancestors.length; ++i) {
+                               fullNodeSelected = (HTMLArea.is_ie && ((editor._statusBarTree.selected === ancestors[i] && ancestors[i].innerText === range.text) || (!editor._statusBarTree.selected && ancestors[i].innerText === range.text)))
+                                                       || (HTMLArea.is_gecko && ((editor._statusBarTree.selected === ancestors[i] && ancestors[i].textContent === range.toString()) || (!editor._statusBarTree.selected && ancestors[i].textContent === range.toString())));
+                               if (fullNodeSelected) {
+                                       if (!HTMLArea.isBlockElement(ancestors[i])) {
+                                               parent = ancestors[i];
+                                       }
+                                       break;
+                               }
+                       }
+                               // Working around bug in Safari selectNodeContents
+                       if (!fullNodeSelected && HTMLArea.is_safari && this.editor._statusBarTree.selected && this.isInlineElement(this.editor._statusBarTree.selected) && this.editor._statusBarTree.selected.textContent === range.toString()) {
+                               fullNodeSelected = true;
+                               parent = this.editor._statusBarTree.selected;
+                       }
+                       
+                       var fullNodeTextSelected = (HTMLArea.is_gecko && parent.textContent === range.toString())
+                                                       || (HTMLArea.is_ie && parent.innerText === range.text);
+                       if (fullNodeTextSelected && elementIsAncestor) {
+                               fullNodeSelected = true;
+                       }
+                       if (element !== "none" && !(fullNodeSelected && elementIsAncestor)) {
+                                       // Add markup
+                               if (HTMLArea.is_gecko) {
+                                       if (fullNodeSelected && editor._statusBarTree.selected) {
+                                               if (HTMLArea.is_safari) {
+                                                       this.editor.selectNode(parent);
+                                                       range = this.editor._createRange(this.editor._getSelection());
+                                               } else {
+                                                       range.selectNode(parent);
+                                               }
+                                       }
+                                       var newElement = this.editor._doc.createElement(element);
+                                       if (element === "bdo") {
+                                               newElement.setAttribute("dir", "rtl");
+                                       }
+                                               // Sometimes Opera 9.25 raises a bad boundary points error
+                                       if (HTMLArea.is_opera) {
+                                               try {
+                                                       range.surroundContents(newElement);
+                                               } catch(e) {
+                                                       newElement.appendChild(range.extractContents());
+                                                       range.insertNode(newElement);
+                                               }
+                                       } else {
+                                               range.surroundContents(newElement);
+                                       }
+                                               // Sometimes Firefox inserts empty elements just outside the boundaries of the range
+                                       var neighbour = newElement.previousSibling;
+                                       if (neighbour && (neighbour.nodeType != 3) && !/\S/.test(neighbour.textContent)) {
+                                               HTMLArea.removeFromParent(neighbour);
+                                       }
+                                       neighbour = newElement.nextSibling;
+                                       if (neighbour && (neighbour.nodeType != 3) && !/\S/.test(neighbour.textContent)) {
+                                               HTMLArea.removeFromParent(neighbour);
+                                       }
+                                       if (fullNodeSelected && editor._statusBarTree.selected && !HTMLArea.is_safari) {
+                                               this.editor.selectNodeContents(newElement.lastChild, false);
+                                       } else {
+                                               this.editor.selectNodeContents(newElement, false);
+                                       }
+                                       range.detach();
+                               } else {
+                                       var tagopen = "<" + element + ">";
+                                       var tagclose = "</" + element + ">";
+                                       if (fullNodeSelected) {
+                                               if (!editor._statusBarTree.selected) {
+                                                       parent.innerHTML = tagopen + parent.innerHTML + tagclose;
+                                                       if (element === "bdo") {
+                                                               parent.firstChild.setAttribute("dir", "rtl");
+                                                       }
+                                                       editor.selectNodeContents(parent, false);
+                                               } else {
+                                                       var content = parent.outerHTML;
+                                                       var newElement = this.remapMarkup(parent, element);
+                                                       newElement.innerHTML = content;
+                                                       editor.selectNodeContents(newElement, false);
+                                               }
+                                       } else {
+                                               var rangeStart = range.duplicate();
+                                               rangeStart.collapse(true);
+                                               var parentStart = rangeStart.parentElement();
+                                               var rangeEnd = range.duplicate();
+                                               rangeEnd.collapse(true);
+                                               var newRange = editor._createRange();
+                                               
+                                               var parentEnd = rangeEnd.parentElement();
+                                               var upperParentStart = parentStart;
+                                               if (parentStart !== parent) {
+                                                       while (upperParentStart.parentNode !== parent) {
+                                                               upperParentStart = upperParentStart.parentNode;
+                                                       }
+                                               }
+                                               
+                                               var newElement = editor._doc.createElement(element);
+                                               newElement.innerHTML = range.htmlText;
+                                                       // IE eats spaces on the start boundary
+                                               if (range.htmlText.charAt(0) === "\x20") {
+                                                       newElement.innerHTML = "&nbsp;" + newElement.innerHTML;
+                                               }
+                                               var newElementClone = newElement.cloneNode(true);
+                                               range.pasteHTML(newElement.outerHTML);
+                                                       // IE inserts the element as the last child of the start container
+                                               if (parentStart !== parent
+                                                               && parentStart.lastChild
+                                                               && parentStart.lastChild.nodeType === 1
+                                                               && parentStart.lastChild.nodeName.toLowerCase() === element) {
+                                                       parent.insertBefore(newElementClone, upperParentStart.nextSibling);
+                                                       parentStart.removeChild(parentStart.lastChild);
+                                                               // Sometimes an empty previous sibling was created
+                                                       if (newElementClone.previousSibling
+                                                                       && newElementClone.previousSibling.nodeType === 1
+                                                                       && !newElementClone.previousSibling.innerText) {
+                                                               parent.removeChild(newElementClone.previousSibling);
+                                                       }
+                                                               // The bookmark will not work anymore
+                                                       newRange.moveToElementText(newElementClone);
+                                                       newRange.collapse(false);
+                                                       newRange.select();
+                                               } else {
+                                                               // Working around IE boookmark bug
+                                                       if (parentStart != parentEnd) {
+                                                               var newRange = editor._createRange();
+                                                               if (newRange.moveToBookmark(bookmark)) {
+                                                                       newRange.collapse(false);
+                                                                       newRange.select();
+                                                               }
+                                                       } else {
+                                                               range.collapse(false);
+                                                       }
+                                               }
+                                               parent.normalize();
+                                       }
+                               }
+                       } else {
+                                       // A complete node is selected: remove the markup
+                               if (fullNodeSelected) {
+                                       if (elementIsAncestor) {
+                                               parent = ancestors[elementAncestorIndex];
+                                       }
+                                       this.removeMarkup(parent);
+                               }
+                       }
+               } else {
+                               // Remove or remap markup when the selection is collapsed
+                       if (parent && !HTMLArea.isBlockElement(parent)) {
+                               if ((element === "none") || elementIsAncestor) {
+                                       if (elementIsAncestor) {
+                                               parent = ancestors[elementAncestorIndex];
+                                       }
+                                       this.removeMarkup(parent);
+                               } else {
+                                       var bookmark = this.editor.getBookmark(range);
+                                       var newElement = this.remapMarkup(parent, element);
+                                       this.editor.selectRange(this.editor.moveToBookmark(bookmark));
+                               }
+                       }
+               }
+       },
+       
+       /*
+        * This function remaps the given element to the specified tagname
+        */
+       remapMarkup : function(element, tagName) {
+               var attributeValue;
+               var newElement = this.editor.convertNode(element, tagName);
+               if (tagName === "bdo") {
+                       newElement.setAttribute("dir", "ltr");
+               }
+               for (var i = 0; i < this.allowedAttributes.length; ++i) {
+                       if (attributeValue = element.getAttribute(this.allowedAttributes[i])) {
+                               newElement.setAttribute(this.allowedAttributes[i], attributeValue);
+                       }
+               }
+               
+               if (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses) {
+                       if (newElement.className && /\S/.test(newElement.className)) {
+                               var allowedClasses = new RegExp( "^(" + this.tags[tagName].allowedClasses.trim().split(",").join("|") + ")$");
+                               classNames = newElement.className.trim().split(" ");
+                               for (var i = 0; i < classNames.length; ++i) {
+                                       if (!allowedClasses.test(classNames[i])) {
+                                               HTMLArea._removeClass(newElement, classNames[i]);
+                                       }
+                               }
+                       }
+               }
+               return newElement;
+       },
+       
+       /*
+        * This function removes the given markup element
+        */
+       removeMarkup : function(element) {
+               var bookmark = this.editor.getBookmark(this.editor._createRange(this.editor._getSelection()));
+               var parent = element.parentNode;
+               while (element.firstChild) {
+                       parent.insertBefore(element.firstChild, element);
+               }
+               parent.removeChild(element);
+               this.editor.selectRange(this.editor.moveToBookmark(bookmark));
+       },
+       
+       /*
+       * This function gets called when the toolbar is updated
+       */
+       onUpdateToolbar : function () {
+               var editor = this.editor;
+               if (editor._editMode !== "textmode") {
+                       var id, activeButton;
+                       var tagName = false, endPointsInSameBlock = true, fullNodeSelected = false;
+                       var sel = editor._getSelection();
+                       var range = editor._createRange(sel);
+                       var parent = editor.getParentElement(sel);
+                       if (parent && !HTMLArea.isBlockElement(parent)) {
+                               tagName = parent.nodeName.toLowerCase();
+                       }
+                       var selectionEmpty = editor._selectionEmpty(sel);
+                       if (!selectionEmpty) {
+                               var ancestors = editor.getAllAncestors();
+                               for (var i = 0; i < ancestors.length; ++i) {
+                                       fullNodeSelected = (editor._statusBarTree.selected === ancestors[i])
+                                               && ((HTMLArea.is_gecko && ancestors[i].textContent === range.toString()) || (HTMLArea.is_ie && ancestors[i].innerText === range.text));
+                                       if (fullNodeSelected) {
+                                               if (!HTMLArea.isBlockElement(ancestors[i])) {
+                                                       tagName = ancestors[i].nodeName.toLowerCase();
+                                               }
+                                               break;
+                                       }
+                               }
+                                       // Working around bug in Safari selectNodeContents
+                               if (!fullNodeSelected && HTMLArea.is_safari && this.editor._statusBarTree.selected && this.isInlineElement(this.editor._statusBarTree.selected) && this.editor._statusBarTree.selected.textContent === range.toString()) {
+                                       fullNodeSelected = true;
+                                       tagName = this.editor._statusBarTree.selected.nodeName.toLowerCase();
+                               }
+                       }
+                       var selectionInInlineElement = tagName && this.REInlineElements.test(tagName);
+                       var disabled = !this.endPointsInSameBlock() || (fullNodeSelected && !tagName) || (selectionEmpty && !selectionInInlineElement);
+                       
+                       var obj = editor.config.customSelects["FormatText"];
+                       if ((typeof(obj) !== "undefined") && (typeof(editor._toolbarObjects[obj.id]) !== "undefined")) {
+                               this.updateValue(editor, obj, tagName, selectionEmpty, fullNodeSelected, disabled);
+                       }
+                       
+                       var ancestors = editor.getAllAncestors();
+                       var bl = this.buttonList;
+                       for (var i = 0; i < bl.length; ++i) {
+                               var btn = bl[i];
+                               id = btn[0];
+                               var obj = editor._toolbarObjects[id];
+                               if ((typeof(obj) !== "undefined")) {
+                                       activeButton = false;
+                                       for (var j = ancestors.length; --j >= 0;) {
+                                               var el = ancestors[j];
+                                               if (!el) { continue; }
+                                               if (this.convertBtn[id] === el.nodeName.toLowerCase()) {
+                                                       activeButton = true;
+                                               }
+                                       }
+                                       obj.state("active", activeButton);
+                                       obj.state("enabled", !disabled);
+                               }
+                       }
+               }
+       },
+       
+       /*
+        * This function determines if the end poins of the current selection are within the same block
+        */
+       endPointsInSameBlock : function() {
+               var selection = this.editor._getSelection();
+               if (this.editor._selectionEmpty(selection)) {
+                       return true;
+               } else {
+                       var parent = this.editor.getParentElement(selection);
+                       var endBlocks = this.editor.getEndBlocks(selection);
+                       return (endBlocks.start === endBlocks.end && !/^(body|table|thead|tbody|tfoot|tr)$/i.test(parent.nodeName));
+               }
+       },
+       
+       /*
+       * This function updates the drop-down list of inline elemenents
+       */
+       updateValue : function (editor, obj, tagName, selectionEmpty, fullNodeSelected, disabled) {
+               var select = document.getElementById(editor._toolbarObjects[obj.id]["elementId"]);
+               var options = select.options;
+               for (var i = options.length; --i >= 0;) {
+                       options[i].selected = false;
+               }
+               select.selectedIndex = 0;
+               options[0].selected = true;
+               select.options[0].text = this.localize("No markup");
+               for (i = options.length; --i >= 0;) {
+                       if (tagName === options[i].value) {
+                               if (selectionEmpty || fullNodeSelected) {
+                                       options[i].selected = true;
+                                       select.selectedIndex = i;
+                                       select.options[0].text = this.localize("Remove markup");
+                               }
+                               break;
+                       }
+               }
+               
+               select.disabled = !(options.length>1) || disabled;
+               select.className = "";
+               if (select.disabled) {
+                       select.className = "buttonDisabled";
+               }
+       }
+});
+
diff --git a/typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/locallang.xml b/typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/locallang.xml
new file mode 100644 (file)
index 0000000..0856feb
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- TYPO3 SVN ID: $Id$ -->
+<T3locallang>
+       <meta type="array">
+               <description>Labels for Inline Elements plugin of htmlArea RTE</description>
+               <type>module</type>
+       </meta>
+       <data type="array">
+               <languageKey index="default" type="array">
+                       <label index="No markup">No text format</label>
+                       <label index="Remove markup">Remove text format</label>
+                       <label index="FormatText-Tooltip">Apply format to selected text</label>
+                       <label index="BiDiOverride-Tooltip">Bidirectionality override</label>
+                       <label index="Big-Tooltip">Large text</label>
+                       <label index="Bold-Tooltip">Bold</label>
+                       <label index="Citation-Tooltip">Citation</label>
+                       <label index="Code-Tooltip">Computer code fragment</label>
+                       <label index="Definition-Tooltip">Definition</label>
+                       <label index="DeletedText-Tooltip">Deleted text</label>
+                       <label index="Emphasis-Tooltip">Emphasis</label>
+                       <label index="Keyboard-Tooltip">Text to be entered by the user</label>
+                       <label index="InsertedText-Tooltip">Inserted text</label>
+                       <label index="Italic-Tooltip">Italic</label>
+                       <label index="MonoSpaced-Tooltip">Monospaced text</label>
+                       <label index="Quotation-Tooltip">Short inline quotation</label>
+                       <label index="Sample-Tooltip">Sample program output or script</label>
+                       <label index="Small-Tooltip">Small text</label>
+                       <label index="Span-Tooltip">Style container</label>
+                       <label index="StrikeThrough-Tooltip">Strike-through text</label>
+                       <label index="Strong-Tooltip">Strong emphasis</label>
+                       <label index="Subscript-Tooltip">Subscript</label>
+                       <label index="Superscript-Tooltip">Superscript</label>
+                       <label index="Underline-Tooltip">Underline</label>
+                       <label index="Variable-Tooltip">Variable or program argument</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/TextStyle/locallang.xml b/typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/locallang.xml
new file mode 100644 (file)
index 0000000..3c041db
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>\r
+<!-- TYPO3 SVN ID: $Id$ -->\r
+<T3locallang>\r
+       <meta type="array">\r
+               <description>Labels for Text Style plugin of htmlArea RTE</description>\r
+               <type>module</type>\r
+       </meta>\r
+       <data type="array">\r
+               <languageKey index="default" type="array">\r
+                       <label index="TextStyle-Tooltip">Apply style to the selected text</label>\r
+                       <label index="Technische Universitat Ilmenau">Technische Universit├Ąt Ilmenau</label>\r
+                       <label index="No style">No text style</label>\r
+                       <label index="Remove style">Remove text style</label>\r
+                       <label index="Unknown style">Unknown text style</label>\r
+                       <label index="Element style">Inline element style</label>\r
+               </languageKey>\r
+       </data>\r
+       <orig_hash type="array">\r
+               <languageKey index="default" type="array">\r
+               </languageKey>\r
+       </orig_hash>\r
+       <orig_text type="array">\r
+               <languageKey index="default" type="array">\r
+               </languageKey>\r
+       </orig_text>\r
+</T3locallang>
\ No newline at end of file
diff --git a/typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/text-style.js b/typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/text-style.js
new file mode 100644 (file)
index 0000000..26752ed
--- /dev/null
@@ -0,0 +1,636 @@
+/***************************************************************
+*  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 copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/*
+ * Text Style Plugin for TYPO3 htmlArea RTE
+ *
+ * TYPO3 SVN ID: $Id$
+ */
+/*
+ * Creation of the class of TextStyle plugins
+ */
+TextStyle = HTMLArea.Plugin.extend({
+       /*
+        * Let the base class do some initialization work
+        */
+       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.textstyle;
+               this.tags = this.pageTSconfiguration.tags;
+               if (!this.tags) {
+                       this.tags = new Object();
+               }
+               if (typeof(this.editorConfiguration.classesTag) !== "undefined") {
+                       if (this.editorConfiguration.classesTag.span) {
+                               if (!this.tags.span) {
+                                       this.tags.span = new Object();
+                               }
+                               if (!this.tags.span.allowedClasses) {
+                                       this.tags.span.allowedClasses = this.editorConfiguration.classesTag.span;
+                               }
+                       }
+               }
+               this.showTagFreeClasses = this.pageTSconfiguration.showTagFreeClasses || this.editorConfiguration.showTagFreeClasses;
+               this.prefixLabelWithClassName = this.pageTSconfiguration.prefixLabelWithClassName;
+               this.postfixLabelWithClassName = this.pageTSconfiguration.postfixLabelWithClassName;
+               
+               /*
+                * Regular expression to check if an element is an inline elment
+                */
+               this.REInlineTags = /^(abbr|acronym|b|bdo|big|cite|code|del|dfn|em|i|ins|kbd|q|samp|small|span|strike|strong|sub|sup|tt|u|var)$/;
+               
+               /*
+                * 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 = "TextStyle";
+               var dropDownConfiguration = {
+                       id              : buttonId,
+                       tooltip         : this.localize(buttonId + "-Tooltip"),
+                       textMode        : false,
+                       options         : {"":""},
+                       action          : "onChange",
+                       refresh         : "generate",
+                       context         : null
+               };
+               this.registerDropDown(dropDownConfiguration);
+               
+               return true;
+       },
+       
+       isInlineElement : function (el) {
+               return el && (el.nodeType === 1) && this.REInlineTags.test(el.nodeName.toLowerCase());
+       },
+       
+       /*
+        * This function gets called when some style in the drop-down list applies it to the highlighted textt
+        */
+       onChange : function (editor, buttonId) {
+               var select = document.getElementById(this.editor._toolbarObjects[buttonId].elementId);
+               var className = select.value;
+               var classNames = null;
+               var fullNodeSelected = false;
+               
+               this.editor.focusEditor();
+               var selection = this.editor._getSelection();
+               var range = this.editor._createRange(selection);
+               var parent = this.editor.getParentElement();
+               var selectionEmpty = this.editor._selectionEmpty(selection);
+               var ancestors = this.editor.getAllAncestors();
+               if (HTMLArea.is_ie) {
+                       var bookmark = range.getBookmark();
+               }
+               
+               if (!selectionEmpty) {
+                               // The selection is not empty
+                       for (var i = 0; i < ancestors.length; ++i) {
+                               fullNodeSelected = (HTMLArea.is_ie && ((this.editor._statusBarTree.selected === ancestors[i] && ancestors[i].innerText === range.text) || (!this.editor._statusBarTree.selected && ancestors[i].innerText === range.text)))
+                                                       || (HTMLArea.is_gecko && ((this.editor._statusBarTree.selected === ancestors[i] && ancestors[i].textContent === range.toString()) || (!this.editor._statusBarTree.selected && ancestors[i].textContent === range.toString())));
+                               if (fullNodeSelected) {
+                                       if (this.isInlineElement(ancestors[i])) {
+                                               parent = ancestors[i];
+                                       }
+                                       break;
+                               }
+                       }
+                               // Working around bug in Safari selectNodeContents
+                       if (!fullNodeSelected && HTMLArea.is_safari && this.editor._statusBarTree.selected && this.isInlineElement(this.editor._statusBarTree.selected) && this.editor._statusBarTree.selected.textContent === range.toString()) {
+                               fullNodeSelected = true;
+                               parent = this.editor._statusBarTree.selected;
+                       }
+               }
+               if (!selectionEmpty && !fullNodeSelected) {
+                               // The selection is not empty, nor full element
+                       if (className !== "none") {
+                                       // Add span element with class attribute
+                               if (HTMLArea.is_gecko) {
+                                       var newElement = this.editor._doc.createElement("span");
+                                       HTMLArea._addClass(newElement, className);
+                                       range.surroundContents(newElement);
+                                       newElement.normalize();
+                                       parent.normalize();
+                                               // Firefox sometimes inserts empty elements just outside the boundaries of the range
+                                       var neighbour = newElement.previousSibling;
+                                       if (neighbour && (neighbour.nodeType != 3) && !/\S/.test(neighbour.textContent)) {
+                                               HTMLArea.removeFromParent(neighbour);
+                                       }
+                                       neighbour = newElement.nextSibling;
+                                       if (neighbour && (neighbour.nodeType != 3) && !/\S/.test(neighbour.textContent)) {
+                                               HTMLArea.removeFromParent(neighbour);
+                                       }
+                                       this.editor.selectNodeContents(newElement, false);
+                                       range.detach();
+                               } else {
+                                       var rangeStart = range.duplicate();
+                                       rangeStart.collapse(true);
+                                       var parentStart = rangeStart.parentElement();
+                                       var rangeEnd = range.duplicate();
+                                       rangeEnd.collapse(true);
+                                       var parentEnd = rangeEnd.parentElement();
+                                       var newRange = editor._createRange();
+                                       
+                                       var upperParentStart = parentStart;
+                                       if (parentStart !== parent) {
+                                               while (upperParentStart.parentNode !== parent) {
+                                                       upperParentStart = upperParentStart.parentNode;
+                                               }
+                                       }
+                                               
+                                       var newElement = editor._doc.createElement("span");
+                                       HTMLArea._addClass(newElement, className);
+                                       newElement.innerHTML = range.htmlText;
+                                               // IE eats spaces on the start boundary
+                                       if (range.htmlText.charAt(0) === "\x20") {
+                                               newElement.innerHTML = "&nbsp;" + newElement.innerHTML;
+                                       }
+                                       var newElementClone = newElement.cloneNode(true);
+                                       range.pasteHTML(newElement.outerHTML);
+                                               // IE inserts the element as the last child of the start container
+                                       if (parentStart !== parent
+                                                       && parentStart.lastChild
+                                                       && parentStart.lastChild.nodeType === 1
+                                                       && parentStart.lastChild.nodeName.toLowerCase() === "span") {
+                                               parent.insertBefore(newElementClone, upperParentStart.nextSibling);
+                                               parentStart.removeChild(parentStart.lastChild);
+                                                       // Sometimes an empty previous sibling was created
+                                               if (newElementClone.previousSibling
+                                                               && newElementClone.previousSibling.nodeType === 1
+                                                               && !newElementClone.previousSibling.innerText) {
+                                                       parent.removeChild(newElementClone.previousSibling);
+                                               }
+                                                       // The bookmark will not work anymore
+                                               newRange.moveToElementText(newElementClone);
+                                               newRange.collapse(false);
+                                               newRange.select();
+                                       } else {
+                                                       // Working around IE boookmark bug
+                                               if (parentStart != parentEnd) {
+                                                       var newRange = editor._createRange();
+                                                       if (newRange.moveToBookmark(bookmark)) {
+                                                               newRange.collapse(false);
+                                                               newRange.select();
+                                                       }
+                                               } else {
+                                                       range.collapse(false);
+                                               }
+                                       }
+                                       parent.normalize();
+                               }
+                       }
+               } else {
+                               // Add or remove class
+                       if (parent && !HTMLArea.isBlockElement(parent)) {
+                               if (className === "none" && parent.className && /\S/.test(parent.className)) {
+                                       classNames = parent.className.trim().split(" ");
+                                       HTMLArea._removeClass(parent, classNames[classNames.length-1]);
+                               }
+                               if (className !== "none") {
+                                       HTMLArea._addClass(parent, className);
+                               }
+                                       // Remove the span tag if it has no more attribute
+                               if ((parent.nodeName.toLowerCase() === "span") && !this.hasAllowedAttributes(parent)) {
+                                       this.removeMarkup(parent);
+                               }
+                       }
+               }
+       },
+       
+       /*
+        * This function verifies if the element has any of the allowed attributes
+        */
+       hasAllowedAttributes : function(element) {
+               var allowedAttributes = new Array("id", "title", "lang", "xml:lang", "dir", "class", "className");
+               for (var i = 0; i < allowedAttributes.length; ++i) {
+                       if (element.getAttribute(allowedAttributes[i])) {
+                               return true;
+                       }
+               }
+               return false;
+       },
+       
+       /*
+        * This function removes the given markup element
+        */
+       removeMarkup : function(element) {
+               var bookmark = this.editor.getBookmark(this.editor._createRange(this.editor._getSelection()));
+               var parent = element.parentNode;
+               while (element.firstChild) {
+                       parent.insertBefore(element.firstChild, element);
+               }
+               parent.removeChild(element);
+               this.editor.selectRange(this.editor.moveToBookmark(bookmark));
+       },
+       
+       /*
+        * This function gets called when the plugin is generated
+        * Get the classes configuration and initiate the parsing of the style sheets
+        */
+       onGenerate : function() {
+               this.generate(this.editor, "TextStyle");
+       },
+       
+       /*
+        * 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.updateToolbar(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);
+               }
+       },
+       
+       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.updateToolbar(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;
+       },
+       
+       /*
+        * This function gets called when the toolbar is being updated
+        */
+       onUpdateToolbar : function() {
+               if (this.editor._editMode !== "textmode") {
+                       this.generate(this.editor, "TextStyle");
+               }
+       },
+       
+       /*
+       * This function gets called when the drop-down list needs to be refreshed
+       */
+       updateToolbar : function(dropDownId) {
+               var editor = this.editor;
+               if (editor._editMode !== "textmode") {
+                       var tagName = false, classNames = Array(), fullNodeSelected = false;
+                       var selection = editor._getSelection();
+                       var range = editor._createRange(selection);
+                       var parent = editor.getParentElement(selection);
+                       var ancestors = editor.getAllAncestors();
+                       if (parent && !HTMLArea.isBlockElement(parent)) {
+                               tagName = parent.nodeName.toLowerCase();
+                               if (parent.className && /\S/.test(parent.className)) {
+                                       classNames = parent.className.trim().split(" ");
+                               }
+                       }
+                       var selectionEmpty = editor._selectionEmpty(selection);
+                       if (!selectionEmpty) {
+                               for (var i = 0; i < ancestors.length; ++i) {
+                                       fullNodeSelected = (editor._statusBarTree.selected === ancestors[i])
+                                               && ((HTMLArea.is_gecko && ancestors[i].textContent === range.toString()) || (HTMLArea.is_ie && ancestors[i].innerText === range.text));
+                                       if (fullNodeSelected) {
+                                               if (!HTMLArea.isBlockElement(ancestors[i])) {
+                                                       tagName = ancestors[i].nodeName.toLowerCase();
+                                                       if (ancestors[i].className && /\S/.test(ancestors[i].className)) {
+                                                               classNames = ancestors[i].className.trim().split(" ");
+                                                       }
+                                               }
+                                               break;
+                                       }
+                               }
+                                       // Working around bug in Safari selectNodeContents
+                               if (!fullNodeSelected && HTMLArea.is_safari && this.editor._statusBarTree.selected && this.isInlineElement(this.editor._statusBarTree.selected) && this.editor._statusBarTree.selected.textContent === range.toString()) {
+                                       fullNodeSelected = true;
+                                       tagName = this.editor._statusBarTree.selected.nodeName.toLowerCase();
+                                       if (this.editor._statusBarTree.selected.className && /\S/.test(this.editor._statusBarTree.selected.className)) {
+                                               classNames = this.editor._statusBarTree.selected.className.trim().split(" ");
+                                       }
+                               }
+                       }
+                       var selectionInInlineElement = tagName && this.REInlineTags.test(tagName);
+                       var disabled = !this.endPointsInSameBlock() || (fullNodeSelected && !tagName) || (selectionEmpty && !selectionInInlineElement);
+                       if (!disabled && !tagName) {
+                               tagName = "span";
+                       }
+                       
+                       this.updateValue(dropDownId, tagName, classNames, selectionEmpty, fullNodeSelected, disabled);
+               }
+       },
+       
+       /*
+        * This function determines if the end poins of the current selection are within the same block
+        */
+       endPointsInSameBlock : function() {
+               var selection = this.editor._getSelection();
+               if (this.editor._selectionEmpty(selection)) {
+                       return true;
+               } else {
+                       var parent = this.editor.getParentElement(selection);
+                       var endBlocks = this.editor.getEndBlocks(selection);
+                       return (endBlocks.start === endBlocks.end && !/^(body|table|thead|tbody|tfoot|tr)$/i.test(parent.nodeName));
+               }
+       },
+       
+       updateValue : function(dropDownId, tagName, classNames, selectionEmpty, fullNodeSelected, disabled) {
+               var editor = this.editor;
+               var select = document.getElementById(editor._toolbarObjects[dropDownId]["elementId"]);
+               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");
+               if (this.REInlineTags.test(tagName)) {
+                               // 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 (cssClass in this.cssArray["all"]) {
+                                               if (allowedClasses.indexOf(cssClass) !== -1) {
+                                                       cssArray[cssClass] = this.cssArray["all"][cssClass];
+                                               }
+                                       }
+                               } else {
+                                       for (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 (!editor.config.disablePCexamples && HTMLArea.classesValues && HTMLArea.classesValues[cssClass] && !HTMLArea.classesNoShow[cssClass]) {
+                                                       select.options[select.options.length-1].setAttribute("style", HTMLArea.classesValues[cssClass]);
+                                               }
+                                       }
+                               }
+                       }
+                       
+                       select.selectedIndex = 0;
+                       if (classNames.length && (selectionEmpty || fullNodeSelected)) {
+                               for (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 (i = select.options.length; --i >= 0;) {
+                                       if (("," + classNames.join(",") + ",").indexOf("," + select.options[i].value + ",") !== -1) {
+                                               if (select.selectedIndex != i) {
+                                                       select.options[i] = null;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               select.disabled = !(select.options.length>1) || disabled;
+               select.className = "";
+               if (select.disabled) {
+                       select.className = "buttonDisabled";
+               }
+       },
+       
+       /*
+        * This function gets called when the editor has changed its mode to "wysiwyg"
+        */
+       onMode : function(mode) {
+               if (mode === "wysiwyg") {
+                       this.generate(this.editor, "TextStyle");
+               }
+       }
+});
+
index 4880bde..a7c50fb 100644 (file)
@@ -55,6 +55,9 @@ RTE.default.proc {
                ## This is a list of additional attributes to keep
        keepPDIVattribs = id, title, dir, lang, xml:lang
        
+               ## DO NOT REMAP BOLD AND ITALIC TO STRONG AND EMPHASIS AND VICE VERSA
+       transformBoldAndItalicTags = 0
+       
                ## CONTENT TO DATABASE
        entryHTMLparser_db = 1
        entryHTMLparser_db {
@@ -100,10 +103,12 @@ RTE.default.proc {
                        q.allowedAttribs = id, title, dir, lang, xml:lang, class
                        samp.allowedAttribs = id, title, dir, lang, xml:lang, class
                        small.allowedAttribs = id, title, dir, lang, xml:lang, class
+                       strike.allowedAttribs = id, title, dir, lang, xml:lang, class
                        strong.allowedAttribs = id, title, dir, lang, xml:lang, class
                        sub.allowedAttribs = id, title, dir, lang, xml:lang, class
                        sup.allowedAttribs = id, title, dir, lang, xml:lang, class
                        tt.allowedAttribs = id, title, dir, lang, xml:lang, class
+                       u.allowedAttribs = id, title, dir, lang, xml:lang, class
                        var.allowedAttribs = id, title, dir, lang, xml:lang, class
                }
                
@@ -128,12 +133,6 @@ RTE.default.proc {
        
        exitHTMLparser_db = 1
        exitHTMLparser_db {
-                       ## REMAP B AND I TAGS
-                       ## b and i tags are used by Mozilla/Firefox in editing mode.
-                       ## This must be done on exit because the default HTMLparser_db parsing executes the reverse mapping.
-               tags.b.remap = strong
-               tags.i.remap = em
-               
                        ## KEEP ALL TAGS
                        ## Unwanted tags were removed on entry.
                        ## Without this rule, the parser will remove all tags! Presumably, this rule will be more efficient than repeating the allowTags rule