Index: typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js (révision 8881) +++ typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js (copie de travail) @@ -368,15 +368,22 @@ HTMLArea.Editor.prototype.moveToBookmark = function (bookmark) { var startSpan = this.getBookmarkNode(bookmark, true); var endSpan = this.getBookmarkNode(bookmark, false); - + var parent; var range = this._createRange(); - // If the previous sibling is a text node, let the anchorNode have it as parent - if (startSpan.previousSibling && startSpan.previousSibling.nodeType == 3) { - range.setStart(startSpan.previousSibling, startSpan.previousSibling.data.length); + if (startSpan) { + // If the previous sibling is a text node, let the anchorNode have it as parent + if (startSpan.previousSibling && startSpan.previousSibling.nodeType == 3) { + range.setStart(startSpan.previousSibling, startSpan.previousSibling.data.length); + } else { + range.setStartBefore(startSpan); + } + parent = startSpan.parentNode; + HTMLArea.removeFromParent(startSpan); + parent.normalize(); } else { - range.setStartBefore(startSpan); + // For some reason, the startSpan was removed or its id attribute was removed so that it cannot be retrieved + range.setStart(this._doc.body, 0); } - HTMLArea.removeFromParent(startSpan); // If the bookmarked range was collapsed, the end span will not be available if (endSpan) { // If the next sibling is a text node, let the focusNode have it as parent @@ -385,7 +392,9 @@ } else { range.setEndBefore(endSpan); } + parent = endSpan.parentNode; HTMLArea.removeFromParent(endSpan); + parent.normalize(); } else { range.collapse(true); } Index: typo3/sysext/rtehtmlarea/mod6/class.tx_rtehtmlarea_parse_html.php =================================================================== --- typo3/sysext/rtehtmlarea/mod6/class.tx_rtehtmlarea_parse_html.php (révision 8881) +++ typo3/sysext/rtehtmlarea/mod6/class.tx_rtehtmlarea_parse_html.php (copie de travail) @@ -124,7 +124,11 @@ $HTMLParser = t3lib_div::makeInstance('t3lib_parsehtml'); if (is_array($thisConfig['enableWordClean.'])) { - $HTMLparserConfig = is_array($thisConfig['enableWordClean.']['HTMLparser.']) ? $HTMLParser->HTMLparserConfig($thisConfig['enableWordClean.']['HTMLparser.']) : ''; + $HTMLparserConfig = $thisConfig['enableWordClean.']['HTMLparser.']; + if (is_array($HTMLparserConfig)) { + $this->keepSpanTagsWithId($HTMLparserConfig); + $HTMLparserConfig = $HTMLParser->HTMLparserConfig($HTMLparserConfig); + } } if (is_array($HTMLparserConfig)) { $html = $HTMLParser->HTMLcleaner($html, $HTMLparserConfig[0], $HTMLparserConfig[1], $HTMLparserConfig[2], $HTMLparserConfig[3]); @@ -140,6 +144,50 @@ } return $html; } + /** + * Modify incoming HTMLparser config in an attempt to keep span tags with id + * Such tags are used by the RTE in order to restore the cursor position when the cleaning operation is completed. + * + * @param array $HTMLparserConfig: incoming HTMLParser configuration (wil be modified) + * @return void + */ + protected function keepSpanTagsWithId(&$HTMLparserConfig) { + // Allow span tag + if (isset($HTMLparserConfig['allowTags'])) { + if (!t3lib_div::inList($HTMLparserConfig['allowTags'], 'span')) { + $HTMLparserConfig['allowTags'] .= ',span'; + } + } else { + $HTMLparserConfig['allowTags'] = 'span'; + } + // Allow attributes on span tags + if (isset($HTMLparserConfig['noAttrib']) && t3lib_div::inList($HTMLparserConfig['noAttrib'], 'span')) { + $HTMLparserConfig['noAttrib'] = t3lib_div::rmFromList('span', $HTMLparserConfig['noAttrib']); + } + // Do not remove span tags + if (isset($HTMLparserConfig['removeTags']) && t3lib_div::inList($HTMLparserConfig['removeTags'], 'span')) { + $HTMLparserConfig['removeTags'] = t3lib_div::rmFromList('span', $HTMLparserConfig['removeTags']); + } + // Review the tags array + if (is_array($HTMLparserConfig['tags.'])) { + // Allow span tag + if (isset($HTMLparserConfig['tags.']['span']) && !$HTMLparserConfig['tags.']['span']) { + $HTMLparserConfig['tags.']['span'] = 1; + } + if (is_array($HTMLparserConfig['tags.']['span.'])) { + if (isset($HTMLparserConfig['tags.']['span.']['allowedAttribs'])) { + if (!$HTMLparserConfig['tags.']['span.']['allowedAttribs']) { + $HTMLparserConfig['tags.']['span.']['allowedAttribs'] = 'id'; + } else if (!t3lib_div::inList($HTMLparserConfig['tags.']['span.']['allowedAttribs'], 'id')) { + $HTMLparserConfig['tags.']['span.']['allowedAttribs'] .= ',id'; + } + } + if (isset($HTMLparserConfig['tags.']['span.']['fixAttrib.']['id.']['unset'])) { + unset($HTMLparserConfig['tags.']['span.']['fixAttrib.']['id.']['unset']); + } + } + } + } } if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/mod6/class.tx_rtehtmlarea_parse_html.php']) { include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/mod6/class.tx_rtehtmlarea_parse_html.php']);