js关于标记选择文案

所用知识

获取及操作选中内容

window.getSelection() / document.getSelection()

使用window.getSelection() / document.getSelection()获取选中内容, 表示用户选择的文本范围或光标的当前位置, 返回一个Selection对象.

Selection对象

Selection对象表示用户选择的文本范围或插入符号的当前位置。它代表页面中的文本选区,可能横跨多个元素。文本选区由用户拖拽鼠标经过文字而产生。要获取用于检查或修改的Selection对象,请调用 window.getSelection()。

  • anchor指向用户开始选择的地方,
  • focus指向用户结束选择的地方。

🌰:

1
2
3
4
5
6
7
8
9
10
11
12
/* 在一个HTML文档中选中所有加粗的文本。 */

var strongs = document.getElementsByTagName("strong");
var s = window.getSelection();

if(s.rangeCount > 0) s.removeAllRanges();

for(var i = 0; i < strongs.length; i++) {
var range = document.createRange();
range.selectNode(strongs[i]);
s.addRange(range);
}

surroundContents

surroundContents() 方法用指定的节点包围范围的内容。

最终实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
chooseSlot(slot) {
let el = window.getSelection()
el.removeAllRanges()
el.addRange(range)
document.execCommand('hiliteColor', true, slot.color)

let fa = el.focusNode.parentElement
fa.setAttribute('data-slot-id', slot.slotId);
fa.innerHTML = fa.innerText
if (fa.nextElementSibling && fa.nextElementSibling.getAttribute('data-slot-id') == ''
&& fa.previousElementSibling && fa.previousElementSibling.getAttribute('data-slot-id') != '') {
fa.nextElementSibling.setAttribute('data-slot-id', fa.previousElementSibling.getAttribute('data-solt-id'));
}
this.dealQuestionSlot(document.querySelector('#content' + this.activeQuestionIndex))
num++
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 递归遍历element对象生成划词数组
* @param element 要处理的问题的element对象
*/
dealQuestionSlot(element) {
let qustion = this.intentData.questionList[this.activeQuestionIndex]
qustion.ranges = []
element.childNodes.forEach(node => {
if (node.toString() == "[object Text]") {
qustion.ranges.push({
text: node.data
})
} else if (node.toString() == "[object HTMLSpanElement]" && node.getAttribute('data-slot-id') != '') {
qustion.ranges.push({
text: node.innerText,
slot: this.intentData.slotList.find(s => {
return s.slotId == node.getAttribute('data-slot-id')
})
})
}
})
this.mackQuestionHtml(this.activeQuestionIndex)
this.showChooseSlot = true
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 遍历ranges,重新生成question
*/
mackQuestionHtml(questionIndex) {
let qustion = this.intentData.questionList[questionIndex]
if (qustion) {
let html = '';
(qustion.ranges || []).forEach(range => {
if (!!range.slot) {
html += `<span data-slot-id="${range.slot.slotId}" style="background-color: ${range.slot.color}">${range.text}</span>`
num++
} else {
html += range.text
}
})
qustion.html = html
}

},