73 lines
1.6 KiB
JavaScript
73 lines
1.6 KiB
JavaScript
|
/**
|
||
|
* Copyright 2013-present, Facebook, Inc.
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* This source code is licensed under the BSD-style license found in the
|
||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
'use strict';
|
||
|
|
||
|
/**
|
||
|
* Given any node return the first leaf node without children.
|
||
|
*
|
||
|
* @param {DOMElement|DOMTextNode} node
|
||
|
* @return {DOMElement|DOMTextNode}
|
||
|
*/
|
||
|
|
||
|
function getLeafNode(node) {
|
||
|
while (node && node.firstChild) {
|
||
|
node = node.firstChild;
|
||
|
}
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the next sibling within a container. This will walk up the
|
||
|
* DOM if a node's siblings have been exhausted.
|
||
|
*
|
||
|
* @param {DOMElement|DOMTextNode} node
|
||
|
* @return {?DOMElement|DOMTextNode}
|
||
|
*/
|
||
|
function getSiblingNode(node) {
|
||
|
while (node) {
|
||
|
if (node.nextSibling) {
|
||
|
return node.nextSibling;
|
||
|
}
|
||
|
node = node.parentNode;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get object describing the nodes which contain characters at offset.
|
||
|
*
|
||
|
* @param {DOMElement|DOMTextNode} root
|
||
|
* @param {number} offset
|
||
|
* @return {?object}
|
||
|
*/
|
||
|
function getNodeForCharacterOffset(root, offset) {
|
||
|
var node = getLeafNode(root);
|
||
|
var nodeStart = 0;
|
||
|
var nodeEnd = 0;
|
||
|
|
||
|
while (node) {
|
||
|
if (node.nodeType === 3) {
|
||
|
nodeEnd = nodeStart + node.textContent.length;
|
||
|
|
||
|
if (nodeStart <= offset && nodeEnd >= offset) {
|
||
|
return {
|
||
|
node: node,
|
||
|
offset: offset - nodeStart
|
||
|
};
|
||
|
}
|
||
|
|
||
|
nodeStart = nodeEnd;
|
||
|
}
|
||
|
|
||
|
node = getLeafNode(getSiblingNode(node));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
module.exports = getNodeForCharacterOffset;
|