PHP Classes

File: public/js/tinymce/src/core/src/main/js/caret/CaretPosition.js

Recommend this page to a friend!
  Classes of Abed Nego Ragil Putra   GoLavaCMS   public/js/tinymce/src/core/src/main/js/caret/CaretPosition.js   Download  
File: public/js/tinymce/src/core/src/main/js/caret/CaretPosition.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: 12,922 bytes
 

Contents

Class file image Download
/** * CaretPosition.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 */ /** * This module contains logic for creating caret positions within a document a caretposition * is similar to a DOMRange object but it doesn't have two endpoints and is also more lightweight * since it's now updated live when the DOM changes. * * @private * @class tinymce.caret.CaretPosition * @example * var caretPos1 = new CaretPosition(container, offset); * var caretPos2 = CaretPosition.fromRangeStart(someRange); */ define( 'tinymce.core.caret.CaretPosition', [ 'tinymce.core.caret.CaretCandidate', 'tinymce.core.dom.DOMUtils', 'tinymce.core.dom.NodeType', 'tinymce.core.geom.ClientRect', 'tinymce.core.selection.RangeNodes', 'tinymce.core.text.ExtendingChar', 'tinymce.core.util.Fun' ], function (CaretCandidate, DOMUtils, NodeType, ClientRect, RangeNodes, ExtendingChar, Fun) { var isElement = NodeType.isElement, isCaretCandidate = CaretCandidate.isCaretCandidate, isBlock = NodeType.matchStyleValues('display', 'block table'), isFloated = NodeType.matchStyleValues('float', 'left right'), isValidElementCaretCandidate = Fun.and(isElement, isCaretCandidate, Fun.negate(isFloated)), isNotPre = Fun.negate(NodeType.matchStyleValues('white-space', 'pre pre-line pre-wrap')), isText = NodeType.isText, isBr = NodeType.isBr, nodeIndex = DOMUtils.nodeIndex, resolveIndex = RangeNodes.getNode; var createRange = function (doc) { return "createRange" in doc ? doc.createRange() : DOMUtils.DOM.createRng(); }; var isWhiteSpace = function (chr) { return chr && /[\r\n\t ]/.test(chr); }; var isHiddenWhiteSpaceRange = function (range) { var container = range.startContainer, offset = range.startOffset, text; if (isWhiteSpace(range.toString()) && isNotPre(container.parentNode)) { text = container.data; if (isWhiteSpace(text[offset - 1]) || isWhiteSpace(text[offset + 1])) { return true; } } return false; }; var getCaretPositionClientRects = function (caretPosition) { var clientRects = [], beforeNode, node; // Hack for older WebKit versions that doesn't // support getBoundingClientRect on BR elements var getBrClientRect = function (brNode) { var doc = brNode.ownerDocument, rng = createRange(doc), nbsp = doc.createTextNode('\u00a0'), parentNode = brNode.parentNode, clientRect; parentNode.insertBefore(nbsp, brNode); rng.setStart(nbsp, 0); rng.setEnd(nbsp, 1); clientRect = ClientRect.clone(rng.getBoundingClientRect()); parentNode.removeChild(nbsp); return clientRect; }; var getBoundingClientRect = function (item) { var clientRect, clientRects; clientRects = item.getClientRects(); if (clientRects.length > 0) { clientRect = ClientRect.clone(clientRects[0]); } else { clientRect = ClientRect.clone(item.getBoundingClientRect()); } if (isBr(item) && clientRect.left === 0) { return getBrClientRect(item); } return clientRect; }; var collapseAndInflateWidth = function (clientRect, toStart) { clientRect = ClientRect.collapse(clientRect, toStart); clientRect.width = 1; clientRect.right = clientRect.left + 1; return clientRect; }; var addUniqueAndValidRect = function (clientRect) { if (clientRect.height === 0) { return; } if (clientRects.length > 0) { if (ClientRect.isEqual(clientRect, clientRects[clientRects.length - 1])) { return; } } clientRects.push(clientRect); }; var addCharacterOffset = function (container, offset) { var range = createRange(container.ownerDocument); if (offset < container.data.length) { if (ExtendingChar.isExtendingChar(container.data[offset])) { return clientRects; } // WebKit returns two client rects for a position after an extending // character a\uxxx|b so expand on "b" and collapse to start of "b" box if (ExtendingChar.isExtendingChar(container.data[offset - 1])) { range.setStart(container, offset); range.setEnd(container, offset + 1); if (!isHiddenWhiteSpaceRange(range)) { addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), false)); return clientRects; } } } if (offset > 0) { range.setStart(container, offset - 1); range.setEnd(container, offset); if (!isHiddenWhiteSpaceRange(range)) { addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), false)); } } if (offset < container.data.length) { range.setStart(container, offset); range.setEnd(container, offset + 1); if (!isHiddenWhiteSpaceRange(range)) { addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(range), true)); } } }; if (isText(caretPosition.container())) { addCharacterOffset(caretPosition.container(), caretPosition.offset()); return clientRects; } if (isElement(caretPosition.container())) { if (caretPosition.isAtEnd()) { node = resolveIndex(caretPosition.container(), caretPosition.offset()); if (isText(node)) { addCharacterOffset(node, node.data.length); } if (isValidElementCaretCandidate(node) && !isBr(node)) { addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), false)); } } else { node = resolveIndex(caretPosition.container(), caretPosition.offset()); if (isText(node)) { addCharacterOffset(node, 0); } if (isValidElementCaretCandidate(node) && caretPosition.isAtEnd()) { addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), false)); return clientRects; } beforeNode = resolveIndex(caretPosition.container(), caretPosition.offset() - 1); if (isValidElementCaretCandidate(beforeNode) && !isBr(beforeNode)) { if (isBlock(beforeNode) || isBlock(node) || !isValidElementCaretCandidate(node)) { addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(beforeNode), false)); } } if (isValidElementCaretCandidate(node)) { addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect(node), true)); } } } return clientRects; }; /** * Represents a location within the document by a container and an offset. * * @constructor * @param {Node} container Container node. * @param {Number} offset Offset within that container node. * @param {Array} clientRects Optional client rects array for the position. */ var CaretPosition = function (container, offset, clientRects) { var isAtStart = function () { if (isText(container)) { return offset === 0; } return offset === 0; }; var isAtEnd = function () { if (isText(container)) { return offset >= container.data.length; } return offset >= container.childNodes.length; }; var toRange = function () { var range; range = createRange(container.ownerDocument); range.setStart(container, offset); range.setEnd(container, offset); return range; }; var getClientRects = function () { if (!clientRects) { clientRects = getCaretPositionClientRects(new CaretPosition(container, offset)); } return clientRects; }; var isVisible = function () { return getClientRects().length > 0; }; var isEqual = function (caretPosition) { return caretPosition && container === caretPosition.container() && offset === caretPosition.offset(); }; var getNode = function (before) { return resolveIndex(container, before ? offset - 1 : offset); }; return { /** * Returns the container node. * * @method container * @return {Node} Container node. */ container: Fun.constant(container), /** * Returns the offset within the container node. * * @method offset * @return {Number} Offset within the container node. */ offset: Fun.constant(offset), /** * Returns a range out of a the caret position. * * @method toRange * @return {DOMRange} range for the caret position. */ toRange: toRange, /** * Returns the client rects for the caret position. Might be multiple rects between * block elements. * * @method getClientRects * @return {Array} Array of client rects. */ getClientRects: getClientRects, /** * Returns true if the caret location is visible/displayed on screen. * * @method isVisible * @return {Boolean} true/false if the position is visible or not. */ isVisible: isVisible, /** * Returns true if the caret location is at the beginning of text node or container. * * @method isVisible * @return {Boolean} true/false if the position is at the beginning. */ isAtStart: isAtStart, /** * Returns true if the caret location is at the end of text node or container. * * @method isVisible * @return {Boolean} true/false if the position is at the end. */ isAtEnd: isAtEnd, /** * Compares the caret position to another caret position. This will only compare the * container and offset not it's visual position. * * @method isEqual * @param {tinymce.caret.CaretPosition} caretPosition Caret position to compare with. * @return {Boolean} true if the caret positions are equal. */ isEqual: isEqual, /** * Returns the closest resolved node from a node index. That means if you have an offset after the * last node in a container it will return that last node. * * @method getNode * @return {Node} Node that is closest to the index. */ getNode: getNode }; }; /** * Creates a caret position from the start of a range. * * @method fromRangeStart * @param {DOMRange} range DOM Range to create caret position from. * @return {tinymce.caret.CaretPosition} Caret position from the start of DOM range. */ CaretPosition.fromRangeStart = function (range) { return new CaretPosition(range.startContainer, range.startOffset); }; /** * Creates a caret position from the end of a range. * * @method fromRangeEnd * @param {DOMRange} range DOM Range to create caret position from. * @return {tinymce.caret.CaretPosition} Caret position from the end of DOM range. */ CaretPosition.fromRangeEnd = function (range) { return new CaretPosition(range.endContainer, range.endOffset); }; /** * Creates a caret position from a node and places the offset after it. * * @method after * @param {Node} node Node to get caret position from. * @return {tinymce.caret.CaretPosition} Caret position from the node. */ CaretPosition.after = function (node) { return new CaretPosition(node.parentNode, nodeIndex(node) + 1); }; /** * Creates a caret position from a node and places the offset before it. * * @method before * @param {Node} node Node to get caret position from. * @return {tinymce.caret.CaretPosition} Caret position from the node. */ CaretPosition.before = function (node) { return new CaretPosition(node.parentNode, nodeIndex(node)); }; CaretPosition.isAtStart = function (pos) { return pos ? pos.isAtStart() : false; }; CaretPosition.isAtEnd = function (pos) { return pos ? pos.isAtEnd() : false; }; CaretPosition.isTextPosition = function (pos) { return pos ? NodeType.isText(pos.container()) : false; }; return CaretPosition; } );