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

2020-05-03 16:13:28 +08:00
 LUREN

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

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

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

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

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

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

从 body 节点开始递归遍历所有节点,发现 text node 就判断一下是否包含特定文本,然后反过来确认包含此 text node 的上级 node 是符合需求的节点,然后全部找到,下一步脱裤子搞事
LUREN
2020-05-03 16:46:27 +08:00
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
2020-05-03 16:58:01 +08:00
把 html 节点和内容都当文本,然后通过文字找到他在文本中的位置,通过向上比对找到它的节点名称,然后就找到他的节点了?
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
2020-05-03 17:02:14 +08:00
我就感觉一开始需求就解读有问题...

这种情况先把 DemoA 的数据结构化成 map, 然后再迭代 DemoB, 从 map 里取 Google 什么的, 取到就塞
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
2020-05-03 20:04:27 +08:00
@Arrowing
@8qwe24657913
@ClericPy
@xiangyuecn 感谢大佬们提供的解決思路,我去试试。
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);
}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/668269

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX