moveToPoint()方法textRange IE11有问题;
似乎它不工作,如果点节点不在第一个屏幕;
document.addEventListener( "click", function(e) {
var x = e.clientX;
var y = e.clientY;
var range = document.body.createTextRange();
range.moveToPoint(x, y);
range.expand('word');
console.log(range);
console.log(range.text);
});
这段代码从点击点抓取单词,但只有在第一个滚动点的节点上单击时,它才会正常运行。
如果我们向下滚动一点到第一个滚动中没有的节点,我们就会捕捉到exeception。
有人知道如何正确处理这种情况吗?
发布于 2016-07-27 20:22:18
受“dinalt”和“JAYBEkster”的启发,我想出了这个解决方案。也许最终会有人需要这个。
下面的代码(对于IE,没有检查所有的11+,但它工作得很好)在复杂嵌套的html中捕获单词。
一步一步如何工作:
我们为什么要做第4和第5步?因为我们在那个节点上找到了一些文字,但它可能不是这个词的结尾或开头,出于一些造型上的原因,它是这个词的一部分--我在它自己的节点上,而target.node我只是这个词的中间部分。所以我们必须跳过节点找到单词的结尾。
如果你确信你没有抱怨你可以跳过所有其他步骤。
是的,这看起来真的很像,因为对于这样的,我们认为简单的任务。但实际上我找不到更好的解决方案,有几种选择,但它们都不是我所需要的那样普遍。
这段代码的好处在于它根本不关心html的复杂性。
我将在这里张贴到我的github网站的链接,在那里你可以找到完整的wordGraber代码,这将工作这个Chrome,Safari,FF和IE当然。
https://github.com/6graNik/wordGrabber
下面只是IE的一部分。
function getWordFromEventIE(e) {
const x = e.clientX;
const y = e.clientY;
const innerText = e.target && e.target.innerText;
const separators = /([\s&^:;,!?(){}])+/;
const IErange = global.document.body.createTextRange();
try {
IErange.moveToElementText(e.target);
IErange.collapse(true);
let wholeSentenceLength = 0;
const reqIEcharTest = () => {
do {
IErange.expand("character");
wholeSentenceLength += 1;
}
while (!separators.test(IErange.text.slice(-1)) && wholeSentenceLength <= innerText.length);
const {boundingLeft, boundingTop, boundingWidth, boundingHeight, text} = IErange;
if (boundingLeft <= x && x <= (boundingLeft + boundingWidth)
&& boundingTop <= y && y <= (boundingTop + boundingHeight)) {
if (wholeSentenceLength <= innerText.length && !separators.test(text.slice(-1)) ) {
return text;
}
return text.substr(0, text.length - 1);
}
IErange.collapse(false);
return reqIEcharTest();
};
const text = reqIEcharTest().trim();
const innerTextArr = innerText.split(text);
const innerTextLeft = innerTextArr[0].split(separators);
const innerTextRight = innerTextArr[1].split(separators);
let leftPart;
if (innerTextLeft <= 1) {
leftPart = recursionWordGet(e.target, 'left') + innerTextLeft.slice(-1)[0];
} else {
leftPart = innerTextLeft.slice(-1)[0];
}
let rightPart;
if (innerTextRight <= 1) {
rightPart = innerTextRight[0] + recursionWordGet(e.target, 'right');
} else {
rightPart = innerTextRight[0];
}
return leftPart + text + rightPart;
} catch (err) {
console.log('>>>>>>>>>>>>>>>>>> text', err);
}
}
function recursionWordGet(target, option) {
const separators = /([\s&^:;,!?(){}])+/;
const uniqString = Date.now();
target.setAttribute("data-target", uniqString);
const {parentNode} = target;
const copyNode = parentNode.cloneNode(true);
copyNode.querySelector(`[data-target="${uniqString}"]`).innerText = uniqString;
const tagName = copyNode.tagName;
const text = copyNode.innerText;
const textArr = text.split(uniqString);
const textLeftPartArr = textArr[0].split(separators);
const textRightPartArr = textArr[1].split(separators);
if (option === 'right') {
let returnText;
if (textRightPartArr.length <= 1 && tagName === 'span') {
returnText = textRightPartArr[0] + recursionWordGet(parentNode, 'right');
} else {
returnText = textRightPartArr[0];
}
return returnText;
}
if (option === 'left') {
let returnText;
if (textLeftPartArr <= 1 && tagName === 'span') {
returnText = recursionWordGet(parentNode, 'left') + textLeftPartArr.slice(-1)[0];
} else {
returnText = textLeftPartArr.slice(-1)[0];
}
return returnText;
}
return '';
}
发布于 2016-07-26 14:59:41
您可以使用offsetX,offsetY属性。或者可以使用父元素的scrollLeft和scrollTop属性将滚动位置添加到x和y vars。
发布于 2016-07-27 11:01:51
我可以确认IE11中存在这样的bug。您可以在注释中找到详细信息:http://generatedcontent.org/post/69213745095/ie11review-part1
可能的解决方案(在创建范围之后):
range.moveToElementText(e.target);
range.collapse(true)
range.expand("word")现在,您已经选择了第一个单词。现在您必须使用TextRange属性boundingHeight、boundingWidth、boundingLeft和boundingTop检查所选单词是否适合您的鼠标单击位置。如果没有,您可以循环到下一个单词:
range.collapse(false);
range.expand("word");https://stackoverflow.com/questions/38589496
复制相似问题