【问题标题】:javascript range surroundContents() catch InvalidStateErrorjavascript 范围环绕内容()捕获 InvalidStateError
【发布时间】:2020-05-16 17:14:34
【问题描述】:

我有一个带有溢出的 div:hidden 包含混合内容 html/文本。 我对这个 div 容器应用了 mousedown 和 mouseup 事件。如果用户在 mousedown 时突出显示内容,则选择会在 mouse up 事件中捕获。

一切正常,(直到/或如果)用户执行以下操作:

用户在 div 容器内按下 mousedown,突出显示特定内容,然后在按下鼠标按钮的同时将指针移到容器外,然后释放鼠标按钮,在 div 容器外调用 mouseup 事件。

我收到此错误: InvalidStateError:尝试使用不可用或不再可用的对象。

我想要实现的是: 如果鼠标按钮在 div 容器外释放,我只想保留容器内仍然突出显示的内容。如果这是不可能的,请删除所有范围/选择/突出显示。

我已阅读有关 .getSelection() 和无效状态错误的所有文档,并在谷歌上搜索所有试图找到结果的方法。

我读过的所有内容都无法捕获 InvalidStateError 或如何处理选择以将内容保留在 div 容器中。

这是我的代码示例:

<style>container{width:120px;height:120px;overflow:hidden;}</style>



<div class="container">testNode text testNode text testNode text testNode text testNode text testNode text testNode text testNode texttestNode text testNode texttestNode texttestNode texttestNode texttestNode texttestNode texttestNode texttestNode texttestNode texttestNode texttestNode texttestNode texttestNode texttestNode texttestNode texttestNode texttestNode text</div>



<script>$('.container').on('mouseup', function(){    
            var sel = getSelection();
            var range = sel.getRangeAt(0).cloneRange();
            var end = sel.toString().length;
            var newNode = document.createElement('tmp');
            /*on this following line i get invalidstate error
            if mouse released outside the container div*/
            range.surroundContents(newNode);
            sel.removeAllRanges();
            sel.addRange(range);
})
</script>

【问题讨论】:

  • 更新: 我发现通过将范围内容放入字符串并在主容器 html/text 中找到 indexOf(字符串格式的范围值)来消除 invalidstateerror。如果 indexOf(range string) == -1 则不要用新节点包装容器的内容。这消除了错误。但是,我更愿意仅在 div 中获取高亮部分的内容。第一次选择尝试,即使它超出了边界

标签: javascript jquery getselection


【解决方案1】:
container = $('.container');
containerString = $('.container').html().toString();
selection = range.cloneContents();
selectionString = selection converted to String();
containerSelectionString = selection append to div get      
$('.container').html().toString();

如果滚动超出范围,我制定了一个解决方案并摆脱了 range.surroundContents(newNode) 。 此解决方案获取用户 selectionString ,然后将 selectionString 与 containerString 进行比较。 如果 containerString 具有 selectionString 的索引,则像上面的第一个代码一样正常进行, 否则,如果 selectionString 的索引为 -1(不存在),那么我们知道鼠标超出范围,因此我们将选择附加到新创建的 div 元素,然后我们得到我们的 containerSelectionString。现在我们知道用户从容器中选择了什么。

现在!!

我们获取我们的 containerSelectionString 并检查它是否唯一并且存在于容器中,如果是,我们可以包装范围。我们测试容器字符串是否只出现一次如下:

if containerString.indexOf(containerSelectionString) == containerString.lastIndexOf(containerSelectionString && containerString.indexOf(containerSelectionString) != -1)

现在我们知道字符串是否唯一且存在。

现在很简单,我们使用我们的 containerString 并像这样进行改造:

containerString  = containerString.substring(0, containerString.indexOf(containerSelectionString)) + '<tmp>' + containerSelectionString + '</tmp>' + (containerString.indexOf(containerSelectionString) + containerSelectionString.length))

现在我们只需使用新的 containerString 填充容器,然后在我的情况下,将 temp 设置为具有独特的背景颜色。就是这样。

如果字符串不是唯一的,我们就让选择消失。可能有一种方法可以从选择或范围中获取 startindex,然后在开始索引处拆分 divtext,如果结束索引较高,则使用字符串的第二部分并匹配,或者如果结束索引较低,则使用第一个字符串的一部分,但是对于我的需要,这个解决方案很好,如果文本不是唯一的,用户只有 10% 的机会需要重新选择文本。

希望对您有所帮助。

顺便说一句!这里的 get .getSelection() 实际上是我做的一个小函数,以防你在不同的浏览器上使用它,这里是 getSelection() 函数:

$.fn.getSelection = function() {
    if (window.getSelection) {
        return window.getSelection();
    } else if (document.getSelection) {
        return document.getSelection();
    } else if (document.selection) {
        return document.selection.createRange().htmlText;
    }
};

代码如下:

$('.container').on('mouseup', function(){  
   var divObject = $(this);   
        var sel = getSelection();
        var range = sel.getRangeAt(0).cloneRange();
        var end = sel.toString().length;

                divText = divObject.html().toString();
                var selHTML = range.cloneContents();
                var div = document.createElement("div");
                div.appendChild(selHTML);
                var testS = div.innerHTML.toString();
                var findx = divText.indexOf(testS);
                if (findx > -1) {
                    var newNode = document.createElement('tmp');
                    range.surroundContents(newNode);
                    sel.removeAllRanges();
                    sel.addRange(range);
                } else {
             var testS = div.querySelector('.container').innerHTML.toString();
             var findx = divText.indexOf(testS);
             if (findx == divText.lastIndexOf(testS) && findx != -1) {
             var sindx = findx + testS.length;
             divText = divText.substring(0, findx) + '<tmp>' + testS + '</tmp>' + divText.substring(sindx);
                        divObject.html(divText);
                    } 
}
                   div.remove();
})

【讨论】:

    猜你喜欢
    • 2015-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-07
    • 1970-01-01
    • 2018-05-21
    • 2017-01-22
    • 1970-01-01
    相关资源
    最近更新 更多