Feature #19439 ยป rtehtmlarea_feature_9521.patch
typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js (copie de travail) | ||
---|---|---|
*
|
||
* (c) 2002-2004, interactivetools.com, inc.
|
||
* (c) 2003-2004 dynarch.com
|
||
* (c) 2004-2008 Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
|
||
* (c) 2004-2008 Stanislas Rolland <typo3(arobas)sjbr.ca>
|
||
* All rights reserved
|
||
*
|
||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||
... | ... | |
this.insertNodeAtSelection(fragment);
|
||
};
|
||
/*
|
||
* Wrap the range with an inline element
|
||
*
|
||
* @param string element: the node that will wrap the range
|
||
* @param object selection: the selection object
|
||
* @param object range: the range to be wrapped
|
||
*
|
||
* @return void
|
||
*/
|
||
HTMLArea.prototype.wrapWithInlineElement = function(element, selection, range) {
|
||
// Sometimes Opera raises a bad boundary points error
|
||
if (HTMLArea.is_opera) {
|
||
try {
|
||
range.surroundContents(element);
|
||
} catch(e) {
|
||
element.appendChild(range.extractContents());
|
||
range.insertNode(element);
|
||
}
|
||
} else {
|
||
range.surroundContents(element);
|
||
element.normalize();
|
||
}
|
||
// Sometimes Firefox inserts empty elements just outside the boundaries of the range
|
||
var neighbour = element.previousSibling;
|
||
if (neighbour && (neighbour.nodeType != 3) && !/\S/.test(neighbour.textContent)) {
|
||
HTMLArea.removeFromParent(neighbour);
|
||
}
|
||
neighbour = element.nextSibling;
|
||
if (neighbour && (neighbour.nodeType != 3) && !/\S/.test(neighbour.textContent)) {
|
||
HTMLArea.removeFromParent(neighbour);
|
||
}
|
||
this.selectNodeContents(element, false);
|
||
};
|
||
/***************************************************
|
||
* EVENTS HANDLERS
|
||
***************************************************/
|
typo3/sysext/rtehtmlarea/htmlarea/htmlarea-ie.js (copie de travail) | ||
---|---|---|
/*
|
||
* Get the deepest node that contains both endpoints of the current selection.
|
||
*/
|
||
HTMLArea.prototype.getParentElement = function(sel) {
|
||
if(!sel) var sel = this._getSelection();
|
||
var range = this._createRange(sel);
|
||
switch (sel.type) {
|
||
HTMLArea.prototype.getParentElement = function(selection, range) {
|
||
if (!selection) var selection = this._getSelection();
|
||
if (typeof(range) === "undefined") {
|
||
var range = this._createRange(selection);
|
||
}
|
||
switch (selection.type) {
|
||
case "Text":
|
||
case "None":
|
||
var el = range.parentElement();
|
||
... | ... | |
range.pasteHTML(html);
|
||
};
|
||
/*
|
||
* Wrap the range with an inline element
|
||
*
|
||
* @param string element: the node that will wrap the range
|
||
* @param object selection: the selection object
|
||
* @param object range: the range to be wrapped
|
||
*
|
||
* @return void
|
||
*/
|
||
HTMLArea.prototype.wrapWithInlineElement = function(element, selection, range) {
|
||
var nodeName = element.nodeName;
|
||
var parent = this.getParentElement(selection, range);
|
||
var bookmark = this.getBookmark(range);
|
||
if (selection.type !== "Control") {
|
||
var rangeStart = range.duplicate();
|
||
rangeStart.collapse(true);
|
||
var parentStart = rangeStart.parentElement();
|
||
var rangeEnd = range.duplicate();
|
||
rangeEnd.collapse(true);
|
||
var newRange = this._createRange();
|
||
|
||
var parentEnd = rangeEnd.parentElement();
|
||
var upperParentStart = parentStart;
|
||
if (parentStart !== parent) {
|
||
while (upperParentStart.parentNode !== parent) {
|
||
upperParentStart = upperParentStart.parentNode;
|
||
}
|
||
}
|
||
|
||
element.innerHTML = range.htmlText;
|
||
// IE eats spaces on the start boundary
|
||
if (range.htmlText.charAt(0) === "\x20") {
|
||
element.innerHTML = " " + element.innerHTML;
|
||
}
|
||
var elementClone = element.cloneNode(true);
|
||
range.pasteHTML(element.outerHTML);
|
||
// IE inserts the element as the last child of the start container
|
||
if (parentStart !== parent
|
||
&& parentStart.lastChild
|
||
&& parentStart.lastChild.nodeType === 1
|
||
&& parentStart.lastChild.nodeName.toLowerCase() === nodeName) {
|
||
parent.insertBefore(elementClone, upperParentStart.nextSibling);
|
||
parentStart.removeChild(parentStart.lastChild);
|
||
// Sometimes an empty previous sibling was created
|
||
if (elementClone.previousSibling
|
||
&& elementClone.previousSibling.nodeType === 1
|
||
&& !elementClone.previousSibling.innerText) {
|
||
parent.removeChild(elementClone.previousSibling);
|
||
}
|
||
// The bookmark will not work anymore
|
||
newRange.moveToElementText(elementClone);
|
||
newRange.collapse(false);
|
||
newRange.select();
|
||
} else {
|
||
// Working around IE boookmark bug
|
||
if (parentStart != parentEnd) {
|
||
var newRange = this._createRange();
|
||
if (newRange.moveToBookmark(bookmark)) {
|
||
newRange.collapse(false);
|
||
newRange.select();
|
||
}
|
||
} else {
|
||
range.collapse(false);
|
||
}
|
||
}
|
||
// normalize() is not available in IE5.5
|
||
try {
|
||
parent.normalize();
|
||
} catch(e) { }
|
||
} else {
|
||
element = parent.parentNode.insertBefore(element, parent);
|
||
element.appendChild(parent);
|
||
this.moveToBookmark(bookmark);
|
||
}
|
||
};
|
||
/***************************************************
|
||
* EVENT HANDLERS
|
||
***************************************************/
|
typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js (copie de travail) | ||
---|---|---|
return oEl;
|
||
};
|
||
/*
|
||
* This function removes the given markup element
|
||
*
|
||
* @param object element: the inline element to be removed, content being preserved
|
||
*
|
||
* @return void
|
||
*/
|
||
HTMLArea.prototype.removeMarkup = function(element) {
|
||
var bookmark = this.getBookmark(this._createRange(this._getSelection()));
|
||
var parent = element.parentNode;
|
||
while (element.firstChild) {
|
||
parent.insertBefore(element.firstChild, element);
|
||
}
|
||
parent.removeChild(element);
|
||
this.selectRange(this.moveToBookmark(bookmark));
|
||
};
|
||
/*
|
||
* This function verifies if the element has any allowed attributes
|
||
*
|
||
* @param object element: the DOM element
|
||
* @param array allowedAttributes: array of allowed attribute names
|
||
*
|
||
* @return boolean true if the element has one of the allowed attributes
|
||
*/
|
||
HTMLArea.hasAllowedAttributes = function(element,allowedAttributes) {
|
||
var value;
|
||
for (var i = allowedAttributes.length; --i >= 0;) {
|
||
value = element.getAttribute(allowedAttributes[i]);
|
||
if (value) {
|
||
// IE returns an object on getAttribute("style");
|
||
if (typeof(value) == "object") {
|
||
if (allowedAttributes[i] == "style" && value.cssText) {
|
||
return true;
|
||
}
|
||
} else {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
/***************************************************
|
||
* SELECTIONS AND RANGES
|
||
***************************************************/
|
||
... | ... | |
};
|
||
/*
|
||
* This function determines if the end poins of the current selection are within the same block
|
||
*
|
||
* @return boolean true if the end points of the current selection are inside the same block element
|
||
*/
|
||
HTMLArea.prototype.endPointsInSameBlock = function() {
|
||
var selection = this._getSelection();
|
||
if (this._selectionEmpty(selection)) {
|
||
return true;
|
||
} else {
|
||
var parent = this.getParentElement(selection);
|
||
var endBlocks = this.getEndBlocks(selection);
|
||
return (endBlocks.start === endBlocks.end && !/^(table|thead|tbody|tfoot|tr)$/i.test(parent.nodeName));
|
||
}
|
||
};
|
||
/*
|
||
* Get the deepest ancestor of the selection that is of the specified type
|
||
* Borrowed from Xinha (is not htmlArea) - http://xinha.gogo.co.nz/
|
||
*/
|
typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js (copie de travail) | ||
---|---|---|
* This function gets called by the base constructor
|
||
*/
|
||
configurePlugin : function (editor) {
|
||
|
||
this.allowedAttributes = new Array("id", "title", "lang", "xml:lang", "dir", (HTMLArea.is_gecko?"class":"className"));
|
||
|
||
// Setting the array of allowed attributes on inline elements
|
||
if (this.editor.plugins.TextStyle && this.editor.plugins.TextStyle.instance) {
|
||
this.allowedAttributes = this.editor.plugins.TextStyle.instance.allowedAttributes;
|
||
} else {
|
||
this.allowedAttributes = new Array("id", "title", "lang", "xml:lang", "dir", (HTMLArea.is_gecko?"class":"className"));
|
||
}
|
||
// Getting tags configuration for inline elements
|
||
if (this.editorConfiguration.buttons.textstyle) {
|
||
this.tags = this.editorConfiguration.buttons.textstyle.tags;
|
||
}
|
||
... | ... | |
},
|
||
|
||
/*
|
||
* This function adds an attribute to the array of allowed attributes on inline elements
|
||
*
|
||
* @param string attribute: the name of the attribute to be added to the array
|
||
*
|
||
* @return void
|
||
*/
|
||
addAllowedAttribute : function (attribute) {
|
||
this.allowedAttributes.push(attribute);
|
||
},
|
||
|
||
/*
|
||
* This function gets called when some inline element button was pressed.
|
||
*/
|
||
onButtonPress : function (editor, id) {
|
||
... | ... | |
var elementIsAncestor = false;
|
||
var selectionEmpty = editor._selectionEmpty(selection);
|
||
if (HTMLArea.is_ie) {
|
||
var bookmark = range.getBookmark();
|
||
var bookmark = editor.getBookmark(range);
|
||
}
|
||
// Check if the chosen element is among the ancestors
|
||
for (var i = 0; i < ancestors.length; ++i) {
|
||
... | ... | |
if (!selectionEmpty) {
|
||
// The selection is not empty.
|
||
for (var i = 0; i < ancestors.length; ++i) {
|
||
fullNodeSelected = (HTMLArea.is_ie && ((editor._statusBarTree.selected === ancestors[i] && ancestors[i].innerText === range.text) || (!editor._statusBarTree.selected && ancestors[i].innerText === range.text)))
|
||
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 && ((editor._statusBarTree.selected === ancestors[i] && ancestors[i].textContent === range.toString()) || (!editor._statusBarTree.selected && ancestors[i].textContent === range.toString())));
|
||
if (fullNodeSelected) {
|
||
if (!HTMLArea.isBlockElement(ancestors[i])) {
|
||
... | ... | |
}
|
||
if (element !== "none" && !(fullNodeSelected && elementIsAncestor)) {
|
||
// Add markup
|
||
var newElement = editor._doc.createElement(element);
|
||
if (element === "bdo") {
|
||
newElement.setAttribute("dir", "rtl");
|
||
}
|
||
if (HTMLArea.is_gecko) {
|
||
if (fullNodeSelected && editor._statusBarTree.selected) {
|
||
if (HTMLArea.is_safari) {
|
||
this.editor.selectNode(parent);
|
||
range = this.editor._createRange(this.editor._getSelection());
|
||
editor.selectNode(parent);
|
||
selection = editor._getSelection();
|
||
range = editor._createRange(selection);
|
||
} else {
|
||
range.selectNode(parent);
|
||
}
|
||
}
|
||
var newElement = this.editor._doc.createElement(element);
|
||
if (element === "bdo") {
|
||
newElement.setAttribute("dir", "rtl");
|
||
}
|
||
// Sometimes Opera 9.25 raises a bad boundary points error
|
||
if (HTMLArea.is_opera) {
|
||
try {
|
||
range.surroundContents(newElement);
|
||
} catch(e) {
|
||
newElement.appendChild(range.extractContents());
|
||
range.insertNode(newElement);
|
||
}
|
||
} else {
|
||
range.surroundContents(newElement);
|
||
}
|
||
// Sometimes Firefox inserts empty elements just outside the boundaries of the range
|
||
var neighbour = newElement.previousSibling;
|
||
if (neighbour && (neighbour.nodeType != 3) && !/\S/.test(neighbour.textContent)) {
|
||
HTMLArea.removeFromParent(neighbour);
|
||
}
|
||
neighbour = newElement.nextSibling;
|
||
if (neighbour && (neighbour.nodeType != 3) && !/\S/.test(neighbour.textContent)) {
|
||
HTMLArea.removeFromParent(neighbour);
|
||
}
|
||
editor.wrapWithInlineElement(newElement, selection, range);
|
||
if (fullNodeSelected && editor._statusBarTree.selected && !HTMLArea.is_safari) {
|
||
this.editor.selectNodeContents(newElement.lastChild, false);
|
||
} else {
|
||
this.editor.selectNodeContents(newElement, false);
|
||
editor.selectNodeContents(newElement.lastChild, false);
|
||
}
|
||
range.detach();
|
||
} else {
|
||
... | ... | |
editor.selectNodeContents(newElement, false);
|
||
}
|
||
} else {
|
||
var rangeStart = range.duplicate();
|
||
rangeStart.collapse(true);
|
||
var parentStart = rangeStart.parentElement();
|
||
var rangeEnd = range.duplicate();
|
||
rangeEnd.collapse(true);
|
||
var newRange = editor._createRange();
|
||
|
||
var parentEnd = rangeEnd.parentElement();
|
||
var upperParentStart = parentStart;
|
||
if (parentStart !== parent) {
|
||
while (upperParentStart.parentNode !== parent) {
|
||
upperParentStart = upperParentStart.parentNode;
|
||
}
|
||
}
|
||
|
||
var newElement = editor._doc.createElement(element);
|
||
newElement.innerHTML = range.htmlText;
|
||
// IE eats spaces on the start boundary
|
||
if (range.htmlText.charAt(0) === "\x20") {
|
||
newElement.innerHTML = " " + newElement.innerHTML;
|
||
}
|
||
var newElementClone = newElement.cloneNode(true);
|
||
range.pasteHTML(newElement.outerHTML);
|
||
// IE inserts the element as the last child of the start container
|
||
if (parentStart !== parent
|
||
&& parentStart.lastChild
|
||
&& parentStart.lastChild.nodeType === 1
|
||
&& parentStart.lastChild.nodeName.toLowerCase() === element) {
|
||
parent.insertBefore(newElementClone, upperParentStart.nextSibling);
|
||
parentStart.removeChild(parentStart.lastChild);
|
||
// Sometimes an empty previous sibling was created
|
||
if (newElementClone.previousSibling
|
||
&& newElementClone.previousSibling.nodeType === 1
|
||
&& !newElementClone.previousSibling.innerText) {
|
||
parent.removeChild(newElementClone.previousSibling);
|
||
}
|
||
// The bookmark will not work anymore
|
||
newRange.moveToElementText(newElementClone);
|
||
newRange.collapse(false);
|
||
newRange.select();
|
||
} else {
|
||
// Working around IE boookmark bug
|
||
if (parentStart != parentEnd) {
|
||
var newRange = editor._createRange();
|
||
if (newRange.moveToBookmark(bookmark)) {
|
||
newRange.collapse(false);
|
||
newRange.select();
|
||
}
|
||
} else {
|
||
range.collapse(false);
|
||
}
|
||
}
|
||
try { // normalize() is not available in IE5.5
|
||
parent.normalize();
|
||
} catch(e) { }
|
||
editor.wrapWithInlineElement(newElement, selection, range);
|
||
}
|
||
}
|
||
} else {
|
||
... | ... | |
if (elementIsAncestor) {
|
||
parent = ancestors[elementAncestorIndex];
|
||
}
|
||
this.removeMarkup(parent);
|
||
editor.removeMarkup(parent);
|
||
}
|
||
}
|
||
} else {
|
||
... | ... | |
if (elementIsAncestor) {
|
||
parent = ancestors[elementAncestorIndex];
|
||
}
|
||
this.removeMarkup(parent);
|
||
editor.removeMarkup(parent);
|
||
} else {
|
||
var bookmark = this.editor.getBookmark(range);
|
||
var newElement = this.remapMarkup(parent, element);
|
||
... | ... | |
},
|
||
|
||
/*
|
||
* This function removes the given markup element
|
||
*/
|
||
removeMarkup : function(element) {
|
||
var bookmark = this.editor.getBookmark(this.editor._createRange(this.editor._getSelection()));
|
||
var parent = element.parentNode;
|
||
while (element.firstChild) {
|
||
parent.insertBefore(element.firstChild, element);
|
||
}
|
||
parent.removeChild(element);
|
||
this.editor.selectRange(this.editor.moveToBookmark(bookmark));
|
||
},
|
||
|
||
/*
|
||
* This function gets called when the toolbar is updated
|
||
*/
|
||
onUpdateToolbar : function () {
|
||
... | ... | |
var ancestors = editor.getAllAncestors();
|
||
for (var i = 0; i < ancestors.length; ++i) {
|
||
fullNodeSelected = (editor._statusBarTree.selected === ancestors[i])
|
||
&& ((HTMLArea.is_gecko && ancestors[i].textContent === range.toString()) || (HTMLArea.is_ie && ancestors[i].innerText === range.text));
|
||
&& ((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();
|
||
... | ... | |
}
|
||
}
|
||
var selectionInInlineElement = tagName && this.REInlineElements.test(tagName);
|
||
var disabled = !this.endPointsInSameBlock() || (fullNodeSelected && !tagName) || (selectionEmpty && !selectionInInlineElement);
|
||
var disabled = !editor.endPointsInSameBlock() || (fullNodeSelected && !tagName) || (selectionEmpty && !selectionInInlineElement);
|
||
|
||
var obj = editor.config.customSelects["FormatText"];
|
||
if ((typeof(obj) !== "undefined") && (typeof(editor._toolbarObjects[obj.id]) !== "undefined")) {
|
||
... | ... | |
},
|
||
|
||
/*
|
||
* This function determines if the end poins of the current selection are within the same block
|
||
*/
|
||
endPointsInSameBlock : function() {
|
||
var selection = this.editor._getSelection();
|
||
if (this.editor._selectionEmpty(selection)) {
|
||
return true;
|
||
} else {
|
||
var parent = this.editor.getParentElement(selection);
|
||
var endBlocks = this.editor.getEndBlocks(selection);
|
||
return (endBlocks.start === endBlocks.end && !/^(table|thead|tbody|tfoot|tr)$/i.test(parent.nodeName));
|
||
}
|
||
},
|
||
|
||
/*
|
||
* This function updates the drop-down list of inline elemenents
|
||
*/
|
||
updateValue : function (editor, obj, tagName, selectionEmpty, fullNodeSelected, disabled) {
|
typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/text-style.js (copie de travail) | ||
---|---|---|
*/
|
||
this.REInlineTags = /^(abbr|acronym|b|bdo|big|cite|code|del|dfn|em|i|ins|kbd|q|samp|small|span|strike|strong|sub|sup|tt|u|var)$/;
|
||
|
||
// Allowed attributes on inline elements
|
||
this.allowedAttributes = new Array("id", "title", "lang", "xml:lang", "dir", (HTMLArea.is_gecko?"class":"className"));
|
||
|
||
/*
|
||
* Registering plugin "About" information
|
||
*/
|
||
... | ... | |
isInlineElement : function (el) {
|
||
return el && (el.nodeType === 1) && this.REInlineTags.test(el.nodeName.toLowerCase());
|
||
},
|
||
|
||
/*
|
||
* This function adds an attribute to the array of allowed attributes on inline elements
|
||
*
|
||
* @param string attribute: the name of the attribute to be added to the array
|
||
*
|
||
* @return void
|
||
*/
|
||
addAllowedAttribute : function (attribute) {
|
||
this.allowedAttributes.push(attribute);
|
||
},
|
||
/*
|
||
* This function gets called when some style in the drop-down list applies it to the highlighted textt
|
||
*/
|
||
onChange : function (editor, buttonId) {
|
||
... | ... | |
// The selection is not empty, nor full element
|
||
if (className !== "none") {
|
||
// Add span element with class attribute
|
||
var newElement = editor._doc.createElement("span");
|
||
HTMLArea._addClass(newElement, className);
|
||
editor.wrapWithInlineElement(newElement, selection, range);
|
||
if (HTMLArea.is_gecko) {
|
||
var newElement = this.editor._doc.createElement("span");
|
||
HTMLArea._addClass(newElement, className);
|
||
range.surroundContents(newElement);
|
||
newElement.normalize();
|
||
parent.normalize();
|
||
// Firefox sometimes inserts empty elements just outside the boundaries of the range
|
||
var neighbour = newElement.previousSibling;
|
||
if (neighbour && (neighbour.nodeType != 3) && !/\S/.test(neighbour.textContent)) {
|
||
HTMLArea.removeFromParent(neighbour);
|
||
}
|
||
neighbour = newElement.nextSibling;
|
||
if (neighbour && (neighbour.nodeType != 3) && !/\S/.test(neighbour.textContent)) {
|
||
HTMLArea.removeFromParent(neighbour);
|
||
}
|
||
this.editor.selectNodeContents(newElement, false);
|
||
range.detach();
|
||
} else {
|
||
var rangeStart = range.duplicate();
|
||
rangeStart.collapse(true);
|
||
var parentStart = rangeStart.parentElement();
|
||
var rangeEnd = range.duplicate();
|
||
rangeEnd.collapse(true);
|
||
var parentEnd = rangeEnd.parentElement();
|
||
var newRange = editor._createRange();
|
||
|
||
var upperParentStart = parentStart;
|
||
if (parentStart !== parent) {
|
||
while (upperParentStart.parentNode !== parent) {
|
||
upperParentStart = upperParentStart.parentNode;
|
||
}
|
||
}
|
||
|
||
var newElement = editor._doc.createElement("span");
|
||
HTMLArea._addClass(newElement, className);
|
||
newElement.innerHTML = range.htmlText;
|
||
// IE eats spaces on the start boundary
|
||
if (range.htmlText.charAt(0) === "\x20") {
|
||
newElement.innerHTML = " " + newElement.innerHTML;
|
||
}
|
||
var newElementClone = newElement.cloneNode(true);
|
||
range.pasteHTML(newElement.outerHTML);
|
||
// IE inserts the element as the last child of the start container
|
||
if (parentStart !== parent
|
||
&& parentStart.lastChild
|
||
&& parentStart.lastChild.nodeType === 1
|
||
&& parentStart.lastChild.nodeName.toLowerCase() === "span") {
|
||
parent.insertBefore(newElementClone, upperParentStart.nextSibling);
|
||
parentStart.removeChild(parentStart.lastChild);
|
||
// Sometimes an empty previous sibling was created
|
||
if (newElementClone.previousSibling
|
||
&& newElementClone.previousSibling.nodeType === 1
|
||
&& !newElementClone.previousSibling.innerText) {
|
||
parent.removeChild(newElementClone.previousSibling);
|
||
}
|
||
// The bookmark will not work anymore
|
||
newRange.moveToElementText(newElementClone);
|
||
newRange.collapse(false);
|
||
newRange.select();
|
||
} else {
|
||
// Working around IE boookmark bug
|
||
if (parentStart != parentEnd) {
|
||
var newRange = editor._createRange();
|
||
if (newRange.moveToBookmark(bookmark)) {
|
||
newRange.collapse(false);
|
||
newRange.select();
|
||
}
|
||
} else {
|
||
range.collapse(false);
|
||
}
|
||
}
|
||
try { // normalize() not available in IE5.5
|
||
parent.normalize();
|
||
} catch(e) { }
|
||
}
|
||
}
|
||
} else {
|
||
... | ... | |
HTMLArea._addClass(parent, className);
|
||
}
|
||
// Remove the span tag if it has no more attribute
|
||
if ((parent.nodeName.toLowerCase() === "span") && !this.hasAllowedAttributes(parent)) {
|
||
this.removeMarkup(parent);
|
||
if ((parent.nodeName.toLowerCase() === "span") && !HTMLArea.hasAllowedAttributes(parent, this.allowedAttributes)) {
|
||
editor.removeMarkup(parent);
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
/*
|
||
* This function verifies if the element has any of the allowed attributes
|
||
*/
|
||
hasAllowedAttributes : function(element) {
|
||
var allowedAttributes = new Array("id", "title", "lang", "xml:lang", "dir", "class", "className");
|
||
for (var i = 0; i < allowedAttributes.length; ++i) {
|
||
if (element.getAttribute(allowedAttributes[i])) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
},
|
||
|
||
/*
|
||
* This function removes the given markup element
|
||
*/
|
||
removeMarkup : function(element) {
|
||
var bookmark = this.editor.getBookmark(this.editor._createRange(this.editor._getSelection()));
|
||
var parent = element.parentNode;
|
||
while (element.firstChild) {
|
||
parent.insertBefore(element.firstChild, element);
|
||
}
|
||
parent.removeChild(element);
|
||
this.editor.selectRange(this.editor.moveToBookmark(bookmark));
|
||
},
|
||
|
||
/*
|
||
* This function gets called when the plugin is generated
|
||
* Get the classes configuration and initiate the parsing of the style sheets
|
||
*/
|
||
... | ... | |
}
|
||
}
|
||
var selectionInInlineElement = tagName && this.REInlineTags.test(tagName);
|
||
var disabled = !this.endPointsInSameBlock() || (fullNodeSelected && !tagName) || (selectionEmpty && !selectionInInlineElement);
|
||
var disabled = !editor.endPointsInSameBlock() || (fullNodeSelected && !tagName) || (selectionEmpty && !selectionInInlineElement);
|
||
if (!disabled && !tagName) {
|
||
tagName = "span";
|
||
}
|
||
... | ... | |
this.updateValue(dropDownId, tagName, classNames, selectionEmpty, fullNodeSelected, disabled);
|
||
}
|
||
},
|
||
|
||
/*
|
||
* This function determines if the end poins of the current selection are within the same block
|
||
*/
|
||
endPointsInSameBlock : function() {
|
||
var selection = this.editor._getSelection();
|
||
if (this.editor._selectionEmpty(selection)) {
|
||
return true;
|
||
} else {
|
||
var parent = this.editor.getParentElement(selection);
|
||
var endBlocks = this.editor.getEndBlocks(selection);
|
||
return (endBlocks.start === endBlocks.end && !/^(body|table|thead|tbody|tfoot|tr)$/i.test(parent.nodeName));
|
||
}
|
||
},
|
||
|
||
updateValue : function(dropDownId, tagName, classNames, selectionEmpty, fullNodeSelected, disabled) {
|
||
var editor = this.editor;
|
||
var select = document.getElementById(editor._toolbarObjects[dropDownId]["elementId"]);
|