PHP Classes

File: public/js/tinymce/src/core/src/main/js/fmt/CaretFormat.js

Recommend this page to a friend!
  Classes of Abed Nego Ragil Putra   GoLavaCMS   public/js/tinymce/src/core/src/main/js/fmt/CaretFormat.js   Download  
File: public/js/tinymce/src/core/src/main/js/fmt/CaretFormat.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: GoLavaCMS
Publish content on Web pages with SEO support
Author: By
Last change:
Date: 6 years ago
Size: 11,619 bytes
 

Contents

Class file image Download
/** * CaretFormat.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ define( 'tinymce.core.fmt.CaretFormat', [ 'ephox.katamari.api.Arr', 'ephox.sugar.api.dom.Insert', 'ephox.sugar.api.dom.Remove', 'ephox.sugar.api.node.Element', 'ephox.sugar.api.node.Node', 'ephox.sugar.api.properties.Attr', 'tinymce.core.caret.CaretPosition', 'tinymce.core.dom.NodeType', 'tinymce.core.dom.PaddingBr', 'tinymce.core.dom.TreeWalker', 'tinymce.core.fmt.ExpandRange', 'tinymce.core.fmt.FormatUtils', 'tinymce.core.fmt.MatchFormat', 'tinymce.core.selection.SplitRange', 'tinymce.core.text.Zwsp', 'tinymce.core.util.Fun' ], function (Arr, Insert, Remove, Element, Node, Attr, CaretPosition, NodeType, PaddingBr, TreeWalker, ExpandRange, FormatUtils, MatchFormat, SplitRange, Zwsp, Fun) { var ZWSP = Zwsp.ZWSP, CARET_ID = '_mce_caret'; var importNode = function (ownerDocument, node) { return ownerDocument.importNode(node, true); }; var isCaretNode = function (node) { return node.nodeType === 1 && node.id === CARET_ID; }; var getEmptyCaretContainers = function (node) { var nodes = []; while (node) { if ((node.nodeType === 3 && node.nodeValue !== ZWSP) || node.childNodes.length > 1) { return []; } // Collect nodes if (node.nodeType === 1) { nodes.push(node); } node = node.firstChild; } return nodes; }; var isCaretContainerEmpty = function (node) { return getEmptyCaretContainers(node).length > 0; }; var findFirstTextNode = function (node) { var walker; if (node) { walker = new TreeWalker(node, node); for (node = walker.current(); node; node = walker.next()) { if (node.nodeType === 3) { return node; } } } return null; }; var createCaretContainer = function (fill) { var caretContainer = Element.fromTag('span'); Attr.setAll(caretContainer, { //style: 'color:red', id: CARET_ID, 'data-mce-bogus': '1', 'data-mce-type': 'format-caret' }); if (fill) { Insert.append(caretContainer, Element.fromText(ZWSP)); } return caretContainer; }; var getParentCaretContainer = function (body, node) { while (node && node !== body) { if (node.id === CARET_ID) { return node; } node = node.parentNode; } return null; }; var trimZwspFromCaretContainer = function (caretContainerNode) { var textNode = findFirstTextNode(caretContainerNode); if (textNode && textNode.nodeValue.charAt(0) === ZWSP) { textNode.deleteData(0, 1); } return textNode; }; var removeCaretContainerNode = function (dom, selection, node, moveCaret) { var rng, block, textNode; rng = selection.getRng(true); block = dom.getParent(node, dom.isBlock); if (isCaretContainerEmpty(node)) { if (moveCaret !== false) { rng.setStartBefore(node); rng.setEndBefore(node); } dom.remove(node); } else { textNode = trimZwspFromCaretContainer(node); if (rng.startContainer === textNode && rng.startOffset > 0) { rng.setStart(textNode, rng.startOffset - 1); } if (rng.endContainer === textNode && rng.endOffset > 0) { rng.setEnd(textNode, rng.endOffset - 1); } dom.remove(node, true); } if (block && dom.isEmpty(block)) { PaddingBr.fillWithPaddingBr(Element.fromDom(block)); } selection.setRng(rng); }; // Removes the caret container for the specified node or all on the current document var removeCaretContainer = function (body, dom, selection, node, moveCaret) { if (!node) { node = getParentCaretContainer(body, selection.getStart()); if (!node) { while ((node = dom.get(CARET_ID))) { removeCaretContainerNode(dom, selection, node, false); } } } else { removeCaretContainerNode(dom, selection, node, moveCaret); } }; var insertCaretContainerNode = function (editor, caretContainer, formatNode) { var dom = editor.dom, block = dom.getParent(formatNode, Fun.curry(FormatUtils.isTextBlock, editor)); if (block && dom.isEmpty(block)) { // Replace formatNode with caretContainer when removing format from empty block like <p><b>|</b></p> formatNode.parentNode.replaceChild(caretContainer, formatNode); } else { PaddingBr.removeTrailingBr(Element.fromDom(formatNode)); if (dom.isEmpty(formatNode)) { formatNode.parentNode.replaceChild(caretContainer, formatNode); } else { dom.insertAfter(caretContainer, formatNode); } } }; var appendNode = function (parentNode, node) { parentNode.appendChild(node); return node; }; var insertFormatNodesIntoCaretContainer = function (formatNodes, caretContainer) { var innerMostFormatNode = Arr.foldr(formatNodes, function (parentNode, formatNode) { return appendNode(parentNode, formatNode.cloneNode(false)); }, caretContainer); return appendNode(innerMostFormatNode, innerMostFormatNode.ownerDocument.createTextNode(ZWSP)); }; var applyCaretFormat = function (editor, name, vars) { var rng, caretContainer, textNode, offset, bookmark, container, text; var selection = editor.selection; rng = selection.getRng(true); offset = rng.startOffset; container = rng.startContainer; text = container.nodeValue; caretContainer = getParentCaretContainer(editor.getBody(), selection.getStart()); if (caretContainer) { textNode = findFirstTextNode(caretContainer); } // Expand to word if caret is in the middle of a text node and the char before/after is a alpha numeric character var wordcharRegex = /[^\s\u00a0\u00ad\u200b\ufeff]/; if (text && offset > 0 && offset < text.length && wordcharRegex.test(text.charAt(offset)) && wordcharRegex.test(text.charAt(offset - 1))) { // Get bookmark of caret position bookmark = selection.getBookmark(); // Collapse bookmark range (WebKit) rng.collapse(true); // Expand the range to the closest word and split it at those points rng = ExpandRange.expandRng(editor, rng, editor.formatter.get(name)); rng = SplitRange.split(rng); // Apply the format to the range editor.formatter.apply(name, vars, rng); // Move selection back to caret position selection.moveToBookmark(bookmark); } else { if (!caretContainer || textNode.nodeValue !== ZWSP) { // Need to import the node into the document on IE or we get a lovely WrongDocument exception caretContainer = importNode(editor.getDoc(), createCaretContainer(true).dom()); textNode = caretContainer.firstChild; rng.insertNode(caretContainer); offset = 1; editor.formatter.apply(name, vars, caretContainer); } else { editor.formatter.apply(name, vars, caretContainer); } // Move selection to text node selection.setCursorLocation(textNode, offset); } }; var removeCaretFormat = function (editor, name, vars, similar) { var dom = editor.dom, selection = editor.selection; var rng = selection.getRng(true), container, offset, bookmark; var hasContentAfter, node, formatNode, parents = [], caretContainer; container = rng.startContainer; offset = rng.startOffset; node = container; if (container.nodeType === 3) { if (offset !== container.nodeValue.length) { hasContentAfter = true; } node = node.parentNode; } while (node) { if (MatchFormat.matchNode(editor, node, name, vars, similar)) { formatNode = node; break; } if (node.nextSibling) { hasContentAfter = true; } parents.push(node); node = node.parentNode; } // Node doesn't have the specified format if (!formatNode) { return; } // Is there contents after the caret then remove the format on the element if (hasContentAfter) { bookmark = selection.getBookmark(); // Collapse bookmark range (WebKit) rng.collapse(true); // Expand the range to the closest word and split it at those points rng = ExpandRange.expandRng(editor, rng, editor.formatter.get(name), true); rng = SplitRange.split(rng); editor.formatter.remove(name, vars, rng); selection.moveToBookmark(bookmark); } else { caretContainer = getParentCaretContainer(editor.getBody(), formatNode); var newCaretContainer = createCaretContainer(false).dom(); var caretNode = insertFormatNodesIntoCaretContainer(parents, newCaretContainer); if (caretContainer) { insertCaretContainerNode(editor, newCaretContainer, caretContainer); } else { insertCaretContainerNode(editor, newCaretContainer, formatNode); } removeCaretContainerNode(dom, selection, caretContainer, false); selection.setCursorLocation(caretNode, 1); if (dom.isEmpty(formatNode)) { dom.remove(formatNode); } } }; var disableCaretContainer = function (body, dom, selection, keyCode) { removeCaretContainer(body, dom, selection, null, false); // Remove caret container if it's empty if (keyCode === 8 && selection.isCollapsed() && selection.getStart().innerHTML === ZWSP) { removeCaretContainer(body, dom, selection, getParentCaretContainer(body, selection.getStart())); } // Remove caret container on keydown and it's left/right arrow keys if (keyCode === 37 || keyCode === 39) { removeCaretContainer(body, dom, selection, getParentCaretContainer(body, selection.getStart())); } }; var setup = function (editor) { var dom = editor.dom, selection = editor.selection; var body = editor.getBody(); editor.on('mouseup keydown', function (e) { disableCaretContainer(body, dom, selection, e.keyCode); }); }; var replaceWithCaretFormat = function (targetNode, formatNodes) { var caretContainer = createCaretContainer(false); var innerMost = insertFormatNodesIntoCaretContainer(formatNodes, caretContainer.dom()); Insert.before(Element.fromDom(targetNode), caretContainer); Remove.remove(Element.fromDom(targetNode)); return CaretPosition(innerMost, 0); }; var isFormatElement = function (editor, element) { var inlineElements = editor.schema.getTextInlineElements(); return inlineElements.hasOwnProperty(Node.name(element)) && !isCaretNode(element.dom()) && !NodeType.isBogus(element.dom()); }; return { setup: setup, applyCaretFormat: applyCaretFormat, removeCaretFormat: removeCaretFormat, isCaretNode: isCaretNode, getParentCaretContainer: getParentCaretContainer, replaceWithCaretFormat: replaceWithCaretFormat, isFormatElement: isFormatElement }; } );