【发布时间】:2014-05-29 09:07:05
【问题描述】:
我尝试将用户所做的选择修改为始终是完整的单词。例如,鉴于文本“报告:奥巴马总统寻求在阿富汗保留 9,800 名美军……消息人士称,今年之后”,如果用户只选择“fghanist”,我希望选择修改为“阿富汗”。经过一番搜索,我在 Stackoverflow 上偶然发现了 here,得到了以下解决方案:
snapSelectionToWord : function() {
var sel;
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);
var direction = [];
if (backwards) {
direction = ['backward', 'forward'];
} else {
direction = ['forward', 'backward'];
}
sel.modify("move", direction[0], "character");
sel.modify("move", direction[1], "word");
sel.extend(endNode, endOffset);
sel.modify("extend", direction[1], "character");
sel.modify("extend", direction[0], "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();
}
}
},
原则上,它工作得很好。然而,也有一些病态的案例。例如,选择“fghanistan..”它会捕捉到“Afghanistan...after”(我想要“Afghanistan”)。我选择“.afte”得到的结果相同(这里的期望结果:“after”)。主要问题似乎是粒度word 只考虑空格而不考虑其他标点符号。
我现在的想法是将粒度从 word 更改为 character 并将其放入循环中,直到达到标点符号。这对于sel.modify("extend", ...); 行非常有效,但对于sel.modify("move", ...); 行却不是(如预期的那样)。在collapse 和第一个move 修改之后,sel.toString() 都是空的。因此,我不能循环第一个/最后一个字符来逐个字符移动。在sel.extend(endNode, endOffset);之后,再次设置sel.toString(),使用循环的方法就可以了。
我根本无法理解这一点。
【问题讨论】:
-
自动选择整个单词的应用程序让我发疯。请注意,有些用户会非常讨厌这一点。 :-)
-
RobG,同意!我也不喜欢被光顾:)。但是,我的目标是用户注释文本 sn-ps 的系统。也就是说,他们首先选择一个 sn-p,然后可以对其进行注释。我认为在这种情况下对齐单词边界是合理的。
标签: javascript html dom selection