文章关键字标记方案(内容标记)
有些公司的业务需要把一篇篇文章里面的关键字标记出来,如果不符合的文章就不发布出去,标记文章里面的关键字有多种方案,比如:使用svg进行标记;使用dom进行标记;使用canvas进行标记。
我个人推荐使用Dom进行标记,符合Dom操作的习惯,而且简单易用,易于理解,同时不需要深入了解画图类的技术底层。
几个重要的方法,仅供参考:
1 mark: function(div, text, processer) { //搜索的dom节点,关键字,插入的dom节点 2 return new Promise(function(resolve, reject) { 3 setTimeout(function() { 4 window.focus(); 5 6 let rTemp = document.createRange(); 7 rTemp.selectNodeContents(div); 8 if (rTemp.simpleText().indexOf(text)<0) { // 不包含 9 return resolve(); 10 } 11 let range = null; 12 search(div, function(e, offset) { 13 if (e == BREAK_RANGE) { 14 range = null; 15 return; 16 } 17 rTemp.setStart(e, offset); //设置文章选区的起始位置 18 if (!range && rTemp.simpleText().indexOf(text)==0) { 19 range = document.createRange(); 20 range.setStart(e, offset); 21 } else if (range) { //跨标签时,因为range一直有,所以一定会找到跟标记内容相等的终点位置 22 range.setEnd(e, offset); 23 if (range.simpleText()==text) { 24 let r = processRange(div, range, processer); 25 range = null; 26 return r; 27 } 28 } 29 }); 30 document.getSelection().removeAllRanges(); 31 resolve(); 32 }, 16); 33 }); 34 }
1 function search(node, doSth) { 2 let root = node; 3 function next(node) { 4 if (node == root) return null; 5 if (node.nextSibling) { 6 return node.nextSibling; 7 } 8 return next(node.parentNode); 9 } 10 outer: while (node) { 11 if (node.nodeType==1) { //元素节点,比如div 12 if (/^(script|style|noscript)$/i.test(node.nodeName)) { 13 node = next(node); 14 } else if (/^(input|object|audio|video|embed|select)$/i.test(node.nodeName)) { 15 node = next(node); 16 doSth(BREAK_RANGE); 17 } else if ($(node).is('.mark-txt')) { 18 node = next(node); 19 doSth(BREAK_RANGE); 20 } else if (node.childNodes && node.childNodes.length) { 21 node = node.childNodes[0]; 22 } else { 23 node = next(node); 24 } 25 } else if (node.nodeType == 8) { //一个comment节点 26 // 注释节点 27 node = next(node); 28 } else if (node.nodeType == 3) { //文本节点 29 let s = node.nodeValue; 30 inner: for (let i=0; i<=s.length; i++) { 31 let end = doSth(node, i); 32 if (end) { 33 node = end; 34 break inner; 35 } 36 } 37 node = next(node); 38 } 39 } 40 }
1 function processRange(div, range, processer) { 2 let s = document.getSelection(); 3 s.removeAllRanges(); 4 s.addRange(range); 5 document.execCommand('createLink', false, `${vhref}`); 6 let list = document.querySelectorAll(`a[href="${vhref}"]`); 7 if (!list.length) return; 8 list = [].slice.call(list); 9 list = mergeElement(list); 10 list = list.map(function(oNode) { 11 let childs = [].slice.call(oNode.childNodes); 12 let last = childs[childs.length-1]; 13 if (!(oNode.textContent||'').trim() || oNode.querySelector('img')) { 14 while (childs.length && oNode.parentNode) { 15 oNode.parentNode.insertBefore(childs.shift(), oNode); 16 oNode.parentNode.removeChild(oNode); 17 } 18 return last; 19 } else { 20 let newNode = processer(childs); 21 oNode.parentNode.replaceChild(newNode, oNode); 22 return newNode; 23 } 24 }); 25 return list.pop(); 26 }
1 function commonParent(a, b) { 2 if (contains(a, b)) { 3 return a; 4 } 5 if (regBlock.test(window.getComputedStyle(a)['display'])) { 6 return null; 7 } 8 let p = a.parentNode; 9 while (true) { 10 if (contains(p, b)) { 11 return p; 12 } 13 if (regBlock.test(window.getComputedStyle(p)['display'])) { 14 return null; 15 } 16 p = p.parentNode; 17 } 18 } 19 function unwrap(a, index) { 20 let p = a.parentNode.cloneNode(); 21 p.removeAttribute('id'); 22 p.innerHTML = ''; 23 while (a.childNodes.length) { 24 p.appendChild(a.childNodes[0]); 25 } 26 a.appendChild(p); 27 if (index!=0) { 28 a.parentNode.parentNode.insertBefore(a, a.parentNode); 29 } else { 30 $(a).insertAfter(a.parentNode); 31 } 32 } 33 function importChild(a, b) { 34 while (b.childNodes.length) { 35 a.appendChild(b.childNodes[0]); 36 } 37 } 38 function mergeElement(list) { 39 let n = []; 40 while (list.length>1) { 41 let a = list.shift(); 42 let b = list.shift(); 43 let p = commonParent(a, b); 44 if (p) { 45 list.unshift(p); 46 } else { 47 n.push(a, b); 48 } 49 } 50 list = n.concat(list); 51 list = list.map(function(node) { 52 let aList = [].slice.call(node.querySelectorAll(`a[href="${vhref}"]`)); 53 if (aList.length<1) return node; 54 if (aList.length<2) return aList[0]; 55 aList.forEach((a, i)=> { 56 while (a.parentNode != node) { 57 unwrap(a, i); 58 } 59 }); 60 let s = aList[0]; 61 let e = aList[aList.length-1]; 62 let next = s.nextSibling; 63 console.log('aList:', aList); 64 while (next) { 65 let index = aList.indexOf(next); 66 if (index>-1) { 67 importChild(s, next); 68 next.parentNode.removeChild(next); 69 if (next == e) { 70 return s; 71 } 72 } else { 73 s.appendChild(next); 74 } 75 next = s.nextSibling; 76 } 77 return s; 78 }); 79 return list; 80 }
浙公网安备 33010602011771号