使用JavaScript,我想从像素位置创建一个折叠的范围,以便在文档流中插入新的节点,在这个位置标识的范围之后。
这可以使用Internet中的TextRange对象(moveToPoint(x,y)方法)来完成。
如何在FireFox &Webkit中做到这一点?
我可以从document.elementFromPoint(x,y)的位置得到容器元素。但是,当位置恰好位于文本节点中时,如何获得构建范围所需的文本偏移量的更多信息?
发布于 2012-11-23 10:49:02
下面是我为旧浏览器实现的caretRangeFromPoint:
if (!document.caretRangeFromPoint) {
document.caretRangeFromPoint = function(x, y) {
var log = "";
function inRect(x, y, rect) {
return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
}
function inObject(x, y, object) {
var rects = object.getClientRects();
for (var i = rects.length; i--;)
if (inRect(x, y, rects[i]))
return true;
return false;
}
function getTextNodes(node, x, y) {
if (!inObject(x, y, node))
return [];
var result = [];
node = node.firstChild;
while (node) {
if (node.nodeType == 3)
result.push(node);
if (node.nodeType == 1)
result = result.concat(getTextNodes(node, x, y));
node = node.nextSibling;
}
return result;
}
var element = document.elementFromPoint(x, y);
var nodes = getTextNodes(element, x, y);
if (!nodes.length)
return null;
var node = nodes[0];
var range = document.createRange();
range.setStart(node, 0);
range.setEnd(node, 1);
for (var i = nodes.length; i--;) {
var node = nodes[i],
text = node.nodeValue;
range = document.createRange();
range.setStart(node, 0);
range.setEnd(node, text.length);
if (!inObject(x, y, range))
continue;
for (var j = text.length; j--;) {
if (text.charCodeAt(j) <= 32)
continue;
range = document.createRange();
range.setStart(node, j);
range.setEnd(node, j + 1);
if (inObject(x, y, range)) {
range.setEnd(node, j);
return range;
}
}
}
return range;
};
}发布于 2010-07-08 21:39:44
下面是我从像素位置获取文本节点内字符位置的调查结果:
发布于 2012-03-07 14:27:29
在MSIE下,您写道:
var range = document.selection.createRange();
range.moveToPoint(x, y); 对于其他浏览器,其思想是在x/y位置确定HTML元素,并在其上创建一个字符选择。基于range.getBoundingClientRect(),您可以确定一个字符选择是在x/y位置之前还是之后。然后我们可以选择下一个字符,直到选择位置raich x/y位置。我为Firefox、Safari和Chrome编写了以下实现:
var nodeInfo = getSelectionNodeInfo(x, y);
var range = document.createRange();
range.setStart(nodeInfo.node, nodeInfo.offsetInsideNode);
range.setEnd(nodeInfo.node, nodeInfo.offsetInsideNode);
/**
Emulates MSIE function range.moveToPoint(x,y) b
returning the selection node info corresponding
to the given x/y location.
@param x the point X coordinate
@param y the point Y coordinate
@return the node and offset in characters as
{node,offsetInsideNode} (e.g. can be passed to range.setStart)
*/
function getSelectionNodeInfo(x, y) {
var startRange = document.createRange();
window.getSelection().removeAllRanges();
window.getSelection().addRange(startRange);
// Implementation note: range.setStart offset is
// counted in number of child elements if any or
// in characters if there is no childs. Since we
// want to compute in number of chars, we need to
// get the node which has no child.
var elem = document.elementFromPoint(x, y);
var startNode = (elem.childNodes.length>0?elem.childNodes[0]:elem);
var startCharIndexCharacter = -1;
do {
startCharIndexCharacter++;
startRange.setStart(startNode, startCharIndexCharacter);
startRange.setEnd(startNode, startCharIndexCharacter+1);
var rangeRect = startRange.getBoundingClientRect();
} while (rangeRect.left<x && startCharIndexCharacter<startNode.length-1);
return {node:startNode, offsetInsideNode:startCharIndexCharacter};
}对这两段代码进行了以下测试:
未对下列情况进行测试:
https://stackoverflow.com/questions/3189812
复制相似问题