@syncfusion/ej2-richtexteditor
Version:
Essential JS 2 RichTextEditor component
270 lines (268 loc) • 15 kB
JavaScript
/**
* `Clear Format` module is used to handle Clear Format.
*/
import { closest, isNullOrUndefined } from '@syncfusion/ej2-base';
import { NodeSelection } from './../../selection/index';
import { NodeCutter } from './nodecutter';
import { DOMNode } from './dom-node';
import { InsertMethods } from './insert-methods';
import { IsFormatted } from './isformatted';
import { isIDevice, setEditFrameFocus } from '../../common/util';
var ClearFormat = /** @class */ (function () {
function ClearFormat() {
}
/**
* clear method
*
* @param {Document} docElement - specifies the document element.
* @param {Node} endNode - specifies the end node
* @param {string} enterAction - specifies the enter key action
* @param {string} selector - specifies the string value
* @param {string} command - specifies the command value
* @returns {void}
* @hidden
*/
ClearFormat.clear = function (docElement, endNode, enterAction, selector, command) {
this.domNode = new DOMNode(endNode, docElement);
this.defaultTag = enterAction === 'P' ? 'p' : 'div';
var nodeSelection = new NodeSelection(endNode);
var nodeCutter = new NodeCutter();
var range = nodeSelection.getRange(docElement);
var nodes = range.collapsed ? nodeSelection.getSelectionNodeCollection(range) :
nodeSelection.getSelectionNodeCollectionBr(range);
var save = nodeSelection.save(range, docElement);
var cursorRange = false;
if (range.collapsed && command !== 'ClearFormat') {
cursorRange = true;
range = nodeCutter.GetCursorRange(docElement, range, nodes[0]);
}
var isCollapsed = range.collapsed;
if (!isCollapsed) {
var preNode = void 0;
if (nodes.length > 0 && nodes[0].nodeName === 'BR' && closest(nodes[0], 'table')) {
preNode = nodeCutter.GetSpliceNode(range, closest(nodes[0], 'table'));
}
else {
preNode = nodeCutter.GetSpliceNode(range, nodes[nodes.length > 1 && nodes[0].nodeName === 'IMG' ? 1 : 0]);
}
if (nodes.length === 1) {
nodeSelection.setSelectionContents(docElement, preNode);
range = nodeSelection.getRange(docElement);
}
else if (nodes.length > 1) {
var i = 1;
var lastText = nodes[nodes.length - i];
while (nodes.length <= i && nodes[nodes.length - i].nodeName === 'BR') {
i++;
lastText = nodes[nodes.length - i];
}
var lasNode = nodeCutter.GetSpliceNode(range, lastText);
if (lasNode) {
nodeSelection.setSelectionText(docElement, preNode, lasNode, 0, (lasNode.nodeType === 3) ?
lasNode.textContent.length : lasNode.childNodes.length);
}
range = nodeSelection.getRange(docElement);
}
var exactNodes = nodeSelection.getNodeCollection(range);
var cloneSelectNodes = exactNodes.slice();
this.clearInlines(nodeSelection.getSelectionNodesBr(cloneSelectNodes), cloneSelectNodes, nodeSelection.getRange(docElement), nodeCutter, endNode);
this.reSelection(docElement, save, exactNodes);
range = nodeSelection.getRange(docElement);
exactNodes = nodeSelection.getNodeCollection(range);
var cloneParentNodes = exactNodes.slice();
this.clearBlocks(docElement, cloneParentNodes, endNode, nodeCutter, nodeSelection);
if (isIDevice()) {
setEditFrameFocus(endNode, selector);
}
this.reSelection(docElement, save, exactNodes);
}
if (cursorRange) {
nodeSelection.setCursorPoint(docElement, range.endContainer, range.endOffset);
}
};
ClearFormat.reSelection = function (docElement, save, exactNodes) {
var selectionNodes = save.getInsertNodes(exactNodes);
save.startContainer = save.getNodeArray(selectionNodes[0], true, docElement);
save.startOffset = 0;
save.endContainer = save.getNodeArray(selectionNodes[selectionNodes.length - 1], false, docElement);
var endIndexNode = selectionNodes[selectionNodes.length - 1];
save.endOffset = (endIndexNode.nodeType === 3) ? endIndexNode.textContent.length
: endIndexNode.childNodes.length;
save.restore();
};
ClearFormat.clearBlocks = function (docElement, nodes, endNode, nodeCutter, nodeSelection) {
var parentNodes = [];
for (var index = 0; index < nodes.length; index++) {
if (this.BLOCK_TAGS.indexOf(nodes[index].nodeName.toLocaleLowerCase()) > -1
&& parentNodes.indexOf(nodes[index]) === -1) {
parentNodes.push(nodes[index]);
}
else if ((this.BLOCK_TAGS.indexOf(nodes[index].parentNode.nodeName.toLocaleLowerCase()) > -1)
&& parentNodes.indexOf(nodes[index].parentNode) === -1
&& endNode !== nodes[index].parentNode) {
parentNodes.push(nodes[index].parentNode);
}
}
parentNodes = this.spliceParent(parentNodes, nodes)[0];
parentNodes = this.removeParent(parentNodes);
this.unWrap(docElement, parentNodes, nodeCutter, nodeSelection);
};
ClearFormat.spliceParent = function (parentNodes, nodes) {
for (var index1 = 0; index1 < parentNodes.length; index1++) {
var len = parentNodes[index1].childNodes.length;
for (var index2 = 0; index2 < len; index2++) {
if ((nodes.indexOf(parentNodes[index1].childNodes[index2]) > 0)
&& (parentNodes[index1].childNodes[index2].childNodes.length > 0)) {
nodes = this.spliceParent([parentNodes[index1].childNodes[index2]], nodes)[1];
}
if ((nodes.indexOf(parentNodes[index1].childNodes[index2]) <= -1) &&
(parentNodes[index1].childNodes[index2].textContent.trim() !== '')) {
for (var index3 = 0; index3 < len; index3++) {
if (nodes.indexOf(parentNodes[index1].childNodes[index3]) > -1) {
nodes.splice(nodes.indexOf(parentNodes[index1].childNodes[index3]), 1);
}
}
index2 = parentNodes[index1].childNodes.length;
var parentIndex = parentNodes.indexOf(parentNodes[index1].parentNode);
var nodeIndex = nodes.indexOf(parentNodes[index1].parentNode);
if (parentIndex > -1) {
parentNodes.splice(parentIndex, 1);
}
if (nodeIndex > -1) {
nodes.splice(nodeIndex, 1);
}
var elementIndex = nodes.indexOf(parentNodes[index1]);
if (elementIndex > -1) {
nodes.splice(elementIndex, 1);
}
parentNodes.splice(index1, 1);
index1--;
}
}
}
return [parentNodes, nodes];
};
ClearFormat.removeChild = function (parentNodes, parentNode) {
var count = parentNode.childNodes.length;
if (count > 0) {
for (var index = 0; index < count; index++) {
if (parentNodes.indexOf(parentNode.childNodes[index]) > -1) {
parentNodes = this.removeChild(parentNodes, parentNode.childNodes[index]);
parentNodes.splice(parentNodes.indexOf(parentNode.childNodes[index]), 1);
}
}
}
return parentNodes;
};
ClearFormat.removeParent = function (parentNodes) {
for (var index = 0; index < parentNodes.length; index++) {
if (parentNodes.indexOf(parentNodes[index].parentNode) > -1) {
parentNodes = this.removeChild(parentNodes, parentNodes[index]);
parentNodes.splice(index, 1);
index--;
}
}
return parentNodes;
};
ClearFormat.unWrap = function (docElement, parentNodes, nodeCutter, nodeSelection) {
for (var index1 = 0; index1 < parentNodes.length; index1++) {
parentNodes[index1] = (closest(parentNodes[index1], 'li') && parentNodes[index1].nodeName !== 'UL' && parentNodes[index1].nodeName !== 'OL')
? closest(parentNodes[index1], 'li')
: parentNodes[index1];
if (this.NONVALID_TAGS.indexOf(parentNodes[index1].nodeName.toLowerCase()) > -1
&& parentNodes[index1].parentNode
&& this.NONVALID_PARENT_TAGS.indexOf(parentNodes[index1].parentNode.nodeName.toLowerCase()) > -1) {
nodeSelection.setSelectionText(docElement, parentNodes[index1], parentNodes[index1], 0, parentNodes[index1].childNodes.length);
InsertMethods.unwrap(nodeCutter.GetSpliceNode(nodeSelection.getRange(docElement), parentNodes[index1].parentNode));
}
var blockquoteNode = closest(parentNodes[index1], 'blockquote');
if (parentNodes[index1].nodeName.toLocaleLowerCase() !== 'blockquote' && !isNullOrUndefined(blockquoteNode) && blockquoteNode.textContent === parentNodes[index1].textContent) {
var blockNodes = this.removeParent([blockquoteNode]);
this.unWrap(docElement, blockNodes, nodeCutter, nodeSelection);
}
if (parentNodes[index1].nodeName.toLocaleLowerCase() !== 'p') {
if (this.NONVALID_PARENT_TAGS.indexOf(parentNodes[index1].nodeName.toLowerCase()) < 0
&& !((parentNodes[index1].nodeName.toLocaleLowerCase() === 'blockquote'
|| parentNodes[index1].nodeName.toLocaleLowerCase() === 'li')
&& this.IGNORE_PARENT_TAGS.indexOf(parentNodes[index1].childNodes[0].nodeName.toLocaleLowerCase()) > -1)
&& !(parentNodes[index1].childNodes.length === 1
&& parentNodes[index1].childNodes[0].nodeName.toLocaleLowerCase() === 'p')) {
InsertMethods.Wrap(parentNodes[index1], docElement.createElement(this.defaultTag));
}
var childNodes = InsertMethods.unwrap(parentNodes[index1]);
if (childNodes.length === 1
&& childNodes[0].parentNode.nodeName.toLocaleLowerCase() === 'p') {
InsertMethods.Wrap(parentNodes[index1], docElement.createElement(this.defaultTag));
InsertMethods.unwrap(parentNodes[index1]);
}
for (var index2 = 0; index2 < childNodes.length; index2++) {
if (this.NONVALID_TAGS.indexOf(childNodes[index2].nodeName.toLowerCase()) > -1) {
this.unWrap(docElement, [childNodes[index2]], nodeCutter, nodeSelection);
}
else if (this.BLOCK_TAGS.indexOf(childNodes[index2].nodeName.toLocaleLowerCase()) > -1 &&
childNodes[index2].nodeName.toLocaleLowerCase() !== 'p') {
var blockNodes = this.removeParent([childNodes[index2]]);
this.unWrap(docElement, blockNodes, nodeCutter, nodeSelection);
}
else if (this.BLOCK_TAGS.indexOf(childNodes[index2].nodeName.toLocaleLowerCase()) > -1 &&
childNodes[index2].nodeName.toLocaleLowerCase() === 'p') {
if (childNodes[index2].parentNode.nodeName.toLocaleLowerCase() === 'p') {
InsertMethods.unwrap(childNodes[index2].parentNode);
}
InsertMethods.Wrap(childNodes[index2], docElement.createElement(this.defaultTag));
InsertMethods.unwrap(childNodes[index2]);
}
else if (this.BLOCK_TAGS.indexOf(childNodes[index2].nodeName.toLocaleLowerCase()) > -1 &&
childNodes[index2].parentNode.nodeName.toLocaleLowerCase() ===
childNodes[index2].nodeName.toLocaleLowerCase()) {
InsertMethods.unwrap(childNodes[index2]);
}
}
}
else {
InsertMethods.Wrap(parentNodes[index1], docElement.createElement(this.defaultTag));
InsertMethods.unwrap(parentNodes[index1]);
}
}
};
ClearFormat.clearInlines = function (textNodes, nodes, range, nodeCutter,
// eslint-disable-next-line
endNode) {
for (var index = 0; index < textNodes.length; index++) {
var currentInlineNode = textNodes[index];
var currentNode = void 0;
while (!this.domNode.isBlockNode(currentInlineNode) &&
(currentInlineNode.parentElement && !currentInlineNode.parentElement.classList.contains('e-img-inner'))) {
currentNode = currentInlineNode;
currentInlineNode = currentInlineNode.parentElement;
}
if (currentNode &&
IsFormatted.inlineTags.indexOf(currentNode.nodeName.toLocaleLowerCase()) > -1) {
nodeCutter.GetSpliceNode(range, currentNode);
this.removeInlineParent(currentNode);
}
}
};
ClearFormat.removeInlineParent = function (textNodes) {
var nodes = InsertMethods.unwrap(textNodes);
for (var index = 0; index < nodes.length; index++) {
if (nodes[index].parentNode.childNodes.length === 1 && !nodes[index].parentNode.classList.contains('e-img-inner')
&& IsFormatted.inlineTags.indexOf(nodes[index].parentNode.nodeName.toLocaleLowerCase()) > -1) {
this.removeInlineParent(nodes[index].parentNode);
}
else if (IsFormatted.inlineTags.indexOf(nodes[index].nodeName.toLocaleLowerCase()) > -1) {
this.removeInlineParent(nodes[index]);
}
}
};
ClearFormat.BLOCK_TAGS = ['address', 'article', 'aside', 'blockquote',
'details', 'dd', 'div', 'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer',
'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'li', 'main', 'nav',
'noscript', 'ol', 'p', 'pre', 'section', 'ul'];
ClearFormat.NONVALID_PARENT_TAGS = ['thead', 'tbody', 'ul', 'ol', 'table', 'tfoot', 'tr'];
ClearFormat.IGNORE_PARENT_TAGS = ['ul', 'ol', 'table'];
ClearFormat.NONVALID_TAGS = ['thead', 'tbody', 'figcaption', 'td', 'tr', 'th', 'tfoot', 'figcaption', 'li'];
ClearFormat.defaultTag = 'p';
return ClearFormat;
}());
export { ClearFormat };