Index: typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js (révision 7230) +++ typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js (copie de travail) @@ -3081,7 +3081,49 @@ } return null; }; - +/* + * Get the node whose contents are currently fully selected + * + * @param array selection: the current selection + * @param array range: the range of the current selection + * @param array ancestors: the array of ancestors node of the current selection + * + * @return object the fully selected node, if any, null otherwise + */ +HTMLArea.Editor.prototype.getFullySelectedNode = function (selection, range, ancestors) { + var node, fullNodeSelected = false; + if (!selection) { + var selection = this._getSelection(); + } + if (!this._selectionEmpty(selection)) { + if (!range) { + var range = this._createRange(selection); + } + if (!ancestors) { + var ancestors = this.getAllAncestors(); + } + Ext.each(ancestors, function (ancestor) { + if (Ext.isIE) { + fullNodeSelected = (selection.type !== 'Control' && ancestor.innerText == range.text) || (selection.type === 'Control' && ancestor.innerText == range.item(0).text); + } else { + fullNodeSelected = (ancestor.textContent == range.toString()); + } + if (fullNodeSelected) { + node = ancestor; + return false; + } + }); + // Working around bug with WebKit selection + if (Ext.isWebKit && !fullNodeSelected) { + var statusBarSelection = this.statusBar ? this.statusBar.getSelection() : null; + if (statusBarSelection && statusBarSelection.textContent == range.toString()) { + fullNodeSelected = true; + node = statusBarSelection; + } + } + } + return fullNodeSelected ? node : null; +}; /*************************************************** * Category: EVENT HANDLERS ***************************************************/ Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js (révision 7230) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js (copie de travail) @@ -224,13 +224,13 @@ * This function applies to the selection the markup chosen in the drop-down list or corresponding to the button pressed */ applyInlineElement : function (editor, element) { - editor.focusEditor(); + editor.focus(); var selection = editor._getSelection(); var range = editor._createRange(selection); var parent = editor.getParentElement(selection, range); var ancestors = editor.getAllAncestors(); var elementIsAncestor = false; - var selectionEmpty = editor._selectionEmpty(selection); + var fullNodeSelected = false; if (HTMLArea.is_ie) { var bookmark = editor.getBookmark(range); } @@ -242,30 +242,13 @@ break; } } - if (!selectionEmpty) { - var statusBarSelection = (editor.statusBar ? editor.statusBar.getSelection() : null); - // The selection is not empty. - for (var i = 0; i < ancestors.length; ++i) { - fullNodeSelected = (HTMLArea.is_ie && ((selection.type !== "Control" && ancestors[i].innerText === range.text) || (selection.type === "Control" && ancestors[i].innerText === range.item(0).text))) - || (HTMLArea.is_gecko && ((statusBarSelection === ancestors[i] && ancestors[i].textContent === range.toString()) || (!statusBarSelection && ancestors[i].textContent === range.toString()))); - if (fullNodeSelected) { - if (!HTMLArea.isBlockElement(ancestors[i])) { - parent = ancestors[i]; - } - break; - } + if (!editor._selectionEmpty(selection)) { + var fullySelectedNode = editor.getFullySelectedNode(selection, range, ancestors); + fullNodeSelected = this.isInlineElement(fullySelectedNode); + if (fullNodeSelected) { + parent = fullySelectedNode; } - // Working around bug in Safari selectNodeContents - if (!fullNodeSelected && HTMLArea.is_safari && statusBarSelection && this.isInlineElement(statusBarSelection) && statusBarSelection.textContent === range.toString()) { - fullNodeSelected = true; - parent = statusBarSelection; - } - - var fullNodeTextSelected = (HTMLArea.is_gecko && parent.textContent === range.toString()) - || (HTMLArea.is_ie && parent.innerText === range.text); - if (fullNodeTextSelected && elementIsAncestor) { - fullNodeSelected = true; - } + var statusBarSelection = (editor.statusBar ? editor.statusBar.getSelection() : null); if (element !== "none" && !(fullNodeSelected && elementIsAncestor)) { // Add markup var newElement = editor._doc.createElement(element); @@ -274,17 +257,17 @@ } if (HTMLArea.is_gecko) { if (fullNodeSelected && statusBarSelection) { - if (HTMLArea.is_safari) { - editor.selectNode(parent); - selection = editor._getSelection(); - range = editor._createRange(selection); + if (Ext.isWebKit) { + newElement = parent.parentNode.insertBefore(newElement, statusBarSelection); + newElement.appendChild(statusBarSelection); + newElement.normalize(); } else { range.selectNode(parent); + editor.wrapWithInlineElement(newElement, selection, range); } - } - editor.wrapWithInlineElement(newElement, selection, range); - if (fullNodeSelected && statusBarSelection && !HTMLArea.is_safari) { editor.selectNodeContents(newElement.lastChild, false); + } else { + editor.wrapWithInlineElement(newElement, selection, range); } range.detach(); } else { @@ -313,7 +296,11 @@ if (elementIsAncestor) { parent = ancestors[elementAncestorIndex]; } + var parentElement = parent.parentNode; editor.removeMarkup(parent); + if (Ext.isWebKit && this.isInlineElement(parentElement)) { + editor.selectNodeContents(parentElement, false); + } } } } else { @@ -378,37 +365,26 @@ } return newElement; }, - /* * This function gets called when the toolbar is updated */ onUpdateToolbar : function (button, mode, selectionEmpty, ancestors, endPointsInSameBlock) { var editor = this.editor; if (mode === "wysiwyg" && editor.isEditable()) { - var tagName = false, fullNodeSelected = false; - var sel = editor._getSelection(); - var range = editor._createRange(sel); - var parent = editor.getParentElement(sel); + var tagName = false, + fullNodeSelected = false; + var selection = editor._getSelection(); + var range = editor._createRange(selection); + var parent = editor.getParentElement(selection); if (parent && !HTMLArea.isBlockElement(parent)) { tagName = parent.nodeName.toLowerCase(); } if (!selectionEmpty) { - var statusBarSelection = editor.statusBar ? editor.statusBar.getSelection() : null; - for (var i = 0, n = ancestors.length; i < n; ++i) { - fullNodeSelected = (statusBarSelection === ancestors[i]) - && ((HTMLArea.is_gecko && ancestors[i].textContent === range.toString()) || (HTMLArea.is_ie && ((sel.type !== "Control" && ancestors[i].innerText === range.text) || (sel.type === "Control" && ancestors[i].innerText === range.item(0).text)))); - if (fullNodeSelected) { - if (!HTMLArea.isBlockElement(ancestors[i])) { - tagName = ancestors[i].nodeName.toLowerCase(); - } - break; - } + var fullySelectedNode = editor.getFullySelectedNode(selection, range, ancestors); + fullNodeSelected = this.isInlineElement(fullySelectedNode); + if (fullNodeSelected) { + tagName = fullySelectedNode.nodeName.toLowerCase(); } - // Working around bug in Safari selectNodeContents - if (!fullNodeSelected && HTMLArea.is_safari && statusBarSelection && this.isInlineElement(statusBarSelection) && statusBarSelection.textContent === range.toString()) { - fullNodeSelected = true; - tagName = statusBarSelection.nodeName.toLowerCase(); - } } var selectionInInlineElement = tagName && this.REInlineElements.test(tagName); var disabled = !endPointsInSameBlock || (fullNodeSelected && !tagName) || (selectionEmpty && !selectionInInlineElement); @@ -426,13 +402,12 @@ return true; } }, this); - button.setInactive(!activeButton); + button.setInactive(!activeButton && this.convertBtn[button.itemId] !== tagName); button.setDisabled(disabled); break; } } }, - /* * This function updates the drop-down list of inline elemenents */ Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/SelectFont/select-font.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/SelectFont/select-font.js (révision 7230) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/SelectFont/select-font.js (copie de travail) @@ -63,21 +63,19 @@ this.allowedAttributes.push("className"); } } - /* * Registering plugin "About" information */ var pluginInformation = { - version : "1.0", - developer : "Stanislas Rolland", - developerUrl : "http://www.sjbr.ca/", - copyrightOwner : "Stanislas Rolland", - sponsor : "SJBR", - sponsorUrl : "http://www.sjbr.ca/", - license : "GPL" + version : '2.0', + developer : 'Stanislas Rolland', + developerUrl : 'http://www.sjbr.ca/', + copyrightOwner : 'Stanislas Rolland', + sponsor : 'SJBR', + sponsorUrl : 'http://www.sjbr.ca/', + license : 'GPL' }; this.registerPluginInformation(pluginInformation); - /* * Registering the dropdowns */ @@ -138,19 +136,29 @@ FontName : "font-family", FontSize : "font-size" }, - /* * This function gets called when some font style or font size was selected from the dropdown lists */ - onChange : function (editor, combo, record, index) { + onChange: function (editor, combo, record, index) { var param = combo.getValue(); - editor.focusEditor(); - var selection = editor._getSelection(), - range = editor._createRange(selection), - statusBarSelection = editor.statusBar ? editor.statusBar.getSelection() : null, - element; - if (editor._selectionEmpty(selection)) { - element = editor.getParentElement(selection, range); + editor.focus(); + var element, + fullNodeSelected = false; + var selection = editor._getSelection(); + var range = editor._createRange(selection); + var parent = editor.getParentElement(selection, range); + var selectionEmpty = editor._selectionEmpty(selection); + var statusBarSelection = editor.statusBar ? editor.statusBar.getSelection() : null; + if (!selectionEmpty) { + var ancestors = editor.getAllAncestors(); + var fullySelectedNode = editor.getFullySelectedNode(selection, range, ancestors); + if (fullySelectedNode) { + fullNodeSelected = true; + parent = fullySelectedNode; + } + } + if (selectionEmpty || fullNodeSelected) { + element = parent; // Set the style attribute this.setStyle(element, combo.itemId, param); // Remove the span tag if it has no more attribute @@ -177,7 +185,6 @@ } return false; }, - /* * This function sets the style attribute on the element * Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Color/typo3color.js =================================================================== --- typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Color/typo3color.js (révision 7230) +++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Color/typo3color.js (copie de travail) @@ -30,51 +30,47 @@ * TYPO3 SVN ID: $Id$ */ TYPO3Color = HTMLArea.Plugin.extend({ - - constructor : function(editor, pluginName) { + constructor: function(editor, pluginName) { this.base(editor, pluginName); }, - /* * This function gets called by the class constructor */ - configurePlugin : function(editor) { - + configurePlugin: function(editor) { this.buttonsConfiguration = this.editorConfiguration.buttons; this.colorsConfiguration = this.editorConfiguration.colors; this.disableColorPicker = this.editorConfiguration.disableColorPicker; - // Coloring will use the style attribute if (this.editor.plugins.TextStyle && this.editor.plugins.TextStyle.instance) { - this.editor.plugins.TextStyle.instance.addAllowedAttribute("style"); + this.editor.plugins.TextStyle.instance.addAllowedAttribute('style'); this.allowedAttributes = this.editor.plugins.TextStyle.instance.allowedAttributes; - } + } if (this.editor.plugins.InlineElements && this.editor.plugins.InlineElements.instance) { - this.editor.plugins.InlineElements.instance.addAllowedAttribute("style"); + this.editor.plugins.InlineElements.instance.addAllowedAttribute('style'); if (!this.allowedAllowedAttributes) { this.allowedAttributes = this.editor.plugins.InlineElements.instance.allowedAttributes; } } if (this.editor.plugins.BlockElements && this.editor.plugins.BlockElements.instance) { - this.editor.plugins.BlockElements.instance.addAllowedAttribute("style"); + this.editor.plugins.BlockElements.instance.addAllowedAttribute('style'); } if (!this.allowedAttributes) { - this.allowedAttributes = new Array("id", "title", "lang", "xml:lang", "dir", "class", "style"); + this.allowedAttributes = new Array('id', 'title', 'lang', 'xml:lang', 'dir', 'class', 'style'); if (HTMLArea.is_ie) { - this.allowedAttributes.push("className"); + this.allowedAttributes.push('className'); } } /* * Registering plugin "About" information */ var pluginInformation = { - version : "4.0", - developer : "Stanislas Rolland", - developerUrl : "http://www.sjbr.ca/", - copyrightOwner : "Stanislas Rolland", - sponsor : "SJBR", - sponsorUrl : "http://www.sjbr.ca/", - license : "GPL" + version : '4.0', + developer : 'Stanislas Rolland', + developerUrl : 'http://www.sjbr.ca/', + copyrightOwner : 'Stanislas Rolland', + sponsor : 'SJBR', + sponsorUrl : 'http://www.sjbr.ca/', + license : 'GPL' }; this.registerPluginInformation(pluginInformation); /* @@ -87,7 +83,7 @@ var buttonConfiguration = { id : buttonId, tooltip : this.localize(buttonId), - action : "onButtonPress", + action : 'onButtonPress', hotKey : (this.buttonsConfiguration[button[1]] ? this.buttonsConfiguration[button[1]].hotKey : null), dialog : true }; @@ -342,11 +338,24 @@ this.restoreSelection(); var buttonId = this.dialog.arguments.buttonId; var color = '#' + this.dialog.find('itemId', 'color')[0].getValue(); + this.editor.focus(); + var element, + fullNodeSelected = false; var selection = this.editor._getSelection(); + var range = this.editor._createRange(selection); + var parent = this.editor.getParentElement(selection, range); + var selectionEmpty = this.editor._selectionEmpty(selection); var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null; - var range = this.editor._createRange(selection); - if (this.editor._selectionEmpty(selection)) { - var element = this.editor.getParentElement(selection, range); + if (!selectionEmpty) { + var ancestors = this.editor.getAllAncestors(); + var fullySelectedNode = this.editor.getFullySelectedNode(selection, range, ancestors); + if (fullySelectedNode) { + fullNodeSelected = true; + parent = fullySelectedNode; + } + } + if (selectionEmpty || fullNodeSelected) { + element = parent; // Set the color in the style attribute element.style[this.styleProperty[buttonId]] = color; // Remove the span tag if it has no more attribute