Effect achieved:
There are generally two ways to realize the annotation function:
1, The back end will store the data in two parts: ① plain text in the article area ② string containing HTML structure
When the front end requests data, it will be directly returned to the front end, and the front end will display it directly.
At present, we adopt this idea, which is relatively easy to realize
2, The back end stores a large collection, including the source text and annotation information collection of the article (the starting point and ending point of multiple annotation points). The front end takes the information for processing, echo and operation. Many problems will also arise under this idea. For example, once the span tag is inserted, the length of the source text will be changed, and the recorded starting point and ending point information will be wrong
Several problems encountered during text annotation on the page:
1, Add dimension (dimension of a sliding selection)
① When the mouse slides the selection in the article, the selection area can use window Getselection() to get a selection object selObj
②selObj.toString() gets the text selected by the mouse
③selObj.getRangeAt(0) gets the range object
④range.surroundContents(ele) to the selected package
2, Remove
Remove a label (put the text to be labeled in the title, and then directly replace the DOM with it)
3, It cannot be marked outside the article area, but only in the article area
4, Annotation congener highlighting
Select all sub elements in the document area, traverse, replace the unmarked ones, obtain outerHTML for the marked ones, splice them into an overall HTML string, and replace the DOM in the article area
5, When the dimension source cancels the dimension, the highlight of the same type is also cancelled
(1) When the first and second functions are implemented separately, it is normal to add and remove, but after the four functions replace the DOM in the article area, the removal will be problematic
① Put the removal function on the outermost DOM tree. When you click a button, get the button area, and then carry out relevant operations
(2) When you click the delete button of a label, other same labels will be deleted
① Get the click point target and get the title.
let pText=e.target.parentElement.title
② Get all child nodes under the container
let dom=document.getElementById('docText').childNodes
③ Traverse the set of child nodes, filter and judge that the title is equal, and replace the node with the title text in place to realize the label after deleting the label
for(let i=0;i<dom.length;i++){
/ / only operate on labeled nodes
if(dom[i].textContent.indexOf('*]x') > -1){
if(dom[i].title === pText){
dom[i].replaceWith(pText)
}
}
}
6, Dimension echo
The background will store the data in two parts: ① plain text in the article area ② string containing HTML structure
When the foreground requests data, it is directly returned to the foreground
Key codes:
methods: { toTag(value,index){ let that = this let domNode = document.getElementById('docText') //Judge whether the selected area is in docText let has=window.getSelection().containsNode(domNode, true) if(has){//Determine whether the mouse sliding area is within the document area let str = value.proxy let selObj=window.getSelection() let txtString=selObj.toString() let spanTxt = str.slice(0,2) + txtString + str.slice(2) // console.log(spanTxt) if(txtString){ let range=selObj.getRangeAt(0) // console.log(range) let ele=document.createElement('span') let eleDel=document.createElement('span') ele.style.backgroundColor=value.btnBgColor ele.className='customTag' ele.title=txtString eleDel.className='del_bt' eleDel.textContent='x' // eleDel.onclick=()=>that.toDel(ele) range.surroundContents(ele) let s='<span class="tagText">'+ spanTxt +'</span>' ele.innerHTML=s ele.appendChild(eleDel) //Article annotation (highlight the selected text) let dom=document.getElementById('docText').childNodes console.log(dom) let pingStr='' for(let i=0;i<dom.length;i++){ //Homogeneous highlight //Those that have been marked are excluded. Only for unmarked operations if(dom[i].textContent.indexOf('*]x') === -1){ let paragraph=dom[i].textContent let reg=new RegExp(txtString,'g') let t=`<span class="customTag" title="${txtString}" style="background-color: rgb(167,173,177);"><span class="tagText">${spanTxt}</span><span class="del_bt">x</span></span>` let replacedTxt=paragraph.replace(reg,t) pingStr+=replacedTxt // dom[i].replaceWith(replacedTxt) // console.log(dom[i].textContent) }else{ pingStr+=dom[i].outerHTML // console.log(dom[i].outerHTML) } } // console.log(pingStr) document.getElementById('docText').innerHTML=pingStr window.getSelection().removeAllRanges() } }else{ this.$modal.msgError("Please mark in the document area") } }, //Click the delete button to delete all the same types toDel(e){ if(e.target.className==='del_bt'){ console.log(e.target.parentElement.title) let pText=e.target.parentElement.title console.log(document.getElementById('docText').childNodes) let dom=document.getElementById('docText').childNodes for(let i=0;i<dom.length;i++){ //Operations on dimensions only if(dom[i].textContent.indexOf('*]x') > -1){ if(dom[i].title === pText){ dom[i].replaceWith(pText) } } } } } }