【问题标题】:How to limit Javascript's window.find to a particular DIV?如何将 Javascript 的 window.find 限制为特定的 DIV?
【发布时间】:2013-02-28 18:03:53
【问题描述】:

是否可以在 Safari/Firefox/Chrome 中使用 Javascript 在特定 div 容器中搜索给定的文本字符串。我知道您可以使用window.find(str) 搜索整个页面,但是否可以将搜索区域仅限于 div?

谢谢!

【问题讨论】:

    标签: javascript google-chrome firefox safari


    【解决方案1】:

    一旦您查找您的 div(您可以通过 document.getElementById 或任何其他 DOM 函数,various specs here),您可以使用 textContentinnerText 来查找该文本div。然后你可以使用indexOf 来查找其中的字符串。

    或者,在较低级别,您可以使用递归函数来搜索窗口中的所有文本节点,这听起来比实际复杂得多。基本上,从你的目标div(这是一个Element)开始,你可以遍历它的childNodes并搜索他们的nodeValue字符串(如果他们是Texts)或递归到他们(如果他们'是Elements)。

    诀窍在于,幼稚版本无法在此标记中找到 "foo"

    <p><span>fo</span>o</p>
    

    ...因为两个Text 节点都没有nodeValue"foo"(其中一个有"fo",另一个有"o")。

    【讨论】:

    • 我实际上是在寻找复制浏览器查找功能(该字符串将被突出显示,并且在再次单击搜索时它会向下移动到 Div 内的下一个匹配项,等等)。
    • @VeePee:恐怕您必须编写它(这是可能的,只是一个真正的痛苦),即使window.find 也不是标准化的。但同样,这是可能的,因为您可以在 Text 节点中找到文本,将该节点拆分为用突出显示的 span 等围绕它。
    【解决方案2】:

    根据您要执行的操作,有一种有趣的方法可以做到这一点(确实需要一些工作)。

    首先,搜索从用户最后点击的位置开始。因此,要获得正确的上下文,您可以强制单击 div。这会将内部指针放在 div 的开头。

    然后,您可以像往常一样使用 window.find 来查找元素。它将突出显示并移至找到的下一个项目。您可以创建自己的对话框并处理 find 返回的 true 或 false,以及检查位置。所以举个例子,你可以保存当前的滚动位置,如果下一个返回的结果在 div 之外,你就恢复滚动。另外,如果返回 false,则可以说没有找到结果。

    您还可以显示默认搜索框。在这种情况下,您可以指定起始位置,但不能指定结束位置,因为您失去了控制。

    一些示例代码可帮助您入门。如果有足够的兴趣,我也可以尝试放置一个 jsfiddle。

    语法:

    window.find(aStringToFind, bCaseSensitive, bBackwards, bWrapAround, bWholeWord, bSearchInFrames, bShowDialog);
    

    例如,要开始在 myDiv 中搜索,请尝试

    document.getElementById("myDiv").click(); //Place cursor at the beginning
    window.find("t", 0, 0, 0, 0, 0, 0); //Go to the next location, no wrap around
    

    您可以设置一个模糊(失去焦点)事件处理程序,以便在您离开 div 时通知您,以便您停止搜索。

    要保存当前滚动位置,请使用 document.body.scrollTop。如果它试图跳出 div,你可以将其设置回来。

    希望这会有所帮助! 〜技术老兄

    【讨论】:

    • 我应该补充一下,这在 firefox/chrome/safari 中确实有效。
    【解决方案3】:

    根据其他答案,您将无法为此使用 window.find 功能。好消息是,您不必完全自己编程,因为现在有一个名为 rangy 的库,它对此有很大帮助。因此,由于代码本身有点太多,无法将粘贴复制到此答案中,因此我将仅参考可以是 found here 的 rangy 库的代码示例。查看代码你会发现

     searchScopeRange.selectNodeContents(document.body);
    

    你可以替换成

     searchScopeRange.selectNodeContents(document.getElementById("content"));
    

    仅在内容 div 中专门搜索。

    【讨论】:

      【解决方案4】:

      如果你还在寻找一些东西,我想我找到了一个很好的解决方案;

      这里是:https://www.aspforums.net/Threads/211834/How-to-search-text-on-web-page-similar-to-CTRL-F-using-jQuery/

      我正在努力删除 jQuery (wip):codepen.io/eloiletagant/pen/MBgOPB 希望还不算太晚:)

      【讨论】:

        【解决方案5】:
        var elements = [];
        $(document).find("*").filter(function () {
          if($(this).text().contains(yourText))
            elements.push($(this));
        });
        console.log(elements);
        

        我没有尝试过,但根据 jQuery 文档应该可以工作。

        【讨论】:

          【解决方案6】:

          这是我对 jquery 的处理方式:

          var result = $('#elementid').text().indexOf('yourtext') > -1
          

          它会返回真或假

          【讨论】:

            【解决方案7】:

            您可以使用Window.find() 搜索页面中的所有匹配项,使用Node.contains() 过滤掉不合适的搜索结果。
            下面是一个如何查找和突出显示特定元素中所有出现的字符串的示例:

            var searchText = "something"
            var container = document.getElementById("specificContainer");
            // selection object
            var sel = window.getSelection()
            sel.collapse(document.body, 0)
            // array to store ranges found
            var ranges = []
            // find all occurrences in a page
            while (window.find(searchText)) {
                // filter out search results outside of a specific element
                if (container.contains(sel.anchorNode)){
                    ranges.push(sel.getRangeAt(sel.rangeCount - 1))
                }
            }   
            // remove selection
            sel.collapseToEnd()
            
            // Handle ranges outside of the while loop above.
            // Otherwise Safari freezes for some reason (Chrome doesn't).
            if (ranges.length == 0){
                alert("No results for '" + searchText + "'")
             } else {
                for (var i = 0; i < ranges.length; i++){
                    var range = ranges[i]
                    if (range.startContainer == range.endContainer){
                        // Range includes just one node
                        highlight(i, range)
                    } else {
                        // More complex case: range includes multiple nodes
                        // Get all the text nodes in the range
                        var textNodes = getTextNodesInRange(
                                            range.commonAncestorContainer,
                                            range.startContainer,
                                            range.endContainer) 
            
                        var startOffset = range.startOffset
                        var endOffset = range.endOffset
                        for (var j = 0; j < textNodes.length; j++){
                            var node = textNodes[j]
                            range.setStart(node, j==0? startOffset : 0)
                            range.setEnd(node, j==textNodes.length-1? 
                                                   endOffset : node.nodeValue.length)
                            highlight(i, range)
                        }
                    }
                }
            }
            
            function highlight(index, range){
                var newNode = document.createElement("span")
                // TODO: define CSS class "highlight"
                // or use <code>newNode.style.backgroundColor = "yellow"</code> instead
                newNode.className = "highlight"
                range.surroundContents(newNode)
                // scroll to the first match found
                if (index == 0){
                    newNode.scrollIntoView()
                }
            }
            
            function getTextNodesInRange(rootNode, firstNode, lastNode){
                var nodes = []
                var startNode = null, endNode = lastNode
                var walker = document.createTreeWalker(
                        rootNode,
                        // search for text nodes
                        NodeFilter.SHOW_TEXT,
                        // Logic to determine whether to accept, reject or skip node.
                        // In this case, only accept nodes that are between
                        // <code>firstNode</code> and <code>lastNode</code>
                        {
                            acceptNode: function(node) {
                                if (!startNode) {
                                    if (firstNode == node){
                                        startNode = node
                                        return NodeFilter.FILTER_ACCEPT
                                    }
                                    return NodeFilter.FILTER_REJECT
                                }
            
                                if (endNode) {
                                    if (lastNode == node){
                                        endNode = null
                                    }
                                    return NodeFilter.FILTER_ACCEPT
                                }
            
                                return NodeFilter.FILTER_REJECT
                             }
                        },
                        false
                    )
            
                while(walker.nextNode()){
                    nodes.push(walker.currentNode);
                }
                return nodes;
            }
            

            对于Range 对象,请参阅https://developer.mozilla.org/en-US/docs/Web/API/Range
            对于TreeWalker 对象,请参阅https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker

            【讨论】:

              【解决方案8】:

              也许你试图不使用 jquery...但如果没有,你可以使用这个 $('div:contains(whatyouarelookingfor)') 唯一的问题是它可以返回也包含匹配的子 div 的父元素。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-05-18
                • 1970-01-01
                • 1970-01-01
                • 2012-04-04
                相关资源
                最近更新 更多