javascript 谷歌浏览器和铬不支持不连续选择错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28215017/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Discontigious Selection is not supported error in google chrome and chromium
提问by Sajid Ahmad
I am working on a bookmark app where i have to store the user's selected keywords or words or content. I am using the createRange() and addRange() javascript methods to create the range and then find out the selected elements/contents by the user. The code i written for this is as follow.
我正在开发一个书签应用程序,我必须在其中存储用户选择的关键字或单词或内容。我正在使用 createRange() 和 addRange() javascript 方法来创建范围,然后找出用户选择的元素/内容。我为此编写的代码如下。
<head>
<script type="text/javascript">
var storedSelections = [];
function StoreSelection () {
if (window.getSelection) {
var currSelection = window.getSelection ();
for (var i = 0; i < currSelection.rangeCount; i++) {
storedSelections.push (currSelection.getRangeAt (i));
}
currSelection.removeAllRanges ();
} else {
alert ("Your browser does not support this example!");
}
}
function ClearStoredSelections () {
storedSelections.splice (0, storedSelections.length);
}
function ShowStoredSelections () {
if (window.getSelection) {
var currSelection = window.getSelection ();
currSelection.removeAllRanges ();
for (var i = 0; i < storedSelections.length; i++) {
currSelection.addRange (storedSelections[i]);
}
} else {
alert ("Your browser does not support this example!");
}
}
</script>
</head>
<body>
Select some content on this page and use the buttons below.<br /> <br />
<button onclick="StoreSelection ();">Store the selection</button>
<button onclick="ClearStoredSelections ();">Clear stored selections
</button>
<button onclick="ShowStoredSelections ();">Show stored selections</button>
</body>
This code is working perfectly on Firefox. I am able to select multiple things one by one and able to show the selected content again but on chrome and chromium i am getting Discontiguous selection is not supported.
error when i store more than one elements in range array and click on show stored selections button.
此代码在 Firefox 上运行良好。我能够一一选择多个内容,并能够再次显示所选内容,但是在 chrome 和 Chromium 上,Discontiguous selection is not supported.
当我在范围数组中存储多个元素并单击“显示存储的选择”按钮时出现错误。
Help will be appreciated. And please suggest me if there is some other alternatives do accomplish this bookmarking task.
帮助将不胜感激。如果有其他替代方法可以完成此书签任务,请建议我。
回答by Shashikant Pandit
Write
写
window.getSelection().removeAllRanges();
immediately before creating range.
在创建范围之前。
https://bugs.chromium.org/p/chromium/issues/detail?id=399791
https://bugs.chromium.org/p/chromium/issues/detail?id=399791
回答by Siguza
Here's the only possible way of doing this that I was able to come up with:
这是我能想出的唯一可能的方法:
Wrap the selection in <span style="background: Highlight;">...</span>
.
将选择包裹在<span style="background: Highlight;">...</span>
.
But note:
但请注意:
- Obviously, you have to remove those spans again as soon as anything else is selected, but that shouldn't be too difficult. However, you should use
window.onmousedown
for that rather thanwindow.onclick
, becauseonclick
is fired afterany button is pressed, so when pressing your "Show stored selections" button, a new selection will be created, thus destroying the one that was supposed to be captured. - Removing or replacing any elements in which a stored selection starts or ends will invalidate that selection, so when clicking "Show stored selections", nothing will show up.
- If the selection spans over multiple elements, it needs to split up into one selection for each element, otherwise inserting the span will either fail or cut other elements (like buttons) in half.
- 显然,一旦选择了其他任何东西,您就必须再次删除这些跨度,但这应该不会太难。但是,您应该使用
window.onmousedown
for that 而不是window.onclick
,因为在按下任何按钮后onclick
会触发,因此当按下“显示存储的选择”按钮时,将创建一个新选择,从而破坏应该被捕获的选择。 - 删除或替换存储选择开始或结束的任何元素将使该选择无效,因此当单击“显示存储的选择”时,不会显示任何内容。
- 如果选择跨多个元素,则需要为每个元素拆分为一个选择,否则插入跨度将失败或将其他元素(如按钮)切成两半。
The following code (fiddle) is the best I was able to do:
以下代码(小提琴)是我能做的最好的:
var storedSelections = [];
var simulatedSelections = [];
window.onmousedown = clearSimulatedSelections;
function storeSelection()
{
if(window.getSelection)
{
var currSelection = window.getSelection();
for(var i = 0; i < currSelection.rangeCount; i++)
{
storeRecursive(currSelection.getRangeAt(i));
}
currSelection.removeAllRanges();
}
else
{
alert("Your browser does not support this example!");
}
}
function storeRecursive(selection, node, started)
{
node = node || document.body;
started = started || false;
var nodes = node.childNodes;
for(var i = 0; i < nodes.length; i++)
{
if(nodes[i].nodeType == 3)
{
var first = nodes[i] == selection.startContainer;
var last = nodes[i] == selection.endContainer;
if(first)
{
started = true;
}
if(started)
{
var sel = selection.cloneRange();
if(!first)
{
sel.setStartBefore(nodes[i]);
}
if(!last)
{
sel.setEndAfter(nodes[i]);
}
storedSelections.push(sel);
if(last)
{
return false;
}
}
}
else
{
started = storeRecursive(selection, nodes[i], started);
}
}
return started;
}
function clearStoredSelections()
{
storedSelections = [];
}
function showStoredSelections()
{
if(window.getSelection)
{
var currSelection = window.getSelection();
currSelection.removeAllRanges();
for(var i = 0; i < storedSelections.length; i++)
{
var node = document.createElement("span");
node.className = "highlight";
storedSelections[i].surroundContents(node);
simulatedSelections.push(node);
}
}
else
{
alert("Your browser does not support this example!");
}
}
function clearSimulatedSelections()
{
for(var i = 0; i < simulatedSelections.length; i++)
{
var sec = simulatedSelections[i];
var pn = sec.parentNode;
while(sec.firstChild)
{
pn.insertBefore(sec.firstChild, sec);
}
pn.removeChild(sec);
}
simulatedSelections = [];
}
.highlight
{
background: Highlight;
}
Select some content on this page and use the buttons below.<br><br>
<button onclick="storeSelection();">Store the selection</button>
<button onclick="clearStoredSelections();">Clear stored selections</button>
<button onclick="showStoredSelections();">Show stored selections</button>
It works in Firefox, Safari and Chrome, but has the following shortcomings:
它适用于 Firefox、Safari 和 Chrome,但有以下缺点:
- Selections over multiple lines don't select the blank area between the end of the line and the border of the parent element, like actual selections do.
- Sometimes when starting a selection at a point before the start of a stored selection, displaying them will merge the ranges, so the text in between is selected too. Sorting the array of stored selections doesn't seem to help.
- In Safari, the tab crashed multiple times with a segmentation fault when selecting multiple lines and ending/starting a selection in the middle of a button's text.
- 多行选择不会像实际选择那样选择行尾和父元素边框之间的空白区域。
- 有时在存储选择开始之前的某个点开始选择时,显示它们会合并范围,因此也选择了中间的文本。对存储的选择数组进行排序似乎没有帮助。
- In Safari, the tab crashed multiple times with a segmentation fault when selecting multiple lines and ending/starting a selection in the middle of a button's text.
However, I doubt that anything better is possible in browsers other than Firefox, but even Firefox has a ticket to drop discontiguous selections.
但是,我怀疑在 Firefox 之外的浏览器中是否有更好的可能,但即使是Firefox 也有删除不连续选择的票证。
回答by Kayce Basques
FYI I was getting a similar error when rolling my own "copy to clipboard" feature. I'm not going to address OP's provided code, but I'll tell you how I fixed it in my own code.
仅供参考,我在滚动我自己的“复制到剪贴板”功能时遇到了类似的错误。我不打算解决 OP 提供的代码,但我会告诉你我是如何在自己的代码中修复它的。
Reproduce:
复制:
- Copy some other text on the page to the clipboard, e.g. "foo".
- Paste the text somewhere. It outputs "foo".
- Click your "copy to clipboard" button, which copies e.g. "bar".
- Paste the text somewhere.
- 将页面上的一些其他文本复制到剪贴板,例如“foo”。
- 将文本粘贴到某处。它输出“foo”。
- 单击“复制到剪贴板”按钮,该按钮复制“条”。
- 将文本粘贴到某处。
Expected:
预期的:
"bar" is outputted.
输出“bar”。
Actual:
实际的:
"Discontiguous selection is not supported"
“不支持不连续选择”
Fix:
使固定:
Call window.getSelection().removeAllRanges()
at the startof your "copy to clipboard" event handler. "Discontiguous" means "not connected". So my guess is that the browser copies the first range (the node containing "foo"), and then gets angry when you try to select another range that is not next to the first node.
window.getSelection().removeAllRanges()
在“复制到剪贴板”事件处理程序开始时调用。“不连续”的意思是“不相连”。所以我的猜测是浏览器复制了第一个范围(包含“foo”的节点),然后当您尝试选择不在第一个节点旁边的另一个范围时会生气。