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 20071127) {
+ styleEvent = (event.browserEvent.attrName == 'style');
+ }
+ if (styleEvent && this.nestedParentElements.sorted.indexOf(target.id) != -1 && this.getEditor().getMode() === 'wysiwyg' && (target.style.display == '' || target.style.display == 'block')) {
+ // Check if all affected nested elements are displayed (style.display!='none'):
+ if (HTMLArea.util.TYPO3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
+ this.setDesignMode(true);
+ this.getEditor().updateToolbar();
+ }
+ }
+ event.stopEvent();
+ },
+ /*
+ * Get the HTML content of the iframe
+ */
+ getHTML: function () {
+ return HTMLArea.getHTML(this.document.body, false, this.getEditor());
+ },
+ /*
+ * Start listening to things happening in the iframe
+ */
+ startListening: function () {
+ var documentElement = Ext.get(Ext.isIE ? this.document.body : this.document.documentElement);
+ // Create keyMap so that plugins may bind key handlers
+ this.keyMap = new Ext.KeyMap(documentElement, [], (Ext.isIE || Ext.isWebKit) ? 'keydown' : 'keypress');
+ // Special keys map
+ this.keyMap.addBinding([
+ {
+ key: [Ext.EventObject.DOWN, Ext.EventObject.UP, Ext.EventObject.LEFT, Ext.EventObject.RIGHT],
+ alt: false,
+ handler: this.onArrow,
+ scope: this
+ },
+ {
+ key: Ext.EventObject.TAB,
+ ctrl: false,
+ alt: false,
+ handler: this.onTab,
+ scope: this
+ },
+ {
+ key: [Ext.EventObject.BACKSPACE, Ext.EventObject.DELETE],
+ alt: false,
+ handler: this.onBackSpace,
+ scope: this
+ },
+ {
+ key: Ext.EventObject.SPACE,
+ ctrl: true,
+ shift: false,
+ alt: false,
+ handler: this.onCtrlSpace,
+ scope: this
+ }
+ ]);
+ if (!Ext.isIE && !this.config.disableEnterParagraphs) {
+ this.keyMap.addBinding(
+ {
+ key: Ext.EventObject.ENTER,
+ shift: false,
+ handler: this.onEnter,
+ scope: this
+ });
+ }
+ if (Ext.isWebKit) {
+ this.keyMap.addBinding(
+ {
+ key: Ext.EventObject.ENTER,
+ alt: false,
+ handler: this.onWebKitEnter,
+ scope: this
+ });
+ }
+ // Hot key map (on keydown for all brwosers)
+ var hotKeys = '';
+ Ext.iterate(this.config.hotKeyList, function (key) {
+ if (key.length == 1) {
+ hotKeys += key.toUpperCase();
+ }
+ });
+ if (!Ext.isEmpty(hotKeys)) {
+ this.hotKeyMap = new Ext.KeyMap(documentElement,
+ {
+ key: hotKeys,
+ ctrl: true,
+ shift: false,
+ alt: false,
+ handler: this.onHotKey,
+ scope: this
+ });
+ }
+ this.mon(documentElement, (Ext.isIE || Ext.isWebKit) ? 'keydown' : 'keypress', this.onAnyKey, this);
+ this.mon(documentElement, 'mouseup', this.onMouse, this);
+ Ext.EventManager.on(this.document, 'mouseup', this.onMouse, this);
+ this.mon(documentElement, 'drag', this.onMouse, this);
+ },
+ /*
+ * Handler for other key events
+ */
+ onAnyKey: function(event) {
+ // In Opera, inhibit key events while synchronous XMLHttpRequest is being processed
+ if (Ext.isOpera && HTMLArea.pendingSynchronousXMLHttpRequest) {
+ event.stopEvent();
+ return false;
+ }
+ // onKeyPress deprecated as of TYPO3 4.4
+ if (this.getEditor().hasPluginWithOnKeyPressHandler) {
+ var letBubble = true;
+ Ext.iterate(this.getEditor().plugins, function (pluginId) {
+ var plugin = this.getEditor().getPlugin(pluginId);
+ if (Ext.isFunction(plugin.onKeyPress)) {
+ if (!plugin.onKeyPress(event.browserEvent)) {
+ event.stopEvent();
+ letBubble = false;
+ }
}
- break;
+ return letBubble;
+ }, this);
+ if (!letBubble) {
+ return letBubble;
}
}
+ if (!event.altKey && !event.ctrlKey) {
+ // Detect URL in non-IE browsers
+ if (!Ext.isIE) {
+ this.getEditor()._detectURL(event);
+ }
+ // Handle option+SPACE for Mac users
+ if (Ext.isMac && event.browserEvent.charCode == 160) {
+ return this.onOptionSpace(event.browserEvent.charCode, event);
+ }
+ }
+ return true;
+ },
+ /*
+ * Handler for mouse events
+ */
+ onMouse: function () {
+ this.getToolbar().updateLater.delay(100);
+ return true;
+ },
+ /*
+ * Handler for UP, DOWN, LEFT and RIGHT keys
+ */
+ onArrow: function () {
+ this.getToolbar().updateLater.delay(100);
+ return true;
+ },
+ /*
+ * Handler for TAB and SHIFT-TAB keys
+ *
+ * If available, BlockElements plugin will handle the TAB key
+ */
+ onTab: function (key, event) {
+ var keyName = (event.shiftKey ? 'SHIFT-' : '') + 'TAB';
+ if (this.config.hotKeyList[keyName] && this.config.hotKeyList[keyName].cmd) {
+ var button = this.getButton(this.config.hotKeyList[keyName].cmd);
+ if (button) {
+ event.stopEvent();
+ button.fireEvent('hotkey', keyName, event);
+ return false;
+ }
+ }
+ return true;
+ },
+ /*
+ * Handler for BACKSPACE and DELETE keys
+ */
+ onBackSpace: function (key, event) {
+ if ((!Ext.isIE && !event.shiftKey) || Ext.isIE) {
+ if (this.getEditor()._checkBackspace()) {
+ event.stopEvent();
+ }
+ }
+ // Update the toolbar state after some time
+ this.getToolbar().updateLater.delay(200);
+ return false;
+ },
+ /*
+ * Handler for ENTER key in non-IE browsers
+ */
+ onEnter: function (key, event) {
+ if (!event.shiftKey) {
+ if (this.getEditor()._checkInsertP()) {
+ event.stopEvent();
+ }
+ }
+ // Update the toolbar state after some time
+ this.getToolbar().updateLater.delay(200);
+ return false;
+ },
+ /*
+ * Handler for ENTER key in WebKit browsers
+ */
+ onWebKitEnter: function (key, event) {
+ if (event.shiftKey || this.config.disableEnterParagraphs) {
+ var brNode = this.document.createElement('br');
+ this.getEditor().insertNodeAtSelection(brNode);
+ if (!brNode.nextSibling || !HTMLArea.getInnerText(brNode.nextSibling)) {
+ var secondBrNode = this.document.createElement('br');
+ secondBrNode = brNode.parentNode.appendChild(secondBrNode);
+ this.getEditor().selectNode(secondBrNode, false);
+ }
+ event.stopEvent();
+ }
+ // Update the toolbar state after some time
+ this.getToolbar().updateLater.delay(200);
+ return false;
+ },
+ /*
+ * Handler for CTRL-SPACE keys
+ */
+ onCtrlSpace: function (key, event) {
+ this.getEditor().insertHTML(' ');
+ event.stopEvent();
+ return false;
+ },
+ /*
+ * Handler for OPTION-SPACE keys on Mac
+ */
+ onOptionSpace: function (key, event) {
+ this.getEditor().insertHTML(' ');
+ event.stopEvent();
+ return false;
+ },
+ /*
+ * Handler for configured hotkeys
+ */
+ onHotKey: function (key, event) {
+ var hotKey = String.fromCharCode(key).toLowerCase();
+ this.getButton(this.config.hotKeyList[hotKey].cmd).fireEvent('hotkey', hotKey, event);
+ return false;
+ },
+ /*
+ * Cleanup
+ */
+ onBeforeDestroy: function () {
+ this.keyMap.disable();
+ this.hotKeyMap.disable();
}
- editor.updateToolbar();
-};
-
+});
+Ext.reg('htmlareaiframe', HTMLArea.Iframe);
/*
- * When we have a form, on reset, re-initialize the HTMLArea content and update the toolbar
+ * HTMLArea.StatusBar extends Ext.Container
*/
-HTMLArea.resetHandler = function(ev) {
- if(!ev) var ev = window.event;
- var form = (ev.target) ? ev.target : ev.srcElement;
- var editor = RTEarea[form._editorNumber]["editor"];
- editor.getPluginInstance("EditorMode").setHTML(editor._textArea.value);
- editor.updateToolbar();
- var a = form.__msh_prevOnReset;
- // call previous reset methods if they were there.
- if (typeof(a) != "undefined") {
- for (var i=a.length; --i >= 0; ) { a[i](); }
- }
-};
-
-/*
- * Clean up event handlers and object references, undo/redo snapshots, update the textarea for submission
- */
-HTMLArea.removeEditorEvents = function(ev) {
- if (!ev) var ev = window.event;
- HTMLArea._stopEvent(ev);
- if (HTMLArea._eventCache) {
- HTMLArea._eventCache.flush();
- }
- for (var editorNumber in RTEarea) {
- if (RTEarea.hasOwnProperty(editorNumber)) {
- var editor = RTEarea[editorNumber].editor;
- if (editor) {
- RTEarea[editorNumber].editor = null;
- // save the HTML content into the original textarea for submit, back/forward, etc.
- editor._textArea.value = editor.getPluginInstance("EditorMode").getHTML();
- // do final cleanup
- HTMLArea.cleanup(editor);
+HTMLArea.StatusBar = Ext.extend(Ext.Container, {
+ /*
+ * Constructor
+ */
+ initComponent: function () {
+ HTMLArea.StatusBar.superclass.initComponent.call(this);
+ this.addListener({
+ render: {
+ fn: this.addComponents,
+ single: true
+ },
+ afterrender: {
+ fn: this.initEventListeners,
+ single: true
}
+ });
+ },
+ /*
+ * Initialize listeners
+ */
+ initEventListeners: function () {
+ this.addListener({
+ beforedestroy: {
+ fn: this.clear,
+ single: true
+ }
+ });
+ // Monitor toolbar updates in order to refresh the contents of the statusbar
+ // The toolbar must have been rendered
+ this.mon(this.ownerCt.toolbar, 'update', this.onUpdateToolbar, this);
+ // Monitor editor changing mode
+ this.mon(this.getEditor(), 'modeChange', this.onModeChange, this);
+ },
+ /*
+ * editorId should be set in config
+ */
+ editorId: null,
+ /*
+ * Get a reference to the editor
+ */
+ getEditor: function() {
+ return RTEarea[this.editorId].editor;
+ },
+ /*
+ * Create span elements to display when the status bar tree or a message when the editor is in text mode
+ */
+ addComponents: function () {
+ this.statusBarTree = Ext.DomHelper.append(this.getEl(), {
+ id: this.editorId + '-statusBarTree',
+ tag: 'span',
+ cls: 'statusBarTree',
+ html: HTMLArea.I18N.msg['Path'] + ': '
+ }, true).setVisibilityMode(Ext.Element.DISPLAY).setVisible(true);
+ this.statusBarTextMode = Ext.DomHelper.append(this.getEl(), {
+ id: this.editorId + '-statusBarTextMode',
+ tag: 'span',
+ cls: 'statusBarTextMode',
+ html: HTMLArea.I18N.msg['TEXT_MODE']
+ }, true).setVisibilityMode(Ext.Element.DISPLAY).setVisible(false);
+ },
+ /*
+ * Clear the status bar tree
+ */
+ clear: function () {
+ this.statusBarTree.removeAllListeners();
+ Ext.each(this.statusBarTree.query('a'), function (node) {
+ Ext.QuickTips.unregister(node);
+ });
+ this.statusBarTree.update('');
+ this.setSelection(null);
+ },
+ /*
+ * Flag indicating that the status bar should not be updated on this toolbar update
+ */
+ noUpdate: false,
+ /*
+ * Update the status bar
+ */
+ onUpdateToolbar: function (mode, selectionEmpty, ancestors, endPointsInSameBlock) {
+ if (mode === 'wysiwyg' && !this.noUpdate) {
+ var text,
+ language,
+ languageObject = this.getEditor().getPlugin('Language'),
+ classes = new Array(),
+ classText;
+ this.clear();
+ var path = Ext.DomHelper.append(this.statusBarTree, {
+ tag: 'span',
+ html: HTMLArea.I18N.msg['Path'] + ': '
+ },true);
+ Ext.each(ancestors, function (ancestor, index) {
+ if (!ancestor) {
+ return true;
+ }
+ text = ancestor.nodeName.toLowerCase();
+ // Do not show any id generated by ExtJS
+ if (ancestor.id && text !== 'body' && ancestor.id.substr(0, 7) !== 'ext-gen') {
+ text += '#' + ancestor.id;
+ }
+ if (languageObject && languageObject.getLanguageAttribute) {
+ language = languageObject.getLanguageAttribute(ancestor);
+ if (language != 'none') {
+ text += '[' + language + ']';
+ }
+ }
+ if (ancestor.className) {
+ classText = '';
+ classes = ancestor.className.trim().split(' ');
+ for (var j = 0, n = classes.length; j < n; ++j) {
+ if (!HTMLArea.reservedClassNames.test(classes[j])) {
+ classText += '.' + classes[j];
+ }
+ }
+ text += classText;
+ }
+ var element = Ext.DomHelper.insertAfter(path, {
+ tag: 'a',
+ href: '#',
+ 'ext:qtitle': HTMLArea.I18N.dialogs['statusBarStyle'],
+ 'ext:qtip': ancestor.style.cssText.split(';').join(' '),
+ html: text
+ }, true);
+ // Ext.DomHelper does not honour the custom attribute
+ element.dom.ancestor = ancestor;
+ if (Ext.isIE) {
+ element.on('click', this.onClick, this);
+ } else {
+ element.on('mousedown', this.onMouseDown, this);
+ }
+ if (!Ext.isOpera) {
+ element.on('contextmenu', this.onContextMenu, this);
+ }
+ if (index) {
+ Ext.DomHelper.insertAfter(element, {
+ tag: 'span',
+ html: String.fromCharCode(0xbb)
+ });
+ }
+ }, this);
}
+ this.noUpdate = false;
+ },
+ /*
+ * Adapt status bar to current editor mode
+ *
+ * @param string mode: the mode to which the editor got switched to
+ */
+ onModeChange: function (mode) {
+ switch (mode) {
+ case 'wysiwyg':
+ this.statusBarTextMode.setVisible(false);
+ this.statusBarTree.setVisible(true);
+ break;
+ case 'textmode':
+ default:
+ this.statusBarTree.setVisible(false);
+ this.statusBarTextMode.setVisible(true);
+ break;
+ }
+ },
+ /*
+ * Refrence to the element last selected on the status bar
+ */
+ selected: null,
+ /*
+ * Get the status bar selection
+ */
+ getSelection: function() {
+ return this.selected;
+ },
+ /*
+ * Set the status bar selection
+ *
+ * @param object element: set the status bar selection to the given element
+ */
+ setSelection: function(element) {
+ this.selected = element ? element : null;
+ },
+ /*
+ * Select the element that was clicked in the status bar and set the status bar selection
+ */
+ selectElement: function (element) {
+ var editor = this.getEditor();
+ element.blur();
+ if (!Ext.isIE) {
+ editor.selectNodeContents(element.ancestor);
+ } else {
+ var nodeName = element.ancestor.nodeName.toLowerCase();
+ if (nodeName == 'table' || nodeName == 'img') {
+ var range = editor.document.body.createControlRange();
+ range.addElement(element.ancestor);
+ range.select();
+ } else {
+ editor.selectNode(element.ancestor);
+ }
+ }
+ this.setSelection(element.ancestor);
+ this.noUpdate = true;
+ editor.toolbar.update();
+ },
+ /*
+ * Click handler
+ */
+ onClick: function (event, element) {
+ this.selectElement(element);
+ event.stopEvent();
+ return false;
+ },
+ /*
+ * MouseDown handler
+ */
+ onMouseDown: function (event, element) {
+ this.selectElement(element);
+ if (Ext.isIE) {
+ return true;
+ } else {
+ event.stopEvent();
+ return false;
+ }
+ },
+ /*
+ * ContextMenu handler
+ */
+ onContextMenu: function (event, target) {
+ this.selectElement(target);
+ return this.getEditor().getPlugin('ContextMenu') ? this.getEditor().getPlugin('ContextMenu').show(event, target.ancestor) : false;
}
-};
-
+});
+Ext.reg('htmlareastatusbar', HTMLArea.StatusBar);
/*
- * Clean up a bunch of references in order to avoid memory leakages mainly in IE, but also in Firefox and Opera
+ * HTMLArea.Framework extends Ext.Panel
*/
-HTMLArea.cleanup = function (editor) {
- // nullify envent handlers
- for (var handler in editor.eventHandlers) {
- if (editor.eventHandlers.hasOwnProperty(handler)) {
- editor.eventHandlers[handler] = null;
+HTMLArea.Framework = Ext.extend(Ext.Panel, {
+ /*
+ * Constructor
+ */
+ initComponent: function () {
+ HTMLArea.Framework.superclass.initComponent.call(this);
+ // Set some references
+ this.toolbar = this.getTopToolbar();
+ this.statusBar = this.getBottomToolbar();
+ this.iframe = this.getComponent('iframe');
+ this.textAreaContainer = this.getComponent('textAreaContainer');
+ this.addEvents(
+ /*
+ * @event frameworkready
+ * Fires when the iframe is ready and all components are rendered
+ */
+ 'frameworkready'
+ );
+ this.addListener({
+ afterrender: {
+ fn: this.initEventListeners,
+ single: true
+ }
+ });
+ // Let the framefork render itself, but it will fail to do so if inside a hidden tab or inline element
+ if (!this.isNested || HTMLArea.util.TYPO3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
+ this.render(this.textArea.parent(), this.textArea.id);
+ } else {
+ // Clone the array of nested tabs and inline levels instead of using a reference as HTMLArea.util.TYPO3.accessParentElements will modify the array
+ var parentElements = [].concat(this.nestedParentElements.sorted);
+ // Walk through all nested tabs and inline levels to get correct sizes
+ HTMLArea.util.TYPO3.accessParentElements(parentElements, 'args[0].render(args[0].textArea.parent(), args[0].textArea.id)', [this]);
}
- }
- for (var button in editor.btnList) {
- if (editor.btnList.hasOwnProperty(button)) {
- editor.btnList[button][3] = null;
+ },
+ /*
+ * Initiate events monitoring
+ */
+ initEventListeners: function () {
+ // Monitor iframe becoming ready
+ this.mon(this.iframe, 'iframeready', this.onIframeReady, this, {single: true});
+ // Make the framework resizable, if configured by the user
+ this.makeResizable();
+ // Monitor textArea container becoming shown or hidden as it may change the height of the status bar
+ this.mon(this.textAreaContainer, 'show', this.onTextAreaShow, this);
+ if (this.resizable) {
+ // Monitor iframe becoming shown or hidden as it may change the height of the status bar
+ this.mon(this.iframe, 'show', this.onIframeShow, this);
}
- }
- for (var dropdown in editor.config.customSelects) {
- if (editor.config.customSelects.hasOwnProperty(dropdown)) {
- editor.config.customSelects[dropdown].action = null;
- editor.config.customSelects[dropdown].refresh = null;
+ // Monitor window resizing
+ if (this.resizable || this.textAreaInitialSize.width.indexOf('%') !== -1) {
+ Ext.EventManager.onWindowResize(this.onWindowResize, this);
}
- }
- for (var hotKey in editor.config.hotKeyList) {
- if (editor.config.customSelects.hasOwnProperty(hotKey)) {
- editor.config.hotKeyList[hotKey].action = null;
+ // If the textarea is inside a form, on reset, re-initialize the HTMLArea content and update the toolbar
+ var form = this.textArea.dom.form;
+ if (form) {
+ if (Ext.isFunction(form.onsubmit)) {
+ if (typeof(form.htmlAreaPreviousOnReset) == 'undefined') {
+ form.htmlAreaPreviousOnReset = [];
+ }
+ form.htmlAreaPreviousOnReset.push(form.onreset);
+ }
+ this.mon(Ext.get(form), 'reset', this.onReset, this);
}
+ this.addListener({
+ beforedestroy: {
+ fn: this.onBeforeDestroy
+ }
+ });
+ },
+ /*
+ * editorId should be set in config
+ */
+ editorId: null,
+ /*
+ * Get a reference to the editor
+ */
+ getEditor: function() {
+ return RTEarea[this.editorId].editor;
+ },
+ /*
+ * Flag indicating whether the framework is inside a tab or inline element that may be hidden
+ * Should be set in config
+ */
+ isNested: false,
+ /*
+ * All nested tabs and inline levels in the sorting order they were applied
+ * Should be set in config
+ */
+ nestedParentElements: {},
+ /*
+ * Flag set to true when the framework is ready
+ */
+ ready: false,
+ /*
+ * All nested tabs and inline levels in the sorting order they were applied
+ * Should be set in config
+ */
+ nestedParentElements: {},
+ /*
+ * Whether the framework should be made resizable
+ * May be set in config
+ */
+ resizable: false,
+ /*
+ * Maximum height to which the framework may resized (in pixels)
+ * May be set in config
+ */
+ maxHeight: 2000,
+ /*
+ * Initial textArea dimensions
+ * Should be set in config
+ */
+ textAreaInitialSize: {
+ width: 0,
+ contextWidth: 0,
+ height: 0
+ },
+ /*
+ * Make the framework resizable, if configured
+ */
+ makeResizable: function () {
+ if (this.resizable) {
+ this.addClass('resizable');
+ this.resizer = new Ext.Resizable(this.getEl(), {
+ minWidth: 300,
+ maxHeight: this.maxHeight,
+ dynamic: false
+ });
+ this.resizer.on('resize', this.onHtmlAreaResize, this);
+ }
+ },
+ /*
+ * Size the iframe according to initial textarea size as set by Page and User TSConfig
+ */
+ onWindowResize: function(width, height) {
+ if (!this.isNested || HTMLArea.util.TYPO3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
+ this.resizeFramework(width, height);
+ } else {
+ // Clone the array of nested tabs and inline levels instead of using a reference as HTMLArea.util.TYPO3.accessParentElements will modify the array
+ var parentElements = [].concat(this.nestedParentElements.sorted);
+ // Walk through all nested tabs and inline levels to get correct sizes
+ HTMLArea.util.TYPO3.accessParentElements(parentElements, 'args[0].resizeFramework(args[1], args[2])', [this, width, height]);
+ }
+ },
+ /*
+ * Resize the framework to its initial size
+ */
+ resizeFramework: function (width, height) {
+ var frameworkHeight = this.fullScreen ? HTMLArea.util.TYPO3.getWindowSize().height - 20 : parseInt(this.textAreaInitialSize.height);
+ if (this.textAreaInitialSize.width.indexOf('%') === -1) {
+ // Width is specified in pixels
+ var frameworkWidth = parseInt(this.textAreaInitialSize.width) - this.getFrameWidth();
+ } else {
+ // Width is specified in %
+ if (Ext.isDefined(width)) {
+ // Framework sizing on actual window resize
+ var frameworkWidth = parseInt(((width - this.textAreaInitialSize.nextSiblingWidth - (this.fullScreen ? 10 : Ext.getScrollBarWidth()) - this.getBox().x - 15) * parseInt(this.textAreaInitialSize.width))/100);
+ } else {
+ // Initial framework sizing
+ var frameworkWidth = parseInt(((HTMLArea.util.TYPO3.getWindowSize().width - this.textAreaInitialSize.nextSiblingWidth - (this.fullScreen ? 10 : Ext.getScrollBarWidth()) - this.getBox().x - 15) * parseInt(this.textAreaInitialSize.width))/100);
+ }
+ }
+ if (this.resizable) {
+ this.resizer.resizeTo(frameworkWidth, frameworkHeight);
+ } else {
+ this.setSize(frameworkWidth, frameworkHeight);
+ // Adjust height of iframe and textarea to height of toolbar and statusbar
+ this.iframe.setSize(this.getInnerWidth(), this.getInnerHeight());
+ this.textArea.setSize(this.getInnerWidth(), this.getInnerHeight());
+ }
+ },
+ /*
+ * Resize the components when the editor framework was resized
+ */
+ onHtmlAreaResize: function (resizer, width, height, event) {
+ // Set width first as it may change the height of the toolbar and of the statusBar
+ this.setWidth(width);
+ // Set height of iframe and textarea
+ this.iframe.setHeight(this.getInnerHeight());
+ this.textArea.setSize(this.getInnerWidth(), this.getInnerHeight());
+ },
+ /*
+ * Adjust the height to the changing size of the statusbar when the textarea is shown
+ */
+ onTextAreaShow: function () {
+ this.iframe.setHeight(this.getInnerHeight());
+ this.textArea.setHeight(this.getInnerHeight());
+ },
+ /*
+ * Adjust the height to the changing size of the statusbar when the iframe is shown
+ */
+ onIframeShow: function () {
+ this.iframe.setHeight(this.getInnerHeight());
+ this.textArea.setHeight(this.getInnerHeight());
+ },
+ /*
+ * Fire the editor when all components of the framework are rendered and ready
+ */
+ onIframeReady: function () {
+ this.ready = this.toolbar.rendered && this.statusBar.rendered && this.textAreaContainer.rendered;
+ if (this.ready) {
+ this.textAreaContainer.show();
+ if (!this.getEditor().config.showStatusBar) {
+ this.statusBar.hide();
+ }
+ // Set the initial size of the framework
+ this.onWindowResize();
+ this.fireEvent('frameworkready');
+ } else {
+ this.onIframeReady.defer(50, this);
+ }
+ },
+ /*
+ * Handler invoked if we are inside a form and the form is reset
+ * On reset, re-initialize the HTMLArea content and update the toolbar
+ */
+ onReset: function (event) {
+ this.getEditor().setHTML(this.textArea.getValue());
+ this.toolbar.update();
+ // Invoke previous reset handlers, if any
+ var htmlAreaPreviousOnReset = event.getTarget().dom.htmlAreaPreviousOnReset;
+ if (typeof(htmlAreaPreviousOnReset) != 'undefined') {
+ Ext.each(htmlAreaPreviousOnReset, function (onReset) {
+ onReset();
+ return true;
+ });
+ }
+ },
+ /*
+ * Cleanup on framework destruction
+ */
+ onBeforeDestroy: function () {
+ if (this.resizable) {
+ Ext.EventManager.removeResizeListener(this.onWindowResize, this);
+ }
+ var form = this.textArea.dom.form;
+ if (form) {
+ form.htmlAreaPreviousOnReset = null;
+ }
}
- editor.onGenerate = null;
- if(editor._textArea.form) {
- editor._textArea.form.__msh_prevOnReset = null;
- editor._textArea.form._editorNumber = null;
- }
-
- // cleaning plugins
- for (var plugin in editor.plugins) {
- if (editor.plugins.hasOwnProperty(plugin)) {
- var pluginInstance = editor.plugins[plugin].instance;
- if (typeof(pluginInstance.onClose) === "function") {
- pluginInstance.onClose();
+});
+Ext.reg('htmlareaframework', HTMLArea.Framework);
+/***************************************************
+ * HTMLArea.Editor extends Ext.util.Observable
+ ***************************************************/
+HTMLArea.Editor = Ext.extend(Ext.util.Observable, {
+ /*
+ * HTMLArea.Editor constructor
+ */
+ constructor: function (config) {
+ HTMLArea.Editor.superclass.constructor.call(this, {});
+ // Save the config
+ this.config = config;
+ // Establish references to this editor
+ this.editorId = this.config.editorId;
+ RTEarea[this.editorId].editor = this;
+ // Get textarea size and wizard context
+ this.textArea = Ext.get(this.config.id);
+ this.textAreaInitialSize = {
+ width: this.config.RTEWidthOverride ? this.config.RTEWidthOverride : this.textArea.getStyle('width'),
+ height: this.config.fullScreen ? HTMLArea.util.TYPO3.getWindowSize().height - 20 : this.textArea.getStyle('height'),
+ nextSiblingWidth: 0
+ };
+ // TYPO3 Inline elements and tabs
+ this.nestedParentElements = {
+ all: this.config.tceformsNested,
+ sorted: HTMLArea.util.TYPO3.simplifyNested(this.config.tceformsNested)
+ };
+ this.isNested = !Ext.isEmpty(this.nestedParentElements.sorted);
+ // Get width of wizards
+ var nextSibling = this.textArea.parent().parent().next();
+ if (nextSibling) {
+ if (!this.isNested || HTMLArea.util.TYPO3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
+ this.textAreaInitialSize.nextSiblingWidth = nextSibling.getWidth();
+ } else {
+ // Clone the array of nested tabs and inline levels instead of using a reference as HTMLArea.util.TYPO3.accessParentElements will modify the array
+ var parentElements = [].concat(this.nestedParentElements.sorted);
+ // Walk through all nested tabs and inline levels to get correct size
+ this.textAreaInitialSize.nextSiblingWidth = HTMLArea.util.TYPO3.accessParentElements(parentElements, 'args[0].getWidth()', [nextSibling]);
}
- pluginInstance.onClose = null;
- pluginInstance.onChange = null;
- pluginInstance.onButtonPress = null;
- pluginInstance.onGenerate = null;
- pluginInstance.onGenerateOnce = null;
- pluginInstance.onMode = null;
- pluginInstance.onHotKey = null;
- pluginInstance.onKeyPress = null;
- pluginInstance.onSelect = null;
- pluginInstance.onUpdateTolbar = null;
}
+ // Plugins register
+ this.plugins = {};
+ // Register the plugins included in the configuration
+ Ext.iterate(this.config.plugin, function (plugin) {
+ if (this.config.plugin[plugin]) {
+ this.registerPlugin(plugin);
+ }
+ }, this);
+ this.addEvents(
+ /*
+ * @event editorready
+ * Fires when initializatio of the editor is complete
+ */
+ 'editorready',
+ /*
+ * @event modeChange
+ * Fires when the editor changes mode
+ */
+ 'modeChange'
+ );
+ },
+ /*
+ * Flag set to true when the editor initialization has completed
+ */
+ ready: false,
+ /*
+ * The current mode of the editor: 'wysiwyg' or 'textmode'
+ */
+ mode: 'textmode',
+ /*
+ * Create the htmlArea framework
+ */
+ generate: function () {
+ // Create the editor framework
+ this.htmlArea = new HTMLArea.Framework({
+ id: this.editorId + '-htmlArea',
+ layout: 'anchor',
+ baseCls: 'htmlarea',
+ editorId: this.editorId,
+ textArea: this.textArea,
+ textAreaInitialSize: this.textAreaInitialSize,
+ fullScreen: this.config.fullScreen,
+ resizable: this.config.resizable,
+ maxHeight: this.config.maxHeight,
+ isNested: this.isNested,
+ nestedParentElements: this.nestedParentElements,
+ // The toolbar
+ tbar: {
+ xtype: 'htmlareatoolbar',
+ id: this.editorId + '-toolbar',
+ anchor: '100%',
+ layout: 'form',
+ cls: 'toolbar',
+ editorId: this.editorId
+ },
+ items: [{
+ // The iframe
+ xtype: 'htmlareaiframe',
+ itemId: 'iframe',
+ anchor: '100%',
+ width: (this.textAreaInitialSize.width.indexOf('%') === -1) ? parseInt(this.textAreaInitialSize.width) : 300,
+ height: parseInt(this.textAreaInitialSize.height),
+ autoEl: {
+ id: this.editorId + '-iframe',
+ tag: 'iframe',
+ cls: 'editorIframe',
+ src: Ext.isGecko ? 'javascript:void(0);' : (Ext.isOpera ? _typo3_host_url : '') + _editor_url + 'popups/blank.html'
+ },
+ isNested: this.isNested,
+ nestedParentElements: this.nestedParentElements,
+ editorId: this.editorId
+ },{
+ // Box container for the textarea
+ xtype: 'box',
+ itemId: 'textAreaContainer',
+ anchor: '100%',
+ width: (this.textAreaInitialSize.width.indexOf('%') === -1) ? parseInt(this.textAreaInitialSize.width) : 300,
+ // Let the framework swallow the textarea
+ listeners: {
+ afterRender: {
+ fn: function (textAreaContainer) { textAreaContainer.getEl().appendChild(this.textArea); },
+ single: true,
+ scope: this
+ }
+ }
+ }
+ ],
+ // The status bar
+ bbar: {
+ xtype: 'htmlareastatusbar',
+ anchor: '100%',
+ cls: 'statusBar',
+ editorId: this.editorId
+ }
+ });
+ // Set some references
+ this.toolbar = this.htmlArea.getTopToolbar();
+ this.statusBar = this.htmlArea.getBottomToolbar();
+ this.iframe = this.htmlArea.getComponent('iframe');
+ this.textAreaContainer = this.htmlArea.getComponent('textAreaContainer');
+ // Get triggered when the framework becomes ready
+ this.relayEvents(this.htmlArea, 'frameworkready');
+ this.on('frameworkready', this.onFrameworkReady, this, {single: true});
+ },
+ /*
+ * Initialize the editor
+ */
+ onFrameworkReady: function () {
+ // Initialize editor mode
+ this.setMode('wysiwyg');
+ // Initiate events listening
+ this.initEventsListening();
+ // Generate plugins
+ this.generatePlugins();
+ // Make the editor visible
+ this.show();
+ // Focus on the first editor that is not hidden
+ Ext.iterate(RTEarea, function (editorId, RTE) {
+ if (!Ext.isDefined(RTE.editor) || (RTE.editor.isNested && !HTMLArea.util.TYPO3.allElementsAreDisplayed(RTE.editor.nestedParentElements.sorted))) {
+ return true;
+ } else {
+ RTE.editor.focus();
+ return false;
+ }
+ }, this);
+ this.ready = true;
+ this.fireEvent('editorready');
+ HTMLArea._appendToLog('[HTMLArea.Editor::start]: Editor ready.');
+ },
+ /*
+ * Set editor mode
+ *
+ * @param string mode: 'textmode' or 'wysiwyg'
+ *
+ * @return void
+ */
+ setMode: function (mode) {
+ switch (mode) {
+ case 'textmode':
+ this.textArea.set({ value: this.getHTML() }, false);
+ this.iframe.setDesignMode(false);
+ this.iframe.hide();
+ this.textAreaContainer.show();
+ this.mode = mode;
+ break;
+ case 'wysiwyg':
+ try {
+ this.document.body.innerHTML = this.getHTML();
+ } catch(e) {
+ HTMLArea._appendToLog('[HTMLArea.Editor::setMode]: The HTML document is not well-formed.');
+ alert(HTMLArea.I18N.msg['HTML-document-not-well-formed']);
+ break;
+ }
+ this.textAreaContainer.hide();
+ this.iframe.show();
+ this.iframe.setDesignMode(true);
+ this.mode = mode;
+ break;
+ }
+ this.fireEvent('modeChange', this.mode);
+ this.focus();
+ Ext.iterate(this.plugins, function(pluginId) {
+ this.getPlugin(pluginId).onMode(this.mode);
+ }, this);
+ },
+ /*
+ * Get current editor mode
+ */
+ getMode: function () {
+ return this.mode;
+ },
+ /*
+ * 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.mode) {
+ case 'wysiwyg':
+ return this.iframe.getHTML();
+ case 'textmode':
+ return this.textArea.getValue();
+ default:
+ return '';
+ }
+ },
+ /*
+ * Retrieve raw HTML
+ *
+ * @return string the textual html content from the current editing mode
+ */
+ getInnerHTML: function () {
+ switch (this.mode) {
+ case 'wysiwyg':
+ return this.document.body.innerHTML;
+ case 'textmode':
+ return this.textArea.getValue();
+ default:
+ return '';
+ }
+ },
+ /*
+ * Replace the html content
+ *
+ * @param string html: the textual html
+ *
+ * @return void
+ */
+ setHTML: function (html) {
+ switch (this.mode) {
+ case 'wysiwyg':
+ this.document.body.innerHTML = html;
+ break;
+ case 'textmode':
+ this.textArea.set({ value: html }, false);;
+ break;
+ }
+ },
+ /*
+ * Generate registered plugins
+ */
+ generatePlugins: function () {
+ this.hasPluginWithOnKeyPressHandler = false;
+ Ext.iterate(this.plugins, function (pluginId) {
+ var plugin = this.getPlugin(pluginId);
+ plugin.onGenerate();
+ // onKeyPress deprecated as of TYPO3 4.4
+ if (Ext.isFunction(plugin.onKeyPress)) {
+ this.hasPluginWithOnKeyPressHandler = true;
+ HTMLArea._appendToLog('[HTMLArea.Editor::generatePlugins]: Deprecated use of onKeyPress function by plugin ' + pluginId + '. Use keyMap instead.');
+ }
+ }, this);
+ HTMLArea._appendToLog('[HTMLArea.Editor::generatePlugins]: All plugins successfully generated.');
+ },
+ /*
+ * Get the instance of the specified plugin, if it exists
+ *
+ * @param string pluginName: the name of the plugin
+ * @return object the plugin instance or null
+ */
+ getPlugin: function(pluginName) {
+ return (this.plugins[pluginName] ? this.plugins[pluginName].instance : null);
+ },
+ /*
+ * Focus on the editor
+ */
+ focus: function () {
+ switch (this.getMode()) {
+ case 'wysiwyg':
+ this.iframe.focus();
+ break;
+ case 'textmode':
+ this.textArea.focus();
+ break;
+ }
+ },
+ /*
+ * Add listeners
+ */
+ initEventsListening: function () {
+ if (Ext.isOpera) {
+ this.iframe.startListening();
+ }
+ // Add unload handler
+ var iframe = this.iframe.getEl().dom;
+ Ext.EventManager.on(iframe.contentWindow ? iframe.contentWindow : iframe.contentDocument, 'unload', this.onUnload, this, {single: true});
+ },
+ /*
+ * Make the editor framework visible
+ */
+ show: function () {
+ document.getElementById('pleasewait' + this.editorId).style.display = 'none';
+ document.getElementById('editorWrap' + this.editorId).style.visibility = 'visible';
+ },
+ /*
+ * Iframe unload handler: Update the textarea for submission and cleanup
+ */
+ onUnload: function (event) {;
+ // Save the HTML content into the original textarea for submit, back/forward, etc.
+ if (this.ready) {
+ this.textArea.set({
+ value: this.getHTML()
+ }, false);
+ }
+ // Cleanup
+ Ext.TaskMgr.stopAll();
+ this.htmlArea.destroy();
+ RTEarea[this.editorId].editor = null;
}
- // cleaning the toolbar elements
- for (var txt in editor._toolbarObjects) {
- if (editor._toolbarObjects.hasOwnProperty(txt)) {
- var obj = editor._toolbarObjects[txt];
- obj.state = null;
- obj.cmd = null;
- var element = document.getElementById(obj.elementId);
- if (element) {
- element._obj = null;
+});
+/***************************************************
+ * HTMLArea.util.TYPO3: Utility functions for dealing with tabs and inline elements in TYPO3 forms
+ ***************************************************/
+HTMLArea.util.TYPO3 = function () {
+ return {
+ /*
+ * 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
+ */
+ 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]);
+ }
+ for (i=0, max=nested.length; i
+ */
+ accessParentElements: function (parentElements, callbackFunc, args) {
+ 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 = '';
+ }
+ result = this.accessParentElements(parentElements, callbackFunc, args);
+ if (actionRequired) {
+ elementStyle.display = 'none';
+ elementStyle.position = originalPosition;
+ elementStyle.visibility = originalVisibility;
+ }
+ } else {
+ result = eval(callbackFunc);
+ }
+ return result;
+ },
+ /*
+ * Check if all elements in input array are currently displayed
+ *
+ * @param array elements: array of element id's
+ * @return boolean true if all elements are displayed
+ */
+ allElementsAreDisplayed: function(elements) {
+ var allDisplayed = true;
+ Ext.each(elements, function (element) {
+ allDisplayed = Ext.get(element).getStyle('display') != 'none';
+ return allDisplayed;
+ });
+ return allDisplayed;
+ },
+ /*
+ * Get current size of window
+ *
+ * @return object width and height of window
+ */
+ getWindowSize: function () {
+ if (Ext.isIE) {
+ var size = Ext.getBody().getSize();
+ } else {
+ var size = {
+ width: window.innerWidth,
+ height: window.innerHeight
+ };
+ }
+ // Subtract the docheader height from the calculated window height
+ var docHeader = Ext.get('typo3-docheader');
+ if (docHeader) {
+ size.height -= docHeader.getHeight();
+ }
+ return size;
}
}
- // final cleanup
- editor._toolbar = null;
- editor._htmlArea = null;
- editor._iframe = null;
-};
-
-/*
- * Get editor mode
- */
-HTMLArea.prototype.getMode = function() {
- return this.getPluginInstance("EditorMode").getEditorMode();
-};
-
-/*
- * Initialize iframe content when in full page mode
- */
-HTMLArea.prototype.setFullHTML = function(html) {
- var save_multiline = RegExp.multiline;
- RegExp.multiline = true;
- if(html.match(HTMLArea.RE_doctype)) {
- this.setDoctype(RegExp.$1);
- html = html.replace(HTMLArea.RE_doctype, "");
- };
- RegExp.multiline = save_multiline;
- if(!HTMLArea.is_ie) {
- if(html.match(HTMLArea.RE_head)) this._doc.getElementsByTagName("head")[0].innerHTML = RegExp.$1;
- if(html.match(HTMLArea.RE_body)) this._doc.getElementsByTagName("body")[0].innerHTML = RegExp.$1;
- } else {
- var html_re = /((.|\n)*?)<\/html>/i;
- html = html.replace(html_re, "$1");
- this._doc.open();
- this._doc.write(html);
- this._doc.close();
- this._doc.body.contentEditable = true;
- return true;
- };
-};
-
+}();
/***************************************************
* PLUGINS, STYLESHEETS, AND IMAGE AND POPUP URL'S
***************************************************/
-
/*
* Instantiate the specified plugin and register it with the editor
*
@@ -1398,7 +2314,7 @@
*
* @return boolean true if the plugin was successfully registered
*/
-HTMLArea.prototype.registerPlugin = function(plugin) {
+HTMLArea.Editor.prototype.registerPlugin = function(plugin) {
var pluginName = plugin;
if (typeof(plugin) === "string") {
try {
@@ -1429,16 +2345,6 @@
};
/*
- * Get the instance of the specified plugin, if it exists
- *
- * @param string pluginName: the name of the plugin
- * @return object the plugin instance or null
- */
-HTMLArea.prototype.getPluginInstance = function(pluginName) {
- return (this.plugins[pluginName] ? this.plugins[pluginName].instance : null);
-};
-
-/*
* Load the required plugin script
*/
HTMLArea.loadPlugin = function (pluginName, url, asynchronous) {
@@ -1468,7 +2374,7 @@
/*
* Get the url of some image
*/
-HTMLArea.prototype.imgURL = function(file, plugin) {
+HTMLArea.Editor.prototype.imgURL = function(file, plugin) {
if (typeof(plugin) == "undefined") return _editor_skin + this.config.imgURL + file;
else return _editor_skin + this.config.imgURL + plugin + "/" + file;
};
@@ -1476,7 +2382,7 @@
/*
* Get the url of some popup
*/
-HTMLArea.prototype.popupURL = function(file) {
+HTMLArea.Editor.prototype.popupURL = function(file) {
var url = "";
if(file.match(/^plugin:\/\/(.*?)\/(.*)/)) {
var pluginId = RegExp.$1;
@@ -1509,36 +2415,22 @@
return txt;
};
-HTMLArea.prototype.forceRedraw = function() {
- this._doc.body.style.visibility = "hidden";
- this._doc.body.style.visibility = "visible";
+HTMLArea.Editor.prototype.forceRedraw = function() {
+ this.htmlArea.doLayout();
};
/*
- * Focus the editor iframe document or the textarea.
+ * Focus the editor iframe window or the textarea.
*/
-HTMLArea.prototype.focusEditor = function() {
- switch (this.getMode()) {
- case "wysiwyg" :
- try {
- if (HTMLArea.is_safari) {
- this._iframe.focus();
- } else {
- this._iframe.contentWindow.focus();
- }
- } catch(e) { }
- break;
- case "textmode":
- this._textArea.focus();
- break;
- }
- return this._doc;
+HTMLArea.Editor.prototype.focusEditor = function() {
+ this.focus();
+ return this.document;
};
/*
* Check if any plugin has an opened window
*/
-HTMLArea.prototype.hasOpenedWindow = function () {
+HTMLArea.Editor.prototype.hasOpenedWindow = function () {
for (var plugin in this.plugins) {
if (this.plugins.hasOwnProperty(plugin)) {
if (HTMLArea.Dialog[plugin.name] && HTMLArea.Dialog[plugin.name].hasOpenedWindow && HTMLArea.Dialog[plugin.name].hasOpenedWindow()) {
@@ -1548,111 +2440,9 @@
}
return false
};
-
-/*
- * Update the enabled/disabled/active state of the toolbar elements
- */
-HTMLArea.updateToolbar = function(editorNumber) {
- var editor = RTEarea[editorNumber]["editor"];
- editor.updateToolbar();
- editor._timerToolbar = null;
+HTMLArea.Editor.prototype.updateToolbar = function(noStatus) {
+ this.toolbar.update(noStatus);
};
-
-HTMLArea.prototype.updateToolbar = function(noStatus) {
- var doc = this._doc,
- initialToolbarHeight = this.getDimensions().toolbar.height,
- text = (this.getMode() == "textmode"),
- selection = false,
- ancestors = null,
- inContext, match, matchAny, k, j, n, commandState;
- if (!text) {
- selection = !this._selectionEmpty(this._getSelection());
- ancestors = this.getAllAncestors();
- }
- for (var cmd in this._toolbarObjects) {
- if (this._toolbarObjects.hasOwnProperty(cmd)) {
- var btn = this._toolbarObjects[cmd];
- // Determine if the button should be enabled
- inContext = true;
- if (btn.context && !text) {
- inContext = false;
- var attrs = [];
- var contexts = [];
- if (/(.*)\[(.*?)\]/.test(btn.context)) {
- contexts = RegExp.$1.split(",");
- attrs = RegExp.$2.split(",");
- } else {
- contexts = btn.context.split(",");
- }
- for (j = contexts.length; --j >= 0;) contexts[j] = contexts[j].toLowerCase();
- matchAny = (contexts[0] == "*");
- for (k = 0; k < ancestors.length; ++k) {
- if (!ancestors[k]) continue;
- match = false;
- for (j = contexts.length; --j >= 0;) match = match || (ancestors[k].tagName.toLowerCase() == contexts[j]);
- if (matchAny || match) {
- inContext = true;
- for (j = attrs.length; --j >= 0;) {
- if (!eval("ancestors[k]." + attrs[j])) {
- inContext = false;
- break;
- }
- }
- if (inContext) break;
- }
- }
- }
-
- if (cmd == "CreateLink") {
- btn.state("enabled", (!text || btn.text) && (inContext || selection));
- } else {
- btn.state("enabled", (!text || btn.text) && inContext && (selection || !btn.selection));
- }
- if (typeof(cmd) == "function") { continue; };
- // look-it-up in the custom dropdown boxes
- var dropdown = this.config.customSelects[cmd];
- if ((!text || btn.text) && (typeof(dropdown) !== "undefined") && (typeof(dropdown.refresh) === "function")) {
- dropdown.refresh(this, cmd);
- continue;
- }
- switch (cmd) {
- case "TextIndicator":
- if(!text) {
- try {with (document.getElementById(btn.elementId).style) {
- backgroundColor = HTMLArea._makeColor(doc.queryCommandValue((HTMLArea.is_ie || HTMLArea.is_safari) ? "BackColor" : "HiliteColor"));
- // Mozilla
- if(/transparent/i.test(backgroundColor)) { backgroundColor = HTMLArea._makeColor(doc.queryCommandValue("BackColor")); }
- color = HTMLArea._makeColor(doc.queryCommandValue("ForeColor"));
- fontFamily = doc.queryCommandValue("FontName");
- // Check if queryCommandState is available
- fontWeight = "normal";
- fontStyle = "normal";
- try { fontWeight = doc.queryCommandState("Bold") ? "bold" : "normal"; } catch(ex) { fontWeight = "normal"; };
- try { fontStyle = doc.queryCommandState("Italic") ? "italic" : "normal"; } catch(ex) { fontStyle = "normal"; };
- }} catch (e) {
- // alert(e + "\n\n" + cmd);
- }
- }
- break;
- default:
- break;
- }
- }
- }
-
- for (var pluginId in this.plugins) {
- if (this.plugins.hasOwnProperty(pluginId)) {
- var pluginInstance = this.plugins[pluginId].instance;
- if (typeof(pluginInstance.onUpdateToolbar) === "function") {
- pluginInstance.onUpdateToolbar();
- }
- }
- }
- if (this.getDimensions().toolbar.height != initialToolbarHeight) {
- this.sizeIframe(2);
- }
-};
-
/***************************************************
* DOM TREE MANIPULATION
***************************************************/
@@ -1661,15 +2451,15 @@
* Surround the currently selected HTML source code with the given tags.
* Delete the selection, if any.
*/
-HTMLArea.prototype.surroundHTML = function(startTag,endTag) {
+HTMLArea.Editor.prototype.surroundHTML = function(startTag,endTag) {
this.insertHTML(startTag + this.getSelectedHTML().replace(HTMLArea.Reg_body, "") + endTag);
};
/*
* Change the tag name of a node.
*/
-HTMLArea.prototype.convertNode = function(el,newTagName) {
- var newel = this._doc.createElement(newTagName), p = el.parentNode;
+HTMLArea.Editor.prototype.convertNode = function(el,newTagName) {
+ var newel = this.document.createElement(newTagName), p = el.parentNode;
while (el.firstChild) newel.appendChild(el.firstChild);
p.insertBefore(newel, el);
p.removeChild(el);
@@ -1692,7 +2482,7 @@
*
* @return void
*/
-HTMLArea.prototype.removeMarkup = function(element) {
+HTMLArea.Editor.prototype.removeMarkup = function(element) {
var bookmark = this.getBookmark(this._createRange(this._getSelection()));
var parent = element.parentNode;
while (element.firstChild) {
@@ -1732,28 +2522,28 @@
/*
* Return true if we have some selected content
*/
-HTMLArea.prototype.hasSelectedText = function() {
+HTMLArea.Editor.prototype.hasSelectedText = function() {
return this.getSelectedHTML() != "";
};
/*
* Get an array with all the ancestor nodes of the selection.
*/
-HTMLArea.prototype.getAllAncestors = function() {
+HTMLArea.Editor.prototype.getAllAncestors = function() {
var p = this.getParentElement();
var a = [];
while (p && (p.nodeType === 1) && (p.nodeName.toLowerCase() !== "body")) {
a.push(p);
p = p.parentNode;
}
- a.push(this._doc.body);
+ a.push(this.document.body);
return a;
};
/*
* Get the block ancestors of an element within a given block
*/
-HTMLArea.prototype.getBlockAncestors = function(element, withinBlock) {
+HTMLArea.Editor.prototype.getBlockAncestors = function(element, withinBlock) {
var ancestors = new Array();
var ancestor = element;
while (ancestor && (ancestor.nodeType === 1) && !/^(body)$/i.test(ancestor.nodeName) && ancestor != withinBlock) {
@@ -1769,9 +2559,9 @@
/*
* Get the block elements containing the start and the end points of the selection
*/
-HTMLArea.prototype.getEndBlocks = function(selection) {
+HTMLArea.Editor.prototype.getEndBlocks = function(selection) {
var range = this._createRange(selection);
- if (HTMLArea.is_gecko) {
+ if (!Ext.isIE) {
var parentStart = range.startContainer;
var parentEnd = range.endContainer;
} else {
@@ -1802,7 +2592,7 @@
*
* @return boolean true if the end points of the current selection are inside the same block element
*/
-HTMLArea.prototype.endPointsInSameBlock = function() {
+HTMLArea.Editor.prototype.endPointsInSameBlock = function() {
var selection = this._getSelection();
if (this._selectionEmpty(selection)) {
return true;
@@ -1817,11 +2607,11 @@
* Get the deepest ancestor of the selection that is of the specified type
* Borrowed from Xinha (is not htmlArea) - http://xinha.gogo.co.nz/
*/
-HTMLArea.prototype._getFirstAncestor = function(sel,types) {
+HTMLArea.Editor.prototype._getFirstAncestor = function(sel,types) {
var prnt = this._activeElement(sel);
if (prnt == null) {
try {
- prnt = (HTMLArea.is_ie ? this._createRange(sel).parentElement() : this._createRange(sel).commonAncestorContainer);
+ prnt = (Ext.isIE ? this._createRange(sel).parentElement() : this._createRange(sel).commonAncestorContainer);
} catch(e) {
return null;
}
@@ -1847,208 +2637,34 @@
***************************************************/
/*
- * Intercept some commands and replace them with our own implementation
+ * Intercept some native execCommand commands
*/
-HTMLArea.prototype.execCommand = function(cmdID, UI, param) {
- this.focusEditor();
+HTMLArea.Editor.prototype.execCommand = function(cmdID, UI, param) {
+ this.focus();
switch (cmdID) {
default:
try {
- this._doc.execCommand(cmdID, UI, param);
+ this.document.execCommand(cmdID, UI, param);
} catch(e) {
if (this.config.debug) alert(e + "\n\nby execCommand(" + cmdID + ");");
}
}
- this.updateToolbar();
+ this.toolbar.update();
return false;
};
-/*
-* A generic event handler for things that happen in the IFRAME's document.
-*/
-HTMLArea._editorEvent = 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"];
- var keyEvent = ((HTMLArea.is_ie || HTMLArea.is_safari) && ev.type == "keydown") || (HTMLArea.is_gecko && ev.type == "keypress");
- var mouseEvent = (ev.type == "mousedown" || ev.type == "mouseup");
- editor.focusEditor();
-
- if(keyEvent) {
- // In Opera, inhibit key events while synchronous XMLHttpRequest is being processed
- if (HTMLArea.is_opera && HTMLArea.pendingSynchronousXMLHttpRequest) {
- HTMLArea._stopEvent(ev);
- return false;
- }
- if (editor._hasPluginWithOnKeyPressHandler) {
- for (var pluginId in editor.plugins) {
- if (editor.plugins.hasOwnProperty(pluginId)) {
- var pluginInstance = editor.plugins[pluginId].instance;
- if (typeof(pluginInstance.onKeyPress) === "function") {
- if (!pluginInstance.onKeyPress(ev)) {
- HTMLArea._stopEvent(ev);
- return false;
- }
- }
- }
- }
- }
- if (ev.ctrlKey && !ev.shiftKey) {
- if (!ev.altKey) {
- // Execute hotkey command
- var key = String.fromCharCode((HTMLArea.is_ie || HTMLArea.is_safari || HTMLArea.is_opera) ? ev.keyCode : ev.charCode).toLowerCase();
- if (key == " " || ev.keyCode == 32) {
- editor.insertHTML(" ");
- editor.updateToolbar();
- HTMLArea._stopEvent(ev);
- return false;
- }
- if (!editor.config.hotKeyList[key]) return true;
- var cmd = editor.config.hotKeyList[key].cmd;
- if (!cmd) return true;
- switch (cmd) {
- case "SelectAll":
- cmd = editor.config.hotKeyList[key].cmd;
- editor.execCommand(cmd, false, null);
- HTMLArea._stopEvent(ev);
- return false;
- break;
- default:
- if (editor.config.hotKeyList[key] && editor.config.hotKeyList[key].action) {
- if (!editor.config.hotKeyList[key].action(editor, key)) {
- HTMLArea._stopEvent(ev);
- return false;
- }
- }
- }
- return true;
- }
- } else if (ev.altKey) {
- // check if context menu is already handling this event
- if(editor.plugins["ContextMenu"] && editor.plugins["ContextMenu"].instance) {
- var keys = editor.plugins["ContextMenu"].instance.keys;
- if (keys.length > 0) {
- var k;
- for (var i = keys.length; --i >= 0;) {
- k = keys[i];
- if (k[0].toLowerCase() == key) {
- HTMLArea._stopEvent(ev);
- return false;
- }
- }
- }
- }
- return true;
- } else if (keyEvent) {
- if (HTMLArea.is_gecko) editor._detectURL(ev);
- switch (ev.keyCode) {
- case 13 : // KEY enter
- if (HTMLArea.is_gecko) {
- if (!ev.shiftKey && !editor.config.disableEnterParagraphs) {
- if (editor._checkInsertP()) {
- HTMLArea._stopEvent(ev);
- }
- } else if (HTMLArea.is_safari) {
- var brNode = editor._doc.createElement("br");
- editor.insertNodeAtSelection(brNode);
- if (!brNode.nextSibling || !HTMLArea.getInnerText(brNode.nextSibling)) {
- var secondBrNode = editor._doc.createElement("br");
- secondBrNode = brNode.parentNode.appendChild(secondBrNode);
- editor.selectNode(secondBrNode, false);
- }
- HTMLArea._stopEvent(ev);
- }
- // update the toolbar state after some time
- if (editor._timerToolbar) window.clearTimeout(editor._timerToolbar);
- editor._timerToolbar = window.setTimeout("HTMLArea.updateToolbar(\'" + editor._editorNumber + "\');", 200);
- return false;
- }
- break;
- case 8 : // KEY backspace
- case 46 : // KEY delete
- if ((HTMLArea.is_gecko && !ev.shiftKey) || HTMLArea.is_ie) {
- if (editor._checkBackspace()) HTMLArea._stopEvent(ev);
- }
- // update the toolbar state after some time
- if (editor._timerToolbar) window.clearTimeout(editor._timerToolbar);
- editor._timerToolbar = window.setTimeout("HTMLArea.updateToolbar(\'" + editor._editorNumber + "\');", 200);
- break;
- case 9: // KEY horizontal tab
- var newkey = (ev.shiftKey ? "SHIFT-" : "") + "TAB";
- if (editor.config.hotKeyList[newkey] && editor.config.hotKeyList[newkey].action) {
- if (!editor.config.hotKeyList[newkey].action(editor, newkey)) {
- HTMLArea._stopEvent(ev);
- return false;
- }
- }
- break;
- case 37: // LEFT arrow key
- case 38: // UP arrow key
- case 39: // RIGHT arrow key
- case 40: // DOWN arrow key
- if (HTMLArea.is_ie || HTMLArea.is_safari) {
- if (editor._timerToolbar) window.clearTimeout(editor._timerToolbar);
- editor._timerToolbar = window.setTimeout("HTMLArea.updateToolbar(\'" + editor._editorNumber + "\');", 200);
- return true;
- }
- break;
- default:
- break;
- }
- switch (ev.charCode) {
- case 160:
- // Handle option+SPACE for Mac users
- if (navigator.platform.indexOf("Mac") != -1) {
- editor.insertHTML(" ");
- editor.updateToolbar();
- HTMLArea._stopEvent(ev);
- return false;
- }
- break;
- default:
- break;
- }
- return true;
- }
- } else if (mouseEvent) {
- // mouse event
- if (editor._timerToolbar) window.clearTimeout(editor._timerToolbar);
- if (ev.type == "mouseup") editor.updateToolbar();
- else editor._timerToolbar = window.setTimeout("HTMLArea.updateToolbar(\'" + editor._editorNumber + "\');", 50);
- }
-};
-
-HTMLArea.prototype.scrollToCaret = function() {
- if (HTMLArea.is_gecko) {
+HTMLArea.Editor.prototype.scrollToCaret = function() {
+ if (!Ext.isIE) {
var e = this.getParentElement(),
w = this._iframe.contentWindow ? this._iframe.contentWindow : window,
h = w.innerHeight || w.height,
- d = this._doc,
+ d = this.document,
t = d.documentElement.scrollTop || d.body.scrollTop;
if (e.offsetTop > h+t || e.offsetTop < t) {
this.getParentElement().scrollIntoView();
}
}
};
-
-/*
- * Get the html content of the current editing mode
- */
-HTMLArea.prototype.getHTML = function() {
- return this.getPluginInstance("EditorMode").getHTML();
-};
-
-/*
- * Set the given doctype when config.fullPage is true
- */
-HTMLArea.prototype.setDoctype = function(doctype) {
- this.doctype = doctype;
-};
-
/***************************************************
* UTILITY FUNCTIONS
***************************************************/
@@ -2060,118 +2676,10 @@
* Check if the client agent is supported
*/
HTMLArea.checkSupportedBrowser = function() {
- if(HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
- if(navigator.productSub < 20030210) return false;
- }
- return HTMLArea.is_gecko || HTMLArea.is_ie;
+ return Ext.isGecko || Ext.isWebKit || Ext.isOpera || Ext.isIE;
};
-/* EventCache Version 1.0
- * Copyright 2005 Mark Wubben
- * Adaptation by Stanislas Rolland
- * Provides a way for automatically removing events from nodes and thus preventing memory leakage.
- * See for more information.
- * This software is licensed under the CC-GNU LGPL
- * Event Cache uses an anonymous function to create a hidden scope chain. This is to prevent scoping issues.
- */
-HTMLArea._eventCacheConstructor = function() {
- var listEvents = [];
-
- return ({
- listEvents : listEvents,
-
- add : function(node, sEventName, fHandler) {
- listEvents.push(arguments);
- },
-
- flush : function() {
- var item;
- for (var i = listEvents.length; --i >= 0;) {
- item = listEvents[i];
- try {
- HTMLArea._removeEvent(item[0], item[1], item[2]);
- item[0][item[1]] = null;
- item[0] = null;
- item[2] = null;
- } catch(e) { }
- }
- listEvents.length = 0;
- }
- });
-};
-
/*
- * Register an event
- */
-HTMLArea._addEvent = function(el,evname,func,useCapture) {
- if (typeof(useCapture) == "undefined") {
- var useCapture = false;
- }
- if (HTMLArea.is_gecko) {
- el.addEventListener(evname, func, !HTMLArea.is_opera || useCapture);
- } else {
- el.attachEvent("on" + evname, func);
- }
- HTMLArea._eventCache.add(el, evname, func);
-};
-
-/*
- * Register a list of events
- */
-HTMLArea._addEvents = function(el,evs,func,useCapture) {
- if (typeof(useCapture) == "undefined") {
- var useCapture = false;
- }
- for (var i = evs.length; --i >= 0;) {
- HTMLArea._addEvent(el,evs[i], func, useCapture);
- }
-};
-
-/*
- * Remove an event listener
- */
-HTMLArea._removeEvent = function(el,evname,func) {
- if (HTMLArea.is_gecko) {
- // Avoid Safari crash when removing events on some orphan documents
- if (!HTMLArea.is_safari || HTMLArea.is_chrome) {
- try {
- el.removeEventListener(evname, func, true);
- el.removeEventListener(evname, func, false);
- } catch(e) { }
- } else if (el.nodeType != 9 || el.defaultView) {
- try {
- el.removeEventListener(evname, func, true);
- el.removeEventListener(evname, func, false);
- } catch(e) { }
- }
- } else {
- try {
- el.detachEvent("on" + evname, func);
- } catch(e) { }
- }
-};
-
-/*
- * Remove a list of events
- */
-HTMLArea._removeEvents = function(el,evs,func) {
- for (var i = evs.length; --i >= 0;) { HTMLArea._removeEvent(el, evs[i], func); }
-};
-
-/*
- * Stop event propagation
- */
-HTMLArea._stopEvent = function(ev) {
- if(HTMLArea.is_gecko) {
- ev.stopPropagation();
- ev.preventDefault();
- } else {
- ev.cancelBubble = true;
- ev.returnValue = false;
- }
-};
-
-/*
* Remove a class name from the class attribute of an element
*
* @param object el: the element
@@ -2193,9 +2701,9 @@
}
}
if (newClasses.length == 0) {
- if (!HTMLArea.is_opera) {
+ if (!Ext.isOpera) {
el.removeAttribute("class");
- if (HTMLArea.is_ie) {
+ if (Ext.isIE) {
el.removeAttribute("className");
}
} else {
@@ -2240,22 +2748,6 @@
return false;
};
-/*
- * Select a value in a select element
- *
- * @param object select: the select object
- * @param string value: the value
- * @return void
- */
-HTMLArea.selectValue = function(select, value) {
- var options = select.getElementsByTagName("option");
- for (var i = options.length; --i >= 0;) {
- var option = options[i];
- option.selected = (option.value == value);
- select.selectedIndex = i;
- }
-};
-
HTMLArea.RE_blockTags = /^(body|p|h1|h2|h3|h4|h5|h6|ul|ol|pre|dl|dt|dd|div|noscript|blockquote|form|hr|table|caption|fieldset|address|td|tr|th|li|tbody|thead|tfoot|iframe)$/;
HTMLArea.isBlockElement = function(el) { return el && el.nodeType == 1 && HTMLArea.RE_blockTags.test(el.nodeName.toLowerCase()); };
HTMLArea.RE_closingTags = /^(p|blockquote|a|li|ol|ul|dl|dt|td|th|tr|tbody|thead|tfoot|caption|colgroup|table|div|b|bdo|big|cite|code|del|dfn|em|i|ins|kbd|label|q|samp|small|span|strike|strong|sub|sup|tt|u|var|abbr|acronym|font|center|object|embed|style|script|title|head)$/;
@@ -2295,7 +2787,7 @@
HTMLArea._appendToLog("The HTML document is not well-formed.");
if(!HTMLArea._debugMode) alert(HTMLArea.I18N.msg["HTML-document-not-well-formed"]);
else return HTMLArea.getHTMLWrapper(root,outputRoot,editor);
- return editor._doc.body.innerHTML;
+ return editor.document.body.innerHTML;
}
};
@@ -2315,19 +2807,8 @@
if (config.htmlRemoveTagsAndContents && config.htmlRemoveTagsAndContents.test(root_tag)) break;
var custom_tag = (config.customTags && config.customTags.test(root_tag));
if (outputRoot) outputRoot = !(config.htmlRemoveTags && config.htmlRemoveTags.test(root_tag));
- if ((HTMLArea.is_ie || HTMLArea.is_safari) && root_tag == "head") {
- if(outputRoot) html += "";
- var save_multiline = RegExp.multiline;
- RegExp.multiline = true;
- var txt = root.innerHTML.replace(HTMLArea.RE_tagName, function(str, p1, p2) {
- return p1 + p2.toLowerCase();
- });
- RegExp.multiline = save_multiline;
- html += txt;
- if(outputRoot) html += "";
- break;
- } else if (outputRoot) {
- if (HTMLArea.is_gecko && root.hasAttribute('_moz_editor_bogus_node')) break;
+ if (outputRoot) {
+ if (Ext.isGecko && root.hasAttribute('_moz_editor_bogus_node')) break;
closed = (!(root.hasChildNodes() || HTMLArea.needsClosingTag(root) || custom_tag));
html = "<" + root_tag;
var a, name, value, attrs = root.attributes;
@@ -2336,14 +2817,14 @@
a = attrs.item(i);
name = a.nodeName.toLowerCase();
if ((!a.specified && name != 'value') || /_moz|contenteditable|_msh|complete/.test(name)) continue;
- if (!HTMLArea.is_ie || name != "style") {
+ if (!Ext.isIE || name != "style") {
// IE5.5 reports wrong values. For this reason we extract the values directly from the root node.
// Using Gecko the values of href and src are converted to absolute links unless we get them using nodeValue()
if (typeof(root[a.nodeName]) != "undefined" && name != "href" && name != "src" && name != "style" && !/^on/.test(name)) {
value = root[a.nodeName];
} else {
value = a.nodeValue;
- if (HTMLArea.is_ie && (name == "href" || name == "src") && editor.plugins.link && editor.plugins.link.instance && editor.plugins.link.instance.stripBaseURL) {
+ if (Ext.isIE && (name == "href" || name == "src") && editor.plugins.link && editor.plugins.link.instance && editor.plugins.link.instance.stripBaseURL) {
value = editor.plugins.link.instance.stripBaseURL(value);
}
}
@@ -2353,7 +2834,11 @@
// Mozilla reports some special values; we don't need them.
if(/(_moz|^$)/.test(value)) continue;
// Strip value="0" reported by IE on all li tags
- if(HTMLArea.is_ie && root_tag == "li" && name == "value" && a.nodeValue == 0) continue;
+ if(Ext.isIE && root_tag == "li" && name == "value" && value == 0) continue;
+ // Strip id generated by ExtJS
+ if (name === 'id' && value.substr(0, 7) === 'ext-gen') {
+ continue;
+ }
html += " " + name + '="' + HTMLArea.htmlEncode(value) + '"';
}
if (html != "") html += closed ? " />" : ">";
@@ -2407,66 +2892,322 @@
pN.removeChild(el);
return el;
};
-
-String.prototype.trim = function() {
- return this.replace(/^\s+/, '').replace(/\s+$/, '');
-};
-
-// creates a rgb-style color from a number
-HTMLArea._makeColor = function(v) {
- if (typeof(v) != "number") {
- // already in rgb (hopefully); IE doesn't get here.
- return v;
+/***************************************************
+ * TIPS ON FORM FIELDS AND MENU ITEMS
+ ***************************************************/
+/*
+ * Intercept Ext.form.Field.afterRender in order to provide tips on form fields and menu items
+ * Adapted from: http://www.extjs.com/forum/showthread.php?t=36642
+ */
+HTMLArea.util.Tips = function () {
+ return {
+ tipsOnFormFields: function () {
+ if (this.helpText || this.helpTitle) {
+ if (!this.helpDisplay) {
+ this.helpDisplay = 'both';
+ }
+ var label = this.label;
+ // IE has problems with img inside label tag
+ if (label && this.helpIcon && !Ext.isIE) {
+ var helpImage = label.insertFirst({
+ tag: 'img',
+ src: _editor_skin + 'images/helpbubble.gif',
+ style: 'vertical-align: middle; padding-right: 2px;'
+ });
+ if (this.helpDisplay == 'image' || this.helpDisplay == 'both'){
+ Ext.QuickTips.register({
+ target: helpImage,
+ title: this.helpTitle,
+ text: this.helpText
+ });
+ }
+ }
+ if (this.helpDisplay == 'field' || this.helpDisplay == 'both'){
+ Ext.QuickTips.register({
+ target: this,
+ title: this.helpTitle,
+ text: this.helpText
+ });
+ }
+ }
+ },
+ tipsOnMenuItems: function () {
+ if (this.helpText || this.helpTitle) {
+ Ext.QuickTips.register({
+ target: this,
+ title: this.helpTitle,
+ text: this.helpText
+ });
+ }
+ }
}
- // IE sends number; convert to rgb.
- var r = v & 0xFF;
- var g = (v >> 8) & 0xFF;
- var b = (v >> 16) & 0xFF;
- return "rgb(" + r + "," + g + "," + b + ")";
-};
-
-// returns hexadecimal color representation from a number or a rgb-style color.
-HTMLArea._colorToRgb = function(v) {
- if (!v)
- return '';
-
- // returns the hex representation of one byte (2 digits)
- function hex(d) {
- return (d < 16) ? ("0" + d.toString(16)) : d.toString(16);
- };
-
- if (typeof(v) == "number") {
- // we're talking to IE here
- var r = v & 0xFF;
- var g = (v >> 8) & 0xFF;
- var b = (v >> 16) & 0xFF;
- return "#" + hex(r) + hex(g) + hex(b);
+}();
+Ext.form.Field.prototype.afterRender = Ext.form.Field.prototype.afterRender.createInterceptor(HTMLArea.util.Tips.tipsOnFormFields);
+Ext.menu.BaseItem.prototype.afterRender = Ext.menu.BaseItem.prototype.afterRender.createInterceptor(HTMLArea.util.Tips.tipsOnMenuItems);
+/***************************************************
+ * COLOR WIDGETS AND UTILITIES
+ ***************************************************/
+HTMLArea.util.Color = function () {
+ return {
+ /*
+ * Returns a rgb-style color from a number
+ */
+ colorToRgb: function(v) {
+ if (typeof(v) != 'number') {
+ return v;
+ }
+ var r = v & 0xFF;
+ var g = (v >> 8) & 0xFF;
+ var b = (v >> 16) & 0xFF;
+ return 'rgb(' + r + ',' + g + ',' + b + ')';
+ },
+ /*
+ * Returns hexadecimal color representation from a number or a rgb-style color.
+ */
+ colorToHex: function(v) {
+ if (!v) {
+ return '';
+ }
+ function hex(d) {
+ return (d < 16) ? ('0' + d.toString(16)) : d.toString(16);
+ };
+ if (typeof(v) == 'number') {
+ var r = v & 0xFF;
+ var g = (v >> 8) & 0xFF;
+ var b = (v >> 16) & 0xFF;
+ return '#' + hex(r) + hex(g) + hex(b);
+ }
+ if (v.substr(0, 3) === 'rgb') {
+ var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/;
+ if (v.match(re)) {
+ var r = parseInt(RegExp.$1);
+ var g = parseInt(RegExp.$2);
+ var b = parseInt(RegExp.$3);
+ return ('#' + hex(r) + hex(g) + hex(b)).toUpperCase();
+ }
+ return null;
+ }
+ if (v.substr(0, 1) === '#') {
+ return v;
+ }
+ return null;
+ },
+ /*
+ * Select interceptor to ensure that the color exists in the palette before trying to select
+ */
+ checkIfColorInPalette: function (color) {
+ // Do not continue if the new color is not in the palette
+ if (this.el && !this.el.child('a.color-' + color)) {
+ // Remove any previous selection
+ this.deSelect();
+ return false;
+ }
+ }
}
-
- if (v.substr(0, 3) == "rgb") {
- // in rgb(...) form -- Mozilla
- var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/;
- if (v.match(re)) {
- var r = parseInt(RegExp.$1);
- var g = parseInt(RegExp.$2);
- var b = parseInt(RegExp.$3);
- return "#" + hex(r) + hex(g) + hex(b);
+}();
+/*
+ * Interim backward compatibility
+ */
+HTMLArea._makeColor = HTMLArea.util.Color.colorToRgb;
+HTMLArea._colorToRgb = HTMLArea.util.Color.colorToHex;
+/*
+ * Intercept Ext.ColorPalette.prototype.select
+ */
+Ext.ColorPalette.prototype.select = Ext.ColorPalette.prototype.select.createInterceptor(HTMLArea.util.Color.checkIfColorInPalette);
+/*
+ * Add deSelect method to Ext.ColorPalette
+ */
+Ext.override(Ext.ColorPalette, {
+ deSelect: function () {
+ if (this.el && this.value){
+ this.el.child('a.color-' + this.value).removeClass('x-color-palette-sel');
+ this.value = null;
}
- // doesn't match RE?! maybe uses percentages or float numbers
- // -- FIXME: not yet implemented.
- return null;
}
-
- if (v.substr(0, 1) == "#") {
- // already hex rgb (hopefully :D )
- return v;
+});
+Ext.ux.menu.HTMLAreaColorMenu = Ext.extend(Ext.menu.Menu, {
+ enableScrolling: false,
+ hideOnClick: true,
+ cls: 'x-color-menu',
+ colorPaletteValue: '',
+ customColorsValue: '',
+ plain: true,
+ showSeparator: false,
+ initComponent: function () {
+ var paletteItems = [];
+ var width = 'auto';
+ if (this.colorsConfiguration) {
+ paletteItems.push({
+ xtype: 'container',
+ layout: 'anchor',
+ width: 160,
+ style: { float: 'right' },
+ items: {
+ xtype: 'colorpalette',
+ itemId: 'custom-colors',
+ cls: 'htmlarea-custom-colors',
+ colors: this.colorsConfiguration,
+ value: this.value,
+ allowReselect: true,
+ tpl: new Ext.XTemplate(
+ '{0}'
+ )
+ }
+ });
+ width = 350;
+ }
+ paletteItems.push({
+ xtype: 'container',
+ layout: 'anchor',
+ items: {
+ xtype: 'colorpalette',
+ itemId: 'color-palette',
+ cls: 'color-palette',
+ colors: this.colors,
+ value: this.value,
+ allowReselect: true
+ }
+ });
+ Ext.apply(this, {
+ layout: 'menu',
+ width: width,
+ items: paletteItems
+ });
+ Ext.ux.menu.HTMLAreaColorMenu.superclass.initComponent.call(this);
+ this.standardPalette = this.find('itemId', 'color-palette')[0];
+ this.customPalette = this.find('itemId', 'custom-colors')[0];
+ if (this.standardPalette) {
+ this.standardPalette.purgeListeners();
+ this.relayEvents(this.standardPalette, ['select']);
+ }
+ if (this.customPalette) {
+ this.customPalette.purgeListeners();
+ this.relayEvents(this.customPalette, ['select']);
+ }
+ this.on('select', this.menuHide, this);
+ if (this.handler){
+ this.on('select', this.handler, this.scope || this);
+ }
+ },
+ menuHide: function() {
+ if (this.hideOnClick){
+ this.hide(true);
+ }
}
-
- // if everything else fails ;)
- return null;
-};
-
+});
+Ext.reg('htmlareacolormenu', Ext.ux.menu.HTMLAreaColorMenu);
/*
+ * Color palette trigger field
+ * Based on http://www.extjs.com/forum/showthread.php?t=89312
+ */
+Ext.ux.form.ColorPaletteField = Ext.extend(Ext.form.TriggerField, {
+ triggerClass : 'x-form-color-trigger',
+ 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'
+ ],
+ // Whether or not the field background, text, or triggerbackgroud are set to the selected color
+ colorizeFieldBackgroud: true,
+ colorizeFieldText: true,
+ colorizeTrigger: false,
+ editable: true,
+ initComponent: function () {
+ Ext.ux.form.ColorPaletteField.superclass.initComponent.call(this);
+ this.addEvents(
+ 'select'
+ );
+ },
+ // private
+ validateBlur: function () {
+ return !this.menu || !this.menu.isVisible();
+ },
+ setValue: function (color) {
+ if (color) {
+ if (this.colorizeFieldBackgroud) {
+ this.el.applyStyles('background: #' + color + ';');
+ }
+ if (this.colorizeFieldText) {
+ this.el.applyStyles('color: #' + this.rgbToHex(this.invert(this.hexToRgb(color))) + ';');
+ }
+ if (this.colorizeTrigger) {
+ this.trigger.applyStyles('background-color: #' + color + ';');
+ }
+ }
+ return Ext.ux.form.ColorPaletteField.superclass.setValue.call(this, color);
+ },
+ // private
+ onDestroy: function () {
+ Ext.destroy(this.menu);
+ Ext.ux.form.ColorPaletteField.superclass.onDestroy.call(this);
+ },
+ // private
+ onTriggerClick: function () {
+ if (this.disabled) {
+ return;
+ }
+ if (this.menu == null) {
+ this.menu = new Ext.ux.menu.HTMLAreaColorMenu({
+ hideOnClick: false,
+ colors: this.colors,
+ colorsConfiguration: this.colorsConfiguration,
+ value: this.getValue()
+ });
+ }
+ this.onFocus();
+ this.menu.show(this.el, "tl-bl?");
+ this.menuEvents('on');
+ },
+ //private
+ menuEvents: function (method) {
+ this.menu[method]('select', this.onSelect, this);
+ this.menu[method]('hide', this.onMenuHide, this);
+ this.menu[method]('show', this.onFocus, this);
+ },
+ onSelect: function (m, d) {
+ this.setValue(d);
+ this.fireEvent('select', this, d);
+ this.menu.hide();
+ },
+ onMenuHide: function () {
+ this.focus(false, 60);
+ this.menuEvents('un');
+ },
+ invert: function ( r, g, b ) {
+ if( r instanceof Array ) { return this.invert.call( this, r[0], r[1], r[2] ); }
+ return [255-r,255-g,255-b];
+ },
+ hexToRgb: function ( hex ) {
+ return [ this.hexToDec( hex.substr(0, 2) ), this.hexToDec( hex.substr(2, 2) ), this.hexToDec( hex.substr(4, 2) ) ];
+ },
+ hexToDec: function( hex ) {
+ var s = hex.split('');
+ return ( ( this.getHCharPos( s[0] ) * 16 ) + this.getHCharPos( s[1] ) );
+ },
+ getHCharPos: function( c ) {
+ var HCHARS = '0123456789ABCDEF';
+ return HCHARS.indexOf( c.toUpperCase() );
+ },
+ rgbToHex: function( r, g, b ) {
+ if( r instanceof Array ) { return this.rgbToHex.call( this, r[0], r[1], r[2] ); }
+ return this.decToHex( r ) + this.decToHex( g ) + this.decToHex( b );
+ },
+ decToHex: function( n ) {
+ var HCHARS = '0123456789ABCDEF';
+ n = parseInt(n, 10);
+ n = ( !isNaN( n )) ? n : 0;
+ n = (n > 255 || n < 0) ? 0 : n;
+ return HCHARS.charAt( ( n - n % 16 ) / 16 ) + HCHARS.charAt( n % 16 );
+ }
+});
+Ext.reg('colorpalettefield', Ext.ux.form.ColorPaletteField);
+/*
* Use XML HTTPRequest to post some data back to the server and do something
* with the response (asyncronously or syncronously); this is used by such things as the spellchecker update personal dict function
*/
@@ -2555,107 +3296,39 @@
* TYPO3-SPECIFIC FUNCTIONS
***************************************************/
/*
- * Set the size of textarea with the RTE. It's called, if we are in fullscreen-mode.
- */
-var setRTEsizeByJS = function(divId, height, width) {
- if (HTMLArea.is_gecko) height = height - 25;
- else height = height - 60;
- if (height > 0) document.getElementById(divId).style.height = height + "px";
- if (HTMLArea.is_gecko) width = "99%";
- else width = "97%";
- document.getElementById(divId).style.width = width;
-};
-
-/*
* Extending the TYPO3 Lorem Ipsum extension
*/
var lorem_ipsum = function(element,text) {
if (element.tagName.toLowerCase() == "textarea" && element.id && element.id.substr(0,7) == "RTEarea") {
var editor = RTEarea[element.id.substr(7, element.id.length)]["editor"];
editor.insertHTML(text);
- editor.updateToolbar();
+ editor.toolbar.update();
}
};
-
/*
- * Initialize the editor, configure the toolbar, setup the plugins, etc.
+ * Create the editor when HTMLArea is loaded and when Ext is ready
*/
-HTMLArea.initTimer = new Object();
-
-HTMLArea.onGenerateHandler = function(editorNumber) {
- return (function() {
- document.getElementById('pleasewait' + editorNumber).style.display = 'none';
- document.getElementById('editorWrap' + editorNumber).style.visibility = 'visible';
- editorNumber = null;
- });
-};
-
HTMLArea.initEditor = function(editorNumber) {
- if (document.getElementById('pleasewait' + editorNumber)) {
- if(HTMLArea.checkSupportedBrowser()) {
- document.getElementById('pleasewait' + editorNumber).style.display = 'block';
- document.getElementById('editorWrap' + editorNumber).style.visibility = 'hidden';
- if(HTMLArea.initTimer[editorNumber]) window.clearTimeout(HTMLArea.initTimer[editorNumber]);
- if(!HTMLArea.is_loaded) {
- HTMLArea.initTimer[editorNumber] = window.setTimeout("HTMLArea.initEditor(\'" + editorNumber + "\');", 150);
+ if (document.getElementById('pleasewait' + editorNumber)) {
+ if (HTMLArea.checkSupportedBrowser()) {
+ document.getElementById('pleasewait' + editorNumber).style.display = 'block';
+ document.getElementById('editorWrap' + editorNumber).style.visibility = 'hidden';
+ if (!HTMLArea.is_loaded) {
+ HTMLArea.initEditor.defer(150, null, [editorNumber]);
+ } else {
+ // Create an editor for the textarea
+ HTMLArea._appendToLog("[HTMLArea::initEditor]: Initializing editor with editor Id: " + editorNumber + ".");
+ var editor = new HTMLArea.Editor(Ext.apply(new HTMLArea.Config(editorNumber), RTEarea[editorNumber]));
+ editor.generate();
+ return false;
+ }
} else {
- var RTE = RTEarea[editorNumber];
- HTMLArea._appendToLog("[HTMLArea::initEditor]: Initializing editor with editor Id: " + editorNumber + ".");
-
- // Get the configuration properties
- var config = new HTMLArea.Config();
- for (var property in RTE) {
- if (RTE.hasOwnProperty(property)) {
- config[property] = RTE[property] ? RTE[property] : false;
- }
- }
- // Create an editor for the textarea
- var editor = new HTMLArea(RTE.id, config);
- RTE.editor = editor;
-
- // Save the editornumber in the object
- editor._typo3EditerNumber = editorNumber;
- editor._editorNumber = editorNumber;
-
- // Override these settings if they were ever modified
- editor.config.width = "auto";
- editor.config.height = "auto";
- editor.config.sizeIncludesToolbar = true;
- editor.config.fullPage = false;
-
- // All nested tabs and inline levels in the sorting order they were applied
- editor.nested = {};
- editor.nested.all = RTEarea[editorNumber].tceformsNested;
- editor.nested.sorted = HTMLArea.simplifyNested(editor.nested.all);
-
- // Register the plugins included in the configuration
- for (var plugin in editor.config.plugin) {
- if (editor.config.plugin.hasOwnProperty(plugin) && editor.config.plugin[plugin]) {
- editor.registerPlugin(plugin);
- }
- }
-
- editor.onGenerate = HTMLArea.onGenerateHandler(editorNumber);
-
- editor.generate();
- return false;
+ document.getElementById('pleasewait' + editorNumber).style.display = 'none';
+ document.getElementById('editorWrap' + editorNumber).style.visibility = 'visible';
}
- } else {
- document.getElementById('pleasewait' + editorNumber).style.display = 'none';
- document.getElementById('editorWrap' + editorNumber).style.visibility = 'visible';
}
- }
};
-HTMLArea.allElementsAreDisplayed = function(elements) {
- for (var i=0, length=elements.length; i < length; i++) {
- if (document.getElementById(elements[i]).style.display == "none") {
- return false;
- }
- }
- return true;
-};
-
/**
* Base, version 1.0.2
* Copyright 2006, Dean Edwards
@@ -2754,7 +3427,7 @@
// single instance
var object = constructor ? klass : _prototype;
// class initialisation
- if (object.init instanceof Function) object.init();
+ //if (object.init instanceof Function) object.init();
return object;
};
@@ -2781,7 +3454,7 @@
*/
constructor : function(editor, pluginName) {
this.editor = editor;
- this.editorNumber = editor._editorNumber;
+ this.editorNumber = editor.editorId;
this.editorConfiguration = editor.config;
this.name = pluginName;
try {
@@ -2854,7 +3527,7 @@
* @return object the plugin object or null
*/
getPluginInstance : function(pluginName) {
- return this.editor.getPluginInstance(pluginName);
+ return this.editor.getPlugin(pluginName);
},
/**
@@ -2863,7 +3536,7 @@
* @return string editor mode
*/
getEditorMode : function() {
- return this.getPluginInstance("EditorMode").getEditorMode();
+ return this.editor.getMode();
},
/**
@@ -2874,52 +3547,70 @@
* @return boolean true if the button is enabled in the toolbar configuration
*/
isButtonInToolbar : function(buttonId) {
- var toolbar = this.editorConfiguration.toolbar;
- var n = toolbar.length;
- for ( var i = 0; i < n; ++i ) {
- var buttonInToolbar = new RegExp( "^(" + toolbar[i].join("|") + ")$", "i");
- if (buttonInToolbar.test(buttonId)) {
- return true;
- }
- }
- return false;
+ var index = -1;
+ Ext.each(this.editorConfiguration.toolbar, function (row) {
+ Ext.each(row, function (group) {
+ index = group.indexOf(buttonId);
+ return index === -1;
+ });
+ return index === -1;
+ });
+ return index !== -1;
},
/**
- * Registors a button for inclusion in the toolbar
+ * Returns the button object from the toolbar
*
+ * @param string buttonId: identification of the button
+ *
+ * @return object the toolbar button object
+ */
+ getButton: function(buttonId) {
+ return this.editor.toolbar.getButton(buttonId);
+ },
+
+ /**
+ * Arrays of ExtJS config properties that may be used on a button or dropdown in Page TSConfig
+ */
+ ExtJSProperties: {
+ htmlareabutton: [],
+ htmlareacombo: ['width', 'listWidth', 'maxHeight' ]
+ },
+
+ /**
+ * Registers a button for inclusion in the toolbar
+ *
* @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
* action : name of the function invoked when the button is pressed
* context : will be disabled if not inside one of listed elements
- * hide : hide in menu and show only in context menu?
- * selection : will be disabled if there is no selection?
+ * hide : hide in menu and show only in context menu (deprecated, use hidden)
+ * hidden : synonym of hide
+ * selection : will be disabled 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
*
* @return boolean true if the button was successfully registered
*/
- registerButton : function (buttonConfiguration) {
+ registerButton: function (buttonConfiguration) {
if (this.isButtonInToolbar(buttonConfiguration.id)) {
- if ((typeof(buttonConfiguration.action) === "string") && (typeof(this[buttonConfiguration.action]) === "function")) {
- var hotKeyAction = buttonConfiguration.action;
- var actionFunctionReference = this.makeFunctionReference(buttonConfiguration.action);
- buttonConfiguration.action = actionFunctionReference;
- if (!buttonConfiguration.textMode) {
- buttonConfiguration.textMode = false;
- }
+ if (Ext.isString(buttonConfiguration.action) && Ext.isFunction(this[buttonConfiguration.action])) {
+ buttonConfiguration.plugins = this;
if (buttonConfiguration.dialog) {
if (!buttonConfiguration.dimensions) {
buttonConfiguration.dimensions = { width: 250, height: 250};
}
buttonConfiguration.dimensions.top = buttonConfiguration.dimensions.top ? buttonConfiguration.dimensions.top : this.editorConfiguration.dialogueWindows.defaultPositionFromTop;
buttonConfiguration.dimensions.left = buttonConfiguration.dimensions.left ? buttonConfiguration.dimensions.left : this.editorConfiguration.dialogueWindows.defaultPositionFromLeft;
- } else {
- buttonConfiguration.dialog = false;
}
+ buttonConfiguration.hidden = buttonConfiguration.hide;
+ // Copy ExtJS properties for the button
+ if (this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[buttonConfiguration.id]]) {
+ buttonConfiguration = Ext.copyTo(buttonConfiguration, this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[buttonConfiguration.id]], this.ExtJSProperties['htmlareabutton']);
+ }
if (this.editorConfiguration.registerButton(buttonConfiguration)) {
var hotKey = buttonConfiguration.hotKey ? buttonConfiguration.hotKey :
((this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[buttonConfiguration.id]] && this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[buttonConfiguration.id]].hotKey) ? this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[buttonConfiguration.id]].hotKey : null);
@@ -2932,8 +3623,7 @@
if (hotKey || hotKey == "0") {
var hotKeyConfiguration = {
id : hotKey,
- cmd : buttonConfiguration.id,
- action : hotKeyAction
+ cmd : buttonConfiguration.id
};
return this.registerHotKey(hotKeyConfiguration);
}
@@ -2945,44 +3635,52 @@
}
return false;
},
-
/**
- * Registors a drop-down list for inclusion in the toolbar
+ * Registers a drop-down list for inclusion in the toolbar
*
* @param object dropDownConfiguration: the configuration object of the drop-down:
* id : unique id for the drop-down
* tooltip : tooltip for the drop-down
+ * action : name of function to invoke when an option is selected
* textMode : enable in text mode
- * action : name of the function invoked when a new option is selected
- * refresh : name of the function invoked in order to refresh the drop-down when the toolbar is updated
- * context : will be disabled if not inside one of listed elements
*
* @return boolean true if the drop-down list was successfully registered
*/
- registerDropDown : function (dropDownConfiguration) {
+ registerDropDown: function (dropDownConfiguration) {
if (this.isButtonInToolbar(dropDownConfiguration.id)) {
- if (typeof((dropDownConfiguration.action) === "string") && (typeof(this[dropDownConfiguration.action]) === "function")) {
- var actionFunctionReference = this.makeFunctionReference(dropDownConfiguration.action);
- dropDownConfiguration.action = actionFunctionReference;
- if (!dropDownConfiguration.textMode) {
- dropDownConfiguration.textMode = false;
+ if (Ext.isString(dropDownConfiguration.action) && Ext.isFunction(this[dropDownConfiguration.action])) {
+ dropDownConfiguration.plugins = this;
+ dropDownConfiguration.hidden = dropDownConfiguration.hide;
+ dropDownConfiguration.xtype = 'htmlareacombo';
+ if (this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[dropDownConfiguration.id]]) {
+ dropDownConfiguration = Ext.copyTo(dropDownConfiguration, this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[dropDownConfiguration.id]], this.ExtJSProperties['htmlareacombo']);
}
- if (typeof(dropDownConfiguration.refresh) === "string") {
- if (typeof(this[dropDownConfiguration.refresh]) === "function") {
- var refreshFunctionReference = this.makeFunctionReference(dropDownConfiguration.refresh);
- dropDownConfiguration.refresh = refreshFunctionReference;
- } else {
- this.appendToLog("registerDropDown", "Function " + dropDownConfiguration.refresh + " was not defined when registering drop-down " + dropDownConfiguration.id);
- return false;
- }
- }
- return this.editorConfiguration.registerDropdown(dropDownConfiguration);
+ return this.editorConfiguration.registerButton(dropDownConfiguration);
} else {
- this.appendToLog("registerDropDown", "Function " + dropDownConfiguration.action + " was not defined when registering drop-down " + dropDownConfiguration.id);
+ this.appendToLog('registerDropDown', 'Function ' + dropDownConfiguration.action + ' was not defined when registering drop-down ' + dropDownConfiguration.id);
}
}
return false;
},
+ /**
+ * Registers a text element for inclusion in the toolbar
+ *
+ * @param object textConfiguration: the configuration object of the text element:
+ * id : unique id for the text item
+ * text : the text litteral
+ * tooltip : tooltip for the text item
+ * cls : a css class to be assigned to the text element
+ *
+ * @return boolean true if the drop-down list was successfully registered
+ */
+ registerText: function (textConfiguration) {
+ if (this.isButtonInToolbar(textConfiguration.id)) {
+ textConfiguration.plugins = this;
+ textConfiguration.xtype = 'htmlareatoolbartext';
+ return this.editorConfiguration.registerButton(textConfiguration);
+ }
+ return false;
+ },
/**
* Returns the drop-down configuration
@@ -2992,7 +3690,7 @@
* @return object the drop-down configuration object
*/
getDropDownConfiguration : function(dropDownId) {
- return this.editorConfiguration.customSelects[dropDownId];
+ return this.editorConfiguration.buttonsConfig[dropDownId];
},
/**
@@ -3000,19 +3698,13 @@
*
* @param object hotKeyConfiguration: the configuration object of the hotkey:
* id : the key
- * action : name of the function invoked when a hotkey is pressed
+ * cmd : name of the button corresponding to the hot key
+ * element : value of the record to be selected in the dropDown item
*
* @return boolean true if the hotkey was successfully registered
*/
registerHotKey : function (hotKeyConfiguration) {
- if (typeof((hotKeyConfiguration.action) === "string") && (typeof(this[hotKeyConfiguration.action]) === "function")) {
- var actionFunctionReference = this.makeFunctionReference(hotKeyConfiguration.action);
- hotKeyConfiguration.action = actionFunctionReference;
- return this.editorConfiguration.registerHotKey(hotKeyConfiguration);
- } else {
- this.appendToLog("registerHotKey", "Function " + hotKeyConfiguration.action + " was not defined when registering hotkey " + hotKeyConfiguration.id);
- return false;
- }
+ return this.editorConfiguration.registerHotKey(hotKeyConfiguration);
},
/**
@@ -3041,24 +3733,33 @@
*
* @return object the hotkey configuration object
*/
- getHotKeyConfiguration : function(key) {
- if (typeof(this.editorConfiguration.hotKeyList[key]) !== "undefined") {
+ getHotKeyConfiguration: function(key) {
+ if (Ext.isDefined(this.editorConfiguration.hotKeyList[key])) {
return this.editorConfiguration.hotKeyList[key];
} else {
return null;
}
},
-
/**
+ * Initializes the plugin
+ * Is invoked when the toolbar component is created (subclass of Ext.ux.HTMLAreaButton or Ext.ux.form.HTMLAreaCombo)
+ *
+ * @param object button: the component
+ *
+ * @return void
+ */
+ init: Ext.emptyFn,
+ /**
* The toolbar refresh handler of the plugin
* This function may be defined by the plugin subclass.
* If defined, the function will be invoked whenever the toolbar state is refreshed.
*
* @return boolean
*/
- onUpdateToolbar : null,
-
+ onUpdateToolbar: Ext.emptyFn,
/**
+ * Deprecated as of TYPO3 4.4
+ * Register the key handler to the editor keyMap in onGenerate function
* The keyPress event handler
* This function may be defined by the plugin subclass.
* If defined, the function is invoked whenever a key is pressed.
@@ -3067,20 +3768,8 @@
*
* @return boolean
*/
- onKeyPress : null,
-
+ onKeyPress: null,
/**
- * The hotKey event handler
- * This function may be defined by the plugin subclass.
- * If defined, the function is invoked whenever a hot key is pressed.
- *
- * @param event key: the hot key that was pressed
- *
- * @return boolean
- */
- onHotKey : null,
-
- /**
* The onMode event handler
* This function may be redefined by the plugin subclass.
* The function is invoked whenever the editor changes mode.
@@ -3089,21 +3778,19 @@
*
* @return boolean
*/
- onMode : function(mode) {
- if (mode === "textmode" && this.dialog && HTMLArea.Dialog[this.name] == this.dialog && !(this.dialog.buttonId && this.editorConfiguration.btnList[this.dialog.buttonId] && this.editorConfiguration.btnList[this.dialog.buttonId].textMode)) {
+ onMode: function(mode) {
+ if (mode === "textmode" && this.dialog && HTMLArea.Dialog[this.name] == this.dialog && !(this.dialog.buttonId && this.editorConfiguration.buttons[this.dialog.buttonId] && this.editorConfiguration.buttons[this.dialog.buttonId].textMode)) {
this.dialog.close();
}
},
-
/**
* The onGenerate event handler
* This function may be defined by the plugin subclass.
- * If defined, the function is invoked when the editor is initialized
+ * The function is invoked when the editor is initialized
*
* @return boolean
*/
- onGenerate : null,
-
+ onGenerate: Ext.emptyFn,
/**
* Make function reference in order to avoid memory leakage in IE
*
@@ -3113,8 +3800,8 @@
*/
makeFunctionReference : function (functionName) {
var self = this;
- return (function(arg1, arg2) {
- return (self[functionName](arg1, arg2));});
+ return (function(arg1, arg2, arg3) {
+ return (self[functionName](arg1, arg2, arg3));});
},
/**
@@ -3197,45 +3884,45 @@
this.appendToLog("openDialog", "Function " + action + " was not defined when opening dialog for " + buttonId);
}
}
- // Window dimensions as per call or button registration
- var dialogueWindowDimensions = {
- width: ((dimensions && dimensions.width) ? dimensions.width :
- (this.editorConfiguration.btnList[buttonId] ? this.editorConfiguration.btnList[buttonId][8].width : 250)),
- height: ((dimensions && dimensions.height) ? dimensions.height :
- (this.editorConfiguration.btnList[buttonId] ? this.editorConfiguration.btnList[buttonId][8].height : 250)),
- top: ((dimensions && dimensions.top) ? dimensions.top :
- (this.editorConfiguration.btnList[buttonId] ? this.editorConfiguration.btnList[buttonId][8].top : this.editorConfiguration.dialogueWindows.defaultPositionFromTop)),
- left: ((dimensions && dimensions.left) ? dimensions.left :
- (this.editorConfiguration.btnList[buttonId] ? this.editorConfiguration.btnList[buttonId][8].left : this.editorConfiguration.dialogueWindows.defaultPositionFromLeft))
- };
- // Overrride window dimensions as per PageTSConfig
- var buttonConfiguration = this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[buttonId]];
- if (buttonConfiguration && buttonConfiguration.dialogueWindow) {
- if (buttonConfiguration.dialogueWindow.width) {
- dialogueWindowDimensions.width = buttonConfiguration.dialogueWindow.width;
- }
- if (buttonConfiguration.dialogueWindow.height) {
- dialogueWindowDimensions.height = buttonConfiguration.dialogueWindow.height;
- }
- if (buttonConfiguration.dialogueWindow.top) {
- dialogueWindowDimensions.top = buttonConfiguration.dialogueWindow.positionFromTop;
- }
- if (buttonConfiguration.dialogueWindow.left) {
- dialogueWindowDimensions.left = buttonConfiguration.dialogueWindow.positionFromLeft;
- }
- }
return new HTMLArea.Dialog(
this,
buttonId,
url,
actionFunctionReference,
arguments,
- dialogueWindowDimensions,
+ this.getWindowDimensions(dimensions, buttonId),
(showScrollbars?showScrollbars:"no"),
dialogOpener
);
}
},
+ getWindowDimensions: function (dimensions, buttonId) {
+ // Apply default dimensions
+ var dialogueWindowDimensions = {
+ width: 250,
+ height: 250,
+ top: this.editorConfiguration.dialogueWindows.defaultPositionFromTop,
+ left: this.editorConfiguration.dialogueWindows.defaultPositionFromLeft
+ };
+ // Apply dimensions as per button registration
+ if (this.editorConfiguration.buttonsConfig[buttonId]) {
+ Ext.apply(dialogueWindowDimensions, this.editorConfiguration.buttonsConfig[buttonId].dimensions);
+ }
+ // Apply dimensions as per call
+ Ext.apply(dialogueWindowDimensions, dimensions);
+ // Overrride dimensions as per PageTSConfig
+ var buttonConfiguration = this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[buttonId]];
+ if (buttonConfiguration && buttonConfiguration.dialogueWindow) {
+ Ext.apply(dialogueWindowDimensions, buttonConfiguration.dialogueWindow);
+ if (buttonConfiguration.dialogueWindow.top) {
+ dialogueWindowDimensions.top = buttonConfiguration.dialogueWindow.positionFromTop;
+ }
+ if (buttonConfiguration.dialogueWindow.left) {
+ dialogueWindowDimensions.left = buttonConfiguration.dialogueWindow.positionFromLeft;
+ }
+ }
+ return dialogueWindowDimensions;
+ },
/**
* Make url from the name of a popup of the plugin
@@ -3270,6 +3957,100 @@
*/
appendToLog : function (functionName, text) {
HTMLArea._appendToLog("[" + this.name + "::" + functionName + "]: " + text);
+ },
+ /*
+ * Add a config element to config array if not empty
+ *
+ * @param object configElement: the config element
+ * @param array configArray: the config array
+ *
+ * @return void
+ */
+ addConfigElement: function (configElement, configArray) {
+ if (!Ext.isEmpty(configElement)) {
+ configArray.push(configElement);
+ }
+ },
+ /*
+ * Handler for Ext.TabPanel tabchange event
+ * Force window ghost height synchronization
+ * Working around ExtJS 3.1 bug
+ */
+ syncHeight: function (tabPanel, tab) {
+ var position = this.dialog.getPosition();
+ if (position[0] > 0) {
+ this.dialog.setPosition(position);
+ }
+ },
+ /*
+ * Show the dialogue window
+ */
+ show: function () {
+ // Close the window if the editor changes mode
+ this.dialog.mon(this.editor, 'modeChange', this.close, this, {single: true });
+ this.saveSelection();
+ this.dialog.show();
+ this.restoreSelection();
+ },
+ /*
+ * Close the dialogue window (after saving the selection, if IE)
+ */
+ close: function () {
+ this.saveSelection();
+ this.dialog.close();
+ },
+ /*
+ * Dialogue window onClose handler
+ */
+ onClose: function () {
+ this.restoreSelection();
+ this.editor.updateToolbar();
+ },
+ /*
+ * Handler for window cancel
+ */
+ onCancel: function () {
+ this.dialog.close();
+ },
+ /*
+ * Save selection
+ * Should be called after processing button other than Cancel
+ */
+ saveSelection: function () {
+ // If IE, save the current selection
+ if (Ext.isIE) {
+ this.bookmark = this.editor.getBookmark(this.editor._createRange(this.editor._getSelection()));
+ }
+ },
+ /*
+ * Restore selection
+ * Should be called before processing dialogue button or result
+ */
+ restoreSelection: function () {
+ // If IE, restore the selection saved when the window was shown
+ if (Ext.isIE) {
+ this.editor.selectRange(this.editor.moveToBookmark(this.bookmark));
+ }
+ },
+ /*
+ * Build the configuration object of a button
+ *
+ * @param string button: the text of the button
+ * @param function handler: button handler
+ *
+ * @return object the button configuration object
+ */
+ buildButtonConfig: function (button, handler) {
+ return {
+ xtype: 'button',
+ text: this.localize(button),
+ listeners: {
+ click: {
+ fn: handler,
+ scope: this
+ }
+ }
+ };
}
});
@@ -3310,7 +4091,6 @@
}
HTMLArea.Dialog[this.plugin.name] = this;
this.dialogWindow = window.open(url, this.plugin.name + "Dialog", "toolbar=no,location=no,directories=no,menubar=no,resizable=yes,top=" + dimensions.top + ",left=" + dimensions.left + ",dependent=yes,dialog=yes,chrome=no,width=" + dimensions.width + ",height=" + dimensions.height + ",scrollbars=" + showScrollbars);
-
if (!this.dialogWindow) {
this.plugin.appendToLog("openDialog", "Dialog window could not be opened with url " + url);
return false;
@@ -3323,67 +4103,9 @@
if (!this.dialogWindow.opener) {
this.dialogWindow.opener = this.window;
}
-
- if (!url) this.createForm();
return true;
},
-
/**
- * Creates the document and the dialogue form of the dialogue window
- *
- * @return void
- */
- createForm : function () {
-
- this.document = this.dialogWindow.document;
- this.editor = this.plugin.editor;
-
- this.document.open();
- var html = this.plugin.editorConfiguration.getDocumentType()
- + '\n';
- this.document.write(html);
- this.document.close();
- // IE needs the stylesheets to be loaded before we create the form
- if (HTMLArea.is_ie) {
- this.loadStyle();
- }
- var head = this.document.getElementsByTagName("head")[0];
- var title = this.document.getElementsByTagName("title")[0];
- if (!title) {
- var title = this.document.createElement("title");
- head.appendChild(title);
- }
- this.document.title = this.arguments.title;
- var body = this.document.body;
- body.className = "popupwin dialog";
- body.id = "--HA-body";
- var content = this.document.createElement("div");
- content.className = "content";
- content.id = "content";
- this.content = content;
- body.appendChild(content);
- // Create the form
- // Localize, resize and initiate capture of events
- if (HTMLArea.is_ie) {
- // Catch errors for IE loosing control in case the window is closed while being initialized
- try {
- this.arguments.initialize(this);
- this.initialize(false, false, "noStyle");
- this.focus();
- } catch(e) { }
- } else {
- this.arguments.initialize(this);
- // Firefox needs a delay defore we resize
- this.initialize(false, (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera));
- this.focus();
- if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
- var self = this;
- setTimeout( function() { self.resize(); }, 100);
- }
- }
- },
-
- /**
* Adds OK and Cancel buttons to the dialogue window
*
* @return void
@@ -3473,7 +4195,6 @@
// Resize the dialog window to its contents
if (!noResize) this.resize(noResize);
},
-
/**
* Load the stylesheets in the dialog window
*
@@ -3485,7 +4206,7 @@
link.rel = "stylesheet";
link.type = "text/css";
link.href = HTMLArea.editorCSS;
- if (link.href.indexOf("http") == -1 && HTMLArea.is_gecko) link.href = _typo3_host_url + link.href;
+ if (link.href.indexOf("http") == -1 && !Ext.isIE) link.href = _typo3_host_url + link.href;
head.appendChild(link);
},
@@ -3536,8 +4257,7 @@
var doc = dialogWindow.document;
var content = doc.getElementById("content");
// As of Google Chrome build 1798, window resizeTo and resizeBy are completely erratic: do nothing
- if ((HTMLArea.is_gecko && !HTMLArea.is_opera && !HTMLArea.is_safari)
- || ((HTMLArea.is_ie || HTMLArea.is_opera || (HTMLArea.is_safari && !HTMLArea.is_chrome)) && content)) {
+ if (Ext.isGecko || ((Ext.isIE || Ext.isOpera || (Ext.isWebKit && !Ext.isChrome)) && content)) {
var self = this;
setTimeout( function() {
if (!noResize) {
@@ -3551,7 +4271,7 @@
}, 75);
} else if (!noResize) {
var body = doc.body;
- if (HTMLArea.is_ie) {
+ if (Ext.isIE) {
var innerX = (doc.documentElement && doc.documentElement.clientWidth) ? doc.documentElement.clientWidth : body.clientWidth;
var innerY = (doc.documentElement && doc.documentElement.clientHeight) ? doc.documentElement.clientHeight : body.clientHeight;
var pageY = Math.max(body.scrollHeight, body.offsetHeight);
@@ -3561,7 +4281,7 @@
dialogWindow.resizeBy((innerX < body.scrollWidth) ? (Math.max(body.scrollWidth, body.offsetWidth) - innerX) : 0, (body.scrollHeight - body.offsetHeight));
}
// As of Google Chrome build 1798, window resizeTo and resizeBy are completely erratic: do nothing
- } else if ((HTMLArea.is_safari && !HTMLArea.is_chrome) || HTMLArea.is_opera) {
+ } else if (Ext.isSafari || Ext.isOpera) {
dialogWindow.resizeTo(dialogWindow.innerWidth, body.offsetHeight + 10);
if (dialogWindow.innerHeight < body.scrollHeight) {
dialogWindow.resizeBy(0, (body.scrollHeight - dialogWindow.innerHeight) + 10);
@@ -3592,8 +4312,8 @@
var contentWidth = content.offsetWidth;
var contentHeight = content.offsetHeight;
- if (HTMLArea.is_gecko && !HTMLArea.is_opera) {
- dialogWindow.resizeTo(contentWidth, contentHeight + (HTMLArea.is_safari ? 40 : (HTMLArea.is_ff2 ? 75 : 95)));
+ if (Ext.isGecko || Ext.isWebKit) {
+ dialogWindow.resizeTo(contentWidth, contentHeight + (Ext.isWebKit ? 40 : (Ext.isGecko2 ? 75 : 95)));
} else {
dialogWindow.resizeTo(contentWidth + 200, contentHeight + 200);
if (dialogWindow.innerWidth) {
@@ -3622,7 +4342,7 @@
var doc = dialogWindow.document;
var body = doc.body;
// Center on parent if allowed
- if (HTMLArea.is_gecko) {
+ if (!Ext.isIE) {
var x = dialogWindow.opener.screenX + (dialogWindow.opener.outerWidth - dialogWindow.outerWidth) / 2;
var y = dialogWindow.opener.screenY + (dialogWindow.opener.outerHeight - dialogWindow.outerHeight) / 2;
} else {
@@ -3632,7 +4352,7 @@
var y = (screen.availHeight - H) / 2;
}
// As of build 1798, Google Chrome moveTo breaks the window dimensions: do nothing
- if (!HTMLArea.is_chrome) {
+ if (!Ext.isChrome) {
try {
dialogWindow.moveTo(x, y);
} catch(e) { }
@@ -3661,22 +4381,7 @@
this.dialogWindow.focus();
}
},
-
/**
- * Recover focus from the parent window
- *
- * @return void
- */
- recoverFocus : function(ev) {
- if (this.dialogWindow && !this.dialogWindow.closed) {
- if (!ev) var ev = window.event;
- HTMLArea._stopEvent(ev);
- this.focus();
- }
- return false;
- },
-
- /**
* Close the dialog window
*
* @return void
@@ -3688,11 +4393,10 @@
this.dialogWindow.openedDialog.close();
}
} catch(e) { }
- this.releaseEvents();
HTMLArea.Dialog[this.plugin.name] = null;
if (!this.dialogWindow.closed) {
this.dialogWindow.dialog = null;
- if (HTMLArea.is_safari || HTMLArea.is_ie) {
+ if (Ext.isWebKit || Ext.isIE) {
this.dialogWindow.blur();
}
this.dialogWindow.close();
@@ -3703,7 +4407,7 @@
}
// Opera unload event may be triggered after the editor iframe is gone
if (this.plugin.editor._iframe) {
- this.plugin.editor.updateToolbar();
+ this.plugin.editor.toolbar.update();
}
}
return false;
@@ -3729,10 +4433,10 @@
*
* @return boolean false if the event was handled
*/
- closeOnEscape : function(ev) {
- if (!ev) var ev = window.event;
+ closeOnEscape : function(event) {
+ var ev = event.browserEvent;
if (ev.keyCode == 27) {
- if (HTMLArea.is_gecko) {
+ if (!Ext.isIE) {
var parentWindow = ev.currentTarget.defaultView;
} else {
var parentWindow = ev.srcElement.parentNode.parentNode.parentWindow;
@@ -3750,81 +4454,21 @@
}
return true;
},
-
/**
- * Capture unload, escape and focus events
+ * Capture unload and escape events
*
* @return void
*/
captureEvents : function (skipUnload) {
- // Capture unload events on the dialogue window, the opener window and the editor frame
- this.unloadFunctionReference = this.makeFunctionReference("close");
- HTMLArea._addEvent(this.dialogWindow.opener, "unload", this.unloadFunctionReference);
- if (HTMLArea.is_gecko && this.plugin.editor._iframe.contentWindow) {
- HTMLArea._addEvent(this.plugin.editor._iframe.contentWindow, "unload", this.unloadFunctionReference);
+ // Capture unload events on the dialogue window and the editor frame
+ if (!Ext.isIE && this.plugin.editor._iframe.contentWindow) {
+ Ext.EventManager.on(this.plugin.editor._iframe.contentWindow, 'unload', this.close, this, {single: true});
}
- if (!skipUnload) HTMLArea._addEvent(this.dialogWindow, "unload", this.unloadFunctionReference);
+ if (!skipUnload) {
+ Ext.EventManager.on(this.dialogWindow, 'unload', this.close, this, {single: true});
+ }
// Capture escape key on the dialogue window
- this.escapeFunctionReference = this.makeFunctionReference("closeOnEscape");
- HTMLArea._addEvent(this.dialogWindow.document, "keypress", this.escapeFunctionReference);
- // Capture focus events on the opener window and its frames
- this.recoverFocusFunctionReference = this.makeFunctionReference("recoverFocus");
- this.captureFocus(this.dialogWindow.opener);
- },
-
- /**
- * Capture focus events
- *
- * @return void
- */
- captureFocus : function (w) {
- if (HTMLArea.is_gecko) {
- w.addEventListener("focus", this.recoverFocusFunctionReference, true);
- } else {
- HTMLArea._addEvent(w, "focus", this.recoverFocusFunctionReference);
- }
- for (var i = w.frames.length; --i >= 0;) {
- this.captureFocus(w.frames[i]);
- }
- },
-
- /**
- * Release all event handlers that were set when the dialogue window was opened
- *
- * @return void
- */
- releaseEvents : function() {
- if (this.dialogWindow) {
- HTMLArea._removeEvent(this.dialogWindow, "unload", this.unloadFunctionReference);
- try {
- if (this.dialogWindow.document) {
- HTMLArea._removeEvent(this.dialogWindow.document, "keypress", this.escapeFunctionReference);
- }
- } catch(e) { }
- try {
- if (this.dialogWindow.opener && !this.dialogWindow.opener.closed) {
- HTMLArea._removeEvent(this.dialogWindow.opener, "unload", this.unloadFunctionReference);
- if (HTMLArea.is_gecko) {
- this.releaseFocus(this.dialogWindow.opener);
- }
- }
- } catch(e) { }
- }
- if ((HTMLArea.is_gecko && !HTMLArea.is_opera) && this.plugin.editor._iframe.contentWindow) {
- HTMLArea._removeEvent(this.plugin.editor._iframe.contentWindow, "unload", this.unloadFunctionReference);
- }
- },
-
- /**
- * Release focus capturing events that were set when the dialogue window was opened
- *
- * @return void
- */
- releaseFocus : function(w) {
- HTMLArea._removeEvent(w, "focus", this.recoverFocusFunctionReference);
- for (var i = w.frames.length; --i >= 0;) {
- this.releaseFocus(w.frames[i]);
- }
- }
+ Ext.EventManager.on(this.dialogWindow.document, 'keypress', this.closeOnEscape, this, {single: true});
+ }
});
};
Index: typo3/sysext/rtehtmlarea/htmlarea/locallang_dialogs.xml
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/locallang_dialogs.xml (révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/locallang_dialogs.xml (copie de travail)
@@ -10,6 +10,7 @@
+
@@ -86,7 +87,7 @@
-
+
@@ -101,14 +102,15 @@
-
-
+
+
+
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/Acronym/acronym.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/Acronym/acronym.js (révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/Acronym/acronym.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
@@ -30,25 +30,28 @@
* TYPO3 SVN ID: $Id$
*/
Acronym = 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.acronym;
this.acronymUrl = this.pageTSConfiguration.acronymUrl;
- this.acronymModulePath = this.pageTSConfiguration.pathAcronymModule;
-
+ this.data = this.getJavascriptFile(this.acronymUrl, 'noEval');
+ if (this.data) {
+ eval(this.data);
+ };
+ this.data = {
+ acronym: acronyms,
+ abbr: abbreviations
+ };
/*
* Registering plugin "About" information
*/
var pluginInformation = {
- version : "1.7",
+ version : "2.0",
developer : "Stanislas Rolland",
developerUrl : "http://www.sjbr.ca/",
copyrightOwner : "Stanislas Rolland",
@@ -67,14 +70,27 @@
tooltip : this.localize("Insert/Modify Acronym"),
action : "onButtonPress",
hide : (this.pageTSConfiguration.noAcronym && this.pageTSConfiguration.noAbbr),
- dialog : true
+ dialog : true,
+ contextMenuTitle: this.localize(buttonId + '-contextMenuTitle')
};
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',
+ helpIcon: true
+ }
+ },
+ /*
* This function gets called when the button was pressed
*
* @param object editor: the editor instance
@@ -82,58 +98,434 @@
*
* @return boolean false if action is completed
*/
- onButtonPress : function(editor, id) {
+ onButtonPress: function(editor, id) {
+ // Could be a button or its hotkey
+ var buttonId = this.translateHotKey(id);
+ buttonId = buttonId ? buttonId : id;
var selection = editor._getSelection();
- var html = editor.getSelectedHTML();
- this.abbr = editor._activeElement(selection);
- this.abbrType = null;
+ var abbr = editor._activeElement(selection);
// Working around Safari issue
- if (!this.abbr && this.getPluginInstance("StatusBar") && this.getPluginInstance("StatusBar").getSelection()) {
- this.abbr = this.getPluginInstance("StatusBar").getSelection();
+ if (!abbr && this.editor.statusBar && this.editor.statusBar.getSelection()) {
+ abbr = this.editor.statusBar.getSelection();
}
- if (!(this.abbr != null && /^(acronym|abbr)$/i.test(this.abbr.nodeName))) {
- this.abbr = editor._getFirstAncestor(selection, ["acronym", "abbr"]);
+ if (!abbr || !/^(acronym|abbr)$/i.test(abbr.nodeName)) {
+ abbr = editor._getFirstAncestor(selection, ['acronym', 'abbr']);
}
- if (this.abbr != null && /^(acronym|abbr)$/i.test(this.abbr.nodeName)) {
- this.param = { title : this.abbr.title, text : this.abbr.innerHTML};
- this.abbrType = this.abbr.nodeName.toLowerCase();
- } else {
- this.param = { title : "", text : html};
- }
- this.dialog = this.openDialog("Acronym", this.makeUrlFromModulePath(this.acronymModulePath), null, null, {width:580, height:280});
+ var type = !Ext.isEmpty(abbr) ? abbr.nodeName.toLowerCase() : '';
+ this.params = {
+ abbr: abbr,
+ title: !Ext.isEmpty(abbr) ? abbr.title : '',
+ text: !Ext.isEmpty(abbr) ? abbr.innerHTML : this.editor.getSelectedHTML()
+ };
+ // Open the dialogue window
+ this.openDialogue(
+ 'Insert/Modify Acronym',
+ buttonId,
+ this.getWindowDimensions({ width: 580}, buttonId),
+ this.buildTabItemsConfig(abbr),
+ this.buildButtonsConfig(abbr, this.okHandler, this.deleteHandler),
+ (type == 'acronym') ? 1 : 0
+ );
return false;
},
-
/*
- * This function removes the given markup element
+ * Open the dialogue window
+ *
+ * @param string title: the window title
+ * @param string buttonId: the itemId of the button that was pressed
+ * @param integer dimensions: the opening width of the window
+ * @param object tabItems: the configuration of the tabbed panel
+ * @param object buttonsConfig: the configuration of the buttons
+ * @param number activeTab: index of the opening tab
+ *
+ * @return void
*/
- removeMarkup : function(element) {
- var bookmark = this.editor.getBookmark(this.editor._createRange(this.editor._getSelection()));
- var parent = element.parentNode;
- while (element.firstChild) {
- parent.insertBefore(element.firstChild, element);
+ openDialogue: function (title, buttonId, dimensions, tabItems, buttonsConfig, activeTab) {
+ this.dialog = new Ext.Window({
+ title: this.localize(title),
+ 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: buttonId,
+ listeners: {
+ close: {
+ fn: this.onClose,
+ scope: this
+ }
+ },
+ items: {
+ xtype: 'tabpanel',
+ activeTab: activeTab ? activeTab : 0,
+ defaults: {
+ xtype: 'container',
+ layout: 'form',
+ defaults: {
+ labelWidth: 150
+ }
+ },
+ listeners: {
+ tabchange: {
+ fn: this.syncHeight,
+ scope: this
+ }
+ },
+ items: tabItems
+ },
+ buttons: buttonsConfig
+ });
+ this.show();
+ },
+ /*
+ * Build the dialogue tab items config
+ *
+ * @param object element: the element being edited, if any
+ *
+ * @return object the tab items configuration
+ */
+ buildTabItemsConfig: function (element) {
+ var type = !Ext.isEmpty(element) ? element.nodeName.toLowerCase() : '';
+ var tabItems = [];
+ var abbrTabItems = [];
+ // abbr tab not shown if the current selection is an acronym
+ if (type !== 'acronym') {
+ if (!this.pageTSConfiguration.noAbbr) {
+ this.addConfigElement(this.buildDefinedTermFieldsetConfig((type == 'abbr') ? element : null, 'abbr'), abbrTabItems);
+ }
+ this.addConfigElement(this.buildUseTermFieldsetConfig((type == 'abbr') ? element : null, 'abbr'), abbrTabItems);
}
- parent.removeChild(element);
- this.editor.selectRange(this.editor.moveToBookmark(bookmark));
+ if (!Ext.isEmpty(abbrTabItems)) {
+ tabItems.push({
+ title: this.localize('Abbreviation'),
+ itemId: 'abbr',
+ items: abbrTabItems
+ });
+ }
+ var acronymTabItems = [];
+ // acronym tab not shown if the current selection is an abbr
+ if (type !== 'abbr') {
+ if (!this.pageTSConfiguration.noAcronym) {
+ this.addConfigElement(this.buildDefinedTermFieldsetConfig((type == 'acronym') ? element : null, 'acronym'), acronymTabItems);
+ }
+ this.addConfigElement(this.buildUseTermFieldsetConfig((type == 'abbr') ? element : null, 'abbr'), acronymTabItems);
+ }
+ if (!Ext.isEmpty(acronymTabItems)) {
+ tabItems.push({
+ title: this.localize('Acronym'),
+ itemId: 'acronym',
+ items: acronymTabItems
+ });
+ }
+ return tabItems;
},
-
/*
- * This function gets called when the toolbar is updated
+ * Build the dialogue buttons config
+ *
+ * @param object element: the element being edited, if any
+ * @param function okHandler: the handler for the ok button
+ * @param function deleteHandler: the handler for the delete button
+ *
+ * @return object the buttons configuration
*/
- onUpdateToolbar : function () {
- if (this.editor.getMode() === "wysiwyg" && this.editor.isEditable()) {
- var buttonId = "Acronym";
- if (this.isButtonInToolbar(buttonId)) {
- var el = this.editor.getParentElement();
- if (el) {
- this.editor._toolbarObjects[buttonId].state("enabled", !((el.nodeName.toLowerCase() == "acronym" && this.pageTSConfiguration.noAcronym) || (el.nodeName.toLowerCase() == "abbr" && this.pageTSConfiguration.noAbbr)));
- this.editor._toolbarObjects[buttonId].state("active", ((el.nodeName.toLowerCase() == "acronym" && !this.pageTSConfiguration.noAcronym) || (el.nodeName.toLowerCase() == "abbr" && !this.pageTSConfiguration.noAbbr)));
+ buildButtonsConfig: function (element, okHandler, deleteHandler) {
+ var buttonsConfig = [this.buildButtonConfig('Cancel', this.onCancel)];
+ if (element) {
+ buttonsConfig.push(this.buildButtonConfig('Delete', deleteHandler));
+ }
+ buttonsConfig.push(this.buildButtonConfig('OK', okHandler));
+ return buttonsConfig;
+ },
+ /*
+ * This function builds the configuration object for the defined Abbreviation or Acronym fieldset
+ *
+ * @param object element: the element being edited, if any
+ *
+ * @return object the fieldset configuration object
+ */
+ buildDefinedTermFieldsetConfig: function (element, type) {
+ var itemsConfig = [];
+ itemsConfig.push(Ext.apply({
+ xtype: 'combo',
+ displayField: 'term',
+ valueField: 'term',
+ fieldLabel: this.localize('Unabridged_term'),
+ itemId: 'termSelector',
+ helpTitle: this.localize('Select_a_term'),
+ tpl: '