V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
LUREN
V2EX  ›  JavaScript

能否使用 JavaScript 选中网页里的指定文字?

  •  
  •   LUREN · 2020-05-03 16:13:28 +08:00 · 2599 次点击
    这是一个创建于 1453 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题。是否可能使用 JavaScript 选择网页里的指定文字?

    有这个问题是因为需要选择某个节点的文字移动到其它节点显示。但是网页内容又是程序生成的,文字不在固定的节点里,节点元素也没有 id class 选择器。

    kaiki
        1
    kaiki  
       2020-05-03 16:17:49 +08:00
    没有任何可以参考的变量怎么去选取啊?这个选择的规则是什么?
    yafoo
        2
    yafoo  
       2020-05-03 16:21:12 +08:00 via Android   ❤️ 1
    既然能指定到文字,那肯定能指定到选择器,把节点发出来看看,让大家帮你定位到元素
    LUREN
        3
    LUREN  
    OP
       2020-05-03 16:24:40 +08:00
    @kaiki 文字所在的节点元素不固定,节点元素没有选择器,没有特征淹没在一大段内容里。。。
    能够确定的是需要选择的文字是固定的,移动目标节点元素有 id 选择器,这种情况还有解么?
    ClericPy
        4
    ClericPy  
       2020-05-03 16:27:05 +08:00
    看楼主的意思... 就是根据文字然后选中它, 这个选中是找到节点就行, 还是框选 createTextRange 那样?

    PS: 能直接给例子或者描述完整需求么, 有可能一开始方向就歪了啊...
    kaiki
        5
    kaiki  
       2020-05-03 16:29:13 +08:00
    @LUREN 循环整个页面,处理这段文字,找到有特征的部分,用正则找出来,原来找到的部分该怎么处理怎么处理,新抓出来的这一段,该放哪放哪,这样可行吗?
    ClericPy
        6
    ClericPy  
       2020-05-03 16:33:49 +08:00
    听起来像 jQuery 的 contains...
    imn1
        7
    imn1  
       2020-05-03 16:36:22 +08:00   ❤️ 1
    css 选择器没有内容相关的,其实 css1/2 有,不知为何 css3 取消了
    建议用 javascript 调用 xpath 的 text()搜索节点

    另一个思路是不需要移动节点,把文字复制 /移动过去,让原节点不可见、不占位也可以
    xiangyuecn
        8
    xiangyuecn  
       2020-05-03 16:45:50 +08:00
    这是一个高级主题哦,要收费的。。虽然完成整个功能涉及的知识不多,但深度够深了😂

    我也不会写,吹水,目测逃不过:

    从 body 节点开始递归遍历所有节点,发现 text node 就判断一下是否包含特定文本,然后反过来确认包含此 text node 的上级 node 是符合需求的节点,然后全部找到,下一步脱裤子搞事
    LUREN
        9
    LUREN  
    OP
       2020-05-03 16:46:27 +08:00
    Arrowing
        10
    Arrowing  
       2020-05-03 16:57:18 +08:00
    可以。
    1 、遍历所有 body 下所有的含文字的节点( div 、span 、p 等);
    2 、筛选出 innerHTML 包含你指定文字的节点;
    3 、使用 window.getSelection 和 addRange 来 选中文字。

    ```javascript
    function selectText(text) {
    let nodes = document.querySelectorAll('body *')
    let textNode
    let textStartIndex
    for (let i = 0, len = nodes.length; i < len; i++) {
    textStartIndex = nodes[i].innerHTML.indexOf(text)
    if (textStartIndex > -1) {
    if (nodes[i].children.length === 0) {
    textNode = nodes[i]
    break // 找到即返回
    }
    }
    }

    if (textNode) {
    let range = document.createRange()
    // range.selectNode(textNode)
    range.setStart(textNode.firstChild, textStartIndex)
    range.setEnd(textNode.firstChild, textStartIndex + text.length)

    let selection = window.getSelection()
    selection.removeAllRanges()
    selection.addRange(range)
    }
    }

    selectText('指定文字') // 当前 V2EX 页面执行
    ```

    * 以上代码仅用于作为示例代码,并没有做边界测试,浏览器兼容,性能优化。
    vangkinva
        11
    vangkinva  
       2020-05-03 16:58:01 +08:00
    把 html 节点和内容都当文本,然后通过文字找到他在文本中的位置,通过向上比对找到它的节点名称,然后就找到他的节点了?
    8qwe24657913
        12
    8qwe24657913  
       2020-05-03 17:01:19 +08:00
    用 xpath 啊
    ```javascript
    const result = document.evaluate("//text()[contains(string(), '这里填文字内容')]", document.body, null, XPathResult.ANY_TYPE, null)
    let textNode
    while (textNode = result.iterateNext()) console.log(textNode)
    ```
    ClericPy
        13
    ClericPy  
       2020-05-03 17:02:14 +08:00
    我就感觉一开始需求就解读有问题...

    这种情况先把 DemoA 的数据结构化成 map, 然后再迭代 DemoB, 从 map 里取 Google 什么的, 取到就塞
    xiangyuecn
        14
    xiangyuecn  
       2020-05-03 17:05:38 +08:00
    #9 你这个 demo 倒是简单了,也太工整了吧,怎么会没有特征?一次简单的遍历全部找到需要的内容节点

    document.querySelector("#demoBoxA").querySelectorAll(".row").forEach(function(v){
    if(/Google|Huawei|BlackBerry/i.test(v.querySelector(".col-md-6").innerText)){//text node 内容匹配检测
    document.querySelector("#demoBoxB").appendChild(v) //下一步脱裤子搞事的事情自己写
    }
    })
    LUREN
        15
    LUREN  
    OP
       2020-05-03 20:04:27 +08:00
    @Arrowing
    @8qwe24657913
    @ClericPy
    @xiangyuecn 感谢大佬们提供的解決思路,我去试试。
    rabbbit
        16
    rabbbit  
       2020-05-03 20:38:15 +08:00
    const rowEls = Array.from(document.querySelectorAll("#demoBoxA .row"));
    rowEls.sort((a, b) => a.firstElementChild.innerText.localeCompare(b.firstElementChild.innerText));
    const boxB = document.querySelector("#demoBoxB");
    boxB.innerHTML = "";
    for (let el of rowEls) {
    boxB.appendChild(el);
    }
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1766 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 16:40 · PVG 00:40 · LAX 09:40 · JFK 12:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.