Index: typo3/sysext/rtehtmlarea/class.tx_rtehtmlarea_base.php =================================================================== --- typo3/sysext/rtehtmlarea/class.tx_rtehtmlarea_base.php (révision 6908) +++ typo3/sysext/rtehtmlarea/class.tx_rtehtmlarea_base.php (copie de travail) @@ -4,7 +4,7 @@ * * (c) 2004-2009 Kasper Skaarhoj (kasper@typo3.com) * (c) 2004-2009 Philipp Borgmann -* (c) 2004-2009 Stanislas Rolland +* (c) 2004-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -36,18 +36,17 @@ */ class tx_rtehtmlarea_base extends t3lib_rteapi { - // Configuration of supported browsers var $conf_supported_browser = array ( 'msie' => array ( 1 => array ( - 'version' => 5.5, + 'version' => 6.0, 'system' => 'win' ) ), 'gecko' => array ( 1 => array ( - 'version' => 1.3 + 'version' => 1.8 ) ), 'safari' => array ( @@ -72,9 +71,7 @@ // Conversion array: TYPO3 button names to htmlArea button names var $convertToolbarForHtmlAreaArray = array ( - 'line' => 'InsertHorizontalRule', 'showhelp' => 'ShowHelp', - 'textindicator' => 'TextIndicator', 'space' => 'space', 'bar' => 'separator', 'linebreak' => 'linebreak', @@ -120,11 +117,11 @@ var $editorCSS; var $specConf; var $toolbar = array(); // Save the buttons for the toolbar - var $toolbar_level_size; // The size for each level in the toolbar: var $toolbarOrderArray = array(); protected $pluginEnabledArray = array(); // Array of plugin id's enabled in the current RTE editing area protected $pluginEnabledCumulativeArray = array(); // Cumulative array of plugin id's enabled so far in any of the RTE editing areas of the form public $registeredPlugins = array(); // Array of registered plugins indexed by their plugin Id's + protected $fullScreen = false; /** * Returns true if the RTE is available. Here you check if the browser requirements are met. @@ -338,13 +335,16 @@ // Preloading the pageStyle and including RTE skin stylesheets $this->addPageStyle(); $this->addSkin(); - // Loading JavaScript files and code if ($this->TCEform->RTEcounter == 1) { $this->TCEform->additionalJS_pre['rtehtmlarea-loadJScode'] = $this->loadJScode($this->TCEform->RTEcounter); } $this->TCEform->additionalCode_pre['rtehtmlarea-loadJSfiles'] = $this->loadJSfiles($this->TCEform->RTEcounter); - + $pageRenderer = $GLOBALS['SOBE']->doc->getPageRenderer(); + $pageRenderer->enableExtJSQuickTips(); + if (!$GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['enableCompressedScripts']) { + $pageRenderer->enableExtJsDebug(); + } /* ======================================= * DRAW THE EDITOR * ======================================= @@ -365,20 +365,10 @@ // Check if wizard_rte called this for fullscreen edtition; if so, change the size of the RTE to fullscreen using JS if (basename(PATH_thisScript) == 'wizard_rte.php') { - $height = 'window.innerHeight'; - $width = 'window.innerWidth'; - if ($this->client['BROWSER'] == 'msie') { - $height = 'document.body.offsetHeight'; - $width = 'document.body.offsetWidth'; - } - - // Subtract the docheader height from the calculated window height - $height .= ' - document.getElementById("typo3-docheader").offsetHeight'; - + $this->fullScreen = true; $editorWrapWidth = '100%'; $editorWrapHeight = '100%'; $this->RTEdivStyle = 'position:relative; left:0px; top:0px; height:100%; width:100%; border: 1px solid black; padding: 2px 0px 2px 2px;'; - $this->TCEform->additionalJS_post[] = $this->setRTEsizeByJS('RTEarea' . $textAreaId, $height, $width); } // Register RTE in JS: @@ -426,9 +416,6 @@ protected function addSkin() { // Get skin file name from Page TSConfig if any $skinFilename = trim($this->thisConfig['skin']) ? trim($this->thisConfig['skin']) : 'EXT:' . $this->ID . '/htmlarea/skins/default/htmlarea.css'; - if($this->client['BROWSER'] == 'gecko' && $this->client['VERSION'] == '1.3' && substr($skinFilename,0,4) == 'EXT:') { - $skinFilename = 'EXT:' . $this->ID . '/htmlarea/skins/default/htmlarea.css'; - } // Skin provided by some extension if (substr($skinFilename,0,4) == 'EXT:') { list($extKey,$local) = explode('/',substr($skinFilename,4),2); @@ -561,44 +548,22 @@ function setToolbar() { global $BE_USER; - if ($this->client['BROWSER'] == 'msie' || $this->client['BROWSER'] == 'opera' || ($this->client['BROWSER'] == 'gecko' && $this->client['VERSION'] == '1.3')) { + if ($this->client['BROWSER'] == 'msie' || $this->client['BROWSER'] == 'opera') { $this->thisConfig['keepButtonGroupTogether'] = 0; } $this->defaultToolbarOrder = 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak, bar, formattext, bold, strong, italic, emphasis, big, small, insertedtext, deletedtext, citation, code, definition, keyboard, monospaced, quotation, sample, variable, bidioverride, strikethrough, subscript, superscript, underline, span, - bar, fontstyle, space, fontsize, bar, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, + bar, fontstyle, space, fontsize, bar, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, line, bar, left, center, right, justifyfull, bar, orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent, bar, lefttoright, righttoleft, language, showlanguagemarks, bar, textcolor, bgcolor, textindicator, - bar, emoticon, insertcharacter, line, link, unlink, image, table,' . (($this->thisConfig['hideTableOperationsInToolbar'] && is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.']['toggleborders.']) && $this->thisConfig['buttons.']['toggleborders.']['keepInToolbar']) ? ' toggleborders,': '') . ' user, acronym, bar, findreplace, spellcheck, + bar, emoticon, insertcharacter, link, unlink, image, table,' . (($this->thisConfig['hideTableOperationsInToolbar'] && is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.']['toggleborders.']) && $this->thisConfig['buttons.']['toggleborders.']['keepInToolbar']) ? ' toggleborders,': '') . ' user, acronym, bar, findreplace, spellcheck, bar, chMode, inserttag, removeformat, bar, copy, cut, paste, bar, undo, redo, bar, showhelp, about, linebreak, ' . ($this->thisConfig['hideTableOperationsInToolbar'] ? '': 'bar, toggleborders,') . ' bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar, columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar, cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge'; - // Special toolbar for Mozilla Wamcom on Mac OS 9 - if($this->client['BROWSER'] == 'gecko' && $this->client['VERSION'] == '1.3') { - $this->defaultToolbarOrder = $this->TCEform->docLarge ? 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak, - bar, fontstyle, space, fontsize, space, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, bar, bold, italic, underline, strikethrough, - subscript, superscript, lefttoright, righttoleft, language, showlanguagemarks, bar, left, center, right, justifyfull, linebreak, - bar, orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent, bar, textcolor, bgcolor, textindicator, bar, emoticon, - insertcharacter, line, link, unlink, image, table, user, acronym, bar, findreplace, spellcheck, bar, chMode, inserttag, - removeformat, bar, copy, cut, paste, bar, undo, redo, bar, showhelp, about, linebreak, - bar, toggleborders, bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar, - columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar, - cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge' - : 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak, - bar, fontstyle, space, fontsize, space, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, bar, bold, italic, underline, strikethrough, - subscript, superscript, linebreak, bar, lefttoright, righttoleft, language, showlanguagemarks, bar, left, center, right, justifyfull, - orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent, bar, textcolor, bgcolor, textindicator, bar, emoticon, - insertcharacter, line, link, unlink, image, table, user, acronym, linebreak, bar, findreplace, spellcheck, bar, chMode, inserttag, - removeformat, bar, copy, cut, paste, bar, undo, redo, bar, showhelp, about, linebreak, - bar, toggleborders, bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar, - columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar, - cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge'; - } - // Additional buttons from registered plugins foreach($this->registeredPlugins as $pluginId => $plugin) { if ($this->isPluginEnabled($pluginId)) { @@ -738,22 +703,7 @@ function convertToolbarForHTMLArea($button) { return $this->convertToolbarForHtmlAreaArray[$button]; } - /** - * Return the JS-function for setting the RTE size. - * - * @param string DivID-Name - * @param int the height for the RTE - * @param int the width for the RTE - * @return string Loader function in JS - */ - function setRTEsizeByJS($divId, $height, $width) { - return ' - setRTEsizeByJS(\''.$divId.'\','.$height.', '.$width.'); - '; - } - - /** * Return the HTML code for loading the Javascript files * * @param integer $RTEcounter: The index number of the current RTE editing area within the form. @@ -777,7 +727,7 @@ if (typeof(RTEarea) == "undefined") { RTEarea = new Object(); RTEarea.init = function() { - if (typeof(HTMLArea) == "undefined") { + if (typeof(HTMLArea) == "undefined" || !Ext.isReady) { window.setTimeout("RTEarea.init();", 40); } else {' . $loadPluginCode . ' @@ -859,6 +809,10 @@ RTEarea[editornumber].deleted = false; RTEarea[editornumber].textAreaId = "' . $textAreaId . '"; RTEarea[editornumber].id = "RTEarea" + editornumber; + RTEarea[editornumber].RTEWidthOverride = "' . trim($this->thisConfig['RTEWidthOverride']) . '"; + RTEarea[editornumber].RTEHeightOverride = "' . trim($this->thisConfig['RTEHeightOverride']) . '"; + RTEarea[editornumber].fullScreen = ' . ($this->fullScreen ? 'true' : 'false') . '; + RTEarea[editornumber].showStatusBar = ' . (trim($this->thisConfig['showStatusBar'])?'true':'false') . '; RTEarea[editornumber].enableWordClean = ' . (trim($this->thisConfig['enableWordClean'])?'true':'false') . '; RTEarea[editornumber]["htmlRemoveComments"] = ' . (trim($this->thisConfig['removeComments'])?'true':'false') . '; RTEarea[editornumber].disableEnterParagraphs = ' . (trim($this->thisConfig['disableEnterParagraphs'])?'true':'false') . '; @@ -1215,64 +1169,62 @@ } /** - * Return the JS-Code for the Toolbar-Config-Array for HTML-Area + * Return the JS code of the toolbar configuration for the HTMLArea editor * - * @return string the JS-Code as an JS-Array + * @return string the JS code as nested JS arrays */ - - function getJSToolbarArray() { - $toolbar = ''; // The JS-Code for the toolbar - $group = ''; // The TS-Code for the group in the moment, each group are between "bar"s - $group_has_button = false; // True if the group has any enabled buttons - $group_needs_starting_bar = false; - $previous_is_space = false; - - // process each button in the order list - foreach ($this->toolbarOrderArray as $button) { - // check if a new group starts - if (($button == 'bar' || $button == 'linebreak') && $group_has_button) { - // New line - if ($button == 'linebreak') { - $convertButton = '"' . $this->convertToolbarForHTMLArea('linebreak') . '"'; - $group = ($group!='') ? ($group . ', ' . $convertButton) : $convertButton; - } - // New group - $toolbar .= $toolbar ? (', ' . $group) : ('[[' . $group); - $group = ''; - $previous_is_space = false; - $group_has_button = false; - $group_needs_starting_bar = ($button == 'bar'); - } elseif ($toolbar && $button == 'linebreak' && !$group_has_button) { - // Insert linebreak if no group is opened - $group = ''; - $previous_is_space = false; - $group_needs_starting_bar = false; - $toolbar .= ', "' . $this->convertToolbarForHTMLArea($button) . '"'; - } elseif ($button == 'bar' && !$group_has_button) { - $group_needs_starting_bar = true; - } elseif ($button == 'space' && $group_has_button && !$previous_is_space) { - $convertButton = $this->convertToolbarForHTMLArea($button); - $convertButton = '"' . $convertButton . '"'; - $group .= $group ? (', ' . $convertButton) : ($group_needs_starting_bar ? ('"' . $this->convertToolbarForHTMLArea('bar') . '", ' . $convertButton) : $convertButton); - $group_needs_starting_bar = false; - $previous_is_space = true; - } elseif (in_array($button, $this->toolbar)) { - // Add the button to the group - $convertButton = $this->convertToolbarForHTMLArea($button); - if ($convertButton) { - $convertButton = '"' . $convertButton . '"'; - $group .= $group ? (', ' . $convertButton) : ($group_needs_starting_bar ? ('"' . $this->convertToolbarForHTMLArea('bar') . '", ' . $convertButton) : $convertButton); - $group_has_button = true; - $group_needs_starting_bar = false; - $previous_is_space = false; - } + protected function getJSToolbarArray() { + // The toolbar array + $toolbar = array(); + // The current row; a "linebreak" ends the current row + $row = array(); + // The current group; each group is between "bar"s; a "linebreak" ends the current group + $group = array(); + // Process each toolbar item in the toolbar order list + foreach ($this->toolbarOrderArray as $item) { + switch ($item) { + case 'linebreak': + // Add row to toolbar if not empty + if (!empty($group)) { + $row[] = $group; + $group = array(); + } + if (!empty($row)) { + $toolbar[] = $row; + $row = array(); + } + break; + case 'bar': + // Add group to row if not empty + if (!empty($group)) { + $row[] = $group; + $group = array(); + } + break; + case 'space': + if (end($group) != $this->convertToolbarForHTMLArea($item)) { + $group[] = $this->convertToolbarForHTMLArea($item); + } + break; + default: + if (in_array($item, $this->toolbar)) { + // Add the item to the group + $convertedItem = $this->convertToolbarForHTMLArea($item); + if ($convertedItem) { + $group[] = $convertedItem; + } + } + break; } - // else ignore } - // add the last group - if($group_has_button) $toolbar .= $toolbar ? (', ' . $group) : ('[[' . $group); - $toolbar = $toolbar . ']]'; - return $toolbar; + // Add the last group and last line, if not empty + if (!empty($group)) { + $row[] = $group; + } + if (!empty($row)) { + $toolbar[] = $row; + } + return json_encode($toolbar); } public function getLLContent($string) { @@ -1347,7 +1299,7 @@ * @return string Javascript code */ function setSaveRTE($RTEcounter, $formName, $textareaId) { - return 'if (RTEarea["' . $textareaId . '"]) { document.' . $formName . '["' . $textareaId . '"].value = RTEarea["' . $textareaId . '"].editor.getPluginInstance("EditorMode").getHTML(); } else { OK = 0; };'; + return 'if (RTEarea["' . $textareaId . '"]) { document.' . $formName . '["' . $textareaId . '"].value = RTEarea["' . $textareaId . '"].editor.getHTML(); } else { OK = 0; };'; } /** Index: typo3/sysext/rtehtmlarea/ext_emconf.php =================================================================== --- typo3/sysext/rtehtmlarea/ext_emconf.php (révision 6908) +++ typo3/sysext/rtehtmlarea/ext_emconf.php (copie de travail) @@ -19,7 +19,7 @@ 'conflicts' => 'rte_conf', 'priority' => '', 'loadOrder' => '', - 'module' => 'mod2,mod3,mod4,mod5,mod6', + 'module' => 'mod3,mod4,mod5,mod6', 'state' => 'stable', 'internal' => 0, 'uploadfolder' => 1, @@ -32,7 +32,7 @@ 'author_company' => 'SJBR', 'CGLcompliance' => '', 'CGLcompliance_note' => '', - 'version' => '1.9.0', + 'version' => '1.9.1', '_md5_values_when_last_written' => 'a:434:{s:9:"ChangeLog";s:4:"e5f3";s:29:"class.tx_rtehtmlarea_base.php";s:4:"8a14";s:27:"class.tx_rtehtmlareaapi.php";s:4:"69b4";s:21:"ext_conf_template.txt";s:4:"afd8";s:12:"ext_icon.gif";s:4:"2f41";s:17:"ext_localconf.php";s:4:"340c";s:14:"ext_tables.php";s:4:"ea2e";s:14:"ext_tables.sql";s:4:"bba8";s:13:"locallang.xml";s:4:"3cca";s:16:"locallang_db.xml";s:4:"c2ed";s:7:"tca.php";s:4:"6b5a";s:14:"doc/manual.sxw";s:4:"e68c";s:59:"extensions/AboutEditor/class.tx_rtehtmlarea_abouteditor.php";s:4:"d8ac";s:40:"extensions/AboutEditor/skin/htmlarea.css";s:4:"eb62";s:44:"extensions/AboutEditor/skin/images/about.gif";s:4:"1690";s:51:"extensions/Acronym/class.tx_rtehtmlarea_acronym.php";s:4:"ee28";s:36:"extensions/Acronym/skin/htmlarea.css";s:4:"c107";s:42:"extensions/Acronym/skin/images/acronym.gif";s:4:"1eaa";s:63:"extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php";s:4:"aeef";s:38:"extensions/BlockElements/locallang.xml";s:4:"479e";s:42:"extensions/BlockElements/skin/htmlarea.css";s:4:"83ce";s:51:"extensions/BlockElements/skin/images/blockquote.gif";s:4:"34dc";s:47:"extensions/BlockElements/skin/images/indent.gif";s:4:"57df";s:58:"extensions/BlockElements/skin/images/insertOrderedList.gif";s:4:"eb1c";s:61:"extensions/BlockElements/skin/images/insertParagraphAfter.gif";s:4:"e335";s:62:"extensions/BlockElements/skin/images/insertParagraphBefore.gif";s:4:"9c42";s:60:"extensions/BlockElements/skin/images/insertUnorderedList.gif";s:4:"5620";s:54:"extensions/BlockElements/skin/images/justifyCenter.gif";s:4:"420d";s:52:"extensions/BlockElements/skin/images/justifyFull.gif";s:4:"b129";s:52:"extensions/BlockElements/skin/images/justifyLeft.gif";s:4:"3799";s:53:"extensions/BlockElements/skin/images/justifyRight.gif";s:4:"0662";s:48:"extensions/BlockElements/skin/images/outdent.gif";s:4:"4786";s:57:"extensions/BlockStyle/class.tx_rtehtmlarea_blockstyle.php";s:4:"3ba0";s:35:"extensions/BlockStyle/locallang.xml";s:4:"26b8";s:61:"extensions/CharacterMap/class.tx_rtehtmlarea_charactermap.php";s:4:"a537";s:41:"extensions/CharacterMap/skin/htmlarea.css";s:4:"06c8";s:55:"extensions/CharacterMap/skin/images/insertCharacter.gif";s:4:"af19";s:59:"extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php";s:4:"e4b5";s:55:"extensions/CopyPaste/class.tx_rtehtmlarea_copypaste.php";s:4:"09ad";s:38:"extensions/CopyPaste/skin/htmlarea.css";s:4:"9391";s:41:"extensions/CopyPaste/skin/images/copy.gif";s:4:"98d2";s:40:"extensions/CopyPaste/skin/images/cut.gif";s:4:"1323";s:42:"extensions/CopyPaste/skin/images/paste.gif";s:4:"7df5";s:61:"extensions/DefaultClean/class.tx_rtehtmlarea_defaultclean.php";s:4:"142b";s:61:"extensions/DefaultColor/class.tx_rtehtmlarea_defaultcolor.php";s:4:"fa59";s:37:"extensions/DefaultColor/locallang.xml";s:4:"3fb4";s:41:"extensions/DefaultColor/skin/htmlarea.css";s:4:"6076";s:49:"extensions/DefaultColor/skin/images/forecolor.gif";s:4:"dbc8";s:51:"extensions/DefaultColor/skin/images/hilitecolor.gif";s:4:"d97c";s:59:"extensions/DefaultFont/class.tx_rtehtmlarea_defaultfont.php";s:4:"2172";s:36:"extensions/DefaultFont/locallang.xml";s:4:"8c90";s:61:"extensions/DefaultImage/class.tx_rtehtmlarea_defaultimage.php";s:4:"12cf";s:41:"extensions/DefaultImage/skin/htmlarea.css";s:4:"6cfe";s:45:"extensions/DefaultImage/skin/images/image.gif";s:4:"c0f0";s:63:"extensions/DefaultInline/class.tx_rtehtmlarea_defaultinline.php";s:4:"4e85";s:38:"extensions/DefaultInline/locallang.xml";s:4:"318f";s:42:"extensions/DefaultInline/skin/htmlarea.css";s:4:"6009";s:45:"extensions/DefaultInline/skin/images/bold.gif";s:4:"94f2";s:47:"extensions/DefaultInline/skin/images/italic.gif";s:4:"f60c";s:54:"extensions/DefaultInline/skin/images/strikethrough.gif";s:4:"3fd0";s:50:"extensions/DefaultInline/skin/images/subscript.gif";s:4:"cedd";s:52:"extensions/DefaultInline/skin/images/superscript.gif";s:4:"8aea";s:50:"extensions/DefaultInline/skin/images/underline.gif";s:4:"81e6";s:59:"extensions/DefaultLink/class.tx_rtehtmlarea_defaultlink.php";s:4:"2219";s:40:"extensions/DefaultLink/skin/htmlarea.css";s:4:"680b";s:43:"extensions/DefaultLink/skin/images/link.gif";s:4:"db9a";s:45:"extensions/DefaultLink/skin/images/unlink.gif";s:4:"86c4";s:65:"extensions/DefinitionList/class.tx_rtehtmlarea_definitionlist.php";s:4:"483d";s:43:"extensions/DefinitionList/skin/htmlarea.css";s:4:"a254";s:56:"extensions/DefinitionList/skin/images/definitionItem.gif";s:4:"33ae";s:56:"extensions/DefinitionList/skin/images/definitionList.gif";s:4:"d5d1";s:57:"extensions/EditorMode/class.tx_rtehtmlarea_editormode.php";s:4:"1453";s:39:"extensions/EditorMode/skin/htmlarea.css";s:4:"0793";s:45:"extensions/EditorMode/skin/images/ed_html.gif";s:4:"fa6e";s:59:"extensions/FindReplace/class.tx_rtehtmlarea_findreplace.php";s:4:"a968";s:40:"extensions/FindReplace/skin/htmlarea.css";s:4:"43cc";s:43:"extensions/FindReplace/skin/images/find.gif";s:4:"827f";s:65:"extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php";s:4:"452a";s:39:"extensions/InlineElements/locallang.xml";s:4:"07c6";s:46:"extensions/InlineElements/res/pageTSConfig.txt";s:4:"088c";s:43:"extensions/InlineElements/skin/htmlarea.css";s:4:"978b";s:54:"extensions/InlineElements/skin/images/bidioverride.gif";s:4:"f38b";s:45:"extensions/InlineElements/skin/images/big.gif";s:4:"779b";s:46:"extensions/InlineElements/skin/images/bold.gif";s:4:"06ac";s:50:"extensions/InlineElements/skin/images/citation.gif";s:4:"b6eb";s:46:"extensions/InlineElements/skin/images/code.gif";s:4:"6057";s:52:"extensions/InlineElements/skin/images/definition.gif";s:4:"692d";s:53:"extensions/InlineElements/skin/images/deletedtext.gif";s:4:"4eec";s:50:"extensions/InlineElements/skin/images/emphasis.gif";s:4:"04c9";s:54:"extensions/InlineElements/skin/images/insertedtext.gif";s:4:"a624";s:48:"extensions/InlineElements/skin/images/italic.gif";s:4:"be83";s:50:"extensions/InlineElements/skin/images/keyboard.gif";s:4:"53ac";s:52:"extensions/InlineElements/skin/images/monospaced.gif";s:4:"78c0";s:51:"extensions/InlineElements/skin/images/quotation.gif";s:4:"7c62";s:48:"extensions/InlineElements/skin/images/sample.gif";s:4:"667c";s:47:"extensions/InlineElements/skin/images/small.gif";s:4:"e013";s:46:"extensions/InlineElements/skin/images/span.gif";s:4:"0dfa";s:55:"extensions/InlineElements/skin/images/strikethrough.gif";s:4:"73b1";s:48:"extensions/InlineElements/skin/images/strong.gif";s:4:"7f50";s:51:"extensions/InlineElements/skin/images/subscript.gif";s:4:"36c0";s:53:"extensions/InlineElements/skin/images/superscript.gif";s:4:"40c4";s:51:"extensions/InlineElements/skin/images/underline.gif";s:4:"dfac";s:50:"extensions/InlineElements/skin/images/variable.gif";s:4:"da61";s:61:"extensions/InsertSmiley/class.tx_rtehtmlarea_insertsmiley.php";s:4:"4d97";s:41:"extensions/InsertSmiley/skin/htmlarea.css";s:4:"fb52";s:46:"extensions/InsertSmiley/skin/images/smiley.gif";s:4:"c331";s:53:"extensions/Language/class.tx_rtehtmlarea_language.php";s:4:"4f0b";s:33:"extensions/Language/locallang.xml";s:4:"ff62";s:37:"extensions/Language/skin/htmlarea.css";s:4:"7034";s:49:"extensions/Language/skin/images/left_to_right.gif";s:4:"1a1f";s:49:"extensions/Language/skin/images/right_to_left.gif";s:4:"2a38";s:55:"extensions/Language/skin/images/show-language-marks.gif";s:4:"0bbb";s:53:"extensions/QuickTag/class.tx_rtehtmlarea_quicktag.php";s:4:"c925";s:37:"extensions/QuickTag/skin/htmlarea.css";s:4:"b006";s:45:"extensions/QuickTag/skin/images/inserttag.gif";s:4:"a463";s:61:"extensions/RemoveFormat/class.tx_rtehtmlarea_removeformat.php";s:4:"f7a1";s:41:"extensions/RemoveFormat/skin/htmlarea.css";s:4:"be33";s:45:"extensions/RemoveFormat/skin/images/clean.gif";s:4:"2a0f";s:57:"extensions/SelectFont/class.tx_rtehtmlarea_selectfont.php";s:4:"281e";s:35:"extensions/SelectFont/locallang.xml";s:4:"cb6e";s:61:"extensions/SpellChecker/class.tx_rtehtmlarea_spellchecker.php";s:4:"9c27";s:41:"extensions/SpellChecker/skin/htmlarea.css";s:4:"cedf";s:51:"extensions/SpellChecker/skin/images/spell-check.gif";s:4:"6e0a";s:55:"extensions/StatusBar/class.tx_rtehtmlarea_statusbar.php";s:4:"7db4";s:57:"extensions/TYPO3Color/class.tx_rtehtmlarea_typo3color.php";s:4:"daad";s:35:"extensions/TYPO3Color/locallang.xml";s:4:"377f";s:39:"extensions/TYPO3Color/skin/htmlarea.css";s:4:"fad4";s:47:"extensions/TYPO3Color/skin/images/forecolor.gif";s:4:"dbc8";s:49:"extensions/TYPO3Color/skin/images/hilitecolor.gif";s:4:"d97c";s:67:"extensions/TYPO3HtmlParser/class.tx_rtehtmlarea_typo3htmlparser.php";s:4:"b885";s:57:"extensions/TYPO3Image/class.tx_rtehtmlarea_typo3image.php";s:4:"55d0";s:39:"extensions/TYPO3Image/skin/htmlarea.css";s:4:"f593";s:43:"extensions/TYPO3Image/skin/images/image.gif";s:4:"c0f0";s:55:"extensions/TYPO3Link/class.tx_rtehtmlarea_typo3link.php";s:4:"50b8";s:38:"extensions/TYPO3Link/skin/htmlarea.css";s:4:"73f9";s:41:"extensions/TYPO3Link/skin/images/link.gif";s:4:"db9a";s:43:"extensions/TYPO3Link/skin/images/unlink.gif";s:4:"86c4";s:67:"extensions/TableOperations/class.tx_rtehtmlarea_tableoperations.php";s:4:"56ba";s:44:"extensions/TableOperations/skin/htmlarea.css";s:4:"b57e";s:54:"extensions/TableOperations/skin/images/cell-delete.gif";s:4:"f371";s:60:"extensions/TableOperations/skin/images/cell-insert-after.gif";s:4:"2dd2";s:61:"extensions/TableOperations/skin/images/cell-insert-before.gif";s:4:"5d13";s:53:"extensions/TableOperations/skin/images/cell-merge.gif";s:4:"cb52";s:52:"extensions/TableOperations/skin/images/cell-prop.gif";s:4:"ca41";s:53:"extensions/TableOperations/skin/images/cell-split.gif";s:4:"0095";s:53:"extensions/TableOperations/skin/images/col-delete.gif";s:4:"da78";s:59:"extensions/TableOperations/skin/images/col-insert-after.gif";s:4:"80d8";s:60:"extensions/TableOperations/skin/images/col-insert-before.gif";s:4:"d47d";s:51:"extensions/TableOperations/skin/images/col-prop.gif";s:4:"b178";s:52:"extensions/TableOperations/skin/images/col-split.gif";s:4:"c168";s:55:"extensions/TableOperations/skin/images/insert_table.gif";s:4:"c01b";s:53:"extensions/TableOperations/skin/images/row-delete.gif";s:4:"a289";s:59:"extensions/TableOperations/skin/images/row-insert-above.gif";s:4:"1ef1";s:59:"extensions/TableOperations/skin/images/row-insert-under.gif";s:4:"9ad6";s:51:"extensions/TableOperations/skin/images/row-prop.gif";s:4:"5344";s:52:"extensions/TableOperations/skin/images/row-split.gif";s:4:"ebfd";s:53:"extensions/TableOperations/skin/images/table-prop.gif";s:4:"0a5c";s:56:"extensions/TableOperations/skin/images/table-restyle.gif";s:4:"9284";s:57:"extensions/TableOperations/skin/images/toggle-borders.gif";s:4:"50cb";s:55:"extensions/TextStyle/class.tx_rtehtmlarea_textstyle.php";s:4:"ed42";s:34:"extensions/TextStyle/locallang.xml";s:4:"23dd";s:53:"extensions/UndoRedo/class.tx_rtehtmlarea_undoredo.php";s:4:"d297";s:37:"extensions/UndoRedo/skin/htmlarea.css";s:4:"de26";s:40:"extensions/UndoRedo/skin/images/redo.gif";s:4:"5fdf";s:40:"extensions/UndoRedo/skin/images/undo.gif";s:4:"8d53";s:61:"extensions/UserElements/class.tx_rtehtmlarea_userelements.php";s:4:"984d";s:41:"extensions/UserElements/skin/htmlarea.css";s:4:"f66d";s:44:"extensions/UserElements/skin/images/user.gif";s:4:"bbb4";s:59:"hooks/clearrtecache/class.tx_rtehtmlarea_clearcachemenu.php";s:4:"b8fe";s:58:"hooks/clearrtecache/class.tx_rtehtmlarea_clearrtecache.php";s:4:"a33e";s:37:"hooks/clearrtecache/clearrtecache.png";s:4:"e03a";s:37:"hooks/clearrtecache/ext_localconf.php";s:4:"3cbb";s:33:"hooks/clearrtecache/locallang.xml";s:4:"3902";s:29:"htmlarea/HTMLAREA_LICENSE.txt";s:4:"a10f";s:26:"htmlarea/htmlarea-gecko.js";s:4:"786d";s:23:"htmlarea/htmlarea-ie.js";s:4:"601e";s:20:"htmlarea/htmlarea.js";s:4:"6dde";s:30:"htmlarea/locallang_dialogs.xml";s:4:"a7aa";s:26:"htmlarea/locallang_msg.xml";s:4:"7b6f";s:31:"htmlarea/locallang_tooltips.xml";s:4:"0152";s:44:"htmlarea/plugins/AboutEditor/about-editor.js";s:4:"8241";s:46:"htmlarea/plugins/AboutEditor/popups/about.html";s:4:"d677";s:35:"htmlarea/plugins/Acronym/acronym.js";s:4:"f9af";s:38:"htmlarea/plugins/Acronym/locallang.xml";s:4:"aea2";s:48:"htmlarea/plugins/BlockElements/block-elements.js";s:4:"4c56";s:44:"htmlarea/plugins/BlockElements/locallang.xml";s:4:"ee21";s:42:"htmlarea/plugins/BlockStyle/block-style.js";s:4:"d9e7";s:41:"htmlarea/plugins/BlockStyle/locallang.xml";s:4:"32ed";s:46:"htmlarea/plugins/CharacterMap/character-map.js";s:4:"3b2b";s:43:"htmlarea/plugins/CharacterMap/locallang.xml";s:4:"7211";s:58:"htmlarea/plugins/CharacterMap/popups/select_character.html";s:4:"c48a";s:44:"htmlarea/plugins/ContextMenu/context-menu.js";s:4:"d88e";s:42:"htmlarea/plugins/ContextMenu/locallang.xml";s:4:"3ead";s:40:"htmlarea/plugins/CopyPaste/copy-paste.js";s:4:"427b";s:40:"htmlarea/plugins/CopyPaste/locallang.xml";s:4:"6703";s:46:"htmlarea/plugins/DefaultClean/default-clean.js";s:4:"409f";s:43:"htmlarea/plugins/DefaultClean/locallang.xml";s:4:"9e62";s:46:"htmlarea/plugins/DefaultColor/default-color.js";s:4:"3c23";s:43:"htmlarea/plugins/DefaultColor/locallang.xml";s:4:"c8d1";s:54:"htmlarea/plugins/DefaultColor/popups/select_color.html";s:4:"8af8";s:44:"htmlarea/plugins/DefaultFont/default-font.js";s:4:"8d1c";s:42:"htmlarea/plugins/DefaultFont/locallang.xml";s:4:"a7f8";s:46:"htmlarea/plugins/DefaultImage/default-image.js";s:4:"9ca0";s:43:"htmlarea/plugins/DefaultImage/locallang.xml";s:4:"1fdd";s:54:"htmlarea/plugins/DefaultImage/popups/insert_image.html";s:4:"6773";s:48:"htmlarea/plugins/DefaultInline/default-inline.js";s:4:"c303";s:44:"htmlarea/plugins/DefaultInline/locallang.xml";s:4:"2b55";s:44:"htmlarea/plugins/DefaultLink/default-link.js";s:4:"3139";s:42:"htmlarea/plugins/DefaultLink/locallang.xml";s:4:"e233";s:45:"htmlarea/plugins/DefaultLink/popups/link.html";s:4:"6157";s:50:"htmlarea/plugins/DefinitionList/definition-list.js";s:4:"581b";s:45:"htmlarea/plugins/DefinitionList/locallang.xml";s:4:"5c85";s:42:"htmlarea/plugins/DynamicCSS/dynamiccss.css";s:4:"85b7";s:41:"htmlarea/plugins/DynamicCSS/locallang.xml";s:4:"b6bf";s:52:"htmlarea/plugins/DynamicCSS/img/red_arrow_bullet.gif";s:4:"82d6";s:42:"htmlarea/plugins/EditorMode/editor-mode.js";s:4:"eaab";s:41:"htmlarea/plugins/EditorMode/locallang.xml";s:4:"5b14";s:44:"htmlarea/plugins/FindReplace/find-replace.js";s:4:"5caf";s:41:"htmlarea/plugins/FindReplace/fr_engine.js";s:4:"4ce4";s:42:"htmlarea/plugins/FindReplace/locallang.xml";s:4:"f836";s:53:"htmlarea/plugins/FindReplace/popups/find_replace.html";s:4:"4ee2";s:40:"htmlarea/plugins/InlineCSS/locallang.xml";s:4:"7840";s:50:"htmlarea/plugins/InlineElements/inline-elements.js";s:4:"d31a";s:45:"htmlarea/plugins/InlineElements/locallang.xml";s:4:"6f8c";s:46:"htmlarea/plugins/InsertSmiley/insert-smiley.js";s:4:"23a1";s:43:"htmlarea/plugins/InsertSmiley/locallang.xml";s:4:"ed64";s:54:"htmlarea/plugins/InsertSmiley/popups/insertsmiley.html";s:4:"6ece";s:46:"htmlarea/plugins/InsertSmiley/smileys/0001.gif";s:4:"4aff";s:46:"htmlarea/plugins/InsertSmiley/smileys/0002.gif";s:4:"02c4";s:46:"htmlarea/plugins/InsertSmiley/smileys/0003.gif";s:4:"834f";s:46:"htmlarea/plugins/InsertSmiley/smileys/0004.gif";s:4:"fb6a";s:46:"htmlarea/plugins/InsertSmiley/smileys/0005.gif";s:4:"2a48";s:46:"htmlarea/plugins/InsertSmiley/smileys/0006.gif";s:4:"f970";s:46:"htmlarea/plugins/InsertSmiley/smileys/0007.gif";s:4:"97ee";s:46:"htmlarea/plugins/InsertSmiley/smileys/0008.gif";s:4:"10a6";s:46:"htmlarea/plugins/InsertSmiley/smileys/0009.gif";s:4:"1907";s:46:"htmlarea/plugins/InsertSmiley/smileys/0010.gif";s:4:"9ee6";s:46:"htmlarea/plugins/InsertSmiley/smileys/0011.gif";s:4:"ae73";s:46:"htmlarea/plugins/InsertSmiley/smileys/0012.gif";s:4:"f058";s:46:"htmlarea/plugins/InsertSmiley/smileys/0013.gif";s:4:"3ed8";s:46:"htmlarea/plugins/InsertSmiley/smileys/0014.gif";s:4:"a948";s:46:"htmlarea/plugins/InsertSmiley/smileys/0015.gif";s:4:"218d";s:46:"htmlarea/plugins/InsertSmiley/smileys/0016.gif";s:4:"3539";s:46:"htmlarea/plugins/InsertSmiley/smileys/0017.gif";s:4:"ee2e";s:46:"htmlarea/plugins/InsertSmiley/smileys/0018.gif";s:4:"8c66";s:46:"htmlarea/plugins/InsertSmiley/smileys/0019.gif";s:4:"ac36";s:46:"htmlarea/plugins/InsertSmiley/smileys/0020.gif";s:4:"71ef";s:37:"htmlarea/plugins/Language/language.js";s:4:"f923";s:39:"htmlarea/plugins/Language/locallang.xml";s:4:"d16c";s:39:"htmlarea/plugins/QuickTag/locallang.xml";s:4:"2f53";s:38:"htmlarea/plugins/QuickTag/quick-tag.js";s:4:"3efd";s:36:"htmlarea/plugins/QuickTag/tag-lib.js";s:4:"ba71";s:46:"htmlarea/plugins/QuickTag/popups/quicktag.html";s:4:"9f4b";s:43:"htmlarea/plugins/RemoveFormat/locallang.xml";s:4:"aa85";s:46:"htmlarea/plugins/RemoveFormat/remove-format.js";s:4:"cbbb";s:54:"htmlarea/plugins/RemoveFormat/popups/removeformat.html";s:4:"061e";s:42:"htmlarea/plugins/SelectColor/locallang.xml";s:4:"9f9e";s:42:"htmlarea/plugins/SelectFont/select-font.js";s:4:"af22";s:43:"htmlarea/plugins/SpellChecker/locallang.xml";s:4:"20d8";s:51:"htmlarea/plugins/SpellChecker/spell-check-style.css";s:4:"82bd";s:47:"htmlarea/plugins/SpellChecker/spell-check-ui.js";s:4:"7831";s:46:"htmlarea/plugins/SpellChecker/spell-checker.js";s:4:"c8a9";s:67:"htmlarea/plugins/SpellChecker/popups/spell-check-ui-iso-8859-1.html";s:4:"8a95";s:56:"htmlarea/plugins/SpellChecker/popups/spell-check-ui.html";s:4:"61dc";s:40:"htmlarea/plugins/StatusBar/status-bar.js";s:4:"c578";s:44:"htmlarea/plugins/TYPO3Browsers/locallang.xml";s:4:"89b8";s:47:"htmlarea/plugins/TYPO3Browsers/img/download.gif";s:4:"f6d9";s:52:"htmlarea/plugins/TYPO3Browsers/img/external_link.gif";s:4:"9e48";s:63:"htmlarea/plugins/TYPO3Browsers/img/external_link_new_window.gif";s:4:"6e8d";s:52:"htmlarea/plugins/TYPO3Browsers/img/internal_link.gif";s:4:"12b9";s:63:"htmlarea/plugins/TYPO3Browsers/img/internal_link_new_window.gif";s:4:"402a";s:43:"htmlarea/plugins/TYPO3Browsers/img/mail.gif";s:4:"d5a2";s:41:"htmlarea/plugins/TYPO3Color/locallang.xml";s:4:"3d3c";s:41:"htmlarea/plugins/TYPO3Color/typo3color.js";s:4:"5afa";s:46:"htmlarea/plugins/TYPO3HtmlParser/locallang.xml";s:4:"8010";s:52:"htmlarea/plugins/TYPO3HtmlParser/typo3html-parser.js";s:4:"99ea";s:41:"htmlarea/plugins/TYPO3Image/locallang.xml";s:4:"ab27";s:41:"htmlarea/plugins/TYPO3Image/typo3image.js";s:4:"ccc3";s:39:"htmlarea/plugins/TYPO3Link/typo3link.js";s:4:"677d";s:46:"htmlarea/plugins/TableOperations/locallang.xml";s:4:"e7ed";s:52:"htmlarea/plugins/TableOperations/table-operations.js";s:4:"1bbc";s:40:"htmlarea/plugins/TextStyle/locallang.xml";s:4:"ff67";s:40:"htmlarea/plugins/TextStyle/text-style.js";s:4:"7356";s:38:"htmlarea/plugins/UndoRedo/undo-redo.js";s:4:"762b";s:43:"htmlarea/plugins/UserElements/locallang.xml";s:4:"33f9";s:46:"htmlarea/plugins/UserElements/user-elements.js";s:4:"52c7";s:26:"htmlarea/popups/blank.html";s:4:"8d8d";s:32:"htmlarea/popups/editor_help.html";s:4:"398a";s:50:"htmlarea/skins/default/htmlarea-edited-content.css";s:4:"6626";s:35:"htmlarea/skins/default/htmlarea.css";s:4:"5112";s:48:"htmlarea/skins/default/images/definitionItem.gif";s:4:"33ae";s:48:"htmlarea/skins/default/images/definitionList.gif";s:4:"d5d1";s:42:"htmlarea/skins/default/images/ed_about.gif";s:4:"2763";s:42:"htmlarea/skins/default/images/ed_blank.gif";s:4:"0208";s:45:"htmlarea/skins/default/images/ed_color_bg.gif";s:4:"c6e2";s:45:"htmlarea/skins/default/images/ed_color_fg.gif";s:4:"5d7f";s:41:"htmlarea/skins/default/images/ed_copy.gif";s:4:"4f55";s:43:"htmlarea/skins/default/images/ed_custom.gif";s:4:"e7b2";s:40:"htmlarea/skins/default/images/ed_cut.gif";s:4:"1b00";s:43:"htmlarea/skins/default/images/ed_delete.gif";s:4:"926b";s:41:"htmlarea/skins/default/images/ed_help.gif";s:4:"e7fc";s:39:"htmlarea/skins/default/images/ed_hr.gif";s:4:"f384";s:41:"htmlarea/skins/default/images/ed_html.gif";s:4:"fa6e";s:42:"htmlarea/skins/default/images/ed_image.gif";s:4:"c0f0";s:50:"htmlarea/skins/default/images/ed_left_to_right.gif";s:4:"1a1f";s:41:"htmlarea/skins/default/images/ed_link.gif";s:4:"db9a";s:48:"htmlarea/skins/default/images/ed_list_bullet.gif";s:4:"5620";s:45:"htmlarea/skins/default/images/ed_list_num.gif";s:4:"eb1c";s:42:"htmlarea/skins/default/images/ed_paste.gif";s:4:"fbd2";s:41:"htmlarea/skins/default/images/ed_redo.gif";s:4:"e9e8";s:50:"htmlarea/skins/default/images/ed_right_to_left.gif";s:4:"2a38";s:41:"htmlarea/skins/default/images/ed_save.gif";s:4:"07ad";s:47:"htmlarea/skins/default/images/ed_splitblock.gif";s:4:"503e";s:45:"htmlarea/skins/default/images/ed_splitcel.gif";s:4:"2c04";s:41:"htmlarea/skins/default/images/ed_undo.gif";s:4:"b9ba";s:43:"htmlarea/skins/default/images/ed_unlink.gif";s:4:"86c4";s:53:"htmlarea/skins/default/images/fullscreen_maximize.gif";s:4:"2118";s:53:"htmlarea/skins/default/images/fullscreen_minimize.gif";s:4:"91d6";s:46:"htmlarea/skins/default/images/insert_table.gif";s:4:"c01b";s:49:"htmlarea/skins/default/images/language-marker.gif";s:4:"7b48";s:53:"htmlarea/skins/default/images/show-language-marks.gif";s:4:"0bbb";s:52:"htmlarea/skins/default/images/Acronym/ed_acronym.gif";s:4:"1eaa";s:58:"htmlarea/skins/default/images/BlockElements/blockquote.gif";s:4:"34dc";s:54:"htmlarea/skins/default/images/BlockElements/indent.gif";s:4:"57df";s:68:"htmlarea/skins/default/images/BlockElements/insertParagraphAfter.gif";s:4:"e335";s:69:"htmlarea/skins/default/images/BlockElements/insertParagraphBefore.gif";s:4:"9c42";s:61:"htmlarea/skins/default/images/BlockElements/justifyCenter.gif";s:4:"420d";s:59:"htmlarea/skins/default/images/BlockElements/justifyFull.gif";s:4:"b129";s:59:"htmlarea/skins/default/images/BlockElements/justifyLeft.gif";s:4:"3799";s:60:"htmlarea/skins/default/images/BlockElements/justifyRight.gif";s:4:"0662";s:55:"htmlarea/skins/default/images/BlockElements/outdent.gif";s:4:"4786";s:57:"htmlarea/skins/default/images/CharacterMap/ed_charmap.gif";s:4:"af19";s:53:"htmlarea/skins/default/images/FindReplace/ed_find.gif";s:4:"827f";s:61:"htmlarea/skins/default/images/InlineElements/bidioverride.gif";s:4:"f38b";s:52:"htmlarea/skins/default/images/InlineElements/big.gif";s:4:"779b";s:53:"htmlarea/skins/default/images/InlineElements/bold.gif";s:4:"06ac";s:57:"htmlarea/skins/default/images/InlineElements/citation.gif";s:4:"b6eb";s:53:"htmlarea/skins/default/images/InlineElements/code.gif";s:4:"6057";s:59:"htmlarea/skins/default/images/InlineElements/definition.gif";s:4:"692d";s:60:"htmlarea/skins/default/images/InlineElements/deletedtext.gif";s:4:"4eec";s:57:"htmlarea/skins/default/images/InlineElements/emphasis.gif";s:4:"04c9";s:61:"htmlarea/skins/default/images/InlineElements/insertedtext.gif";s:4:"a624";s:55:"htmlarea/skins/default/images/InlineElements/italic.gif";s:4:"be83";s:57:"htmlarea/skins/default/images/InlineElements/keyboard.gif";s:4:"53ac";s:59:"htmlarea/skins/default/images/InlineElements/monospaced.gif";s:4:"78c0";s:58:"htmlarea/skins/default/images/InlineElements/quotation.gif";s:4:"7c62";s:55:"htmlarea/skins/default/images/InlineElements/sample.gif";s:4:"667c";s:54:"htmlarea/skins/default/images/InlineElements/small.gif";s:4:"e013";s:53:"htmlarea/skins/default/images/InlineElements/span.gif";s:4:"0dfa";s:62:"htmlarea/skins/default/images/InlineElements/strikethrough.gif";s:4:"73b1";s:55:"htmlarea/skins/default/images/InlineElements/strong.gif";s:4:"7f50";s:58:"htmlarea/skins/default/images/InlineElements/subscript.gif";s:4:"36c0";s:60:"htmlarea/skins/default/images/InlineElements/superscript.gif";s:4:"40c4";s:58:"htmlarea/skins/default/images/InlineElements/underline.gif";s:4:"dfac";s:57:"htmlarea/skins/default/images/InlineElements/variable.gif";s:4:"da61";s:56:"htmlarea/skins/default/images/InsertSmiley/ed_smiley.gif";s:4:"c331";s:54:"htmlarea/skins/default/images/QuickTag/ed_quicktag.gif";s:4:"a463";s:55:"htmlarea/skins/default/images/RemoveFormat/ed_clean.gif";s:4:"2a0f";s:58:"htmlarea/skins/default/images/SpellChecker/spell-check.gif";s:4:"6e0a";s:59:"htmlarea/skins/default/images/TYPO3ViewHelp/module_help.gif";s:4:"a500";s:61:"htmlarea/skins/default/images/TableOperations/cell-delete.gif";s:4:"f371";s:67:"htmlarea/skins/default/images/TableOperations/cell-insert-after.gif";s:4:"2dd2";s:68:"htmlarea/skins/default/images/TableOperations/cell-insert-before.gif";s:4:"5d13";s:60:"htmlarea/skins/default/images/TableOperations/cell-merge.gif";s:4:"a2d2";s:59:"htmlarea/skins/default/images/TableOperations/cell-prop.gif";s:4:"ca41";s:60:"htmlarea/skins/default/images/TableOperations/cell-split.gif";s:4:"d87c";s:60:"htmlarea/skins/default/images/TableOperations/col-delete.gif";s:4:"da78";s:66:"htmlarea/skins/default/images/TableOperations/col-insert-after.gif";s:4:"80d8";s:67:"htmlarea/skins/default/images/TableOperations/col-insert-before.gif";s:4:"d47d";s:58:"htmlarea/skins/default/images/TableOperations/col-prop.gif";s:4:"b178";s:59:"htmlarea/skins/default/images/TableOperations/col-split.gif";s:4:"eacc";s:62:"htmlarea/skins/default/images/TableOperations/insert_table.gif";s:4:"c1db";s:60:"htmlarea/skins/default/images/TableOperations/row-delete.gif";s:4:"a289";s:66:"htmlarea/skins/default/images/TableOperations/row-insert-above.gif";s:4:"1ef1";s:66:"htmlarea/skins/default/images/TableOperations/row-insert-after.gif";s:4:"5e98";s:66:"htmlarea/skins/default/images/TableOperations/row-insert-under.gif";s:4:"9ad6";s:58:"htmlarea/skins/default/images/TableOperations/row-prop.gif";s:4:"5344";s:59:"htmlarea/skins/default/images/TableOperations/row-split.gif";s:4:"a712";s:60:"htmlarea/skins/default/images/TableOperations/table-prop.gif";s:4:"0a5c";s:63:"htmlarea/skins/default/images/TableOperations/table-restyle.gif";s:4:"9284";s:64:"htmlarea/skins/default/images/TableOperations/toggle-borders.gif";s:4:"50cb";s:54:"htmlarea/skins/default/images/UserElements/ed_user.gif";s:4:"bbb4";s:16:"mod2/acronym.php";s:4:"6dce";s:41:"mod2/class.tx_rtehtmlarea_acronym_mod.php";s:4:"9dce";s:14:"mod2/clear.gif";s:4:"cc11";s:13:"mod2/conf.php";s:4:"1ec2";s:18:"mod2/locallang.xml";s:4:"0cd8";s:21:"mod3/browse_links.php";s:4:"8d69";s:42:"mod3/class.tx_rtehtmlarea_browse_links.php";s:4:"f98e";s:46:"mod3/class.tx_rtehtmlarea_dam_browse_links.php";s:4:"e306";s:14:"mod3/clear.gif";s:4:"cc11";s:13:"mod3/conf.php";s:4:"b2fb";s:18:"mod3/locallang.xml";s:4:"2d51";s:46:"mod4/class.tx_rtehtmlarea_dam_browse_media.php";s:4:"a1e8";s:42:"mod4/class.tx_rtehtmlarea_select_image.php";s:4:"a55f";s:14:"mod4/clear.gif";s:4:"cc11";s:13:"mod4/conf.php";s:4:"8598";s:18:"mod4/locallang.xml";s:4:"8995";s:21:"mod4/select_image.php";s:4:"c6b9";s:34:"mod5/class.tx_rtehtmlarea_user.php";s:4:"f5fc";s:14:"mod5/clear.gif";s:4:"cc11";s:13:"mod5/conf.php";s:4:"7149";s:18:"mod5/locallang.xml";s:4:"7a78";s:13:"mod5/user.php";s:4:"f5b5";s:40:"mod6/class.tx_rtehtmlarea_parse_html.php";s:4:"33c4";s:13:"mod6/conf.php";s:4:"0cab";s:19:"mod6/parse_html.php";s:4:"e04e";s:32:"pi1/class.tx_rtehtmlarea_pi1.php";s:4:"54b2";s:17:"pi1/locallang.xml";s:4:"2e58";s:32:"pi2/class.tx_rtehtmlarea_pi2.php";s:4:"91ea";s:17:"pi2/locallang.xml";s:4:"a0a7";s:32:"pi3/class.tx_rtehtmlarea_pi3.php";s:4:"b2b7";s:36:"res/accessibilityicons/locallang.xml";s:4:"8211";s:39:"res/accessibilityicons/pageTSConfig.txt";s:4:"7e1a";s:39:"res/accessibilityicons/img/download.gif";s:4:"f6d9";s:44:"res/accessibilityicons/img/external_link.gif";s:4:"9e48";s:55:"res/accessibilityicons/img/external_link_new_window.gif";s:4:"6e8d";s:44:"res/accessibilityicons/img/internal_link.gif";s:4:"12b9";s:55:"res/accessibilityicons/img/internal_link_new_window.gif";s:4:"402a";s:35:"res/accessibilityicons/img/mail.gif";s:4:"d5a2";s:29:"res/advanced/pageTSConfig.txt";s:4:"414e";s:29:"res/advanced/userTSConfig.txt";s:4:"8e7a";s:26:"res/contentcss/default.css";s:4:"429f";s:28:"res/contentcss/locallang.xml";s:4:"ec0e";s:39:"res/contentcss/img/red_arrow_bullet.gif";s:4:"82d6";s:25:"res/demo/pageTSConfig.txt";s:4:"146c";s:25:"res/demo/userTSConfig.txt";s:4:"9b82";s:26:"res/image/pageTSConfig.txt";s:4:"9b6f";s:32:"res/indentalign/pageTSConfig.txt";s:4:"14d5";s:25:"res/proc/pageTSConfig.txt";s:4:"d4f8";s:26:"res/style/pageTSConfig.txt";s:4:"e8e7";s:28:"res/typical/pageTSConfig.txt";s:4:"d33d";s:28:"res/typical/userTSConfig.txt";s:4:"9fa6";s:29:"static/clickenlarge/setup.txt";s:4:"5681";}', 'constraints' => array( 'depends' => array( Index: typo3/sysext/rtehtmlarea/ext_localconf.php =================================================================== --- typo3/sysext/rtehtmlarea/ext_localconf.php (révision 6908) +++ typo3/sysext/rtehtmlarea/ext_localconf.php (copie de travail) @@ -2,7 +2,7 @@ /*************************************************************** * Copyright notice * -* (c) 2005-2009 Stanislas Rolland +* (c) 2005-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -68,6 +68,7 @@ // Troubleshooting and experimentation $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['enableDebugMode'] = $_EXTCONF['enableDebugMode'] ? $_EXTCONF['enableDebugMode'] : 0; $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['enableCompressedScripts'] = $_EXTCONF['enableCompressedScripts'] ? $_EXTCONF['enableCompressedScripts'] : 0; +$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['enableCompressedScripts'] = $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['enableCompressedScripts'] && !$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['enableDebugMode']; // Integrating with DAM // DAM browser may be enabled here only for DAM version lower than 1.1 @@ -95,9 +96,6 @@ // Initialize plugin registration array $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins'] = array(); - // Status Bar configuration -$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['StatusBar'] = array(); -$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['StatusBar']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/StatusBar/class.tx_rtehtmlarea_statusbar.php:&tx_rtehtmlarea_statusbar'; // Editor Mode configuration $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['EditorMode'] = array(); $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['EditorMode']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/EditorMode/class.tx_rtehtmlarea_editormode.php:&tx_rtehtmlarea_editormode'; @@ -186,10 +184,6 @@ // Register features that use the style attribute $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['allowStyleAttribute'] = $_EXTCONF['allowStyleAttribute'] ? $_EXTCONF['allowStyleAttribute'] : 0; if ($TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['allowStyleAttribute']) { - $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['DefaultColor'] = array(); - $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['DefaultColor']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/DefaultColor/class.tx_rtehtmlarea_defaultcolor.php:&tx_rtehtmlarea_defaultcolor'; - $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['DefaultColor']['addIconsToSkin'] = 0; - $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['DefaultColor']['disableInFE'] = 0; $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TYPO3Color'] = array(); $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TYPO3Color']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/TYPO3Color/class.tx_rtehtmlarea_typo3color.php:&tx_rtehtmlarea_typo3color'; $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TYPO3Color']['addIconsToSkin'] = 0; @@ -200,6 +194,10 @@ $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['SelectFont']['disableInFE'] = 0; t3lib_extMgm::addPageTSConfig(''); } +$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TextIndicator'] = array(); +$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TextIndicator']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/TextIndicator/class.tx_rtehtmlarea_textindicator.php:&tx_rtehtmlarea_textindicator'; +$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TextIndicator']['addIconsToSkin'] = 0; +$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TextIndicator']['disableInFE'] = 0; $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['InsertSmiley'] = array(); $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['InsertSmiley']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/InsertSmiley/class.tx_rtehtmlarea_insertsmiley.php:&tx_rtehtmlarea_insertsmiley'; $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['InsertSmiley']['addIconsToSkin'] = 0; Index: typo3/sysext/rtehtmlarea/extensions/Acronym/class.tx_rtehtmlarea_acronym.php =================================================================== --- typo3/sysext/rtehtmlarea/extensions/Acronym/class.tx_rtehtmlarea_acronym.php (révision 6908) +++ typo3/sysext/rtehtmlarea/extensions/Acronym/class.tx_rtehtmlarea_acronym.php (copie de travail) @@ -2,7 +2,7 @@ /*************************************************************** * Copyright notice * -* (c) 2008-2009 Stanislas Rolland +* (c) 2008-2010 Stanislas Rolland * All rights reserved * * This script is part of the Typo3 project. The Typo3 project is @@ -118,22 +118,18 @@ $charset = $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] ? $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] : 'iso-8859-1'; $button = 'acronym'; + $acronymArray = array(); + $abbrArray = array(); - $linebreak = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->htmlAreaRTE->ID]['enableCompressedScripts'] ? '' : chr(10); - $JSAcronymArray .= 'acronyms = { ' . $linebreak; - $JSAcronymLanguageArray .= 'acronymLanguage = { ' . $linebreak; - $JSAbbreviationArray .= 'abbreviations = { ' . $linebreak; - $JSAbbreviationLanguageArray .= 'abbreviationLanguage = { ' . $linebreak; - $tableA = 'tx_rtehtmlarea_acronym'; $tableB = 'static_languages'; - $fields = $tableA.'.type,' . $tableA . '.term,' . $tableA . '.acronym,' . $tableB . '.lg_iso_2'; + $fields = $tableA.'.type,' . $tableA . '.term,' . $tableA . '.acronym,' . $tableB . '.lg_iso_2,' . $tableB . '.lg_country_iso_2'; $tableAB = $tableA . ' LEFT JOIN ' . $tableB . ' ON ' . $tableA . '.static_lang_isocode=' . $tableB . '.uid'; $whereClause = '1=1'; // Get all acronyms on pages to which the user has access $lockBeUserToDBmounts = isset($this->thisConfig['buttons.'][$button.'.']['lockBeUserToDBmounts']) ? $this->thisConfig['buttons.'][$button.'.']['lockBeUserToDBmounts'] : $GLOBALS['TYPO3_CONF_VARS']['BE']['lockBeUserToDBmounts']; if (!$GLOBALS['BE_USER']->isAdmin() && $GLOBALS['TYPO3_CONF_VARS']['BE']['lockBeUserToDBmounts'] && $lockBeUserToDBmounts) { - // Temporarily setting alternative web browsing mounts + // Temporarily setting alternative web browsing mounts $altMountPoints = trim($GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.altElementBrowserMountPoints')); if ($altMountPoints) { $savedGroupDataWebmounts = $GLOBALS['BE_USER']->groupData['webmounts']; @@ -182,21 +178,16 @@ $whereClause .= t3lib_BEfunc::deleteClause($tableB); $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, $tableAB, $whereClause); while ($acronymRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { - if( $acronymRow['type'] == 1) { - $JSAcronymArray .= (($this->acronymIndex++)?',':'') . '"' . $GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['term'], $charset) . '":"' . $GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['acronym'], $charset) . '"' . $linebreak; - $JSAcronymLanguageArray .= (($this->acronymIndex-1)?',':'') . '"' . $GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['term'], $charset) . '":"' . $GLOBALS['LANG']->csConvObj->utf8_encode(strtolower($acronymRow['lg_iso_2']), $charset) . '"' . $linebreak; + $item = array($GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['term'], $charset), $GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['acronym'], $charset), $GLOBALS['LANG']->csConvObj->utf8_encode(strtolower($acronymRow['lg_iso_2']), $charset) . ($acronymRow['lg_country_iso_2'] ? ('-' . $acronymRow['lg_country_iso_2']) : '')); + if ($acronymRow['type'] == 1) { + $acronymArray[] = $item; + } else if ($acronymRow['type'] == 2) { + $abbrArray[] = $item; } - if ($acronymRow['type'] == 2) { - $JSAbbreviationArray .= (($this->abbreviationIndex++)?',':'') . '"' . $GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['term'], $charset) . '":"' . $GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['acronym'], $charset) . '"' . $linebreak; - $JSAbbreviationLanguageArray .= (($this->abbreviationIndex-1)?',':'') . '"' . $GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['term'], $charset) . '":"' . $GLOBALS['LANG']->csConvObj->utf8_encode(strtolower($acronymRow['lg_iso_2']), $charset) . '"' . $linebreak; - } } - $JSAcronymArray .= '};' . $linebreak; - $JSAcronymLanguageArray .= '};' . $linebreak; - $JSAbbreviationArray .= '};' . $linebreak; - $JSAbbreviationLanguageArray .= '};' . $linebreak; - - return $JSAcronymArray . $JSAcronymLanguageArray . $JSAbbreviationArray . $JSAbbreviationLanguageArray; + $this->acronymIndex = count($acronymArray); + $this->abbreviationIndex = count($abbrArray); + return 'var acronyms = ' . json_encode($acronymArray) . ';' . 'var abbreviations = ' . json_encode($abbrArray) . ';'; } } Index: typo3/sysext/rtehtmlarea/extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php =================================================================== --- typo3/sysext/rtehtmlarea/extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php (révision 6908) +++ typo3/sysext/rtehtmlarea/extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php (copie de travail) @@ -2,7 +2,7 @@ /*************************************************************** * Copyright notice * -* (c) 2007-2208 Stanislas Rolland +* (c) 2007-2010 Stanislas Rolland * All rights reserved * * This script is part of the Typo3 project. The Typo3 project is @@ -43,7 +43,7 @@ protected $toolbar; // Reference to RTE toolbar array protected $LOCAL_LANG; // Frontend language array - protected $pluginButtons = 'formatblock, indent, outdent, blockquote, insertparagraphbefore, insertparagraphafter, left, center, right, justifyfull, orderedlist, unorderedlist'; + protected $pluginButtons = 'formatblock, indent, outdent, blockquote, insertparagraphbefore, insertparagraphafter, left, center, right, justifyfull, orderedlist, unorderedlist, line'; protected $convertToolbarForHtmlAreaArray = array ( 'formatblock' => 'FormatBlock', 'indent' => 'Indent', @@ -57,6 +57,7 @@ 'justifyfull' => 'JustifyFull', 'orderedlist' => 'InsertOrderedList', 'unorderedlist' => 'InsertUnorderedList', + 'line' => 'InsertHorizontalRule', ); protected $defaultBlockElements = array( @@ -171,16 +172,13 @@ } } // Generating the javascript options - $JSBlockElements = '{ - "'. $first.'" : "none"'; + $JSBlockElements = array(); + $JSBlockElements[] = array($first, 'none'); foreach ($blockElementsOptions as $item => $label) { - $JSBlockElements .= ', - "' . $label . '" : "' . $item . '"'; + $JSBlockElements[] = array($label, $item); } - $JSBlockElements .= '};'; - $registerRTEinJavascriptString .= ' - RTEarea['.$RTEcounter.'].buttons.formatblock.dropDownOptions = '. $JSBlockElements; + RTEarea['.$RTEcounter.'].buttons.formatblock.data = ' . json_encode($JSBlockElements) . ';'; } return $registerRTEinJavascriptString; } Index: typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/htmlarea.css =================================================================== --- typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/htmlarea.css (révision 6908) +++ typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/htmlarea.css (copie de travail) @@ -11,3 +11,4 @@ .htmlarea .toolbar .JustifyFull, .htmlarea-context-menu .JustifyFull {background-image:url("images/justifyFull.gif");} .htmlarea .toolbar .InsertOrderedList, .htmlarea-context-menu .InsertOrderedList {background-image:url("images/insertOrderedList.gif");} .htmlarea .toolbar .InsertUnorderedList, .htmlarea-context-menu .InsertUnorderedList {background-image:url("images/insertUnorderedList.gif");} +.htmlarea .toolbar .InsertHorinzontalRule, .htmlarea-context-menu .InsertHorinzontalRule {background-image:url("images/insertHorizontalRule.gif");} Index: typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/insertHorizontalRule.gif =================================================================== Impossible d'afficher : fichier considéré comme binaire. svn:mime-type = application/octet-stream Modification de propriétés sur typo3\sysext\rtehtmlarea\extensions\BlockElements\skin\images\insertHorizontalRule.gif ___________________________________________________________________ Ajouté : svn:mime-type + application/octet-stream Index: typo3/sysext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php =================================================================== --- typo3/sysext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php (révision 6908) +++ typo3/sysext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php (copie de travail) @@ -2,7 +2,7 @@ /*************************************************************** * Copyright notice * -* (c) 2008-2009 Stanislas Rolland +* (c) 2008-2010 Stanislas Rolland * All rights reserved * * This script is part of the Typo3 project. The Typo3 project is @@ -22,7 +22,7 @@ * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ /** - * About Editor plugin for htmlArea RTE + * Context Menu plugin for htmlArea RTE * * @author Stanislas Rolland * @@ -49,7 +49,6 @@ public function main($parentObject) { return parent::main($parentObject) && !($this->htmlAreaRTE->client['BROWSER'] == 'opera' || $this->thisConfig['disableContextMenu'] || $this->thisConfig['disableRightClick']); } - /** * Return JS configuration of the htmlArea plugins registered by the extension * @@ -59,17 +58,26 @@ * * 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"; + * RTEarea['.$editorId.']["buttons"]["button-id"]["property"] = "value"; */ - public function buildJavascriptConfiguration($RTEcounter) { + public function buildJavascriptConfiguration($editorId) { $registerRTEinJavascriptString = ''; + if (is_array( $this->thisConfig['contextMenu.'])) { + $registerRTEinJavascriptString .= ' + RTEarea['.$editorId.'].contextMenu = new Object();'; + if ($this->thisConfig['contextMenu.']['showButtons']) { + $registerRTEinJavascriptString .= ' + RTEarea['.$editorId.'].contextMenu.showButtons = ' . json_encode(t3lib_div::trimExplode(',', $this->htmlAreaRTE->cleanList(t3lib_div::strtolower($this->thisConfig['contextMenu.']['showButtons'])), 1)) . ';'; + } + if ($this->thisConfig['contextMenu.']['hideButtons']) { + $registerRTEinJavascriptString .= ' + RTEarea['.$editorId.'].contextMenu.hideButtons = ' . json_encode(t3lib_div::trimExplode(',', $this->htmlAreaRTE->cleanList(t3lib_div::strtolower($this->thisConfig['contextMenu.']['hideButtons'])), 1)) . ';'; + } + } return $registerRTEinJavascriptString; } - -} // end of class - +} if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php']) { include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php']); } - ?> \ No newline at end of file Index: typo3/sysext/rtehtmlarea/extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php =================================================================== --- typo3/sysext/rtehtmlarea/extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php (révision 6908) +++ typo3/sysext/rtehtmlarea/extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php (copie de travail) @@ -2,7 +2,7 @@ /*************************************************************** * Copyright notice * -* (c) 2007-2009 Stanislas Rolland +* (c) 2007-2010 Stanislas Rolland * All rights reserved * * This script is part of the Typo3 project. The Typo3 project is @@ -24,7 +24,7 @@ /** * InlineElements plugin for htmlArea RTE * - * @author Stanislas Rolland + * @author Stanislas Rolland * * TYPO3 SVN ID: $Id$ * @@ -200,16 +200,13 @@ } } // Generating the javascript options - $JSInlineElements = '{ - "'. $first.'" : "none"'; + $JSInlineElements = array(); + $JSInlineElements[] = array($first, 'none'); foreach ($inlineElementsOptions as $item => $label) { - $JSInlineElements .= ', - "' . $label . '" : "' . $item . '"'; + $JSInlineElements[] = array($label, $item); } - $JSInlineElements .= '};'; - $registerRTEinJavascriptString .= ' - RTEarea['.$RTEcounter.'].buttons.formattext.dropDownOptions = '. $JSInlineElements; + RTEarea['.$RTEcounter.'].buttons.formattext.data = ' . json_encode($JSInlineElements) . ';'; } return $registerRTEinJavascriptString; } Index: typo3/sysext/rtehtmlarea/extensions/Language/class.tx_rtehtmlarea_language.php =================================================================== --- typo3/sysext/rtehtmlarea/extensions/Language/class.tx_rtehtmlarea_language.php (révision 6908) +++ typo3/sysext/rtehtmlarea/extensions/Language/class.tx_rtehtmlarea_language.php (copie de travail) @@ -2,7 +2,7 @@ /*************************************************************** * Copyright notice * -* (c) 2008-2009 Stanislas Rolland +* (c) 2008-2010 Stanislas Rolland * All rights reserved * * This script is part of the Typo3 project. The Typo3 project is @@ -85,10 +85,14 @@ $first = $GLOBALS['LANG']->getLL('No language mark'); } $languages = array('none' => $first); - $languages = array_merge($languages, $this->getLanguages()); - $languagesJSArray = 'HTMLArea.languageOptions = ' . json_encode(array_flip($languages)); + $languages = array_flip(array_merge($languages, $this->getLanguages())); + $languagesJSArray = array(); + foreach ($languages as $key => $value) { + $languagesJSArray[] = array($key, $value); + } + $languagesJSArray = 'var options = ' . json_encode($languagesJSArray) . ';'; $registerRTEinJavascriptString .= ' - RTEarea['.$RTEcounter.'].buttons.'. $button .'.languagesUrl = "' . $this->htmlAreaRTE->writeTemporaryFile('', 'languages_'.$this->htmlAreaRTE->contentLanguageUid, 'js', $languagesJSArray) . '";'; + RTEarea['.$RTEcounter.'].buttons.'. $button .'.dataUrl = "' . $this->htmlAreaRTE->writeTemporaryFile('', $button . '_' . $this->htmlAreaRTE->contentLanguageUid, 'js', $languagesJSArray) . '";'; } return $registerRTEinJavascriptString; } Index: typo3/sysext/rtehtmlarea/extensions/SelectFont/class.tx_rtehtmlarea_selectfont.php =================================================================== --- typo3/sysext/rtehtmlarea/extensions/SelectFont/class.tx_rtehtmlarea_selectfont.php (révision 6908) +++ typo3/sysext/rtehtmlarea/extensions/SelectFont/class.tx_rtehtmlarea_selectfont.php (copie de travail) @@ -2,7 +2,7 @@ /*************************************************************** * Copyright notice * -* (c) 2008-2009 Stanislas Rolland +* (c) 2008-2010 Stanislas Rolland * All rights reserved * * This script is part of the Typo3 project. The Typo3 project is @@ -133,13 +133,11 @@ // Initializing the items array $items = array(); if ($this->htmlAreaRTE->is_FE()) { - $items['none'] = ' - "' . $GLOBALS['TSFE']->getLLL((($buttonId == 'fontstyle') ? 'Default font' : 'Default size'), $this->LOCAL_LANG) . '" : ""'; + $items['none'] = array($GLOBALS['TSFE']->getLLL((($buttonId == 'fontstyle') ? 'Default font' : 'Default size'), $this->LOCAL_LANG), 'none'); } else { - $items['none'] = ' - "' . ($this->htmlAreaRTE->TCEform->inline->isAjaxCall + $items['none'] = array(($this->htmlAreaRTE->TCEform->inline->isAjaxCall ? $GLOBALS['LANG']->csConvObj->utf8_encode($GLOBALS['LANG']->getLL(($buttonId == 'fontstyle') ? 'Default font' : 'Default size'), $GLOBALS['LANG']->charSet) - : $GLOBALS['LANG']->getLL(($buttonId == 'fontstyle') ? 'Default font' : 'Default size')) . '" : ""'; + : $GLOBALS['LANG']->getLL(($buttonId == 'fontstyle') ? 'Default font' : 'Default size')), 'none'); } // Inserting and localizing default items if ($hideItems != '*') { @@ -155,8 +153,7 @@ } $label = $this->htmlAreaRTE->TCEform->inline->isAjaxCall ? $GLOBALS['LANG']->csConvObj->utf8_encode($label, $GLOBALS['LANG']->charSet) : $label; } - $items[$name] = ' - "' . $label . '" : "' . $this->htmlAreaRTE->cleanList($value) . '"'; + $items[$name] = array($label, $this->htmlAreaRTE->cleanList($value)); } $index++; } @@ -168,35 +165,29 @@ if (in_array($name, $addItems)) { $label = $this->htmlAreaRTE->getPageConfigLabel($conf['name'],0); $label = (!$this->htmlAreaRTE->is_FE() && $this->htmlAreaRTE->TCEform->inline->isAjaxCall) ? $GLOBALS['LANG']->csConvObj->utf8_encode($label, $GLOBALS['LANG']->charSet) : $label; - $items[$name] = ' - "' . $label . '" : "' . $this->htmlAreaRTE->cleanList($conf['value']) . '"'; + $items[$name] = array($label, $this->htmlAreaRTE->cleanList($conf['value'])); } } } // Seting default item if ($this->thisConfig['buttons.'][$buttonId . '.']['defaultItem'] && $items[$this->thisConfig['buttons.'][$buttonId . '.']['defaultItem']]) { - $items['none'] = $items[$this->thisConfig['buttons.'][$buttonId . '.']['defaultItem']]; + $items['none'] = array($items[$this->thisConfig['buttons.'][$buttonId . '.']['defaultItem']][0], 'none'); unset($items[$this->thisConfig['buttons.'][$buttonId . '.']['defaultItem']]); } // Setting the JS list of options - $JSOptions = ''; - $index = 0; + $itemsJSArray = array(); foreach ($items as $option) { - $JSOptions .= ($index ? ',' : '') . $option; - $index++; + $itemsJSArray[] = $option; } - $JSOptions = '{' - . $JSOptions . ' - };'; - + $itemsJSArray = 'var options = ' . json_encode($itemsJSArray) . ';'; + // Adding to button JS configuration if (!is_array( $this->thisConfig['buttons.']) || !is_array($this->thisConfig['buttons.'][$buttonId . '.'])) { $configureRTEInJavascriptString .= ' RTEarea['.$RTEcounter.'].buttons.'. $buttonId .' = new Object();'; } $configureRTEInJavascriptString .= ' - RTEarea['.$RTEcounter.'].buttons.'. $buttonId .'.options = '. $JSOptions; - + RTEarea['.$RTEcounter.'].buttons.'. $buttonId . '.dataUrl = \'' . $this->htmlAreaRTE->writeTemporaryFile('', $buttonId . '_'. $this->htmlAreaRTE->contentLanguageUid, 'js', $itemsJSArray) . '\';'; return $configureRTEInJavascriptString; } } // end of class Index: typo3/sysext/rtehtmlarea/extensions/TableOperations/class.tx_rtehtmlarea_tableoperations.php =================================================================== --- typo3/sysext/rtehtmlarea/extensions/TableOperations/class.tx_rtehtmlarea_tableoperations.php (révision 6908) +++ typo3/sysext/rtehtmlarea/extensions/TableOperations/class.tx_rtehtmlarea_tableoperations.php (copie de travail) @@ -111,18 +111,20 @@ $disabledFieldsets = strtolower(implode(',', $disabledFieldsets)); // Dialogue fieldsets removal configuration - $dialogues = array('table', 'tableproperties', 'rowproperties', 'columnproperties', 'cellproperties'); - foreach ($dialogues as $dialogue) { - if (!is_array( $this->thisConfig['buttons.']) || !is_array( $this->thisConfig['buttons.'][$dialogue.'.'])) { - $registerRTEinJavascriptString .= ' - RTEarea['.$RTEcounter.'].buttons.'.$dialogue.' = new Object(); - RTEarea['.$RTEcounter.'].buttons.'.$dialogue.'.removeFieldsets = "' . $disabledFieldsets . '";'; - } else if ($this->thisConfig['buttons.'][$dialogue.'.']['removeFieldsets']) { - $registerRTEinJavascriptString .= ' - RTEarea['.$RTEcounter.'].buttons.'.$dialogue.'.removeFieldsets += ",' . $disabledFieldsets . '";'; - } else { - $registerRTEinJavascriptString .= ' - RTEarea['.$RTEcounter.'].buttons.'.$dialogue.'.removeFieldsets = ",' . $disabledFieldsets . '";'; + if ($disabledFieldsets) { + $dialogues = array('table', 'tableproperties', 'rowproperties', 'columnproperties', 'cellproperties'); + foreach ($dialogues as $dialogue) { + if (!is_array( $this->thisConfig['buttons.']) || !is_array( $this->thisConfig['buttons.'][$dialogue.'.'])) { + $registerRTEinJavascriptString .= ' + RTEarea['.$RTEcounter.'].buttons.'.$dialogue.' = new Object(); + RTEarea['.$RTEcounter.'].buttons.'.$dialogue.'.removeFieldsets = "' . $disabledFieldsets . '";'; + } else if ($this->thisConfig['buttons.'][$dialogue.'.']['removeFieldsets']) { + $registerRTEinJavascriptString .= ' + RTEarea['.$RTEcounter.'].buttons.'.$dialogue.'.removeFieldsets += ",' . $disabledFieldsets . '";'; + } else { + $registerRTEinJavascriptString .= ' + RTEarea['.$RTEcounter.'].buttons.'.$dialogue.'.removeFieldsets = ",' . $disabledFieldsets . '";'; + } } } Index: typo3/sysext/rtehtmlarea/extensions/TextIndicator/class.tx_rtehtmlarea_textindicator.php =================================================================== --- typo3/sysext/rtehtmlarea/extensions/TextIndicator/class.tx_rtehtmlarea_textindicator.php (révision 0) +++ typo3/sysext/rtehtmlarea/extensions/TextIndicator/class.tx_rtehtmlarea_textindicator.php (révision 0) @@ -0,0 +1,66 @@ + +* 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! +***************************************************************/ +/** + * Text Indicator plugin for htmlArea RTE + * + * @author Stanislas Rolland + * + * TYPO3 SVN ID: $Id: class.tx_rtehtmlarea_textindicator.php 5489 2009-05-23 15:26:20Z ohader $ + * + */ +require_once(t3lib_extMgm::extPath('rtehtmlarea').'class.tx_rtehtmlareaapi.php'); + +class tx_rtehtmlarea_textindicator extends tx_rtehtmlareaapi { + protected $extensionKey = 'rtehtmlarea'; // The key of the extension that is extending htmlArea RTE + protected $pluginName = 'TextIndicator'; // The name of the plugin registered by the extension + protected $relativePathToLocallangFile = ''; // Path to this main locallang file of the extension relative to the extension dir. + protected $relativePathToSkin = 'extensions/TextIndicator/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 = 'textindicator'; + protected $convertToolbarForHtmlAreaArray = array ( + 'textindicator' => 'TextIndicator', + ); + /** + * 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) { + $registerRTEinJavascriptString = ''; + return $registerRTEinJavascriptString; + } +} +if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/TextIndicator/class.tx_rtehtmlarea_textindicator.php']) { + include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/TextIndicator/class.tx_rtehtmlarea_textindicator.php']); +} +?> \ No newline at end of file Index: typo3/sysext/rtehtmlarea/extensions/TextIndicator/skin/htmlarea.css =================================================================== --- typo3/sysext/rtehtmlarea/extensions/TextIndicator/skin/htmlarea.css (révision 0) +++ typo3/sysext/rtehtmlarea/extensions/TextIndicator/skin/htmlarea.css (révision 0) @@ -0,0 +1,9 @@ +/* Selectors for the TextIndicator plugin of htmlArea RTE */ +/* TYPO3 SVN ID: $Id $ */ +.htmlarea .toolbar .indicator { + background-color:white;cursor:default; + width:20px;overflow:hidden; + text-align:center; + border:1px solid ButtonShadow;margin:4px 1px 0px 1px;padding:0px 3px; + float:left; +} Index: typo3/sysext/rtehtmlarea/extensions/TYPO3Color/class.tx_rtehtmlarea_typo3color.php =================================================================== --- typo3/sysext/rtehtmlarea/extensions/TYPO3Color/class.tx_rtehtmlarea_typo3color.php (révision 6908) +++ typo3/sysext/rtehtmlarea/extensions/TYPO3Color/class.tx_rtehtmlarea_typo3color.php (copie de travail) @@ -2,7 +2,7 @@ /*************************************************************** * Copyright notice * -* (c) 2008-2009 Stanislas Rolland +* (c) 2008-2010 Stanislas Rolland * All rights reserved * * This script is part of the Typo3 project. The Typo3 project is @@ -50,7 +50,7 @@ ); public function main($parentObject) { - return parent::main($parentObject) && $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['allowStyleAttribute'] && !$this->thisConfig['disableSelectColor']; + return parent::main($parentObject) && $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['allowStyleAttribute']; } /** @@ -80,53 +80,40 @@ * @return string Javascript configuration of colors */ function buildJSColorsConfig($RTEcounter) { - if ($this->htmlAreaRTE->is_FE()) { $RTEProperties = $this->htmlAreaRTE->RTEsetup; } else { $RTEProperties = $this->htmlAreaRTE->RTEsetup['properties']; } - $configureRTEInJavascriptString = ''; - $configureRTEInJavascriptString .= ' RTEarea['.$RTEcounter.'].disableColorPicker = ' . (trim($this->thisConfig['disableColorPicker']) ? 'true' : 'false') . ';'; - - // Building JS array of configured colors + // Building the array of configured colors if (is_array($RTEProperties['colors.']) ) { $HTMLAreaColorname = array(); foreach ($RTEProperties['colors.'] as $colorName => $conf) { - $colorName=substr($colorName,0,-1); - $colorLabel = $this->htmlAreaRTE->getPageConfigLabel($conf['name']); - $HTMLAreaColorname[$colorName] = ' - [' . $colorLabel . ' , "' . $conf['value'] . '"]'; + $colorName = substr($colorName, 0, -1); + $colorLabel = $this->htmlAreaRTE->getPageConfigLabel($conf['name'], 0); + $colorLabel = (!$this->htmlAreaRTE->is_FE() && $this->htmlAreaRTE->TCEform->inline->isAjaxCall) ? $GLOBALS['LANG']->csConvObj->utf8_encode($colorLabel, $GLOBALS['LANG']->charSet) : $colorLabel; + $HTMLAreaColorname[$colorName] = array($colorLabel, strtoupper(substr($conf['value'], 1, 6))); } } - // Setting the list of colors if specified in the RTE config - if ($this->thisConfig['colors'] ) { - $HTMLAreaJSColors = '['; + if ($this->thisConfig['colors']) { $HTMLAreaColors = t3lib_div::trimExplode(',' , $this->htmlAreaRTE->cleanList($this->thisConfig['colors'])); - $HTMLAreaColorsIndex = 0; + $HTMLAreaJSColors = array(); foreach ($HTMLAreaColors as $colorName) { - if($HTMLAreaColorsIndex && $HTMLAreaColorname[$colorName]) { - $HTMLAreaJSColors .= ','; + if ($HTMLAreaColorname[$colorName]) { + $HTMLAreaJSColors[] = $HTMLAreaColorname[$colorName]; } - $HTMLAreaJSColors .= $HTMLAreaColorname[$colorName]; - $HTMLAreaColorsIndex++; } - $HTMLAreaJSColors .= '];'; $configureRTEInJavascriptString .= ' - RTEarea['.$RTEcounter.'].colors = '. $HTMLAreaJSColors; + RTEarea['.$RTEcounter.'].colors = ' . json_encode($HTMLAreaJSColors) . ';'; } - return $configureRTEInJavascriptString; } - -} // end of class - +} if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/TYPO3Color/class.tx_rtehtmlarea_typo3color.php']) { include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/TYPO3Color/class.tx_rtehtmlarea_typo3color.php']); } - ?> \ No newline at end of file Index: typo3/sysext/rtehtmlarea/extensions/TYPO3Link/class.tx_rtehtmlarea_typo3link.php =================================================================== --- typo3/sysext/rtehtmlarea/extensions/TYPO3Link/class.tx_rtehtmlarea_typo3link.php (révision 6908) +++ typo3/sysext/rtehtmlarea/extensions/TYPO3Link/class.tx_rtehtmlarea_typo3link.php (copie de travail) @@ -87,10 +87,8 @@ $registerRTEinJavascriptString .= ' RTEarea['.$RTEcounter.'].buttons.'. $button .'.classesAnchorUrl = "' . $this->htmlAreaRTE->writeTemporaryFile('', 'classesAnchor_'.$this->htmlAreaRTE->contentLanguageUid, 'js', $this->buildJSClassesAnchorArray()) . '";'; } - if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extensionKey]['plugins'][$this->pluginName]['additionalAttributes']) { - $registerRTEinJavascriptString .= ' - RTEarea['.$RTEcounter.'].buttons.'. $button .'.additionalAttributes = "' . $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extensionKey]['plugins'][$this->pluginName]['additionalAttributes'] .'";'; - } + $registerRTEinJavascriptString .= ' + RTEarea['.$RTEcounter.'].buttons.'. $button .'.additionalAttributes = "external' . ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extensionKey]['plugins'][$this->pluginName]['additionalAttributes'] ? (',' . $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extensionKey]['plugins'][$this->pluginName]['additionalAttributes']) : '') . '";'; } return $registerRTEinJavascriptString; } Index: typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js (copie de travail) @@ -3,7 +3,7 @@ * * (c) 2002-2004 interactivetools.com, inc. * (c) 2003-2004 dynarch.com -* (c) 2004-2009 Stanislas Rolland +* (c) 2004-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -35,71 +35,24 @@ /*************************************************** * GECKO-SPECIFIC FUNCTIONS ***************************************************/ -HTMLArea.prototype.isEditable = function() { +HTMLArea.Editor.prototype.isEditable = function() { return (this._doc.designMode === "on"); }; - /*************************************************** - * MOZILLA/FIREFOX EDIT MODE INITILIZATION - ***************************************************/ - -HTMLArea.prototype._initEditMode = function () { - // We can't set designMode when we are in a hidden TYPO3 tab - // Then we will set it when the tab comes in the front. - var isNested = false; - var allDisplayed = true; - - if (this.nested.sorted && this.nested.sorted.length) { - isNested = true; - allDisplayed = HTMLArea.allElementsAreDisplayed(this.nested.sorted); - } - if (!isNested || allDisplayed) { - try { - this._iframe.style.display = "block"; - this._doc.designMode = "on"; - if (this._doc.queryCommandEnabled("insertbronreturn")) this._doc.execCommand("insertbronreturn", false, this.config.disableEnterParagraphs); - if (this._doc.queryCommandEnabled("enableObjectResizing")) this._doc.execCommand("enableObjectResizing", false, !this.config.disableObjectResizing); - if (this._doc.queryCommandEnabled("enableInlineTableEditing")) this._doc.execCommand("enableInlineTableEditing", false, (this.config.buttons.table && this.config.buttons.table.enableHandles) ? true : false); - if (this._doc.queryCommandEnabled("styleWithCSS")) this._doc.execCommand("styleWithCSS", false, this.config.useCSS); - else if (this._doc.queryCommandEnabled("useCSS")) this._doc.execCommand("useCSS", false, !this.config.useCSS); - } catch(e) { - if (HTMLArea.is_wamcom) { - this._doc.open(); - this._doc.close(); - this._initIframeTimer = window.setTimeout("HTMLArea.initIframe(\'" + this._editorNumber + "\');", 500); - return false; - } - } - } - // When the TYPO3 TCA feature div2tab is used, the editor iframe may become hidden with style.display = "none" - // This breaks the editor in Mozilla/Firefox browsers: the designMode attribute needs to be resetted after the style.display of the containing div is resetted to "block" - // Here we rely on TYPO3 naming conventions for the div id and class name - if (this.nested.sorted && this.nested.sorted.length) { - var nestedObj, listenerFunction; - for (var i=0, length=this.nested.sorted.length; i < length; i++) { - nestedObj = document.getElementById(this.nested.sorted[i]); - listenerFunction = HTMLArea.NestedListener(this, nestedObj, false); - HTMLArea._addEvent(nestedObj, 'DOMAttrModified', listenerFunction); - } - } - return true; -}; - -/*************************************************** * SELECTIONS AND RANGES ***************************************************/ /* * Get the current selection object */ -HTMLArea.prototype._getSelection = function() { +HTMLArea.Editor.prototype._getSelection = function() { return this._iframe.contentWindow.getSelection(); }; /* * Empty the selection object */ -HTMLArea.prototype.emptySelection = function(selection) { +HTMLArea.Editor.prototype.emptySelection = function(selection) { if (HTMLArea.is_safari) { selection.empty(); } else { @@ -113,7 +66,7 @@ /* * Add a range to the selection */ -HTMLArea.prototype.addRangeToSelection = function(selection, range) { +HTMLArea.Editor.prototype.addRangeToSelection = function(selection, range) { if (HTMLArea.is_safari) { selection.setBaseAndExtent(range.startContainer, range.startOffset, range.endContainer, range.endOffset); } else { @@ -124,7 +77,7 @@ /* * Create a range for the current selection */ -HTMLArea.prototype._createRange = function(sel) { +HTMLArea.Editor.prototype._createRange = function(sel) { if (HTMLArea.is_safari) { var range = this._doc.createRange(); if (typeof(sel) == "undefined") { @@ -143,7 +96,9 @@ return range; } } - if (typeof(sel) == "undefined") return this._doc.createRange(); + if (Ext.isEmpty(sel)) { + return this._doc.createRange(); + } try { return sel.getRangeAt(0); } catch(e) { @@ -154,7 +109,7 @@ /* * Select a node AND the contents inside the node */ -HTMLArea.prototype.selectNode = function(node, endPoint) { +HTMLArea.Editor.prototype.selectNode = function(node, endPoint) { this.focusEditor(); var selection = this._getSelection(); var range = this._doc.createRange(); @@ -173,7 +128,7 @@ /* * Select ONLY the contents inside the given node */ -HTMLArea.prototype.selectNodeContents = function(node, endPoint) { +HTMLArea.Editor.prototype.selectNodeContents = function(node, endPoint) { this.focusEditor(); var selection = this._getSelection(); var range = this._doc.createRange(); @@ -185,7 +140,7 @@ this.addRangeToSelection(selection, range); }; -HTMLArea.prototype.rangeIntersectsNode = function(range, node) { +HTMLArea.Editor.prototype.rangeIntersectsNode = function(range, node) { var nodeRange = this._doc.createRange(); try { nodeRange.selectNode(node); @@ -200,7 +155,7 @@ /* * Get the selection type */ -HTMLArea.prototype.getSelectionType = function(selection) { +HTMLArea.Editor.prototype.getSelectionType = function(selection) { // By default set the type to "Text". var type = "Text"; if (!selection) { @@ -222,7 +177,7 @@ /* * Retrieves the selected element (if any), just in the case that a single element (object like and image or a table) is selected. */ -HTMLArea.prototype.getSelectedElement = function(selection) { +HTMLArea.Editor.prototype.getSelectedElement = function(selection) { var selectedElement = null; if (!selection) { var selection = this._getSelection(); @@ -244,7 +199,7 @@ /* * Retrieve the HTML contents of selected block */ -HTMLArea.prototype.getSelectedHTML = function() { +HTMLArea.Editor.prototype.getSelectedHTML = function() { var range = this._createRange(this._getSelection()); if (range.collapsed) return ""; var cloneContents = range.cloneContents(); @@ -257,14 +212,14 @@ /* * Retrieve simply HTML contents of the selected block, IE ignoring control ranges */ -HTMLArea.prototype.getSelectedHTMLContents = function() { +HTMLArea.Editor.prototype.getSelectedHTMLContents = function() { return this.getSelectedHTML(); }; /* * Get the deepest node that contains both endpoints of the current selection. */ -HTMLArea.prototype.getParentElement = function(selection, range) { +HTMLArea.Editor.prototype.getParentElement = function(selection, range) { if (!selection) { var selection = this._getSelection(); } @@ -290,7 +245,7 @@ * @returns null | element * Borrowed from Xinha (is not htmlArea) - http://xinha.gogo.co.nz/ */ -HTMLArea.prototype._activeElement = function(selection) { +HTMLArea.Editor.prototype._activeElement = function(selection) { if (this._selectionEmpty(selection)) { return null; } @@ -305,7 +260,7 @@ /* * Determine if the current selection is empty or not. */ -HTMLArea.prototype._selectionEmpty = function(sel) { +HTMLArea.Editor.prototype._selectionEmpty = function(sel) { if (!sel) return true; return sel.isCollapsed; }; @@ -317,7 +272,7 @@ * in the range boundaries. The advantage of it is that it is possible to * handle DOM mutations when moving back to the bookmark. */ -HTMLArea.prototype.getBookmark = function (range) { +HTMLArea.Editor.prototype.getBookmark = function (range) { // Create the bookmark info (random IDs). var bookmark = { startId : (new Date()).valueOf() + Math.floor(Math.random()*1000) + 'S', @@ -364,7 +319,7 @@ * Get the end point of the bookmark * Adapted from FCKeditor */ -HTMLArea.prototype.getBookmarkNode = function(bookmark, endPoint) { +HTMLArea.Editor.prototype.getBookmarkNode = function(bookmark, endPoint) { if (endPoint) { return this._doc.getElementById(bookmark.startId); } else { @@ -376,7 +331,7 @@ * Move the range to the bookmark * Adapted from FCKeditor */ -HTMLArea.prototype.moveToBookmark = function (bookmark) { +HTMLArea.Editor.prototype.moveToBookmark = function (bookmark) { var startSpan = this.getBookmarkNode(bookmark, true); var endSpan = this.getBookmarkNode(bookmark, false); @@ -406,7 +361,7 @@ /* * Select range */ -HTMLArea.prototype.selectRange = function (range) { +HTMLArea.Editor.prototype.selectRange = function (range) { var selection = this._getSelection(); this.emptySelection(selection); this.addRangeToSelection(selection, range); @@ -421,7 +376,7 @@ * Delete the current selection, if any. * Split the text node, if needed. */ -HTMLArea.prototype.insertNodeAtSelection = function(toBeInserted) { +HTMLArea.Editor.prototype.insertNodeAtSelection = function(toBeInserted) { this.focusEditor(); var range = this._createRange(this._getSelection()); range.deleteContents(); @@ -434,7 +389,7 @@ * Insert HTML source code at the current position. * Delete the current selection, if any. */ -HTMLArea.prototype.insertHTML = function(html) { +HTMLArea.Editor.prototype.insertHTML = function(html) { this.focusEditor(); var fragment = this._doc.createDocumentFragment(); var div = this._doc.createElement("div"); @@ -454,7 +409,7 @@ * * @return void */ -HTMLArea.prototype.wrapWithInlineElement = function(element, selection, range) { +HTMLArea.Editor.prototype.wrapWithInlineElement = function(element, selection, range) { // Sometimes Opera raises a bad boundary points error if (HTMLArea.is_opera) { try { @@ -486,7 +441,7 @@ * * @return void */ -HTMLArea.prototype.cleanAppleStyleSpans = function(node) { +HTMLArea.Editor.prototype.cleanAppleStyleSpans = function(node) { if (HTMLArea.is_safari) { if (node.getElementsByClassName) { var spans = node.getElementsByClassName("Apple-style-span"); @@ -513,62 +468,10 @@ /*************************************************** * EVENTS HANDLERS ***************************************************/ - /* - * TYPO3 hidden tab and inline event listener (gets event calls) - */ -HTMLArea.NestedListener = function (editor,nestedObj,noOpenCloseAction) { - return (function(ev) { - if(!ev) var ev = window.event; - HTMLArea.NestedHandler(ev,editor,nestedObj,noOpenCloseAction); - }); -}; - -/* - * TYPO3 hidden tab and inline event handler (performs actions on event calls) - */ -HTMLArea.NestedHandler = function(ev,editor,nestedObj,noOpenCloseAction) { - window.setTimeout(function() { - var target = (ev.target) ? ev.target : ev.srcElement, styleEvent = true; - // In older versions of Mozilla ev.attrName is not yet set and refering to it causes a non-catchable crash - // We are assuming that this was fixed in Firefox 2.0.0.11 - if (navigator.productSub > 20071127) { - styleEvent = (ev.attrName == "style"); - } - if (target == nestedObj && editor.getMode() == "wysiwyg" && styleEvent && (target.style.display == "" || target.style.display == "block")) { - // Check if all affected nested elements are displayed (style.display!='none'): - if (HTMLArea.allElementsAreDisplayed(editor.nested.sorted)) { - window.setTimeout(function() { - try { - editor._doc.designMode = "on"; - if (editor.config.sizeIncludesToolbar && editor._initialToolbarOffsetHeight != editor._toolbar.offsetHeight) { - editor.sizeIframe(2); - } - if (editor._doc.queryCommandEnabled("insertbronreturn")) editor._doc.execCommand("insertbronreturn", false, editor.config.disableEnterParagraphs); - if (editor._doc.queryCommandEnabled("enableObjectResizing")) editor._doc.execCommand("enableObjectResizing", false, !editor.config.disableObjectResizing); - if (editor._doc.queryCommandEnabled("enableInlineTableEditing")) editor._doc.execCommand("enableInlineTableEditing", false, (editor.config.buttons.table && editor.config.buttons.table.enableHandles) ? true : false); - if (editor._doc.queryCommandEnabled("styleWithCSS")) editor._doc.execCommand("styleWithCSS", false, editor.config.useCSS); - else if (editor._doc.queryCommandEnabled("useCSS")) editor._doc.execCommand("useCSS", false, !editor.config.useCSS); - } catch(e) { - // If an event of a parent tab ("nested tabs") is triggered, the following lines should not be - // processed, because this causes some trouble on all event handlers... - if (!noOpenCloseAction) { - editor._doc.open(); - editor._doc.close(); - } - editor.initIframe(); - } - }, 50); - } - HTMLArea._stopEvent(ev); - } - }, 50); -}; - -/* * Backspace event handler */ -HTMLArea.prototype._checkBackspace = function() { +HTMLArea.Editor.prototype._checkBackspace = function() { if (!HTMLArea.is_safari && !HTMLArea.is_opera) { var self = this; window.setTimeout(function() { @@ -609,7 +512,7 @@ /* * Enter event handler */ -HTMLArea.prototype._checkInsertP = function() { +HTMLArea.Editor.prototype._checkInsertP = function() { var editor = this; this.focusEditor(); var i, left, right, rangeClone, @@ -742,7 +645,8 @@ * Detect emails and urls as they are typed in Mozilla * Borrowed from Xinha (is not htmlArea) - http://xinha.gogo.co.nz/ */ -HTMLArea.prototype._detectURL = function(ev) { +HTMLArea.Editor.prototype._detectURL = function(event) { + var ev = event.browserEvent; var editor = this; var s = this._getSelection(); if (this.getParentElement(s).nodeName.toLowerCase() != 'a') { @@ -754,7 +658,7 @@ a.appendChild(textNode); rightText.data += " "; s.collapse(rightText, rightText.data.length); - HTMLArea._stopEvent(ev); + event.stopEvent(); editor._unLink = function() { var t = a.firstChild; @@ -809,7 +713,7 @@ if(ev.keyCode == 27 || (editor._unlinkOnUndo && ev.ctrlKey && ev.which == 122) ) { if(this._unLink) { this._unLink(); - HTMLArea._stopEvent(ev); + event.stopEvent(); } break; } else if(ev.which || ev.keyCode == 8 || ev.keyCode == 46) { Index: typo3/sysext/rtehtmlarea/htmlarea/htmlarea-ie.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/htmlarea-ie.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/htmlarea-ie.js (copie de travail) @@ -3,7 +3,7 @@ * * (c) 2002-2004 interactivetools.com, inc. * (c) 2003-2004 dynarch.com -* (c) 2004-2009 Stanislas Rolland +* (c) 2004-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -35,7 +35,7 @@ /*************************************************** * IE-SPECIFIC FUNCTIONS ***************************************************/ -HTMLArea.prototype.isEditable = function() { +HTMLArea.Editor.prototype.isEditable = function() { return this._doc.body.contentEditable; }; @@ -45,14 +45,14 @@ /* * Get the current selection object */ -HTMLArea.prototype._getSelection = function() { +HTMLArea.Editor.prototype._getSelection = function() { return this._doc.selection; }; /* * Create a range for the current selection */ -HTMLArea.prototype._createRange = function(sel) { +HTMLArea.Editor.prototype._createRange = function(sel) { if (typeof(sel) == "undefined") { var sel = this._getSelection(); } @@ -65,7 +65,7 @@ /* * Select a node AND the contents inside the node */ -HTMLArea.prototype.selectNode = function(node) { +HTMLArea.Editor.prototype.selectNode = function(node) { this.focusEditor(); this.forceRedraw(); var range = this._doc.body.createTextRange(); @@ -76,7 +76,7 @@ /* * Select ONLY the contents inside the given node */ -HTMLArea.prototype.selectNodeContents = function(node, endPoint) { +HTMLArea.Editor.prototype.selectNodeContents = function(node, endPoint) { this.focusEditor(); this.forceRedraw(); var range = this._doc.body.createTextRange(); @@ -90,7 +90,7 @@ /* * Determine whether the node intersects the range */ -HTMLArea.prototype.rangeIntersectsNode = function(range, node) { +HTMLArea.Editor.prototype.rangeIntersectsNode = function(range, node) { this.focusEditor(); var nodeRange = this._doc.body.createTextRange(); nodeRange.moveToElementText(node); @@ -101,7 +101,7 @@ /* * Retrieve the HTML contents of selected block */ -HTMLArea.prototype.getSelectedHTML = function() { +HTMLArea.Editor.prototype.getSelectedHTML = function() { var sel = this._getSelection(); var range = this._createRange(sel); if (sel.type.toLowerCase() == "control") { @@ -116,7 +116,7 @@ /* * Retrieve simply HTML contents of the selected block, IE ignoring control ranges */ -HTMLArea.prototype.getSelectedHTMLContents = function() { +HTMLArea.Editor.prototype.getSelectedHTMLContents = function() { var sel = this._getSelection(); var range = this._createRange(sel); return range.htmlText; @@ -125,7 +125,7 @@ /* * Get the deepest node that contains both endpoints of the current selection. */ -HTMLArea.prototype.getParentElement = function(selection, range) { +HTMLArea.Editor.prototype.getParentElement = function(selection, range) { if (!selection) { var selection = this._getSelection(); } @@ -150,7 +150,7 @@ * @returns null | element * Borrowed from Xinha (is not htmlArea) - http://xinha.gogo.co.nz/ */ -HTMLArea.prototype._activeElement = function(sel) { +HTMLArea.Editor.prototype._activeElement = function(sel) { if (sel == null) { return null; } @@ -172,7 +172,7 @@ /* * Determine if the current selection is empty or not. */ -HTMLArea.prototype._selectionEmpty = function(selection) { +HTMLArea.Editor.prototype._selectionEmpty = function(selection) { if (!selection || selection.type.toLowerCase() === "none") return true; if (selection.type.toLowerCase() === "text") { return !this._createRange(selection).text; @@ -183,14 +183,14 @@ /* * Get a bookmark */ -HTMLArea.prototype.getBookmark = function (range) { +HTMLArea.Editor.prototype.getBookmark = function (range) { return range.getBookmark(); }; /* * Move the range to the bookmark */ -HTMLArea.prototype.moveToBookmark = function (bookmark) { +HTMLArea.Editor.prototype.moveToBookmark = function (bookmark) { var range = this._createRange(); range.moveToBookmark(bookmark); return range; @@ -199,7 +199,7 @@ /* * Select range */ -HTMLArea.prototype.selectRange = function (range) { +HTMLArea.Editor.prototype.selectRange = function (range) { range.select(); }; /*************************************************** @@ -211,7 +211,7 @@ * Delete the current selection, if any. * Split the text node, if needed. */ -HTMLArea.prototype.insertNodeAtSelection = function(toBeInserted) { +HTMLArea.Editor.prototype.insertNodeAtSelection = function(toBeInserted) { this.insertHTML(toBeInserted.outerHTML); }; @@ -219,7 +219,7 @@ * Insert HTML source code at the current position. * Delete the current selection, if any. */ -HTMLArea.prototype.insertHTML = function(html) { +HTMLArea.Editor.prototype.insertHTML = function(html) { var sel = this._getSelection(); if (sel.type.toLowerCase() == "control") { sel.clear(); @@ -238,7 +238,7 @@ * * @return void */ -HTMLArea.prototype.wrapWithInlineElement = function(element, selection, range) { +HTMLArea.Editor.prototype.wrapWithInlineElement = function(element, selection, range) { var nodeName = element.nodeName; var parent = this.getParentElement(selection, range); var bookmark = this.getBookmark(range); @@ -312,7 +312,7 @@ /* * Handle the backspace event in IE browsers */ -HTMLArea.prototype._checkBackspace = function() { +HTMLArea.Editor.prototype._checkBackspace = function() { var selection = this._getSelection(); var range = this._createRange(selection); if (selection.type == "Control"){ // Deleting or backspacing on a control selection : delete the element Index: typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js (copie de travail) @@ -3,7 +3,7 @@ * * (c) 2002-2004 interactivetools.com, inc. * (c) 2003-2004 dynarch.com -* (c) 2004-2009 Stanislas Rolland +* (c) 2004-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -33,46 +33,22 @@ * * TYPO3 SVN ID: $Id$ */ - + // Avoid re-starting on Ajax request +if (typeof(HTMLArea) == 'undefined') { + // Establish HTMLArea name space +Ext.namespace('HTMLArea.util.TYPO3', 'HTMLArea.util.Tips', 'HTMLArea.util.Color', 'Ext.ux.form', 'Ext.ux.menu', 'Ext.ux.Toolbar'); /*************************************************** - * EDITOR INITIALIZATION AND CONFIGURATION + * BROWSER IDENTIFICATION ***************************************************/ - // Avoid re-starting on Ajax request -if (typeof(HTMLArea) != "function") { - -/* - * HTMLArea object constructor. - */ -HTMLArea = function(textarea, config) { - if (HTMLArea.checkSupportedBrowser()) { - if (typeof(config) == "undefined") this.config = new HTMLArea.Config(); - else this.config = config; - this._htmlArea = null; - this._textArea = textarea; - if (typeof(this._textArea) == "string") { - this._textArea = HTMLArea.getElementById("textarea", this._textArea); - } - this.plugins = {}; - this._timerToolbar = null; - this.doctype = ''; - this.eventHandlers = {}; - } -}; - -/* - * Browser identification - */ HTMLArea.agt = navigator.userAgent.toLowerCase(); -HTMLArea.is_opera = (HTMLArea.agt.indexOf("opera") != -1); +HTMLArea.is_opera = Ext.isOpera; // Some operations require bug fixes provided by Opera 10 (Presto 2.2) -HTMLArea.is_opera9 = HTMLArea.is_opera && HTMLArea.agt.indexOf("Presto/2.1") != -1; -HTMLArea.is_ie = (HTMLArea.agt.indexOf("msie") != -1) && !HTMLArea.is_opera; -HTMLArea.is_safari = (HTMLArea.agt.indexOf("webkit") != -1); -HTMLArea.is_gecko = (navigator.product == "Gecko") || HTMLArea.is_opera; -HTMLArea.is_ff2 = (HTMLArea.agt.indexOf("firefox/2") != -1); -HTMLArea.is_chrome = HTMLArea.is_safari && (HTMLArea.agt.indexOf("chrome") != -1); -// Check on MacOS Wamcom version 1.3, if Mozilla will check earliest supported build in checkSupportedBrowser() -HTMLArea.is_wamcom = (HTMLArea.agt.indexOf("wamcom") != -1) || (HTMLArea.is_gecko && HTMLArea.agt.indexOf("rv:1.3") != -1); +HTMLArea.is_opera9 = Ext.isOpera && HTMLArea.agt.indexOf("Presto/2.1") != -1; +HTMLArea.is_ie = Ext.isIE; +HTMLArea.is_safari = Ext.isWebKit; +HTMLArea.is_gecko = Ext.isGecko || Ext.isOpera || Ext.isWebKit; +HTMLArea.is_ff2 = Ext.isGecko2; +HTMLArea.is_chrome = Ext.isChrome; /* * A log for troubleshooting @@ -86,7 +62,9 @@ } } }; - +/*************************************************** + * SCRIPTS LOADING PROCESS + ***************************************************/ /* * Build stack of scripts to be loaded */ @@ -97,7 +75,7 @@ if (typeof(asynchronous) == "undefined") { var asynchronous = true; } - if (HTMLArea.is_opera) url = _typo3_host_url + url; + if (Ext.isOpera) url = _typo3_host_url + url; if (HTMLArea._compressedScripts && url.indexOf("compressed") == -1) url = url.replace(/\.js$/gi, "_compressed.js"); var scriptInfo = { pluginName : pluginName, @@ -202,8 +180,6 @@ if (typeof(_editor_edited_content_CSS) != "string") _editor_edited_content_CSS = _editor_skin + "htmlarea-edited-content.css"; if (typeof(_editor_lang) == "string") _editor_lang = _editor_lang ? _editor_lang.toLowerCase() : "en"; HTMLArea.editorCSS = _editor_CSS; - // Initialize event cache - HTMLArea._eventCache = HTMLArea._eventCacheConstructor(); // Initialize pending request flag HTMLArea.pendingSynchronousXMLHttpRequest = false; // Set troubleshooting mode @@ -220,8 +196,8 @@ HTMLArea._scripts = []; HTMLArea._scriptLoaded = []; HTMLArea._request = []; - if (HTMLArea.is_gecko) HTMLArea.loadScript(RTEarea[0]["htmlarea-gecko"] ? RTEarea[0]["htmlarea-gecko"] : _editor_url + "htmlarea-gecko.js"); - if (HTMLArea.is_ie) HTMLArea.loadScript(RTEarea[0]["htmlarea-ie"] ? RTEarea[0]["htmlarea-ie"] : _editor_url + "htmlarea-ie.js"); + if (!Ext.isIE) HTMLArea.loadScript(RTEarea[0]["htmlarea-gecko"] ? RTEarea[0]["htmlarea-gecko"] : _editor_url + "htmlarea-gecko.js"); + if (Ext.isIE) HTMLArea.loadScript(RTEarea[0]["htmlarea-ie"] ? RTEarea[0]["htmlarea-ie"] : _editor_url + "htmlarea-ie.js"); for (var i = 0, n = HTMLArea_plugins.length; i < n; i++) { HTMLArea.loadScript(HTMLArea_plugins[i].url, "", HTMLArea_plugins[i].asynchronous); } @@ -247,10 +223,10 @@ if (success) { HTMLArea.checkInitialLoad(); } else { - if (HTMLArea.is_ie) window.setTimeout('alert(HTMLArea.I18N.msg["ActiveX-required"]);', 200); + if (Ext.isIE) window.setTimeout('alert(HTMLArea.I18N.msg["ActiveX-required"]);', 200); } } else { - if (HTMLArea.is_ie) alert(HTMLArea.I18N.msg["ActiveX-required"]); + if (Ext.isIE) alert(HTMLArea.I18N.msg["ActiveX-required"]); } } }; @@ -259,25 +235,17 @@ * Compile some regular expressions */ HTMLArea.RE_tagName = /(<\/|<)\s*([^ \t\n>]+)/ig; -HTMLArea.RE_doctype = /()\n?/i; HTMLArea.RE_head = /((.|\n)*?)<\/head>/i; HTMLArea.RE_body = /((.|\n)*?)<\/body>/i; HTMLArea.Reg_body = new RegExp("<\/?(body)[^>]*>", "gi"); HTMLArea.reservedClassNames = /htmlarea/; HTMLArea.RE_email = /([0-9a-z]+([a-z0-9_-]*[0-9a-z])*){1}(\.[0-9a-z]+([a-z0-9_-]*[0-9a-z])*)*@([0-9a-z]+([a-z0-9_-]*[0-9a-z])*\.)+[a-z]{2,9}/i; HTMLArea.RE_url = /(https?:\/\/)?(([a-z0-9_]+:[a-z0-9_]+@)?[a-z0-9_-]{2,}(\.[a-z0-9_-]{2,})+\.[a-z]{2,5}(:[0-9]+)?(\/\S+)*)/i; - -/* - * Editor configuration object constructor - */ - -HTMLArea.Config = function () { - this.width = "auto"; - this.height = "auto"; - // whether the toolbar should be included in the size or not. - this.sizeIncludesToolbar = true; - // if true then HTMLArea will retrieve the full HTML, starting with the tag. - this.fullPage = false; +/*************************************************** + * EDITOR CONFIGURATION + ***************************************************/ +HTMLArea.Config = function (editorId) { + this.editorId = editorId; // if the site is secure, create a secure iframe this.useHTTPS = false; // for Mozilla @@ -300,7 +268,9 @@ this.customTags = null; // BaseURL included in the iframe document this.baseURL = document.baseURI || document.URL; - if(this.baseURL && this.baseURL.match(/(.*)\/([^\/]+)/)) this.baseURL = RegExp.$1 + "/"; + if (this.baseURL && this.baseURL.match(/(.*)\/([^\/]+)/)) { + this.baseURL = RegExp.$1 + "/"; + } // URL-s this.imgURL = "images/"; this.popupURL = "popups/"; @@ -308,1089 +278,2035 @@ this.documentType = '\r'; - - this.btnList = { - InsertHorizontalRule: ["Horizontal Rule", "ed_hr.gif",false, function(editor) {editor.execCommand("InsertHorizontalRule");}], - SelectAll: ["SelectAll", "", true, function(editor) {editor.execCommand("SelectAll");}, null, true, false] + this.resizable = TYPO3.settings.textareaResize; + this.maxHeight = TYPO3.settings.textareaMaxHeight; + // Hold the configuration of buttons and hot keys registered by plugins + this.buttonsConfig = {}; + this.hotKeyList = {}; + // Default configurations for toolbar items + this.configDefaults = { + all: { + xtype: 'htmlareabutton', + disabledClass: 'buttonDisabled', + textMode: false, + selection: false, + dialog: false, + hidden: false, + hideMode: 'display' + }, + htmlareabutton: { + cls: 'button', + overCls: 'buttonHover' + }, + htmlareacombo: { + cls: 'select', + typeAhead: true, + triggerAction: 'all', + editable: !Ext.isIE, + validationEvent: false, + validateOnBlur: false, + submitValue: false, + forceSelection: true, + mode: 'local', + storeFields: [ { name: 'text'}, { name: 'value'}], + valueField: 'value', + displayField: 'text', + labelSeparator: '', + hideLabel: true, + tpl: '
{text}
' + } }; - // Default hotkeys - this.hotKeyList = { - a: { cmd: "SelectAll", action: null} - }; - - // Initialize tooltips from the I18N module, generate correct image path - for (var buttonId in this.btnList) { - if (this.btnList.hasOwnProperty(buttonId)) { - var btn = this.btnList[buttonId]; - if (typeof(HTMLArea.I18N.tooltips[buttonId.toLowerCase()]) !== "undefined") { - btn[0] = HTMLArea.I18N.tooltips[buttonId.toLowerCase()]; - } - if (typeof(btn[1]) === "string") { - btn[1] = _editor_skin + this.imgURL + btn[1]; - } else { - btn[1][0] = _editor_skin + this.imgURL + btn[1][0]; - } +}; +HTMLArea.Config = Ext.extend(HTMLArea.Config, { + /** + * Registers a button for inclusion in the toolbar, adding some standard configuration properties for the ExtJS widgets + * + * @param object buttonConfiguration: the configuration object of the button: + * id : unique id for the button + * tooltip : tooltip for the button + * textMode : enable in text mode + * context : disable if not inside one of listed elements + * hidden : hide in menu and show only in context menu + * selection : disable if there is no selection + * hotkey : hotkey character + * dialog : if true, the button opens a dialogue + * dimensions : the opening dimensions object of the dialogue window: { width: nn, height: mm } + * and potentially other ExtJS config properties (will be forwarded) + * + * @return boolean true if the button was successfully registered + */ + registerButton: function (config) { + config.itemId = config.id; + if (Ext.type(this.buttonsConfig[config.id])) { + HTMLArea._appendToLog('[HTMLArea.Config::registerButton]: A toolbar item with the same Id: ' + config.id + ' already exists and will be overidden.'); } + // Apply defaults + config = Ext.applyIf(config, this.configDefaults['all']); + config = Ext.applyIf(config, this.configDefaults[config.xtype]); + // Set some additional properties + switch (config.xtype) { + case 'htmlareacombo': + // Create combo store + config.store = new Ext.data.ArrayStore({ + autoDestroy: true, + fields: config.storeFields, + data: config.options + }); + config.hideLabel = Ext.isEmpty(config.fieldLabel); + config.helpTitle = config.tooltip; + break; + default: + config.iconCls = config.id; + break; + } + config.cmd = config.id; + config.tooltip = { title: config.tooltip }; + this.buttonsConfig[config.id] = config; + return true; + }, + /* + * Register a hotkey with the editor configuration. + */ + registerHotKey: function (hotKeyConfiguration) { + if (Ext.isDefined(this.hotKeyList[hotKeyConfiguration.id])) { + HTMLArea._appendToLog('[HTMLArea.Config::registerHotKey]: A hotkey with the same key ' + hotKeyConfiguration.id + ' already exists and will be overidden.'); + } + if (Ext.isDefined(hotKeyConfiguration.cmd) && !Ext.isEmpty(hotKeyConfiguration.cmd) && Ext.isDefined(this.buttonsConfig[hotKeyConfiguration.cmd])) { + this.hotKeyList[hotKeyConfiguration.id] = hotKeyConfiguration; + HTMLArea._appendToLog('[HTMLArea.Config::registerHotKey]: A hotkey with key ' + hotKeyConfiguration.id + ' was registered for toolbar item ' + hotKeyConfiguration.cmd + '.'); + return true; + } else { + HTMLArea._appendToLog('[HTMLArea.Config::registerHotKey]: A hotkey with key ' + hotKeyConfiguration.id + ' could not be registered because toolbar item with id ' + hotKeyConfiguration.cmd + ' was not registered.'); + return false; + } + }, + /* + * Get the configured document type for dialogue windows + */ + getDocumentType: function () { + return this.documentType; } - this.customSelects = {}; -}; - -/* - * Register a new button with the configuration. - * It can be called with all arguments, or with only one (first one). When called with - * only one argument it must be an object with the following properties: - * id, tooltip, image, textMode, action, context. Examples: - * - * 1. config.registerButton("my-hilite", "Hilite text", "my-hilite.gif", false, function(editor) {...}, context); - * 2. config.registerButton({ - * id : "my-hilite", // Unique id for the button - * tooltip : "Hilite text", // the tooltip - * image : "my-hilite.gif", // image to be displayed in the toolbar - * textMode : false, // disabled in text mode - * action : function(editor) { // called when the button is clicked - * editor.surroundHTML('', ''); - * }, - * context : "p" // will be disabled if not inside a

element - * hide : false // hide in menu and show only in context menu - * selection : false // will be disabled if there is no selection - * dialog : true // the button opens a dialogue - * dimensions : { width: nn, height: mm } // opening dimensions of the dialogue window - * }); - */ -HTMLArea.Config.prototype.registerButton = function(id,tooltip,image,textMode,action,context,hide,selection, dialog, dimensions) { - var buttonId; - switch (typeof(id)) { - case "string": buttonId = id; break; - case "object": buttonId = id.id; break; - default: HTMLArea._appendToLog("[HTMLArea.Config::registerButton]: invalid arguments"); - return false; - } - if (typeof(this.customSelects[buttonId]) !== "undefined") { - HTMLArea._appendToLog("[HTMLArea.Config::registerButton]: A dropdown with the same Id: " + buttonId + " already exists."); - return false; - } - if (typeof(this.btnList[buttonId]) !== "undefined") { - HTMLArea._appendToLog("[HTMLArea.Config::registerButton]: A button with the same Id: " + buttonId + " already exists and will be overidden."); - } - switch (typeof(id)) { - case "string": - if (typeof(hide) === "undefined") var hide = false; - if (typeof(selection) === "undefined") var selection = false; - if (typeof(dialog) === "undefined") var dialog = true; - this.btnList[id] = [tooltip, image, textMode, action, context, hide, selection, dialog, dimensions]; - break; - case "object": - if (typeof(id.hide) === "undefined") id.hide = false; - if (typeof(id.selection) === "undefined") id.selection = false; - if (typeof(id.dialog) === "undefined") id.dialog = true; - this.btnList[id.id] = [id.tooltip, id.image, id.textMode, id.action, id.context, id.hide, id.selection, id.dialog, id.dimensions]; - break; - } - return true; -}; - -/* - * Register a dropdown box with the editor configuration. - */ -HTMLArea.Config.prototype.registerDropdown = function(dropDownConfiguration) { - if (typeof(this.customSelects[dropDownConfiguration.id]) != "undefined") { - HTMLArea._appendToLog("[HTMLArea.Config::registerDropdown]: A dropdown with the same ID " + dropDownConfiguration.id + " already exists and will be overidden."); - } - if (typeof(this.btnList[dropDownConfiguration.id]) != "undefined") { - HTMLArea._appendToLog("ERROR [HTMLArea.Config::registerDropdown]: A button with the same ID " + dropDownConfiguration.id + " already exists."); - return false; - } - this.customSelects[dropDownConfiguration.id] = dropDownConfiguration; - return true; -}; - -/* - * Register a hotkey with the editor configuration. - */ -HTMLArea.Config.prototype.registerHotKey = function(hotKeyConfiguration) { - if (typeof(this.hotKeyList[hotKeyConfiguration.id]) != "undefined") { - HTMLArea._appendToLog("[HTMLArea.Config::registerHotKey]: A hotkey with the same key " + hotKeyConfiguration.id + " already exists and will be overidden."); - } - this.hotKeyList[hotKeyConfiguration.id] = hotKeyConfiguration; - return true; -}; - -HTMLArea.Config.prototype.getDocumentType = function () { - return this.documentType; -}; - +}); /*************************************************** - * EDITOR FRAMEWORK + * TOOLBAR COMPONENTS ***************************************************/ /* - * Update the state of a toolbar element. - * This function is member of a toolbar element object, unnamed object created by createButton or createSelect functions. + * Ext.ux.HTMLAreaButton extends Ext.Button */ -HTMLArea.setButtonStatus = function(id,newval) { - var oldval = this[id]; - var el = document.getElementById(this.elementId); - if (oldval != newval) { - switch (id) { - case "enabled": - if (newval) { - if (!HTMLArea.is_wamcom) { - HTMLArea._removeClass(el, "buttonDisabled"); - HTMLArea._removeClass(el.parentNode, "buttonDisabled"); - } - el.disabled = false; - } else { - if (!HTMLArea.is_wamcom) { - HTMLArea._addClass(el, "buttonDisabled"); - HTMLArea._addClass(el.parentNode, "buttonDisabled"); - } - el.disabled = true; +Ext.ux.HTMLAreaButton = Ext.extend(Ext.Button, { + /* + * Component initialization + */ + initComponent: function () { + Ext.ux.HTMLAreaButton.superclass.initComponent.call(this); + this.addEvents( + /* + * @event hotkey + * Fires when the button hotkey is pressed + */ + 'hotkey' + ); + this.addListener({ + afterrender: { + fn: this.initEventListeners, + single: true + } + }); + }, + /* + * Initialize listeners + */ + initEventListeners: function () { + this.addListener({ + click: { + fn: this.onButtonClick + }, + hotkey: { + fn: this.onHotKey + } + }); + // Monitor toolbar updates in order to refresh the state of the button + this.mon(this.getToolbar(), 'update', this.onUpdateToolbar, this); + }, + /* + * Get a reference to the editor + */ + getEditor: function() { + return RTEarea[this.ownerCt.editorId].editor; + }, + /* + * Get a reference to the toolbar + */ + getToolbar: function() { + return this.ownerCt; + }, + /* + * Add properties and function to set button active or not depending on current selection + */ + inactive: true, + activeClass: 'buttonActive', + setInactive: function (inactive) { + this.inactive = inactive; + return inactive ? this.removeClass(this.activeClass) : this.addClass(this.activeClass); + }, + /* + * Determine if the button should be enabled based on the current selection and context configuration property + */ + isInContext: function (mode, selectionEmpty, ancestors) { + var editor = this.getEditor(); + var inContext = true; + if (mode === 'wysiwyg' && this.context) { + var attributes = [], + contexts = []; + if (/(.*)\[(.*?)\]/.test(this.context)) { + contexts = RegExp.$1.split(','); + attributes = RegExp.$2.split(','); + } else { + contexts = this.context.split(','); + } + contexts = new RegExp( '^(' + contexts.join('|') + ')$', 'i'); + var matchAny = contexts.test('*'); + Ext.each(ancestors, function (ancestor) { + inContext = matchAny || contexts.test(ancestor.nodeName); + if (inContext) { + Ext.each(attributes, function (attribute) { + inContext = eval("ancestor." + attribute); + return inContext; + }); } - break; - case "active": - if (newval) { - HTMLArea._addClass(el, "buttonPressed"); - HTMLArea._addClass(el.parentNode, "buttonPressed"); - el.active = true; - } else { - HTMLArea._removeClass(el, "buttonPressed"); - HTMLArea._removeClass(el.parentNode, "buttonPressed"); - el.active = false; - } - break; + return !inContext; + }); } - this[id] = newval; - } -}; - -/* - * Create a new line in the toolbar - */ -HTMLArea.newLine = function(toolbar) { - tb_line = document.createElement("ul"); - tb_line.className = "tb-line"; - toolbar.appendChild(tb_line); - return tb_line; -}; - -/* - * Add a toolbar element to the current line or group - */ -HTMLArea.addTbElement = function(element, tb_line, first_cell_on_line) { - var tb_cell = document.createElement("li"); - if (first_cell_on_line) tb_cell.className = "tb-first-cell"; - else tb_cell.className = "tb-cell"; - HTMLArea._addClass(tb_cell, element.className); - tb_line.appendChild(tb_cell); - tb_cell.appendChild(element); - if(element.style.display == "none") { - tb_cell.style.display = "none"; - if(HTMLArea._hasClass(tb_cell.previousSibling, "separator")) tb_cell.previousSibling.style.display = "none"; - } - return false; -}; - -/* - * Create a new group on the current line - */ -HTMLArea.addTbGroup = function(tb_line, first_cell_on_line) { - var tb_group = document.createElement("ul"); - tb_group.className = "tb-group"; - HTMLArea.addTbElement(tb_group, tb_line, first_cell_on_line); - return tb_group; -}; - -/* - * Create a combo box and add it to the toolbar - */ -HTMLArea.prototype.createSelect = function(txt,tb_line,first_cell_on_line,labelObj) { - var options = null, - cmd = null, - context = null, - tooltip = "", - newObj = { - created : false, - el : null, - first : first_cell_on_line, - labelUsed : false - }; - - cmd = txt; - var dropdown = this.config.customSelects[cmd]; - if (typeof(dropdown) != "undefined") { - options = dropdown.options; - context = dropdown.context; - if (typeof(dropdown.tooltip) != "undefined") tooltip = dropdown.tooltip; - } - if (options) { - newObj["el"] = document.createElement("select"); - newObj["el"].className = "select"; - newObj["el"].title = tooltip; - newObj["el"].id = this._editorNumber + "-" + txt; - newObj["first"] = HTMLArea.addTbElement(newObj["el"], tb_line, first_cell_on_line); - var obj = { - name : txt, // field name - elementId : newObj["el"].id, // unique id for the UI element - enabled : true, // is it enabled? - text : false, // enabled in text mode? - cmd : cmd, // command ID - state : HTMLArea.setButtonStatus, // for changing state - context : context, - editorNumber : this._editorNumber - }; - this._toolbarObjects[txt] = obj; - newObj["el"]._obj = obj; - if (labelObj["labelRef"]) { - labelObj["el"].htmlFor = newObj["el"].id; - newObj["labelUsed"] = true; + return inContext && (!this.selection || !selectionEmpty); + }, + /* + * Handler invoked when the button is clicked + */ + onButtonClick: function (button, event, key) { + if (!this.disabled) { + if (!this.plugins[this.action](this.getEditor(), key || this.itemId) && event) { + event.stopEvent(); + } + if (Ext.isOpera) { + this.getEditor().focus(); + } + if (this.dialog) { + this.setDisabled(true); + } else { + this.getToolbar().update(); + } } - HTMLArea._addEvent(newObj["el"], "change", HTMLArea.toolBarButtonHandler); - - for (var i in options) { - if (options.hasOwnProperty(i)) { - var op = document.createElement("option"); - op.innerHTML = i; - op.value = options[i]; - newObj["el"].appendChild(op); + return false; + }, + /* + * Handler invoked when the hotkey configured for this button is pressed + */ + onHotKey: function (key, event) { + return this.onButtonClick(this, event, key); + }, + /* + * Handler invoked when the toolbar is updated + */ + onUpdateToolbar: function (mode, selectionEmpty, ancestors, endPointsInSameBlock) { + this.setDisabled(mode === 'textmode' && !this.textMode); + if (!this.disabled) { + if (!this.noAutoUpdate) { + this.setDisabled(!this.isInContext(mode, selectionEmpty, ancestors)); } + this.plugins['onUpdateToolbar'](this, mode, selectionEmpty, ancestors, endPointsInSameBlock); } - - newObj["created"] = true; } - - return newObj; -}; - +}); +Ext.reg('htmlareabutton', Ext.ux.HTMLAreaButton); /* - * Create a button and add it to the toolbar + * Ext.ux.Toolbar.HTMLAreaToolbarText extends Ext.Toolbar.TextItem */ -HTMLArea.prototype.createButton = function (txt,tb_line,first_cell_on_line,labelObj) { - var btn = null, - newObj = { - created : false, - el : null, - first : first_cell_on_line, - labelUsed : false - }; - - switch (txt) { - case "separator": - newObj["el"] = document.createElement("div"); - newObj["el"].className = "separator"; - newObj["first"] = HTMLArea.addTbElement(newObj["el"], tb_line, first_cell_on_line); - newObj["created"] = true; - break; - case "space": - newObj["el"] = document.createElement("div"); - newObj["el"].className = "space"; - newObj["el"].innerHTML = " "; - newObj["first"] = HTMLArea.addTbElement(newObj["el"], tb_line, first_cell_on_line); - newObj["created"] = true; - break; - case "TextIndicator": - newObj["el"] = document.createElement("div"); - newObj["el"].appendChild(document.createTextNode("A")); - newObj["el"].className = "indicator"; - newObj["el"].title = HTMLArea.I18N.tooltips.textindicator; - newObj["el"].id = this._editorNumber + "-" + txt; - newObj["first"] = HTMLArea.addTbElement(newObj["el"], tb_line, first_cell_on_line); - var obj = { - name : txt, - elementId : newObj["el"].id, - enabled : true, - active : false, - text : false, - cmd : "TextIndicator", - state : HTMLArea.setButtonStatus - }; - this._toolbarObjects[txt] = obj; - newObj["created"] = true; - break; - default: - btn = this.config.btnList[txt]; - } - if(!newObj["created"] && btn) { - newObj["el"] = document.createElement("button"); - newObj["el"].title = btn[0]; - newObj["el"].className = "button"; - newObj["el"].id = this._editorNumber + "-" + txt; - if (btn[5]) newObj["el"].style.display = "none"; - newObj["first"] = HTMLArea.addTbElement(newObj["el"], tb_line, first_cell_on_line); - var obj = { - name : txt, // the button name - elementId : newObj["el"].id, // unique id for the UI element - enabled : true, // is it enabled? - active : false, // is it pressed? - text : btn[2], // enabled in text mode? - cmd : btn[3], // the function to be invoked - state : HTMLArea.setButtonStatus, // for changing state - context : btn[4] || null, // enabled in a certain context? - selection : btn[6], // disabled when no selection? - editorNumber : this._editorNumber - }; - this._toolbarObjects[txt] = obj; - newObj["el"]._obj = obj; - if (labelObj["labelRef"]) { - labelObj["el"].htmlFor = newObj["el"].id; - newObj["labelUsed"] = true; +Ext.ux.Toolbar.HTMLAreaToolbarText = Ext.extend(Ext.Toolbar.TextItem, { + /* + * Constructor + */ + initComponent: function () { + Ext.ux.Toolbar.HTMLAreaToolbarText.superclass.initComponent.call(this); + this.addListener({ + afterrender: { + fn: this.initEventListeners, + single: true + } + }); + }, + /* + * Initialize listeners + */ + initEventListeners: function () { + // Monitor toolbar updates in order to refresh the state of the button + this.mon(this.getToolbar(), 'update', this.onUpdateToolbar, this); + }, + /* + * Get a reference to the editor + */ + getEditor: function() { + return RTEarea[this.ownerCt.editorId].editor; + }, + /* + * Get a reference to the toolbar + */ + getToolbar: function() { + return this.ownerCt; + }, + /* + * Handler invoked when the toolbar is updated + */ + onUpdateToolbar: function (mode, selectionEmpty, ancestors, endPointsInSameBlock) { + this.setDisabled(mode === 'textmode' && !this.textMode); + if (!this.disabled) { + this.plugins['onUpdateToolbar'](this, mode, selectionEmpty, ancestors, endPointsInSameBlock); } - HTMLArea._addEvents(newObj["el"],["mouseover", "mouseout", "mousedown", "click"], HTMLArea.toolBarButtonHandler); - newObj["el"].className += " " + txt; - newObj["created"] = true; } - return newObj; -}; - +}); +Ext.reg('htmlareatoolbartext', Ext.ux.Toolbar.HTMLAreaToolbarText); /* - * Create a label and add it to the toolbar + * Ext.ux.form.HTMLAreaCombo extends Ext.form.ComboBox */ -HTMLArea.createLabel = function(txt,tb_line,first_cell_on_line) { - var newObj = { - created : false, - el : null, - labelRef : false, - first : first_cell_on_line - }; - if (/^([IT])\[(.*?)\]/.test(txt)) { - var l7ed = RegExp.$1 == "I"; // localized? - var label = RegExp.$2; - if (l7ed) label = HTMLArea.I18N.dialogs[label]; - newObj["el"] = document.createElement("label"); - newObj["el"].className = "label"; - newObj["el"].innerHTML = label; - newObj["labelRef"] = true; - newObj["created"] = true; - newObj["first"] = HTMLArea.addTbElement(newObj["el"], tb_line, first_cell_on_line); - } - return newObj; -}; - -/* - * Create the toolbar and append it to the _htmlarea. - */ -HTMLArea.prototype._createToolbar = function () { - var j, k, code, n = this.config.toolbar.length, m, - tb_line = null, tb_group = null, - first_cell_on_line = true, - labelObj = new Object(), - tbObj = new Object(); - - var toolbar = document.createElement("div"); - this._toolbar = toolbar; - toolbar.className = "toolbar"; - toolbar.unselectable = "1"; - this._toolbarObjects = new Object(); - - for (j = 0; j < n; ++j) { - tb_line = HTMLArea.newLine(toolbar); - if(!this.config.keepButtonGroupTogether) HTMLArea._addClass(tb_line, "free-float"); - first_cell_on_line = true; - tb_group = null; - var group = this.config.toolbar[j]; - m = group.length; - for (k = 0; k < m; ++k) { - code = group[k]; - if (code == "linebreak") { - tb_line = HTMLArea.newLine(toolbar); - if(!this.config.keepButtonGroupTogether) HTMLArea._addClass(tb_line, "free-float"); - first_cell_on_line = true; - tb_group = null; - } else { - if ((code == "separator" || first_cell_on_line) && this.config.keepButtonGroupTogether) { - tb_group = HTMLArea.addTbGroup(tb_line, first_cell_on_line); - first_cell_on_line = false; - } - created = false; - if (/^([IT])\[(.*?)\]/.test(code)) { - labelObj = HTMLArea.createLabel(code, (tb_group?tb_group:tb_line), first_cell_on_line); - created = labelObj["created"] ; - first_cell_on_line = labelObj["first"]; - } - if (!created) { - tbObj = this.createButton(code, (tb_group?tb_group:tb_line), first_cell_on_line, labelObj); - created = tbObj["created"]; - first_cell_on_line = tbObj["first"]; - if(tbObj["labelUsed"]) labelObj["labelRef"] = false; - } - if (!created) { - tbObj = this.createSelect(code, (tb_group?tb_group:tb_line), first_cell_on_line, labelObj); - created = tbObj["created"]; - first_cell_on_line = tbObj["first"]; - if(tbObj["labelUsed"]) labelObj["labelRef"] = false; - } - if (!created) HTMLArea._appendToLog("ERROR [HTMLArea::createToolbar]: Unknown toolbar item: " + code); +Ext.ux.form.HTMLAreaCombo = Ext.extend(Ext.form.ComboBox, { + /* + * Constructor + */ + initComponent: function () { + Ext.ux.form.HTMLAreaCombo.superclass.initComponent.call(this); + this.addEvents( + /* + * @event hotkey + * Fires when a hotkey configured for the combo is pressed + */ + 'hotkey' + ); + this.addListener({ + afterrender: { + fn: this.initEventListeners, + single: true } + }); + }, + /* + * Initialize listeners + */ + initEventListeners: function () { + this.addListener({ + select: { + fn: this.onComboSelect + }, + specialkey: { + fn: this.onSpecialKey + }, + hotkey: { + fn: this.onHotKey + } + }); + // Monitor toolbar updates in order to refresh the state of the combo + this.mon(this.getToolbar(), 'update', this.onUpdateToolbar, this); + // Monitor framework becoming ready + if (Ext.isIE) { + this.mon(this.getToolbar().ownerCt, 'frameworkready', this.onFrameworkReady, this); } - } - - tb_line = HTMLArea.newLine(toolbar); - this._htmlArea.appendChild(toolbar); -}; - -/* - * Handle toolbar element events handler - */ -HTMLArea.toolBarButtonHandler = function(ev) { - if(!ev) var ev = window.event; - var target = (ev.target) ? ev.target : ev.srcElement; - while (target.tagName.toLowerCase() == "img" || target.tagName.toLowerCase() == "div") target = target.parentNode; - var obj = target._obj; - var editorNumber = obj["editorNumber"]; - var editor = RTEarea[editorNumber]["editor"]; - if (obj.enabled) { - switch (ev.type) { - case "mouseover": - HTMLArea._addClass(target, "buttonHover"); - HTMLArea._addClass(target.parentNode, "buttonHover"); - break; - case "mouseout": - HTMLArea._removeClass(target, "buttonHover"); - HTMLArea._removeClass(target.parentNode, "buttonHover"); - HTMLArea._removeClass(target, "buttonActive"); - HTMLArea._removeClass(target.parentNode, "buttonActive"); - if (obj.active) { - HTMLArea._addClass(target, "buttonPressed"); - HTMLArea._addClass(target.parentNode, "buttonPressed"); + }, + /* + * Get a reference to the editor + */ + getEditor: function() { + return RTEarea[this.ownerCt.editorId].editor; + }, + /* + * Get a reference to the toolbar + */ + getToolbar: function() { + return this.ownerCt; + }, + /* + * Handler invoked when an item is selected in the dropdown list + */ + onComboSelect: function (combo, record, index) { + if (!combo.disabled) { + var editor = this.getEditor(); + // In IE, reclaim lost focus on the editor iframe and restore the bookmarked selection + if (Ext.isIE) { + editor.focus(); + if (!Ext.isEmpty(this.bookmark)) { + editor.selectRange(editor.moveToBookmark(this.bookmark)); + this.bookmark = null; } - break; - case "mousedown": - HTMLArea._addClass(target, "buttonActive"); - HTMLArea._addClass(target.parentNode, "buttonActive"); - HTMLArea._removeClass(target, "buttonPressed"); - HTMLArea._removeClass(target.parentNode, "buttonPressed"); - HTMLArea._stopEvent(ev); - break; - case "click": - HTMLArea._removeClass(target, "buttonActive"); - HTMLArea._removeClass(target.parentNode, "buttonActive"); - HTMLArea._removeClass(target, "buttonHover"); - HTMLArea._removeClass(target.parentNode, "buttonHover"); - obj.cmd(editor, obj.name); - HTMLArea._stopEvent(ev); - if (HTMLArea.is_opera) { - editor._iframe.focus(); - } - if (!editor.config.btnList[obj.name][7]) { - editor.updateToolbar(); - } - break; - case "change": - editor.focusEditor(); - var dropdown = editor.config.customSelects[obj.name]; - if (typeof(dropdown) !== "undefined") { - dropdown.action(editor, obj.name); - HTMLArea._stopEvent(ev); - if (HTMLArea.is_opera) { - editor._iframe.focus(); - } - editor.updateToolbar(); - } else { - HTMLArea._appendToLog("ERROR [HTMLArea::toolBarButtonHandler]: Combo box " + obj.name + " not registered."); - } + } + // Invoke the plugin onChange handler + this.plugins[this.action](editor, combo, record, index); + // In IE, bookmark the updated selection as the editor will be loosing focus + if (Ext.isIE) { + editor.focus(); + this.bookmark = editor.getBookmark(editor._createRange(editor._getSelection())); + this.triggered = true; + } + if (Ext.isOpera) { + editor.focus(); + } + this.getToolbar().update(); } - } -}; - -/* - * Create the htmlArea iframe and replace the textarea with it. - */ -HTMLArea.prototype.generate = function () { - var self = this; - // Get the textarea, hide it and make it resizable - this.textArea = Ext.get(this._textArea).setVisibilityMode(2).setVisible(false); - if (TYPO3.settings.textareaResize) { - this.textArea.addClass('resizable'); - this.textAreaResizer = new Ext.Resizable(this.textArea, { - minWidth: 300, - minHeight: 200, - maxHeight: TYPO3.settings.textareaMaxHeight, - dynamic: true - }); - this.textAreaResizer.on('resize', function(ev) { self.resizeOnTextAreaChange(2); }); - } - - // Create the editor framework and insert it before the textarea - this.htmlArea = Ext.DomHelper.insertBefore(this.textArea, { - tag: 'div', - cls: 'htmlarea' - }, true).setWidth(this.textArea.getStyle('width')); - this._htmlArea = this.htmlArea.dom; - - // If we have a form, on reset, re-initialize the HTMLArea content and update the toolbar - if (this.textArea.dom.form) { - var f = this.textArea.dom.form; - if (typeof(f.onreset) == "function") { - var funcref = f.onreset; - if (typeof(f.__msh_prevOnReset) == "undefined") f.__msh_prevOnReset = []; - f.__msh_prevOnReset.push(funcref); + return false; + }, + /* + * Handler invoked when the trigger element is clicked + * In IE, need to reclaim lost focus for the editor in order to restore the selection + */ + onTriggerClick: function () { + Ext.ux.form.HTMLAreaCombo.superclass.onTriggerClick.call(this); + // In IE, avoid focus being stolen and selection being lost + if (Ext.isIE) { + this.triggered = true; + this.getEditor().focus(); } - f._editorNumber = this._editorNumber; - HTMLArea._addEvent(f, "reset", HTMLArea.resetHandler); - } - - // Create & append the toolbar - this._createToolbar(); - HTMLArea._appendToLog("[HTMLArea::generate]: Toolbar successfully created."); - - // Create the editor iframe and append it to the toolbar - this.iframe = Ext.DomHelper.append(this.htmlArea, { - tag: 'iframe', - cls: 'editorIframe', - src: (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) ? 'javascript:void(0);' : (HTMLArea.is_opera?_typo3_host_url:'') + _editor_url + 'popups/blank.html' - }, true); - if (!this.getPluginInstance('StatusBar')) { - this.iframe.addClass('noStatusBar'); - } - this._iframe = this.iframe.dom; - HTMLArea._appendToLog("[HTMLArea::generate]: Editor iframe successfully created."); - // Make the editor framework resizable - if (TYPO3.settings.textareaResize) { - this.htmlArea.addClass('resizable'); - var dimensions = this.getDimensions(); - this.htmlAreaResizer = new Ext.Resizable(this.htmlArea, { - maxHeight: parseInt(TYPO3.settings.textareaMaxHeight) + dimensions.toolbar.height + dimensions.statusbar.height, - dynamic: false - }); - this.htmlAreaResizer.on('resize', function(ev) { self.resizeOnHtmlAreaChange(2); }); - } - if (HTMLArea.is_opera) { - this.iframe.on('load', function() { self.initIframe(); } , this); - } else { - this.initIframe(); - } - return this; -}; - -/* - * Resize the editor framework and the iframe when the textarea was resized - */ -HTMLArea.prototype.resizeOnTextAreaChange = function(diff) { - // Set width first as it may change the height of the toolbar and of the statusbar - var width = this.textArea.getStyle('width'); - if (width.indexOf('%') == -1) { - width = (parseInt(width) + diff) + 'px'; - } - this.iframe.setStyle('width', HTMLArea.is_opera ? width : '100%'); - this.htmlArea.setStyle('width', width); - // Set height - var dimensions = this.getDimensions(); - var height = this.textArea.getStyle('height'); - if (height.indexOf('%') == -1) { - height = (parseInt(height) + diff) + 'px'; - } - this.iframe.setStyle('height', height); - this.htmlArea.setStyle('height', (dimensions.toolbar.height + dimensions.statusbar.height) + 'px'); -}; - -/* - * Resize the textarea and iframe when the htmlArea was resized - */ -HTMLArea.prototype.resizeOnHtmlAreaChange = function(diff) { - // Set width first as it may change the height of the toolbar and of the statusbar - var width = this.htmlArea.getStyle('width'); - // Do not shrink narrower than configured textarea - if (parseInt(width) < this.textAreaResizer.minWidth + diff) { - width = (this.textAreaResizer.minWidth + diff) + 'px'; - this.htmlArea.setStyle('width', width); - } - if (width.indexOf('%') == -1) { - width = (parseInt(width) - diff) + 'px'; - } - this.textArea.setStyle('width', width); - // Set height - var height = this.iframe.getStyle('height'); - if (height.indexOf('%') == -1) { - var dimensions = this.getDimensions(); - height = parseInt(this.htmlArea.getStyle('height')) - dimensions.toolbar.height - dimensions.statusbar.height; - // Do not shrink shorter than configured textarea - if (height < this.textAreaResizer.minHeight + diff) { - height = this.textAreaResizer.minHeight + diff; - this.htmlArea.setStyle('height', (height + dimensions.toolbar.height + dimensions.statusbar.height) + 'px'); + }, + /* + * Handler invoked when the list of options is clicked in + */ + onViewClick: function (doFocus) { + // Avoid stealing focus from the editor + Ext.ux.form.HTMLAreaCombo.superclass.onViewClick.call(this, false); + }, + /* + * Handler invoked in IE when the mouse moves out of the editor iframe + */ + saveSelection: function (event) { + var editor = this.getEditor(); + if (editor.document.hasFocus()) { + this.bookmark = editor.getBookmark(editor._createRange(editor._getSelection())); } - this.iframe.setStyle('height', height + 'px'); - height = (height - diff) + 'px'; - } - this.textArea.setStyle('height', height); -}; - -/* - * Size the iframe according to user's prefs or initial textarea - */ -HTMLArea.prototype.sizeIframe = function(diff) { - // Clone the array of nested tabs and inline levels instead of using a reference (this.accessParentElements will change the array): - var parentElements = (this.nested.sorted && this.nested.sorted.length ? [].concat(this.nested.sorted) : []); - // Walk through all nested tabs and inline levels to make a correct positioning: - var dimensions = this.accessParentElements(parentElements, 'this.getDimensions()'); - // Set height - this.config.height = (this.config.height == "auto") ? this._textArea.style.height : this.config.height; - var iframeHeight = this.config.height; - var textareaHeight = this.config.height; - var htmlAreaHeight = this.config.height; - if (this.config.height.indexOf("%") == -1) { - iframeHeight = parseInt(iframeHeight) - diff; - if (this.config.sizeIncludesToolbar) { - this._initialToolbarOffsetHeight = this._initialToolbarOffsetHeight ? this._initialToolbarOffsetHeight : dimensions.toolbar.height; - iframeHeight -= dimensions.toolbar.height; - iframeHeight -= dimensions.statusbar.height; + }, + /* + * Handler invoked in IE when the editor gets the focus back + */ + restoreSelection: function (event) { + if (!Ext.isEmpty(this.bookmark) && this.triggered) { + var editor = this.getEditor(); + editor.selectRange(editor.moveToBookmark(this.bookmark)); + this.triggered = false; } - if (iframeHeight < 0) { - iframeHeight = 0; + }, + /* + * Handler invoked when the enter key is pressed while the combo has focus + */ + onSpecialKey: function (combo, event) { + if (event.getKey() == event.ENTER) { + event.stopEvent(); + } + return false; + }, + /* + * Handler invoked when a hot key configured for this dropdown list is pressed + */ + onHotKey: function (key) { + if (!this.disabled) { + this.plugins.onHotKey(this.getEditor(), key); + if (Ext.isOpera) { + this.getEditor().focus(); + } + this.getToolbar().update(); } - htmlAreaHeight = (iframeHeight + dimensions.toolbar.height + dimensions.statusbar.height) + 'px'; - textareaHeight = (iframeHeight - 4); - if (textareaHeight < 0) { - textareaHeight = 0; + return false; + }, + /* + * Handler invoked when the toolbar is updated + */ + onUpdateToolbar: function (mode, selectionEmpty, ancestors, endPointsInSameBlock) { + this.setDisabled(mode === 'textmode' && !this.textMode); + if (!this.disabled) { + this.plugins['onUpdateToolbar'](this, mode, selectionEmpty, ancestors, endPointsInSameBlock); } - iframeHeight += "px"; - textareaHeight += "px"; + }, + /* + * Special handling for combo stealing focus in IE + * The iframe must have been rendered + */ + onFrameworkReady: function () { + // Take a bookmark in case the editor looses focus by activation of this combo + this.mon(this.getEditor().iframe.getEl(), 'mouseleave', this.saveSelection, this); + // Restore the selection if combo was triggered + this.mon(this.getEditor().iframe.getEl(), 'focus', this.restoreSelection, this); } - this._iframe.style.height = iframeHeight; - this._textArea.style.height = textareaHeight; - this.htmlArea.setStyle('height', htmlAreaHeight); - // Set width - this.config.width = (this.config.width == "auto") ? this._textArea.style.width : this.config.width; - var textareaWidth = this.config.width; - var iframeWidth = this.config.width; - if (textareaWidth.indexOf("%") == -1) { - iframeWidth = parseInt(textareaWidth) + "px"; - textareaWidth = parseInt(textareaWidth) - diff; - if (textareaWidth < 0) { - textareaWidth = 0; - } - textareaWidth += "px"; - } - this._iframe.style.width = "100%"; - if (HTMLArea.is_opera) { - this._iframe.style.width = iframeWidth; - } - this._textArea.style.width = textareaWidth; -}; - +}); +Ext.reg('htmlareacombo', Ext.ux.form.HTMLAreaCombo); +/*************************************************** + * EDITOR FRAMEWORK + ***************************************************/ /* - * Resize the iframes + * HTMLArea.Toolbar extends Ext.Container */ -HTMLArea.resizeIframes = function(ev) { - if (!ev) var ev = window.event; - HTMLArea._stopEvent(ev); - for (var editorNumber in RTEarea) { - if (RTEarea.hasOwnProperty(editorNumber)) { - var editor = RTEarea[editorNumber].editor; - if (editor) { - editor.sizeIframe(2); +HTMLArea.Toolbar = Ext.extend(Ext.Container, { + /* + * Constructor + */ + initComponent: function () { + HTMLArea.Toolbar.superclass.initComponent.call(this); + this.addEvents( + /* + * @event update + * Fires when the toolbar is updated + */ + 'update' + ); + // Build the deferred toolbar update task + this.updateLater = new Ext.util.DelayedTask(this.update, this); + // Add the toolbar items + this.addItems(); + this.addListener({ + afterrender: { + fn: this.initEventListeners, + single: true } + }); + }, + /* + * Initialize listeners + */ + initEventListeners: function () { + // Monitor editor becoming ready + this.mon(this.getEditor(), 'editorready', this.update, this, {single: true}); + }, + /* + * editorId should be set in config + */ + editorId: null, + /* + * Get a reference to the editor + */ + getEditor: function() { + return RTEarea[this.editorId].editor; + }, + /* + * Create the toolbar items based on editor toolbar configuration + */ + addItems: function () { + var editor = this.getEditor(); + // Walk through the editor toolbar configuration nested arrays: [ toolbar [ row [ group ] ] ] + var firstOnRow = true; + var firstInGroup = true; + Ext.each(editor.config.toolbar, function (row) { + if (!firstOnRow) { + // If a visible item was added to the previous line + this.add({ + xtype: 'tbspacer', + cls: 'x-form-clear-left' + }); + } + firstOnRow = true; + // Add the groups + Ext.each(row, function (group) { + // To do: this.config.keepButtonGroupTogether ... + if (!firstOnRow && !firstInGroup) { + // If a visible item was added to the line + this.add({ + xtype: 'tbseparator', + cls: 'separator' + }); + } + firstInGroup = true; + // Add each item + Ext.each(group, function (item) { + if (item == 'space') { + this.add({ + xtype: 'tbspacer', + cls: 'space' + }); + } else { + // Get the item's config as registered by some plugin + var itemConfig = editor.config.buttonsConfig[item]; + if (!Ext.isEmpty(itemConfig)) { + itemConfig.id = this.editorId + '-' + itemConfig.id; + this.add(itemConfig); + firstInGroup = firstInGroup && itemConfig.hidden; + firstOnRow = firstOnRow && firstInGroup; + } + } + return true; + }, this); + return true; + }, this); + return true; + }, this); + this.add({ + xtype: 'tbspacer', + cls: 'x-form-clear-left' + }); + }, + /* + * Retrieve a toolbar item by itemId + */ + getButton: function (buttonId) { + return this.find('itemId', buttonId)[0]; + }, + /* + * Update the state of the toolbar + */ + update: function() { + var editor = this.getEditor(), + mode = editor.getMode(), + selectionEmpty = true, + ancestors = null, + endPointsInSameBlock = true; + if (editor.getMode() === 'wysiwyg') { + selectionEmpty = editor._selectionEmpty(editor._getSelection()); + ancestors = editor.getAllAncestors(); + endPointsInSameBlock = editor.endPointsInSameBlock(); } + this.fireEvent('update', mode, selectionEmpty, ancestors, endPointsInSameBlock); } -}; - -/** - * Get the dimensions of the toolbar and statusbar. - * - * @return object An object with width/height pairs for statusbar and toolbar. - * @author Oliver Hader +}); +Ext.reg('htmlareatoolbar', HTMLArea.Toolbar); +/* + * HTMLArea.Iframe extends Ext.BoxComponent */ -HTMLArea.prototype.getDimensions = function() { - return { - toolbar: {width: this._toolbar.offsetWidth, height: this._toolbar.offsetHeight}, - statusbar: {width: ((this.getPluginInstance("StatusBar") && this.getPluginInstance("StatusBar").statusBar) ? this.getPluginInstance("StatusBar").statusBar.offsetWidth : 0), height: ((this.getPluginInstance("StatusBar") && this.getPluginInstance("StatusBar").statusBar) ? this.getPluginInstance("StatusBar").statusBar.offsetHeight : 0)} - }; -}; - -/** - * Access an inline relational element or tab menu and make it "accessible". - * If a parent object has the style "display: none", offsetWidth & offsetHeight are '0'. - * - * @params object callbackFunc: A function to be called, when the embedded objects are "accessible". - * @return object An object returned by the callbackFunc. - * @author Oliver Hader - */ -HTMLArea.prototype.accessParentElements = function(parentElements, callbackFunc) { - var result = {}; - - if (parentElements.length) { - var currentElement = parentElements.pop(); - var elementStyle = document.getElementById(currentElement).style; - var actionRequired = (elementStyle.display == 'none' ? true : false); - - if (actionRequired) { - var originalVisibility = elementStyle.visibility; - var originalPosition = elementStyle.position; - elementStyle.visibility = 'hidden'; - elementStyle.position = 'absolute'; - elementStyle.display = ''; +HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, { + /* + * Constructor + */ + initComponent: function () { + HTMLArea.Iframe.superclass.initComponent.call(this); + this.addEvents( + /* + * @event iframeready + * Fires when the iframe style sheets become accessible + */ + 'iframeready' + ); + this.addListener({ + afterrender: { + fn: this.initEventListeners, + single: true + }, + beforeDestroy: { + fn: this.onBeforeDestroy, + single: true + } + }); + this.config = this.getEditor().config; + if (!this.config.showStatusBar) { + this.addClass('noStatusBar'); } - - result = this.accessParentElements(parentElements, callbackFunc); - - if (actionRequired) { - elementStyle.display = 'none'; - elementStyle.position = originalPosition; - elementStyle.visibility = originalVisibility; + }, + /* + * Initialize event listeners and the document after the iframe has rendered + */ + initEventListeners: function () { + // The editor iframe may become hidden with style.display = "none" + // This breaks the editor in Firefox: the designMode attribute needs to be reset after the style.display of the containing div is reset to "block" + if (Ext.isGecko && this.isNested) { + Ext.each(this.nestedParentElements.sorted, function (nested) { + this.mon(Ext.get(nested), 'DOMAttrModified', this.onNestedShow, this, {delay: 100}); + }, this); } - - } else { - result = eval(callbackFunc); - - } - - return result; -}; - -/** - * Simplify the array of nested levels. Create an indexed array with the correct names of the elements. - * - * @param object nested: The array with the nested levels - * @return object The simplified array - * @author Oliver Hader - */ -HTMLArea.simplifyNested = function(nested) { - var i, type, level, max, simplifiedNested=[]; - if (nested && nested.length) { - if (nested[0][0]=='inline') { - nested = inline.findContinuedNestedLevel(nested, nested[0][1]); + if (Ext.isOpera) { + this.mon(this.getEl(), 'load', this.initializeIframe , this, {single: true}); + } else { + this.initializeIframe(); } - for (i=0, max=nested.length; i

{term}
', + store: new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'term'}, { name: 'abbr'}, { name: 'language'}], + data: this.data[type] + }), + width: 350, + listeners: { + beforerender: { + fn: this.onSelectorRender, + scope: this + }, + select: { + fn: this.onTermSelect, + scope: this } - if (this.dialog) { - this.dialog.focus(); + } + }, this.configDefaults['combo'])); + itemsConfig.push(Ext.apply({ + xtype: 'combo', + displayField: 'abbr', + valueField: 'abbr', + tpl: '
{abbr}
', + fieldLabel: this.localize('Abridged_term'), + itemId: 'abbrSelector', + helpTitle: this.localize('Select_an_' + type), + store: new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'term'}, { name: 'abbr'}, { name: 'language'}], + data: this.data[type] + }), + width: 100, + listeners: { + beforerender: { + fn: this.onSelectorRender, + scope: this + }, + select: { + fn: this.onAbbrSelect, + scope: this } } + }, this.configDefaults['combo'])); + var languageObject = this.getPluginInstance('Language'); + if (this.getButton('Language')) { + var languageStore = new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'} ], + data: this.getDropDownConfiguration('Language').options + }); + var selectedLanguage = !Ext.isEmpty(element) ? languageObject.getLanguageAttribute(element) : 'none'; + if (selectedLanguage !== 'none') { + languageStore.removeAt(0); + languageStore.insert(0, new languageStore.recordType({ + text: languageObject.localize('Remove language mark'), + value: 'none' + })); + } + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize('Language'), + itemId: 'language', + helpTitle: this.localize('Select_a_language'), + helpText: this.localize('Language_' + type + '_helpText'), + valueField: 'value', + displayField: 'text', + tpl: '
{text}
', + store: languageStore, + width: 200, + value: selectedLanguage + }, this.configDefaults['combo'])); } + return { + xtype: 'fieldset', + title: this.localize('Defined_' + type), + items: itemsConfig, + listeners: { + render: { + fn: this.onDefinedTermFieldsetRender, + scope: this + } + } + }; + }, + /* + * Handler on rendering the defined abbreviation fieldset + * If an abbr is selected but no term is selected, select any corresponding term with the correct language value, if any + */ + onDefinedTermFieldsetRender: function (fieldset) { + var termSelector = fieldset.find('itemId', 'termSelector')[0]; + var term = termSelector.getValue(); + var abbrSelector = fieldset.find('itemId', 'abbrSelector')[0]; + var abbr = abbrSelector.getValue(); + var language = ''; + var languageSelector = fieldset.find('itemId', 'language')[0]; + if (languageSelector) { + var language = languageSelector.getValue(); + if (language == 'none') { + language = ''; + } + } + if (abbr && !term) { + var abbrStore = abbrSelector.getStore(); + var index = abbrStore.findBy(function (record) { + return record.get('abbr') == abbr && (!languageSelector || record.get('language') == language); + }, this); + if (index !== -1) { + term = abbrStore.getAt(index).get('term'); + termSelector.setValue(term); + fieldset.ownerCt.find('itemId', 'useTerm')[0].setValue(term); + } + } + }, + /* + * Filter the term and abbr selector lists + * Set initial values + * If there is already an abbr and the filtered list has only one or no element, hide the fieldset + */ + onSelectorRender: function (combo) { + var store = combo.getStore(); + store.filterBy(function (record) { + return !this.params.text || !this.params.title || this.params.text == record.get('term') || this.params.title == record.get('term') || this.params.title == record.get('abbr'); + }, this); + // Make sure the combo list is filtered + store.snapshot = store.data; + var store = combo.getStore(); + if (combo.getItemId() == 'termSelector' && this.params.title) { + var index = store.findExact('term', this.params.title); + if (index !== -1) { + combo.setValue(store.getAt(index).get('term')); + } + } else if (combo.getItemId() == 'abbrSelector' && this.params.text) { + var index = store.findExact('abbr', this.params.text); + if (index !== -1) { + combo.setValue(store.getAt(index).get('abbr')); + } + } + if (this.params.abbr && store.getCount() < 2) { + combo.ownerCt.hide(); + } + }, + /* + * Handler when a term is selected + */ + onTermSelect: function (combo, record, index) { + var tab = combo.findParentByType('container'); + var term = record.get('term'); + var abbr = record.get('abbr'); + var language = record.get('language'); + // Update the abbreviation selector + var abbrSelector = tab.find('itemId', 'abbrSelector')[0]; + abbrSelector.setValue(abbr); + // Update the language selector + var languageSelector = tab.find('itemId', 'language'); + if (!Ext.isEmpty(languageSelector)) { + if (language) { + languageSelector[0].setValue(language); + } else { + languageSelector[0].setValue('none'); + } + } + // Update the term to use + tab.find('itemId', 'useTerm')[0].setValue(term); + }, + /* + * Handler when an abbreviation or acronym is selected + */ + onAbbrSelect: function (combo, record, index) { + var tab = combo.findParentByType('container'); + var term = record.get('term'); + var language = record.get('language'); + // Update the term selector + var termSelector = tab.find('itemId', 'termSelector')[0]; + termSelector.setValue(term); + // Update the language selector + var languageSelector = tab.find('itemId', 'language'); + if (!Ext.isEmpty(languageSelector)) { + if (language) { + languageSelector[0].setValue(language); + } else { + languageSelector[0].setValue('none'); + } + } + // Update the term to use + tab.find('itemId', 'useTerm')[0].setValue(term); + }, + /* + * This function builds the configuration object for the Abbreviation or Acronym to use fieldset + * + * @param object element: the element being edited, if any + * + * @return object the fieldset configuration object + */ + buildUseTermFieldsetConfig: function (element, type) { + var itemsConfig = []; + itemsConfig.push({ + fieldLabel: this.localize('Use_this_term'), + labelSeparator: '', + itemId: 'useTerm', + value: element ? element.title : '', + width: 300, + helpTitle: this.localize('Use_this_term_explain') + }); + return { + xtype: 'fieldset', + title: this.localize('Term_to_abridge'), + defaultType: 'textfield', + defaults: { + helpIcon: true + }, + items: itemsConfig + }; + }, + /* + * Handler when the ok button is pressed + */ + okHandler: function (button, event) { + this.restoreSelection(); + var tab = this.dialog.findByType('tabpanel')[0].getActiveTab(); + var type = tab.getItemId(); + var languageSelector = tab.find('itemId', 'language'); + var language = !Ext.isEmpty(languageSelector) ? languageSelector[0].getValue() : ''; + var term = tab.find('itemId', 'termSelector')[0].getValue(); + if (!this.params.abbr) { + var abbr = this.editor.document.createElement(type); + abbr.title = tab.find('itemId', 'useTerm')[0].getValue(); + if (term == abbr.title) { + abbr.innerHTML = tab.find('itemId', 'abbrSelector')[0].getValue(); + } else { + abbr.innerHTML = this.params.text; + } + if (language) { + this.getPluginInstance('Language').setLanguageAttributes(abbr, language); + } + this.editor.insertNodeAtSelection(abbr); + } else { + var abbr = this.params.abbr; + abbr.title = tab.find('itemId', 'useTerm')[0].getValue(); + if (language) { + this.getPluginInstance('Language').setLanguageAttributes(abbr, language); + } + if (term == abbr.title) { + abbr.innerHTML = tab.find('itemId', 'abbrSelector')[0].getValue(); + } + } + this.close(); + event.stopEvent(); + }, + /* + * Handler when the delete button is pressed + */ + deleteHandler: function (button, event) { + this.restoreSelection(); + var abbr = this.params.abbr; + if (abbr) { + this.editor.removeMarkup(abbr); + } + this.close(); + event.stopEvent(); + }, + /* + * This function gets called when the toolbar is updated + */ + onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) { + if ((mode === 'wysiwyg') && this.editor.isEditable()) { + var el = this.editor.getParentElement(); + if (el) { + button.setDisabled(((el.nodeName.toLowerCase() == 'acronym' && this.pageTSConfiguration.noAcronym) || (el.nodeName.toLowerCase() == 'abbr' && this.pageTSConfiguration.noAbbr))); + button.setInactive(!(el.nodeName.toLowerCase() == 'acronym' && !this.pageTSConfiguration.noAcronym) && !(el.nodeName.toLowerCase() == 'abbr' && !this.pageTSConfiguration.noAbbr)); + } + if (this.dialog) { + this.dialog.focus(); + } + } } }); - Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/Acronym/locallang.xml =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/Acronym/locallang.xml (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/Acronym/locallang.xml (copie de travail) @@ -1,5 +1,5 @@ - + Labels for Acronym plugin of htmlArea RTE @@ -8,6 +8,24 @@ + + + + + + + + + + + + + + + + + + Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/block-elements.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/block-elements.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/block-elements.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2007-2009 Stanislas Rolland +* (c) 2007-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -106,7 +106,7 @@ * Registering plugin "About" information */ var pluginInformation = { - version : "1.3", + version : "1.4", developer : "Stanislas Rolland", developerUrl : "http://www.sjbr.ca/", copyrightOwner : "Stanislas Rolland", @@ -121,48 +121,48 @@ */ var buttonId = "FormatBlock"; var dropDownConfiguration = { - id : buttonId, - tooltip : this.localize(buttonId + "-Tooltip"), - options : ((this.editorConfiguration.buttons.formatblock && this.editorConfiguration.buttons.formatblock.dropDownOptions) ? this.editorConfiguration.buttons.formatblock.dropDownOptions : null), - action : "onChange", - refresh : null, - context : null + id: buttonId, + tooltip: this.localize(buttonId + "-Tooltip"), + width: (this.buttonsConfiguration.formatblock && this.buttonsConfiguration.formatblock.width) ? this.buttonsConfiguration.formatblock.width : 200, + listWidth: (this.buttonsConfiguration.formatblock && this.buttonsConfiguration.formatblock.listWidth) ? this.buttonsConfiguration.formatblock.listWidth : 200, + maxHeight: (this.buttonsConfiguration.formatblock && this.buttonsConfiguration.formatblock.maxHeight) ? this.buttonsConfiguration.formatblock.maxHeight : 300, + options: (this.buttonsConfiguration.formatblock ? this.buttonsConfiguration.formatblock.data : null), + action: "onChange" }; this.registerDropDown(dropDownConfiguration); - + /* * Establishing the list of allowed block elements */ var blockElements = new Array(); - for (var option in dropDownConfiguration.options) { - if (dropDownConfiguration.options.hasOwnProperty(option)) { - blockElements.push(dropDownConfiguration.options[option]); + Ext.each(dropDownConfiguration.options, function (option) { + if (option[1] != 'none') { + blockElements.push(option[1]); } - } + }); this.allowedBlockElements = new RegExp( "^(" + blockElements.join("|") + ")$", "i"); - + /* - * Registering hot keys + * Registering hot keys for the dropdown list items */ - for (var i = 0; i < blockElements.length; ++i) { - var configuredHotKey = this.defaultHotKeys[blockElements[i]]; + Ext.each(blockElements, function (blockElement) { + var configuredHotKey = this.defaultHotKeys[blockElement]; if (this.editorConfiguration.buttons.formatblock && this.editorConfiguration.buttons.formatblock.items - && this.editorConfiguration.buttons.formatblock.items[blockElements[i]] - && this.editorConfiguration.buttons.formatblock.items[blockElements[i]].hotKey) { - configuredHotKey = this.editorConfiguration.buttons.formatblock.items[blockElements[i]].hotKey; + && this.editorConfiguration.buttons.formatblock.items[blockElement] + && this.editorConfiguration.buttons.formatblock.items[blockElement].hotKey) { + configuredHotKey = this.editorConfiguration.buttons.formatblock.items[blockElement].hotKey; } if (configuredHotKey) { var hotKeyConfiguration = { id : configuredHotKey, cmd : buttonId, - action : "onHotKey", - element : blockElements[i] + element : blockElement }; this.registerHotKey(hotKeyConfiguration); } - } - + }, this); + /* * Registering the buttons */ @@ -171,22 +171,21 @@ var button = this.buttonList[buttonId]; var buttonConfiguration = { id : buttonId, - tooltip : this.localize(buttonId + "-Tooltip"), + tooltip : this.localize(buttonId + '-Tooltip') || this.localize(button[2]), + contextMenuTitle: this.localize(buttonId + '-contextMenuTitle'), action : "onButtonPress", - context : button[0], hotKey : (this.buttonsConfiguration[button[2]] ? this.buttonsConfiguration[button[2]].hotKey : (button[1] ? button[1] : null)) }; this.registerButton(buttonConfiguration); } } - return true; }, /* * The list of buttons added by this plugin */ - buttonList : { + buttonList: { Indent : [null, "TAB", "indent"], Outdent : [null, "SHIFT-TAB", "outdent"], Blockquote : [null, null, "blockquote"], @@ -197,7 +196,8 @@ JustifyRight : [null, "r", "right"], JustifyFull : [null, "j", "justifyfull"], InsertOrderedList : [null, null, "orderedlist"], - InsertUnorderedList : [null, null, "unorderedlist"] + InsertUnorderedList : [null, null, "unorderedlist"], + InsertHorizontalRule : [null, null, "inserthorizontalrule"] }, /* @@ -234,10 +234,8 @@ /* * This function gets called when some block element was selected in the drop-down list */ - onChange : function (editor, buttonId) { - var tbobj = this.editor._toolbarObjects[buttonId]; - var blockElement = document.getElementById(tbobj.elementId).value; - this.applyBlockElement(buttonId, blockElement); + onChange : function (editor, combo, record, index) { + this.applyBlockElement(combo.itemId, combo.getValue()); }, applyBlockElement : function(buttonId, blockElement) { @@ -297,7 +295,7 @@ this.editor.focusEditor(); var selection = editor._getSelection(); var range = editor._createRange(selection); - var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null; + var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null; var parentElement = statusBarSelection ? statusBarSelection : this.editor.getParentElement(selection, range); if (target) { parentElement = target; @@ -307,7 +305,6 @@ } var blockAncestors = this.getBlockAncestors(parentElement); var tableCell = null; - if (id === "TAB" || id === "SHIFT-TAB") { for (var i = blockAncestors.length; --i >= 0;) { if (/^(td|th)$/i.test(blockAncestors[i].nodeName)) { @@ -317,7 +314,6 @@ } } var fullNodeTextSelected = (HTMLArea.is_gecko && parentElement.textContent === range.toString()) || (HTMLArea.is_ie && parentElement.innerText === range.text); - switch (buttonId) { case "Indent" : if (/^(ol|ul)$/i.test(parentElement.nodeName) && !(fullNodeTextSelected && !/^(li)$/i.test(parentElement.parentNode.nodeName))) { @@ -334,6 +330,7 @@ this.indentSelectedListElements(parentElement, range); } } else if (tableCell) { + var tablePart = tableCell.parentNode.parentNode; // Get next cell in same table part var nextCell = tableCell.nextSibling ? tableCell.nextSibling : (tableCell.parentNode.nextSibling ? tableCell.parentNode.nextSibling.cells[0] : null); @@ -349,7 +346,6 @@ case "tfoot": this.editor.selectNodeContents(tablePart.parentNode.lastChild.lastChild.lastChild, true); } - } if (!nextCell) { if (this.editor.plugins.TableOperations) { @@ -359,6 +355,9 @@ } } if (nextCell) { + if (Ext.isOpera && !nextCell.hasChildNodes()) { + nextCell.appendChild(this.editor.document.createElement('br')); + } this.editor.selectNodeContents(nextCell, true); } } else if (this.useBlockquote) { @@ -415,6 +414,9 @@ } } if (previousCell) { + if (Ext.isOpera && !previousCell.hasChildNodes()) { + previousCell.appendChild(this.editor.document.createElement('br')); + } this.editor.selectNodeContents(previousCell, true); } } else if (this.useBlockquote) { @@ -535,6 +537,9 @@ case "InsertUnorderedList": this.insertList(buttonId, parentElement); break; + case "InsertHorizontalRule": + this.editor.execCommand('InsertHorizontalRule'); + break; case "none" : if (this.isAllowedBlockElement(parentElement.nodeName)) { this.removeElement(parentElement); @@ -919,44 +924,61 @@ this.editor.selectNodeContents(paragraph, true); } }, - /* - * This function gets called by the main editor event handler when a key was pressed. + * This function gets called when the plugin is generated + */ + onGenerate: function () { + // Register the enter key handler for IE when the cursor is at the end of a dt or a dd element + if (Ext.isIE) { + this.editor.iframe.keyMap.addBinding({ + key: Ext.EventObject.ENTER, + shift: false, + handler: this.onKey, + scope: this + }); + } + }, + /* + * This function gets called when the enter key was pressed in IE * It will process the enter key for IE when the cursor is at the end of a dt or a dd element + * + * @param string key: the key code + * @param object event: the Ext event object (keydown) + * + * @return boolean false, if the event was taken care of */ - onKeyPress : function (ev) { - if (HTMLArea.is_ie && ev.keyCode == 13 && !ev.shiftKey) { - var selection = this.editor._getSelection(); - if (this.editor._selectionEmpty(selection)) { - var range = this.editor._createRange(selection); - var parentElement = this.editor.getParentElement(selection, range); - while (parentElement && !HTMLArea.isBlockElement(parentElement)) { - parentElement = parentElement.parentNode; - } - if (/^(dt|dd)$/i.test(parentElement.nodeName)) { - var nodeRange = this.editor._createRange(); - nodeRange.moveToElementText(parentElement); - range.setEndPoint("EndToEnd", nodeRange); - if (!range.text || range.text == "\x20") { - var item = parentElement.parentNode.insertBefore(this.editor._doc.createElement((parentElement.nodeName.toLowerCase() === "dt") ? "dd" : "dt"), parentElement.nextSibling); - item.innerHTML = "\x20"; - this.editor.selectNodeContents(item, true); - return false; - } - } else if (/^(li)$/i.test(parentElement.nodeName) - && !parentElement.innerText - && parentElement.parentNode.parentNode - && /^(dd|td|th)$/i.test(parentElement.parentNode.parentNode.nodeName)) { - var item = parentElement.parentNode.parentNode.insertBefore(this.editor._doc.createTextNode("\x20"), parentElement.parentNode.nextSibling); - this.editor.selectNodeContents(parentElement.parentNode.parentNode, false); - parentElement.parentNode.removeChild(parentElement); + onKey: function (key, event) { + var selection = this.editor._getSelection(); + if (this.editor._selectionEmpty(selection)) { + var range = this.editor._createRange(selection); + var parentElement = this.editor.getParentElement(selection, range); + while (parentElement && !HTMLArea.isBlockElement(parentElement)) { + parentElement = parentElement.parentNode; + } + if (/^(dt|dd)$/i.test(parentElement.nodeName)) { + var nodeRange = this.editor._createRange(); + nodeRange.moveToElementText(parentElement); + range.setEndPoint("EndToEnd", nodeRange); + if (!range.text || range.text == "\x20") { + var item = parentElement.parentNode.insertBefore(this.editor._doc.createElement((parentElement.nodeName.toLowerCase() === "dt") ? "dd" : "dt"), parentElement.nextSibling); + item.innerHTML = "\x20"; + this.editor.selectNodeContents(item, true); + event.stopEvent(); return false; } + } else if (/^(li)$/i.test(parentElement.nodeName) + && !parentElement.innerText + && parentElement.parentNode.parentNode + && /^(dd|td|th)$/i.test(parentElement.parentNode.parentNode.nodeName)) { + var item = parentElement.parentNode.parentNode.insertBefore(this.editor._doc.createTextNode("\x20"), parentElement.parentNode.nextSibling); + this.editor.selectNodeContents(parentElement.parentNode.parentNode, false); + parentElement.parentNode.removeChild(parentElement); + event.stopEvent(); + return false; } } return true; }, - /* * This function removes any disallowed class or mutually exclusive classes from the class attribute of the node */ @@ -984,39 +1006,30 @@ /* * This function gets called when the toolbar is updated */ - onUpdateToolbar : function () { - if (this.getEditorMode() === "textmode" || !this.editor.isEditable()) { - return false; - } - var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null; - var parentElement = statusBarSelection ? statusBarSelection : this.editor.getParentElement(); - if (parentElement.nodeName.toLowerCase() === "body") return false; - while (parentElement && !HTMLArea.isBlockElement(parentElement) || /^li$/i.test(parentElement.nodeName)) { - parentElement = parentElement.parentNode; - } - var blockAncestors = this.getBlockAncestors(parentElement); - - var selection = this.editor._getSelection(); - var endBlocks = this.editor.getEndBlocks(selection); - var startAncestors = this.getBlockAncestors(endBlocks.start); - var endAncestors = this.getBlockAncestors(endBlocks.end); - var index = 0; - while (index < startAncestors.length && index < endAncestors.length && startAncestors[index] === endAncestors[index]) { - ++index; - } - if (endBlocks.start === endBlocks.end || !startAncestors[index]) { - --index; - } - var dropDownConfiguration = this.getDropDownConfiguration("FormatBlock"); - if ((typeof(dropDownConfiguration) !== "undefined") && this.isButtonInToolbar(dropDownConfiguration.id)) { - this.updateDropDown(dropDownConfiguration, blockAncestors[blockAncestors.length-1], startAncestors[index]); - } - - var commandState; - for (var buttonId in this.buttonList) { - commandState = false; - if (this.buttonList.hasOwnProperty(buttonId) && this.isButtonInToolbar(buttonId)) { - switch (buttonId) { + onUpdateToolbar: function (button, mode, selectionEmpty, ancestors, endPointsInSameBlock) { + if (mode === 'wysiwyg' && this.editor.isEditable()) { + var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null; + var parentElement = statusBarSelection ? statusBarSelection : this.editor.getParentElement(); + if (!/^body$/i.test(parentElement.nodeName)) { + while (parentElement && !HTMLArea.isBlockElement(parentElement) || /^li$/i.test(parentElement.nodeName)) { + parentElement = parentElement.parentNode; + } + var blockAncestors = this.getBlockAncestors(parentElement); + var endBlocks = this.editor.getEndBlocks(this.editor._getSelection()); + var startAncestors = this.getBlockAncestors(endBlocks.start); + var endAncestors = this.getBlockAncestors(endBlocks.end); + var index = 0; + while (index < startAncestors.length && index < endAncestors.length && startAncestors[index] === endAncestors[index]) { + ++index; + } + if (endBlocks.start === endBlocks.end || !startAncestors[index]) { + --index; + } + var commandState = false; + switch (button.itemId) { + case 'FormatBlock': + this.updateDropDown(button, blockAncestors[blockAncestors.length-1], startAncestors[index]); + break; case "Outdent" : if (this.useBlockquote) { for (var j = blockAncestors.length; --j >= 0;) { @@ -1029,19 +1042,19 @@ commandState = true; } else { for (var j = blockAncestors.length; --j >= 0;) { - if (HTMLArea._hasClass(blockAncestors[j], this.useClass.Indent)) { + if (HTMLArea._hasClass(blockAncestors[j], this.useClass.Indent) || /^(td|th)$/i.test(blockAncestors[j].nodeName)) { commandState = true; break; } } } - this.editor._toolbarObjects[buttonId].state("enabled", commandState); + button.setDisabled(!commandState); break; case "Indent" : break; case "InsertParagraphBefore" : case "InsertParagraphAfter" : - this.editor._toolbarObjects[buttonId].state("enabled", !(/^(body)$/i.test(startAncestors[index].nodeName))); + button.setDisabled(/^(body)$/i.test(startAncestors[index].nodeName)); break; case "Blockquote" : for (var j = blockAncestors.length; --j >= 0;) { @@ -1050,7 +1063,7 @@ break; } } - this.editor._toolbarObjects[buttonId].state("active", commandState); + button.setInactive(!commandState); break; case "JustifyLeft" : case "JustifyCenter" : @@ -1058,37 +1071,38 @@ case "JustifyFull" : if (this.useAlignAttribute) { try { - commandState = this.editor._doc.queryCommandState(buttonId); + commandState = this.editor._doc.queryCommandState(button.itemId); } catch(e) { commandState = false; } } else { if (/^(body)$/i.test(startAncestors[index].nodeName)) { - this.editor._toolbarObjects[buttonId].state("enabled", false); + button.setDisabled(true); } else { - this.editor._toolbarObjects[buttonId].state("enabled", true); + button.setDisabled(false); commandState = true; for (var block = startAncestors[index]; block; block = block.nextSibling) { - commandState = commandState && HTMLArea._hasClass(block, this.useClass[buttonId]); + commandState = commandState && HTMLArea._hasClass(block, this.useClass[button.itemId]); if (block == endAncestors[index]) { break; } } } } - this.editor._toolbarObjects[buttonId].state("active", commandState); + button.setInactive(!commandState); break; case "InsertOrderedList": case "InsertUnorderedList": try { - commandState = this.editor._doc.queryCommandState(buttonId); + commandState = this.editor._doc.queryCommandState(button.itemId); } catch(e) { commandState = false; } - this.editor._toolbarObjects[buttonId].state("active", commandState); + button.setInactive(!commandState); break; default : break; + } } } @@ -1097,40 +1111,35 @@ /* * This function updates the drop-down list of block elements */ - updateDropDown : function(dropDownConfiguration, deepestBlockAncestor, startAncestor) { - - var select = document.getElementById(this.editor._toolbarObjects[dropDownConfiguration.id].elementId); - var options = select.options; - for (var i = options.length; --i >= 0;) { - options[i].selected = false; - } - select.selectedIndex = 0; - options[0].selected = true; - options[0].style.display = "list-item"; - options[0].text = this.localize("No block"); - + updateDropDown : function(select, deepestBlockAncestor, startAncestor) { + var store = select.getStore(); + store.removeAt(0); + var index = -1; if (deepestBlockAncestor) { var nodeName = deepestBlockAncestor.nodeName.toLowerCase(); - for (i = options.length; --i >= 0;) { - var item = this.formatBlockItems[options[i].value]; - if (item && item.tagName == nodeName && item.addClass && HTMLArea._hasClass(deepestBlockAncestor, item.addClass)) { - options[i].selected = true; - select.selectedIndex = i; - options[0].text = this.localize("Remove block"); - break; - } + // Could be a custom item ... + index = store.findBy(function(record, id) { + var item = this.formatBlockItems[record.get('value')]; + return item && item.tagName == nodeName && item.addClass && HTMLArea._hasClass(deepestBlockAncestor, item.addClass); + }, this); + if (index == -1) { + // ... or a standard one + index = store.findExact('value', nodeName); } - if (!select.selectedIndex) { - for (i = options.length; --i >= 0;) { - if (nodeName === options[i].value.toLowerCase()) { - options[i].selected = true; - select.selectedIndex = i; - options[0].text = this.localize("Remove block"); - break; - } - } - } } + if (index == -1) { + store.insert(0, new store.recordType({ + text: this.localize('No block'), + value: 'none' + })); + select.setValue('none'); + } else { + store.insert(0, new store.recordType({ + text: this.localize('Remove block'), + value: 'none' + })); + select.setValue(store.getAt(index+1).get('value')); + } }, /* Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/locallang.xml =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/locallang.xml (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/locallang.xml (copie de travail) @@ -13,6 +13,8 @@ + + Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/block-style.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/block-style.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/block-style.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2007-2009 Stanislas Rolland +* (c) 2007-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -100,7 +100,7 @@ * Registering plugin "About" information */ var pluginInformation = { - version : "1.3", + version : "1.4", developer : "Stanislas Rolland", developerUrl : "http://www.sjbr.ca/", copyrightOwner : "Stanislas Rolland", @@ -111,30 +111,34 @@ this.registerPluginInformation(pluginInformation); /* - * Registeringthe drop-down list + * Registering the drop-down list */ - var dropDownId = "BlockStyle"; + var dropDownId = 'BlockStyle'; + var fieldLabel = this.pageTSconfiguration.fieldLabel; + if (Ext.isEmpty(fieldLabel) && this.isButtonInToolbar('I[Block style label]')) { + fieldLabel = this.localize('Block style label'); + } var dropDownConfiguration = { - id : dropDownId, - tooltip : this.localize(dropDownId + "-Tooltip"), - textMode : false, - options : {"":""}, - action : "onChange", - refresh : "generate", - context : null + id: dropDownId, + tooltip: this.localize(dropDownId + '-Tooltip'), + fieldLabel: fieldLabel, + width: this.pageTSconfiguration.width ? this.pageTSconfiguration.width : 'auto', + listWidth: this.pageTSconfiguration.listWidth ? this.pageTSconfiguration.listWidth : 250, + maxHeight: this.pageTSconfiguration.maxHeight ? this.pageTSconfiguration.maxHeight : 300, + options: [[this.localize('No style'), 'none']], + action: 'onChange', + storeFields: [ { name: 'text'}, { name: 'value'}, { name: 'style'} ], + tpl: '
{text}
' }; this.registerDropDown(dropDownConfiguration); - return true; }, /* * This function gets called when some block style was selected in the drop-down list */ - onChange : function(editor, dropDownId) { - var dropDown = document.getElementById(this.editor._toolbarObjects[dropDownId].elementId); - var className = dropDown.value; - + onChange : function (editor, combo, record, index) { + var className = combo.getValue(); this.editor.focusEditor(); var blocks = this.getSelectedBlocks(); for (var k = 0; k < blocks.length; ++k) { @@ -160,9 +164,9 @@ for (var i = classNames.length; --i >= 0;) { if (!HTMLArea.reservedClassNames.test(classNames[i])) { HTMLArea._removeClass(node, classNames[i]); - if (node.nodeName.toLowerCase() === "table" && this.editor.plugins.TableOperations) { - this.editor.plugins.TableOperations.instance.removeAlternatingClasses(node, classNames[i]); - this.editor.plugins.TableOperations.instance.removeCountingClasses(node, classNames[i]); + if (node.nodeName.toLowerCase() === "table" && this.getPluginInstance('TableOperations')) { + this.getPluginInstance('TableOperations').removeAlternatingClasses(node, classNames[i]); + this.getPluginInstance('TableOperations').removeCountingClasses(node, classNames[i]); } break; } @@ -180,8 +184,8 @@ } else { HTMLArea._addClass(node, className); } - if (nodeName === "table" && this.editor.plugins.TableOperations) { - this.editor.plugins.TableOperations.instance.reStyleTable(node); + if (nodeName === "table" && this.getPluginInstance('TableOperations')) { + this.getPluginInstance('TableOperations').reStyleTable(node); } } }, @@ -191,7 +195,7 @@ */ getSelectedBlocks : function() { var block, range, i = 0, blocks = []; - var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null; + var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null; if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) { var selection = this.editor._getSelection(); try { @@ -207,34 +211,32 @@ } return blocks; }, - /* * This function gets called when the editor is generated */ - onGenerate : function() { + onGenerate: function() { + // Monitor editor changing mode + this.editor.iframe.mon(this.editor, 'modeChange', this.onModeChange, this); if (HTMLArea.is_gecko) { - this.generate(this.editor, "BlockStyle"); + this.generate(this.editor, 'BlockStyle'); } }, - /* * This function gets called when the toolbar is being updated */ - onUpdateToolbar : function() { - if (this.getEditorMode() === "wysiwyg") { - this.generate(this.editor, "BlockStyle"); + onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) { + if (mode === 'wysiwyg') { + this.generate(this.editor, button.itemId); } }, - /* * This function gets called when the editor has changed its mode to "wysiwyg" */ - onMode : function(mode) { + onModeChange: function(mode) { if (this.getEditorMode() === "wysiwyg") { this.generate(this.editor, "BlockStyle"); } }, - /* * This function gets called on plugin generation, on toolbar update and on change mode * Re-initiate the parsing of the style sheets, if not yet completed, and refresh our toolbar components @@ -244,11 +246,7 @@ this.updateValue(dropDownId); } else { if (this.cssTimeout) { - if (this.editor._iframe.contentWindow) { - this.editor._iframe.contentWindow.clearTimeout(this.cssTimeout); - } else { - window.clearTimeout(this.cssTimeout); - } + window.clearTimeout(this.cssTimeout); this.cssTimeout = null; } if (this.classesUrl && (typeof(HTMLArea.classesLabels) === "undefined")) { @@ -262,30 +260,27 @@ * This function updates the current value of the dropdown list */ updateValue : function(dropDownId) { - var dropDown = document.getElementById(this.editor._toolbarObjects[dropDownId].elementId); - dropDown.disabled = true; - - var classNames = new Array(); - var tagName = null; - var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null; - var parent = statusBarSelection ? statusBarSelection : this.editor.getParentElement(); - while (parent && !HTMLArea.isBlockElement(parent) && parent.nodeName.toLowerCase() != "img") { - parent = parent.parentNode; + var dropDown = this.getButton(dropDownId); + if (dropDown) { + var classNames = new Array(); + var tagName = null; + var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null; + var parent = statusBarSelection ? statusBarSelection : this.editor.getParentElement(); + while (parent && !HTMLArea.isBlockElement(parent) && parent.nodeName.toLowerCase() != "img") { + parent = parent.parentNode; + } + if (parent) { + tagName = parent.nodeName.toLowerCase(); + classNames = this.getClassNames(parent); + } + if (tagName && tagName !== "body"){ + this.buildDropDownOptions(dropDown, tagName); + this.setSelectedOption(dropDown, classNames); + } else { + this.initializeDropDown(dropDown); + dropDown.setDisabled(true); + } } - if (parent) { - tagName = parent.nodeName.toLowerCase(); - classNames = this.getClassNames(parent); - } - if (tagName && tagName !== "body"){ - this.buildDropDownOptions(dropDown, tagName); - this.setSelectedOption(dropDown, classNames); - } else { - this.initializeDropDown(dropDown); - } - dropDown.className = ""; - if (dropDown.disabled) { - dropDown.className = "buttonDisabled"; - } }, /* @@ -315,29 +310,20 @@ * This function reinitializes the options of the dropdown */ initializeDropDown : function (dropDown) { - if (HTMLArea.is_gecko) { - while (dropDown.options.length > 0) { - dropDown.remove(dropDown.options.length-1); - } - } else { - while (dropDown.firstChild) { - dropDown.removeChild(dropDown.firstChild); - } - } - var owner = dropDown.ownerDocument; - if (!owner) { // IE5.5 does not report any ownerDocument - owner = window.document; - } - var styleOption = owner.createElement("option"); - styleOption = dropDown.appendChild(styleOption); - styleOption.value = "none"; - styleOption.text = this.localize("No style"); + var store = dropDown.getStore(); + store.removeAll(true); + store.insert(0, new store.recordType({ + text: this.localize('No style'), + value: 'none' + })); + dropDown.setValue('none'); }, /* * This function builds the options to be displayed in the dropDown box */ buildDropDownOptions : function (dropDown, tagName) { + var store = dropDown.getStore(); var cssArray = new Array(); this.initializeDropDown(dropDown); // Get classes allowed for all tags @@ -393,22 +379,16 @@ } cssArray = sortedCssArray; } - var doc = dropDown.ownerDocument; - if (!doc) { // IE5.5 does not report any ownerDocument - doc = window.document; - } for (var cssClass in cssArray) { if (cssArray.hasOwnProperty(cssClass) && cssArray[cssClass]) { - if (cssClass == "none") { - dropDown.options[0].text = cssArray[cssClass]; + if (cssClass == 'none') { + store.getAt(0).set('text', cssArray[cssClass]); } else { - var styleOption = doc.createElement("option"); - styleOption = dropDown.appendChild(styleOption); - styleOption.value = cssClass; - styleOption.text = cssArray[cssClass]; - if (!this.editor.config.disablePCexamples && HTMLArea.classesValues && HTMLArea.classesValues[cssClass] && !HTMLArea.classesNoShow[cssClass]) { - dropDown.options[dropDown.options.length-1].setAttribute("style", HTMLArea.classesValues[cssClass]); - } + store.add(new store.recordType({ + text: cssArray[cssClass], + value: cssClass, + style: (!this.editor.config.disablePCexamples && HTMLArea.classesValues && HTMLArea.classesValues[cssClass] && !HTMLArea.classesNoShow[cssClass]) ? HTMLArea.classesValues[cssClass] : null + })); } } } @@ -418,36 +398,35 @@ * This function sets the selected option of the dropDown box */ setSelectedOption : function (dropDown, classNames, noUnknown, defaultClass) { - dropDown.selectedIndex = 0; + var store = dropDown.getStore(); + dropDown.setValue('none'); if (classNames.length) { - for (var i = dropDown.options.length; --i >= 0;) { - if (classNames[classNames.length-1] == dropDown.options[i].value) { - dropDown.options[i].selected = true; - dropDown.selectedIndex = i; - if (!defaultClass) { - dropDown.options[0].text = this.localize("Remove style"); - } - break; + var index = store.findExact('value', classNames[classNames.length-1]); + if (index != -1) { + dropDown.setValue(classNames[classNames.length-1]); + if (!defaultClass) { + store.getAt(0).set('text', this.localize('Remove style')); } } - if (dropDown.selectedIndex == 0 && !noUnknown) { - dropDown.options[dropDown.options.length] = new Option(this.localize("Unknown style"), classNames[classNames.length-1]); - dropDown.options[dropDown.options.length-1].selected = true; - dropDown.selectedIndex = dropDown.options.length-1; - } - for (var i = dropDown.options.length; --i >= 0;) { - if (("," + classNames.join(",") + ",").indexOf("," + dropDown.options[i].value + ",") !== -1) { - if (dropDown.selectedIndex != i) { - dropDown.options[i] = null; - } + if (index == -1 && !noUnknown) { + store.add(new store.recordType({ + text: this.localize('Unknown style'), + value: classNames[classNames.length-1] + })); + index = store.getCount()-1; + dropDown.setValue(classNames[classNames.length-1]); + if (!defaultClass) { + store.getAt(0).set('text', this.localize('Remove style')); } } + store.each(function (option) { + if (store.indexOf(option) != index && (',' + classNames.join(',') + ',').indexOf(',' + option.get('value') + ',') != -1) { + store.removeAt(store.indexOf(option)); + } + return true; + }); } - if (dropDown.options.length > 1) { - dropDown.disabled = false; - } else { - dropDown.disabled = true; - } + dropDown.setDisabled(!(store.getCount()>1)); }, /* @@ -456,8 +435,7 @@ 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.cssTimeout = this.buildCssArray.defer(200, this, [editor, dropDownId]); this.cssParseCount++; } else { this.cssTimeout = null; Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/CharacterMap/character-map.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/CharacterMap/character-map.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/CharacterMap/character-map.js (copie de travail) @@ -3,7 +3,7 @@ * * (c) 2004 Bernhard Pfeifer novocaine@gmx.net * (c) 2004 systemconcept.de. Authored by Holger Hees based on HTMLArea XTD 1.5 (http://mosforge.net/projects/htmlarea3xtd/). -* (c) 2005-2009 Stanislas Rolland +* (c) 2005-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -106,7 +106,7 @@ * * @return void */ - onUpdateToolbar : function () { + onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) { // Reclaim focus if (this.dialog) { this.dialog.focus(); Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/context-menu.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/context-menu.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/context-menu.js (copie de travail) @@ -2,7 +2,7 @@ * Copyright notice * * Copyright (c) 2003 dynarch.com. Authored by Mihai Bazon. Sponsored by www.americanbible.org. -* Copyright (c) 2004-2009 Stanislas Rolland +* Copyright (c) 2004-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -32,26 +32,28 @@ * * TYPO3 SVN ID: $Id$ */ - ContextMenu = HTMLArea.Plugin.extend({ - constructor : function(editor, pluginName) { this.base(editor, pluginName); }, - /* * This function gets called by the class constructor */ configurePlugin : function(editor) { - this.currentMenu = null; - this.keys = []; - this.eventHandlers = {}; - + this.pageTSConfiguration = this.editorConfiguration.contextMenu; + if (this.pageTSConfiguration) { + if (this.pageTSConfiguration.showButtons) { + this.showButtons = this.pageTSConfiguration.showButtons; + } + if (this.pageTSConfiguration.hideButtons) { + this.hideButtons = this.pageTSConfiguration.hideButtons; + } + } /* * Registering plugin "About" information */ var pluginInformation = { - version : "2.0", + version : "3.0", developer : "Mihai Bazon & Stanislas Rolland", developerUrl : "http://www.sjbr.ca/", copyrightOwner : "dynarch.com & Stanislas Rolland", @@ -60,541 +62,201 @@ license : "GPL" }; this.registerPluginInformation(pluginInformation); - return true; }, - /* * This function gets called when the editor gets generated */ - onGenerate : function() { - this.editor.eventHandlers["contextMenu"] = this.makeFunctionReference("popupMenu"); - HTMLArea._addEvent((HTMLArea.is_ie ? this.editor._doc.body : this.editor._doc), (HTMLArea.is_opera ? "mousedown" : "contextmenu"), this.editor.eventHandlers["contextMenu"]); + onGenerate: function() { + // Build the context menu + this.menu = new Ext.menu.Menu({ + cls: 'htmlarea-context-menu', + height: 800, + defaultType: 'menuitem', + listeners: { + itemClick: { + fn: this.onItemClick, + scope: this + }, + show: { + fn: this.onShow, + scope: this + }, + hide: { + fn: this.onHide, + scope: this + } + }, + items: this.buildItemsConfig() + }); + // Monitor contextmenu clicks on the iframe + this.menu.mon(Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement), 'contextmenu', this.show, this, {single: true}); }, - - popupMenu : function(ev, target) { - if (HTMLArea.is_opera && ev.button < 2) { - return false; - } - var editor = this.editor; - if (!ev) var ev = window.event; - if (!target) var target = (ev.target) ? ev.target : ev.srcElement; - if (this.currentMenu) this.currentMenu.parentNode.removeChild(this.currentMenu); - this.keys = []; - var ifpos = ContextMenu.getPos(this.editor._iframe); - var x = ev.clientX + ifpos.x; - var y = ev.clientY + ifpos.y; - - var doc, list, separator = false; - - if (!HTMLArea.is_ie) { - doc = document; - } else { - var popup = this.iePopup = window.createPopup(); - doc = popup.document; - var head = doc.getElementsByTagName("head")[0]; - var link = doc.createElement("link"); - link.rel = "stylesheet"; - link.type = "text/css"; - if ( _editor_CSS.indexOf("http") == -1 ) link.href = _typo3_host_url + _editor_CSS; - else link.href = _editor_CSS; - head.appendChild(link); - } - - list = doc.createElement("ul"); - list.className = "htmlarea-context-menu"; - doc.body.appendChild(list); - - var options = this.getContextMenu(target); - var n = options.length; - for (var i=0; i < n; ++i) { - var option = options[i]; - if (!option){ - separator = true; - } else { - var item = doc.createElement("li"); - list.appendChild(item); - var label = option[0]; - if (separator) { - HTMLArea._addClass(item, "separator"); - separator = false; + /* + * Create the menu items config + */ + buildItemsConfig: function () { + var itemsConfig = []; + // Walk through the editor toolbar configuration nested arrays: [ toolbar [ row [ group ] ] ] + var firstInGroup = true, convertedItemId; + Ext.each(this.editor.config.toolbar, function (row) { + // Add the groups + firstInGroup = true; + Ext.each(row, function (group) { + if (!firstInGroup) { + // If a visible item was added to the line + itemsConfig.push({ + xtype: 'menuseparator', + cls: 'separator' + }); } - item.__msh = { - item: item, - label: label, - action: option[1], - tooltip: option[2] || null, - icon: option[3] || null, - activate: ContextMenu.activateHandler(item, this), - cmd: option[4] || null, - dialog: option[5] || null - }; - label = label.replace(/_([a-zA-Z0-9])/, "$1"); - if (label != option[0]) this.keys.push([ RegExp.$1, item ]); - label = label.replace(/__/, "_"); - var button = doc.createElement("button"); - HTMLArea._addClass(button, "button"); - if (item.__msh.cmd) { - HTMLArea._addClass(button, item.__msh.cmd); - if (editor._toolbarObjects[item.__msh.cmd] && editor._toolbarObjects[item.__msh.cmd].active) { - HTMLArea._addClass(button, "buttonActive"); + firstInGroup = true; + // Add each item + Ext.each(group, function (itemId) { + convertedItemId = this.editorConfiguration.convertButtonId[itemId]; + if ((!this.showButtons || this.showButtons.indexOf(convertedItemId) !== -1) + && (!this.hideButtons || this.hideButtons.indexOf(convertedItemId) === -1)) { + var button = this.getButton(itemId); + if (button && button.getXType() === 'htmlareabutton' && !button.hideInContextMenu) { + var itemId = button.getItemId(); + itemsConfig.push({ + itemId: itemId, + cls: 'button', + overCls: 'hover', + text: (button.contextMenuTitle || button.tooltip.title), + iconCls: button.iconCls, + helpText: this.localize(itemId + '-helpText') || this.localize(itemId + '-tooltip'), + hidden: true + }); + firstInGroup = false; + } } - } else if (item.__msh.icon) { - button.innerHTML = ""; - } - item.appendChild(button); - item.innerHTML = item.innerHTML + label; - // Setting event handlers on the menu items - item.__msh.mouseover = ContextMenu.mouseOverHandler(editor, item); - HTMLArea._addEvent(item, "mouseover", item.__msh.mouseover); - item.__msh.mouseout = ContextMenu.mouseOutHandler(item); - HTMLArea._addEvent(item, "mouseout", item.__msh.mouseout); - item.__msh.contextmenu = ContextMenu.itemContextMenuHandler(item); - HTMLArea._addEvent(item, "contextmenu", item.__msh.contextmenu); - if (!HTMLArea.is_ie) { - item.__msh.mousedown = ContextMenu.mouseDownHandler(item); - HTMLArea._addEvent(item, "mousedown", item.__msh.mousedown); - } - item.__msh.mouseup = ContextMenu.mouseUpHandler(item, this); - HTMLArea._addEvent(item, "mouseup", item.__msh.mouseup); - } + return true; + }, this); + return true; + }, this); + return true; + }, this); + // If a visible item was added + if (!firstInGroup) { + itemsConfig.push({ + xtype: 'menuseparator', + cls: 'separator' + }); } - if (n) { - if(!HTMLArea.is_ie) { - var dx = x + list.offsetWidth - window.innerWidth - window.pageXOffset + 4; - var dy = y + list.offsetHeight - window.innerHeight - window.pageYOffset + 4; - if(dx > 0) x -= dx; - if(dy > 0) y -= dy; - list.style.left = x + "px"; - list.style.top = y + "px"; - } else { - // determine the size - list.style.left = "0px"; - list.style.top = "0px"; - var foobar = document.createElement("ul"); - foobar.className = "htmlarea-context-menu"; - foobar.innerHTML = list.innerHTML; - editor._iframe.contentWindow.parent.document.body.appendChild(foobar); - this.iePopup.show(ev.screenX, ev.screenY, foobar.clientWidth+2, foobar.clientHeight+2); - editor._iframe.contentWindow.parent.document.body.removeChild(foobar); - } - this.currentMenu = list; - this.timeStamp = (new Date()).getTime(); - this.eventHandlers["documentClick"] = this.makeFunctionReference("documentClickHandler"); - HTMLArea._addEvent((HTMLArea.is_ie ? document.body : document), "mousedown", this.eventHandlers["documentClick"]); - HTMLArea._addEvent((HTMLArea.is_ie ? editor._doc.body : editor._doc), "mousedown", this.eventHandlers["documentClick"]); - if (this.keys.length > 0) { - this.eventHandlers["keyPress"] = ContextMenu.keyPressHandler(this); - HTMLArea._addEvents((HTMLArea.is_ie ? editor._doc.body : editor._doc), ["keypress", "keydown"], this.eventHandlers["keyPress"]); - } - } - HTMLArea._stopEvent(ev); + // Add special target delete item + var itemId = 'DeleteTarget'; + itemsConfig.push({ + itemId: itemId, + cls: 'button', + overCls: 'hover', + iconCls: itemId, + helpText: this.localize('Remove this node from the document') + }); + return itemsConfig; + }, + /* + * Handler when the menu gets shown + */ + onShow: function () { + this.menu.mun(Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement), 'contextmenu', this.show, this); + this.menu.mon(Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement), 'mousedown', this.menu.hide, this.menu, {single: true}); + }, + /* + * Handler when the menu gets hidden + */ + onHide: function () { + this.menu.mon(Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement), 'contextmenu', this.show, this); + this.menu.mun(Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement), 'mousedown', this.menu.hide, this.menu); + }, + /* + * Handler to show the context menu + */ + show: function (event, target) { + // Need to wait a while for the toolbar state to be updated + this.showMenu.defer(150, this, [event, target]); + event.stopEvent(); return false; }, - - pushOperations : function (opcodes, elmenus, pluginId) { - var editor = this.editor; - var pluginInstance = this.editor.plugins[pluginId]; - if (pluginInstance) { - pluginInstance = pluginInstance.instance; - } - var toolbarObjects = editor._toolbarObjects; - var btnList = editor.config.btnList; - var enabled = false, opcode, opEnabled = [], i = opcodes.length; - for (i; i > 0;) { - opcode = opcodes[--i]; - opEnabled[opcode] = toolbarObjects[opcode] && toolbarObjects[opcode].enabled; - enabled = enabled || opEnabled[opcode]; - } - if (enabled && elmenus.length) { - elmenus.push(null); - } - for (i = opcodes.length; i > 0;) { - opcode = opcodes[--i]; - if (opEnabled[opcode]) { - switch (pluginId) { - case "TableOperations" : - elmenus.push([ - this.localize(opcode + "-title"), - ContextMenu.tableOperationsHandler(editor, pluginInstance, opcode), - this.localize(opcode + "-tooltip"), - btnList[opcode][1], - opcode, - btnList[opcode][7] - ]); - break; - case "BlockElements" : - elmenus.push([this.localize(opcode + "-title"), - ContextMenu.blockElementsHandler(editor, null, opcode), - this.localize(opcode + "-tooltip"), - btnList[opcode][1], opcode]); - break; - default : - elmenus.push([this.localize(opcode + "-title"), - ContextMenu.execCommandHandler(editor, opcode), - this.localize(opcode + "-tooltip"), - btnList[opcode][1], opcode]); - break; - } - } - } + /* + * Show the context menu + */ + showMenu: function (event, target) { + this.showContextItems(target); + var iframeEl = this.editor.iframe.getEl(); + this.menu.showAt([Ext.get(target).getX() + iframeEl.getX(), Ext.get(target).getY() + iframeEl.getY()]); }, - - getContextMenu : function(target) { - var editor = this.editor; - var toolbarObjects = editor._toolbarObjects; - var config = editor.config; - var btnList = config.btnList; - var menu = [], opcode; - var tbo = this.editor.plugins["TableOperations"]; - if (tbo) tbo = "TableOperations"; - - var selection = editor.hasSelectedText(); - if(selection) { - if (toolbarObjects['Cut'] && toolbarObjects['Cut'].enabled) { - opcode = "Cut"; - menu.push([this.localize(opcode), ContextMenu.execCommandHandler(editor, opcode), null, btnList[opcode][1], opcode]); - } - if (toolbarObjects['Copy'] && toolbarObjects['Copy'].enabled) { - opcode = "Copy"; - menu.push([this.localize(opcode), ContextMenu.execCommandHandler(editor, opcode), null, btnList[opcode][1], opcode]); - } - } - if (toolbarObjects['Paste'] && toolbarObjects['Paste'].enabled) { - opcode = "Paste"; - menu.push([this.localize(opcode), ContextMenu.execCommandHandler(editor, opcode), null, btnList[opcode][1], opcode]); - } - - var currentTarget = target, - tmp, tag, link = false, - table = null, tr = null, td = null, img = null, list = null, div = null; - - for(; target; target = target.parentNode) { - tag = target.nodeName; - if(!tag) continue; - tag = tag.toLowerCase(); - switch (tag) { - case "img": - img = target; - if (toolbarObjects["InsertImage"] && toolbarObjects["InsertImage"].enabled) { - if (menu.length) menu.push(null); - menu.push( - [this.localize("Image Properties"), - ContextMenu.imageHandler(editor, img), - this.localize("Show the image properties dialog"), - btnList["InsertImage"][1], "InsertImage"] - ); + /* + * Show items depending on context + */ + showContextItems: function (target) { + var lastIsSeparator = false, lastIsButton = false, xtype, lastVisible; + this.menu.cascade(function (menuItem) { + xtype = menuItem.getXType(); + if (xtype === 'menuseparator') { + menuItem.setVisible(lastIsButton); + lastIsButton = false; + } else if (xtype === 'menuitem') { + var button = this.getButton(menuItem.getItemId()); + if (button) { + menuItem.setVisible(!button.disabled); + lastIsButton = lastIsButton || !button.disabled; + } else { + // Special target delete item + this.deleteTarget = Ext.get(target); + if (/^(html|body)$/i.test(target.nodeName)) { + this.deleteTarget = null; + } else if (/^(table|thead|tbody|tr|td|th|tfoot)$/i.test(target.nodeName)) { + var targetAncestor = this.deleteTarget.findParent('table'); + } else if (/^(ul|ol|dl|li|dd|dt)$/i.test(target.nodeName)) { + var targetAncestor = this.deleteTarget.findParent('ul') || this.deleteTarget.findParent('ol') || this.deleteTarget.findParent('dl'); + } + if (targetAncestor) { + this.deleteTarget = Ext.get(targetAncestor); + } + if (this.deleteTarget) { + menuItem.setVisible(true); + menuItem.setText(this.localize('Remove the') + ' <' + this.deleteTarget.dom.nodeName.toLowerCase() + '> '); + lastIsButton = true; + } else { + menuItem.setVisible(false); + } } - break; - case "a": - link = target; - if (toolbarObjects["CreateLink"]) { - if (menu.length) menu.push(null); - menu.push( - [this.localize("Modify Link"), - this.linkHandler(link, "ModifyLink"), - this.localize("Current URL is") + ': ' + link.href, - btnList["CreateLink"][1], "CreateLink"], - [this.localize("Check Link"), - this.linkHandler(link, "CheckLink"), - this.localize("Opens this link in a new window"), - null, null], - [this.localize("Remove Link"), - this.linkHandler(link, "RemoveLink"), - this.localize("Unlink the current element"), - editor.imgURL("ed_unlink.gif"), "UnLink"] - ); - } - break; - case "td": - case "th": - td = target; - if(!tbo) break; - this.pushOperations(["TO-cell-split", "TO-cell-delete", "TO-cell-insert-after", "TO-cell-insert-before", "TO-cell-prop"], menu, tbo); - break; - case "tr": - tr = target; - if(!tbo) break; - opcode = "TO-cell-merge"; - if (toolbarObjects[opcode] && toolbarObjects[opcode].enabled) { - menu.push([this.localize(opcode + "-title"), - ContextMenu.tableOperationsHandler(editor, this.editor.plugins.TableOperations.instance, opcode), - this.localize(opcode + "-tooltip"), - btnList[opcode][1], opcode]); - } - this.pushOperations(["TO-row-split", "TO-row-delete", "TO-row-insert-under", "TO-row-insert-above", "TO-row-prop"], menu, tbo); - break; - case "table": - table = target; - if(!tbo) break; - this.pushOperations(["TO-col-split", "TO-col-delete", "TO-col-insert-after", "TO-col-insert-before", "TO-col-prop"], menu, tbo); - this.pushOperations(["TO-toggle-borders", "TO-table-restyle", "TO-table-prop"], menu, tbo); - break; - case "ol": - case "ul": - case "dl": - list = target; - break; - case "div": - div = target; - break; - case "body": - this.pushOperations(["JustifyFull", "JustifyRight", "JustifyCenter", "JustifyLeft"], menu, "BlockElements"); - break; } - } - - if (selection && !link && btnList.CreateLink) { - if (menu.length) menu.push(null); - menu.push([this.localize("Make link"), - this.linkHandler(link, "MakeLink"), - this.localize("Create a link"), - btnList["CreateLink"][1],"CreateLink"]); - } - - if (!/^(html|body)$/i.test(currentTarget.nodeName)) { - if (/^(table|thead|tbody|tr|td|th|tfoot)$/i.test(currentTarget.nodeName)) { - tmp = table; - table = null; - } else if(list) { - tmp = list; - list = null; - } else { - tmp = currentTarget; + if (!menuItem.hidden) { + lastVisible = menuItem; } - if (menu.length) menu.push(null); - menu.push( - [this.localize("Remove the") + " <" + tmp.tagName.toLowerCase() + "> " + this.localize("Element"), - this.deleteElementHandler(tmp, table), this.localize("Remove this node from the document")], - [this.localize("Insert paragraph before"), - ContextMenu.blockElementsHandler(editor, tmp, "InsertParagraphBefore"), this.localize("Insert a paragraph before the current node"), null, "InsertParagraphBefore"], - [this.localize("Insert paragraph after"), - ContextMenu.blockElementsHandler(editor, tmp, "InsertParagraphAfter"), this.localize("Insert a paragraph after the current node"), null, "InsertParagraphAfter"] - ); + }, this); + // Hide the last item if it is a separator + if (!lastIsButton) { + lastVisible.setVisible(false); } - return menu; }, - - closeMenu : function() { - HTMLArea._removeEvent((HTMLArea.is_ie ? document.body : document), "mousedown", this.eventHandlers["documentClick"]); - HTMLArea._removeEvent((HTMLArea.is_ie ? this.editor._doc.body : this.editor._doc), "mousedown", this.eventHandlers["documentClick"]); - if (this.keys.length > 0) HTMLArea._removeEvent((HTMLArea.is_ie ? this.editor._doc.body : this.editor._doc), "keypress", this.eventHandlers["keyPress"]); - for (var handler in this.eventHandlers) this.eventHandlers[handler] = null; - var e, items = document.getElementsByTagName("li"); - if (HTMLArea.is_ie) items = this.iePopup.document.getElementsByTagName("li");; - for (var i = items.length; --i >= 0 ;) { - e = items[i]; - if ( e.__msh ) { - HTMLArea._removeEvent(e, "mouseover", e.__msh.mouseover); - e.__msh.mouseover = null; - HTMLArea._removeEvent(e, "mouseout", e.__msh.mouseout); - e.__msh.mouseout = null; - HTMLArea._removeEvent(e, "contextmenu", e.__msh.contextmenu); - e.__msh.contextmenu = null; - if (!HTMLArea.is_ie) HTMLArea._removeEvent(e, "mousedown", e.__msh.mousedown); - e.__msh.mousedown = null; - HTMLArea._removeEvent(e, "mouseup", e.__msh.mouseup); - e.__msh.mouseup = null; - e.__msh.action = null; - e.__msh.activate = null; - e.__msh = null; + /* + * Handler invoked when a menu item is clicked on + */ + onItemClick: function (item, event) { + var button = this.getButton(item.getItemId()); + if (button) { + button.fireEvent('click', button, event); + } else if (item.getItemId() === 'DeleteTarget') { + // Do not leave a non-ie table cell empty + var parent = this.deleteTarget.parent().dom; + parent.normalize(); + if (!Ext.isIE && /^(td|th)$/i.test(parent.nodeName) && parent.childNodes.length == 1) { + // Do not leave a non-ie table cell empty + this.deleteTarget.insertSibling(this.editor.document.createElement('br')); } - } - this.currentMenu.parentNode.removeChild(this.currentMenu); - this.currentMenu = null; - this.keys = []; - if (HTMLArea.is_ie) this.iePopup.hide(); - }, - - linkHandler : function (link, opcode) { - var editor = this.editor; - var self = this; - switch (opcode) { - case "MakeLink": - case "ModifyLink": - return (function() { - var obj = editor._toolbarObjects.CreateLink; - obj.cmd(editor, "CreateLink", link); - }); - case "CheckLink": - return (function() { - window.open(link.href); - }); - case "RemoveLink": - return (function() { - if (confirm(self.localize("Please confirm unlink") + "\n" + - self.localize("Link points to:") + " " + link.href)) { - var obj = editor._toolbarObjects.CreateLink; - obj.cmd(editor, "UnLink", link); - } - }); - } - }, - - deleteElementHandler : function (tmp,table) { - var editor = this.editor; - var self = this; - return (function() { - if(confirm(self.localize("Please confirm remove") + " " + tmp.tagName.toLowerCase())) { - var el = tmp; - var p = el.parentNode; - p.removeChild(el); - if(HTMLArea.is_gecko) { - if(p.tagName.toLowerCase() == "td" && !p.hasChildNodes()) p.appendChild(editor._doc.createElement("br")); - editor.forceRedraw(); - editor.focusEditor(); - editor.updateToolbar(); - if(table) { - var save_collapse = table.style.borderCollapse; - table.style.borderCollapse = "collapse"; - table.style.borderCollapse = "separate"; - table.style.borderCollapse = save_collapse; - } - } + // Try to find a reasonable replacement selection + var nextSibling = this.deleteTarget.dom.nextSibling; + var previousSibling = this.deleteTarget.dom.previousSibling; + if (nextSibling) { + this.editor.selectNode(nextSibling, true); + } else if (previousSibling) { + this.editor.selectNode(previousSibling, false); } - }); - }, - - documentClickHandler : function (ev) { - if (!ev) var ev = window.event; - if (!this.currentMenu) { - alert(this.localize("How did you get here? (Please report!)")); - return false; - } - var el = (ev.target) ? ev.target : ev.srcElement; - for (; el != null && el != this.currentMenu; el = el.parentNode); - if (el == null) { - this.closeMenu(); + this.deleteTarget.remove(); this.editor.updateToolbar(); } } }); - -ContextMenu.tableOperationsHandler = function(editor,tbo,opcode) { - return (function() { - tbo.onButtonPress(editor,opcode); - }); -}; - -ContextMenu.imageHandler = function(editor, currentTarget) { - return (function() { - var obj = editor._toolbarObjects.InsertImage; - obj.cmd(editor, obj.name, currentTarget); - if (HTMLArea.is_opera) { - editor._iframe.focus(); - } - if (!editor.config.btnList[obj.name][7]) { - editor.updateToolbar(); - } - }); -}; - -ContextMenu.execCommandHandler = function(editor,opcode) { - return (function() { - editor.execCommand(opcode); - }); -}; - -ContextMenu.blockElementsHandler = function(editor, currentTarget, buttonId) { - return (function() { - var blockElements = editor.plugins.BlockElements; - if (blockElements) { - blockElements = blockElements.instance; - blockElements.onButtonPress(editor, buttonId, currentTarget); - } else { - var el = currentTarget; - var par = el.parentNode; - var p = editor._doc.createElement("p"); - var after = (buttonId === "InsertParagraphAfter"); - p.appendChild(editor._doc.createElement("br")); - par.insertBefore(p, after ? el.nextSibling : el); - var sel = editor._getSelection(); - var range = editor._createRange(sel); - editor.selectNodeContents(p, true); - } - }); -}; - -ContextMenu.mouseOverHandler = function(editor,item) { - return (function() { - item.className += " hover"; - if (editor.getPluginInstance("StatusBar")) { - editor.getPluginInstance("StatusBar").setText(item.__msh.tooltip || " "); - } - }); -}; - -ContextMenu.mouseOutHandler = function(item) { - return (function() { - item.className = item.className.replace(/hover/,""); - }); -}; - -ContextMenu.itemContextMenuHandler = function(item) { - return (function(ev) { - item.__msh.activate(); - if(!HTMLArea.is_ie) HTMLArea._stopEvent(ev); - return false; - }); -}; - -ContextMenu.mouseDownHandler = function(item) { - return (function(ev) { - HTMLArea._stopEvent(ev); - return false; - }); -}; - -ContextMenu.mouseUpHandler = function(item,instance) { - return (function(ev) { - var timeStamp = (new Date()).getTime(); - if (timeStamp - instance.timeStamp > 500) { - item.__msh.activate(); - } - if (!HTMLArea.is_ie) { - HTMLArea._stopEvent(ev); - } - return false; - }); -}; - -ContextMenu.activateHandler = function(item,instance) { - return (function() { - item.__msh.action(); - if (!item.__msh.dialog) { - instance.editor.updateToolbar(); - } - instance.closeMenu(); - }); -}; - -ContextMenu.keyPressHandler = function(instance) { - return (function(ev) { - if (!ev) var ev = window.event; - if (ev.keyCode == 27) { - instance.closeMenu(); - return false; - } - if(ev.altKey && !ev.ctrlKey) { - var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase(); - var keys = instance.keys; - for (var i = keys.length; --i >= 0;) { - var k = keys[i]; - if (k[0].toLowerCase() == key) k[1].__msh.activate(); - } - HTMLArea._stopEvent(ev); - return false; - } - }); -}; - -ContextMenu.getPos = function(el) { - var r = { x: el.offsetLeft, y: el.offsetTop }; - if (el.offsetParent) { - var tmp = ContextMenu.getPos(el.offsetParent); - r.x += tmp.x; - r.y += tmp.y; - } - return r; -}; - Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/locallang.xml =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/locallang.xml (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/locallang.xml (copie de travail) @@ -44,7 +44,7 @@ - + Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/CopyPaste/copy-paste.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/CopyPaste/copy-paste.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/CopyPaste/copy-paste.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2008-2009 Stanislas Rolland +* (c) 2008-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -49,7 +49,7 @@ * Registering plugin "About" information */ var pluginInformation = { - version : "1.0", + version : "2.0", developer : "Stanislas Rolland", developerUrl : "http://www.sjbr.ca/", copyrightOwner : "Stanislas Rolland", @@ -70,14 +70,14 @@ tooltip : this.localize(buttonId.toLowerCase()), action : "onButtonPress", context : button[0], + selection : button[3], hotKey : (this.buttonsConfiguration[button[2]] ? this.buttonsConfiguration[button[2]].hotKey : (button[1] ? button[1] : null)) }; this.registerButton(buttonConfiguration); if (!this.isButtonInToolbar(buttonId)) { var hotKeyConfiguration = { id : buttonConfiguration.hotKey, - cmd : buttonConfiguration.id, - action : buttonConfiguration.action + cmd : buttonConfiguration.id }; this.registerHotKey(hotKeyConfiguration); } @@ -90,9 +90,9 @@ * The list of buttons added by this plugin */ buttonList : { - Copy : [null, "c", "copy"], - Cut : [null, "x", "cut"], - Paste : [null, "v", "paste"] + Copy : [null, "c", "copy", true], + Cut : [null, "x", "cut", true], + Paste : [null, "v", "paste", false] }, /* @@ -119,8 +119,7 @@ this.applyBrowserCommand(buttonId); } else if (buttonId == "Cut") { // If we are handling the cut hotkey - var removeEmpyLinkLaterFunctRef = this.makeFunctionReference("removeEmptyLinkLater"); - window.setTimeout(removeEmpyLinkLaterFunctRef, 50); + this.removeEmptyLinkLater.defer(50, this); } break; case "Paste": @@ -129,11 +128,14 @@ this.applyBrowserCommand(buttonId); } // In FF3, the paste operation will indeed trigger the onPaste event not in FF2; nor in Opera - if (HTMLArea.is_opera || (HTMLArea.is_gecko && navigator.productSub < 20080514) || HTMLArea.is_safari) { - var cleanLaterFunctRef = this.getPluginInstance("DefaultClean") ? this.getPluginInstance("DefaultClean").cleanLaterFunctRef : (this.getPluginInstance("TYPO3HtmlParser") ? this.getPluginInstance("TYPO3HtmlParser").cleanLaterFunctRef : null); - if (cleanLaterFunctRef) { - window.setTimeout(cleanLaterFunctRef, 50); + if (Ext.isOpera || Ext.isGecko2 || Ext.isWebKit) { + var cleaner = this.getPluginInstance('DefaultClean'); + if (!cleaner) { + cleaner = this.getPluginInstance('TYPO3HtmlParser'); } + if (cleaner) { + cleaner.clean.defer(50, cleaner); + } } break; default: @@ -150,7 +152,7 @@ try { this.editor._doc.execCommand(buttonId, false, null); } catch (e) { - if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) { + if (Ext.isGecko) { this.mozillaClipboardAccessException(); } } @@ -172,11 +174,11 @@ if (/^(a)$/i.test(parent.nodeName)) { parent.normalize(); if (!parent.innerHTML || (parent.childNodes.length == 1 && /^(br)$/i.test(parent.firstChild.nodeName))) { - if (HTMLArea.is_gecko) { + if (!Ext.isIE) { var container = parent.parentNode; this.editor.removeMarkup(parent); // Opera does not render empty list items - if (HTMLArea.is_opera && /^(li)$/i.test(container.nodeName) && !container.firstChild) { + if (Ext.isOpera && /^(li)$/i.test(container.nodeName) && !container.firstChild) { container.innerHTML = "
"; this.editor.selectNodeContents(container, true); } @@ -185,7 +187,7 @@ } } } - if (HTMLArea.is_safari) { + if (Ext.isWebKit) { // Remove Apple's span and font tags this.editor.cleanAppleStyleSpans(this.editor._doc.body); // Reset Safari selection in order to prevent insertion of span and/or font tags on next text input @@ -215,7 +217,7 @@ case "Cut" : HTMLArea.copiedCells = null; var endBlocks = this.editor.getEndBlocks(selection); - if ((/^(tr)$/i.test(parent.nodeName) && HTMLArea.is_gecko) || (/^(td|th)$/i.test(endBlocks.start.nodeName) && /^(td|th)$/i.test(endBlocks.end.nodeName) && (HTMLArea.is_ie || HTMLArea.is_safari || HTMLArea.is_opera) && endBlocks.start != endBlocks.end)) { + if ((/^(tr)$/i.test(parent.nodeName) && !Ext.isIE) || (/^(td|th)$/i.test(endBlocks.start.nodeName) && /^(td|th)$/i.test(endBlocks.end.nodeName) && !Ext.isGecko && endBlocks.start != endBlocks.end)) { HTMLArea.copiedCells = this.collectCells(buttonId, selection, endBlocks); if (buttonId === "Cut") return true; } @@ -231,7 +233,7 @@ pasteCells : function (selection, endBlocks) { var cell = null; - if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) { + if (Ext.isGecko) { range = selection.getRangeAt(0); cell = range.startContainer.childNodes[range.startOffset]; while (cell && !HTMLArea.isBlockElement(cell)) { @@ -289,7 +291,7 @@ } var row = null; var cutRows = []; - if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) { // Firefox + if (Ext.isGecko) { if (selection.rangeCount == 1) { // Collect the cells in the selected row cells = []; for (var i = 0, n = endBlocks.start.cells.length; i < n; ++i) { @@ -389,19 +391,16 @@ /* * This function gets called when the toolbar is updated */ - onUpdateToolbar : function () { - if (this.getEditorMode() === "wysiwyg" || this.editor.isEditable()) { - var buttonId = "Paste"; - if (typeof(this.editor._toolbarObjects[buttonId]) !== "undefined") { - try { - this.editor._toolbarObjects[buttonId].state("enabled", this.editor._doc.queryCommandEnabled(buttonId)); - } catch(e) { - this.editor._toolbarObjects[buttonId].state("enabled", false); - } + onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) { + if (mode === 'wysiwyg' && this.editor.isEditable() && button.itemId === 'Paste') { + try { + button.setDisabled(!this.editor._doc.queryCommandEnabled(button.itemId)); + } catch(e) { + button.setDisabled(true); } } }, - + /* * Mozilla clipboard access exception handler */ Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultClean/default-clean.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultClean/default-clean.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultClean/default-clean.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2008-2009 Stanislas Rolland +* (c) 2008-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -63,7 +63,8 @@ id : buttonId, tooltip : this.localize(buttonId + "-Tooltip"), action : "onButtonPress", - hide : true + hide : true, + hideInContextMenu: true }; this.registerButton(buttonConfiguration); }, @@ -84,14 +85,16 @@ this.clean(); return false; }, - - onGenerate : function () { - var doc = this.editor._doc; - // Function reference used on paste with older versions of Mozilla/Firefox in which onPaste is not fired - this.cleanLaterFunctRef = this.makeFunctionReference("clean"); - HTMLArea._addEvents((HTMLArea.is_ie ? doc.body : doc), ["paste","dragdrop","drop"], DefaultClean.wordCleanHandler, true); + /* + * This function gets called when the editor is generated + */ + onGenerate: function () { + var documentElement = Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement); + this.editor.iframe.mon(documentElement, 'paste', this.wordCleanHandler, this); + this.editor.iframe.mon(documentElement, 'dragdrop', this.wordCleanHandler, this); + this.editor.iframe.mon(documentElement, 'drop', this.wordCleanHandler, this); }, - + clean : function () { function clearClass(node) { var newc = node.className.replace(/(^|\s)mso.*?(\s|$)/ig,' '); @@ -167,34 +170,16 @@ if (HTMLArea.is_safari) { this.editor.cleanAppleStyleSpans(this.editor._doc.body); } + }, + /* + * Handler for paste, dragdrop and drop events + */ + wordCleanHandler: function (event) { + // If we dropped an image dragged from the TYPO3 Image plugin, let's close the dialog window + if (typeof(HTMLArea.Dialog) != "undefined" && HTMLArea.Dialog.TYPO3Image) { + HTMLArea.Dialog.TYPO3Image.close(); + } else { + this.clean.defer(250, this); + } } }); - -/* - * Closure avoidance for IE - */ -DefaultClean.cleanLater = function (editorNumber) { - var editor = RTEarea[editorNumber].editor; - editor.getPluginInstance("DefaultClean").clean(); -}; - -/* - * Handler for paste, dragdrop and drop events - */ -DefaultClean.wordCleanHandler = function (ev) { - if (!ev) var ev = window.event; - var target = ev.target ? ev.target : ev.srcElement; - var owner = target.ownerDocument ? target.ownerDocument : target; - if (HTMLArea.is_ie) { // IE5.5 does not report any ownerDocument - while (owner.parentElement) { owner = owner.parentElement; } - } - var editor = RTEarea[owner._editorNo].editor; - - // If we dropped an image dragged from the TYPO3 Image plugin, let's close the dialog window - if (typeof(HTMLArea.Dialog) != "undefined" && HTMLArea.Dialog.TYPO3Image) { - HTMLArea.Dialog.TYPO3Image.close(); - } else { - window.setTimeout("DefaultClean.cleanLater(\'" + editor._editorNumber + "\');", 250); - } -}; - Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultInline/default-inline.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultInline/default-inline.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultInline/default-inline.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2007-2009 Stanislas Rolland +* (c) 2007-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -44,7 +44,7 @@ * Registering plugin "About" information */ var pluginInformation = { - version : "1.0", + version : "1.1", developer : "Stanislas Rolland", developerUrl : "http://www.fructifor.ca/", copyrightOwner : "Stanislas Rolland", @@ -57,11 +57,8 @@ /* * Registering the buttons */ - var buttonList = DefaultInline.buttonList, buttonId; - var n = buttonList.length; - for (var i = 0; i < n; ++i) { - var button = buttonList[i]; - buttonId = button[0]; + Ext.each(this.buttonList, function (button) { + var buttonId = button[0]; var buttonConfiguration = { id : buttonId, tooltip : this.localize(buttonId + "-Tooltip"), @@ -71,11 +68,19 @@ hotKey : (this.editorConfiguration.buttons[buttonId.toLowerCase()]?this.editorConfiguration.buttons[buttonId.toLowerCase()].hotKey:null) }; this.registerButton(buttonConfiguration); - } - + return true; + }, this); return true; - }, - + }, + /* The list of buttons added by this plugin */ + buttonList: [ + ["Bold", null], + ["Italic", null], + ["StrikeThrough", null], + ["Subscript", null], + ["Superscript", null], + ["Underline", null] + ], /* * This function gets called when some inline element button was pressed. */ @@ -96,34 +101,16 @@ /* * This function gets called when the toolbar is updated */ - onUpdateToolbar : function () { - var editor = this.editor; - var buttonList = DefaultInline.buttonList; - var buttonId, n = buttonList.length, commandState; - if (editor.getMode() === "wysiwyg" && editor.isEditable()) { - for (var i = 0; i < n; ++i) { - buttonId = buttonList[i][0]; - if (this.isButtonInToolbar(buttonId)) { - commandState = false; - try { - commandState = editor._doc.queryCommandState(buttonId); - } catch(e) { - commandState = false; - } - editor._toolbarObjects[buttonId].state("active", commandState); - } + onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) { + if (mode === 'wysiwyg' && this.editor.isEditable()) { + var commandState = false; + try { + commandState = this.editor._doc.queryCommandState(button.itemId); + } catch(e) { + commandState = false; } + button.setInactive(!commandState); } } }); -/* The list of buttons added by this plugin */ -DefaultInline.buttonList = [ - ["Bold", null], - ["Italic", null], - ["StrikeThrough", null], - ["Subscript", null], - ["Superscript", null], - ["Underline", null] -]; - Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/DefinitionList/definition-list.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/DefinitionList/definition-list.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/DefinitionList/definition-list.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2008-2009 Stanislas Rolland +* (c) 2008-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -71,34 +71,36 @@ /* * Registering the buttons */ - for (var buttonId in this.buttonList) { - if (this.buttonList.hasOwnProperty(buttonId)) { - var button = this.buttonList[buttonId]; - var buttonConfiguration = { - id : buttonId, - tooltip : this.localize(buttonId + "-Tooltip"), - action : "onButtonPress", - context : button[0], - hotKey : (this.buttonsConfiguration[button[2]] ? this.buttonsConfiguration[button[2]].hotKey : (button[1] ? button[1] : null)) - }; - this.registerButton(buttonConfiguration); - } - } - + Ext.each(this.buttonList, function (button) { + var buttonId = button[0]; + var buttonConfiguration = { + id : buttonId, + tooltip : this.localize(buttonId + "-Tooltip"), + action : "onButtonPress", + context : button[1], + hotKey : (this.buttonsConfiguration[button[3]] ? this.buttonsConfiguration[button[3]].hotKey : (button[2] ? button[2] : null)), + noAutoUpdate : button[4] + }; + this.registerButton(buttonConfiguration); + }, this); return true; }, /* * The list of buttons added by this plugin */ - buttonList : { - Indent : [null, "TAB", "indent"], - Outdent : [null, "SHIFT-TAB", "outdent"], - DefinitionList : [null, null, "definitionlist"], - DefinitionItem : ["dd,dt", null, "definitionitem"] - }, - + buttonList : [ + ['Indent', null, 'TAB', 'indent', false], + ['Outdent', null, 'SHIFT-TAB', 'outdent', false], + ['DefinitionList', null, null, 'definitionlist', true], + ['DefinitionItem', 'dd,dt', null, 'definitionitem', false] + ], /* + * This function gets called when the plugin is generated + * Avoid re-execution of the base function + */ + onGenerate: Ext.emptyFn, + /* * This function gets called when a button was pressed. * * @param object editor: the editor instance @@ -115,7 +117,7 @@ this.editor.focusEditor(); var selection = editor._getSelection(); var range = editor._createRange(selection); - var statusBarSelection = editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null; + var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null; var parentElement = statusBarSelection ? statusBarSelection : this.editor.getParentElement(selection, range); if (target) { parentElement = target; @@ -311,36 +313,27 @@ /* * This function gets called when the toolbar is updated */ - onUpdateToolbar : function () { - if (this.getEditorMode() === "textmode" || !this.editor.isEditable()) { - return false; - } - var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null; - var parentElement = statusBarSelection ? statusBarSelection : this.editor.getParentElement(); - if (parentElement.nodeName.toLowerCase() === "body") return false; - while (parentElement && (!HTMLArea.isBlockElement(parentElement) || /^(li)$/i.test(parentElement.nodeName))) { - parentElement = parentElement.parentNode; - } - var blockAncestors = this.getBlockAncestors(parentElement); - var selection = this.editor._getSelection(); - var endBlocks = this.editor.getEndBlocks(selection); - for (var buttonId in this.buttonList) { - commandState = false; - if (this.buttonList.hasOwnProperty(buttonId) && this.isButtonInToolbar(buttonId)) { - switch (buttonId) { - case "Outdent" : + onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) { + var editor = this.editor; + if (mode === 'wysiwyg' && this.editor.isEditable()) { + var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null; + var parentElement = statusBarSelection ? statusBarSelection : editor.getParentElement(); + if (!/^(body)$/i.test(parentElement.nodeName)) { + var endBlocks = editor.getEndBlocks(editor._getSelection()); + switch (button.itemId) { + case 'Outdent': if (/^(dt)$/i.test(endBlocks.start.nodeName) && /^(dl)$/i.test(endBlocks.start.parentNode.nodeName) && /^(dd)$/i.test(endBlocks.start.parentNode.parentNode.nodeName) && !endBlocks.end.nextSibling) { - this.editor._toolbarObjects[buttonId].state("enabled", true); + button.setDisabled(false); } else { - this.base(); + this.base(button, mode, selectionEmpty, ancestors); } break; - case "DefinitionList" : - this.editor._toolbarObjects[buttonId].state("enabled", (this.editor._selectionEmpty() && /^(p|div|address|pre|blockquote|h[1-6]|li|td|dd)$/i.test(endBlocks.start.nodeName)) - || (endBlocks.start != endBlocks.end && /^(p|h[1-6])$/i.test(endBlocks.start.nodeName))); + case 'DefinitionList': + button.setDisabled(!(selectionEmpty && /^(p|div|address|pre|blockquote|h[1-6]|li|td|dd)$/i.test(endBlocks.start.nodeName)) + && !(endBlocks.start != endBlocks.end && /^(p|h[1-6])$/i.test(endBlocks.start.nodeName))); break; } } Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/EditorMode/editor-mode.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/EditorMode/editor-mode.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/EditorMode/editor-mode.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2009 Stanislas Rolland +* (c) 2009-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -30,21 +30,18 @@ * TYPO3 SVN ID: $Id$ */ EditorMode = HTMLArea.Plugin.extend({ - constructor : function(editor, pluginName) { this.base(editor, pluginName); }, - /* * This function gets called by the class constructor */ configurePlugin : function (editor) { - /* * Registering plugin "About" information */ var pluginInformation = { - version : "0.1", + version : "2.0", developer : "Stanislas Rolland", developerUrl : "http://www.sjbr.ca/", copyrightOwner : "Stanislas Rolland", @@ -53,7 +50,6 @@ license : "GPL" }; this.registerPluginInformation(pluginInformation); - /* * Registering the buttons */ @@ -71,64 +67,13 @@ this.registerButton(buttonConfiguration); } return true; - }, - - /* The list of buttons added by this plugin */ - buttonList : [ - ["TextMode", null] - ], - - /* - * This function gets called during the editor generation and initializes the editor mode - * - * @return void - */ - init : function () { - var doc = this.editor._doc; - // Catch error if html content is invalid - var documentIsWellFormed = true; - try { - doc.body.innerHTML = this.editor._textArea.value; - } catch(e) { - this.appendToLog("init", "The HTML document is not well-formed."); - alert(this.localize("HTML-document-not-well-formed")); - documentIsWellFormed = false; - } - // Set contents editable - if (documentIsWellFormed) { - if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera && !this.editor._initEditMode()) { - return false; - } - if (HTMLArea.is_ie || HTMLArea.is_safari) { - doc.body.contentEditable = true; - } - if (HTMLArea.is_opera || HTMLArea.is_safari) { - doc.designMode = "on"; - this.setGeckoOptions(); - } - this.editorMode = "wysiwyg"; - if (doc.body.contentEditable || doc.designMode == "on") { - this.appendToLog("init", "Design mode successfully set."); - } - } else { - this.editorMode = "textmode"; - this.setEditorMode("docnotwellformedmode"); - this.appendToLog("init", "Design mode could not be set."); - } - return true; }, - - /* - * This function gets called when the editor is generated - * - * @return void + /** + * The list of buttons added by this plugin */ - onGenerate : function () { - // Set some references - this.textArea = this.editor._textArea; - this.editorBody = this.editor._doc.body; - }, - + buttonList: [ + ['TextMode', null] + ], /* * This function gets called when a button was pressed. * @@ -137,173 +82,19 @@ * * @return boolean false if action is completed */ - onButtonPress : function (editor, id, target) { + onButtonPress: function (editor, id, target) { // Could be a button or its hotkey var buttonId = this.translateHotKey(id); buttonId = buttonId ? buttonId : id; - this.setEditorMode((this.getEditorMode() == buttonId.toLowerCase()) ? "wysiwyg" : buttonId.toLowerCase()); + this.editor.setMode((this.editor.getMode() == buttonId.toLowerCase()) ? 'wysiwyg' : buttonId.toLowerCase()); return false; }, - /* - * Switch editor mode - * - * @param string "textmode" or "wysiwyg"; if no parameter was passed, toggle between modes. - * @return void - */ - setEditorMode : function (mode) { - var editor = this.editor; - switch (mode) { - case "textmode": - case "docnotwellformedmode": - this.textArea.value = this.getHTML(); - editor._iframe.style.display = "none"; - var dimensions = editor.getDimensions(); - editor.htmlArea.setStyle('height', (dimensions.toolbar.height + dimensions.statusbar.height) + 'px'); - editor.htmlArea.removeClass('resizable'); - this.textArea.style.display = "block"; - this.editorMode = "textmode"; - break; - case "wysiwyg": - if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) { - editor._doc.designMode = "off"; - } - try { - this.editorBody.innerHTML = this.getHTML(); - } catch(e) { - alert(HTMLArea.I18N.msg["HTML-document-not-well-formed"]); - break; - } - this.textArea.style.display = "none"; - editor._iframe.style.display = "block"; - var dimensions = editor.getDimensions(); - editor.htmlArea.setStyle('height', (parseInt(editor.iframe.getStyle('height')) + dimensions.toolbar.height + dimensions.statusbar.height) + 'px'); - editor.htmlArea.addClass('resizable'); - if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) { - editor._doc.designMode = "on"; - } - this.editorMode = "wysiwyg"; - this.setGeckoOptions(); - break; - case "htmlmode": - this.editorMode = "htmlmode"; - break; - default: - return false; - } - if (mode !== "docnotwellformedmode") { - editor.focusEditor(); - } - for (var pluginId in editor.plugins) { - if (editor.plugins.hasOwnProperty(pluginId)) { - var pluginInstance = this.getPluginInstance(pluginId); - if (typeof(pluginInstance.onMode) === "function") { - pluginInstance.onMode(mode); - } - } - } - }, - - /* - * Set gecko editing mode options (if we can... raises exception in Firefox 3) - * - * @return void - */ - setGeckoOptions : function () { - if (HTMLArea.is_gecko) { - var doc = this.editor._doc; - var config = this.editor.config; - try { - if (doc.queryCommandEnabled("insertbronreturn")) { - doc.execCommand("insertbronreturn", false, config.disableEnterParagraphs); - } - if (doc.queryCommandEnabled("styleWithCSS")) { - doc.execCommand("styleWithCSS", false, config.useCSS); - } else if (!HTMLArea.is_opera && !HTMLArea.is_safari && doc.queryCommandEnabled("useCSS")) { - doc.execCommand("useCSS", false, !config.useCSS); - } - if (!HTMLArea.is_opera && !HTMLArea.is_safari) { - if (doc.queryCommandEnabled("enableObjectResizing")) { - doc.execCommand("enableObjectResizing", false, !config.disableObjectResizing); - } - if (doc.queryCommandEnabled("enableInlineTableEditing")) { - doc.execCommand("enableInlineTableEditing", false, (config.buttons.table && config.buttons.table.enableHandles) ? true : false); - } - } - } catch(e) {} - } - }, - - /* - * Get editor mode - * - * @return string the current editor mode - */ - getEditorMode : function() { - return this.editorMode; - }, - - /* * This function gets called when the toolbar is updated * * @return void */ - onUpdateToolbar : function () { - var buttonList = this.buttonList, buttonId; - for (var i = 0, n = buttonList.length; i < n; ++i) { - buttonId = buttonList[i][0]; - if (this.isButtonInToolbar(buttonId)) { - this.editor._toolbarObjects[buttonId].state("active", (this.getEditorMode() == buttonId.toLowerCase())); - } - } - }, - - /* - * Retrieve the HTML - * In the case of the wysiwyg mode, the html content is parsed - * - * @return string the textual html content from the current editing mode - */ - getHTML : function () { - switch (this.editorMode) { - case "wysiwyg": - return HTMLArea.getHTML(this.editorBody, false, this.editor); - case "textmode": - return this.textArea.value; - } - return ""; - }, - - /* - * Retrieve raw HTML - * - * @return string the textual html content from the current editing mode - */ - getInnerHTML : function () { - switch (this.editorMode) { - case "wysiwyg": - return this.editorBody.innerHTML; - case "textmode": - return this.textArea.value; - } - return ""; - }, - - /* - * Replace the HTML inside - * - * @param string html: the textual html - * @return boolean false - */ - setHTML : function (html) { - switch (this.editorMode) { - case "wysiwyg": - this.editorBody.innerHTML = html; - break; - case "textmode": - this.textArea.value = html; - break; - } - return false; + onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) { + button.setInactive(mode !== button.itemId.toLowerCase()); } }); Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/find-replace.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/find-replace.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/find-replace.js (copie de travail) @@ -2,7 +2,7 @@ * Copyright notice * * (c) 2004 Cau guanabara -* (c) 2005-2009 Stanislas Rolland +* (c) 2005-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -96,10 +96,9 @@ if (/\w/.test(sel)) { param = { fr_pattern: sel }; } - if (HTMLArea.is_opera) { - this.cleanUpFunctionReference = this.makeFunctionReference("cleanUp"); + if (Ext.isOpera) { this.cleanUpRegularExpression = /(]*id=.?frmark[^>]*>)([^<>]*)(<\/span>)/gi; - this.editor._iframe.contentWindow.setTimeout(this.cleanUpFunctionReference, 200); + this.cleanUp.defer(200, this); } this.dialog = this.openDialog("FindReplace", this.makeUrlFromPopupName("find_replace"), null, param, {width:this.popupWidth, height:this.popupHeight}); return false; @@ -112,10 +111,10 @@ */ cleanUp : function () { if (this.dialog && (!this.dialog.dialogWindow || (this.dialog.dialogWindow && this.dialog.dialogWindow.closed))) { - this.getPluginInstance("EditorMode").setHTML(this.getPluginInstance("EditorMode").getInnerHTML().replace(this.cleanUpRegularExpression,"$2")); + this.editor.setHTML(this.editor.getInnerHTML().replace(this.cleanUpRegularExpression,"$2")); this.dialog.close(); } else { - this.editor._iframe.contentWindow.setTimeout(this.cleanUpFunctionReference, 200); + this.cleanUp.defer(200, this); } } }); Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2007-2009 Stanislas Rolland +* (c) 2007-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -63,7 +63,7 @@ * Registering plugin "About" information */ var pluginInformation = { - version : "1.1", + version : "2.0", developer : "Stanislas Rolland", developerUrl : "http://www.sjbr.ca/", copyrightOwner : "Stanislas Rolland", @@ -80,9 +80,8 @@ 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 + options : (this.editorConfiguration.buttons[buttonId.toLowerCase()] ? this.editorConfiguration.buttons[buttonId.toLowerCase()].data : null), + action : "onChange" }; this.registerDropDown(dropDownConfiguration); @@ -193,7 +192,6 @@ // 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); @@ -206,9 +204,8 @@ /* * 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; + onChange : function (editor, combo, record, index) { + var element = combo.getValue(); this.applyInlineElement(editor, element, false); }, @@ -235,7 +232,7 @@ } } if (!selectionEmpty) { - var statusBarSelection = (editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null); + var statusBarSelection = (editor.statusBar ? editor.statusBar.getSelection() : null); // The selection is not empty. for (var i = 0; i < ancestors.length; ++i) { fullNodeSelected = (HTMLArea.is_ie && ((selection.type !== "Control" && ancestors[i].innerText === range.text) || (selection.type === "Control" && ancestors[i].innerText === range.item(0).text))) @@ -374,22 +371,19 @@ /* * This function gets called when the toolbar is updated */ - onUpdateToolbar : function () { + onUpdateToolbar : function (button, mode, selectionEmpty, ancestors, endPointsInSameBlock) { var editor = this.editor; - if (this.getEditorMode() === "wysiwyg" && editor.isEditable()) { - var id, activeButton; - var tagName = false, endPointsInSameBlock = true, fullNodeSelected = false; + if (mode === "wysiwyg" && editor.isEditable()) { + var tagName = false, 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 statusBarSelection = editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null; - var ancestors = editor.getAllAncestors(); - for (var i = 0; i < ancestors.length; ++i) { + var statusBarSelection = editor.statusBar ? editor.statusBar.getSelection() : null; + for (var i = 0, n = ancestors.length; i < n; ++i) { fullNodeSelected = (statusBarSelection === ancestors[i]) && ((HTMLArea.is_gecko && ancestors[i].textContent === range.toString()) || (HTMLArea.is_ie && ((sel.type !== "Control" && ancestors[i].innerText === range.text) || (sel.type === "Control" && ancestors[i].innerText === range.item(0).text)))); if (fullNodeSelected) { @@ -406,31 +400,24 @@ } } var selectionInInlineElement = tagName && this.REInlineElements.test(tagName); - var disabled = !editor.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()) { + var disabled = !endPointsInSameBlock || (fullNodeSelected && !tagName) || (selectionEmpty && !selectionInInlineElement); + switch (button.itemId) { + case 'FormatText': + this.updateValue(editor, button, tagName, selectionEmpty, fullNodeSelected, disabled); + break; + default: + var activeButton = false; + Ext.each(ancestors, function (ancestor) { + if (ancestor && this.convertBtn[button.itemId] === ancestor.nodeName.toLowerCase()) { activeButton = true; + return false; + } else { + return true; } - } - obj.state("active", activeButton); - obj.state("enabled", !disabled); - } + }, this); + button.setInactive(!activeButton); + button.setDisabled(disabled); + break; } } }, @@ -438,31 +425,23 @@ /* * 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; + updateValue: function (editor, select, tagName, selectionEmpty, fullNodeSelected, disabled) { + var store = select.getStore(); + store.removeAt(0); + if ((store.findExact('value', tagName) != -1) && (selectionEmpty || fullNodeSelected)) { + select.setValue(tagName); + store.insert(0, new store.recordType({ + text: this.localize('Remove markup'), + value: 'none' + })); + } else { + store.insert(0, new store.recordType({ + text: this.localize('No markup'), + value: 'none' + })); + select.setValue('none'); } - 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"; - } + select.setDisabled(!(store.getCount()>1) || disabled); } }); Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/InsertSmiley/insert-smiley.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/InsertSmiley/insert-smiley.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/InsertSmiley/insert-smiley.js (copie de travail) @@ -2,7 +2,7 @@ * Copyright notice * * (c) 2004 Ki Master George -* (c) 2005-2009 Stanislas Rolland +* (c) 2005-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -34,32 +34,31 @@ */ InsertSmiley = HTMLArea.Plugin.extend({ - constructor : function(editor, pluginName) { this.base(editor, pluginName); }, - /* * This function gets called by the class constructor */ configurePlugin : function(editor) { - this.pageTSConfiguration = this.editorConfiguration.buttons.emoticon; - + this.editor_url = _typo3_host_url + _editor_url; + if (this.editor_url == '../') { + this.editor_url = document.URL.replace(/^(.*\/).*\/.*$/g, "$1"); + } /* * Registering plugin "About" information */ var pluginInformation = { - version : "1.2", + version : "2.0", developer : "Ki Master George & Stanislas Rolland", - developerUrl : "http://www.fructifor.ca/", + developerUrl : "http://www.sjbr.ca/", copyrightOwner : "Ki Master George & Stanislas Rolland", - sponsor : "Ki Master George & Fructifor Inc.", - sponsorUrl : "http://www.fructifor.ca/", + sponsor : "Ki Master George & SJBR", + sponsorUrl : "http://www.sjbr.ca/", license : "GPL" }; this.registerPluginInformation(pluginInformation); - /* * Registering the button */ @@ -72,10 +71,8 @@ dialog : true }; this.registerButton(buttonConfiguration); - return true; }, - /* * This function gets called when the button was pressed. * @@ -84,31 +81,77 @@ * * @return boolean false if action is completed */ - onButtonPress : function (editor, id) { - - var sel = this.editor.getSelectedHTML().replace(/(<[^>]*>| |\n|\r)/g,""); - var param = new Object(); - param.editor_url = _typo3_host_url + _editor_url; - if (param.editor_url == "../") { - param.editor_url = document.URL; - param.editor_url = param.editor_url.replace(/^(.*\/).*\/.*$/g, "$1"); + onButtonPress: function (editor, id) { + // Could be a button or its hotkey + var buttonId = this.translateHotKey(id); + buttonId = buttonId ? buttonId : id; + var dimensions = this.getWindowDimensions({width:175, height:230}, buttonId); + this.dialog = new Ext.Window({ + title: this.localize('Insert Smiley'), + cls: 'htmlarea-window', + border: false, + width: dimensions.width, + height: 'auto', + iconCls: buttonId, + listeners: { + close: { + fn: this.onClose, + scope: this + } + }, + items: { + xtype: 'box', + cls: 'emoticon-array', + tpl: new Ext.XTemplate( + '' + ), + listeners: { + render: { + fn: this.render, + scope: this + } + } + }, + buttons: [this.buildButtonConfig('Cancel', this.onCancel)] + }); + this.show(); + }, + /* + * Render the array of emoticon + * + * @param object component: the box containing the emoticons + * + * @return void + */ + render: function (component) { + this.icons = []; + var numberOfIcons = 20, inum; + for (var i = 1; i <= numberOfIcons; i++) { + inum = i; + if (i < 10) { + inum = '000' + i; + } else if (i < 100) { + inum = '00' + i; + } else if (i < 1000) { + inum = '0' + i; + } + this.icons.push(this.editor_url + 'plugins/InsertSmiley/smileys/' + inum + '.gif'); } - this.dialog = this.openDialog("InsertSmiley", this.makeUrlFromPopupName("insertsmiley"), "insertImageTag", param, {width:250, height:230}); + component.tpl.overwrite(component.el, this.icons); + component.mon(component.el, 'click', this.insertImageTag, this, {delegate: 'a'}); }, - /* - * Insert the selected smiley + * Insert the selected emoticon * - * @param object param: the selected smiley + * @param object event: the Ext event + * @param HTMLelement target: the html element target * - * @return boolean false + * @return void */ - insertImageTag : function (param) { - if (param && typeof(param.imgURL) != "undefined") { - this.editor.focusEditor(); - this.editor.insertHTML('Smiley'); - } - return false; + insertImageTag: function (event, target) { + this.editor.focus(); + this.restoreSelection(); + this.editor.insertHTML(''); + this.close(); } }); - Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/Language/language.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/Language/language.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/Language/language.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2008-2009 Stanislas Rolland +* (c) 2008-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -52,14 +52,14 @@ } // Importing list of allowed attributes - if (this.editor.getPluginInstance("TextStyle")) { - this.allowedAttributes = this.editor.getPluginInstance("TextStyle").allowedAttributes; + if (this.getPluginInstance("TextStyle")) { + this.allowedAttributes = this.getPluginInstance("TextStyle").allowedAttributes; } - if (!this.allowedAttributes && this.editor.getPluginInstance("InlineElements")) { - this.allowedAttributes = this.editor.getPluginInstance("InlineElements").allowedAttributes; + if (!this.allowedAttributes && this.getPluginInstance("InlineElements")) { + this.allowedAttributes = this.getPluginInstance("InlineElements").allowedAttributes; } - if (!this.allowedAttributes && this.editor.getPluginInstance("BlockElements")) { - this.allowedAttributes = this.editor.getPluginInstance("BlockElements").allowedAttributes; + if (!this.allowedAttributes && this.getPluginInstance("BlockElements")) { + this.allowedAttributes = this.getPluginInstance("BlockElements").allowedAttributes; } if (!this.allowedAttributes) { this.allowedAttributes = new Array("id", "title", "lang", "xml:lang", "dir", "class"); @@ -72,7 +72,7 @@ * Registering plugin "About" information */ var pluginInformation = { - version : "0.1", + version : "1.0", developer : "Stanislas Rolland", developerUrl : "http://www.sjbr.ca/", copyrightOwner : "Stanislas Rolland", @@ -101,21 +101,20 @@ /* * Registering the dropdown list */ - if (this.buttonsConfiguration.language && this.buttonsConfiguration.language.languagesUrl) { - // Load the options into HTMLArea.languageOptions - var languagesData = this.getJavascriptFile(this.buttonsConfiguration.language.languagesUrl, "noEval"); - if (languagesData) { - eval(languagesData); + var buttonId = 'Language'; + if (this.buttonsConfiguration[buttonId.toLowerCase()] && this.buttonsConfiguration[buttonId.toLowerCase()].dataUrl) { + // Load the options var + var optionsData = this.getJavascriptFile(this.buttonsConfiguration[buttonId.toLowerCase()].dataUrl, "noEval"); + if (optionsData) { + eval(optionsData); } } - var buttonId = "Language"; var dropDownConfiguration = { id : buttonId, tooltip : this.localize(buttonId + "-Tooltip"), - options : (HTMLArea.languageOptions ? HTMLArea.languageOptions : null), + options : options, action : "onChange", - refresh : null, - context : null + listWidth : 200 }; this.registerDropDown(dropDownConfiguration); @@ -136,16 +135,13 @@ // Add rules to the stylesheet for language mark highlighting // Model: body.htmlarea-show-language-marks *[lang=en]:before { content: "en: "; } // Works in IE8, but not in earlier versions of IE - var obj = this.getDropDownConfiguration("Language"); - if ((typeof(obj) !== "undefined") && (typeof(this.editor._toolbarObjects[obj.id]) !== "undefined")) { + var select = this.getButton('Language'); + if (select) { var styleSheet = this.editor._doc.styleSheets[0]; - var select = document.getElementById(this.editor._toolbarObjects[obj.id].elementId); - var options = select.options; - var rule, selector, style; - for (var i = options.length; --i >= 0;) { - selector = 'body.htmlarea-show-language-marks *[' + 'lang="' + options[i].value + '"]:before'; - style = 'content: "' + options[i].value + ': ";'; - rule = selector + ' { ' + style + ' }'; + select.getStore().each(function (option) { + var selector = 'body.htmlarea-show-language-marks *[' + 'lang="' + option.get('value') + '"]:before'; + var style = 'content: "' + option.get('value') + ': ";'; + var rule = selector + ' { ' + style + ' }'; if (HTMLArea.is_gecko) { try { styleSheet.insertRule(rule, styleSheet.cssRules.length); @@ -155,7 +151,8 @@ } else { styleSheet.addRule(selector, style); } - } + return true; + }); } }, @@ -225,10 +222,8 @@ /* * This function gets called when some language was selected in the drop-down list */ - onChange : function (editor, buttonId) { - var tbobj = this.editor._toolbarObjects[buttonId]; - var language = document.getElementById(tbobj.elementId).value; - this.applyLanguageMark(language); + onChange : function (editor, combo, record, index) { + this.applyLanguageMark(combo.getValue()); }, /* @@ -236,7 +231,7 @@ */ applyLanguageMark : function (language) { var selection = this.editor._getSelection(); - var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null; + var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null; var range = this.editor._createRange(selection); var parent = this.editor.getParentElement(selection, range); var selectionEmpty = this.editor._selectionEmpty(selection); @@ -391,94 +386,74 @@ /* * This function gets called when the toolbar is updated */ - onUpdateToolbar : function () { - if (this.getEditorMode() === "wysiwyg" && this.editor.isEditable()) { + onUpdateToolbar: function (button, mode, selectionEmpty, ancestors, endPointsInSameBlock) { + if (mode === 'wysiwyg' && this.editor.isEditable()) { var selection = this.editor._getSelection(); - var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null; + var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null; var range = this.editor._createRange(selection); var parent = this.editor.getParentElement(selection); - // Updating the direction buttons - var buttonList = this.buttonList, buttonId; - for (var i = 0, n = buttonList.length; i < n; ++i) { - buttonId = buttonList[i][0]; - if (this.isButtonInToolbar(buttonId)) { - switch (buttonId) { - case "RightToLeft" : - case "LeftToRight" : - if (parent) { - var direction = (buttonId === "RightToLeft") ? "rtl" : "ltr"; - this.editor._toolbarObjects[buttonId].state("active",(parent.dir == direction || parent.style.direction == direction)); - } - break; - case "ShowLanguageMarks": - this.editor._toolbarObjects[buttonId].state("active", HTMLArea._hasClass(this.editor._doc.body, 'htmlarea-show-language-marks')); - break; - default : - break; + switch (button.itemId) { + case 'RightToLeft': + case 'LeftToRight': + if (parent) { + var direction = (button.itemId === 'RightToLeft') ? 'rtl' : 'ltr'; + button.setInactive(parent.dir != direction && parent.style.direction != direction); } - } - } - // Updating the language drop-down - var fullNodeSelected = false; - var language = this.getLanguageAttribute(parent); - var selectionEmpty = this.editor._selectionEmpty(selection); - var endPointsInSameBlock = this.editor.endPointsInSameBlock(); - if (!selectionEmpty) { - if (endPointsInSameBlock) { - var ancestors = this.editor.getAllAncestors(); - for (var i = 0; i < ancestors.length; ++i) { - fullNodeSelected = (statusBarSelection === ancestors[i]) - && ((HTMLArea.is_gecko && ancestors[i].textContent === range.toString()) || (HTMLArea.is_ie && ((selection.type !== "Control" && ancestors[i].innerText === range.text) || (selection.type === "Control" && ancestors[i].innerText === range.item(0).text)))); - if (fullNodeSelected) { - parent = ancestors[i]; - break; + break; + case 'ShowLanguageMarks': + button.setInactive(!HTMLArea._hasClass(this.editor._doc.body, 'htmlarea-show-language-marks')); + break; + case 'Language': + // Updating the language drop-down + var fullNodeSelected = false; + var language = this.getLanguageAttribute(parent); + if (!selectionEmpty) { + if (endPointsInSameBlock) { + for (var i = 0; i < ancestors.length; ++i) { + fullNodeSelected = (statusBarSelection === ancestors[i]) + && ((HTMLArea.is_gecko && ancestors[i].textContent === range.toString()) || (HTMLArea.is_ie && ((selection.type !== "Control" && ancestors[i].innerText === range.text) || (selection.type === "Control" && ancestors[i].innerText === range.item(0).text)))); + if (fullNodeSelected) { + parent = ancestors[i]; + break; + } + } + // Working around bug in Safari selectNodeContents + if (!fullNodeSelected && HTMLArea.is_safari && statusBarSelection && statusBarSelection.textContent === range.toString()) { + fullNodeSelected = true; + parent = statusBarSelection; + } + language = this.getLanguageAttribute(parent); + } else { + language = this.getLanguageAttributeFromBlockElements(); } } - // Working around bug in Safari selectNodeContents - if (!fullNodeSelected && HTMLArea.is_safari && statusBarSelection && statusBarSelection.textContent === range.toString()) { - fullNodeSelected = true; - parent = statusBarSelection; - } - language = this.getLanguageAttribute(parent); - } else { - language = this.getLanguageAttributeFromBlockElements(); - } + this.updateValue(button, language, selectionEmpty, fullNodeSelected, endPointsInSameBlock); + break; + default: + break; } - var obj = this.getDropDownConfiguration("Language"); - if ((typeof(obj) !== "undefined") && (typeof(this.editor._toolbarObjects[obj.id]) !== "undefined")) { - this.updateValue(obj, language, selectionEmpty, fullNodeSelected, endPointsInSameBlock); - } } }, /* * This function updates the language drop-down list */ - updateValue : function (obj, language, selectionEmpty, fullNodeSelected, endPointsInSameBlock) { - var select = document.getElementById(this.editor._toolbarObjects[obj.id]["elementId"]); - var options = select.options; - for (var i = options.length; --i >= 0;) { - options[i].selected = false; + updateValue : function (select, language, selectionEmpty, fullNodeSelected, endPointsInSameBlock) { + var store = select.getStore(); + store.removeAt(0); + if ((store.findExact('value', language) != -1) && (selectionEmpty || fullNodeSelected || !endPointsInSameBlock)) { + select.setValue(language); + store.insert(0, new store.recordType({ + text: this.localize('Remove language mark'), + value: 'none' + })); + } else { + store.insert(0, new store.recordType({ + text: this.localize('No language mark'), + value: 'none' + })); + select.setValue('none'); } - select.selectedIndex = 0; - options[0].selected = true; - select.options[0].text = this.localize("No language mark"); - if (language != "none") { - for (i = options.length; --i >= 0;) { - if (language == options[i].value) { - if (selectionEmpty || fullNodeSelected || !endPointsInSameBlock) { - options[i].selected = true; - select.selectedIndex = i; - select.options[0].text = this.localize("Remove language mark"); - } - break; - } - } - } - select.disabled = !(options.length>1) || (selectionEmpty && this.editor.getParentElement().nodeName.toLowerCase() === "body"); - select.className = ""; - if (select.disabled) { - select.className = "buttonDisabled"; - } + select.setDisabled(!(store.getCount()>1) || (selectionEmpty && this.editor.getParentElement().nodeName.toLowerCase() === 'body')); } }); Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/QuickTag/locallang.xml =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/QuickTag/locallang.xml (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/QuickTag/locallang.xml (copie de travail) @@ -12,9 +12,9 @@ - - - + + + Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/QuickTag/quick-tag.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/QuickTag/quick-tag.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/QuickTag/quick-tag.js (copie de travail) @@ -2,7 +2,7 @@ * Copyright notice * * (c) 2004 Cau guanabara -* (c) 2005-2009 Stanislas Rolland +* (c) 2005-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -33,52 +33,61 @@ * TYPO3 SVN ID: $Id$ */ QuickTag = HTMLArea.Plugin.extend({ - constructor : function(editor, pluginName) { this.base(editor, pluginName); }, - /* * This function gets called by the class constructor */ configurePlugin : function(editor) { - this.pageTSConfiguration = this.editorConfiguration.buttons.inserttag; - this.tags = (this.pageTSConfiguration && this.pageTSConfiguration.tags) ? this.pageTSConfiguration.tags : null; + this.allowedTags = (this.pageTSConfiguration && this.pageTSConfiguration.tags) ? this.pageTSConfiguration.tags : null; this.denyTags = (this.pageTSConfiguration && this.pageTSConfiguration.denyTags) ? this.pageTSConfiguration.denyTags : null; this.allowedAttribs = (this.pageTSConfiguration && this.pageTSConfiguration.allowedAttribs) ? this.pageTSConfiguration.allowedAttribs : null; - + this.quotes = new RegExp('^\w+\s*([a-zA-Z_0-9:;]+=\"[^\"]*\"\s*|[a-zA-Z_0-9:;]+=\'[^\']*\'\s*)*$'); /* * Registering plugin "About" information */ var pluginInformation = { - version : "1.3", - developer : "Cau Guanabara & Stanislas Rolland", - developerUrl : "mailto:caugb@ibest.com.br", - copyrightOwner : "Cau Guanabara & Stanislas Rolland", - sponsor : "Independent production & SJBR", - sponsorUrl : "http://www.netflash.com.br/gb/HA3-rc1/examples/quick-tag.html", - license : "GPL" + version : '2.0', + developer : 'Cau Guanabara & Stanislas Rolland', + developerUrl : 'http://www.sjbr.ca', + copyrightOwner : 'Cau Guanabara & Stanislas Rolland', + sponsor : 'Independent production & SJBR', + sponsorUrl : 'http://www.sjbr.ca', + license : 'GPL' }; this.registerPluginInformation(pluginInformation); - /* * Registering the button */ - var buttonId = "InsertTag"; + var buttonId = 'InsertTag'; var buttonConfiguration = { id : buttonId, - tooltip : this.localize("Quick Tag Editor"), - action : "onButtonPress", + tooltip : this.localize('Quick Tag Editor'), + action : 'onButtonPress', selection : true, dialog : true }; this.registerButton(buttonConfiguration); - return true; }, - /* + * Sets of default configuration values for dialogue form fields + */ + configDefaults: { + combo: { + editable: true, + typeAhead: true, + triggerAction: 'all', + forceSelection: true, + mode: 'local', + valueField: 'value', + displayField: 'text', + helpIcon: true + } + }, + /* * This function gets called when the button was pressed. * * @param object editor: the editor instance @@ -87,22 +96,678 @@ * * @return boolean false if action is completed */ - onButtonPress : function(editor, id, target) { - this.dialog = this.openDialog("InsertTag", this.makeUrlFromPopupName("quicktag"), "setTag", null, {width:470, height:115}); + onButtonPress: function(editor, id, target) { + // Could be a button or its hotkey + var buttonId = this.translateHotKey(id); + buttonId = buttonId ? buttonId : id; + this.openDialogue( + 'Quick Tag Editor', + { + buttonId: buttonId + }, + this.getWindowDimensions({ width: 570}, buttonId), + this.buildItemsConfig(), + this.setTag + ); + this.insertedTag = this.dialog.find('itemId', 'insertedTag')[0]; + this.tagCombo = this.dialog.find('itemId', 'tags')[0]; + this.attributeCombo = this.dialog.find('itemId', 'attributes')[0]; + this.valueCombo = this.dialog.find('itemId', 'values')[0]; + this.colorCombo = this.dialog.find('itemId', 'colors')[0]; }, - /* - * Insert the tag + * Build the window items config + */ + buildItemsConfig: function (element, buttonId) { + var tagStore = new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}], + data: this.tags + }); + if (this.denyTags) { + var denyTags = new RegExp('^(' + this.denyTags.split(',').join('|').replace(/ /g, '') + ')$', 'i'); + tagStore.filterBy(function (record) { + return !denyTags.test(record.get('value')); + }); + // Make sure the combo list is filtered + tagStore.snapshot = tagStore.data; + } + var attributeStore = new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ {name: 'tag'}, { name: 'text'}, { name: 'value'}], + data: this.attributes + }); + this.valueRecord = Ext.data.Record.create([{name: 'attribute'}, { name: 'text'}, { name: 'value'}]); + var valueStore = new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ {name: 'attribute'}, { name: 'text'}, { name: 'value'}], + data: this.values, + listeners: { + load: { + fn: this.captureClasses, + scope: this + } + } + }); + var itemsConfig = [{ + xtype: 'textarea', + itemId: 'tagopen', + width: 400, + itemId: 'insertedTag', + fieldLabel: '<', + labelSeparator: '', + grow: true, + listeners: { + change: { + fn: this.filterAttributes, + scope: this + }, + focus: { + fn: this.filterAttributes, + scope: this + } + } + },{ + xtype: 'displayfield', + text: '>' + }, Ext.apply({ + xtype: 'combo', + itemId: 'tags', + fieldLabel: this.localize('TAGs'), + store: tagStore, + listeners: { + select: { + fn: this.onTagSelect, + scope: this + } + } + }, this.configDefaults['combo']) + , Ext.apply({ + xtype: 'combo', + itemId: 'attributes', + fieldLabel: this.localize('ATTRIBUTES'), + store: attributeStore, + hidden: true, + listeners: { + select: { + fn: this.onAttributeSelect, + scope: this + } + } + }, this.configDefaults['combo']) + , Ext.apply({ + xtype: 'combo', + itemId: 'values', + fieldLabel: this.localize('OPTIONS'), + store: valueStore, + hidden: true, + listeners: { + select: { + fn: this.onValueSelect, + scope: this + } + } + }, this.configDefaults['combo']) + ,{ + xtype: 'colorpalettefield', + fieldLabel: this.localize('Colors'), + itemId: 'colors', + colorsConfiguration: this.editorConfiguration.colors, + hidden: true, + listeners: { + select: { + fn: this.onColorSelect, + scope: this + } + } + } + ]; + return { + xtype: 'fieldset', + title: this.localize('Quick Tag Editor'), + defaultType: 'textfield', + labelWidth: 100, + defaults: { + helpIcon: true + }, + items: itemsConfig + }; + }, + /* + * Add a record for each class selector found in the stylesheets + */ + captureClasses: function (valueStore) { + this.parseCssRule(this.editor.document.styleSheets, valueStore); + }, + parseCssRule: function (rules, valueStore) { + Ext.each(rules, function (rule) { + if (rule.selectorText) { + if (/^(\w*)\.(\w+)$/.test(rule.selectorText)) { + valueStore.add(new this.valueRecord({ + attribute: 'class', + text: rule.selectorText, + value: RegExp.$2 + '"' + })); + } + } else { + // ImportRule (Mozilla) + if (rule.styleSheet) { + this.parseCssRule(rule.styleSheet.cssRules, valueStore); + } + // MediaRule (Mozilla) + if (rule.cssRules) { + this.parseCssRule(rule.cssRules, valueStore); + } + // IE imports + if (rule.imports) { + this.parseCssRule(rule.imports, valueStore); + } + if (rule.rules) { + this.parseCssRule(rule.rules, valueStore); + } + } + }, this); + }, + /* + * Handler invoked when a tag is selected + * Update the attributes combo and the inserted tag field + */ + onTagSelect: function (tagCombo, tagRecord) { + var tag = tagRecord.get('value'); + this.filterAttributes(); + this.attributeCombo.clearValue(); + this.attributeCombo.show(); + this.valueCombo.hide(); + this.insertedTag.setValue(tag); + this.insertedTag.focus(false, 50); + }, + /* + * Filter out attributes not applicable to the tag, already present in the tag or not allowed + */ + filterAttributes: function () { + var tag = this.tagCombo.getValue(); + var insertedTag = this.insertedTag.getValue(); + var attributeStore = this.attributeCombo.getStore(); + if (attributeStore.realSnapshot) { + attributeStore.snapshot = attributeStore.realSnapshot; + delete attributeStore.realSnapshot; + attributeStore.clearFilter(true); + } + var allowedAttribs = ''; + if (this.allowedAttribs) { + allowedAttribs = this.allowedAttribs.split(',').join('|').replace(/ /g, ''); + } + if (this.tags && this.tags[tag] && this.tags[tag].allowedAttribs) { + allowedAttribs += allowedAttribs ? '|' : ''; + allowedAttribs += this.tags[tag].allowedAttribs.split(',').join('|').replace(/ /g, ''); + } + if (allowedAttribs) { + var allowedAttribs = new RegExp('^(' + allowedAttribs + ')$'); + } + attributeStore.filterBy(function (attributeRecord) { + // Filter out attributes already used in the tag, not applucable to tag or not allowed + var testAttrib = new RegExp('(' + attributeRecord.get('value') + ')', 'ig'); + var tagValue = attributeRecord.get('tag'); + return (tagValue == 'all' || tagValue == tag) && !testAttrib.test(insertedTag) && (!allowedAttribs || allowedAttribs.test(attributeRecord.get('text'))); + }); + // Make sure the combo list is filtered + attributeStore.realSnapshot = attributeStore.snapshot; + attributeStore.snapshot = attributeStore.data; + }, + /* + * Filter out not applicable to the attribute or style values already present in the tag + * Filter out classes not applicable to the current tag + */ + filterValues: function (attribute) { + var tag = this.tagCombo.getValue(); + var insertedTag = this.insertedTag.getValue(); + var valueStore = this.valueCombo.getStore(); + if (valueStore.realSnapshot) { + valueStore.snapshot = valueStore.realSnapshot; + delete valueStore.realSnapshot; + valueStore.clearFilter(true); + } + var expr = new RegExp('(^' + tag + '[\.])|(^[\.])', 'i'); + valueStore.filterBy(function (valueRecord) { + var value = valueRecord.get('value'); + if (attribute === 'style') { + expr = new RegExp('(' + ((value.charAt(0) == '+' || value.charAt(0) == '-') ? '\\' : '') + value + ')', 'ig'); + } + return valueRecord.get('attribute') == attribute && (attribute !== 'style' || !expr.test(insertedTag)) && (attribute !== 'class' || expr.test(valueRecord.get('text'))); + }); + // Make sure the combo list is filtered + valueStore.realSnapshot = valueStore.snapshot; + valueStore.snapshot = valueStore.data; + this.valueCombo.setVisible(valueStore.getCount() ? true : false); + }, + /* + * Handler invoked when an attribute is selected + * Update the values combo and the inserted tag field + */ + onAttributeSelect: function (attributeCombo, attributeRecord) { + var insertedTag = this.insertedTag.getValue(); + var attribute = attributeRecord.get('text'); + this.valueCombo.clearValue(); + if (/color/.test(attribute)) { + this.valueCombo.hide(); + this.colorCombo.show(); + } else { + this.filterValues(attribute); + } + this.insertedTag.setValue(insertedTag + ((/\"/.test(insertedTag) && (!/\"$/.test(insertedTag) || /=\"$/.test(insertedTag))) ? '" ' : ' ') + attributeRecord.get('value')); + this.insertedTag.focus(false, 50); + }, + /* + * Handler invoked when a value is selected + * Update the inserted tag field + */ + onValueSelect: function (combo, record) { + var style = this.attributeCombo.getValue() === 'style="'; + this.insertedTag.setValue(this.insertedTag.getValue() + (style && !/="$/.test(this.insertedTag.getValue()) ? '; ' : '') + combo.getValue()); + this.insertedTag.focus(false, 50); + combo.clearValue(); + if (style) { + if (/color/.test(record.get('text'))) { + this.colorCombo.show(); + } + } else { + combo.hide(); + this.attributeCombo.clearValue(); + } + }, + /* + * Handler invoked when a color is selected + * Update the inserted tag field + */ + onColorSelect: function (combo, record) { + var style = this.attributeCombo.getValue() === 'style="'; + this.insertedTag.setValue(this.insertedTag.getValue() + '#' + combo.getValue() + (style ? '' : '"')); + this.insertedTag.focus(false, 50); + combo.setValue(''); + combo.hide(); + if (!style) { + this.attributeCombo.clearValue(); + } + }, + /* + * Handler invoked when a OK button is pressed + */ + setTag: function (button, event) { + this.restoreSelection(); + var insertedTag = this.insertedTag.getValue(); + var currentTag = this.tagCombo.getValue(); + if (!insertedTag) { + Ext.MessageBox.alert('', this.localize("Enter the TAG you want to insert")); + this.insertedTag.focus(); + event.stopEvent(); + return false; + } + if (this.quotes.test(insertedTag)) { + if (this.quotes.test(insertedTag + '"')) { + Ext.MessageBox.alert('', this.localize("There are some unclosed quote")); + this.insertedTag.focus(); + this.insertedTag.select(); + event.stopEvent(); + return false; + } else { + this.insertedTag.setValue(insertedTag + '"'); + } + } + insertedTag = insertedTag.replace(/(<|>)/g, ''); + var tagOpen = '<' + insertedTag + '>'; + var tagClose = tagOpen.replace(/^<(\w+) ?.*>/, ''); + var subTags = this.subTags[currentTag]; + if (subTags) { + tagOpen = tagOpen + this.subTags.open; + tagClose = this.subTags.close + tagClose; + } + this.editor.focus(); + this.editor.surroundHTML(tagOpen, tagClose); + this.close(); + event.stopEvent(); + }, + /* + * Open the dialogue window * - * @param object param: the constructed tag + * @param string title: the window title + * @param object arguments: some arguments for the handler + * @param integer dimensions: the opening dimensions of the window + * @param object items: the configuration of the window items + * @param function handler: handler when the OK button if clicked * - * @return boolean false + * @return void */ - setTag : function(param) { - if(param && typeof(param.tagopen) != "undefined") { - this.editor.focusEditor(); - this.editor.surroundHTML(param.tagopen, param.tagclose); + openDialogue: function (title, arguments, dimensions, items, handler) { + if (this.dialog) { + this.dialog.close(); } + this.dialog = new Ext.Window({ + title: this.localize(title), + arguments: arguments, + cls: 'htmlarea-window', + border: false, + width: dimensions.width, + height: 'auto', + iconCls: arguments.buttonId, + listeners: { + close: { + fn: this.onClose, + scope: this + } + }, + items: { + xtype: 'container', + layout: 'form', + defaults: { + labelWidth: 150 + }, + items: items + }, + buttons: [ + this.buildButtonConfig('Cancel', this.onCancel), + this.buildButtonConfig('OK', handler) + ] + }); + this.show(); + }, + tags: [ + ['a', 'a'], + ['abbr', 'abbr'], + ['acronym', 'acronym'], + ['address', 'address'], + ['b', 'b'], + ['big', 'big'], + ['blockquote', 'blockquote'], + ['cite', 'cite'], + ['code', 'code'], + ['div', 'div'], + ['em', 'em'], + ['fieldset', 'fieldset'], + ['font', 'font'], + ['h1', 'h1'], + ['h2', 'h2'], + ['h3', 'h3'], + ['h4', 'h4'], + ['h5', 'h5'], + ['h6', 'h6'], + ['i', 'i'], + ['legend', 'legend'], + ['li', 'li'], + ['ol', 'ol'], + ['ul', 'ul'], + ['p', 'p'], + ['pre', 'pre'], + ['q', 'q'], + ['small', 'small'], + ['span', 'span'], + ['strike', 'strike'], + ['strong', 'strong'], + ['sub', 'sub'], + ['sup', 'sup'], + ['table', 'table'], + ['tt', 'tt'], + ['u', 'u'] + ], + attributes: [ + ['all', 'class', 'class="'], + ['all', 'dir', 'dir="'], + ['all', 'id', 'id="'], + ['all', 'lang', 'lang="'], + ['all', 'onFocus', 'onFocus="'], + ['all', 'onBlur', 'onBlur="'], + ['all', 'onClick', 'onClick="'], + ['all', 'onDblClick', 'onDblClick="'], + ['all', 'onMouseDown', 'onMouseDown="'], + ['all', 'onMouseUp', 'onMouseUp="'], + ['all', 'onMouseOver', 'onMouseOver="'], + ['all', 'onMouseMove', 'onMouseMove="'], + ['all', 'onMouseOut', 'onMouseOut="'], + ['all', 'onKeyPress', 'onKeyPress="'], + ['all', 'onKeyDown', 'onKeyDown="'], + ['all', 'onKeyUp', 'onKeyUp="'], + ['all', 'style', 'style="'], + ['all', 'title', 'title="'], + ['all', 'xml:lang', 'xml:lang="'], + ['a', 'href', 'href="'], + ['a', 'name', 'name="'], + ['a', 'target', 'target="'], + ['font', 'face', 'face="'], + ['font', 'size', 'size="'], + ['font', 'color', 'color="'], + ['div', 'align', 'align="'], + ['h1', 'align', 'align="'], + ['h2', 'align', 'align="'], + ['h3', 'align', 'align="'], + ['h4', 'align', 'align="'], + ['h5', 'align', 'align="'], + ['h6', 'align', 'align="'], + ['p', 'align', 'align="'], + ['table', 'align', 'align="'], + ['table', 'width', 'width="'], + ['table', 'height', 'height="'], + ['table', 'cellpadding', 'cellpadding="'], + ['table', 'cellspacing', 'cellspacing="'], + ['table', 'background', 'background="'], + ['table', 'bgcolor', 'bgcolor="'], + ['table', 'border', 'border="'], + ['table', 'bordercolor', 'bordercolor="'] + ], + values: [ + ['href', 'http://', 'http://'], + ['href', 'https://', 'https://'], + ['href', 'ftp://', 'ftp://'], + ['href', 'mailto:', 'mailto:'], + ['href', '#', '#"'], + ['target', '_top', '_top"'], + ['target', '_self', '_self"'], + ['target', '_parent', '_parent"'], + ['target', '_blank', '_blank"'], + ['face', 'Verdana', 'Verdana"'], + ['face', 'Arial', 'Arial"'], + ['face', 'Tahoma', 'Tahoma"'], + ['face', 'Courier New', 'Courier New"'], + ['face', 'Times New Roman', 'Times New Roman"'], + ['size', '1', '1"'], + ['size', '2', '2"'], + ['size', '3', '3"'], + ['size', '4', '4"'], + ['size', '5', '5"'], + ['size', '6', '6"'], + ['size', '+1', '+1"'], + ['size', '+2', '+2"'], + ['size', '+3', '+3"'], + ['size', '+4', '+4"'], + ['size', '+5', '+5"'], + ['size', '+6', '+6"'], + ['size', '-1', '-1"'], + ['size', '-2', '-2"'], + ['size', '-3', '-3"'], + ['size', '-4', '-4"'], + ['size', '-5', '-5"'], + ['size', '-6', '-6"'], + ['align', 'center', 'center"'], + ['align', 'left', 'left"'], + ['align', 'right', 'right"'], + ['align', 'justify', 'justify"'], + ['dir', 'rtl', 'rtl"'], + ['dir', 'ltr', 'ltr"'], + ['lang', 'Afrikaans ', 'af"'], + ['lang', 'Albanian ', 'sq"'], + ['lang', 'Arabic ', 'ar"'], + ['lang', 'Basque ', 'eu"'], + ['lang', 'Breton ', 'br"'], + ['lang', 'Bulgarian ', 'bg"'], + ['lang', 'Belarusian ', 'be"'], + ['lang', 'Catalan ', 'ca"'], + ['lang', 'Chinese ', 'zh"'], + ['lang', 'Croatian ', 'hr"'], + ['lang', 'Czech ', 'cs"'], + ['lang', 'Danish ', 'da"'], + ['lang', 'Dutch ', 'nl"'], + ['lang', 'English ', 'en"'], + ['lang', 'Estonian ', 'et"'], + ['lang', 'Faeroese ', 'fo"'], + ['lang', 'Farsi ', 'fa"'], + ['lang', 'Finnish ', 'fi"'], + ['lang', 'French ', 'fr"'], + ['lang', 'Gaelic ', 'gd"'], + ['lang', 'German ', 'de"'], + ['lang', 'Greek ', 'el"'], + ['lang', 'Hebrew ', 'he"'], + ['lang', 'Hindi ', 'hi"'], + ['lang', 'Hungarian ', 'hu"'], + ['lang', 'Icelandic ', 'is"'], + ['lang', 'Indonesian ', 'id"'], + ['lang', 'Italian ', 'it"'], + ['lang', 'Japanese ', 'ja"'], + ['lang', 'Korean ', 'ko"'], + ['lang', 'Latvian ', 'lv"'], + ['lang', 'Lithuanian ', 'lt"'], + ['lang', 'Macedonian ', 'mk"'], + ['lang', 'Malaysian ', 'ms"'], + ['lang', 'Maltese ', 'mt"'], + ['lang', 'Norwegian ', 'no"'], + ['lang', 'Polish ', 'pl"'], + ['lang', 'Portuguese ', 'pt"'], + ['lang', 'Rhaeto-Romanic ', 'rm"'], + ['lang', 'Romanian ', 'ro"'], + ['lang', 'Russian ', 'ru"'], + ['lang', 'Sami ', 'sz"'], + ['lang', 'Serbian ', 'sr"'], + ['lang', 'Setswana ', 'tn"'], + ['lang', 'Slovak ', 'sk"'], + ['lang', 'Slovenian ', 'sl"'], + ['lang', 'Spanish ', 'es"'], + ['lang', 'Sutu ', 'sx"'], + ['lang', 'Swedish ', 'sv"'], + ['lang', 'Thai ', 'th"'], + ['lang', 'Tsonga ', 'ts"'], + ['lang', 'Turkish ', 'tr"'], + ['lang', 'Ukrainian ', 'uk"'], + ['lang', 'Urdu ', 'ur"'], + ['lang', 'Vietnamese ', 'vi"'], + ['lang', 'Xhosa ', 'xh"'], + ['lang', 'Yiddish ', 'yi"'], + ['lang', 'Zulu', 'zu"'], + ['style', 'azimuth', 'azimuth: '], + ['style', 'background', 'background: '], + ['style', 'background-attachment', 'background-attachment: '], + ['style', 'background-color', 'background-color: '], + ['style', 'background-image', 'background-image: '], + ['style', 'background-position', 'background-position: '], + ['style', 'background-repeat', 'background-repeat: '], + ['style', 'border', 'border: '], + ['style', 'border-bottom', 'border-bottom: '], + ['style', 'border-left', 'border-left: '], + ['style', 'border-right', 'border-right: '], + ['style', 'border-top', 'border-top: '], + ['style', 'border-bottom-color', 'border-bottom-color: '], + ['style', 'border-left-color', 'border-left-color: '], + ['style', 'border-right-color', 'border-right-color: '], + ['style', 'border-top-color', 'border-top-color: '], + ['style', 'border-bottom-style', 'border-bottom-style: '], + ['style', 'border-left-style', 'border-left-style: '], + ['style', 'border-right-style', 'border-right-style: '], + ['style', 'border-top-style', 'border-top-style: '], + ['style', 'border-bottom-width', 'border-bottom-width: '], + ['style', 'border-left-width', 'border-left-width: '], + ['style', 'border-right-width', 'border-right-width: '], + ['style', 'border-top-width', 'border-top-width: '], + ['style', 'border-collapse', 'border-collapse: '], + ['style', 'border-color', 'border-color: '], + ['style', 'border-style', 'border-style: '], + ['style', 'border-width', 'border-width: '], + ['style', 'bottom', 'bottom: '], + ['style', 'caption-side', 'caption-side: '], + ['style', 'cell-spacing', 'cell-spacing: '], + ['style', 'clear', 'clear: '], + ['style', 'clip', 'clip: '], + ['style', 'color', 'color: '], + ['style', 'column-span', 'column-span: '], + ['style', 'content', 'content: '], + ['style', 'cue', 'cue: '], + ['style', 'cue-after', 'cue-after: '], + ['style', 'cue-before', 'cue-before: '], + ['style', 'cursor', 'cursor: '], + ['style', 'direction', 'direction: '], + ['style', 'display', 'display: '], + ['style', 'elevation', 'elevation: '], + ['style', 'filter', 'filter: '], + ['style', 'float', 'float: '], + ['style', 'font-family', 'font-family: '], + ['style', 'font-size', 'font-size: '], + ['style', 'font-size-adjust', 'font-size-adjust: '], + ['style', 'font-style', 'font-style: '], + ['style', 'font-variant', 'font-variant: '], + ['style', 'font-weight', 'font-weight: '], + ['style', 'height', 'height: '], + ['style', '!important', '!important: '], + ['style', 'left', 'left: '], + ['style', 'letter-spacing', 'letter-spacing: '], + ['style', 'line-height', 'line-height: '], + ['style', 'list-style', 'list-style: '], + ['style', 'list-style-image', 'list-style-image: '], + ['style', 'list-style-position', 'list-style-position: '], + ['style', 'list-style-type', 'list-style-type: '], + ['style', 'margin', 'margin: '], + ['style', 'margin-bottom', 'margin-bottom: '], + ['style', 'margin-left', 'margin-left: '], + ['style', 'margin-right', 'margin-right: '], + ['style', 'margin-top', 'margin-top: '], + ['style', 'marks', 'marks: '], + ['style', 'max-height', 'max-height: '], + ['style', 'min-height', 'min-height: '], + ['style', 'max-width', 'max-width: '], + ['style', 'min-width', 'min-width: '], + ['style', 'orphans', 'orphans: '], + ['style', 'overflow', 'overflow: '], + ['style', 'padding', 'padding: '], + ['style', 'padding-bottom', 'padding-bottom: '], + ['style', 'padding-left', 'padding-left: '], + ['style', 'padding-right', 'padding-right: '], + ['style', 'padding-top', 'padding-top: '], + ['style', 'page-break-after', 'page-break-after: '], + ['style', 'page-break-before', 'page-break-before: '], + ['style', 'pause', 'pause: '], + ['style', 'pause-after', 'pause-after: '], + ['style', 'pause-before', 'pause-before: '], + ['style', 'pitch', 'pitch: '], + ['style', 'pitch-range', 'pitch-range: '], + ['style', 'play-during', 'play-during: '], + ['style', 'position', 'position: '], + ['style', 'richness', 'richness: '], + ['style', 'right', 'right: '], + ['style', 'row-span', 'row-span: '], + ['style', 'size', 'size: '], + ['style', 'speak', 'speak: '], + ['style', 'speak-date', 'speak-date: '], + ['style', 'speak-header', 'speak-header: '], + ['style', 'speak-numeral', 'speak-numeral: '], + ['style', 'speak-punctuation', 'speak-punctuation: '], + ['style', 'speak-time', 'speak-time: '], + ['style', 'speech-rate', 'speech-rate: '], + ['style', 'stress', 'stress: '], + ['style', 'table-layout', 'table-layout: '], + ['style', 'text-align', 'text-align: '], + ['style', 'text-decoration', 'text-decoration: '], + ['style', 'text-indent', 'text-indent: '], + ['style', 'text-shadow', 'text-shadow: '], + ['style', 'text-transform', 'text-transform: '], + ['style', 'top', 'top: '], + ['style', 'vertical-align', 'vertical-align: '], + ['style', 'visibility', 'visibility: '], + ['style', 'voice-family', 'voice-family: '], + ['style', 'volume', 'volume: '], + ['style', 'white-space', 'white-space: '], + ['style', 'widows', 'widows: '], + ['style', 'width', 'width: '], + ['style', 'word-spacing', 'word-spacing: '], + ['style', 'z-index', 'z-index: '] + ], + subTags: { + 'table': { + 'open': '', + 'close': '' + } } }); - Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/RemoveFormat/remove-format.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/RemoveFormat/remove-format.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/RemoveFormat/remove-format.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2005-2009 Stanislas Rolland +* (c) 2005-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -44,12 +44,12 @@ * Registering plugin "About" information */ var pluginInformation = { - version : "1.6", + version : "1.7", developer : "Stanislas Rolland", - developerUrl : "http://www.fructifor.ca/", + developerUrl : "http://www.sjbr.ca/", copyrightOwner : "Stanislas Rolland", - sponsor : "Fructifor Inc.", - sponsorUrl : "http://www.fructifor.ca/", + sponsor : "SJBR", + sponsorUrl : "http://www.sjbr.ca/", license : "GPL" }; this.registerPluginInformation(pluginInformation); @@ -172,7 +172,7 @@ } if (param["cleaning_area"] == "all") { - editor._doc.body.innerHTML = html; + editor.setHTML(html); } else { editor.insertHTML(html); } @@ -182,4 +182,3 @@ } } }); - Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/SelectFont/select-font.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/SelectFont/select-font.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/SelectFont/select-font.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2008-2009 Stanislas Rolland +* (c) 2008-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -40,35 +40,22 @@ */ configurePlugin : function (editor) { - this.options = new Object(); - this.defaultValue = new Object(); - if (this.editorConfiguration.buttons.fontstyle) { - this.options.FontName = this.editorConfiguration.buttons.fontstyle.options; - if (this.editorConfiguration.buttons.fontstyle.defaultItem) { - this.defaultValue.FontName = this.editorConfiguration.buttons.fontstyle.options[this.editorConfiguration.buttons.fontstyle.defaultItem]; - } - } - if (this.editorConfiguration.buttons.fontsize) { - this.options.FontSize = this.editorConfiguration.buttons.fontsize.options; - if (this.editorConfiguration.buttons.fontsize.defaultItem) { - this.defaultValue.FontSize = this.editorConfiguration.buttons.fontsize.options[this.editorConfiguration.buttons.fontsize.defaultItem]; - } - } + this.buttonsConfiguration = this.editorConfiguration.buttons; this.disablePCexamples = this.editorConfiguration.disablePCexamples; // Font formating will use the style attribute - if (this.editor.getPluginInstance("TextStyle")) { - this.editor.getPluginInstance("TextStyle").addAllowedAttribute("style"); - this.allowedAttributes = this.editor.getPluginInstance("TextStyle").allowedAttributes; + if (this.getPluginInstance("TextStyle")) { + this.getPluginInstance("TextStyle").addAllowedAttribute("style"); + this.allowedAttributes = this.getPluginInstance("TextStyle").allowedAttributes; } - if (this.editor.getPluginInstance("InlineElements")) { - this.editor.getPluginInstance("InlineElements").addAllowedAttribute("style"); + if (this.getPluginInstance("InlineElements")) { + this.getPluginInstance("InlineElements").addAllowedAttribute("style"); if (!this.allowedAllowedAttributes) { - this.allowedAttributes = this.editor.getPluginInstance("InlineElements").allowedAttributes; + this.allowedAttributes = this.getPluginInstance("InlineElements").allowedAttributes; } } - if (this.editor.getPluginInstance("BlockElements")) { - this.editor.getPluginInstance("BlockElements").addAllowedAttribute("style"); + if (this.getPluginInstance("BlockElements")) { + this.getPluginInstance("BlockElements").addAllowedAttribute("style"); } if (!this.allowedAttributes) { this.allowedAttributes = new Array("id", "title", "lang", "xml:lang", "dir", "class", "style"); @@ -94,19 +81,25 @@ /* * Registering the dropdowns */ - var buttonId; - for (var i = 0, n = this.dropDownList.length; i < n; ++i) { - var dropDown = this.dropDownList[i]; - buttonId = dropDown[0]; + Ext.each(this.dropDownList, function (dropDown) { + var buttonId = dropDown[0]; + // Load the options var + if (this.buttonsConfiguration[dropDown[2]] && this.buttonsConfiguration[dropDown[2]].dataUrl) { + var optionsData = this.getJavascriptFile(this.buttonsConfiguration[dropDown[2]].dataUrl, "noEval"); + if (optionsData) { + eval(optionsData); + } + } var dropDownConfiguration = { - id : buttonId, - tooltip : this.localize(buttonId.toLowerCase()), - options : this.options[buttonId], - action : "onChange", - context : null + id: buttonId, + tooltip: this.localize(buttonId.toLowerCase()), + options: options, + action: "onChange", + tpl: this.disablePCexamples ? '' : '
{text}
' }; this.registerDropDown(dropDownConfiguration); - } + return true; + }, this); return true; }, @@ -114,8 +107,8 @@ * The list of buttons added by this plugin */ dropDownList : [ - ["FontName", null], - ["FontSize", null] + ['FontName', null, 'fontstyle', 'font-family:{value};text-align:left;font-size:11px;'], + ['FontSize', null, 'fontsize', 'text-align:left;font-size:{value};'] ], /* @@ -137,21 +130,17 @@ /* * This function gets called when some font style or font size was selected from the dropdown lists */ - onChange : function (editor, buttonId) { - var select = document.getElementById(this.editor._toolbarObjects[buttonId].elementId), - param = select.value; - if (!select.selectedIndex) { - param = ""; - } + onChange : function (editor, combo, record, index) { + var param = combo.getValue(); editor.focusEditor(); var selection = editor._getSelection(), range = editor._createRange(selection), - statusBarSelection = editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null, + statusBarSelection = editor.statusBar ? editor.statusBar.getSelection() : null, element; if (editor._selectionEmpty(selection)) { element = editor.getParentElement(selection, range); // Set the style attribute - this.setStyle(element, buttonId, param); + this.setStyle(element, combo.itemId, param); // Remove the span tag if it has no more attribute if ((element.nodeName.toLowerCase() === "span") && !HTMLArea.hasAllowedAttributes(element, this.allowedAttributes)) { editor.removeMarkup(element); @@ -159,7 +148,7 @@ } else if (statusBarSelection) { element = statusBarSelection; // Set the style attribute - this.setStyle(element, buttonId, param); + this.setStyle(element, combo.itemId, param); // Remove the span tag if it has no more attribute if ((element.nodeName.toLowerCase() === "span") && !HTMLArea.hasAllowedAttributes(element, this.allowedAttributes)) { editor.removeMarkup(element); @@ -167,7 +156,7 @@ } else if (editor.endPointsInSameBlock()) { element = editor._doc.createElement("span"); // Set the style attribute - this.setStyle(element, buttonId, param); + this.setStyle(element, combo.itemId, param); // Wrap the selection with span tag with the style attribute editor.wrapWithInlineElement(element, selection, range); if (HTMLArea.is_gecko) { @@ -187,9 +176,9 @@ * @return void */ setStyle : function (element, buttonId, value) { - element.style[this.styleProperty[buttonId]] = value; + element.style[this.styleProperty[buttonId]] = (value && value !== 'none') ? value : ''; // In IE, we need to remove the empty attribute in order to unset it - if (HTMLArea.is_ie && !value) { + if (HTMLArea.is_ie && (!value || value == 'none')) { element.style.removeAttribute(this.styleProperty[buttonId], false); } if (HTMLArea.is_opera) { @@ -207,62 +196,36 @@ /* * This function gets called when the toolbar is updated */ - onUpdateToolbar : function () { + onUpdateToolbar: function (select, mode, selectionEmpty, ancestors, endPointsInSameBlock) { var editor = this.editor; - if (editor.getMode() === "wysiwyg" && this.editor.isEditable()) { - var statusBarSelection = editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null; - var parentElement = statusBarSelection ? statusBarSelection : editor.getParentElement(), - enabled = editor.endPointsInSameBlock() && !(editor._selectionEmpty(editor._getSelection()) && parentElement.nodeName.toLowerCase() == "body"), - buttonId, value, k; - for (var i = this.dropDownList.length; --i >= 0;) { - buttonId = this.dropDownList[i][0]; - if (this.isButtonInToolbar(buttonId)) { - var select = document.getElementById(editor._toolbarObjects[buttonId].elementId); - value = parentElement.style[this.styleProperty[buttonId]]; - if (!value) { - if (HTMLArea.is_gecko) { - if (editor._doc.defaultView.getComputedStyle(parentElement, null)) { - value = editor._doc.defaultView.getComputedStyle(parentElement, null).getPropertyValue(this.cssProperty[buttonId]); - } - } else { - value = parentElement.currentStyle[this.styleProperty[buttonId]]; - } + if (mode === 'wysiwyg' && editor.isEditable()) { + var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null; + var parentElement = statusBarSelection ? statusBarSelection : editor.getParentElement(); + var value = parentElement.style[this.styleProperty[select.itemId]]; + if (!value) { + if (HTMLArea.is_gecko) { + if (editor._doc.defaultView.getComputedStyle(parentElement, null)) { + value = editor._doc.defaultView.getComputedStyle(parentElement, null).getPropertyValue(this.cssProperty[select.itemId]); } - select.selectedIndex = 0; - if (value) { - var options = this.options[buttonId]; - k = 0; - for (var option in options) { - if (options.hasOwnProperty(option)) { - if (options[option] == value - || options[option].replace(/[\'\"]/g, "") == value.replace(/, /g, ",").replace(/[\'\"]/g, "")) { - select.selectedIndex = k; - break; - } - ++k; - } - } - } - select.disabled = !enabled; - select.className = ""; - if (select.disabled) { - select.className = "buttonDisabled"; - } + } else { + value = parentElement.currentStyle[this.styleProperty[select.itemId]]; } } - } - }, - - /* - * This function gets called when the plugin is generated - */ - onGenerate : function () { - if (!this.disablePCexamples && this.isButtonInToolbar("FontName")) { - var select = document.getElementById(this.editor._toolbarObjects.FontName.elementId); - for (var i = select.options.length; --i >= 0;) { - if (HTMLArea.is_gecko) select.options[i].setAttribute("style", "font-family:" + select.options[i].value + ";"); - else select.options[i].style.cssText = "font-family:" + select.options[i].value + ";"; + var store = select.getStore(); + var index = -1; + if (value) { + index = store.findBy( + function (record, id) { + return record.get('value').replace(/[\"\']/g, "") == value.replace(/, /g, ",").replace(/[\"\']/g, ""); + } + ); } + if (index != -1) { + select.setValue(store.getAt(index).get('value')); + } else { + select.setValue('none'); + } + select.setDisabled(!endPointsInSameBlock || (selectionEmpty && /^body$/i.test(parentElement.nodeName))); } } }); Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-check-ui.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-check-ui.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-check-ui.js (copie de travail) @@ -67,7 +67,7 @@ function saveClicked() { if (modified) { - dialog.plugin.editor.getPluginInstance("EditorMode").setHTML(makeCleanDoc(false)); + dialog.plugin.editor.setHTML(makeCleanDoc(false)); } if ((to_p_dict.length || to_r_list.length) && dialog.plugin.enablePersonalDicts) { var data = {}; Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-checker.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-checker.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-checker.js (copie de travail) @@ -2,7 +2,7 @@ * Copyright notice * * (c) 2003 dynarch.com. Authored by Mihai Bazon, sponsored by www.americanbible.org. -* (c) 2004-2009 Stanislas Rolland +* (c) 2004-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -92,8 +92,6 @@ // Could be a button or its hotkey var buttonId = this.translateHotKey(id); buttonId = buttonId ? buttonId : id; - - var editorNumber = editor._editorNumber; switch (buttonId) { case "SpellCheck": var charset = (this.contentCharset.toLowerCase() == 'iso-8859-1') ? "-iso-8859-1" : ""; Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/locallang.xml =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/locallang.xml (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/locallang.xml (copie de travail) @@ -67,6 +67,7 @@ + Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/table-operations.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/table-operations.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/table-operations.js (copie de travail) @@ -3,7 +3,7 @@ * * (c) 2002 interactivetools.com, inc. Authored by Mihai Bazon, sponsored by http://www.bloki.com. * (c) 2005 Xinha, http://xinha.gogo.co.nz/ for the original toggle borders function. -* (c) 2004-2009 Stanislas Rolland +* (c) 2004-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -66,11 +66,9 @@ this.defaultClass = this.buttonsConfiguration.table.properties.tableClass.defaultValue; } } - if (this.buttonsConfiguration.blockstyle) { this.tags = this.editorConfiguration.buttons.blockstyle.tags; } - this.tableParts = ["tfoot", "thead", "tbody"]; this.convertAlignment = { "not set" : "none", "left" : "JustifyLeft", "center" : "JustifyCenter", "right" : "JustifyRight", "justify" : "JustifyFull" }; @@ -78,7 +76,7 @@ * Registering plugin "About" information */ var pluginInformation = { - version : "4.2", + version : "5.0", developer : "Mihai Bazon & Stanislas Rolland", developerUrl : "http://www.sjbr.ca/", copyrightOwner : "Mihai Bazon & Stanislas Rolland", @@ -114,7 +112,7 @@ /* * The list of buttons added by this plugin */ - buttonList : [ + buttonList: [ ["InsertTable", null, "table", true], ["toggle-borders", null, "toggleborders", false], ["table-prop", "table", "tableproperties", true], @@ -136,222 +134,430 @@ ["cell-merge", "tr", "cellmerge", false], ["cell-split", "td,th[colSpan!=1,rowSpan!=1]", "cellsplit", false] ], - /* + * Sets of default configuration values for dialogue form fields + */ + configDefaults: { + combo: { + editable: true, + typeAhead: true, + triggerAction: 'all', + forceSelection: true, + mode: 'local', + valueField: 'value', + displayField: 'text', + helpIcon: true, + tpl: '
{text}
' + } + }, + /* * Retrieve the closest element having the specified nodeName in the list of * ancestors of the current selection/caret. */ - getClosest : function (nodeName) { - var editor = this.editor; - var ancestors = editor.getAllAncestors(); - var ret = null; - nodeName = ("" + nodeName).toLowerCase(); - for (var i=0; i < ancestors.length; ++i) { - var el = ancestors[i]; - if (el.nodeName.toLowerCase() == nodeName) { - ret = el; - break; + getClosest: function (nodeName) { + var ancestors = this.editor.getAllAncestors(); + var element = null; + Ext.each(ancestors, function (ancestor) { + if (ancestor.nodeName.toLowerCase() === nodeName) { + element = ancestor; + return false; } + }); + return element; + }, + /* + * Get the integer value of a string or '' if the string is not a number + * + * @param string string: the input value + * + * @return mixed a number or '' + */ + getLength: function (string) { + var length = parseInt(string); + if (isNaN(length)) { + length = ''; } - return ret; + return length; }, - /* - * Open the table properties dialogue + * Open properties dialogue + * + * @param string type: 'cell', 'column', 'row' or 'table' + * @param string buttonId: the buttonId of the button that was pressed + * + * @return void */ - dialogTableProperties : function (buttonId) { - var tablePropertiesInitFunctRef = this.makeFunctionReference("tablePropertiesInit"); - var insert = (buttonId === "InsertTable"); - var arguments = { - buttonId : buttonId, - title : (insert ? "Insert Table" : "Table Properties"), - initialize : tablePropertiesInitFunctRef, - element : (insert ? null : this.getClosest("table")) - }; - var dimensions = { - width : 860, - height : 620 - }; - this.dialog = this.openDialog((insert ? "InsertTable" : "TO-table-prop"), "", "tablePropertiesUpdate", arguments, dimensions); + openPropertiesDialogue: function (type, buttonId) { + // Retrieve the element being edited and set configuration according to type + switch (type) { + case 'cell': + case 'column': + var element = this.getClosest('td'); + if (!element) { + var element = this.getClosest('th'); + } + this.properties = this.buttonsConfiguration.cellproperties.properties; + var title = (type == 'column') ? 'Column Properties' : 'Cell Properties'; + break; + case 'row': + var element = this.getClosest('tr'); + this.properties = this.buttonsConfiguration.rowproperties.properties; + var title = 'Row Properties'; + break; + case 'table': + var insert = (buttonId === 'InsertTable'); + var element = insert ? null : this.getClosest('table'); + this.properties = this.buttonsConfiguration.table.properties; + var title = insert ? 'Insert Table' : 'Table Properties'; + break; + } + var propertySet = element ? type + 'properties' : 'table'; + this.removedFieldsets = (this.buttonsConfiguration[propertySet] && this.buttonsConfiguration[propertySet].removeFieldsets) ? this.buttonsConfiguration[propertySet].removeFieldsets : ''; + this.removedProperties = (this.properties && this.properties.removed) ? this.properties.removed : ''; + // Open the dialogue window + this.openDialogue( + title, + { + element: element, + cell: type == 'cell', + column: type == 'column', + buttonId: buttonId + }, + type == 'table' ? this.getWindowDimensions({ width: 600}, buttonId) : this.getWindowDimensions({ width: 600}, buttonId), + this.buildTabItemsConfig(element, type, buttonId), + type == 'table' ? this.tablePropertiesUpdate : this.rowCellPropertiesUpdate + ); }, - /* - * Initialize the table insertion or table properties dialog + * Build the dialogue tab items config + * + * @param object element: the element being edited, if any + * @param string type: 'cell', 'column', 'row' or 'table' + * @param string buttonId: the buttonId of the button that was pressed + * + * @return object the tab items configuration */ - tablePropertiesInit : function(dialog) { - var doc = dialog.document; - var content = dialog.content; - var table = dialog.arguments.element; - this.removedFieldsets = this.buttonsConfiguration[table?"tableproperties":"table"].removeFieldsets ? this.buttonsConfiguration[table?"tableproperties":"table"].removeFieldsets : ""; - this.properties = this.buttonsConfiguration.table.properties; - this.removedProperties = (this.properties && this.properties.removed) ? this.properties.removed : ""; - TableOperations.buildTitle(doc, content, dialog.arguments.title); - TableOperations.insertSpace(doc, content); - if (this.removedFieldsets.indexOf("description") == -1) { - TableOperations.buildDescriptionFieldset(doc, table, content, "floating"); + buildTabItemsConfig: function (element, type, buttonId) { + var tabItems = []; + var generalTabItems = []; + switch (type) { + case 'table': + if (this.removedFieldsets.indexOf('description') === -1) { + this.addConfigElement(this.buildDescriptionFieldsetConfig(element), generalTabItems); + } + if (Ext.isEmpty(element) || this.removedProperties.indexOf('headers') === -1) { + this.addConfigElement(this.buildSizeAndHeadersFieldsetConfig(element), generalTabItems); + } + break; + case 'column': + if (this.removedFieldsets.indexOf('columntype') == -1) { + this.addConfigElement(this.buildCellTypeFieldsetConfig(element, true), generalTabItems); + } + break; + case 'cell': + if (this.removedFieldsets.indexOf('celltype') == -1) { + this.addConfigElement(this.buildCellTypeFieldsetConfig(element, false), generalTabItems); + } + break; + case 'row': + if (this.removedFieldsets.indexOf('rowgroup') == -1) { + this.addConfigElement(this.buildRowGroupFieldsetConfig(element), generalTabItems); + } + break; } - if (this.removedFieldsets.indexOf("spacing") == -1) TableOperations.buildSpacingFieldset(doc, table, content); - TableOperations.insertSpace(doc, content); - this.buildSizeAndHeadersFieldset(doc, table, content, "floating"); - if (this.removedFieldsets.indexOf("style") == -1 && dialog.editor.config.customSelects.BlockStyle) { - var blockStyle = dialog.editor.plugins.BlockStyle.instance; + if (this.removedFieldsets.indexOf('style') == -1 && this.getButton('BlockStyle')) { + var blockStyle = this.getPluginInstance('BlockStyle'); if (blockStyle && blockStyle.cssLoaded) { - this.buildStylingFieldset(doc, table, content, null, dialog.arguments.buttonId); - TableOperations.insertSpace(doc, content); + this.addConfigElement(this.buildStylingFieldsetConfig(element, buttonId), generalTabItems); } } - this.buildLanguageFieldset(doc, table, content, "floating"); - if (this.removedFieldsets.indexOf("layout") == -1) this.buildLayoutFieldset(doc, table, content, "floating"); - if (this.removedFieldsets.indexOf("alignment") == -1) this.buildAlignmentFieldset(doc, table, content); - TableOperations.insertSpace(doc, content); - if (this.removedFieldsets.indexOf("borders") == -1) this.buildBordersFieldset(dialog.dialogWindow, doc, dialog.editor, table, content); - if (this.removedFieldsets.indexOf("color") == -1) TableOperations.buildColorsFieldset(dialog.dialogWindow, doc, dialog.editor, table, content); - dialog.addButtons("ok", "cancel"); + if (!Ext.isEmpty(generalTabItems)) { + tabItems.push({ + title: this.localize('General'), + items: generalTabItems + }); + } + var layoutTabItems = []; + if (type === 'table' && this.removedFieldsets.indexOf('spacing') === -1) { + this.addConfigElement(this.buildSpacingFieldsetConfig(element), layoutTabItems); + } + if (this.removedFieldsets.indexOf('layout') == -1) { + this.addConfigElement(this.buildLayoutFieldsetConfig(element), layoutTabItems); + } + if (!Ext.isEmpty(layoutTabItems)) { + tabItems.push({ + title: this.localize('Layout'), + items: layoutTabItems + }); + } + var languageTabItems = []; + if (this.removedFieldsets.indexOf('language') === -1 && (this.removedProperties.indexOf('language') === -1 || this.removedProperties.indexOf('direction') === -1) && (this.getButton('Language') || this.getButton('LeftToRight') || this.getButton('RightToLeft'))) { + this.addConfigElement(this.buildLanguageFieldsetConfig(element), languageTabItems); + } + if (!Ext.isEmpty(languageTabItems)) { + tabItems.push({ + title: this.localize('Language'), + items: languageTabItems + }); + } + var alignmentAndBordersTabItems = []; + if (this.removedFieldsets.indexOf('alignment') === -1) { + this.addConfigElement(this.buildAlignmentFieldsetConfig(element), alignmentAndBordersTabItems); + } + if (this.removedFieldsets.indexOf('borders') === -1) { + this.addConfigElement(this.buildBordersFieldsetConfig(element), alignmentAndBordersTabItems); + } + if (!Ext.isEmpty(alignmentAndBordersTabItems)) { + tabItems.push({ + title: this.localize('Alignment') + '/' + this.localize('Border'), + items: alignmentAndBordersTabItems + }); + } + var colorTabItems = []; + if (this.removedFieldsets.indexOf('color') === -1) { + this.addConfigElement(this.buildColorsFieldsetConfig(element), colorTabItems); + } + if (!Ext.isEmpty(colorTabItems)) { + tabItems.push({ + title: this.localize('Background and colors'), + items: colorTabItems + }); + } + return tabItems; }, - /* + * Open the dialogue window + * + * @param string title: the window title + * @param object arguments: some arguments for the handler + * @param integer dimensions: the opening width of the window + * @param object tabItems: the configuration of the tabbed panel + * @param function handler: handler when the OK button if clicked + * + * @return void + */ + openDialogue: function (title, arguments, dimensions, tabItems, handler) { + if (this.dialog) { + this.dialog.close(); + } + this.dialog = new Ext.Window({ + title: this.localize(title), + arguments: arguments, + cls: 'htmlarea-window', + // As of ExtJS 3.1, JS error with IE when the window is resizable + resizable: !Ext.isIE, + border: false, + width: dimensions.width, + height: 'auto', + iconCls: arguments.buttonId, + listeners: { + close: { + fn: this.onClose, + scope: this + } + }, + items: { + xtype: 'tabpanel', + activeTab: 0, + defaults: { + xtype: 'container', + layout: 'form', + defaults: { + labelWidth: 150 + } + }, + listeners: { + tabchange: { + fn: this.syncHeight, + scope: this + } + }, + items: tabItems + }, + buttons: [ + this.buildButtonConfig('Cancel', this.onCancel), + this.buildButtonConfig('OK', handler) + ] + }); + this.show(); + }, + /* * Insert the table or update the table properties and close the dialogue */ - tablePropertiesUpdate : function(dialog, params) { + tablePropertiesUpdate: function () { + this.restoreSelection() + var params = {}; + var fieldTypes = ['combo', 'textfield', 'numberfield', 'checkbox', 'colorpalettefield']; + this.dialog.findBy(function (item) { + if (fieldTypes.indexOf(item.getXType()) !== -1) { + params[item.getItemId()] = item.getValue(); + return true; + } + return false; + }); + var errorFlag = false; if (this.buttonsConfiguration.table.properties && this.buttonsConfiguration.table.properties.required) { - if (this.buttonsConfiguration.table.properties.required.indexOf("captionOrSummary") != -1) { + if (this.buttonsConfiguration.table.properties.required.indexOf('captionOrSummary') != -1) { if (!/\S/.test(params.f_caption) && !/\S/.test(params.f_summary)) { - dialog.dialogWindow.alert(this.localize("captionOrSummary" + "-required")); - var el = dialog.document.getElementById("f_caption"); - el.focus(); + Ext.MessageBox.alert(this.localize('Error'), this.localize('captionOrSummary' + '-required')); + var field = this.dialog.find('itemId', 'f_caption')[0]; + var tab = field.findParentByType('container'); + tab.ownerCt.activate(tab); + field.focus(); return false; } } else { - var required = { "f_caption": "caption", "f_summary": "summary" }; - for (var i in required) { - if (required.hasOwnProperty(i)) { - var el = dialog.document.getElementById(i); - if (!el.value && this.buttonsConfiguration.table.properties.required.indexOf(required[i]) != -1) { - dialog.dialogWindow.alert(this.localize(required[i] + "-required")); - el.focus(); - return false; - } + var required = { + f_caption: 'caption', + f_summary: 'summary' + }; + Ext.iterate(required, function (item) { + if (!params[item] && this.buttonsConfiguration.table.properties.required.indexOf(required[item]) != -1) { + Ext.MessageBox.alert(this.localize('Error'), this.localize(required[item] + '-required')); + var field = this.dialog.find('itemId', item)[0]; + var tab = field.findParentByType('container'); + tab.ownerCt.activate(tab); + field.focus(); + errorFlag = true; + return false; } + }, this); + if (errorFlag) { + return false; } } } - var doc = dialog.editor._doc; - if (dialog.buttonId === "InsertTable") { - var required = { "f_rows": "You must enter a number of rows", "f_cols": "You must enter a number of columns" }; - for (var i in required) { - if (required.hasOwnProperty(i)) { - var el = dialog.document.getElementById(i); - if (!el.value) { - dialog.dialogWindow.alert(this.localize(required[i])); - el.focus(); - return false; - } + var doc = this.editor._doc; + if (this.dialog.arguments.buttonId === 'InsertTable') { + var required = { + f_rows: 'You must enter a number of rows', + f_cols: 'You must enter a number of columns' + }; + Ext.iterate(required, function (item) { + if (!params[item]) { + Ext.MessageBox.alert(this.localize('Error'), this.localize(required[item])); + var field = this.dialog.find('itemId', item)[0]; + var tab = field.findParentByType('container'); + tab.ownerCt.activate(tab); + field.focus(); + errorFlag = true; + return false; } + }, this); + if (errorFlag) { + return false; } - var table = doc.createElement("table"); - var tbody = doc.createElement("tbody"); + var table = doc.createElement('table'); + var tbody = doc.createElement('tbody'); table.appendChild(tbody); for (var i = params.f_rows; --i >= 0;) { - var tr = doc.createElement("tr"); + var tr = doc.createElement('tr'); tbody.appendChild(tr); for (var j = params.f_cols; --j >= 0;) { - var td = doc.createElement("td"); - if (HTMLArea.is_gecko) td.innerHTML = "
"; + var td = doc.createElement('td'); + if (HTMLArea.is_gecko) td.innerHTML = '
'; tr.appendChild(td); } } } else { - var table = dialog.arguments.element; + var table = this.dialog.arguments.element; } - table = this.setHeaders(table, params); - table = this.processStyle(table, params); - table.removeAttribute("border"); - for (var i in params) { - if (params.hasOwnProperty(i)) { - var val = params[i]; - switch (i) { - case "f_caption": - if (/\S/.test(val)) { - // contains non white-space characters - var caption = table.getElementsByTagName("caption"); - if (caption) { - caption = caption[0]; - } - if (!caption) { - var caption = doc.createElement("caption"); - table.insertBefore(caption, table.firstChild); - } - caption.innerHTML = val; - } else { - // delete the caption if found - if (table.caption) table.deleteCaption(); + this.setHeaders(table, params); + this.processStyle(table, params); + table.removeAttribute('border'); + Ext.iterate(params, function (item) { + var val = params[item]; + switch (item) { + case "f_caption": + if (/\S/.test(val)) { + // contains non white-space characters + var caption = table.getElementsByTagName("caption"); + if (caption) { + caption = caption[0]; } - break; - case "f_summary": - table.summary = val; - break; - case "f_width": - table.style.width = ("" + val) + params.f_unit; - break; - case "f_align": - table.align = val; - break; - case "f_spacing": - table.cellSpacing = val; - break; - case "f_padding": - table.cellPadding = val; - break; - case "f_frames": - table.frame = (val != "not set") ? val : ""; - break; - case "f_rules": - if (val != "not set") table.rules = val; - else table.removeAttribute("rules"); - break; - case "f_st_float": - switch (val) { - case "not set": - HTMLArea._removeClass(table, this.floatRight); - HTMLArea._removeClass(table, this.floatLeft); - break; - case "right": - HTMLArea._removeClass(table, this.floatLeft); - HTMLArea._addClass(table, this.floatRight); - break; - case "left": - HTMLArea._removeClass(table, this.floatRight); - HTMLArea._addClass(table, this.floatLeft); - break; + if (!caption) { + var caption = doc.createElement("caption"); + table.insertBefore(caption, table.firstChild); } + caption.innerHTML = val; + } else { + // delete the caption if found + if (table.caption) table.deleteCaption(); + } + break; + case "f_summary": + table.summary = val; + break; + case "f_width": + table.style.width = ("" + val) + params.f_unit; + break; + case "f_align": + table.align = val; + break; + case "f_spacing": + table.cellSpacing = val; + break; + case "f_padding": + table.cellPadding = val; + break; + case "f_frames": + if (val !== 'not set' && table.style.borderStyle !== 'none') { + table.frame = val; + } else { + table.removeAttribute('rules'); + } + break; + case "f_rules": + if (val !== 'not set') { + table.rules = val; + } else { + table.removeAttribute('rules'); + } + break; + case "f_st_float": + switch (val) { + case "not set": + HTMLArea._removeClass(table, this.floatRight); + HTMLArea._removeClass(table, this.floatLeft); break; - case "f_st_textAlign": - if (this.editor.plugins.BlockElements) { - this.editor.plugins.BlockElements.instance.toggleAlignmentClass(table, this.convertAlignment[val]); - table.style.textAlign = ""; - } + case "right": + HTMLArea._removeClass(table, this.floatLeft); + HTMLArea._addClass(table, this.floatRight); break; - case "f_class": - case "f_class_tbody": - case "f_class_thead": - case "f_class_tfoot": - var tpart = table; - if (i.length > 7) tpart = table.getElementsByTagName(i.substring(8,13))[0]; - if (tpart) { - this.editor.plugins.BlockStyle.instance.applyClassChange(tpart, val); - } + case "left": + HTMLArea._removeClass(table, this.floatRight); + HTMLArea._addClass(table, this.floatLeft); break; - case "f_lang": - this.getPluginInstance("Language").setLanguageAttributes(table, val); - break; - case "f_dir": - table.dir = (val != "not set") ? val : ""; - break; } + break; + case "f_st_textAlign": + if (this.getPluginInstance('BlockElements')) { + this.getPluginInstance('BlockElements').toggleAlignmentClass(table, this.convertAlignment[val]); + table.style.textAlign = ""; + } + break; + case "f_class": + case "f_class_tbody": + case "f_class_thead": + case "f_class_tfoot": + var tpart = table; + if (item.length > 7) { + tpart = table.getElementsByTagName(item.substring(8,13))[0]; + } + if (tpart) { + this.getPluginInstance('BlockStyle').applyClassChange(tpart, val); + } + break; + case "f_lang": + this.getPluginInstance('Language').setLanguageAttributes(table, val); + break; + case "f_dir": + table.dir = (val != "not set") ? val : ""; + break; } - } - if (dialog.buttonId === "InsertTable") { - if (HTMLArea.is_gecko) { + }, this); + if (this.dialog.arguments.buttonId === "InsertTable") { + if (!Ext.isIE) { this.editor.insertNodeAtSelection(table); } else { table.id = "htmlarea_table_insert"; @@ -364,94 +570,38 @@ this.toggleBorders(true); } } - dialog.close(); + this.close(); }, - /* - * Open the row/column/cell properties dialogue + * Update the row/column/cell properties */ - dialogRowCellProperties : function (cell, column) { - // retrieve existing values - if (cell) { - var element = this.getClosest("td"); - if (!element) var element = this.getClosest("th"); - } else { - var element = this.getClosest("tr"); - } - if (element) { - var rowCellPropertiesInitFunctRef = this.makeFunctionReference("rowCellPropertiesInit"); - var arguments = { - title : (cell ? (column ? "Column Properties" : "Cell Properties") : "Row Properties"), - initialize : rowCellPropertiesInitFunctRef, - element : element, - cell : cell, - column : column - }; - this.dialog = this.openDialog("TO-" + (cell ? (column ? "col-prop" : "cell-prop") :"row-prop"), "", "rowCellPropertiesUpdate", arguments, { width : 660, height : 460 }); - } - }, - - /* - * Initialize the row/column/cell properties dialogue - */ - rowCellPropertiesInit : function(dialog) { - var doc = dialog.document; - var content = dialog.content; - var element = dialog.arguments.element; - var cell = dialog.arguments.cell; - var column = dialog.arguments.column; - this.removedFieldsets = this.buttonsConfiguration[cell?(column?"columnproperties":"cellproperties"):"rowproperties"].removeFieldsets ? this.buttonsConfiguration[cell?(column?"columnproperties":"cellproperties"):"rowproperties"].removeFieldsets : ""; - this.properties = this.buttonsConfiguration[(cell ||column)?"cellproperties":"rowproperties"].properties; - this.removedProperties = (this.properties && this.properties.removed) ? this.properties.removed : ""; - TableOperations.buildTitle(doc, content, (cell ? (column ? "Column Properties" : "Cell Properties") : "Row Properties")); - TableOperations.insertSpace(doc, content); - if (column) { - if (this.removedFieldsets.indexOf("columntype") == -1) this.buildCellTypeFieldset(doc, element, content, true); - } else if (cell) { - if (this.removedFieldsets.indexOf("celltype") == -1) this.buildCellTypeFieldset(doc, element, content, false); - } else { - if (this.removedFieldsets.indexOf("rowgroup") == -1) TableOperations.buildRowGroupFieldset(dialog.dialogWindow, doc, dialog.editor, element, content); - } - if (this.removedFieldsets.indexOf("style") == -1 && this.editor.config.customSelects.BlockStyle) { - var blockStyle = this.editor.plugins.BlockStyle.instance; - if (blockStyle && blockStyle.cssLoaded) { - this.buildStylingFieldset(doc, element, content); - TableOperations.insertSpace(doc, content); - } else { - TableOperations.insertSpace(doc, content); + rowCellPropertiesUpdate: function() { + this.restoreSelection() + // Collect values from each form field + var params = {}; + var fieldTypes = ['combo', 'textfield', 'numberfield', 'checkbox', 'colorpalettefield']; + this.dialog.findBy(function (item) { + if (fieldTypes.indexOf(item.getXType()) !== -1) { + params[item.getItemId()] = item.getValue(); + return true; } - } else { - TableOperations.insertSpace(doc, content); - } - this.buildLanguageFieldset(doc, element, content, "floating"); - if (this.removedFieldsets.indexOf("layout") == -1) this.buildLayoutFieldset(doc, element, content, "floating"); - if (this.removedFieldsets.indexOf("alignment") == -1) this.buildAlignmentFieldset(doc, element, content); - if (this.removedFieldsets.indexOf("borders") == -1) this.buildBordersFieldset(dialog.dialogWindow, doc, dialog.editor, element, content); - if (this.removedFieldsets.indexOf("color") == -1) TableOperations.buildColorsFieldset(dialog.dialogWindow, doc, dialog.editor, element, content); - dialog.addButtons("ok", "cancel"); - }, - - /* - * Update the row/column/cell properties - */ - rowCellPropertiesUpdate : function(dialog, params) { - var element = dialog.arguments.element; - var cell = dialog.arguments.cell; - var column = dialog.arguments.column; - var section = (cell || column) ? element.parentNode.parentNode : element.parentNode; + return false; + }); + var cell = this.dialog.arguments.cell; + var column = this.dialog.arguments.column; + var section = (cell || column) ? this.dialog.arguments.element.parentNode.parentNode : this.dialog.arguments.element.parentNode; var table = section.parentNode; - var elements = new Array(); + var elements = []; if (column) { - elements = this.getColumnCells(dialog.arguments.element); + elements = this.getColumnCells(this.dialog.arguments.element); } else { - elements.push(dialog.arguments.element); + elements.push(this.dialog.arguments.element); } - for (var k = elements.length; --k >= 0;) { - var element = elements[k]; - element = this.processStyle(element, params); - for (var i in params) { - var val = params[i]; - switch (i) { + Ext.each(elements, function (element) { + this.processStyle(element, params); + Ext.iterate(params, function (item) { + var val = params[item]; + switch (item) { case "f_cell_type": if (val.substring(0,2) != element.nodeName.toLowerCase()) { element = this.remapCell(element, val.substring(0,2)); @@ -465,7 +615,7 @@ var nodeName = section.nodeName.toLowerCase(); if (val != nodeName) { var newSection = table.getElementsByTagName(val)[0]; - if (!newSection) var newSection = table.insertBefore(dialog.editor._doc.createElement(val), table.getElementsByTagName("tbody")[0]); + if (!newSection) var newSection = table.insertBefore(this.editor._doc.createElement(val), table.getElementsByTagName("tbody")[0]); if (nodeName == "thead" && val == "tbody") var newElement = newSection.insertBefore(element, newSection.firstChild); else var newElement = newSection.appendChild(element); if (!section.hasChildNodes()) table.removeChild(section); @@ -479,46 +629,52 @@ } break; case "f_st_textAlign": - if (this.editor.plugins.BlockElements) { - this.editor.plugins.BlockElements.instance.toggleAlignmentClass(element, this.convertAlignment[val]); + if (this.getPluginInstance('BlockElements')) { + this.getPluginInstance('BlockElements').toggleAlignmentClass(element, this.convertAlignment[val]); element.style.textAlign = ""; } break; case "f_class": - this.editor.plugins.BlockStyle.instance.applyClassChange(element, val); + this.getPluginInstance('BlockStyle').applyClassChange(element, val); break; case "f_lang": - this.getPluginInstance("Language").setLanguageAttributes(element, val); + this.getPluginInstance('Language').setLanguageAttributes(element, val); break; case "f_dir": element.dir = (val != "not set") ? val : ""; break; } - } - } + }, this); + }, this); this.reStyleTable(table); - dialog.close(); + this.close(); }, - /* * This function gets called when the plugin is generated - * Set table borders if requested by configuration */ - onGenerate : function() { + onGenerate: function () { + // Set table borders if requested by configuration if (this.buttonsConfiguration.toggleborders && this.buttonsConfiguration.toggleborders.setOnRTEOpen) { this.toggleBorders(true); } + // Register handler for the enter key for IE and Opera when buttons.table.disableEnterParagraphs is set in the editor configuration + if ((Ext.isIE || Ext.isOpera) && this.disableEnterParagraphs) { + this.editor.iframe.keyMap.addBinding({ + key: Ext.EventObject.ENTER, + shift: false, + handler: this.onKey, + scope: this + }); + } }, - /* * This function gets called when the toolbar is being updated */ - onUpdateToolbar : function() { - if (this.getEditorMode() === "wysiwyg" && this.editor.isEditable() && this.isButtonInToolbar("TO-toggle-borders")) { - this.editor._toolbarObjects["TO-toggle-borders"].state("active", HTMLArea._hasClass(this.editor._doc.body, 'htmlarea-showtableborders')); + onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) { + if (mode === 'wysiwyg' && this.editor.isEditable() && button.itemId === 'TO-toggle-borders') { + button.setInactive(!HTMLArea._hasClass(this.editor._doc.body, 'htmlarea-showtableborders')); } }, - /* * This function gets called when a Table Operations button was pressed. * @@ -527,7 +683,7 @@ * * @return boolean false if action is completed */ - onButtonPress : function (editor, id, target) { + onButtonPress: function (editor, id, target) { // Could be a button or its hotkey var buttonId = this.translateHotKey(id); buttonId = buttonId ? buttonId : id; @@ -858,7 +1014,7 @@ for (var k = tableParts.length; --k >= 0;) rows[k] = []; var row = null; var cells = null; - if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) { + if (Ext.isGecko) { try { while (range = sel.getRangeAt(i++)) { var td = range.startContainer.childNodes[range.startOffset]; @@ -878,7 +1034,7 @@ var cell = this.getClosest("td"); if (!cell) var cell = this.getClosest("th"); if (!cell) { - alert(this.localize("Please click into some cell")); + Ext.MessageBox.alert('', this.localize("Please click into some cell")); break; } var tr = cell.parentElement; @@ -956,19 +1112,19 @@ // CREATION AND PROPERTIES case "InsertTable": case "TO-table-prop": - this.dialogTableProperties(buttonId); + this.openPropertiesDialogue('table', buttonId); break; case "TO-table-restyle": - this.reStyleTable(this.getClosest("table")); + this.reStyleTable(this.getClosest('table')); break; case "TO-row-prop": - this.dialogRowCellProperties(false, false); + this.openPropertiesDialogue('row', buttonId); break; case "TO-col-prop": - this.dialogRowCellProperties(true, true); + this.openPropertiesDialogue('column', buttonId); break; case "TO-cell-prop": - this.dialogRowCellProperties(true, false); + this.openPropertiesDialogue('cell', buttonId); break; case "TO-toggle-borders": this.toggleBorders(); @@ -977,7 +1133,6 @@ alert("Button [" + buttonId + "] not yet implemented"); } }, - /* * Returns an array of all cells in the column containing the given cell * @@ -1002,7 +1157,6 @@ } return cells; }, - /* * Toggles the display of borders on tables and table cells * @@ -1018,7 +1172,6 @@ HTMLArea._removeClass(body,'htmlarea-showtableborders'); } }, - /* * Applies to rows/cells the alternating and counting classes of an alternating or counting style scheme * @@ -1058,7 +1211,6 @@ } } }, - /* * Removes from rows/cells the alternating classes of an alternating style scheme * @@ -1083,7 +1235,6 @@ } } }, - /* * Applies/removes the alternating classes of an alternating rows style scheme * @@ -1124,7 +1275,6 @@ } } }, - /* * Applies/removes the alternating classes of an alternating columns style scheme * @@ -1168,8 +1318,7 @@ } } } - }, - + }, /* * Removes from rows/cells the counting classes of an counting style scheme * @@ -1194,7 +1343,6 @@ } } }, - /* * Applies/removes the counting classes of an counting rows style scheme * @@ -1241,7 +1389,6 @@ } } }, - /* * Applies/removes the counting classes of a counting columns style scheme * @@ -1292,16 +1439,15 @@ } } }, - /* * This function sets the headers cells on the table (top, left, both or none) * * @param object table: the table being edited * @param object params: the field values entered in the form * - * @return object the modified table + * @return void */ - setHeaders : function (table, params) { + setHeaders: function (table, params) { var headers = params.f_headers; var doc = this.editor._doc; var tbody = table.tBodies[0]; @@ -1371,7 +1517,6 @@ } } this.reStyleTable(table); - return table; }, /* @@ -1442,9 +1587,9 @@ * @param object element: the element * @param object params: the properties * - * @return object the modified element + * @return void */ - processStyle : function (element, params) { + processStyle: function (element, params) { var style = element.style; if (HTMLArea.is_ie) { style.styleFloat = ""; @@ -1457,10 +1602,10 @@ var val = params[i]; switch (i) { case "f_st_backgroundColor": - style.backgroundColor = val; + style.backgroundColor = ((val.charAt(0) === '#') ? '' : '#') + val; break; case "f_st_color": - style.color = val; + style.color = ((val.charAt(0) === '#') ? '' : '#') + val; break; case "f_st_backgroundImage": if (/\S/.test(val)) { @@ -1482,10 +1627,16 @@ style.borderStyle = (val != "not set") ? val : ""; break; case "f_st_borderColor": - style.borderColor = val; + style.borderColor = ((val.charAt(0) === '#') ? '' : '#') + val; + if (params.f_st_borderStyle === 'none') { + style.borderColor = ''; + } break; case "f_st_borderCollapse": - style.borderCollapse = val ? "collapse" : ""; + style.borderCollapse = (val !== 'not set') ? val : ''; + if (params.f_st_borderStyle === 'none') { + style.borderCollapse = ''; + } break; case "f_st_width": if (/\S/.test(val)) { @@ -1510,610 +1661,888 @@ } } } - return element; }, - /* - * This function creates a Size and Headers fieldset to be added to the form + * This function builds the configuration object for the table Description fieldset * - * @param object doc: the dialog document - * @param object table: the table being edited - * @param object content: the content div of the dialog window + * @param object table: the table being edited, if any * - * @return void + * @return object the fieldset configuration object */ - buildSizeAndHeadersFieldset : function (doc, table, content, fieldsetClass) { - if (!table || this.removedProperties.indexOf("headers") == -1) { - var fieldset = doc.createElement("fieldset"); - if (fieldsetClass) fieldset.className = fieldsetClass; - if (!table) { - TableOperations.insertLegend(doc, fieldset, "Size and Headers"); - TableOperations.buildInput(doc, fieldset, "f_rows", "Rows:", "Number of rows", "", "5", ((this.properties && this.properties.numberOfRows && this.properties.numberOfRows.defaultValue) ? this.properties.numberOfRows.defaultValue : "2"), "fr"); - TableOperations.insertSpace(doc, fieldset); - TableOperations.buildInput(doc, fieldset, "f_cols", "Cols:", "Number of columns", "", "5", ((this.properties && this.properties.numberOfColumns && this.properties.numberOfColumns.defaultValue) ? this.properties.numberOfColumns.defaultValue : "4"), "fr"); + buildDescriptionFieldsetConfig: function (table) { + if (!Ext.isEmpty(table)) { + var caption = table.getElementsByTagName('caption')[0]; + } + return { + xtype: 'fieldset', + title: this.localize('Description'), + defaultType: 'textfield', + defaults: { + labelSeparator: '', + helpIcon: true + }, + items: [{ + fieldLabel: this.localize('Caption:'), + itemId: 'f_caption', + value: Ext.isDefined(caption) ? caption.innerHTML : '', + width: 300, + helpTitle: this.localize('Description of the nature of the table') + },{ + fieldLabel: this.localize('Summary:'), + itemId: 'f_summary', + value: !Ext.isEmpty(table) ? table.summary : '', + width: 300, + helpTitle: this.localize('Summary of the table purpose and structure') + }] + }; + }, + /* + * This function builds the configuration object for the table Size and Headers fieldset + * + * @param object table: the table being edited, if any + * + * @return object the fieldset configuration object + */ + buildSizeAndHeadersFieldsetConfig: function (table) { + var itemsConfig = []; + if (Ext.isEmpty(table)) { + itemsConfig.push({ + fieldLabel: this.localize('Rows:'), + labelSeparator: '', + itemId: 'f_rows', + value: (this.properties && this.properties.numberOfRows && this.properties.numberOfRows.defaultValue) ? this.properties.numberOfRows.defaultValue : '2', + width: 30, + minValue: 1, + helpTitle: this.localize('Number of rows') + }); + itemsConfig.push({ + fieldLabel: this.localize('Cols:'), + labelSeparator: '', + itemId: 'f_cols', + value: (this.properties && this.properties.numberOfColumns && this.properties.numberOfColumns.defaultValue) ? this.properties.numberOfColumns.defaultValue : '4', + width: 30, + minValue: 1, + helpTitle: this.localize('Number of columns') + }); + } + if (this.removedProperties.indexOf('headers') == -1) { + // Create combo store + var store = new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}], + data: [ + [this.localize('No header cells'), 'none'], + [this.localize('Header cells on top'), 'top'], + [this.localize('Header cells on left'), 'left'], + [this.localize('Header cells on top and left'), 'both'] + ] + }); + this.removeOptions(store, 'headers'); + if (Ext.isEmpty(table)) { + var selected = (this.properties && this.properties.headers && this.properties.headers.defaultValue) ? this.properties.headers.defaultValue : 'top'; } else { - TableOperations.insertLegend(doc, fieldset, "Headers"); - } - if (this.removedProperties.indexOf("headers") == -1) { - var ul = doc.createElement("ul"); - fieldset.appendChild(ul); - var li = doc.createElement("li"); - ul.appendChild(li); - if (!table) { - var selected = (this.properties && this.properties.headers && this.properties.headers.defaultValue) ? this.properties.headers.defaultValue : "top"; - } else { - var selected = "none"; - var thead = table.getElementsByTagName("thead"); - var tbody = table.getElementsByTagName("tbody"); - if (thead.length && thead[0].rows.length) { - selected = "top"; - } else if (tbody.length && tbody[0].rows.length) { - if (HTMLArea._hasClass(tbody[0].rows[0], this.useHeaderClass)) { - selected = "both"; - } else if (tbody[0].rows[0].cells.length && tbody[0].rows[0].cells[0].nodeName.toLowerCase() == "th") { - selected = "left"; - } + var selected = 'none'; + var thead = table.getElementsByTagName('thead'); + var tbody = table.getElementsByTagName('tbody'); + if (thead.length && thead[0].rows.length) { + selected = 'top'; + } else if (tbody.length && tbody[0].rows.length) { + if (HTMLArea._hasClass(tbody[0].rows[0], this.useHeaderClass)) { + selected = 'both'; + } else if (tbody[0].rows[0].cells.length && tbody[0].rows[0].cells[0].nodeName.toLowerCase() == 'th') { + selected = 'left'; } } - var selectHeaders = TableOperations.buildSelectField(doc, li, "f_headers", "Headers:", "fr", "floating", "Table headers", ["No header cells", "Header cells on top", "Header cells on left", "Header cells on top and left"], ["none", "top", "left", "both"], new RegExp((selected ? selected : "top"), "i")); - this.removeOptions(selectHeaders, "headers"); } - TableOperations.insertSpace(doc, fieldset); - content.appendChild(fieldset); + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize('Headers:'), + itemId: 'f_headers', + helpTitle: this.localize('Table headers'), + store: store, + width: (this.properties && this.properties['headers'] && this.properties['headers'].width) ? this.properties['headers'].width : 200, + value: selected + }, this.configDefaults['combo'])); } + return { + xtype: 'fieldset', + title: this.localize(Ext.isEmpty(table) ? 'Size and Headers' : 'Headers'), + defaultType: 'numberfield', + defaults: { + helpIcon: true + }, + items: itemsConfig + }; }, - - buildLayoutFieldset : function(doc, el, content, fieldsetClass) { - var select, selected; - var fieldset = doc.createElement("fieldset"); - if (fieldsetClass) fieldset.className = fieldsetClass; - TableOperations.insertLegend(doc, fieldset, "Layout"); - var f_st_width = el ? TableOperations.getLength(el.style.width) : ((this.properties && this.properties.width && this.properties.width.defaultValue) ? this.properties.width.defaultValue : ""); - var f_st_height = el ? TableOperations.getLength(el.style.height) : ((this.properties && this.properties.height && this.properties.height.defaultValue) ? this.properties.height.defaultValue : ""); - var selectedWidthUnit = el ? (/%/.test(el.style.width) ? '%' : (/px/.test(el.style.width) ? 'px' : 'em')) : ((this.properties && this.properties.widthUnit &&this.properties.widthUnit.defaultValue) ? this.properties.widthUnit.defaultValue : "%"); - var selectedHeightUnit = el ? (/%/.test(el.style.height) ? '%' : (/px/.test(el.style.height) ? 'px' : 'em')) : ((this.properties && this.properties.heightUnit &&this.properties.heightUnit.defaultValue) ? this.properties.heightUnit.defaultValue : "%"); - var nodeName = el ? el.nodeName.toLowerCase() : "table"; - var ul = doc.createElement("ul"); - fieldset.appendChild(ul); - switch(nodeName) { - case "table" : - var widthTitle = "Table width"; - var heightTitle = "Table height"; - break; - case "tr" : - var widthTitle = "Row width"; - var heightTitle = "Row height"; - break; - case "td" : - case "th" : - var widthTitle = "Cell width"; - var heightTitle = "Cell height"; + /* + * This function builds the configuration object for the Style fieldset + * + * @param object element: the element being edited, if any + * @param string buttonId: the id of the button that was pressed + * + * @return object the fieldset configuration object + */ + buildStylingFieldsetConfig: function (element, buttonId) { + var itemsConfig = []; + var nodeName = element ? element.nodeName.toLowerCase() : 'table'; + var table = (nodeName == 'table'); + var select = this.buildStylingFieldConfig('f_class', (table ? 'Table class:' : 'Class:'), (table ? 'Table class selector' : 'Class selector')); + this.setStyleOptions(select, element, nodeName, (buttonId === 'InsertTable') ? this.defaultClass : null); + itemsConfig.push(select); + if (element && table) { + var tbody = element.getElementsByTagName('tbody')[0]; + if (tbody) { + var tbodyStyleSelect = this.buildStylingFieldConfig('f_class_tbody', 'Table body class:', 'Table body class selector'); + this.setStyleOptions(tbodyStyleSelect, tbody, 'tbody'); + itemsConfig.push(tbodyStyleSelect); + } + var thead = element.getElementsByTagName('thead')[0]; + if (thead) { + var theadStyleSelect = this.buildStylingFieldConfig('f_class_thead', 'Table header class:', 'Table header class selector'); + this.setStyleOptions(theadStyleSelect, thead, 'thead'); + itemsConfig.push(theadStyleSelect); + } + var tfoot = element.getElementsByTagName('tfoot')[0]; + if (tfoot) { + var tfootStyleSelect = this.buildStylingFieldConfig('f_class_tfoot', 'Table footer class:', 'Table footer class selector'); + this.setStyleOptions(tfootStyleSelect, tfoot, 'tfoot'); + itemsConfig.push(tfootStyleSelect); + } } - if (this.removedProperties.indexOf("width") == -1) { - var li = doc.createElement("li"); - ul.appendChild(li); - TableOperations.buildInput(doc, li, "f_st_width", "Width:", widthTitle, "", "5", f_st_width, "fr"); - select = TableOperations.buildSelectField(doc, li, "f_st_widthUnit", "", "", "", "Width unit", ["percent", "pixels", "em"], ["%", "px", "em"], new RegExp((selectedWidthUnit ? selectedWidthUnit : "%"), "i")); - this.removeOptions(select, "widthUnit"); - } - if (this.removedProperties.indexOf("height") == -1) { - var li = doc.createElement("li"); - ul.appendChild(li); - TableOperations.buildInput(doc, li, "f_st_height", "Height:", heightTitle, "", "5", f_st_height, "fr"); - select = TableOperations.buildSelectField(doc, li, "f_st_heightUnit", "", "", "", "Height unit", ["percent", "pixels", "em"], ["%", "px", "em"], new RegExp((selectedHeightUnit ? selectedHeightUnit : "%"), "i")); - this.removeOptions(select, "heightUnit"); - } - if (nodeName == "table" && this.removedProperties.indexOf("float") == -1) { - selected = el ? (HTMLArea._hasClass(el, this.floatLeft) ? "left" : (HTMLArea._hasClass(el, this.floatRight) ? "right" : "not set")) : this.floatDefault; - select = TableOperations.buildSelectField(doc, li, "f_st_float", "Float:", "", "", "Specifies where the table should float", ["Not set", "Left", "Right"], ["not set", "left", "right"], new RegExp((selected ? selected : "not set"), "i")); - this.removeOptions(select, "float"); - } - content.appendChild(fieldset); + return { + xtype: 'fieldset', + defaults: { + labelSeparator: '' + }, + title: this.localize('CSS Style'), + items: itemsConfig + }; }, - - setStyleOptions : function (doc, dropDown, el, nodeName, defaultClass) { - if (!dropDown) return false; - if (this.editor.config.customSelects.BlockStyle) { - var blockStyle = this.editor.plugins.BlockStyle.instance; - if (!blockStyle || !blockStyle.cssLoaded) return false; + /* + * This function builds a style selection field + * + * @param string fieldName: the name of the field + * @param string fieldLabel: the label for the field + * @param string fieldTitle: the title for the field tooltip + * + * @return object the style selection field object + */ + buildStylingFieldConfig: function(fieldName, fieldLabel, fieldTitle) { + return new Ext.form.ComboBox(Ext.apply({ + xtype: 'combo', + itemId: fieldName, + fieldLabel: this.localize(fieldLabel), + helpTitle: this.localize(fieldTitle), + width: (this.properties && this.properties['style'] && this.properties['style'].width) ? this.properties['style'].width : 300, + store: new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}, { name: 'style'} ], + data: [[this.localize('No block style'), 'none']] + }), + }, { + tpl: '
{text}
' + }, this.configDefaults['combo'] + )); + }, + /* + * This function populates the style store and sets the selected option + * + * @param object: dropDown: the combobox object + * @param object element: the element being edited, if any + * @param string nodeName: the type of element ('table' on table insertion) + * @param string defaultClass: default class, if any is configured + * + * @return object the fieldset configuration object + */ + setStyleOptions: function (dropDown, element, nodeName, defaultClass) { + var blockStyle = this.getPluginInstance('BlockStyle'); + if (dropDown && blockStyle && blockStyle.cssLoaded) { if (defaultClass) { var classNames = new Array(); classNames.push(defaultClass); } else { - var classNames = blockStyle.getClassNames(el); + var classNames = blockStyle.getClassNames(element); } blockStyle.buildDropDownOptions(dropDown, nodeName); - blockStyle.setSelectedOption(dropDown, classNames, "noUnknown", defaultClass); + blockStyle.setSelectedOption(dropDown, classNames, 'noUnknown', defaultClass); } }, - - buildStylingFieldset : function (doc, el, content, fieldsetClass, buttonId) { - var nodeName = el ? el.nodeName.toLowerCase() : "table"; - var table = (nodeName == "table"); - var fieldset = doc.createElement("fieldset"); - if (fieldsetClass) fieldset.className = fieldsetClass; - TableOperations.insertLegend(doc, fieldset, "CSS Style"); - TableOperations.insertSpace(doc, fieldset); - var ul = doc.createElement("ul"); - ul.className = "floating"; - fieldset.appendChild(ul); - var li = doc.createElement("li"); - ul.appendChild(li); - var select = TableOperations.buildSelectField(doc, li, "f_class", (table ? "Table class:" : "Class:"), "fr", "", (table ? "Table class selector" : "Class selector"), new Array("undefined"), new Array("none"), new RegExp("none", "i"), "", false); - this.setStyleOptions(doc, select, el, nodeName, (buttonId === "InsertTable") ? this.defaultClass : null); - if (el && table) { - var tbody = el.getElementsByTagName("tbody")[0]; - if (tbody) { - var li = doc.createElement("li"); - ul.appendChild(li); - var select = TableOperations.buildSelectField(doc, li, "f_class_tbody", "Table body class:", "fr", "", "Table body class selector", new Array("undefined"), new Array("none"), new RegExp("none", "i"), "", false); - this.setStyleOptions(doc, select, tbody, "tbody"); + /* + * This function builds the configuration object for the Language fieldset + * + * @param object element: the element being edited, if any + * + * @return object the fieldset configuration object + */ + buildLanguageFieldsetConfig: function (element) { + var itemsConfig = []; + var languageObject = this.getPluginInstance('Language'); + if (this.removedProperties.indexOf('language') == -1 && this.getButton('Language')) { + var languageStore = new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'} ], + data: this.getDropDownConfiguration('Language').options + }); + var selectedLanguage = !Ext.isEmpty(element) ? languageObject.getLanguageAttribute(element) : 'none'; + if (selectedLanguage !== 'none') { + languageStore.removeAt(0); + languageStore.insert(0, new languageStore.recordType({ + text: languageObject.localize('Remove language mark'), + value: 'none' + })); } - var thead = el.getElementsByTagName("thead")[0]; - if (thead) { - var li = doc.createElement("li"); - ul.appendChild(li); - var select = TableOperations.buildSelectField(doc, li, "f_class_thead", "Table header class:", "fr", "", "Table header class selector", new Array("undefined"), new Array("none"), new RegExp("none", "i"), "", false); - this.setStyleOptions(doc, select, thead, "thead"); - } - var tfoot = el.getElementsByTagName("tfoot")[0]; - if (tfoot) { - var li = doc.createElement("li"); - ul.appendChild(li); - var select = TableOperations.buildSelectField(doc, li, "f_class_tfoot", "Table footer class:", "fr", "", "Table footer class selector", new Array("undefined"), new Array("none"), new RegExp("none", "i"), "", false); - this.setStyleOptions(doc, select, tfoot, "tfoot"); - } + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize('Language'), + itemId: 'f_lang', + helpTitle: this.localize('Language'), + store: languageStore, + width: (this.properties && this.properties['language'] && this.properties['language'].width) ? this.properties['language'].width : 200, + value: selectedLanguage + }, this.configDefaults['combo'])); } - TableOperations.insertSpace(doc, fieldset); - content.appendChild(fieldset); + if (this.removedProperties.indexOf('direction') == -1 && (this.getButton('LeftToRight') || this.getButton('RightToLeft'))) { + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize('Text direction'), + itemId: 'f_dir', + helpTitle: this.localize('Text direction'), + store: new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}], + data: [ + [this.localize('Not set'), 'not set'], + [this.localize('RightToLeft'), 'rtl'], + [this.localize('LeftToRight'), 'ltr'] + ] + }), + width: (this.properties && this.properties['direction'] && this.properties['dirrection'].width) ? this.properties['direction'].width : 200, + value: !Ext.isEmpty(element) && element.dir ? element.dir : 'not set' + }, this.configDefaults['combo'])); + } + return { + xtype: 'fieldset', + title: this.localize('Language'), + items: itemsConfig + }; }, - - buildLanguageFieldset : function (doc, el, content, fieldsetClass) { - if (this.removedFieldsets.indexOf("language") == -1 && (this.removedProperties.indexOf("language") == -1 || this.removedProperties.indexOf("direction") == -1) && this.getPluginInstance("Language") && (this.isButtonInToolbar("Language") || this.isButtonInToolbar("LeftToRight") || this.isButtonInToolbar("RightToLeft"))) { - var languageObject = this.getPluginInstance("Language"); - var fieldset = doc.createElement("fieldset"); - if (fieldsetClass) { - fieldset.className = fieldsetClass; - } - TableOperations.insertLegend(doc, fieldset, "Language"); - var ul = doc.createElement("ul"); - fieldset.appendChild(ul); - if (this.removedProperties.indexOf("language") == -1 && this.isButtonInToolbar("Language")) { - var languageOptions = this.getDropDownConfiguration("Language").options; - var select, - selected = "", - options = new Array(), - values = new Array(); - for (var option in languageOptions) { - if (languageOptions.hasOwnProperty(option)) { - options.push(option); - values.push(languageOptions[option]); - } + /* + * This function builds the configuration object for the spacing fieldset + * + * @param object table: the table being edited, if any + * + * @return object the fieldset configuration object + */ + buildSpacingFieldsetConfig: function (table) { + return { + xtype: 'fieldset', + title: this.localize('Spacing and padding'), + defaultType: 'numberfield', + defaults: { + labelSeparator: '', + helpIcon: true + }, + items: [{ + fieldLabel: this.localize('Cell spacing:'), + itemId: 'f_spacing', + value: !Ext.isEmpty(table) ? table.cellSpacing : '', + width: 30, + minValue: 0, + helpTitle: this.localize('Space between adjacent cells') + },{ + fieldLabel: this.localize('Cell padding:'), + itemId: 'f_padding', + value: !Ext.isEmpty(table) ? table.cellPadding : '', + width: 30, + minValue: 0, + helpTitle: this.localize('Space between content and border in cell') + }] + }; + }, + /* + * This function builds the configuration object for the Layout fieldset + * + * @param object table: the element being edited, if any + * + * @return object the fieldset configuration object + */ + buildLayoutFieldsetConfig: function(element) { + var itemsConfig = []; + var nodeName = element ? element.nodeName.toLowerCase() : 'table'; + switch(nodeName) { + case 'table' : + var widthTitle = 'Table width'; + var heightTitle = 'Table height'; + break; + case 'tr' : + var widthTitle = 'Row width'; + var heightTitle = 'Row height'; + break; + case 'td' : + case 'th' : + var widthTitle = 'Cell width'; + var heightTitle = 'Cell height'; + } + if (this.removedProperties.indexOf('width') === -1) { + var widthUnitStore = new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}], + data: [ + [this.localize('percent'), '%'], + [this.localize('pixels'), 'px'], + [this.localize('em'), 'em'] + ] + }); + this.removeOptions(widthUnitStore, 'widthUnit'); + itemsConfig.push({ + fieldLabel: this.localize('Width:'), + labelSeparator: '', + itemId: 'f_st_width', + value: element ? this.getLength(element.style.width) : ((this.properties && this.properties.width && this.properties.width.defaultValue) ? this.properties.width.defaultValue : ''), + width: 30, + helpTitle: this.localize(widthTitle) + }); + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize('Width unit'), + itemId: 'f_st_widthUnit', + helpTitle: this.localize('Width unit'), + store: widthUnitStore, + width: (this.properties && this.properties['widthUnit'] && this.properties['widthUnit'].width) ? this.properties['widthUnit'].width : 60, + value: element ? (/%/.test(element.style.width) ? '%' : (/px/.test(element.style.width) ? 'px' : 'em')) : ((this.properties && this.properties.widthUnit &&this.properties.widthUnit.defaultValue) ? this.properties.widthUnit.defaultValue : '%') + }, this.configDefaults['combo'])); + } + if (this.removedProperties.indexOf('height') === -1) { + var heightUnitStore = new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}], + data: [ + [this.localize('percent'), '%'], + [this.localize('pixels'), 'px'], + [this.localize('em'), 'em'] + ] + }); + this.removeOptions(heightUnitStore, 'heightUnit'); + itemsConfig.push({ + fieldLabel: this.localize('Height:'), + labelSeparator: '', + itemId: 'f_st_height', + value: element ? this.getLength(element.style.height) : ((this.properties && this.properties.height && this.properties.height.defaultValue) ? this.properties.height.defaultValue : ''), + width: 30, + helpTitle: this.localize(heightTitle) + }); + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize('Height unit'), + itemId: 'f_st_heightUnit', + helpTitle: this.localize('Height unit'), + store: heightUnitStore, + width: (this.properties && this.properties['heightUnit'] && this.properties['heightUnit'].width) ? this.properties['heightUnit'].width : 60, + value: element ? (/%/.test(element.style.height) ? '%' : (/px/.test(element.style.height) ? 'px' : 'em')) : ((this.properties && this.properties.heightUnit &&this.properties.heightUnit.defaultValue) ? this.properties.heightUnit.defaultValue : '%') + }, this.configDefaults['combo'])); + } + if (nodeName == 'table' && this.removedProperties.indexOf('float') === -1) { + var floatStore = new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}], + data: [ + [this.localize('Not set'), 'not set'], + [this.localize('Left'), 'left'], + [this.localize('Right'), 'right'] + ] + }); + this.removeOptions(floatStore, 'float'); + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize('Float:'), + labelSeparator: '', + itemId: 'f_st_float', + helpTitle: this.localize('Specifies where the table should float'), + store: floatStore, + width: (this.properties && this.properties['float'] && this.properties['float'].width) ? this.properties['float'].width : 120, + value: element ? (Ext.get(element).hasClass(this.floatLeft) ? 'left' : (Ext.get(element).hasClass(this.floatRight) ? 'right' : 'not set')) : this.floatDefault + }, this.configDefaults['combo'])); + } + return { + xtype: 'fieldset', + title: this.localize('Layout'), + defaultType: 'numberfield', + defaults: { + helpIcon: true + }, + items: itemsConfig + }; + }, + /* + * This function builds the configuration object for the Layout fieldset + * + * @param object element: the element being edited, if any + * + * @return object the fieldset configuration object + */ + buildAlignmentFieldsetConfig: function (element) { + var itemsConfig = []; + // Text alignment + var selectedTextAlign = 'not set'; + var blockElements = this.getPluginInstance('BlockElements'); + if (element && blockElements) { + Ext.iterate(this.convertAlignment, function (value) { + if (Ext.get(element).hasClass(blockElements.useClass[this.convertAlignment[value]])) { + selectedTextAlign = value; + return false; } - selected = el ? languageObject.getLanguageAttribute(el) : "none"; - if (selected != "none") { - options[0] = languageObject.localize("Remove language mark"); + return true; + }, this); + } else { + selectedTextAlign = (element && element.style.textAlign) ? element.style.textAlign : 'not set'; + } + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize('Text alignment:'), + itemId: 'f_st_textAlign', + helpTitle: this.localize('Horizontal alignment of text within cell'), + store: new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}], + data: [ + [this.localize('Not set'), 'not set'], + [this.localize('Left'), 'left'], + [this.localize('Center'), 'center'], + [this.localize('Right'), 'right'], + [this.localize('Justify'), 'justify'] + ] + }), + width: (this.properties && this.properties['textAlign'] && this.properties['textAlign'].width) ? this.properties['textAlign'].width : 100, + value: selectedTextAlign + }, this.configDefaults['combo'])); + // Vertical alignment + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize('Vertical alignment:'), + itemId: 'f_st_vertAlign', + helpTitle: this.localize('Vertical alignment of content within cell'), + store: new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}], + data: [ + [this.localize('Not set'), 'not set'], + [this.localize('Top'), 'top'], + [this.localize('Middle'), 'middle'], + [this.localize('Bottom'), 'bottom'], + [this.localize('Baseline'), 'baseline'] + ] + }), + width: (this.properties && this.properties['verticalAlign'] && this.properties['verticalAlign'].width) ? this.properties['verticalAlign'].width : 100, + value: (element && element.style.verticalAlign) ? element.style.verticalAlign : 'not set' + }, this.configDefaults['combo'])); + return { + xtype: 'fieldset', + title: this.localize('Alignment'), + defaults: { + labelSeparator: '' + }, + items: itemsConfig + }; + }, + /* + * This function builds the configuration object for the Borders fieldset + * + * @param object element: the element being edited, if any + * + * @return object the fieldset configuration object + */ + buildBordersFieldsetConfig: function (element) { + var itemsConfig = []; + var nodeName = element ? element.nodeName.toLowerCase() : 'table'; + // Border style + var borderStyleStore = new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}], + data: [ + [this.localize('Not set'), 'not set'], + [this.localize('No border'), 'none'], + [this.localize('Dotted'), 'dotted'], + [this.localize('Dashed'), 'dashed'], + [this.localize('Solid'), 'solid'], + [this.localize('Double'), 'double'], + [this.localize('Groove'), 'groove'], + [this.localize('Ridge'), 'ridge'], + [this.localize('Inset'), 'inset'], + [this.localize('Outset'), 'outset'] + ] + }); + this.removeOptions(borderStyleStore, 'borderStyle'); + // Gecko reports "solid solid solid solid" for "border-style: solid". + // That is, "top right bottom left" -- we only consider the first value. + var selectedBorderStyle = element && element.style.borderStyle ? element.style.borderStyle : ((this.properties && this.properties.borderWidth) ? ((this.properties.borderStyle && this.properties.borderStyle.defaultValue) ? this.properties.borderStyle.defaultValue : 'solid') : 'not set'); + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize('Border style:'), + itemId: 'f_st_borderStyle', + helpTitle: this.localize('Border style'), + store: borderStyleStore, + width: (this.properties && this.properties.borderStyle && this.properties.borderStyle.width) ? this.properties.borderStyle.width : 150, + value: selectedBorderStyle, + listeners: { + change: { + fn: this.setBorderFieldsDisabled } - (selected.match(/([^\s]*)\s/)) && (selected = RegExp.$1); - var li = doc.createElement("li"); - ul.appendChild(li); - select = TableOperations.buildSelectField(doc, li, "f_lang", "Language:", "fr", "", "Language", options, values, new RegExp((selected ? selected : "none"), "i")); } - if (this.removedProperties.indexOf("direction") == -1 && (this.isButtonInToolbar("LeftToRight") || this.isButtonInToolbar("RightToLeft"))) { - var li = doc.createElement("li"); - ul.appendChild(li); - selected = el ? el.dir : ""; - (selected.match(/([^\s]*)\s/)) && (selected = RegExp.$1); - select = TableOperations.buildSelectField(doc, li, "f_dir", "Text direction:", "fr", "", "Text direction", ["Not set", "Right to left", "Left to right"], ["not set", "rtl", "ltr"], new RegExp((selected ? selected : "not set"), "i")); - } - content.appendChild(fieldset); + }, this.configDefaults['combo'])); + // Border width + itemsConfig.push({ + fieldLabel: this.localize('Border width:'), + itemId: 'f_st_borderWidth', + value: element ? this.getLength(element.style.borderWidth) : ((this.properties && this.properties.borderWidth && this.properties.borderWidth.defaultValue) ? this.properties.borderWidth.defaultValue : ''), + width: 30, + minValue: 0, + helpTitle: this.localize('Border width'), + helpText: this.localize('pixels'), + disabled: (selectedBorderStyle === 'none') + }); + // Border color + itemsConfig.push({ + xtype: 'colorpalettefield', + fieldLabel: this.localize('Color:'), + itemId: 'f_st_borderColor', + colorsConfiguration: this.editorConfiguration.colors, + value: HTMLArea.util.Color.colorToHex(element && element.style.borderColor ? element.style.borderColor : ((this.properties && this.properties.borderColor && this.properties.borderColor.defaultValue) ? this.properties.borderColor.defaultValue : '')).substr(1, 6), + helpTitle: this.localize('Border color'), + disabled: (selectedBorderStyle === 'none') + }); + if (nodeName === 'table') { + // Collapsed borders + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize('Collapsed borders'), + labelSeparator: ':', + itemId: 'f_st_borderCollapse', + helpTitle: this.localize('Collapsed borders'), + store: new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}], + data: [ + [this.localize('Not set'), 'not set'], + [this.localize('Collapsed borders'), 'collapse'], + [this.localize('Detached borders'), 'separate'] + ] + }), + width: (this.properties && this.properties.borderCollapse && this.properties.borderCollapse.width) ? this.properties.borderCollapse.width : 150, + value: element && element.style.borderCollapse ? element.style.borderCollapse : 'not set', + disabled: (selectedBorderStyle === 'none') + }, this.configDefaults['combo'])); + // Frame + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize('Frames:'), + itemId: 'f_frames', + helpTitle: this.localize('Specifies which sides should have a border'), + store: new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}], + data: [ + [this.localize('Not set'), 'not set'], + [this.localize('No sides'), 'void'], + [this.localize('The top side only'), 'above'], + [this.localize('The bottom side only'), 'below'], + [this.localize('The top and bottom sides only'), 'hsides'], + [this.localize('The right and left sides only'), 'vsides'], + [this.localize('The left-hand side only'), 'lhs'], + [this.localize('The right-hand side only'), 'rhs'], + [this.localize('All four sides'), 'box'] + ] + }), + width: (this.properties && this.properties.frame && this.properties.frame.width) ? this.properties.frame.width : 250, + value: (element && element.frame) ? element.frame : 'not set', + disabled: (selectedBorderStyle === 'none') + }, this.configDefaults['combo'])); + // Rules + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize('Rules:'), + itemId: 'f_rules', + helpTitle: this.localize('Specifies where rules should be displayed'), + store: new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}], + data: [ + [this.localize('Not set'), 'not set'], + [this.localize('No rules'), 'none'], + [this.localize('Rules will appear between rows only'), 'rows'], + [this.localize('Rules will appear between columns only'), 'cols'], + [this.localize('Rules will appear between all rows and columns'), 'all'] + ] + }), + width: (this.properties && this.properties.rules && this.properties.rules.width) ? this.properties.rules.width : 360, + value: (element && element.rules) ? element.rules : 'not set' + }, this.configDefaults['combo'])); } + return { + xtype: 'fieldset', + title: this.localize('Frame and borders'), + defaultType: 'numberfield', + defaults: { + labelSeparator: '', + helpIcon: true + }, + items: itemsConfig + }; }, - - buildCellTypeFieldset : function (doc, el, content, column, fieldsetClass) { - var fieldset = doc.createElement("fieldset"); - if (fieldsetClass) fieldset.className = fieldsetClass; - TableOperations.insertLegend(doc, fieldset, column ? "Type of cells" : "Cell Type and Scope"); - TableOperations.insertSpace(doc, fieldset); - var ul = doc.createElement("ul"); - fieldset.appendChild(ul); - var li = doc.createElement("li"); - ul.appendChild(li); + /* + * onChange handler: enable/disable other fields of the same fieldset + */ + setBorderFieldsDisabled: function (field, value) { + field.ownerCt.findBy(function (item) { + var itemId = item.getItemId(); + if (itemId == 'f_st_borderStyle' || itemId == 'f_rules') { + return false; + } else if (value === 'none') { + switch (item.getXType()) { + case 'numberfield': + item.setValue(0); + break; + case 'colorpalettefield': + item.setValue(''); + break; + default: + item.setValue('not set'); + break; + } + item.setDisabled(true); + } else { + item.setDisabled(false); + } + return true; + }); + }, + /* + * This function builds the configuration object for the Colors fieldset + * + * @param object element: the element being edited, if any + * + * @return object the fieldset configuration object + */ + buildColorsFieldsetConfig: function (element) { + var itemsConfig = []; + // Text color + itemsConfig.push({ + xtype: 'colorpalettefield', + fieldLabel: this.localize('FG Color:'), + itemId: 'f_st_color', + colorsConfiguration: this.editorConfiguration.colors, + value: HTMLArea.util.Color.colorToHex(element && element.style.color ? element.style.color : ((this.properties && this.properties.color && this.properties.color.defaultValue) ? this.properties.color.defaultValue : '')).substr(1, 6) + }); + // Background color + itemsConfig.push({ + xtype: 'colorpalettefield', + fieldLabel: this.localize('Background:'), + itemId: 'f_st_backgroundColor', + colorsConfiguration: this.editorConfiguration.colors, + value: HTMLArea.util.Color.colorToHex(element && element.style.backgroundColor ? element.style.backgroundColor : ((this.properties && this.properties.backgroundColor && this.properties.backgroundColor.defaultValue) ? this.properties.backgroundColor.defaultValue : '')).substr(1, 6) + }); + // Background image + itemsConfig.push({ + fieldLabel: this.localize('Image URL:'), + itemId: 'f_st_backgroundImage', + value: element && element.style.backgroundImage.match(/url\(\s*(.*?)\s*\)/) ? RegExp.$1 : '', + width: (this.properties && this.properties.backgroundImage && this.properties.backgroundImage.width) ? this.properties.backgroundImage.width : 300, + helpTitle: this.localize('URL of the background image'), + helpIcon: true + }); + return { + xtype: 'fieldset', + title: this.localize('Background and colors'), + defaultType: 'textfield', + defaults: { + labelSeparator: '' + }, + items: itemsConfig + }; + }, + /* + * This function builds the configuration object for the Cell Type fieldset + * + * @param object element: the element being edited, if any + * @param boolean column: true if the element is a column, false if the element is a cell + * + * @return object the fieldset configuration object + */ + buildCellTypeFieldsetConfig: function (element, column) { + var itemsConfig = []; if (column) { - var selectType = TableOperations.buildSelectField(doc, li, "f_cell_type", "Type of cells of the column", "fl", "", "Specifies the type of cells", ["Data cells", "Headers for rows", "Headers for row groups"], ["td", "throw", "throwgroup"], new RegExp(el.nodeName.toLowerCase()+el.scope.toLowerCase()+"$", "i")); + var data = [ + [this.localize('Data cells'), 'td'], + [this.localize('Headers for rows'), 'throw'], + [this.localize('Headers for row groups'), 'throwgroup'] + ]; } else { - var selectType = TableOperations.buildSelectField(doc, li, "f_cell_type", "Type of cell", "fr", "", "Specifies the type of cell", ["Normal", "Header for column", "Header for row", "Header for row group"], ["td", "thcol", "throw", "throwgroup"], new RegExp(el.nodeName.toLowerCase()+el.scope.toLowerCase()+"$", "i")); + var data = [ + [this.localize('Normal'), 'td'], + [this.localize('Header for column'), 'thcol'], + [this.localize('Header for row'), 'throw'], + [this.localize('Header for row group'), 'throwgroup'] + ]; } + // onChange handler: reset the CSS class dropdown when the cell type changes + // @param object cellTypeField: the combo object + // @param string value: the value of the cell type field + // @return void var self = this; - selectType.onchange = function() { self.setStyleOptions(doc, doc.getElementById("f_class"), el, this.value.substring(0,2)); }; - TableOperations.insertSpace(doc, fieldset); - content.appendChild(fieldset); - }, - - buildAlignmentFieldset : function (doc, el, content, fieldsetClass) { - var select; - var nodeName = el ? el.nodeName.toLowerCase() : "table"; - var fieldset = doc.createElement("fieldset"); - if (fieldsetClass) fieldset.className = fieldsetClass; - TableOperations.insertLegend(doc, fieldset, "Alignment"); - var options = ["Not set", "Left", "Center", "Right", "Justify"]; - var values = ["not set", "left", "center", "right", "justify"]; - var selected = ""; - if (el && this.editor.plugins.BlockElements) { - var blockElements = this.editor.plugins.BlockElements.instance; - for (var value in this.convertAlignment) { - if (this.convertAlignment.hasOwnProperty(value) && HTMLArea._hasClass(el, blockElements.useClass[this.convertAlignment[value]])) { - selected = value; - break; + function resetStyleOptions(cellTypeField, value) { + self.setStyleOptions(self.dialog.find('itemId', 'f_class'), element, value.substring(0,2)); + } + var selected = element.nodeName.toLowerCase() + element.scope.toLowerCase(); + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize(column ? 'Type of cells of the column' : 'Type of cell'), + itemId: 'f_cell_type', + helpTitle: this.localize(column ? 'Specifies the type of cells' : 'Specifies the type of cell'), + store: new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}], + data: data + }), + width: (this.properties && this.properties.cellType && this.properties.cellType.width) ? this.properties.cellType.width : 250, + value: (column && selected == 'thcol') ? 'td' : selected, + listeners: { + change: { + fn: resetStyleOptions, + scope: this } } - } else { - selected = el ? el.style.verticalAlign : ""; + }, this.configDefaults['combo'])); + return { + xtype: 'fieldset', + title: this.localize(column ? 'Type of cells' : 'Cell Type and Scope'), + defaults: { + labelSeparator: '', + helpIcon: true + }, + items: itemsConfig + }; + }, + /* + * This function builds the configuration object for the Row Group fieldset + * + * @param object element: the row being edited, if any + * + * @return object the fieldset configuration object + */ + buildRowGroupFieldsetConfig: function (element) { + var itemsConfig = []; + var current = element.parentNode.nodeName.toLowerCase(); + // onChange handler: show/hide cell conversion checkbox with appropriate label + // @param object field: the combo object + // @param object record: the selected record + // @return void + function displayCheckbox(field, record, index) { + var checkBox = field.ownerCt.getComponent('f_convertCells'); + var value = record.get('value'); + if (current !== value && (current === 'thead' || value === 'thead')) { + checkBox.label.dom.innerHTML = (value === 'thead') ? this.localize('Make cells header cells') : this.localize('Make cells data cells'); + checkBox.show(); + checkBox.label.show(); + checkBox.setValue(true); + } else { + checkBox.setValue(false); + checkBox.hide(); + checkBox.label.hide(); + } } - (selected.match(/([^\s]*)\s/)) && (selected = RegExp.$1); - var ul = doc.createElement("ul"); - fieldset.appendChild(ul); - var li = doc.createElement("li"); - ul.appendChild(li); - select = TableOperations.buildSelectField(doc, li, "f_st_textAlign", "Text alignment:", "fr", "", "Horizontal alignment of text within cell", options, values, new RegExp((selected ? selected : "not set"), "i")); - - var li = doc.createElement("li"); - ul.appendChild(li); - selected = el ? el.style.verticalAlign : ""; - (selected.match(/([^\s]*)\s/)) && (selected = RegExp.$1); - select = TableOperations.buildSelectField(doc, li, "f_st_vertAlign", "Vertical alignment:", "fr", "", "Vertical alignment of content within cell", ["Not set", "Top", "Middle", "Bottom", "Baseline"], ["not set", "top", "middle", "bottom", "baseline"], new RegExp((selected ? selected : "not set"), "i")); - content.appendChild(fieldset); - }, - - buildBordersFieldset : function (w, doc, editor, el, content, fieldsetClass) { - var nodeName = el ? el.nodeName.toLowerCase() : "table"; - var select; - var selected; - var borderFields = []; - function setBorderFieldsVisibility(value) { - for (var i = 0; i < borderFields.length; ++i) { - var borderFieldElement = borderFields[i]; - borderFieldElement.style.visibility = value ? "hidden" : "visible"; - if (!value && (borderFieldElement.nodeName.toLowerCase() == "input")) { - borderFieldElement.focus(); - borderFieldElement.select(); + itemsConfig.push(Ext.apply({ + xtype: 'combo', + fieldLabel: this.localize('Row group:'), + itemId: 'f_rowgroup', + helpTitle: this.localize('Table section'), + store: new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [ { name: 'text'}, { name: 'value'}], + data: [ + [this.localize('Table body'), 'tbody'], + [this.localize('Table header'), 'thead'], + [this.localize('Table footer'), 'tfoot'] + ] + }), + width: (this.properties && this.properties.rowGroup && this.properties.rowGroup.width) ? this.properties.rowGroup.width : 150, + value: current, + labelSeparator: '', + listeners: { + select: { + fn: displayCheckbox, + scope: this } } + }, this.configDefaults['combo'])); + // Cell conversion checkbox + itemsConfig.push({ + xtype: 'checkbox', + fieldLabel: this.localize('Make cells header cells'), + labelSeparator: ':', + itemId: 'f_convertCells', + helpTitle: this.localize('Make cells header cells'), + value: false, + hideMode: 'visibility', + hidden: true, + hideLabel: true + }); + return { + xtype: 'fieldset', + title: this.localize('Row group'), + defaults: { + helpIcon: true + }, + items: itemsConfig }; - var fieldset = doc.createElement("fieldset"); - fieldset.className = fieldsetClass; - TableOperations.insertLegend(doc, fieldset, "Frame and borders"); - TableOperations.insertSpace(doc, fieldset); - // Gecko reports "solid solid solid solid" for "border-style: solid". - // That is, "top right bottom left" -- we only consider the first value. - var f_st_borderWidth = el ? TableOperations.getLength(el.style.borderWidth) : ((this.properties && this.properties.borderWidth && this.properties.borderWidth.defaultValue) ? this.properties.borderWidth.defaultValue : ""); - selected = el ? el.style.borderStyle : ((this.properties && this.properties.borderWidth) ? ((this.properties.borderStyle && this.properties.borderStyle.defaultValue) ? this.properties.borderStyle.defaultValue : "solid") : ""); - (selected.match(/([^\s]*)\s/)) && (selected = RegExp.$1); - selectBorderStyle = TableOperations.buildSelectField(doc, fieldset, "f_st_borderStyle", "Border style:", "fr", "floating", "Border style", ["Not set", "No border", "Dotted", "Dashed", "Solid", "Double", "Groove", "Ridge", "Inset", "Outset"], ["not set", "none", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"], new RegExp((selected ? selected : "not set"), "i")); - selectBorderStyle.onchange = function() { setBorderFieldsVisibility(this.value == "none"); }; - this.removeOptions(selectBorderStyle, "borderStyle"); - TableOperations.buildInput(doc, fieldset, "f_st_borderWidth", "Border width:", "Border width", "pixels", "5", f_st_borderWidth, "fr", "floating", "postlabel", borderFields); - TableOperations.insertSpace(doc, fieldset, borderFields); - - if (nodeName == "table") { - TableOperations.buildColorField(w, doc, editor, fieldset, "", "Color:", "fr", "colorButton", (el ? el.style.borderColor : ""), "borderColor", borderFields); - var label = doc.createElement("label"); - label.className = "fl-borderCollapse"; - label.htmlFor = "f_st_borderCollapse"; - label.innerHTML = "Collapsed borders"; - fieldset.appendChild(label); - borderFields.push(label); - var input = doc.createElement("input"); - input.className = "checkbox"; - input.type = "checkbox"; - input.name = "f_st_borderCollapse"; - input.id = "f_st_borderCollapse"; - input.defaultChecked = el ? /collapse/i.test(el.style.borderCollapse) : false; - input.checked = input.defaultChecked; - fieldset.appendChild(input); - borderFields.push(input); - TableOperations.insertSpace(doc, fieldset, borderFields); - select = TableOperations.buildSelectField(doc, fieldset, "f_frames", "Frames:", "fr", "floating", "Specifies which sides should have a border", ["Not set", "No sides", "The top side only", "The bottom side only", "The top and bottom sides only", "The right and left sides only", "The left-hand side only", "The right-hand side only", "All four sides"], ["not set", "void", "above", "below", "hsides", "vsides", "lhs", "rhs", "box"], new RegExp(((el && el.frame) ? el.frame : "not set"), "i"), borderFields); - TableOperations.insertSpace(doc, fieldset, borderFields); - select = TableOperations.buildSelectField(doc, fieldset, "f_rules", "Rules:", "fr", "floating", "Specifies where rules should be displayed", ["Not set", "No rules", "Rules will appear between rows only", "Rules will appear between columns only", "Rules will appear between all rows and columns"], ["not set", "none", "rows", "cols", "all"], new RegExp(((el && el.rules) ? el.rules : "not set"), "i"), borderFields); - } else { - TableOperations.insertSpace(doc, fieldset, borderFields); - TableOperations.buildColorField(w, doc, editor, fieldset, "", "Color:", "fr", "colorButton", (el ? el.style.borderColor : ""), "borderColor", borderFields); - } - setBorderFieldsVisibility(selectBorderStyle.value == "none"); - TableOperations.insertSpace(doc, fieldset); - content.appendChild(fieldset); }, - - removeOptions : function(select, property) { + /* + * This function removes some items from a data store for the specified property + * + */ + removeOptions: function (store, property) { if (this.properties && this.properties[property] && this.properties[property].removeItems) { - for (var i = select.options.length; --i >= 0;) { - if (this.properties[property].removeItems.indexOf(select.options[i].value) != -1) { - if (select.options[i].value != select.value) { - select.options[i] = null; - } + var items = this.properties[property].removeItems.split(','); + var index = -1; + Ext.each(items, function (item) { + index = store.findExact('value', item.trim()); + if (index !== -1) { + store.removeAt(index); } - } + return true; + }); } }, - /* - * This function gets called by the main editor event handler when a key was pressed. + * This function gets called by the editor key map when a key was pressed. * It will process the enter key for IE and Opera when buttons.table.disableEnterParagraphs is set in the editor configuration + * + * @param string key: the key code + * @param object event: the Ext event object (keydown) + * + * @return boolean false, if the event was taken care of */ - onKeyPress : function (ev) { - if ((HTMLArea.is_ie || HTMLArea.is_opera) && ev.keyCode == 13 && !ev.shiftKey && this.disableEnterParagraphs) { - var selection = this.editor._getSelection(); - var range = this.editor._createRange(selection); - var parentElement = this.editor.getParentElement(selection, range); - while (parentElement && !HTMLArea.isBlockElement(parentElement)) { - parentElement = parentElement.parentNode; - } - if (/^(td|th)$/i.test(parentElement.nodeName)) { - if (HTMLArea.is_ie) { - range.pasteHTML("
"); + onKey: function (key, event) { + var selection = this.editor._getSelection(); + var range = this.editor._createRange(selection); + var parentElement = this.editor.getParentElement(selection, range); + while (parentElement && !HTMLArea.isBlockElement(parentElement)) { + parentElement = parentElement.parentNode; + } + if (/^(td|th)$/i.test(parentElement.nodeName)) { + if (Ext.isIE) { + range.pasteHTML('
'); + range.select(); + } else { + var brNode = this.editor._doc.createElement('br'); + this.editor.insertNodeAtSelection(brNode); + if (brNode.nextSibling) { + this.editor.selectNodeContents(brNode.nextSibling, true); } else { - var brNode = this.editor._doc.createElement("br"); - this.editor.insertNodeAtSelection(brNode); - this.editor.selectNode(brNode, false); + this.editor.selectNodeContents(brNode, false); } - return false; } + event.stopEvent(); + return false; } return true; } }); - -TableOperations.getLength = function(value) { - var len = parseInt(value); - if (isNaN(len)) len = ""; - return len; -}; - -// Returns an HTML element for a widget that allows color selection. That is, -// a button that contains the given color, if any, and when pressed will popup -// the sooner-or-later-to-be-rewritten select_color.html dialog allowing user -// to select some color. If a color is selected, an input field with the name -// "f_st_"+name will be updated with the color value in #123456 format. -TableOperations.createColorButton = function(w, doc, editor, color, name) { - if (!color) { - color = ""; - } else if (!/#/.test(color)) { - color = HTMLArea._colorToRgb(color); - } - - var df = doc.createElement("span"); - var field = doc.createElement("input"); - field.type = "hidden"; - df.appendChild(field); - field.name = "f_st_" + name; - field.id = "f_st_" + name; - field.value = color; - var button = doc.createElement("span"); - button.className = "buttonColor"; - df.appendChild(button); - var span = doc.createElement("span"); - span.className = "chooser"; - span.style.backgroundColor = color; - var space = doc.createTextNode("\xA0"); - span.appendChild(space); - button.appendChild(span); - button.onmouseover = function() { if (!this.disabled) this.className += " buttonColor-hilite"; }; - button.onmouseout = function() { if (!this.disabled) this.className = "buttonColor"; }; - span.onclick = function() { - if (this.parentNode.disabled) return false; - var colorPlugin = editor.plugins.TYPO3Color; - if (colorPlugin) { - colorPlugin.instance.dialogSelectColor("color", span, field, w); - } else { - colorPlugin = editor.plugins.DefaultColor; - if (colorPlugin) { - w.insertColor = function (color) { - if (color) { - span.style.backgroundColor = color; - field.value = color; - } - }; - colorPlugin.instance.onButtonPress(editor, "TableOperations"); - } - } - }; - var span2 = doc.createElement("span"); - span2.innerHTML = "×"; - span2.className = "nocolor"; - span2.title = "Unset color"; - button.appendChild(span2); - span2.onmouseover = function() { if (!this.parentNode.disabled) this.className += " nocolor-hilite"; }; - span2.onmouseout = function() { if (!this.parentNode.disabled) this.className = "nocolor"; }; - span2.onclick = function() { - span.style.backgroundColor = ""; - field.value = ""; - }; - return df; -}; -TableOperations.buildTitle = function(doc, content, title) { - var div = doc.createElement("div"); - div.className = "title"; - div.innerHTML = title; - content.appendChild(div); - doc.title = title; -}; -TableOperations.buildDescriptionFieldset = function(doc, el, content, fieldsetClass) { - var fieldset = doc.createElement("fieldset"); - if (fieldsetClass) fieldset.className = fieldsetClass; - TableOperations.insertLegend(doc, fieldset, "Description"); - TableOperations.insertSpace(doc, fieldset); - var f_caption = ""; - if (el) { - var capel = el.getElementsByTagName("caption")[0]; - if (capel) f_caption = capel.innerHTML; - } - TableOperations.buildInput(doc, fieldset, "f_caption", "Caption:", "Description of the nature of the table", "", "", f_caption, "fr", "value", ""); - TableOperations.insertSpace(doc, fieldset); - TableOperations.buildInput(doc, fieldset, "f_summary", "Summary:", "Summary of the table purpose and structure", "", "", (el ? el.summary : ""), "fr", "value", ""); - TableOperations.insertSpace(doc, fieldset); - content.appendChild(fieldset); -}; -TableOperations.buildRowGroupFieldset = function(w, doc, editor, el, content, fieldsetClass) { - var fieldset = doc.createElement("fieldset"); - if (fieldsetClass) fieldset.className = fieldsetClass; - TableOperations.insertLegend(doc, fieldset, "Row group"); - TableOperations.insertSpace(doc, fieldset); - TableOperations.insertSpace(doc, fieldset); - selected = el.parentNode.nodeName.toLowerCase(); - var selectScope = TableOperations.buildSelectField(doc, fieldset, "f_rowgroup", "Row group:", "fr", "floating", "Table section", ["Table body", "Table header", "Table footer"], ["tbody", "thead", "tfoot"], new RegExp((selected ? selected : "tbody"), "i")); - function displayCheckbox(current, value) { - if (current !== "thead" && value === "thead") { - label1.style.display = "inline"; - label2.style.display = "none"; - input.style.display = "inline"; - input.checked = true; - } else if (current === "thead" && value !== "thead") { - label1.style.display = "none"; - label2.style.display = "inline"; - input.style.display = "inline"; - input.checked = true; - } else { - label1.style.display = "none"; - label2.style.display = "none"; - input.style.display = "none"; - input.checked = false; - } - } - selectScope.onchange = function() { displayCheckbox(selected, this.value); }; - var label1 = doc.createElement("label"); - label1.className = "fl"; - label1.htmlFor = "f_convertCells"; - label1.innerHTML = "Make cells header cells"; - label1.style.display = "none"; - fieldset.appendChild(label1); - var label2 = doc.createElement("label"); - label2.className = "fl"; - label2.htmlFor = "f_convertCells"; - label2.innerHTML = "Make cells data cells"; - label2.style.display = "none"; - fieldset.appendChild(label2); - var input = doc.createElement("input"); - input.className = "checkbox"; - input.type = "checkbox"; - input.name = "f_convertCells"; - input.id = "f_convertCells"; - input.checked = false; - input.style.display = "none"; - fieldset.appendChild(input); - TableOperations.insertSpace(doc, fieldset); - content.appendChild(fieldset); -}; -TableOperations.buildSpacingFieldset = function(doc, el, content) { - var fieldset = doc.createElement("fieldset"); - TableOperations.insertLegend(doc, fieldset, "Spacing and padding"); - TableOperations.buildInput(doc, fieldset, "f_spacing", "Cell spacing:", "Space between adjacent cells", "pixels", "5", (el ? el.cellSpacing : ""), "fr", "", "postlabel"); - TableOperations.insertSpace(doc, fieldset); - TableOperations.buildInput(doc, fieldset, "f_padding", "Cell padding:", "Space between content and border in cell", "pixels", "5", (el ? el.cellPadding : ""), "fr", "", "postlabel"); - content.appendChild(fieldset); -}; -TableOperations.buildColorsFieldset = function(w, doc, editor, el, content) { - var fieldset = doc.createElement("fieldset"); - TableOperations.insertLegend(doc, fieldset, "Background and colors"); - var ul = doc.createElement("ul"); - fieldset.appendChild(ul); - var li = doc.createElement("li"); - ul.appendChild(li); - TableOperations.buildColorField(w, doc, editor, li, "", "FG Color:", "fr", "colorButtonNoFloat", (el ? el.style.color : ""), "color"); - var li = doc.createElement("li"); - ul.appendChild(li); - TableOperations.buildColorField(w, doc, editor, li, "", "Background:", "fr", "colorButtonNoFloat", (el ? el.style.backgroundColor : ""), "backgroundColor"); - var url; - if (el && el.style.backgroundImage.match(/url\(\s*(.*?)\s*\)/)) url = RegExp.$1; - TableOperations.buildInput(doc, li, "f_st_backgroundImage", "Image URL:", "URL of the background image", "", "", url, "", "shorter-value"); - content.appendChild(fieldset); -}; -TableOperations.insertLegend = function(doc, fieldset, legend) { - var legendNode = doc.createElement("legend"); - legendNode.innerHTML = legend; - fieldset.appendChild(legendNode); -}; -TableOperations.insertSpace = function(doc,fieldset,fields) { - var space = doc.createElement("div"); - space.className = "space"; - fieldset.appendChild(space); - if(fields) fields.push(space); -}; -TableOperations.buildInput = function(doc, fieldset,fieldName,fieldLabel,fieldTitle,postLabel,fieldSize,fieldValue,labelClass,inputClass,postClass,fields) { - var label; - // Field label - if(fieldLabel) { - label = doc.createElement("label"); - if(labelClass) label.className = labelClass; - label.innerHTML = fieldLabel; - label.htmlFor = fieldName; - fieldset.appendChild(label); - if(fields) fields.push(label); - } - // Input field - var input = doc.createElement("input"); - input.type = "text"; - input.id = fieldName; - input.name = fieldName; - if(inputClass) input.className = inputClass; - if(fieldTitle) input.title = fieldTitle; - if(fieldSize) input.size = fieldSize; - if(fieldValue) input.value = fieldValue; - fieldset.appendChild(input); - if(fields) fields.push(input); - // Field post label - if(postLabel) { - label = doc.createElement("span"); - if(postClass) label.className = postClass; - label.innerHTML = postLabel; - fieldset.appendChild(label); - if(fields) fields.push(label); - } - return input; -}; -TableOperations.buildSelectField = function(doc, fieldset,fieldName,fieldLabel,labelClass,selectClass,fieldTitle,options,values,selected,fields,translateOptions) { - if(typeof(translateOptions) == "undefined") var translateOptions = true; - // Field Label - if(fieldLabel) { - var label = doc.createElement("label"); - if(labelClass) label.className = labelClass; - label.innerHTML = fieldLabel; - label.htmlFor = fieldName; - fieldset.appendChild(label); - if(fields) fields.push(label); - } - // Text Alignment Select Box - var select = doc.createElement("select"); - if (selectClass) select.className = selectClass; - select.id = fieldName; - select.name = fieldName; - select.title= fieldTitle; - select.selectedIndex = 0; - var option; - for (var i = 0; i < options.length; ++i) { - option = doc.createElement("option"); - select.appendChild(option); - option.value = values[i]; - option.innerHTML = options[i]; - option.selected = selected.test(option.value); - } - if (select.options.length>1) select.disabled = false; - else select.disabled = true; - fieldset.appendChild(select); - if(fields) fields.push(select); - return select; -}; -TableOperations.buildColorField = function(w, doc, editor, fieldset,fieldName,fieldLabel,labelClass, buttonClass, fieldValue,fieldType,fields) { - // Field Label - if(fieldLabel) { - var label = doc.createElement("label"); - if(labelClass) label.className = labelClass; - label.innerHTML = fieldLabel; - fieldset.appendChild(label); - if(fields) fields.push(label); - } - var colorButton = TableOperations.createColorButton(w, doc, editor, fieldValue, fieldType); - colorButton.className = buttonClass; - fieldset.appendChild(colorButton); - if(fields) fields.push(colorButton); -}; Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TextIndicator/text-indicator.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/TextIndicator/text-indicator.js (révision 0) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TextIndicator/text-indicator.js (révision 0) @@ -0,0 +1,103 @@ +/*************************************************************** +* Copyright notice +* +* (c) 2010 Stanislas Rolland +* 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! +***************************************************************/ +/* + * TextIndicator Plugin for TYPO3 htmlArea RTE + * + * TYPO3 SVN ID: $Id: text-indicator.js 6539 2009-11-25 14:49:14Z stucki $ + */ +TextIndicator = HTMLArea.Plugin.extend({ + + constructor : function(editor, pluginName) { + this.base(editor, pluginName); + }, + + /* + * This function gets called by the class constructor + */ + configurePlugin : function (editor) { + /* + * Registering plugin "About" information + */ + var pluginInformation = { + version : "1.0", + developer : "Stanislas Rolland", + developerUrl : "http://www.sjbr.ca/", + copyrightOwner : "Stanislas Rolland", + sponsor : "SJBR", + sponsorUrl : "http://www.sjbr.ca/", + license : "GPL" + }; + this.registerPluginInformation(pluginInformation); + + /* + * Registering the indicator + */ + var buttonId = 'TextIndicator'; + var textConfiguration = { + id: buttonId, + cls: 'indicator', + text: 'A', + tooltip: this.localize(buttonId.toLowerCase()) + }; + this.registerText(textConfiguration); + return true; + }, + + /* + * This function gets called when the toolbar is updated + */ + onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) { + var editor = this.editor; + if (mode === 'wysiwyg' && editor.isEditable()) { + var doc = editor._doc; + try { + var style = { + backgroundColor: HTMLArea._makeColor(doc.queryCommandValue((HTMLArea.is_ie || HTMLArea.is_safari) ? 'BackColor' : 'HiliteColor')), + color: HTMLArea._makeColor(doc.queryCommandValue('ForeColor')), + fontFamily: doc.queryCommandValue('FontName'), + fontWeight: 'normal', + fontStyle: 'normal' + }; + // Mozilla + if (/transparent/i.test(style.backgroundColor)) { + style.backgroundColor = HTMLArea._makeColor(doc.queryCommandValue('BackColor')); + } + try { + style.fontWeight = doc.queryCommandState('Bold') ? 'bold' : 'normal'; + } catch(e) { + style.fontWeight = 'normal'; + } + try { + style.fontStyle = doc.queryCommandState('Italic') ? 'italic' : 'normal'; + } catch(e) { + style.fontStyle = 'normal'; + } + button.getEl().setStyle(style); + } catch (e) { } + } + } +}); Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/text-style.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/text-style.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/text-style.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2007-2009 Stanislas Rolland +* (c) 2007-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -112,15 +112,22 @@ /* * Registering the dropdown list */ - var buttonId = "TextStyle"; + var buttonId = 'TextStyle'; + var fieldLabel = this.pageTSconfiguration.fieldLabel; + if (Ext.isEmpty(fieldLabel) && this.isButtonInToolbar('I[text_style]')) { + fieldLabel = this.localize('text_style'); + } var dropDownConfiguration = { - id : buttonId, - tooltip : this.localize(buttonId + "-Tooltip"), - textMode : false, - options : {"":""}, - action : "onChange", - refresh : "generate", - context : null + id: buttonId, + tooltip: this.localize(buttonId + '-Tooltip'), + fieldLabel: fieldLabel, + width: this.pageTSconfiguration.width ? this.pageTSconfiguration.width : 'auto', + listWidth: this.pageTSconfiguration.listWidth ? this.pageTSconfiguration.listWidth : 250, + maxHeight: this.pageTSconfiguration.maxHeight ? this.pageTSconfiguration.maxHeight : 300, + options: [[this.localize('No style'), 'none']], + action: 'onChange', + storeFields: [ { name: 'text'}, { name: 'value'}, { name: 'style'} ], + tpl: '
{text}
' }; this.registerDropDown(dropDownConfiguration); @@ -145,15 +152,14 @@ /* * 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; + onChange : function (editor, combo, record, index) { + var className = combo.getValue(); var classNames = null; var fullNodeSelected = false; this.editor.focusEditor(); var selection = this.editor._getSelection(); - var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null; + var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null; var range = this.editor._createRange(selection); var parent = this.editor.getParentElement(); var selectionEmpty = this.editor._selectionEmpty(selection); @@ -213,7 +219,9 @@ * This function gets called when the plugin is generated * Get the classes configuration and initiate the parsing of the style sheets */ - onGenerate : function() { + onGenerate: function() { + // Monitor editor changing mode + this.editor.iframe.mon(this.editor, 'modeChange', this.onModeChange, this); this.generate(this.editor, "TextStyle"); }, @@ -226,11 +234,7 @@ this.updateToolbar(dropDownId); } else { if (this.cssTimeout) { - if (editor._iframe.contentWindow) { - editor._iframe.contentWindow.clearTimeout(this.cssTimeout); - } else { - window.clearTimeout(this.cssTimeout); - } + window.clearTimeout(this.cssTimeout); this.cssTimeout = null; } if (this.classesUrl && (typeof(HTMLArea.classesLabels) === "undefined")) { @@ -243,8 +247,7 @@ 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.cssTimeout = this.buildCssArray.defer(200, this, [editor, dropDownId]); this.cssParseCount++; } else { this.cssTimeout = null; @@ -393,9 +396,9 @@ /* * This function gets called when the toolbar is being updated */ - onUpdateToolbar : function() { - if (this.getEditorMode() === "wysiwyg" && this.editor.isEditable()) { - this.generate(this.editor, "TextStyle"); + onUpdateToolbar: function(button, mode, selectionEmpty, ancestors) { + if (mode === "wysiwyg" && this.editor.isEditable()) { + this.generate(this.editor, button.itemId); } }, @@ -407,7 +410,7 @@ if (this.getEditorMode() === "wysiwyg" && this.editor.isEditable()) { var tagName = false, classNames = Array(), fullNodeSelected = false; var selection = editor._getSelection(); - var statusBarSelection = editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null; + var statusBarSelection = editor.statusBar ? editor.statusBar.getSelection() : null; var range = editor._createRange(selection); var parent = editor.getParentElement(selection); var ancestors = editor.getAllAncestors(); @@ -446,122 +449,144 @@ if (!disabled && !tagName) { tagName = "span"; } - this.updateValue(dropDownId, tagName, classNames, selectionEmpty, fullNodeSelected, disabled); + } else { + var dropDown = this.getButton(dropDownId); + if (dropDown) { + dropDown.setDisabled(!dropDown.textMode); + } } }, + /* + * This function reinitializes the options of the dropdown + */ + initializeDropDown : function (dropDown) { + var store = dropDown.getStore(); + store.removeAll(true); + store.insert(0, new store.recordType({ + text: this.localize('No style'), + value: 'none' + })); + dropDown.setValue('none'); + }, + + /* + * This function sets the selected option of the dropDown box + */ + setSelectedOption : function (dropDown, classNames, noUnknown, defaultClass) { + var store = dropDown.getStore(); + var index = store.findExact('value', classNames[classNames.length-1]); + if (index != -1) { + dropDown.setValue(classNames[classNames.length-1]); + if (!defaultClass) { + store.getAt(0).set('text', this.localize('Remove style')); + } + } + if (index == -1 && !noUnknown) { + store.add(new store.recordType({ + text: this.localize('Unknown style'), + value: classNames[classNames.length-1] + })); + index = store.getCount()-1; + dropDown.setValue(classNames[classNames.length-1]); + if (!defaultClass) { + store.getAt(0).set('text', this.localize('Remove style')); + } + } + store.each(function (option) { + if (("," + classNames.join(",") + ",").indexOf("," + option.get('value') + ",") != -1 && store.indexOf(option) != index) { + store.removeAt(store.indexOf(option)); + } + return true; + }); + }, + 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") { - var cssArrayAll = this.cssArray.all; - if (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses) { - var allowedClasses = this.tags[tagName].allowedClasses; - for (var cssClass in cssArrayAll) { - if (cssArrayAll.hasOwnProperty(cssClass) && allowedClasses.test(cssClass)) { - cssArray[cssClass] = cssArrayAll[cssClass]; + var dropDown = this.getButton(dropDownId); + if (dropDown) { + var store = dropDown.getStore(); + var cssArray = new Array(); + this.initializeDropDown(dropDown); + if (this.REInlineTags.test(tagName)) { + // Get classes allowed for all tags + if (typeof(this.cssArray["all"]) !== "undefined") { + var cssArrayAll = this.cssArray.all; + if (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses) { + var allowedClasses = this.tags[tagName].allowedClasses; + for (var cssClass in cssArrayAll) { + if (cssArrayAll.hasOwnProperty(cssClass) && allowedClasses.test(cssClass)) { + cssArray[cssClass] = cssArrayAll[cssClass]; + } } - } - } else { - for (var cssClass in cssArrayAll) { - if (cssArrayAll.hasOwnProperty(cssClass)) { - cssArray[cssClass] = cssArrayAll[cssClass]; + } else { + for (var cssClass in cssArrayAll) { + if (cssArrayAll.hasOwnProperty(cssClass)) { + cssArray[cssClass] = cssArrayAll[cssClass]; + } } } } - } - // Merge classes allowed for tagName and sort the array - if (typeof(this.cssArray[tagName]) !== "undefined") { - var cssArrayTagName = this.cssArray[tagName]; - if (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses) { - var allowedClasses = this.tags[tagName].allowedClasses; - for (var cssClass in cssArrayTagName) { - if (cssArrayTagName.hasOwnProperty(cssClass) && allowedClasses.test(cssClass)) { - cssArray[cssClass] = cssArrayTagName[cssClass]; + // Merge classes allowed for tagName and sort the array + if (typeof(this.cssArray[tagName]) !== "undefined") { + var cssArrayTagName = this.cssArray[tagName]; + if (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses) { + var allowedClasses = this.tags[tagName].allowedClasses; + for (var cssClass in cssArrayTagName) { + if (cssArrayTagName.hasOwnProperty(cssClass) && allowedClasses.test(cssClass)) { + cssArray[cssClass] = cssArrayTagName[cssClass]; + } } + } else { + for (var cssClass in cssArrayTagName) { + if (cssArrayTagName.hasOwnProperty(cssClass)) { + cssArray[cssClass] = cssArrayTagName[cssClass]; + } + } } - } else { - for (var cssClass in cssArrayTagName) { - if (cssArrayTagName.hasOwnProperty(cssClass)) { - cssArray[cssClass] = cssArrayTagName[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; } - 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]); + if (cssArray.hasOwnProperty(cssClass) && cssArray[cssClass]) { + if (cssClass == 'none') { + store.getAt(0).set('text', cssArray[cssClass]); + } else { + store.add(new store.recordType({ + text: cssArray[cssClass], + value: cssClass, + style: (!this.editor.config.disablePCexamples && HTMLArea.classesValues && HTMLArea.classesValues[cssClass] && !HTMLArea.classesNoShow[cssClass]) ? HTMLArea.classesValues[cssClass] : null + })); } } } - } - - 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 (classNames.length && (selectionEmpty || fullNodeSelected)) { + this.setSelectedOption(dropDown, classNames); } - 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; - } - } - } } + dropDown.setDisabled(!(store.getCount()>1) || disabled); } - 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) { + onModeChange: function(mode) { if (mode === "wysiwyg" && this.editor.isEditable()) { this.generate(this.editor, "TextStyle"); } Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Color/typo3color.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Color/typo3color.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Color/typo3color.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2004-2009 Stanislas Rolland +* (c) 2004-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -64,12 +64,11 @@ this.allowedAttributes.push("className"); } } - /* * Registering plugin "About" information */ var pluginInformation = { - version : "3.0", + version : "4.0", developer : "Stanislas Rolland", developerUrl : "http://www.sjbr.ca/", copyrightOwner : "Stanislas Rolland", @@ -78,7 +77,6 @@ license : "GPL" }; this.registerPluginInformation(pluginInformation); - /* * Registering the buttons */ @@ -95,26 +93,33 @@ }; this.registerButton(buttonConfiguration); } - return true; }, - /* * The list of buttons added by this plugin */ - buttonList : [ - ["ForeColor", "textcolor"], - ["HiliteColor", "bgcolor"] + buttonList: [ + ['ForeColor', 'textcolor'], + ['HiliteColor', 'bgcolor'] ], - /* * Conversion object: button name to corresponding style property name */ - styleProperty : { - ForeColor : "color", - HiliteColor : "backgroundColor" + styleProperty: { + ForeColor : 'color', + HiliteColor : 'backgroundColor' }, - + colors: [ + '000000', '222222', '444444', '666666', '999999', 'BBBBBB', 'DDDDDD', 'FFFFFF', + '660000', '663300', '996633', '003300', '003399', '000066', '330066', '660066', + '990000', '993300', 'CC9900', '006600', '0033FF', '000099', '660099', '990066', + 'CC0000', 'CC3300', 'FFCC00', '009900', '0066FF', '0000CC', '663399', 'CC0099', + 'FF0000', 'FF3300', 'FFFF00', '00CC00', '0099FF', '0000FF', '9900CC', 'FF0099', + 'CC3333', 'FF6600', 'FFFF33', '00FF00', '00CCFF', '3366FF', '9933FF', 'FF00FF', + 'FF6666', 'FF6633', 'FFFF66', '66FF66', '00FFFF', '3399FF', '9966FF', 'FF66FF', + 'FF9999', 'FF9966', 'FFFF99', '99FF99', '99FFFF', '66CCFF', '9999FF', 'FF99FF', + 'FFCCCC', 'FFCC99', 'FFFFCC', 'CCFFCC', 'CCFFFF', '99CCFF', 'CCCCFF', 'FFCCFF' + ], /* * This function gets called when the button was pressed. * @@ -124,275 +129,258 @@ * * @return boolean false if action is completed */ - onButtonPress : function (editor, id, target) { + onButtonPress: function (editor, id, target) { // Could be a button or its hotkey var buttonId = this.translateHotKey(id); buttonId = buttonId ? buttonId : id; - this.dialogSelectColor(buttonId,"",""); + var element = this.editor.getParentElement(); + this.openDialogue( + buttonId + '_title', + { + element: element, + buttonId: buttonId + }, + this.getWindowDimensions({ width: 350}, buttonId), + this.buildItemsConfig(element, buttonId), + this.setColor + ); }, - - dialogSelectColor : function (buttonId, element, field, dialogOpener) { - var dimensions = { - width : 440, - height : 300 - }; - var arguments = { - title : buttonId + "_title", - buttonId : buttonId, - element : element, - field : field - }; - // buttonId's "color" and "tag" are not registered but used to interface with the Table Operations and QuickTag plugins - switch (buttonId) { - case "ForeColor" : - case "HiliteColor" : - var selectColorWithButtonInitFunctRef = this.makeFunctionReference("selectColorWithButtonInit"); - arguments.initialize = selectColorWithButtonInitFunctRef; - this.dialog = this.openDialog(buttonId, "", "setColor", arguments, dimensions, "yes"); - break; - case "color" : - var selectColorCodeInitFunctRef = this.makeFunctionReference("selectColorCodeInit"); - arguments.initialize = selectColorCodeInitFunctRef; - this.dialog = this.openDialog(buttonId, "", "setColor", arguments, dimensions, "yes", dialogOpener); - break; - case "tag" : - var selectColorCodeInitFunctRef = this.makeFunctionReference("selectColorCodeInit"); - arguments.initialize = selectColorCodeInitFunctRef; - arguments.title = "color_title"; - this.dialog = this.openDialog(buttonId, "", "setColorInTag", arguments, dimensions, "yes", dialogOpener); - } - }, - /* - * Initialize the forecolor and the hilitecolor select color dialogues + * Build the window items config */ - selectColorWithButtonInit : function(dialog) { - var editor = dialog.editor; - var doc = editor._doc; - var buttonId = dialog.arguments.buttonId; - var initialValue; - var parentElement = editor.getParentElement(); - initialValue = HTMLArea._colorToRgb(parentElement.style[this.styleProperty[buttonId]]); - dialog.content.innerHTML = this.renderPopupSelectColor(buttonId, dialog, dialog.arguments.title, initialValue); - var colorTable = dialog.document.getElementById("colorTable"); - colorTable.onclick = function(e) { - dialog.callFormInputHandler(); - return false; - }; - var colorForm = dialog.document.getElementById("HA-color-select-form"); - colorForm.onsubmit = function (e) { - dialog.callFormInputHandler(); - return false; - }; - var colorUnset = dialog.document.getElementById("colorUnset"); - colorUnset.onclick = function(e) { - dialog.document.getElementById(buttonId).value=""; - dialog.callFormInputHandler(); - return false; - }; - dialog.document.getElementById(buttonId+"Current").style.backgroundColor = initialValue; - dialog.addButtons("ok", "cancel"); - }, - - /* - * Set the color and close the ForeColor and the HiliteColor select color dialogues - */ - setColor : function(dialog, params) { - var editor = this.editor, element; - switch (dialog.arguments.buttonId) { - case "ForeColor": - case "HiliteColor": - var selection = editor._getSelection(); - var statusBarSelection = editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null; - var range = editor._createRange(selection); - if (editor._selectionEmpty(selection)) { - element = editor.getParentElement(selection, range); - // Set the color in the style attribute - this.processStyle(dialog, params, element, dialog.arguments.field); - // Remove the span tag if it has no more attribute - if ((element.nodeName.toLowerCase() === "span") && !HTMLArea.hasAllowedAttributes(element, this.allowedAttributes)) { - editor.removeMarkup(element); + buildItemsConfig: function (element, buttonId) { + var itemsConfig = []; + var paletteItems = []; + // Standard colors palette (boxed) + if (!this.disableColorPicker) { + paletteItems.push({ + xtype: 'container', + items: { + xtype: 'colorpalette', + itemId: 'color-palette', + colors: this.colors, + cls: 'color-palette', + value: (element && element.style[this.styleProperty[buttonId]]) ? HTMLArea.util.Color.colorToHex(element.style[this.styleProperty[buttonId]]).substr(1, 6) : '', + allowReselect: true, + listeners: { + select: { + fn: this.onSelect, + scope: this + } } - } else if (statusBarSelection) { - element = statusBarSelection; - // Set the color in the style attribute - this.processStyle(dialog, params, element, dialog.arguments.field); - // Remove the span tag if it has no more attribute - if ((element.nodeName.toLowerCase() === "span") && !HTMLArea.hasAllowedAttributes(element, this.allowedAttributes)) { - editor.removeMarkup(element); + } + }); + } + // Custom colors palette (boxed) + if (this.colorsConfiguration) { + paletteItems.push({ + xtype: 'container', + items: { + xtype: 'colorpalette', + itemId: 'custom-colors', + cls: 'htmlarea-custom-colors', + colors: this.colorsConfiguration, + value: (element && element.style[this.styleProperty[buttonId]]) ? HTMLArea.util.Color.colorToHex(element.style[this.styleProperty[buttonId]]).substr(1, 6) : '', + tpl: new Ext.XTemplate( + ' {0}' + ), + allowReselect: true, + listeners: { + select: { + fn: this.onSelect, + scope: this + } } - } else if (editor.endPointsInSameBlock()) { - element = editor._doc.createElement("span"); - // Set the color in the style attribute - this.processStyle(dialog, params, element, dialog.arguments.field); - editor.wrapWithInlineElement(element, selection, range); - if (HTMLArea.is_gecko) { - range.detach(); - } } - break; - case "color": - default: - element = dialog.arguments.element; - // Set the color in the style attribute - this.processStyle(dialog, params, element, dialog.arguments.field); - break; + }); } - dialog.close(); + itemsConfig.push({ + xtype: 'container', + layout: 'hbox', + items: paletteItems + }); + itemsConfig.push({ + xtype: 'displayfield', + itemId: 'show-color', + cls: 'show-color', + width: 60, + height: 22, + helpTitle: this.localize(buttonId) + }); + itemsConfig.push({ + itemId: 'color', + cls: 'color', + width: 60, + minValue: 0, + value: (element && element.style[this.styleProperty[buttonId]]) ? HTMLArea.util.Color.colorToHex(element.style[this.styleProperty[buttonId]]).substr(1, 6) : '', + enableKeyEvents: true, + fieldLabel: this.localize(buttonId), + helpTitle: this.localize(buttonId), + listeners: { + change: { + fn: this.onChange, + scope: this + }, + afterrender: { + fn: this.onAfterRender, + scope: this + } + } + }); + return { + xtype: 'fieldset', + title: this.localize('color_title'), + defaultType: 'textfield', + labelWidth: 175, + defaults: { + helpIcon: false + }, + items: itemsConfig + }; }, - /* - * Initialize the case=color select color dialogue - * This case is used by the Table Operations and QuickTag plugins + * On select handler: set the value of the color field, display the new color and update the other palette */ - selectColorCodeInit : function(dialog) { - var buttonId = dialog.arguments.buttonId; - var field = dialog.arguments.field; - dialog.content.innerHTML = this.renderPopupSelectColor(buttonId, dialog, this.localize(dialog.arguments.title), (field.value ? field.value : "")); - var colorTable = dialog.document.getElementById("colorTable"); - colorTable.onclick = function(e) { - if(!e) var e = dialog.dialogWindow.event; - var target = e.target ? e.target : e.srcElement; - if (target.nodeType == 3) target = target.parentNode; - dialog.document.getElementById(buttonId).value = target.bgColor; - dialog.callFormInputHandler(); - return false; - }; - var colorUnset = dialog.document.getElementById("colorUnset"); - colorUnset.onclick = function(e) { - dialog.document.getElementById(buttonId).value = ""; - dialog.callFormInputHandler(); - return false; - }; - var colorForm = dialog.document.getElementById("HA-color-select-form"); - colorForm.onsubmit = function(e) { - dialog.callFormInputHandler(); - return false; - }; - if (buttonId === "color") { - dialog.document.getElementById(buttonId+"Current").style.backgroundColor = field.value; - } else if (buttonId === "tag"){ - dialog.document.getElementById(buttonId+"Current").style.backgroundColor = ""; + onSelect: function (palette, color) { + this.dialog.find('itemId', 'color')[0].setValue(color); + this.showColor(color); + if (palette.getItemId() == 'color-palette') { + var customPalette = this.dialog.find('itemId', 'custom-colors')[0]; + if (customPalette) { + customPalette.deSelect(); + } + } else { + var standardPalette = this.dialog.find('itemId', 'color-palette')[0]; + if (standardPalette) { + standardPalette.deSelect(); + } } - dialog.addButtons("ok", "cancel"); }, - /* - * Sets the color - */ - setColorInTag : function(dialog, params) { - dialog.arguments.field.insertColor(params.tag); - dialog.close(); + * Display the selected color + */ + showColor: function (color) { + if (color) { + this.dialog.find('itemId', 'show-color')[0].el.setStyle('backgroundColor', '#' + color); + } }, - /* - * Applies the style found in "params" to the given element - */ - processStyle : function (dialog, params, element, field) { - if (element) { - for (var i in params) { - var val = params[i]; - if (val && val.charAt(0) != "#") { - val = "#" + val; - } - switch (i) { - case "ForeColor": - case "HiliteColor": - element.style[this.styleProperty[i]] = val; - break; - case "color": - element.style.backgroundColor = val; - field.value = val; - break; - } + * On change handler: display the new color and select it in the palettes, if it exists + */ + onChange: function (field, value) { + if (value) { + var color = value.toUpperCase(); + this.showColor(color); + var standardPalette = this.dialog.find('itemId', 'color-palette')[0]; + if (standardPalette) { + standardPalette.select(color); } + var customPalette = this.dialog.find('itemId', 'custom-colors')[0]; + if (customPalette) { + customPalette.select(color); + } } }, - - /** - * Making color selector table + /* + * On after render handler: display the color */ - renderPopupSelectColor : function (sID,dialog,title,initialValue) { - var editor = this.editor; - var cfgColors = this.colorsConfiguration; - var colorDef; - var szID = sID + "Current"; - var sz; - var cPick = new Array("00","33","66","99","CC","FF"); - var iColors = cPick.length; - var szColor = ""; - var szColorId = ""; - - sz = '
' + title + '
'; - sz += '
'; - sz += '
'; - var onMouseOut = ' onMouseout="document.getElementById(\'' + szID + '\').style.backgroundColor=\'\'; document.getElementById(\'' + sID + '\').value=\'\';"'; - var onMouseOver = ' onMouseover="if(' + HTMLArea.is_ie + '){ if (event.srcElement.bgColor) { document.getElementById(\'' + szID + '\').style.backgroundColor = event.srcElement.bgColor; document.getElementById(\'' + sID + '\').value = event.srcElement.bgColor;} } else { if (event.target.bgColor) { document.getElementById(\'' + szID + '\').style.backgroundColor=event.target.bgColor; document.getElementById(\'' + sID + '\').value=event.target.bgColor;} };" '; - // Making colorPicker - if (!this.disableColorPicker) { - for ( var r = 0; r < iColors; r++) { - sz+=''; - for (var g = iColors-1; g >= 0; g--) { - for (var b=iColors-1;b>=0;b--) { - szColor = cPick[r]+cPick[g]+cPick[b]; - sz+=''; - } + onAfterRender: function (field) { + if (!Ext.isEmpty(field.getValue())) { + this.showColor(field.getValue()); + } + }, + /* + * Open the dialogue window + * + * @param string title: the window title + * @param object arguments: some arguments for the handler + * @param integer dimensions: the opening width of the window + * @param object tabItems: the configuration of the tabbed panel + * @param function handler: handler when the OK button if clicked + * + * @return void + */ + openDialogue: function (title, arguments, dimensions, items, handler) { + if (this.dialog) { + this.dialog.close(); + } + this.dialog = new Ext.Window({ + title: this.localize(title), + arguments: arguments, + cls: 'htmlarea-window', + border: false, + width: dimensions.width, + height: 'auto', + iconCls: arguments.buttonId, + listeners: { + close: { + fn: this.onClose, + scope: this } - sz+=''; + }, + items: { + xtype: 'container', + layout: 'form', + defaults: { + labelWidth: 150 + }, + items: items + }, + buttons: [ + this.buildButtonConfig('Cancel', this.onCancel), + this.buildButtonConfig('OK', handler) + ] + }); + this.show(); + }, + /* + * Set the color and close the dialogue + */ + setColor: function(button, event) { + this.restoreSelection(); + var buttonId = this.dialog.arguments.buttonId; + var color = '#' + this.dialog.find('itemId', 'color')[0].getValue(); + var selection = this.editor._getSelection(); + var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null; + var range = this.editor._createRange(selection); + if (this.editor._selectionEmpty(selection)) { + var element = this.editor.getParentElement(selection, range); + // Set the color in the style attribute + element.style[this.styleProperty[buttonId]] = color; + // Remove the span tag if it has no more attribute + if ((element.nodeName.toLowerCase() === 'span') && !HTMLArea.hasAllowedAttributes(element, this.allowedAttributes)) { + this.editor.removeMarkup(element); } - } - - // Making specific color selector: - if (cfgColors) { - var iCfgColors = cfgColors.length; - if (iCfgColors && !this.disableColorPicker) { - sz += ''; + } else if (statusBarSelection) { + var element = statusBarSelection; + // Set the color in the style attribute + element.style[this.styleProperty[buttonId]] = color; + // Remove the span tag if it has no more attribute + if ((element.nodeName.toLowerCase() === 'span') && !HTMLArea.hasAllowedAttributes(element, this.allowedAttributes)) { + this.editor.removeMarkup(element); } - onMouseOverTitle = ' onMouseover="if(' + HTMLArea.is_ie + '){ if (document.getElementById(event.srcElement.id+\'Value\')) { document.getElementById(\'' + szID + '\').style.backgroundColor = document.getElementById(event.srcElement.id+\'Value\').bgColor; document.getElementById(\'' + sID + '\').value = document.getElementById(event.srcElement.id+\'Value\').bgColor;} } else { if (document.getElementById(event.target.id+\'Value\')) { document.getElementById(\'' + szID + '\').style.backgroundColor=document.getElementById(event.target.id+\'Value\').bgColor; document.getElementById(\'' + sID + '\').value=document.getElementById(event.target.id+\'Value\').bgColor;} };" '; - for (var theColor = 0; theColor < iCfgColors; theColor++) { - colorDef = cfgColors[theColor]; - szColor = colorDef[1]; - sz += ''; - sz += ''; - sz += ''; - sz += ''; + } else if (this.editor.endPointsInSameBlock()) { + var element = this.editor._doc.createElement('span'); + // Set the color in the style attribute + element.style[this.styleProperty[buttonId]] = color; + this.editor.wrapWithInlineElement(element, selection, range); + if (HTMLArea.is_gecko) { + range.detach(); } } - sz += '
 
 '+colorDef[0]+'
'; - sz += '
'; - sz += ''; - sz += '
'; - sz += '  '; - sz += ' '; - sz += '
'; - return sz; + this.close(); + event.stopEvent(); }, - /* * This function gets called when the toolbar is updated */ - onUpdateToolbar : function () { - var editor = this.editor; - if (this.getEditorMode() === "wysiwyg" && editor.isEditable()) { - var buttonId; - var statusBarSelection = editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null; - var parentElement = statusBarSelection ? statusBarSelection : editor.getParentElement(); - var enabled = editor.endPointsInSameBlock() && !(editor._selectionEmpty(editor._getSelection()) && parentElement.nodeName.toLowerCase() == "body"); - for (var i = 0, n = this.buttonList.length; i < n; ++i) { - buttonId = this.buttonList[i][0]; - var obj = editor._toolbarObjects[buttonId]; - if ((typeof(obj) !== "undefined")) { - obj.state("active", parentElement.style[this.styleProperty[buttonId]]); - obj.state("enabled", enabled); - } - } + onUpdateToolbar: function (button, mode, selectionEmpty, ancestors, endPointsInSameBlock) { + if (mode === 'wysiwyg' && this.editor.isEditable()) { + var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null, + parentElement = statusBarSelection ? statusBarSelection : this.editor.getParentElement(), + disabled = !endPointsInSameBlock || (selectionEmpty && /^body$/i.test(parentElement.nodeName)); + button.setInactive(!parentElement.style[this.styleProperty[button.itemId]]); + button.setDisabled(disabled); } } }); - Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3HtmlParser/typo3html-parser.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3HtmlParser/typo3html-parser.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3HtmlParser/typo3html-parser.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2005-2009 Stanislas Rolland +* (c) 2005-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -64,7 +64,8 @@ id : buttonId, tooltip : this.localize(buttonId + "-Tooltip"), action : "onButtonPress", - hide : true + hide : true, + hideInContextMenu: true }; this.registerButton(buttonConfiguration); }, @@ -84,61 +85,45 @@ this.clean(); return false; }, - - onGenerate : function () { - var doc = this.editor._doc; - // Function reference used on paste with older versions of Mozilla/Firefox in which onPaste is not fired - this.cleanLaterFunctRef = this.makeFunctionReference("clean"); - HTMLArea._addEvents((HTMLArea.is_ie ? doc.body : doc), ["paste","dragdrop","drop"], TYPO3HtmlParser.wordCleanHandler, true); + /* + * This function gets called when the editor is generated + */ + onGenerate: function () { + var documentElement = Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement); + this.editor.iframe.mon(documentElement, 'paste', this.wordCleanHandler, this); + this.editor.iframe.mon(documentElement, 'dragdrop', this.wordCleanHandler, this); + this.editor.iframe.mon(documentElement, 'drop', this.wordCleanHandler, this); }, - clean : function() { + clean: function() { var editor = this.editor; - if (HTMLArea.is_safari) { + if (Ext.isWebKit) { editor.cleanAppleStyleSpans(editor._doc.body); } var bookmark = editor.getBookmark(editor._createRange(editor._getSelection())); var content = { editorNo : this.editorNumber, - content : this.getPluginInstance("EditorMode").getInnerHTML() + content : editor.getInnerHTML() }; // Server-based synchronous pasted content cleaning this.postData( this.parseHtmlModulePath, content, function(response) { - editor.getPluginInstance("EditorMode").setHTML(response); + editor.setHTML(response); editor.selectRange(editor.moveToBookmark(bookmark)); }, false ); + }, + /* + * Handler for paste, dragdrop and drop events + */ + wordCleanHandler: function (event) { + // If we dropped an image dragged from the TYPO3 Image plugin, let's close the dialog window + if (typeof(HTMLArea.Dialog) != "undefined" && HTMLArea.Dialog.TYPO3Image) { + HTMLArea.Dialog.TYPO3Image.close(); + } else { + this.clean.defer(250, this); + } } }); - -/* - * Closure avoidance for IE - */ -TYPO3HtmlParser.cleanLater = function (editorNumber) { - var editor = RTEarea[editorNumber].editor; - editor.getPluginInstance("TYPO3HtmlParser").clean(); -}; - -/* - * Handler for paste, dragdrop and drop events - */ -TYPO3HtmlParser.wordCleanHandler = function (ev) { - if (!ev) var ev = window.event; - var target = ev.target ? ev.target : ev.srcElement; - var owner = target.ownerDocument ? target.ownerDocument : target; - if (HTMLArea.is_ie) { // IE5.5 does not report any ownerDocument - while (owner.parentElement) { owner = owner.parentElement; } - } - var editor = RTEarea[owner._editorNo].editor; - - // If we dropped an image dragged from the TYPO3 Image plugin, let's close the dialog window - if (typeof(HTMLArea.Dialog) != "undefined" && HTMLArea.Dialog.TYPO3Image) { - HTMLArea.Dialog.TYPO3Image.close(); - } else { - window.setTimeout("TYPO3HtmlParser.cleanLater(\'" + editor._editorNumber + "\');", 250); - } -}; - Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Link/typo3link.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Link/typo3link.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Link/typo3link.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2005-2009 Stanislas Rolland +* (c) 2005-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -48,7 +48,7 @@ * Registering plugin "About" information */ var pluginInformation = { - version : "1.1", + version : "1.2", developer : "Stanislas Rolland", developerUrl : "http://www.sjbr.ca/", copyrightOwner : "Stanislas Rolland", @@ -84,7 +84,7 @@ * The list of buttons added by this plugin */ buttonList : [ - ["CreateLink", "a,img", true, true], + ["CreateLink", "a,img", false, true], ["UnLink", "a", false, false] ], @@ -371,6 +371,14 @@ if (i.nodeType == 1 || i.nodeType == 11) this.cleanAllLinks(i, range, keepLinks); } } + }, + /* + * This function gets called when the toolbar is updated + */ + onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) { + if (mode === 'wysiwyg' && this.editor.isEditable() && button.itemId === 'CreateLink') { + button.setDisabled(selectionEmpty && !button.isInContext(mode, selectionEmpty, ancestors)); + } } }); Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/UndoRedo/undo-redo.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/UndoRedo/undo-redo.js (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/UndoRedo/undo-redo.js (copie de travail) @@ -1,7 +1,7 @@ /*************************************************************** * Copyright notice * -* (c) 2008-2009 Stanislas Rolland +* (c) 2008-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -50,13 +50,12 @@ this.undoSteps = 25; // The time interval at which undo samples are taken: 1/2 sec. this.undoTimeout = 500; - this.undoTimer; /* * Registering plugin "About" information */ var pluginInformation = { - version : "1.0", + version : "1.1", developer : "Stanislas Rolland", developerUrl : "http://www.sjbr.ca", copyrightOwner : "Stanislas Rolland", @@ -77,8 +76,8 @@ id : buttonId, tooltip : this.localize(buttonId.toLowerCase()), action : "onButtonPress", - context : button[1], - hotKey : (this.editorConfiguration.buttons[buttonId.toLowerCase()]?this.editorConfiguration.buttons[buttonId.toLowerCase()].hotKey:button[2]) + hotKey : (this.editorConfiguration.buttons[buttonId.toLowerCase()]?this.editorConfiguration.buttons[buttonId.toLowerCase()].hotKey:button[2]), + noAutoUpdate : true }; this.registerButton(buttonConfiguration); } @@ -97,25 +96,18 @@ /* * This function gets called when the editor is generated */ - onGenerate : function () { + onGenerate: function () { // Start undo snapshots if (this.customUndo) { - var takeSnapshotFunctRef = this.makeFunctionReference("takeSnapshot"); - this.undoTimer = window.setInterval(takeSnapshotFunctRef, this.undoTimeout); + Ext.TaskMgr.start({ + run: this.takeSnapshot, + scope: this, + interval: this.undoTimeout + }); } }, /* - * This function gets called when the editor is closing - */ - onClose : function () { - // Clear snapshot interval - window.clearInterval(this.undoTimer); - // Release undo/redo snapshots - this.undoQueue = null; - }, - - /* * Take a snapshot of the current contents for undo */ takeSnapshot : function () { @@ -132,7 +124,7 @@ newSnapshot = true; } // Get the html text - var text = this.getPluginInstance("EditorMode").getInnerHTML(); + var text = this.editor.getInnerHTML(); if (newSnapshot) { // If previous slot contains the same text, a new one should not be used @@ -182,7 +174,7 @@ } // Get the bookmarked html text and remove the bookmark if (bookmark) { - bookmarkedText = this.getPluginInstance("EditorMode").getInnerHTML(); + bookmarkedText = this.editor.getInnerHTML(); var range = this.editor.moveToBookmark(bookmark); // Restore Firefox selection if (HTMLArea.is_gecko && !HTMLArea.is_opera && !HTMLArea.is_safari) { @@ -192,7 +184,7 @@ } } return { - text : this.getPluginInstance("EditorMode").getInnerHTML(), + text : this.editor.getInnerHTML(), bookmark : bookmark, bookmarkedText : bookmarkedText }; @@ -231,55 +223,63 @@ setContent : function (undoPosition) { var bookmark = this.undoQueue[undoPosition].bookmark; if (bookmark) { - this.getPluginInstance("EditorMode").setHTML(this.undoQueue[undoPosition].bookmarkedText); - this.editor.focusEditor(); + this.editor.setHTML(this.undoQueue[undoPosition].bookmarkedText); + this.editor.focus(); this.editor.selectRange(this.editor.moveToBookmark(bookmark)); this.editor.scrollToCaret(); } else { - this.getPluginInstance("EditorMode").setHTML(this.undoQueue[undoPosition].text); + this.editor.setHTML(this.undoQueue[undoPosition].text); } }, /* * This function gets called when the toolbar is updated */ - onUpdateToolbar : function () { - this.updateButtonsState(); - }, - - /* - * Update the state of the undo/redo buttons - */ - updateButtonsState : function () { - if (this.editor.getMode() == "wysiwyg" && this.editor.isEditable()) { + onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) { + if (mode == 'wysiwyg' && this.editor.isEditable()) { if (this.customUndo) { - if (this.isButtonInToolbar("Undo")) { - this.editor._toolbarObjects.Undo.state("enabled", this.undoPosition > 0); + switch (button.itemId) { + case 'Undo': + button.setDisabled(this.undoPosition == 0); + break; + case 'Redo': + button.setDisabled(this.undoPosition >= this.undoQueue.length-1); + break; } - if (this.isButtonInToolbar("Redo")) { - this.editor._toolbarObjects.Redo.state("enabled", this.undoPosition < this.undoQueue.length-1); - } } else { try { - if (this.isButtonInToolbar("Undo")) { - this.editor._toolbarObjects.Undo.state("enabled", this.editor._doc.queryCommandEnabled("Undo")); - } - if (this.isButtonInToolbar("Redo")) { - this.editor._toolbarObjects.Redo.state("enabled", this.editor._doc.queryCommandEnabled("Redo")); - } + button.setDisabled(!this.editor._doc.queryCommandEnabled(button.itemId)); } catch (e) { - if (this.isButtonInToolbar("Undo")) { - this.editor._toolbarObjects.Undo.state("enabled", false); - } - if (this.isButtonInToolbar("Redo")) { - this.editor._toolbarObjects.Redo.state("enabled", false); - } + button.setDisabled(true); } } + } else { + button.setDisabled(!button.textMode); } }, /* + * Update the state of the undo/redo buttons + */ + updateButtonsState: function () { + var mode = this.getEditorMode(), + selectionEmpty = true, + ancestors = null; + if (mode === 'wysiwyg') { + selectionEmpty = this.editor._selectionEmpty(this.editor._getSelection()); + ancestors = this.editor.getAllAncestors(); + } + var button = this.getButton('Undo'); + if (button) { + this.onUpdateToolbar(button, mode, selectionEmpty, ancestors) + } + var button = this.getButton('Redo'); + if (button) { + this.onUpdateToolbar(button, mode, selectionEmpty, ancestors) + } + }, + + /* * This function gets called when the button was pressed. * * @param object editor: the editor instance @@ -291,7 +291,7 @@ // Could be a button or its hotkey var buttonId = this.translateHotKey(id); buttonId = buttonId ? buttonId : id; - if (this.isButtonInToolbar(buttonId) && !this.editor._toolbarObjects[buttonId].disabled) { + if (this.getButton(buttonId) && !this.getButton(buttonId).disabled) { if (this.customUndo) { this[buttonId.toLowerCase()](); } else { Index: typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea-edited-content.css =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea-edited-content.css (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea-edited-content.css (copie de travail) @@ -5,6 +5,7 @@ margin:0; padding:3px; background-color:#ffffff; + border-width:0; } /* Selectors for the Table Operations plugin */ @@ -16,7 +17,7 @@ /* Make language marks visible */ body.htmlarea-show-language-marks *[lang] { - background: url("images/language-marker.gif") left bottom no-repeat; padding-left: 14px; text-decoration: underline; + background: url("images/language-marker.gif") left top no-repeat; padding-left: 14px; text-decoration: underline; } /* Selectors for the Abbreviation plugin */ Index: typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea.css =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea.css (révision 6908) +++ typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea.css (copie de travail) @@ -1,100 +1,103 @@ /* Selectors for the htmlArea RTE editor */ .htmlarea { background-color:#fff; - margin:0;padding:0; + margin:0 2px 0 0;padding:0; } -.resizable { - background-color:transparent; - padding-right:7px; - padding-bottom:6px; - background-image: url("images/resize.gif"); - background-position: bottom right; - background-repeat: no-repeat; -} .pleasewait { - position:relative;top:0px;text-align:left; - font-size:8pt; + position:relative; margin-top:30px; + padding: 20px 0 20px 50px; + font-size: 11px !important; + text-align:left; + background: url('images/loading.gif') no-repeat 10px center; + vertical-align: middle; + color: #7F8083; } .editorWrap { margin:0;padding:0; } -/* Selectors for the editor toolbar */ -.htmlarea div.toolbar { - background-color:#e4e0db;cursor:default; - width:100%; - border:1px solid #e4e0db;border-bottom:1px solid #000;margin:0;padding:0px 0px 2px 0px; +.editorWrap textarea { + border: 1px solid #A2AAB8; + border-style:solid; + border-color:#A2AAB8; + border-width:0px 1px 1px 1px; + padding:0px 1px; + margin:0; } -.htmlarea .toolbar ul { - background-color:transparent; - list-style-type:none;list-style-image:none; - border-style:none;margin:0;padding:0; +.editorWrap .resizable { + background-image: url("images/resize.gif"); + background-position: bottom right; + background-repeat: no-repeat; } -.htmlarea .toolbar ul.tb-line { - clear:both; +.editorWrap div.resizable { + padding-right: 7px; + padding-bottom: 5px; } -.htmlarea .toolbar ul.tb-group { - clear:none;float:left; +/* Selectors for the editor toolbar */ +.htmlarea .toolbar { + background-color:#E4E0DB;cursor:default; + border:1px solid #E4E0DB; + border-bottom:0px; + margin:0; + padding:2px 0px; + font-family: Verdana, Helvetica, Geneva, Arial, sans-serif; } -.htmlarea .toolbar ul li { +.htmlarea .toolbar .tb-group { + clear:none; float:left; - background-color:transparent; - font:11px Tahoma,Verdana,sans-serif; - border-style:none;padding:0; + margin:1px 2px 0px 0px; + padding:0; } -.htmlarea .toolbar ul.tb-line li { - margin:1px 0px 1px 0px; -} -.htmlarea .toolbar ul.free-float li, .htmlarea .toolbar ul.tb-group li { - height:22px; +.htmlarea .toolbar .x-form-item { + float: left; margin:0; } -.htmlarea .toolbar label { - float:left; +.htmlarea .toolbar .x-form-item-label { vertical-align:middle; - height:22px; - background-color:#e4e0db; + background-color:transparent; + border-style:none; margin:0;padding:3px 3px 0px 3px; } -.htmlarea .toolbar button { - vertical-align:top; - background-color:#e4e0db;background-position:1px 1px;background-repeat:no-repeat;color:ButtonText; - border:1px solid #e4e0db;margin:0;padding:1px; +.htmlarea .toolbar .button { + background-color:transparent;color:ButtonText;background-position:10px 0px;background-repeat:no-repeat; width:22px;height:22px; + border-style:solid;border-color:#EFEFF4;border-width:1px; + margin:0 0 1px 0;padding:0; + float:left; } -.htmlarea .toolbar button div.buttonImgContainer { - position:relative;top:0;left:0; - width:18px;height:18px;overflow:hidden; +.htmlarea .toolbar .x-btn-mc, .htmlarea .toolbar .x-btn-ml, .htmlarea .toolbar .x-btn-mr, .htmlarea .toolbar .x-btn-tc, .htmlarea .toolbar .x-btn-tl, .htmlarea .toolbar .x-btn-tr, .htmlarea .toolbar .x-btn-bl, .htmlarea .toolbar .x-btn-bc, .htmlarea .toolbar .x-btn-br { + background-color:transparent;background-image:none; + border-style:none; margin:0;padding:0; } -.htmlarea .toolbar .BiDiOverride {background-image:url("images/InlineElements/bidioverride.gif");} -.htmlarea .toolbar .Big {background-image:url("images/InlineElements/big.gif");} -.htmlarea .toolbar .Bold {background-image:url("images/InlineElements/bold.gif");} -.htmlarea .toolbar .Citation {background-image:url("images/InlineElements/citation.gif");} -.htmlarea .toolbar .Code {background-image:url("images/InlineElements/code.gif");} -.htmlarea .toolbar .Definition {background-image:url("images/InlineElements/definition.gif");} -.htmlarea .toolbar .DeletedText {background-image:url("images/InlineElements/deletedtext.gif");} -.htmlarea .toolbar .Emphasis {background-image:url("images/InlineElements/emphasis.gif");} -.htmlarea .toolbar .InsertedText {background-image:url("images/InlineElements/insertedtext.gif");} -.htmlarea .toolbar .Italic {background-image:url("images/InlineElements/italic.gif");} -.htmlarea .toolbar .Keyboard {background-image:url("images/InlineElements/keyboard.gif");} -.htmlarea .toolbar .MonoSpaced {background-image:url("images/InlineElements/monospaced.gif");} -.htmlarea .toolbar .Quotation {background-image:url("images/InlineElements/quotation.gif");} -.htmlarea .toolbar .Sample {background-image:url("images/InlineElements/sample.gif");} -.htmlarea .toolbar .Small {background-image:url("images/InlineElements/small.gif");} -.htmlarea .toolbar .Span {background-image:url("images/InlineElements/span.gif");} -.htmlarea .toolbar .StrikeThrough {background-image:url("images/InlineElements/strikethrough.gif");} -.htmlarea .toolbar .Strong {background-image:url("images/InlineElements/strong.gif");} -.htmlarea .toolbar .Subscript {background-image:url("images/InlineElements/subscript.gif");} -.htmlarea .toolbar .Superscript {background-image:url("images/InlineElements/superscript.gif");} -.htmlarea .toolbar .Underline {background-image:url("images/InlineElements/underline.gif");} -.htmlarea .toolbar .Variable {background-image:url("images/InlineElements/variable.gif");} -.htmlarea .toolbar .LeftToRight {background-image:url("images/ed_left_to_right.gif");} -.htmlarea .toolbar .RightToLeft {background-image:url("images/ed_right_to_left.gif");} -.htmlarea .toolbar .ShowLanguageMarks {background-image:url("images/show-language-marks.gif");} -.htmlarea .toolbar .Indent {background-image:url("images/BlockElements/indent.gif");} -.htmlarea .toolbar .Outdent {background-image:url("images/BlockElements/outdent.gif");} -.htmlarea .toolbar .Blockquote {background-image:url("images/BlockElements/blockquote.gif");} +.htmlarea .toolbar .BiDiOverride, .htmlarea-context-menu .BiDiOverride {background-image:url("images/InlineElements/bidioverride.gif");} +.htmlarea .toolbar .Big, .htmlarea-context-menu .Big {background-image:url("images/InlineElements/big.gif");} +.htmlarea .toolbar .Bold, .htmlarea-context-menu .Bold {background-image:url("images/InlineElements/bold.gif");} +.htmlarea .toolbar .Citation, .htmlarea-context-menu .Citation {background-image:url("images/InlineElements/citation.gif");} +.htmlarea .toolbar .Code, .htmlarea-context-menu .Code {background-image:url("images/InlineElements/code.gif");} +.htmlarea .toolbar .Definition, .htmlarea-context-menu .Definition {background-image:url("images/InlineElements/definition.gif");} +.htmlarea .toolbar .DeletedText, .htmlarea-context-menu .DeletedText {background-image:url("images/InlineElements/deletedtext.gif");} +.htmlarea .toolbar .Emphasis, .htmlarea-context-menu .Emphasis {background-image:url("images/InlineElements/emphasis.gif");} +.htmlarea .toolbar .InsertedText, .htmlarea-context-menu .InsertedText {background-image:url("images/InlineElements/insertedtext.gif");} +.htmlarea .toolbar .Italic, .htmlarea-context-menu .Italic {background-image:url("images/InlineElements/italic.gif");} +.htmlarea .toolbar .Keyboard, .htmlarea-context-menu .Keyboard {background-image:url("images/InlineElements/keyboard.gif");} +.htmlarea .toolbar .MonoSpaced, .htmlarea-context-menu .MonoSpaced {background-image:url("images/InlineElements/monospaced.gif");} +.htmlarea .toolbar .Quotation, .htmlarea-context-menu .Quotation {background-image:url("images/InlineElements/quotation.gif");} +.htmlarea .toolbar .Sample, .htmlarea-context-menu .Sample {background-image:url("images/InlineElements/sample.gif");} +.htmlarea .toolbar .Small, .htmlarea-context-menu .Small {background-image:url("images/InlineElements/small.gif");} +.htmlarea .toolbar .Span, .htmlarea-context-menu .Span {background-image:url("images/InlineElements/span.gif");} +.htmlarea .toolbar .StrikeThrough, .htmlarea-context-menu .StrikeThrough {background-image:url("images/InlineElements/strikethrough.gif");} +.htmlarea .toolbar .Strong, .htmlarea-context-menu .Strong {background-image:url("images/InlineElements/strong.gif");} +.htmlarea .toolbar .Subscript, .htmlarea-context-menu .Subscript {background-image:url("images/InlineElements/subscript.gif");} +.htmlarea .toolbar .Superscript, .htmlarea-context-menu .Superscript {background-image:url("images/InlineElements/superscript.gif");} +.htmlarea .toolbar .Underline, .htmlarea-context-menu .Underline {background-image:url("images/InlineElements/underline.gif");} +.htmlarea .toolbar .Variable, .htmlarea-context-menu .Variable {background-image:url("images/InlineElements/variable.gif");} +.htmlarea .toolbar .LeftToRight, .htmlarea-context-menu .LeftToRight {background-image:url("images/ed_left_to_right.gif");} +.htmlarea .toolbar .RightToLeft, .htmlarea-context-menu .RightToLeft {background-image:url("images/ed_right_to_left.gif");} +.htmlarea .toolbar .ShowLanguageMarks, .htmlarea-context-menu .ShowLanguageMarks {background-image:url("images/show-language-marks.gif");} +.htmlarea .toolbar .Indent, .htmlarea-context-menu .Indent {background-image:url("images/BlockElements/indent.gif");} +.htmlarea .toolbar .Outdent, .htmlarea-context-menu .Outdent {background-image:url("images/BlockElements/outdent.gif");} +.htmlarea .toolbar .Blockquote, .htmlarea-context-menu .Blockquote {background-image:url("images/BlockElements/blockquote.gif");} .htmlarea .toolbar .InsertParagraphBefore, .htmlarea-context-menu .InsertParagraphBefore {background-image:url("images/BlockElements/insertParagraphBefore.gif");} .htmlarea .toolbar .InsertParagraphAfter, .htmlarea-context-menu .InsertParagraphAfter {background-image:url("images/BlockElements/insertParagraphAfter.gif");} .htmlarea .toolbar .JustifyLeft, .htmlarea-context-menu .JustifyLeft {background-image:url("images/BlockElements/justifyLeft.gif");} @@ -103,136 +106,172 @@ .htmlarea .toolbar .JustifyFull, .htmlarea-context-menu .JustifyFull {background-image:url("images/BlockElements/justifyFull.gif");} .htmlarea .toolbar .DefinitionList, .htmlarea-context-menu .DefinitionList {background-image:url("images/definitionList.gif");} .htmlarea .toolbar .DefinitionItem, .htmlarea-context-menu .DefinitionItem {background-image:url("images/definitionItem.gif");} -.htmlarea .toolbar .InsertOrderedList {background-image:url("images/ed_list_num.gif");} -.htmlarea .toolbar .InsertUnorderedList {background-image:url("images/ed_list_bullet.gif");} -.htmlarea .toolbar .ForeColor {background-image:url("images/ed_color_fg.gif");} -.htmlarea .toolbar .HiliteColor {background-image:url("images/ed_color_bg.gif");} -.htmlarea .toolbar .InsertSmiley {background-image:url("images/InsertSmiley/ed_smiley.gif");} -.htmlarea .toolbar .InsertCharacter {background-image:url("images/CharacterMap/ed_charmap.gif");} -.htmlarea .toolbar .InsertHorizontalRule {background-image:url("images/ed_hr.gif");} -.htmlarea .toolbar .CreateLink, .htmlarea-context-menu .CreateLink {background-image:url("images/ed_link.gif");} +.htmlarea .toolbar .InsertOrderedList, .htmlarea-context-menu .InsertOrderedList {background-image:url("images/ed_list_num.gif");} +.htmlarea .toolbar .InsertUnorderedList, .htmlarea-context-menu .InsertUnorderedList {background-image:url("images/ed_list_bullet.gif");} +.htmlarea .toolbar .InsertHorizontalRule, .htmlarea-context-menu .InsertHorizontalRule {background-image:url("images/BlockElements/insertHorizontalRule.gif");} +.htmlarea .toolbar .ForeColor, .htmlarea-context-menu .ForeColor, .htmlarea-window .ForeColor {background-image:url("images/ed_color_fg.gif");} +.htmlarea .toolbar .HiliteColor, .htmlarea-context-menu .HiliteColor, .htmlarea-window .HiliteColor {background-image:url("images/ed_color_bg.gif");} +.htmlarea .toolbar .InsertSmiley, .htmlarea-context-menu .InsertSmiley, .htmlarea-window .InsertSmiley {background-image:url("images/InsertSmiley/ed_smiley.gif");} +.htmlarea .toolbar .InsertCharacter, .htmlarea-context-menu .InsertCharacter, .htmlarea-window .InsertCharacter {background-image:url("images/CharacterMap/ed_charmap.gif");} +.htmlarea .toolbar .CreateLink, .htmlarea-context-menu .CreateLink, .htmlarea-window .CreateLink {background-image:url("images/ed_link.gif");} .htmlarea .toolbar .UnLink, .htmlarea-context-menu .UnLink {background-image:url("images/ed_unlink.gif");} -.htmlarea .toolbar .InsertImage, .htmlarea-context-menu .InsertImage {background-image:url("images/ed_image.gif");} -.htmlarea .toolbar .InsertTable {background-image:url("images/insert_table.gif");} -.htmlarea .toolbar .UserElements {background-image:url("images/UserElements/ed_user.gif");} -.htmlarea .toolbar .FindReplace {background-image:url("images/FindReplace/ed_find.gif");} -.htmlarea .toolbar .SpellCheck { background-image:url("images/SpellChecker/spell-check.gif"); } -.htmlarea .toolbar .InsertTag { background-image:url("images/QuickTag/ed_quicktag.gif"); } -.htmlarea .toolbar .Acronym { background-image:url("images/Acronym/ed_acronym.gif"); } -.htmlarea .toolbar .RemoveFormat { background-image:url("images/RemoveFormat/ed_clean.gif"); } +.htmlarea .toolbar .InsertImage, .htmlarea-context-menu .InsertImage, .htmlarea-window .InsertImage {background-image:url("images/ed_image.gif");} +.htmlarea .toolbar .InsertTable, .htmlarea-context-menu .InsertTable, .htmlarea-window .InsertTable {background-image:url("images/insert_table.gif");} +.htmlarea .toolbar .UserElements, .htmlarea-context-menu .UserElements, .htmlarea-window .UserElements {background-image:url("images/UserElements/ed_user.gif");} +.htmlarea .toolbar .FindReplace, .htmlarea-context-menu .FindReplace, .htmlarea-window .FindReplace {background-image:url("images/FindReplace/ed_find.gif");} +.htmlarea .toolbar .SpellCheck, .htmlarea-context-menu .SpellCheck, .htmlarea-window .SpellCheck { background-image:url("images/SpellChecker/spell-check.gif"); } +.htmlarea .toolbar .InsertTag, .htmlarea-context-menu .InsertTag, .htmlarea-window .InsertTag { background-image:url("images/QuickTag/ed_quicktag.gif"); } +.htmlarea .toolbar .Acronym, .htmlarea-context-menu .Acronym, .htmlarea-window .Acronym { background-image:url("images/Acronym/ed_acronym.gif"); } +.htmlarea .toolbar .RemoveFormat, .htmlarea-context-menu .RemoveFormat, .htmlarea-window .RemoveFormat { background-image:url("images/RemoveFormat/ed_clean.gif"); } .htmlarea .toolbar .SplitBlock {background-image:url("images/ed_splitblock.gif"); } .htmlarea .toolbar .TextMode { background-image:url("images/ed_html.gif"); } -.htmlarea .toolbar .Copy, .htmlarea-context-menu .Copy { background-image:url("images/ed_copy.gif");} -.htmlarea .toolbar .Cut, .htmlarea-context-menu .Cut { background-image:url("images/ed_cut.gif");} +.htmlarea .toolbar .Copy, .htmlarea-context-menu .Copy { background-image:url("images/ed_copy.gif");} +.htmlarea .toolbar .Cut, .htmlarea-context-menu .Cut { background-image:url("images/ed_cut.gif");} .htmlarea .toolbar .Paste, .htmlarea-context-menu .Paste { background-image:url("images/ed_paste.gif");} -.htmlarea .toolbar .Undo { background-image:url("images/ed_undo.gif");} -.htmlarea .toolbar .Redo { background-image:url("images/ed_redo.gif");} -.htmlarea .toolbar .About { background-image:url("images/ed_about.gif");} +.htmlarea-context-menu .DeleteTarget {background-image:url("images/ed_delete.gif");} +.htmlarea .toolbar .Undo, .htmlarea-context-menu .Undo { background-image:url("images/ed_undo.gif");} +.htmlarea .toolbar .Redo, .htmlarea-context-menu .Redo { background-image:url("images/ed_redo.gif");} +.htmlarea .toolbar .About, .htmlarea-context-menu .About, .htmlarea-window .About { background-image:url("images/ed_about.gif");} .htmlarea .toolbar .ShowHelp { background-image:url("images/TYPO3ViewHelp/module_help.gif");} .htmlarea .toolbar .TO-toggle-borders, .htmlarea-context-menu .TO-toggle-borders {background-image:url("images/TableOperations/toggle-borders.gif");} -.htmlarea .toolbar .TO-table-prop, .htmlarea-context-menu .TO-table-prop {background-image:url("images/TableOperations/table-prop.gif");} +.htmlarea .toolbar .TO-table-prop, .htmlarea-context-menu .TO-table-prop, .htmlarea-window .TO-table-prop {background-image:url("images/TableOperations/table-prop.gif");} .htmlarea .toolbar .TO-table-restyle, .htmlarea-context-menu .TO-table-restyle {background-image:url("images/TableOperations/table-restyle.gif");} -.htmlarea .toolbar .TO-row-prop, .htmlarea-context-menu .TO-row-prop {background-image:url("images/TableOperations/row-prop.gif");} +.htmlarea .toolbar .TO-row-prop, .htmlarea-context-menu .TO-row-prop, .htmlarea-window .TO-row-prop {background-image:url("images/TableOperations/row-prop.gif");} .htmlarea .toolbar .TO-row-insert-above, .htmlarea-context-menu .TO-row-insert-above {background-image:url("images/TableOperations/row-insert-above.gif");} .htmlarea .toolbar .TO-row-insert-under, .htmlarea-context-menu .TO-row-insert-under {background-image:url("images/TableOperations/row-insert-under.gif");} .htmlarea .toolbar .TO-row-delete, .htmlarea-context-menu .TO-row-delete {background-image:url("images/TableOperations/row-delete.gif");} .htmlarea .toolbar .TO-row-split, .htmlarea-context-menu .TO-row-split {background-image:url("images/TableOperations/row-split.gif");} -.htmlarea .toolbar .TO-col-prop, .htmlarea-context-menu .TO-col-prop {background-image:url("images/TableOperations/col-prop.gif");} +.htmlarea .toolbar .TO-col-prop, .htmlarea-context-menu .TO-col-prop, .htmlarea-window .TO-col-prop {background-image:url("images/TableOperations/col-prop.gif");} .htmlarea .toolbar .TO-col-insert-before, .htmlarea-context-menu .TO-col-insert-before {background-image:url("images/TableOperations/col-insert-before.gif");} .htmlarea .toolbar .TO-col-insert-after, .htmlarea-context-menu .TO-col-insert-after {background-image:url("images/TableOperations/col-insert-after.gif");} .htmlarea .toolbar .TO-col-delete, .htmlarea-context-menu .TO-col-delete {background-image:url("images/TableOperations/col-delete.gif");} .htmlarea .toolbar .TO-col-split, .htmlarea-context-menu .TO-col-split {background-image:url("images/TableOperations/col-split.gif");} -.htmlarea .toolbar .TO-cell-prop, .htmlarea-context-menu .TO-cell-prop {background-image:url("images/TableOperations/cell-prop.gif");} +.htmlarea .toolbar .TO-cell-prop, .htmlarea-context-menu .TO-cell-prop, .htmlarea-window .TO-cell-prop {background-image:url("images/TableOperations/cell-prop.gif");} .htmlarea .toolbar .TO-cell-insert-before, .htmlarea-context-menu .TO-cell-insert-before {background-image:url("images/TableOperations/cell-insert-before.gif");} .htmlarea .toolbar .TO-cell-insert-after, .htmlarea-context-menu .TO-cell-insert-after {background-image:url("images/TableOperations/cell-insert-after.gif");} .htmlarea .toolbar .TO-cell-delete, .htmlarea-context-menu .TO-cell-delete {background-image:url("images/TableOperations/cell-delete.gif");} .htmlarea .toolbar .TO-cell-split, .htmlarea-context-menu .TO-cell-split {background-image:url("images/TableOperations/cell-split.gif");} .htmlarea .toolbar .TO-cell-merge, .htmlarea-context-menu .TO-cell-merge {background-image:url("images/TableOperations/cell-merge.gif");} -.htmlarea .toolbar button.buttonHover { +.htmlarea .toolbar .buttonHover { border:1px solid;border-color:#e4e0db #999999 #999999 #e4e0db; } -.htmlarea .toolbar button.buttonActive { +.htmlarea .toolbar .buttonActive, .htmlarea .toolbar .buttonPressed, .htmlarea-context-menu .buttonActive { border:1px solid;border-color:ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; - padding:2px 0px 0px 2px; + background-color:ButtonHighlight; } -.htmlarea .toolbar button.buttonPressed, .htmlarea-context-menu button.buttonActive { +.htmlarea .toolbar .buttonPressed, .htmlarea-context-menu .buttonActive { background-color:ButtonHighlight; - border:1px solid;border-color:#999999 #e4e0db #e4e0db #999999; - padding:2px 0px 0px 2px; text-decoration:none; } -.htmlarea .toolbar div.indicator { - margin:4px 0px 0px 0px; - padding:0px 3px; - overflow:hidden; - width:20px; +.htmlarea .toolbar .indicator { + background-color:white;cursor:default; + width:20px;overflow:hidden; + height:16px; text-align:center; - cursor:default; border:1px solid ButtonShadow; + margin:3px 1px 4px 1px;padding:0 3px; + float:left; } -.htmlarea .toolbar button.buttonDisabled { +.htmlarea .toolbar .buttonDisabled { filter: alpha(opacity=25); -moz-opacity: 0.25; opacity: 0.25; } -.htmlarea .toolbar div.separator { - position:relative; - border-left:1px solid #999;margin:0 3px;padding:0; - width:0px;height:20px; -} -.htmlarea .toolbar li.tb-first-cell .separator { - border-style:none;margin:0;padding:0; -} -.htmlarea .toolbar div.space { +.htmlarea .toolbar .separator { + border:1px solid #999; + width:7px;height:23px; float:left; +} +.htmlarea .toolbar .space { height:22px; - margin:0;padding:0px 1px 0px 0px; + border-style:none; + margin:0;padding:0 1px; + float:left; } -.htmlarea .toolbar select { +.htmlarea .toolbar .select { font:10px Tahoma,Verdana,sans-serif; height:18px; border:1px solid #A2AAB8; - margin:0;padding:1px; + margin:0 0 3px 0;padding:1px; } -.htmlarea .toolbar select, .htmlarea .toolbar select:hover, .htmlarea .toolbar select:active { +.htmlarea .toolbar .select, .htmlarea .toolbar .select:hover, .htmlarea .toolbar .select:active { background-color:#fff;color:ButtonText; } -.htmlarea .toolbar select.buttonDisabled { +.htmlarea .toolbar .buttonDisabled { background-color:#e4e0db; } .htmlarea .editorIframe { clear:both; width:100%; - border:1px solid #000;border-top:0px;margin:0;padding:0; + border:1px solid #A2AAB8;border-bottom:1px solid #e4e0db; + margin:0;padding:0; } .htmlarea .noStatusBar { border-bottom:1px solid #000; } .htmlarea .statusBar { - clear:both; - background-color:#e4e0db;color:ButtonText; - font:11px Tahoma,Verdana,sans-serif; - width:100%; - border:1px solid;border-color:ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;margin:0;padding:0; + color:ButtonText; + background-color:#e4e0db; + font-size:10px; + font-family: Verdana, Helvetica, Geneva, Arial, sans-serif; + border:1px solid;border-color:#C5C5D5 #A2AAB8 #A2AAB8 #A2AAB8; + margin: 0; + padding: 0 3px; + line-height: 20px; } -.htmlarea .statusBarTree { - padding:2px 5px; -} .htmlarea .statusBar .statusBarTree a { - color:#00f; - padding:2px 5px; + color:ButtonText; + text-decoration:none; + font-weight:bold; + padding:0px 5px; } .htmlarea .statusBar .statusBarTree a:visited { color:#00f; } .htmlarea .statusBar .statusBarTree a:hover { - background-color:Highlight;color:HighlightText; - border:1px solid HighlightText;padding:1px 4px; + text-decoration: underline; } -.htmlarea .statusBarTextMode { - padding:2px 5px; -} /* Selectors for dialogue windows */ +.htmlarea-window .x-tab-panel-body { + background-color: #EFEFF4; +} +.htmlarea-window .x-fieldset { + margin: 3px; +} +.htmlarea-window .x-form-item-label { + text-align: right; + vertical-align: middle; + padding: 4px 5px 0 5px; +} +.htmlarea-window .x-btn-text { + font-weight: normal; + color: #000000; +} +.htmlarea-window .x-form-check-wrap input { + vertical-align: middle; +} +.htmlarea-window .show-color { + margin-top: 10px; + margin-left: 5px; + border-style: solid; + border-width: 1px; + border-color: white; +} +.htmlarea-custom-colors a { + border-style: none; + float: none; + display: block; + width: 100%; +} +.htmlarea-custom-colors em { + display: block; + border: 1px solid; + border-color: #C5C5D5; + width: 100%; +} +.htmlarea-custom-colors em span { + width: 100%; +} .popupwin { background-color:#e4e0db;color:ButtonText; font:11px Tahoma,Verdana,sans-serif; @@ -393,53 +432,6 @@ .popupwin input.shorter-value { width:17em; } -/* Selectors for TYPO3 Color dialogue */ -.popupwin .buttonColor { - cursor:default; - border-style:solid;border-width:1px;border-color:ButtonHighlight ButtonShadow ButtonHighlight ButtonHighlight; - padding:1px;margin:2px 10px 0 0; - height:1em; - white-space:nowrap; -} -.popupwin div.buttonColor { - float:left; - vertical-align:middle; -} -.popupwin .buttonColor-hilite { - border-color:black black black black; -} -.popupwin .buttonColor .chooser, .popupwin .buttonColor .nocolor { - height:0.6em; - border-width:1px;border-style:solid;border-width:1px;border-color:ButtonShadow ButtonHighlight ButtonShadow ButtonShadow; - padding:0 1em; -} -.popupwin .buttonColor .nocolor { - padding:0; -} -.popupwin .buttonColor .nocolor-hilite { - background-color:#fff;color:#f00;cursor:pointer; -} -.popupwin .colorTableWrapper { -} -.popupwin .colorTable { - width:350px; -} -.popupwin .currentColor { - width:20px;height:20px; - border:black 1px solid; - margin:0pt 15pt; -} -.popupwin .colorTable tr { - height:6px; -} -.popupwin .colorTable td { - width:6px; - cursor:pointer; -} -.popupwin .colorTable td.colorTitle { - width:auto; - padding-left:10px; -} /* Selectors for the Default Image dialogue */ .htmlarea-default-image #image, .htmlarea-default-image #alt { white-space:nowrap; @@ -460,22 +452,18 @@ white-space:nowrap; } /* Selectors for the InsertSmiley plugin */ -.htmlarea-insert-smiley div.smileytable { - text-align:center; - height:130px;margin-bottom:10px; +.htmlarea-window .emoticon-array { + padding: 10px; + width: 150px; } -.htmlarea-insert-smiley #smileytable { - height:130px; +.htmlarea-window .emoticon { + display: block; + float: left; + padding: 5px; + width: 20px; + height: 20px; + vertical-align: middle; } -.htmlarea-insert-smiley #smileytable tr { - height:25px; -} -.htmlarea-insert-smiley #smileytable td { - width:35px;height:25px; -} -.htmlarea-insert-smiley #smileytable td img { - border-style:none; -} /* Selectors for the FindReplace dialogue */ .htmlarea-find-replace .long-label { text-align:left; @@ -505,47 +493,6 @@ .htmlarea-character-map td.character-hilite { background-color:Highlight;color:HighlightText; } -/* Selectors for the DefaultColor dialogue */ -.htmlarea-default-color #selectedColor div { - white-space:nowrap; -} -.htmlarea-default-color #ColorPreview { - height:21px;width:50px; - float:left; - background-color:#000; -} -.htmlarea-default-color #ColorHex { - font-size:12px; - display:inline; - vertical-align:top; - margin-left:5px; -} -.htmlarea-default-color table { - margin:5px 0; -} -.htmlarea-default-color .color { - width:10px;height:10px; - cursor:pointer; -} -/* Selectors for the QuickTag dialogue */ -.htmlarea-quick-tag #tag { - text-align:center; - padding:3px; - background-color:#E9E9E9; -} -.htmlarea-quick-tag #tagopen { - background-color: #E9E9E9; - width:370px; - border-style:none; -} -.htmlarea-quick-tag strong { - font-size:14px; -} -.htmlarea-quick-tag #showselect { - position:absolute;left:7px;top:81px; - width:150px;height:13px; - z-index:100;visibility:visible; -} /* Selectors for the SpellChecker dialogue */ .htmlarea-spell-check .dictionaries { float:right; @@ -599,32 +546,23 @@ } /* Selectors for the ContextMenu plugin */ .htmlarea-context-menu { - position:absolute;top:-1000px;left:-1000px;z-index:1000; - background-color:#cdf;cursor:default; - font:11px Tahoma,Verdana,sans-serif; - list-style:none; - border:1px solid #aca899;margin:0;padding:2px; + background-color:#EFEFF4; + color:#212424; + font-family: Verdana, Helvetica, Geneva, Arial, sans-serif; + font-size:10px; } -.htmlarea-context-menu li { - background-color:#cdf; - border:1px solid #cdf;margin:1px 0;padding:0; - font-size:11px; +.htmlarea-context-menu .button { + background-color:transparent; + background-repeat:no-repeat; + background-position:0px 0px; } -.htmlarea-context-menu li button { - text-align:left;vertical-align:middle; - background-color:transparent;background-repeat:no-repeat;background-position:0px 0px; - height:19px;width:20px; - border-style:none;margin:0px 3px 0px 0;padding:0; +.htmlarea-context-menu .separator { + border-top:1px solid #A2AAB8; } -.htmlarea-context-menu li .button img { - width:18px;height:18px; -} -.htmlarea-context-menu li.separator { - border-top:1px solid #fff; -} -.htmlarea-context-menu li.hover { - background-color:#316ac5; -} -.htmlarea-context-menu li.hover .button { +.htmlarea-context-menu .hover { + background-image:url('alt_menu_mainitem_bg.gif'); + background-repeat: repeat-x; color:#fff; + padding-bottom:0;margin-bottom:0; + border-color:#A2AAB8; } Index: typo3/sysext/rtehtmlarea/htmlarea/skins/default/images/BlockElements/insertHorizontalRule.gif =================================================================== Impossible d'afficher : fichier considéré comme binaire. svn:mime-type = application/octet-stream Modification de propriétés sur typo3\sysext\rtehtmlarea\htmlarea\skins\default\images\BlockElements\insertHorizontalRule.gif ___________________________________________________________________ Ajouté : svn:mime-type + application/octet-stream Index: typo3/sysext/rtehtmlarea/htmlarea/skins/default/images/helpbubble.gif =================================================================== Impossible d'afficher : fichier considéré comme binaire. svn:mime-type = application/octet-stream Modification de propriétés sur typo3\sysext\rtehtmlarea\htmlarea\skins\default\images\helpbubble.gif ___________________________________________________________________ Ajouté : svn:mime-type + application/octet-stream Index: typo3/sysext/rtehtmlarea/htmlarea/skins/default/images/loading.gif =================================================================== Impossible d'afficher : fichier considéré comme binaire. svn:mime-type = application/octet-stream Modification de propriétés sur typo3\sysext\rtehtmlarea\htmlarea\skins\default\images\loading.gif ___________________________________________________________________ Ajouté : svn:mime-type + application/octet-stream Index: typo3/sysext/rtehtmlarea/pi2/class.tx_rtehtmlarea_pi2.php =================================================================== --- typo3/sysext/rtehtmlarea/pi2/class.tx_rtehtmlarea_pi2.php (révision 6908) +++ typo3/sysext/rtehtmlarea/pi2/class.tx_rtehtmlarea_pi2.php (copie de travail) @@ -2,7 +2,7 @@ /*************************************************************** * Copyright notice * -* (c) 2005-2009 Stanislas Rolland +* (c) 2005-2010 Stanislas Rolland * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -225,6 +225,10 @@ $pageRenderer->addCssFile($this->hostURL . '/t3lib/js/extjs/ux/resize.css'); // Loading JavaScript files and code $pageRenderer->loadExtJs(); + $pageRenderer->enableExtJSQuickTips(); + if (!$GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['enableCompressedScripts']) { + $pageRenderer->enableExtJsDebug(); + } $pageRenderer->addJsFile($this->hostURL . '/t3lib/js/extjs/ux/ext.resizable.js'); if ($this->TCEform->RTEcounter == 1) { $this->TCEform->additionalJS_pre['rtehtmlarea-loadJScode'] = $this->loadJScode($this->TCEform->RTEcounter); Index: typo3/sysext/rtehtmlarea/res/demo/pageTSConfig.txt =================================================================== --- typo3/sysext/rtehtmlarea/res/demo/pageTSConfig.txt (révision 6908) +++ typo3/sysext/rtehtmlarea/res/demo/pageTSConfig.txt (copie de travail) @@ -228,7 +228,7 @@ ## Configuration specific to the inserttag button or QuickTag feature (htmlArea RTE only) ## Do not allow insertion of the following tags - buttons.inserttag.denyTags = font, underline, strike, table + buttons.inserttag.denyTags = font, u, strike, table ## Configuration specific to the bold and italic buttons (htmlArea RTE only) ## Add hotkeys associated with bold, italic, strikethrough and underline buttons Index: typo3/sysext/t3skin/rtehtmlarea/htmlarea-edited-content.css =================================================================== --- typo3/sysext/t3skin/rtehtmlarea/htmlarea-edited-content.css (révision 6908) +++ typo3/sysext/t3skin/rtehtmlarea/htmlarea-edited-content.css (copie de travail) @@ -5,6 +5,7 @@ margin:0; padding:3px; background-color:#ffffff; + border-width:0; } /* Selectors for the Table Operations plugin */ @@ -16,7 +17,7 @@ /* Make language marks visible */ body.htmlarea-show-language-marks *[lang] { - background: url("images/language-marker.gif") left bottom no-repeat; padding-left: 14px; text-decoration: underline; + background: url("images/language-marker.gif") left top no-repeat; padding-left: 14px; text-decoration: underline; } /* Selectors for the Abbreviation plugin */ Index: typo3/sysext/t3skin/rtehtmlarea/htmlarea.css =================================================================== --- typo3/sysext/t3skin/rtehtmlarea/htmlarea.css (révision 6908) +++ typo3/sysext/t3skin/rtehtmlarea/htmlarea.css (copie de travail) @@ -1,21 +1,17 @@ -/* CSS Selectors for skin sr_rtehtmlarea_bluelook */ /* Selectors for the htmlArea RTE editor */ .htmlarea { - background-color:#fff; - margin:0;padding:0; + background-color:#EFEFF4; + margin:0 2px 0 0;padding:0; } -.resizable { - background-color:transparent; - padding-right:7px; - padding-bottom:6px; - background-image: url("images/resize.gif"); - background-position: bottom right; - background-repeat: no-repeat; -} .pleasewait { - position:relative;top:0px;text-align:left; - font-size:10px; + position:relative; margin-top:30px; + padding: 20px 0 20px 50px; + font-size: 11px !important; + text-align:left; + background: url('images/loading.gif') no-repeat 10px center; + vertical-align: middle; + color: #7F8083; } .editorWrap { margin:0;padding:0; @@ -28,83 +24,80 @@ padding:0px 1px; margin:0; } +.editorWrap .resizable { + background-image: url("images/resize.gif"); + background-position: bottom right; + background-repeat: no-repeat; +} +.editorWrap div.resizable { + padding-right: 7px; + padding-bottom: 5px; +} /* Selectors for the editor toolbar */ -.htmlarea div.toolbar { +.htmlarea .toolbar { background-color:#EFEFF4;cursor:default; - width:100%; border:1px solid #EFEFF4; border-bottom:0px; margin:0; padding:2px 0px; + font-family: Verdana, Helvetica, Geneva, Arial, sans-serif; } -.htmlarea .toolbar ul { - background-color:transparent; - list-style-type:none; -} -.htmlarea .toolbar ul.tb-line { - clear:both; - border-style:none;margin:0;padding:0px 2px; -} -.htmlarea .toolbar ul.tb-group { - clear:none;float:left; - margin:1px 2px 0px 0px;padding:0; -} -.htmlarea .toolbar ul li { +.htmlarea .toolbar .tb-group { + clear:none; float:left; - background-color:transparent; - color: #212424; - font-size:10px; - font-family: Verdana, Helvetica, Geneva, Arial, sans-serif; - border-style:none;margin:0;padding:0; + margin:1px 2px 0px 0px; + padding:0; } -.htmlarea .toolbar ul.free-float li, .htmlarea .toolbar ul.tb-group li { - height:24px; +.htmlarea .toolbar .x-form-item { + float: left; + margin:0; } -.htmlarea .toolbar label { +.htmlarea .toolbar .x-form-item-label { vertical-align:middle; background-color:transparent; - border-style:none;margin:0;padding:3px 3px 0px 3px; + border-style:none; + margin:0;padding:3px 3px 0px 3px; } - -.htmlarea .toolbar button { - vertical-align:top; - background-color:transparent;color:ButtonText;background-position:1px 1px;background-repeat:no-repeat; +.htmlarea .toolbar .button { + background-color:transparent;color:ButtonText;background-position:10px 0px;background-repeat:no-repeat; width:22px;height:22px; - border-style:solid;border-color:#EFEFF4;border-width:0px 1px;margin:0;padding:0; + border-style:solid;border-color:#EFEFF4;border-width:1px; + margin:0 0 1px 0;padding:0; + float:left; } -.htmlarea .toolbar button div.buttonImgContainer { - position:relative;top:0;left:0; - width:18px;height:18px;overflow:hidden; +.htmlarea .toolbar .x-btn-mc, .htmlarea .toolbar .x-btn-ml, .htmlarea .toolbar .x-btn-mr, .htmlarea .toolbar .x-btn-tc, .htmlarea .toolbar .x-btn-tl, .htmlarea .toolbar .x-btn-tr, .htmlarea .toolbar .x-btn-bl, .htmlarea .toolbar .x-btn-bc, .htmlarea .toolbar .x-btn-br { + background-color:transparent;background-image:none; + border-style:none; margin:0;padding:0; } -.htmlarea .toolbar .BiDiOverride {background-image:url("images/InlineElements/bidioverride.gif");} -.htmlarea .toolbar .Big {background-image:url("images/InlineElements/big.gif");} -.htmlarea .toolbar .Bold {background-image:url("images/InlineElements/bold.gif");} -.htmlarea .toolbar .Citation {background-image:url("images/InlineElements/citation.gif");} -.htmlarea .toolbar .Code {background-image:url("images/InlineElements/code.gif");} -.htmlarea .toolbar .Definition {background-image:url("images/InlineElements/definition.gif");} -.htmlarea .toolbar .DeletedText {background-image:url("images/InlineElements/deletedtext.gif");} -.htmlarea .toolbar .Emphasis {background-image:url("images/InlineElements/emphasis.gif");} -.htmlarea .toolbar .InsertedText {background-image:url("images/InlineElements/insertedtext.gif");} -.htmlarea .toolbar .Italic {background-image:url("images/InlineElements/italic.gif");} -.htmlarea .toolbar .Keyboard {background-image:url("images/InlineElements/keyboard.gif");} -.htmlarea .toolbar .MonoSpaced {background-image:url("images/InlineElements/monospaced.gif");} -.htmlarea .toolbar .Quotation {background-image:url("images/InlineElements/quotation.gif");} -.htmlarea .toolbar .Sample {background-image:url("images/InlineElements/sample.gif");} -.htmlarea .toolbar .Small {background-image:url("images/InlineElements/small.gif");} -.htmlarea .toolbar .Span {background-image:url("images/InlineElements/span.gif");} -.htmlarea .toolbar .StrikeThrough {background-image:url("images/InlineElements/strikethrough.gif");} -.htmlarea .toolbar .Strong {background-image:url("images/InlineElements/strong.gif");} -.htmlarea .toolbar .Subscript {background-image:url("images/InlineElements/subscript.gif");} -.htmlarea .toolbar .Superscript {background-image:url("images/InlineElements/superscript.gif");} -.htmlarea .toolbar .Underline {background-image:url("images/InlineElements/underline.gif");} -.htmlarea .toolbar .Variable {background-image:url("images/InlineElements/variable.gif");} -.htmlarea .toolbar .LeftToRight {background-image:url("images/ed_left_to_right.gif");} -.htmlarea .toolbar .RightToLeft {background-image:url("images/ed_right_to_left.gif");} -.htmlarea .toolbar .ShowLanguageMarks {background-image:url("images/show-language-marks.gif");} -.htmlarea .toolbar .Indent {background-image:url("images/BlockElements/indent.gif");} -.htmlarea .toolbar .Outdent {background-image:url("images/BlockElements/outdent.gif");} -.htmlarea .toolbar .Blockquote {background-image:url("images/BlockElements/blockquote.gif");} +.htmlarea .toolbar .BiDiOverride, .htmlarea-context-menu .BiDiOverride {background-image:url("images/InlineElements/bidioverride.gif");} +.htmlarea .toolbar .Big, .htmlarea-context-menu .Big {background-image:url("images/InlineElements/big.gif");} +.htmlarea .toolbar .Bold, .htmlarea-context-menu .Bold {background-image:url("images/InlineElements/bold.gif");} +.htmlarea .toolbar .Citation, .htmlarea-context-menu .Citation {background-image:url("images/InlineElements/citation.gif");} +.htmlarea .toolbar .Code, .htmlarea-context-menu .Code {background-image:url("images/InlineElements/code.gif");} +.htmlarea .toolbar .Definition, .htmlarea-context-menu .Definition {background-image:url("images/InlineElements/definition.gif");} +.htmlarea .toolbar .DeletedText, .htmlarea-context-menu .DeletedText {background-image:url("images/InlineElements/deletedtext.gif");} +.htmlarea .toolbar .Emphasis, .htmlarea-context-menu .Emphasis {background-image:url("images/InlineElements/emphasis.gif");} +.htmlarea .toolbar .InsertedText, .htmlarea-context-menu .InsertedText {background-image:url("images/InlineElements/insertedtext.gif");} +.htmlarea .toolbar .Italic, .htmlarea-context-menu .Italic {background-image:url("images/InlineElements/italic.gif");} +.htmlarea .toolbar .Keyboard, .htmlarea-context-menu .Keyboard {background-image:url("images/InlineElements/keyboard.gif");} +.htmlarea .toolbar .MonoSpaced, .htmlarea-context-menu .MonoSpaced {background-image:url("images/InlineElements/monospaced.gif");} +.htmlarea .toolbar .Quotation, .htmlarea-context-menu .Quotation {background-image:url("images/InlineElements/quotation.gif");} +.htmlarea .toolbar .Sample, .htmlarea-context-menu .Sample {background-image:url("images/InlineElements/sample.gif");} +.htmlarea .toolbar .Small, .htmlarea-context-menu .Small {background-image:url("images/InlineElements/small.gif");} +.htmlarea .toolbar .Span, .htmlarea-context-menu .Span {background-image:url("images/InlineElements/span.gif");} +.htmlarea .toolbar .StrikeThrough, .htmlarea-context-menu .StrikeThrough {background-image:url("images/InlineElements/strikethrough.gif");} +.htmlarea .toolbar .Strong, .htmlarea-context-menu .Strong {background-image:url("images/InlineElements/strong.gif");} +.htmlarea .toolbar .Subscript, .htmlarea-context-menu .Subscript {background-image:url("images/InlineElements/subscript.gif");} +.htmlarea .toolbar .Superscript, .htmlarea-context-menu .Superscript {background-image:url("images/InlineElements/superscript.gif");} +.htmlarea .toolbar .Underline, .htmlarea-context-menu .Underline {background-image:url("images/InlineElements/underline.gif");} +.htmlarea .toolbar .Variable, .htmlarea-context-menu .Variable {background-image:url("images/InlineElements/variable.gif");} +.htmlarea .toolbar .LeftToRight, .htmlarea-context-menu .LeftToRight {background-image:url("images/ed_left_to_right.gif");} +.htmlarea .toolbar .RightToLeft, .htmlarea-context-menu .RightToLeft {background-image:url("images/ed_right_to_left.gif");} +.htmlarea .toolbar .ShowLanguageMarks, .htmlarea-context-menu .ShowLanguageMarks {background-image:url("images/show-language-marks.gif");} +.htmlarea .toolbar .Indent, .htmlarea-context-menu .Indent {background-image:url("images/BlockElements/indent.gif");} +.htmlarea .toolbar .Outdent, .htmlarea-context-menu .Outdent {background-image:url("images/BlockElements/outdent.gif");} +.htmlarea .toolbar .Blockquote, .htmlarea-context-menu .Blockquote {background-image:url("images/BlockElements/blockquote.gif");} .htmlarea .toolbar .InsertParagraphBefore, .htmlarea-context-menu .InsertParagraphBefore {background-image:url("images/BlockElements/insertParagraphBefore.gif");} .htmlarea .toolbar .InsertParagraphAfter, .htmlarea-context-menu .InsertParagraphAfter {background-image:url("images/BlockElements/insertParagraphAfter.gif");} .htmlarea .toolbar .JustifyLeft, .htmlarea-context-menu .JustifyLeft {background-image:url("images/BlockElements/justifyLeft.gif");} @@ -113,125 +106,130 @@ .htmlarea .toolbar .JustifyFull, .htmlarea-context-menu .JustifyFull {background-image:url("images/BlockElements/justifyFull.gif");} .htmlarea .toolbar .DefinitionList, .htmlarea-context-menu .DefinitionList {background-image:url("images/definitionList.gif");} .htmlarea .toolbar .DefinitionItem, .htmlarea-context-menu .DefinitionItem {background-image:url("images/definitionItem.gif");} -.htmlarea .toolbar .InsertOrderedList {background-image:url("images/ed_list_num.gif");} -.htmlarea .toolbar .InsertUnorderedList {background-image:url("images/ed_list_bullet.gif");} -.htmlarea .toolbar .ForeColor {background-image:url("images/ed_color_fg.gif");} -.htmlarea .toolbar .HiliteColor {background-image:url("images/ed_color_bg.gif");} -.htmlarea .toolbar .InsertSmiley {background-image:url("images/InsertSmiley/ed_smiley.gif");} -.htmlarea .toolbar .InsertCharacter {background-image:url("images/CharacterMap/ed_charmap.gif");} -.htmlarea .toolbar .InsertHorizontalRule {background-image:url("images/ed_hr.gif");} -.htmlarea .toolbar .CreateLink, .htmlarea-context-menu .CreateLink {background-image:url("images/ed_link.gif");} +.htmlarea .toolbar .InsertOrderedList, .htmlarea-context-menu .InsertOrderedList {background-image:url("images/ed_list_num.gif");} +.htmlarea .toolbar .InsertUnorderedList, .htmlarea-context-menu .InsertUnorderedList {background-image:url("images/ed_list_bullet.gif");} +.htmlarea .toolbar .InsertHorizontalRule, .htmlarea-context-menu .InsertHorizontalRule {background-image:url("images/BlockElements/insertHorizontalRule.gif");} +.htmlarea .toolbar .ForeColor, .htmlarea-context-menu .ForeColor, .htmlarea-window .ForeColor {background-image:url("images/ed_color_fg.gif");} +.htmlarea .toolbar .HiliteColor, .htmlarea-context-menu .HiliteColor, .htmlarea-window .HiliteColor {background-image:url("images/ed_color_bg.gif");} +.htmlarea .toolbar .InsertSmiley, .htmlarea-context-menu .InsertSmiley, .htmlarea-window .InsertSmiley {background-image:url("images/InsertSmiley/ed_smiley.gif");} +.htmlarea .toolbar .InsertCharacter, .htmlarea-context-menu .InsertCharacter, .htmlarea-window .InsertCharacter {background-image:url("images/CharacterMap/ed_charmap.gif");} +.htmlarea .toolbar .CreateLink, .htmlarea-context-menu .CreateLink, .htmlarea-window .CreateLink {background-image:url("images/ed_link.gif");} .htmlarea .toolbar .UnLink, .htmlarea-context-menu .UnLink {background-image:url("images/ed_unlink.gif");} -.htmlarea .toolbar .InsertImage, .htmlarea-context-menu .InsertImage {background-image:url("images/ed_image.gif");} -.htmlarea .toolbar .InsertTable {background-image:url("images/insert_table.gif");} -.htmlarea .toolbar .UserElements {background-image:url("images/UserElements/ed_user.gif");} -.htmlarea .toolbar .FindReplace {background-image:url("images/FindReplace/ed_find.gif");} -.htmlarea .toolbar .SpellCheck {background-image:url("images/SpellChecker/spell-check.gif"); } -.htmlarea .toolbar .InsertTag {background-image:url("images/QuickTag/ed_quicktag.gif"); } -.htmlarea .toolbar .Acronym {background-image:url("images/Acronym/ed_acronym.gif"); } -.htmlarea .toolbar .RemoveFormat {background-image:url("images/RemoveFormat/ed_clean.gif"); } +.htmlarea .toolbar .InsertImage, .htmlarea-context-menu .InsertImage, .htmlarea-window .InsertImage {background-image:url("images/ed_image.gif");} +.htmlarea .toolbar .InsertTable, .htmlarea-context-menu .InsertTable, .htmlarea-window .InsertTable {background-image:url("images/insert_table.gif");} +.htmlarea .toolbar .UserElements, .htmlarea-context-menu .UserElements, .htmlarea-window .UserElements {background-image:url("images/UserElements/ed_user.gif");} +.htmlarea .toolbar .FindReplace, .htmlarea-context-menu .FindReplace, .htmlarea-window .FindReplace {background-image:url("images/FindReplace/ed_find.gif");} +.htmlarea .toolbar .SpellCheck, .htmlarea-context-menu .SpellCheck, .htmlarea-window .SpellCheck {background-image:url("images/SpellChecker/spell-check.gif"); } +.htmlarea .toolbar .InsertTag, .htmlarea-context-menu .InsertTag, .htmlarea-window .InsertTag {background-image:url("images/QuickTag/ed_quicktag.gif"); } +.htmlarea .toolbar .Acronym, .htmlarea-context-menu .Acronym, .htmlarea-window .Acronym {background-image:url("images/Acronym/ed_acronym.gif"); } +.htmlarea .toolbar .RemoveFormat, .htmlarea-context-menu .RemoveFormat, .htmlarea-window .RemoveFormat {background-image:url("images/RemoveFormat/ed_clean.gif"); } .htmlarea .toolbar .SplitBlock {background-image:url("images/ed_splitblock.gif"); } -.htmlarea .toolbar .TextMode {background-image:url("images/ed_html.gif"); } -.htmlarea .toolbar .Copy, .htmlarea-context-menu .Copy {background-image:url("images/ed_copy.gif");} +.htmlarea .toolbar .TextMode, .htmlarea-context-menu .TextMode {background-image:url("images/ed_html.gif"); } +.htmlarea .toolbar .Copy, .htmlarea-context-menu .Copy {background-image:url("images/ed_copy.gif");} .htmlarea .toolbar .Cut, .htmlarea-context-menu .Cut {background-image:url("images/ed_cut.gif");} .htmlarea .toolbar .Paste, .htmlarea-context-menu .Paste {background-image:url("images/ed_paste.gif");} -.htmlarea .toolbar .Undo {background-image:url("images/ed_undo.gif");} -.htmlarea .toolbar .Redo {background-image:url("images/ed_redo.gif");} -.htmlarea .toolbar .About {background-image:url("images/ed_about.gif");} +.htmlarea-context-menu .DeleteTarget {background-image:url("images/ed_delete.gif");} +.htmlarea .toolbar .Undo, .htmlarea-context-menu .Undo {background-image:url("images/ed_undo.gif");} +.htmlarea .toolbar .Redo, .htmlarea-context-menu .Redo {background-image:url("images/ed_redo.gif");} +.htmlarea .toolbar .About, .htmlarea-context-menu .About, .htmlarea-window .About {background-image:url("images/ed_about.gif");} .htmlarea .toolbar .ShowHelp { background-image:url("images/TYPO3ViewHelp/module_help.gif");} .htmlarea .toolbar .TO-toggle-borders, .htmlarea-context-menu .TO-toggle-borders {background-image:url("images/TableOperations/toggle-borders.gif");} -.htmlarea .toolbar .TO-table-prop, .htmlarea-context-menu .TO-table-prop {background-image:url("images/TableOperations/table-prop.gif");} +.htmlarea .toolbar .TO-table-prop, .htmlarea-context-menu .TO-table-prop, .htmlarea-window .TO-table-prop {background-image:url("images/TableOperations/table-prop.gif");} .htmlarea .toolbar .TO-table-restyle, .htmlarea-context-menu .TO-table-restyle {background-image:url("images/TableOperations/table-restyle.gif");} -.htmlarea .toolbar .TO-row-prop, .htmlarea-context-menu .TO-row-prop {background-image:url("images/TableOperations/row-prop.gif");} +.htmlarea .toolbar .TO-row-prop, .htmlarea-context-menu .TO-row-prop, .htmlarea-window .TO-row-prop {background-image:url("images/TableOperations/row-prop.gif");} .htmlarea .toolbar .TO-row-insert-above, .htmlarea-context-menu .TO-row-insert-above {background-image:url("images/TableOperations/row-insert-above.gif");} .htmlarea .toolbar .TO-row-insert-under, .htmlarea-context-menu .TO-row-insert-under {background-image:url("images/TableOperations/row-insert-under.gif");} .htmlarea .toolbar .TO-row-delete, .htmlarea-context-menu .TO-row-delete {background-image:url("images/TableOperations/row-delete.gif");} .htmlarea .toolbar .TO-row-split, .htmlarea-context-menu .TO-row-split {background-image:url("images/TableOperations/row-split.gif");} -.htmlarea .toolbar .TO-col-prop, .htmlarea-context-menu .TO-col-prop {background-image:url("images/TableOperations/col-prop.gif");} +.htmlarea .toolbar .TO-col-prop, .htmlarea-context-menu .TO-col-prop, .htmlarea-window .TO-col-prop {background-image:url("images/TableOperations/col-prop.gif");} .htmlarea .toolbar .TO-col-insert-before, .htmlarea-context-menu .TO-col-insert-before {background-image:url("images/TableOperations/col-insert-before.gif");} .htmlarea .toolbar .TO-col-insert-after, .htmlarea-context-menu .TO-col-insert-after {background-image:url("images/TableOperations/col-insert-after.gif");} .htmlarea .toolbar .TO-col-delete, .htmlarea-context-menu .TO-col-delete {background-image:url("images/TableOperations/col-delete.gif");} .htmlarea .toolbar .TO-col-split, .htmlarea-context-menu .TO-col-split {background-image:url("images/TableOperations/col-split.gif");} -.htmlarea .toolbar .TO-cell-prop, .htmlarea-context-menu .TO-cell-prop {background-image:url("images/TableOperations/cell-prop.gif");} +.htmlarea .toolbar .TO-cell-prop, .htmlarea-context-menu .TO-cell-prop, .htmlarea-window .TO-cell-prop {background-image:url("images/TableOperations/cell-prop.gif");} .htmlarea .toolbar .TO-cell-insert-before, .htmlarea-context-menu .TO-cell-insert-before {background-image:url("images/TableOperations/cell-insert-before.gif");} .htmlarea .toolbar .TO-cell-insert-after, .htmlarea-context-menu .TO-cell-insert-after {background-image:url("images/TableOperations/cell-insert-after.gif");} .htmlarea .toolbar .TO-cell-delete, .htmlarea-context-menu .TO-cell-delete {background-image:url("images/TableOperations/cell-delete.gif");} .htmlarea .toolbar .TO-cell-split, .htmlarea-context-menu .TO-cell-split {background-image:url("images/TableOperations/cell-split.gif");} .htmlarea .toolbar .TO-cell-merge, .htmlarea-context-menu .TO-cell-merge {background-image:url("images/TableOperations/cell-merge.gif");} -.htmlarea .toolbar button.buttonHover { +.htmlarea .toolbar .buttonHover { border:1px solid;border-color:white #C5C5D5 #C5C5D5 white; background-color: #E0E0E9; } -.htmlarea .toolbar button.buttonActive, .htmlarea .toolbar button.buttonPressed, .htmlarea-context-menu button.buttonActive { +.htmlarea .toolbar .buttonActive, .htmlarea .toolbar .buttonPressed, .htmlarea-context-menu .buttonActive { border:1px solid;border-color:#C5C5D5 white white #C5C5D5; + background-color:ButtonHighlight; } -.htmlarea .toolbar button.buttonPressed, .htmlarea-context-menu button.buttonActive { +.htmlarea .toolbar .buttonPressed, .htmlarea-context-menu .buttonActive { background-color:ButtonHighlight; text-decoration:none; } -.htmlarea .toolbar div.indicator { +.htmlarea .toolbar .indicator { background-color:white;cursor:default; width:20px;overflow:hidden; + height:16px; text-align:center; - border:1px solid ButtonShadow;margin:4px 1px 0px 1px;padding:0px 3px; + border:1px solid ButtonShadow; + margin:3px 1px 4px 1px;padding:0 3px; + float:left; } -.htmlarea .toolbar button.buttonDisabled { +.htmlarea .toolbar .buttonDisabled { filter: gray() alpha(opacity=25); -moz-opacity:0.25; opacity:0.25; } -.htmlarea .toolbar div.separator { - background-color:transparent;background-image:url(separator.gif);background-repeat:no-repeat; - width:7px;height:22px; - border:1px solid #EFEFF4;margin:0;padding:0; -} -.htmlarea .toolbar div.space { +.htmlarea .toolbar .separator { + background-color:transparent;background-image:url(separator.gif);background-repeat:no-repeat;background-position:0; + width:7px;height:23px; + border:1px solid #EFEFF4; float:left; +} +.htmlarea .toolbar .space { background-color:transparent; height:22px; - border-style:none;margin:0;padding:0 1px; + border-style:none; + margin:0;padding:0 1px; + float:left; } -.htmlarea .toolbar select { +.htmlarea .toolbar .select { color:WindowText; font-size:10px; font-family: Verdana, Helvetica, Geneva, Arial, sans-serif; height:18px; border:1px solid #A2AAB8; - margin:0;padding:1px; + margin:0 0 3px 0;padding:1px; } -.htmlarea .toolbar select, .htmlarea .toolbar select:hover, .htmlarea .toolbar select:active { +.htmlarea .toolbar .select, .htmlarea .toolbar .select:hover, .htmlarea .toolbar .select:active { background-color:Window; } -.htmlarea .toolbar select.buttonDisabled { +.htmlarea .toolbar .select .buttonDisabled { color:GrayText; background-color:#EFEFF4; } .htmlarea .editorIframe { clear:both; width:100%; - border:1px solid #A2AAB8;border-bottom:1px solid #e4e0db;margin:0;padding:0; + border:1px solid #A2AAB8;border-bottom:1px solid #e4e0db; + margin:0;padding:0; } .htmlarea .noStatusBar { border-bottom:1px solid #A2AAB8; } .htmlarea .statusBar { - clear:both; - background-color:#EFEFF4;background-image:url('alt_menu_mainitem_bg.gif');background-repeat:repeat-x;color:ButtonText; + color:#FFFFFF; + background-color:#EFEFF4;background-image:url('alt_menu_mainitem_bg.gif');background-repeat:repeat; font-size:10px; font-family: Verdana, Helvetica, Geneva, Arial, sans-serif; - width:100%;height:20px; - border:1px solid;border-color:#C5C5D5 #A2AAB8 #A2AAB8 #A2AAB8;margin:0;padding:0; + border:1px solid;border-color:#C5C5D5 #A2AAB8 #A2AAB8 #A2AAB8; + margin: 0; + padding: 0 3px; + line-height: 20px; } -.htmlarea .statusBarTree { - color:#FFFFFF; - display:block; - margin:3px 3px; -} .htmlarea .statusBar .statusBarTree a { color:#FFFFFF; text-decoration:none; font-weight:bold; - padding:2px 5px; + padding:0px 5px; } .htmlarea .statusBar .statusBarTree a:visited { color:#FFFFFF; @@ -239,11 +237,47 @@ .htmlarea .statusBar .statusBarTree a:hover { text-decoration: underline; } -.htmlarea .statusBarTextMode { - margin-top:2px; - padding:2px 5px; -} /* Selectors for dialogue windows */ +.htmlarea-window .x-tab-panel-body { + background-color: #EFEFF4; +} +.htmlarea-window .x-fieldset { + margin: 3px; +} +.htmlarea-window .x-form-item-label { + text-align: right; + vertical-align: middle; + padding: 4px 5px 0 5px; +} +.htmlarea-window .x-btn-text { + font-weight: normal; + color: #000000; +} +.htmlarea-window .x-form-check-wrap input { + vertical-align: middle; +} +.htmlarea-window .show-color { + margin-top: 10px; + margin-left: 5px; + border-style: solid; + border-width: 1px; + border-color: white; +} +.htmlarea-custom-colors a { + border-style: none; + float: none; + display: block; + width: 100%; +} +.htmlarea-custom-colors em { + display: block; + border: 1px solid; + border-color: #C5C5D5; + width: 100%; +} +.htmlarea-custom-colors em span { + width: 100%; +} .popupwin { color: #212424;background-color:#EFEFF4; font-size:11px;font-family:Verdana, Helvetica, Geneva, Arial, sans-serif; @@ -295,6 +329,7 @@ } .popupwin select { display:inline; + font-size:11px;font-family:Verdana, Helvetica, Geneva, Arial, sans-serif; } .popupwin table { border-collapse:collapse;border-style:none;margin:0;padding:0; @@ -348,6 +383,8 @@ } .popupwin select, .popupwin input, .popupwin button, .popupwin textarea, .popupwin table, .popupwin label { font-size:1.0em; + padding: 3px 1px 1px 1px; + font-family:Verdana, Helvetica, Geneva, Arial, sans-serif; } .popupwin button { width:8em; @@ -402,53 +439,6 @@ .popupwin input.shorter-value { width:17em; } -/* Selectors for TYPO3 Color dialogue */ -.popupwin .buttonColor { - cursor:default; - border-style:solid;border-width:1px;border-color:ButtonHighlight ButtonShadow ButtonHighlight ButtonHighlight; - padding:1px;margin:2px 10px 0 0; - height:1em; - white-space:nowrap; -} -.popupwin div.buttonColor { - float:left; - vertical-align:middle; -} -.popupwin .buttonColor-hilite { - border-color:black black black black; -} -.popupwin .buttonColor .chooser, .popupwin .buttonColor .nocolor { - height:0.6em; - border-width:1px;border-style:solid;border-width:1px;border-color:ButtonShadow ButtonHighlight ButtonShadow ButtonShadow; - padding:0 1em; -} -.popupwin .buttonColor .nocolor { - padding:0; -} -.popupwin .buttonColor .nocolor-hilite { - background-color:#fff;color:#f00;cursor:pointer; -} -.popupwin .colorTableWrapper { -} -.popupwin .colorTable { - width:350px; -} -.popupwin .currentColor { - width:20px;height:20px; - border:black 1px solid; - margin:0pt 15pt; -} -.popupwin .colorTable tr { - height:6px; -} -.popupwin .colorTable td { - width:6px; - cursor:pointer; -} -.popupwin .colorTable td.colorTitle { - width:auto; - padding-left:10px; -} /* Selectors for the Default Image dialogue */ .htmlarea-default-image #image, .htmlarea-default-image #alt { white-space:nowrap; @@ -469,22 +459,18 @@ white-space:nowrap; } /* Selectors for the InsertSmiley plugin */ -.htmlarea-insert-smiley div.smileytable { - text-align:center; - height:130px;margin-bottom:10px; +.htmlarea-window .emoticon-array { + padding: 10px; + width: 150px; } -.htmlarea-insert-smiley #smileytable { - height:130px; +.htmlarea-window .emoticon { + display: block; + float: left; + padding: 5px; + width: 20px; + height: 20px; + vertical-align: middle; } -.htmlarea-insert-smiley #smileytable tr { - height:25px; -} -.htmlarea-insert-smiley #smileytable td { - width:35px;height:25px; -} -.htmlarea-insert-smiley #smileytable td img { - border-style:none; -} /* Selectors for the FindReplace dialogue */ .htmlarea-find-replace .long-label { text-align:left; @@ -514,47 +500,6 @@ .htmlarea-character-map td.character-hilite { background-color:Highlight;color:HighlightText; } -/* Selectors for the DefaultColor dialogue */ -.htmlarea-default-color #selectedColor div { - white-space:nowrap; -} -.htmlarea-default-color #ColorPreview { - height:21px;width:50px; - float:left; - background-color:#000; -} -.htmlarea-default-color #ColorHex { - font-size:12px; - display:inline; - vertical-align:top; - margin-left:5px; -} -.htmlarea-default-color table { - margin:5px 0; -} -.htmlarea-default-color .color { - width:10px;height:10px; - cursor:pointer; -} -/* Selectors for the QuickTag dialogue */ -.htmlarea-quick-tag #tag { - text-align:center; - padding:3px; - background-color:#E9E9E9; -} -.htmlarea-quick-tag #tagopen { - background-color: #E9E9E9; - width:370px; - border-style:none; -} -.htmlarea-quick-tag strong { - font-size:14px; -} -.htmlarea-quick-tag #showselect { - position:absolute;left:7px;top:81px; - width:150px;height:13px; - z-index:100;visibility:visible; -} /* Selectors for the SpellChecker dialogue */ .htmlarea-spell-check .dictionaries { float:right; @@ -608,32 +553,23 @@ } /* Selectors for the ContextMenu plugin */ .htmlarea-context-menu { - position:absolute;top:-1000px;left:-1000px;z-index:1000; - background-color:#EFEFF4;cursor:default; + background-color:#EFEFF4; color:#212424; font-family: Verdana, Helvetica, Geneva, Arial, sans-serif; font-size:10px; - list-style:none; - border:1px solid #A2AAB8;margin:0;padding:2px; } -.htmlarea-context-menu li { - background-color:#EFEFF4; - border:1px solid #EFEFF4;margin:0;padding:0; - font-size:10px; +.htmlarea-context-menu .button { + background-color:transparent; + background-repeat:no-repeat; + background-position:0px 0px; } -.htmlarea-context-menu li button { - text-align:left;vertical-align:middle; - background-color:transparent;background-repeat:no-repeat;background-position:0px 0px; - height:20px;width:21px; - border-style:none;margin:0 3px 0 0;padding:0; -} -.htmlarea-context-menu li .button img { - width:18px;height:18px; -} -.htmlarea-context-menu li.separator { +.htmlarea-context-menu .separator { border-top:1px solid #A2AAB8; } -.htmlarea-context-menu li.hover { +.htmlarea-context-menu .hover { background-image:url('alt_menu_mainitem_bg.gif'); - color:#fff;border-color:#A2AAB8; + background-repeat: repeat-x; + color:#fff; + padding-bottom:0;margin-bottom:0; + border-color:#A2AAB8; } Index: typo3/sysext/t3skin/rtehtmlarea/images/BlockElements/insertHorizontalRule.gif =================================================================== Impossible d'afficher : fichier considéré comme binaire. svn:mime-type = application/octet-stream Modification de propriétés sur typo3\sysext\t3skin\rtehtmlarea\images\BlockElements\insertHorizontalRule.gif ___________________________________________________________________ Ajouté : svn:mime-type + application/octet-stream Index: typo3/sysext/t3skin/rtehtmlarea/images/helpbubble.gif =================================================================== Impossible d'afficher : fichier considéré comme binaire. svn:mime-type = application/octet-stream Modification de propriétés sur typo3\sysext\t3skin\rtehtmlarea\images\helpbubble.gif ___________________________________________________________________ Ajouté : svn:mime-type + application/octet-stream Index: typo3/sysext/t3skin/rtehtmlarea/images/loading.gif =================================================================== Impossible d'afficher : fichier considéré comme binaire. svn:mime-type = application/octet-stream Modification de propriétés sur typo3\sysext\t3skin\rtehtmlarea\images\loading.gif ___________________________________________________________________ Ajouté : svn:mime-type + application/octet-stream