如何使用 JavaScript 将选择扩展到单词边界,仅一次
How do I extend selection to word boundary using JavaScript, once only?
我正在使用此答案中显示的技术将网页的选择扩展到单词边界:
function snapSelectionToWord() {
var sel;
// Check for existence of window.getSelection() and that it has a
// modify() method. IE 9 has both selection APIs but no modify() method.
if (window.getSelection && (sel = window.getSelection()).modify) {
sel = window.getSelection();
if (!sel.isCollapsed) {
// Detect if selection is backwards
var range = document.createRange();
range.setStart(sel.anchorNode, sel.anchorOffset);
range.setEnd(sel.focusNode, sel.focusOffset);
var backwards = range.collapsed;
range.detach();
// modify() works on the focus of the selection
var endNode = sel.focusNode, endOffset = sel.focusOffset;
sel.collapse(sel.anchorNode, sel.anchorOffset);
if (backwards) {
sel.modify("move", "forward", "word");
sel.extend(endNode, endOffset);
sel.modify("extend", "backward", "word");
} else {
sel.modify("move", "backward", "word");
sel.extend(endNode, endOffset);
sel.modify("extend", "forward", "word");
}
}
} else if ( (sel = document.selection) && sel.type != "Control") {
var textRange = sel.createRange();
if (textRange.text) {
textRange.expand("word");
// Move the end back to not include the word's trailing space(s),
// if necessary
while (/'s$/.test(textRange.text)) {
textRange.moveEnd("character", -1);
}
textRange.select();
}
}
}
目前为止,一切都好。 但是,如果在选择上多次调用 snapSelectionToWord
函数,则每次调用时,它都会在两个方向上向外扩展一个单词,如果要在选择文本时多次调用它,则不好。
这是一个实时的jsFiddle示例,它允许您重复单击"捕捉"按钮,该按钮演示了问题。
如何修复原始解决方案,以便在它已经在单词边界上时不会扩展选择?
- 我
- 更愿意对原始解决方案发表评论,但遗憾的是,我还没有被 StackOverflow 业力旅赐予足够的业力——否则,我只会在那里问。 而且我不确定如何解决问题,所以我不会编辑原始解决方案。
编辑:为每个请求添加代码片段
我写了那个样本。由于您指出的原因,我从来都不满意它,也因为它在所有浏览器中(或根本不在 Opera 中)都能一致地工作。
我一直在为我的 Rangy 库研究跨浏览器解决方案。当前版本被描述为 alpha 版本,但它运行良好。下面是一个演示:
http://rangy.googlecode.com/svn/trunk/demos/textrange.html
这是您的演示,修改为使用 Rangy:
http://jsfiddle.net/timdown/RgZ8r/
关键的一条线是
rangy.getSelection().expand("word");
如果你不想使用像Rangy这样重量级的东西(使用TextRange模块需要50KB的代码),那么可以改进原始代码(正如Matt M在他的答案中所做的那样),但它仍然有局限性。
也许在你捕捉单词之前,尝试在任一方向弹出一个字符:
if (backwards) {
sel.modify("move", "backward", "character");
sel.modify("move", "forward", "word");
sel.extend(endNode, endOffset);
sel.modify("extend", "forward", "character");
sel.modify("extend", "backward", "word");
} else {
sel.modify("move", "forward", "character");
sel.modify("move", "backward", "word");
sel.extend(endNode, endOffset);
sel.modify("extend", "backward", "character");
sel.modify("extend", "forward", "word");
}
http://jsfiddle.net/3RAkZ/
您的代码在阿拉伯语文本中无法正常工作你可以试试这个片段nstead
function snapSelectionToWord() {
var sel;
// Check for existence of window.getSelection() and that it has a
// modify() method. IE 9 has both selection APIs but no modify() method.
if (window.getSelection && (sel = window.getSelection()).modify) {
sel = window.getSelection();
if (sel.isCollapsed) {
var rng2 = sel.getRangeAt(0);
var startOffset = rng2.startOffset;
startOffset = 0
for (var i = rng2.startOffset; i >= 0; i--) {
if (rng2.startContainer.data[i].match(/'S/) != null) {
startOffset++;
} else
break;
}
var endOffset = rng2.endOffset;
endOffset = 0;
for (var i = rng2.endOffset; i < rng2.endContainer.data.length; i++)
if (rng2.endContainer.data[i].match(/'S/)) {
endOffset++;
} else
break;
startOffset = rng2.startOffset - startOffset;
startOffset = startOffset < 0 ? 0 : startOffset;
endOffset = rng2.endOffset + endOffset;
endOffset = endOffset >= rng2.endContainer.data.length ? rng2.endContainer.data.length - 1 : endOffset;
rng2.setStart(rng2.startContainer, startOffset);
rng2.setEnd(rng2.endContainer, endOffset);
sel.removeAllRanges();
sel.addRange(rng2);
}
} else if ( (sel = document.selection) && sel.type != "Control") {
var textRange = sel.createRange();
if (textRange.text) {
textRange.expand("word");
// Move the end back to not include the word's trailing space(s),
// if necessary
while (/'s$/.test(textRange.text)) {
textRange.moveEnd("character", -1);
}
textRange.select();
}
}
}
相关文章:
- Javascript返回值只在循环中返回一次
- Jquery FadeIn FadeOut 只工作一次
- Javascript html每点击一次就会更改url
- 如何在chrome扩展中存储数据/结果,以及如何使用setTimeout使其只被调用一次
- Rails操作只调用一次,但我在ajax中每秒钟都调用一次
- jQuery滚动功能只工作一次
- 刷新导致我的帖子“;张贴“;再一次
- 引导程序崩溃一次只能看到一个
- 有没有一个抽象层,这样我就可以集成一次,然后使用pusher、pubnub或faye
- 加载器组件仅加载一次
- 根据Angular.JS上一次的内容禁用选择
- 一次又一次地在新的和相同的选项卡中打开一个url
- 只在宽度以下和宽度以上各准备一次
- 如果30秒未单击,请应用CSS一次,将其删除,然后重新迭代
- Angularjs:空对象,当只有一次点击时
- 在Angular应用程序中每个帖子投票一次
- 主干模型更改事件只触发一次
- 使用每500ms运行一次的jquery函数是个好主意吗
- For循环在Jquery中只运行一次
- 如何使用 JavaScript 将选择扩展到单词边界,仅一次