Yan*_*roo 10 javascript position range
使用JavaScript,我想从像素位置创建折叠范围,以便在此位置标识的范围之后在文档流中插入新节点.
这可以使用Internet Exporer中的TextRange对象(moveToPoint(x,y)方法)来完成.
我怎么能在FireFox和Webkit中做到这一点?
我可以从document.elementFromPoint(x,y)的位置获取容器元素.但是当位置恰好位于文本节点内时,如何获得有关构建范围所需的文本偏移量的更多信息?
Val*_*gin 17
这是我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;
};
}
Run Code Online (Sandbox Code Playgroud)
Yan*_*roo 12
以下是我从像素位置获取文本节点内字符位置的调查结果:
在MSIE下,您写道:
var range = document.selection.createRange();
range.moveToPoint(x, y);
Run Code Online (Sandbox Code Playgroud)
对于其他浏览器,我们的想法是确定x/y位置的HTML元素并在其上创建一个字符选择.基于此range.getBoundingClientRect()
,您可以确定是否在x/y位置之前或之后选择一个字符.然后我们可以选择下一个字符,直到选择位置位于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};
}
Run Code Online (Sandbox Code Playgroud)
这两段代码已经过测试:
未测试以下情况:
归档时间: |
|
查看次数: |
5539 次 |
最近记录: |