¡¡¡¡1. ʲôÊÇ“»®´Ê¸ßÁÁ”£¿
¡¡¡¡ÓÐЩͬѧ¿ÉÄܲ»Ì«Çå³þ“»®´Ê¸ßÁÁ”ÊÇָʲô£¬ÏÂÃæ¾ÍÊÇÒ»¸öµäÐ͵ē»®´Ê¸ßÁÁ”£º
¡¡¡¡Óû§Ñ¡ÔñÒ»¶ÎÎı¾£¨¼´»®´Ê£©£¬¼´»á×Ô¶¯½«Õâ¶ÎÑ¡È¡µÄÎı¾Ìí¼Ó¸ßÁÁ±³¾°£¬Óû§¿ÉÒԺܷ½±ãµØΪÍøÒ³Ìí¼ÓÔÚÏ߱ʼǡ£
¡¡¡¡±ÊÕßÇ°¶Îʱ¼äΪÏßÉÏÒµÎñʵÏÖÁËÒ»¸öÓëÄÚÈݽṹ·ÇñîºÏµÄÎı¾¸ßÁÁÔÚÏ߱ʼǹ¦ÄÜ¡£·ÇñîºÏÊÇÖ¸²»ÐèҪΪ¸ßÁÁ¹¦Äܽ¨Á¢ÌØÊâµÄÒ³Ãæ DOM ½á¹¹£¬¶ø¸ßÁÁ¹¦ÄܶÔÒµÎñ½üºõ͸Ã÷¡£¸Ã¹¦ÄܺËÐIJ¿·Ö¾ßÓнÏÇ¿µÄͨÓÃÐÔÓëÒÆÖ²ÐÔ£¬¹ÊÄóöÀ´ºÍ´ó¼Ò·ÖÏí½»Á÷һϡ£
¡¡¡¡±¾ÎľßÌåµÄºËÐÄ´úÂëÒÑ·â×°³É¶ÀÁ¢¿â web-highlighter£¬ÔĶÁÖÐÈçÓÐÒÉÎʿɲο¼ÆäÖдúÂë↓↓¡£
¡¡¡¡2. ʵÏÖ“»®´Ê¸ßÁÁ”ÐèÒª½â¾öÄÄЩÎÊÌ⣿
¡¡¡¡ÊµÏÖÒ»¸ö“»®´Ê¸ßÁÁ”µÄÔÚÏ߱ʼǹ¦ÄÜÐèÒª½â¾öµÄºËÐÄÎÊÌâÓÐÁ½¸ö£º
¡¡¡¡¼Ó¸ßÁÁ±³¾°¡£¼´ÈçºÎ¸ù¾ÝÓû§ÔÚÍøÒ³ÉϵÄÑ¡È¡£¬ÎªÏàÓ¦µÄÎı¾Ìí¼Ó¸ßÁÁ±³¾°£»
¡¡¡¡¸ßÁÁÇøÓòµÄ³Ö¾Ã»¯Ó뻹ԡ£¼´ÈçºÎ±£´æÓû§¸ßÁÁÐÅÏ¢£¬²¢ÔÚÏ´Îä¯ÀÀʱ׼ȷ»¹Ô£¬·ñÔòÏ´δò¿ªÒ³ÃæÓû§¸ßÁÁµÄÐÅÏ¢¾Í¶ªÊ§ÁË¡£
¡¡¡¡Ò»°ãÀ´Ëµ£¬»®´Ê¸ßÁÁµÄÒµÎñÐèÇó·½Ö÷ÒªÊÇÕë¶Ô×Ô¼º²ú³öµÄÄÚÈÝ£¬Äã¿ÉÒԱȽÏÈÝÒ׶ÔÄÚÈÝÔÚÍøÒ³ÉϵÄÅÅ°æ¡¢HTML ±êÇ©µÈ·½Ãæ½øÐпØÖÆ¡£ÕâÖÖÇé¿öÏ£¬´¦Àí¸ßÁÁÐèÇó»á¸ü·½±ãһЩ£¬±Ï¾¹×Ô¼º¿ÉÒÔ¸ù¾Ý¸ßÁÁÐèÇóµ÷ÕûÏÖÓÐÄÚÈÝµÄ HTML¡£
¡¡¡¡¶ø±ÊÕßÃæ¶ÔµÄÇé¿öÊÇ£¬Ò³Ãæ HTML ÅÅ°æ½á¹¹¸´ÔÓ£¬ÇÒÎÞ·¨¸ù¾Ý¸ßÁÁÐèÇóÀ´Íƶ¯ÒµÎñ¸Ä¶¯ HTML¡£ÕâÒ²´ßÉú³öÁ˶Խâ¾ö·½°¸¸üͨÓû¯µÄÒªÇó£¬Ä¿±ê¾ÍÊÇ£ºÕë¶ÔÈÎÒâÄÚÈݾù¿É“»®´Ê¸ßÁÁ”²¢Ö§³ÖºóÐø·ÃÎÊʱ»¹Ô¸ßÁÁ״̬£¬¶ø²»ÓÃÈ¥¹ØÐÄÄÚÈݵÄ×éÖ¯½á¹¹¡£
¡¡¡¡ÏÂÃæ¾ÍÀ´¾ßÌå˵˵£¬ÈçºÎ½â¾öÉÏÃæµÄÁ½¸öºËÐÄÎÊÌâ¡£
¡¡¡¡3. ÈçºÎ“¼Ó¸ßÁÁ±³¾°”£¿
¡¡¡¡¸ù¾Ý¶¯Í¼ÑÝʾÎÒÃÇ¿ÉÒÔÖªµÀ£¬Óû§Ñ¡Ôñijһ¶ÎÎı¾£¨ÏÂÎijÆΪ“Óû§Ñ¡Çø”£©ºó£¬ÎÒÃÇ»á¸øÕâ¶ÎÎı¾¼ÓÒ»¸ö¸ßÁÁ±³¾°¡£
¡¡¡¡ÀýÈçÓû§Ñ¡ÔñÁËÉÏͼÖеÄÎı¾£¨¼´À¶É«²¿·Ö£©¡£ÎªÆä¼Ó¸ßÁÁµÄ»ù±¾Ë¼Â·ÈçÏ£º
¡¡¡¡»ñÈ¡Ñ¡ÖеÄÎı¾½Úµã£ºÍ¨¹ýÓû§Ñ¡ÔñµÄÇøÓòÐÅÏ¢£¬»ñÈ¡ËùÓб»Ñ¡ÖеÄËùÓÐÎı¾½Úµã£»
¡¡¡¡ÎªÎı¾½ÚµãÌí¼Ó±³¾°É«£º¸øÕâЩÎı¾½Úµã°ü¹üÒ»²ãеÄÔªËØ£¬¸ÃÔªËؾßÓÐÖ¸¶¨µÄ±³¾°ÑÕÉ«¡£
¡¡¡¡3.1. ÈçºÎ»ñÈ¡Ñ¡ÖеÄÎı¾½Úµã£¿
¡¡¡¡1£©Selection API
¡¡¡¡ÐèÒª»ùÓÚä¯ÀÀÆ÷ΪÎÒÃÇÌṩµÄ Selection API ¡£ËüµÄ¼æÈÝÐÔ»¹²»´í¡£Èç¹ûÒªÖ§³Ö¸üµÍ°æ±¾µÄä¯ÀÀÆ÷ÔòÐèÒªÓà polyfill¡£
¡¡¡¡Selection API ¿ÉÒÔ·µ»ØһϵÁйØÓÚÓû§Ñ¡ÇøµÄÐÅÏ¢¡£ÄÇôÊDz»ÊÇ¿ÉÒÔͨ¹ýËüÖ±½Ó»ñÈ¡Ñ¡È¡ÖеÄËùÓÐ DOM ÔªËØÄØ£¿
¡¡¡¡ºÜÒź¶²¢²»ÄÜ¡£µ«ºÃÔÚËü¿ÉÒÔ·µ»ØÑ¡ÇøµÄÊ×β½ÚµãÐÅÏ¢£º
- const range = window.getSelection().getRangeAt(0);
- const start = {
- node: range.startContainer,
- offset: range.startOffset
- };
- const end = {
- node: range.endContainer,
- offset: range.endOffset
- };
¡¡¡¡Range ¶ÔÏó°üº¬ÁËÑ¡ÇøµÄ¿ªÊ¼Óë½áÊøÐÅÏ¢£¬ÆäÖаüÀ¨½Úµã£¨node£©ÓëÎı¾Æ«ÒÆÁ¿£¨offset£©¡£½ÚµãÐÅÏ¢²»Óöà˵£¬ÕâÀï½âÊÍһϠoffset ÊÇָʲô£ºÀýÈ磬±êÇ©
ÕâÊÇÒ»¶ÎÎı¾µÄʾÀý
£¬Óû§Ñ¡È¡µÄ²¿·ÖÊÇ“Ò»¶ÎÎı¾”ÕâËĸö×Ö£¬ÕâʱÊ×βµÄ node ¾ùΪ p ÔªËØÄÚµÄÎı¾½Úµã£¨Text Node£©£¬¶ø startOffset ºÍ endOffset ·Ö±ðΪ 2 ºÍ 6¡£
¡¡¡¡2£©Ê×βÎı¾½Úµã²ð·Ö
¡¡¡¡Àí½âÁË offset µÄ¸ÅÄîºó£¬×ÔÈ»¾Í·¢ÏÖÓиöÎÊÌâÐèÒª½â¾ö¡£ÓÉÓÚÓû§Ñ¡Çø£¨selection£©¿ÉÄÜÖ»°üº¬Ò»¸öÎı¾½ÚµãµÄÒ»²¿·Ö£¨¼´ offset ²»Îª 0£©£¬ËùÒÔÎÒÃÇ×îºóµÃµ½µÄÓû§Ñ¡ÇøËù°üº¬µÄ½ÚµãÀҲֻϣÍûÓÐÊ×βÎı¾½ÚµãµÄÕâ“Ò»²¿·Ö”¡£¶Ô´Ë£¬ÎÒÃÇ¿ÉÒÔʹÓà .splitText() ²ð·ÖÎı¾½Úµã£º
¡¡
- // Ê×½Úµã
- if (curNode === $startNode) {
- if (curNode.nodeType === 3) {
- curNode.splitText(startOffset);
- const node = curNode.nextSibling;
- selectedNodes.push(node);
- }
- }
- // β½Úµã
- if (curNode === $endNode) {
- if (curNode.nodeType === 3) {
- const node = curNode;
- node.splitText(endOffset);
- selectedNodes.push(node);
- }
- }
¡¡¡¡ÒÔÉÏ´úÂë»áÒÀ¾Ý offset ¶ÔÎı¾½Úµã½øÐвð·Ö¡£¶ÔÓÚ¿ªÊ¼½Úµã£¬Ö»ÐèÒªÊÕ¼¯ËüµÄºó°ë²¿·Ö£»¶ø¶ÔÓÚ½áÊø½ÚµãÔòÊÇÇ°°ë²¿·Ö¡£
¡¡¡¡3£©±éÀú DOM Ê÷
¡¡¡¡µ½Ä¿Ç°ÎªÖ¹£¬ÎÒÃÇ׼ȷÕÒµ½ÁËÊ×β½Úµã£¬ËùÒÔÏÂÒ»²½¾ÍÊÇÕÒ³ö“Öмä”ËùÓеÄÎı¾½Úµã¡£Õâ¾ÍÐèÒª±éÀú DOM Ê÷¡£
¡¡¡¡“Öм䔼ÓÉÏÒýºÅÊÇÒòΪ£¬ÔÚÊÓ¾õÉÏÕâЩ½ÚµãÊÇλÓÚÊ×β֮¼äµÄ£¬µ«ÓÉÓÚ DOM ²»ÊÇÏßÐԽṹ¶øÊÇÊ÷Ðνṹ£¬ËùÒÔÕâ¸ö“Öм䔻»³É³ÌÐòÓïÑÔ£¬¾ÍÊÇÖ¸Éî¶ÈÓÅÏȱéÀúʱ£¬Î»ÓÚÊ×βÁ½½ÚµãÖ®¼äµÄËùÓÐÎı¾½Úµã¡£DFS µÄ·½·¨Óкܶ࣬¿ÉÒԵݹ飬Ҳ¿ÉÒÔÓÃÕ»+Ñ»·£¬ÕâÀï¾Í²»×¸ÊöÁË¡£
¡¡¡¡ÐèÒªÌáһϵÄÊÇ£¬ÓÉÓÚÎÒÃÇÊÇҪΪÎı¾½ÚµãÌí¼Ó¸ßÁÁ±³¾°£¬Òò´ËÔÚ±éÀúʱֻ»áÊÕ¼¯Îı¾½Úµã¡£
- if (curNode.nodeType === 3) {
- selectedNodes.push(curNode);
- }
¡¡¡¡3.2. ÈçºÎΪÎı¾½ÚµãÌí¼Ó±³¾°É«£¿
¡¡¡¡ÕâÒ»²½±¾Éí²¢²»À§ÄÑ¡£ÔÚÉÏÒ»²½µÄ»ù´¡ÉÏ£¬ÎÒÃÇÒѾѡ³öÁËËùÓб»Óû§Ñ¡ÖÐµÄ Îı¾½Úµã£¨°üÀ¨²ð·ÖºóµÄÊ×β½Úµã£©¡£¶Ô´Ë£¬Ò»¸ö×îÖ±½ÓµÄ·½·¨¾ÍÊÇΪÆä“°ü¹üÉϔһ¸ö´ø±³¾°ÑùʽµÄÔªËØ¡£
¡¡¡¡¾ßÌåµÄ£¬ÎÒÃÇ¿ÉÒÔ¸øÿ¸öÎı¾½ÚµãÍâ¼ÓÉÏÒ»¸ö class Ϊ highlight µÄ ÔªËØ£»¶ø±³¾°ÑùʽÔòͨ¹ý CSS .highlight Ñ¡ÔñÆ÷ÉèÖá£
- // ʹÓÃÉÏÒ»²½Öзâ×°µÄ·½·¨»ñÈ¡Ñ¡ÇøÄÚµÄÎı¾½Úµã
- const nodes = getSelectedNodes(start, end);
- nodes.forEach(node => {
- const wrap = document.createElement('span');
- wrap.setAttribute('class', 'highlight');
- wrap.appendChild(node.cloneNode(false));
- node.parentNode.replaceChild(wrap);
- });
- .highlight {
- background: #ff9;
- }
¡¡¡¡ÕâÑù¾Í¿ÉÒÔ¸ø±»Ñ¡ÖеÄÎÄ×ÖÌí¼ÓÒ»¸ö“ÓÀ¾Ã”µÄ¸ßÁÁ±³¾°ÁË¡£
¡¡¡¡p.s. Ñ¡ÇøµÄÖغÏÎÊÌâ
¡¡¡¡È»¶ø£¬Îı¾¸ßÁÁÀﻹÓÐÒ»¸ö±È½Ï¼¬ÊÖµÄÐèÇó —— ¸ßÁÁÇøÓòµÄÖغϡ£¾Ù¸öÀý×Ó£¬×ʼµÄÑÝʾͼ£¨ÏÂͼ£©ÀµÚÒ»¸ö¸ßÁÁÇøÓòºÍµÚ¶þ¸ö¸ßÁÁÇøÓòÖ®¼ä´æÔÚÖصþ²¿·Ö£¬¼´“±¾ÇøÓò¸ß”Ëĸö×Ö¡£
¡¡¡¡Õâ¸öÎÊÌâÄ¿Ç°À´¿´Ëƺõ»¹²»ÊÇÎÊÌ⣬µ«ÔÚ½áºÏÏÂÃæÒªÌáµ½µÄһЩ¹¦ÄÜÓëÐèÇóʱ£¬¾Í»á±ä³É·Ç³£Âé·³£¬ÉõÖÁÎÞ·¨Õý³£ÔËÐУ¨Ò»Ð©¿ªÔ´¿âÕâ¿é´¦ÀíÒ²²»¾¡ÈçÈËÒ⣬ÕâÒ²ÊÇûÓÐÑ¡ÔñËüÃǵÄÒ»¸öÔÒò£©¡£ÕâÀï¼òµ¥Ìáһϣ¬¾ßÌåµÄÇé¿öÎÒ»á·Åµ½ºóÐø¶ÔÓ¦µÄµØ·½ÔÙÏêϸ˵¡£
¡¡¡¡4. ÈçºÎʵÏÖ¸ßÁÁÑ¡ÇøµÄ³Ö¾Ã»¯Ó뻹ԣ¿
¡¡¡¡µ½Ä¿Ç°ÎÒÃÇÒѾ¿ÉÒÔ¸øÑ¡ÖеÄÎı¾Ìí¼Ó¸ßÁÁ±³¾°ÁË¡£µ«»¹ÓÐÒ»¸ö´óÎÊÌ⣺
¡¡¡¡ÏëÏóһϣ¬Óû§ÐÁÐÁ¿à¿à»®Á˺ܶàÖص㣨¸ßÁÁ£©£¬¿ªÐĵØÍ˳öÒ³Ãæºó£¬Ï´ηÃÎÊʱ·¢ÏÖÕâЩ¶¼²»Äܱ£´æʱ£¬¸ÃÓжàôµÃ¾ÚÉ¥¡£Òò´Ë£¬Èç¹ûÖ»ÊÇÔÚÒ³ÃæÉÏ×ö“Ò»´ÎÐÔ”µÄÎı¾¸ßÁÁ£¬ÄÇËüµÄʹÓüÛÖµ»á´ó´ó½µµÍ¡£ÕâÒ²¾Í´ÙʹÎÒÃǵē»®´Ê¸ßÁÁ”¹¦ÄÜÒªÄܹ»±£´æ£¨³Ö¾Ã»¯£©ÕâЩ¸ßÁÁÑ¡Çø²¢ÕýÈ·»¹Ô¡£
³Ö¾Ã»¯¸ßÁÁÑ¡ÇøµÄºËÐÄÊÇÕÒµ½Ò»ÖÖºÏÊ浀 DOM ½ÚµãÐòÁл¯·½·¨¡£
¡¡¡¡Í¨¹ýµÚÈý²¿·Ö¿ÉÒÔÖªµÀ£¬µ±È·¶¨ÁËÊ×β½ÚµãÓëÎı¾Æ«ÒÆ£¨offset£©ÐÅÏ¢ºó£¬¼´¿ÉΪÆä¼äÎı¾½ÚµãÌí¼Ó±³¾°É«¡£ÆäÖУ¬offset ÊÇÊýÖµÀàÐÍ£¬ÒªÔÚ·þÎñÆ÷±£´æËü×ÔȻûÓÐÎÊÌ⣻µ«ÊÇ DOM ½Úµã²»Í¬£¬ÔÚä¯ÀÀÆ÷Öб£´æËüÖ»ÐèÒª¸³Öµ¸øÒ»¸ö±äÁ¿£¬µ«ÏëÔÚºó¶Ë±£´æËùνµÄ DOM Ôò²»ÄÇôֱ½ÓÁË¡£
¡¡¡¡4.1 ÐòÁл¯ DOM ½Úµã±êʶ
¡¡¡¡ËùÒÔÕâÀïµÄºËÐĵã¾ÍÊÇÕÒµ½Ò»ÖÖ·½·¨£¬Äܹ»¶¨Î» DOM ½Úµã£¬Í¬Ê±¿ÉÒÔ±»±£´æ³ÉÆÕͨµÄ JSON Object£¬ÓÃÒÔ´«¸øºó¶Ë±£´æ£¬Õâ¸ö¹ý³ÌÔÚ±¾ÎÄÖб»³ÆΪ DOM ±êʶ µÄ“ÐòÁл¯”¡£¶øÏ´ÎÓû§·ÃÎÊʱ£¬ÓÖ¿ÉÒÔ´Óºó¶ËÈ¡»Ø£¬È»ºó“·´ÐòÁл¯”Ϊ¶ÔÓ¦µÄ DOM ½Úµã¡£
¡¡¡¡Óм¸ÖÖ³£¼ûµÄ·½Ê½À´±êʶ DOM ½Úµã£º
¡¡¡¡Ê¹Óà xPath
¡¡¡¡Ê¹Óà CSS Selector Óï·¨
¡¡¡¡Ê¹Óà tagName + index
¡¡¡¡ÕâÀïÑ¡ÔñÁËʹÓõÚÈýÖÖ·½Ê½À´¿ìËÙʵÏÖ¡£ÐèҪעÒâÒ»µã£¬ÎÒÃÇͨ¹ý Selection API È¡µ½µÄÊ×β½ÚµãÒ»°ãÊÇÎı¾½Úµã£¬¶øÕâÀïÒª¼Ç¼µÄ tagName ºÍ index ¶¼ÊǸÃÎı¾½ÚµãµÄ¸¸ÔªËؽڵ㣨Element Node£©µÄ£¬¶ø childIndex ±íʾ¸ÃÎı¾½ÚµãÊÇÆ丸Ç׵ĵڼ¸¸ö¶ù×Ó£º
- function serialize(textNode, root = document) {
- const node = textNode.parentElement;
- let childIndex = -1;
- for (let i = 0; i < node.childNodes.length; i++) {
- if (textNode === node.childNodes[i]) {
- childIndex = i;
- break;
- }
- }
- const tagName = node.tagName;
- const list = root.getElementsByTagName(tagName);
- for (let index = 0; index < list.length; index++) {
- if (node === list[index]) {
- return {tagName, index, childIndex};
- }
- }
- return {tagName, index: -1, childIndex};
- }
¡¡¡¡Í¨¹ý¸Ã·½·¨·µ»ØµÄÐÅÏ¢£¬ÔÙ¼ÓÉÏ offset ÐÅÏ¢£¬¼´¶¨Î»Ñ¡È¡µÄÆðʼλÖã¬Í¬Ê±Ò²ÍêÈ«¿É·¢Ë͸øºó¶Ë½øÐб£´æÁË¡£
¡¡¡¡4.2 ·´ÐòÁл¯ DOM ½Úµã
¡¡¡¡»ùÓÚÉÏÒ»½ÚµÄÐòÁл¯·½·¨£¬´Óºó¶Ë»ñÈ¡µ½Êý¾Ýºó£¬¿ÉÒÔºÜÈÝÒ×·´ÐòÁл¯Îª DOM ½Úµã£º
- function deSerialize(meta, root = document) {
- const {tagName, index, childIndex} = meta;
- const parent = root.getElementsByTagName(tagName)[index];
- return parent.childNodes[childIndex];
- }
¡¡¡¡ÖÁ´Ë£¬ÎÒÃÇ´óÌåÒѾ½â¾öÁËÁ½¸öºËÐÄÎÊÌ⣬ÕâËƺõÒѾÊÇÒ»¸ö¿ÉÓð汾ÁË¡£µ«Æäʵ²»È»£¬¸ù¾Ýʵ¼ù¾Ñ飬Èç¹û½ö½öÊÇÉÏÃæÕâЩ´¦Àí£¬ÍùÍùÊÇÎÞ·¨Ó¦¶Ôʵ¼ÊÐèÇóµÄ£¬´æÔÚһЩ“ÖÂÃüÎÊÌ┡£
¡¡¡¡µ«²»ÓûÒÐÄ£¬ÏÂÃæ»á¾ßÌåÀ´ËµËµËùνµÄ“ÖÂÃüÎÊÌâ”ÊÇʲô£¬¶øÓÖÊÇÈçºÎ½â¾ö²¢ÊµÏÖÒ»¸öÏßÉÏÒµÎñ¿ÉÓõÄͨÓÓ»®´Ê¸ßÁÁ”¹¦Äܵġ£
¡¡¡¡5. ÈçºÎʵÏÖÒ»¸öÉú²ú»·¾³¿ÉÓõē»®´Ê¸ßÁÁ”£¿
¡¡¡¡1£©ÉÏÃæµÄ·½°¸ÓÐʲôÎÊÌ⣿
¡¡¡¡Ê×ÏÈÀ´¿´¿´ÉÏÃæµÄ·½°¸»áÓÐʲôÎÊÌâ¡£
¡¡¡¡µ±ÎÒÃÇÐèÒª¸ßÁÁÎı¾Ê±£¬»áΪÎı¾½Úµã°ü¹üspanÔªËØ£¬Õâ¾Í¸Ä¶¯ÁËÒ³ÃæµÄ DOM ½á¹¹¡£Ëü¿ÉÄܻᵼÖºóÐø¸ßÁÁµÄÊ×β½ÚµãÓëÆä offset ÐÅÏ¢ÆäʵÊÇ»ùÓÚ±»¸Ä¶¯ºóµÄ DOM ½á¹¹µÄ¡£´øÀ´µÄ½á¹ûÓÐÁ½¸ö£º
¡¡¡¡Ï´ηÃÎÊʱ£¬³ÌÐò±ØÐë°´ÉÏ´ÎÓû§¸ßÁÁµÄ˳Ðò»¹Ô¡£
¡¡¡¡Óû§²»ÄÜËæÒâÈ¡Ïû£¨É¾³ý£©¸ßÁÁÇøÓò£¬Ö»ÄÜ°´Ìí¼Ó˳Ðò´ÓºóÍùǰɾ¡£
¡¡¡¡·ñÔò£¬¾Í»áÓв¿·ÖµÄ¸ßÁÁÑ¡ÇøÔÚ»¹ÔʱÎÞ·¨¶¨Î»µ½ÕýÈ·µÄÔªËØ¡£
¡¡¡¡ÎÄ×Ö¿ÉÄܲ»ºÃÀí½â£¬ÏÂÃæÎÒ¾Ù¸öÀý×ÓÀ´Ö±¹Û½âÊÍÏÂÕâ¸öÎÊÌâ¡£
- <p>
- ·Ç³£¸ßÐ˽ñÌìÄܹ»ÔÚÕâÀïºÍ´ó¼Ò·ÖÏíÒ»ÏÂÎı¾¸ßÁÁ£¨ÔÚÏ߱ʼǣ©µÄʵÏÖ·½Ê½¡£
- </p>
¡¡¡¡¶ÔÓÚÉÏÃæÕâ¶Î HTML£¬Óû§·Ö±ð°´Ë³Ðò¸ßÁÁÁËÁ½¸ö²¿·Ö£º“¸ßÐË”ºÍ“Îı¾¸ßÁÁ”¡£ÄÇô°´ÕÕÉÏÃæµÄʵÏÖ·½Ê½£¬Õâ¶Î HTML ±ä³ÉÁËÏÂÃæÕâÑù£º
- <p>
- ·Ç³£
- <span class="highlight">¸ßÐË</span>
- ½ñÌìÄܹ»ÔÚÕâÀïºÍ´ó¼Ò·ÖÏíÒ»ÏÂ
- <span class="highlight">Îı¾¸ßÁÁ</span>
- £¨ÔÚÏ߱ʼǣ©µÄʵÏÖ·½Ê½¡£
- </p>
¡¡¡¡¶ÔÓ¦µÄÁ½¸öÐòÁл¯Êý¾Ý·Ö±ðΪ£º
- // “¸ßÐË”Á½¸ö×Ö±»¸ßÁÁʱ»ñÈ¡µÄÐòÁл¯ÐÅÏ¢
- {
- start: {
- tagName: 'p',
- index: 0,
- childIndex: 0,
- offset: 2
- },
- end: {
- tagName: 'p',
- index: 0,
- childIndex: 0,
- offset: 4
- }
- }
¡¡
- // “Îı¾¸ßÁÁ”Ëĸö×Ö±»¸ßÁÁʱ»ñÈ¡µÄÐòÁл¯ÐÅÏ¢¡£
- // ÕâʱºòÓÉÓÚpÏÂÃæÒѾ´æÔÚÁËÒ»¸ö¸ßÁÁÐÅÏ¢£¨¼´“¸ßÐË”£©¡£
- // ËùÒÔÆäÄÚ²¿ HTML ½á¹¹Òѱ»Ð޸ģ¬Ö±¹ÛÀ´Ëµ¾ÍÊÇ childNodes ¸Ä±äÁË¡£
- // ½ø¶ø£¬childIndexÊôÐÔÓÉÓÚÇ°Ò»¸ö span ÔªËصļÓÈ룬±äΪÁË 2¡£
- {
- start: {
- tagName: 'p',
- index: 0,
- childIndex: 2,
- offset: 14
- },
- end: {
- tagName: 'p',
- index: 0,
- childIndex: 2,
- offset: 18
- }
- }
¡¡¡¡¿ÉÒÔ¿´µ½£¬“Îı¾¸ßÁÁ”ÕâËĸö×ÖµÄÊ×β½ÚµãµÄ childIndex ¶¼±»¼ÇΪ 2£¬ÕâÊÇÓÉÓÚÇ°Ò»¸ö¸ßÁÁÇøÓò¸Ä±äÁË
ÔªËØϵÄDOM½á¹¹¡£Èç¹û´Ëʱ“¸ßÐ˔ѡÇøµÄ¸ßÁÁ±»Óû§È¡Ïû£¬ÄÇôÏ´ÎÔÙ·ÃÎÊÒ³Ãæ¾ÍÎÞ·¨»¹Ô¸ßÁÁÁË —— “¸ßÐ˔ѡÇøµÄ¸ßÁÁ±»È¡ÏûÁË£¬
ÏÂ×ÔÈ»¾Í²»»á³öÏÖµÚÈý¸ö childNode£¬ÄÇô childIndex Ϊ 2 ¾ÍÕÒ²»µ½¶ÔÓ¦µÄ½ÚµãÁË¡£Õâ¾Íµ¼Ö´洢µÄÊý¾ÝÔÚ»¹Ô¸ßÁÁÑ¡Çøʱ³öÏÖÎÊÌâ¡£
¡¡¡¡´ËÍ⣬»¹¼ÇµÃÔÚµÚÈý²¿·ÖĩβÌáµ½µÄ¸ßÁÁÑ¡È¡ÖغÏÎÊÌâô£¿Ö§³ÖÑ¡È¡ÖغϺÜÈÝÒ׳öÏÖÈçϵİü¹üÔªËØǶÌ×Çé¿ö£º
- <p>
- ·Ç³£
- <span class="highlight">¸ßÐË</span>
- ½ñÌìÄܹ»ÔÚÕâÀïºÍ´ó¼Ò·ÖÏíÒ»ÏÂ
- <span class="highlight">
- Îı¾
- <span class="highlight">¸ßÁÁ</span>
- </span>
- £¨ÔÚÏ߱ʼǣ©µÄʵÏÖ·½Ê½¡£
- </p>
¡¡¡¡ÕâҲʹµÃij¸öÎı¾ÇøÓò¾¹ý¶à´Î¸ßÁÁ¡¢È¡Ïû¸ßÁÁºó£¬»á³öÏÖÓëÔ HTML Ò³Ã治ͬµÄ¸´ÔÓǶÌ׽ṹ¡£¿ÉÒÔÔ¤¼û£¬µ±ÎÒÃÇʹÓà xpath »ò CSS selector ×÷Ϊ DOM ±êʶʱ£¬ÉÏÃæÌáµ½µÄÎÊÌâÒ²»á³öÏÖ£¬Í¬Ê±Ò²Ê¹ÆäËûÐèÇóµÄʵÏÖ¸ü¼Ó¸´ÔÓ¡£
¡¡¡¡µ½ÕâÀï¿ÉÒÔÌáÒ»ÏÂÆäËû¿ªÔ´¿â»ò²úÆ·ÊÇÈçºÎ´¦ÀíÑ¡ÇøÖغÏÎÊÌâµÄ£º
¡¡¡¡¿ªÔ´¿â Rangy ÓÐÒ»¸ö Highlighter Ä£¿é¿ÉÒÔʵÏÖÎı¾¸ßÁÁ£¬µ«Æä¶ÔÓÚÑ¡ÇøÖغϵÄÇé¿öÊǽ«Á½¸öÑ¡ÇøÖ±½ÓºÏ²¢ÁË£¬ÕâÊDz»ºÏ·ûÎÒÃÇÒµÎñÐèÇóµÄ¡£
¡¡¡¡¸¶·Ñ²úÆ· Diigo Ö±½Ó²»ÔÊÐíÑ¡ÇøµÄÖغϡ£
¡¡¡¡Medium.com ÊÇÖ§³ÖÑ¡ÇøÖغϵģ¬ÌåÑé·Ç³£²»´í£¬ÕâÒ²ÊÇÎÒÃDzúÆ·µÄÄ¿±ê¡£µ«ËüÒ³ÃæµÄÄÚÈÝÇø½á¹¹Ïà½ÏÎÒÃæ¶ÔµÄÇé¿ö»á¸ü¼òµ¥Óë¸ü¿É¿Ø¡£
¡¡¡¡ËùÒÔÈçºÎ½â¾öÕâЩÎÊÌâÄØ£¿
¡¡¡¡2£©ÁíÒ»ÖÖÐòÁл¯ / ·´ÐòÁл¯·½Ê½
¡¡¡¡ÎÒ»á¶ÔµÚËIJ¿·ÖÌáµ½µÄÐòÁл¯·½Ê½½øÐиĽø¡£ÈÔÈ»¼Ç¼Îı¾½ÚµãµÄ¸¸½Úµã tagName Óë index£¬µ«²»ÔټǼÎı¾½ÚµãÔÚ childNodes ÖÐµÄ index Óë offset£¬¶øÊǼǼ¿ªÊ¼£¨½áÊø£©Î»ÖÃÔÚÕû¸ö¸¸ÔªËؽڵãÖеÄÎı¾Æ«ÒÆÁ¿¡£
¡¡¡¡ÀýÈçÏÂÃæÕâ¶Î HTML£º
- <p>
- ·Ç³£
- <span class="highlight">¸ßÐË</span>
- ½ñÌìÄܹ»ÔÚÕâÀïºÍ´ó¼Ò·ÖÏíÒ»ÏÂ
- <span class="highlight">Îı¾¸ßÁÁ</span>
- £¨ÔÚÏ߱ʼǣ©µÄʵÏÖ·½Ê½¡£
- </p>
¡¡¡¡¶ÔÓÚ“Îı¾¸ßÁÁ”Õâ¸ö¸ßÁÁÑ¡Çø£¬Ö®Ç°ÓÃÓÚ±êʶÎı¾ÆðʼλÖõÄÐÅϢΪchildIndex = 2, offset = 14¡£¶øÏÖÔÚ±äΪoffset = 18£¨´Ó
ÔªËØϵÚÒ»¸öÎı¾“·Ç”¿ªÊ¼¼ÆË㣬¾¹ý18¸ö×Ö·ûºóÊÇ“ÎÄ”£©¡£¿ÉÒÔ¿´³ö£¬ÕâÑù±íʾµÄÓŵãÊÇ£¬²»¹Ü
ÄÚ²¿ÔÓеÄÎı¾½Úµã±»£¨°ü¹ü£©½ÚµãÈçºÎ·Ö¸î£¬¶¼²»»áÓ°Ïì¸ßÁÁÑ¡Çø»¹ÔʱµÄ½Úµã¶¨Î»¡£
¡¡¡¡¾Ý´Ë£¬ÔÚÐòÁл¯Ê±£¬ÎÒÃÇÐèÒªÒ»¸ö·½·¨À´½«Îı¾½ÚµãÄÚÆ«ÒÆÁ¿“·Òë”ΪÆä¶ÔÓ¦µÄ¸¸½ÚµãÄÚ²¿µÄ×ÜÌåÎı¾Æ«ÒÆÁ¿£º
- function getTextPreOffset(root, text) {
- const nodeStack = [root];
- let curNode = null;
- let offset = 0;
- while (curNode = nodeStack.pop()) {
- const children = curNode.childNodes;
- for (let i = children.length - 1; i >= 0; i--) {
- nodeStack.push(children[i]);
- }
- if (curNode.nodeType === 3 && curNode !== text) {
- offset += curNode.textContent.length;
- }
- else if (curNode.nodeType === 3) {
- break;
- }
- }
- return offset;
- }
¡¡¡¡¶ø»¹Ô¸ßÁÁÑ¡Çøʱ£¬ÐèÒªÒ»¸ö¶ÔÓ¦µÄÄæ¹ý³Ì£º
- function getTextChildByOffset(parent, offset) {
- const nodeStack = [parent];
- let curNode = null;
- let curOffset = 0;
- let startOffset = 0;
- while (curNode = nodeStack.pop()) {
- const children = curNode.childNodes;
- for (let i = children.length - 1; i >= 0; i--) {
- nodeStack.push(children[i]);
- }
- if (curNode.nodeType === 3) {
- startOffset = offset - curOffset;
- curOffset += curNode.textContent.length;
- if (curOffset >= offset) {
- break;
- }
- }
- }
- if (!curNode) {
- curNode = parent;
- }
- return {node: curNode, offset: startOffset};
- }
¡¡¡¡3£©Ö§³Ö¸ßÁÁÑ¡ÇøµÄÖغÏ
¡¡¡¡ÖغϵĸßÁÁÑ¡Çø´øÀ´µÄÒ»¸öÎÊÌâ¾ÍÊǸßÁÁ°ü¹üÔªËصÄǶÌ×£¬´Ó¶øʹµÃ DOM ½á¹¹»áÓнϸ´Ôӵı䶯£¬Ôö¼ÓÁËÆäËû¹¦ÄÜ£¨½»»¥£©ÊµÏÖÓëÎÊÌâÅŲéµÄ¸´ÔӶȡ£Òò´Ë£¬ÎÒÔÚ 3.2. ½ÚÌáµ½µÄ°ü¹ü¸ßÁÁÔªËØʱ£¬»áÔÙ½øÐÐһЩÉÔ¸´ÔӵĴ¦Àí£¨ÓÈÆäÊÇÖغÏÑ¡Çø£©£¬ÒÔ±£Ö¤¾¡Á¿¸´ÓÃÒÑÓеİü¹üÔªËØ£¬±ÜÃâÔªËصÄǶÌס£
¡¡¡¡ÔÚ´¦Àíʱ£¬½«ÐèÒª°ü¹üµÄ¸÷¸öÎı¾Æ¬¶Î£¨Text Node£©·ÖΪÈýÀàÇé¿ö£º
¡¡¡¡Íêȫδ±»°ü¹ü£¬ÔòÖ±½Ó°ü¹ü¸Ã²¿·Ö¡£
¡¡¡¡ÊôÓÚ±»°ü¹ü¹ýµÄÎı¾½ÚµãµÄÒ»²¿·Ö£¬ÔòʹÓÃ.splitText()½«Æä²ð·Ö¡£
¡¡¡¡ÊÇÒ»¶ÎÍêÈ«±»°ü¹üµÄÎı¾¶Î£¬²»ÐèÒª¶Ô½Úµã½øÐд¦Àí¡£
¡¡¡¡ÓÚ´Ëͬʱ£¬ÎªÃ¿¸öÑ¡ÇøÉú³ÉΨһ ID£¬½«¸Ã¶ÎÎı¾¼¸µã¶à¶ÔÓ¦µÄ ID¡¢ÒÔ¼°ÆäÓÉÓÚÑ¡ÇøÖغÏËùÉæ¼°µ½µÄÆäËû ID£¬¶¼¸½¼Ó°ü¹üÔªËØÉÏ¡£Òò´ËÏñÉÏÃæµÄµÚÈýÖÖÇé¿ö£¬²»ÐèÒª±ä¸ü DOM ½á¹¹£¬Ö»Óøüаü¹üÔªËØÁ½Àà ID Ëù¶ÔÓ¦µÄ dataset ÊôÐÔ¼´¿É¡£
¡¡¡¡6. ÆäËûÎÊÌâ
¡¡¡¡½â¾öÒÔÉϵÄһЩÎÊÌâºó£¬“Îı¾»®´Ê¸ßÁÁ”¾Í»ù±¾¿ÉÓÃÁË¡£»¹Ê£ÏÂһЩ“СÐÞ²¹”£¬¼òµ¥Ìáһϡ£
¡¡¡¡6.1. ¸ßÁÁÑ¡ÇøµÄ½»»¥Ê¼þ£¬ÀýÈç click¡¢hover
¡¡¡¡Ê×ÏÈ£¬¿ÉÒÔΪÿ¸ö¸ßÁÁÑ¡ÇøÉú³ÉÒ»¸öΨһ ID£¬È»ºóÔÚ¸ÃÑ¡ÇøÄÚËùÓеİü¹üÔªËØÉϼǼ¸Ã ID ÐÅÏ¢£¬ÀýÈçÓÃdata-highlight-idÊôÐÔ¡£¶ø¶ÔÓÚÑ¡È¡ÖغϵIJ¿·Ö¿ÉÒÔÔÚdata-highlight-extra-idÊôÐÔÖмǼÖغϵÄÆäËûÑ¡ÇøµÄ ID¡£
¡¡¡¡¶ø¼àÌýµ½°ü¹üÔªËØµÄ click¡¢hover ºó£¬Ôò´¥·¢ highlighter µÄÏàӦʼþ£¬²¢´øÉϸßÁÁ ID¡£
¡¡¡¡6.2. È¡Ïû¸ßÁÁ£¨¸ßÁÁ±³¾°µÄɾ³ý£©
¡¡¡¡ÓÉÓÚÔÚ°ü¹üʱ֧³ÖÑ¡ÇøÖغϣ¨¶ÔÓ¦»áÓÐÉÏÃæÌáµ½µÄÈýÖÖÇé¿öÐèÒª´¦Àí£©£¬Òò´Ë£¬ÔÚɾ³ýÑ¡È¡¸ßÁÁʱ£¬Ò²»áÓÐÈýÖÖÇé¿öÐèÒª·Ö±ð´¦Àí£º
¡¡¡¡Ö±½Óɾ³ý°ü¹üÔªËØ¡£¼´²»´æÔÚÑ¡ÇøÖغϡ£
¡¡¡¡¸üÐÂdata-highlight-idÊôÐÔºÍdata-highlight-extra-idÊôÐÔ¡£¼´É¾³ýµÄ¸ßÁÁ ID Óë data-highlight-id Ïàͬ¡£
¡¡¡¡Ö»¸üÐÂdata-highlight-extra-idÊôÐÔ¡£¼´É¾³ýµÄ¸ßÁÁ ID Ö»ÔÚ data-highlight-extra-idÖС£
¡¡¡¡6.3. ¶ÔÓÚÇ°¶ËÉú³ÉµÄ¶¯Ì¬Ò³ÃæÔõô°ì£¿
¡¡¡¡²»ÄÑ·¢ÏÖ£¬ÕâÖÖ·ÇñîºÏµÄÎı¾¸ßÁÁ¹¦ÄܺÜÒÀÀµÓÚÒ³ÃæµÄ DOM ½á¹¹£¬ÐèÒª±£Ö¤×ö¸ßÁÁʱµÄ DOM ½á¹¹ºÍ»¹ÔʱµÄÒ»Ö£¬·ñÔòÎÞ·¨ÕýÈ·»¹Ô³öÑ¡ÇøµÄÆðʼ½ÚµãλÖ᣾ݴˣ¬¶Ô“»®´Ê”¸ßÁÁ×îÓѺõÄÓ¦¸ÃÊÇ´¿ºó¶ËäÖȾµÄÒ³Ã棬ÔÚonload¼àÌýÖд¥·¢¸ßÁÁÑ¡Çø»¹ÔµÄ·½·¨¼´¿É¡£µ«Ä¿Ç°Ô½À´Ô½¶àµÄÒ³Ã棨»òÒ³ÃæµÄÒ»²¿·Ö£©ÊÇÇ°¶Ë¶¯Ì¬Éú³ÉµÄ£¬Õë¶ÔÕâ¸öÎÊÌâ¸ÃÔõô´¦ÀíÄØ£¿
¡¡¡¡ÎÒÔÚʵ¼Ê¹¤×÷ÖÐÒ²Óöµ½ÁËÀàËÆÎÊÌâ —— Ò³ÃæµÄºÜ¶àÇøÓòÊÇ ajax ÇëÇóºóÇ°¶ËäÖȾµÄ¡£ÎҵĴ¦Àí·½Ê½°üÀ¨ÈçÏ£º
¡¡¡¡¸ôÀë±ä»¯·¶Î§¡£½«ÉÏÊö´úÂëÖеē¸ù½Úµã”´ÓdocumentElement»»ÎªÁíÒ»¸ö¸ü¾ßÌåµÄÈÝÆ÷ÔªËØ¡£ÀýÈçÎÒÃæ¶ÔµÄÒµÎñ»áÔÚ id Ϊ article-container µÄ
ÄÚ¼ÓÔض¯Ì¬ÄÚÈÝ£¬ÄÇôÎҾͻáÖ¸¶¨Õâ¸ö article-container Ϊ“¸ù½Úµã”¡£ÕâÑù¿ÉÒÔ×î´ó³Ì¶È·ÀÖ¹ÍⲿµÄ DOM ±ä¶¯Ó°Ïìµ½¸ßÁÁλÖõĶ¨Î»£¬ÓÈÆäÊÇÒ³Ãæ¸Ä°æ¡£
¡¡¡¡È·¶¨¸ßÁÁÑ¡ÇøµÄ»¹Ôʱ»ú¡£ÓÉÓÚÄÚÈÝ¿ÉÄÜÊǶ¯Ì¬Éú³É£¬ËùÒÔÐèÒªµÈµ½¸Ã²¿·ÖµÄ DOM äÖȾÍê³ÉºóÔÙµ÷Óû¹Ô·½·¨¡£Èç¹ûÓб©Â¶µÄ¼àÌýʼþ¿ÉÒÔÔÚ¼àÌýÄÚ´¦Àí£»»òÕßͨ¹ý MutationObserver ¼àÌý±êÖ¾ÐÔÔªËØÀ´Åжϸò¿·ÖÊÇ·ñ¼ÓÔØÍê³É¡£
¡¡¡¡¼Ç¼ҵÎñÄÚÈÝÐÅÏ¢£¬Ó¦¶ÔÄÚÈÝÇø¸Ä°æ¡£ÄÚÈÝÇøµÄ DOM ½á¹¹¸ü¸ÄËãÊÇ“»ÙÃðÐÔ´ò»÷”¡£ÈçºÎȷʵÓиÃÀàÇé¿ö£¬¿ÉÒÔ³¢ÊÔÈÃÒµÎñÄÚÈÝչʾ·½½«¶ÎÂäÐÅÏ¢µÈ¾ßÌåµÄÄÚÈÝÐÅÏ¢°ó¶¨ÔÚ DOM ÔªËØÉÏ£¬¶øÎÒÔÚ¸ßÁÁʱȡ³öÕâЩÐÅÏ¢À´ÈßÓà´æ´¢£¬¸Ä°æºó¿ÉÒÔͨ¹ýÕâЩÄÚÈÝÐÅÏ¢“Ë¢”Ò»±é´æ´¢µÄÊý¾Ý¡£
¡¡¡¡6.4. ÆäËû
¡¡¡¡Æª·ùÎÊÌ⣬»¹ÓÐÆäËûϸ½ÚµÄÎÊÌâ¾Í²»ÔÚÕâƪÎÄÕÂÀï·ÖÏíÁË¡£ÏêϸÄÚÈÝ¿ÉÒԲο¼ web-highlighter Õâ¸ö²Ö¿âÀïµÄʵÏÖ¡£
¡¡¡¡7. ×ܽá
¡¡¡¡±¾ÎÄÏÈ´Ó“»®´Ê¸ßÁÁ”¹¦ÄܵÄÁ½¸öºËÐÄÎÊÌ⣨ÈçºÎ¸ßÁÁÓû§Ñ¡ÇøµÄÎı¾¡¢ÈçºÎ½«¸ßÁÁÑ¡Çø»¹Ô£©ÇÐÈ룬»ùÓÚ Selection API¡¢Éî¶ÈÓÅÏȱéÀúºÍ DOM ½Úµã±êʶµÄÐòÁл¯ÕâЩÊÖ¶ÎʵÏÖÁË“»®´Ê¸ßÁÁ”µÄºËÐŦÄÜ¡£È»¶ø£¬¸Ã·½°¸ÈÔÈ»´æÔÚһЩʵ¼ÊÎÊÌ⣬Òò´ËÔÚµÚ 5 ²¿·Ö½øÒ»²½¸ø³öÁËÏàÓ¦µÄ½â¾ö·½°¸¡£
¡¡¡¡»ùÓÚʵ¼Ê¿ª·¢µÄ¾Ñ飬ÎÒ·¢ÏÖ½â¾öÉÏÊö¼¸¸ö“»®´Ê¸ßÁÁ”ºËÐÄÎÊÌâµÄ´úÂë¾ßÓÐÒ»¶¨Í¨ÓÃÐÔ£¬Òò´Ë°ÑºËÐIJ¿·ÖµÄÔ´Âë·â×°³ÉÁ˶ÀÁ¢µÄ¿â web-highlighter£¬ÍйÜÔÚ github£¬Ò²¿ÉÒÔͨ¹ý npm °²×°¡£
ÆäÒÑ·þÎñÓÚÏßÉϲúÆ·ÒµÎñ£¬»ù±¾µÄ¸ßÁÁ¹¦ÄÜÒ»ÐдúÂë¼´¿É¿ªÆô£º
- (new Highlighter()).run();
¡¡¡¡¼æÈÝIE 10/11¡¢Edge¡¢Firefox 52+¡¢Chrome 15+¡¢Safari 5.1+¡¢Opera 15+¡£
תÔØÇë×¢Ã÷£º ÎÄÕÂתÔØ×Ô£º°®Ë¼×ÊÔ´Íø http://www.aseoe.com/show-12-1126-1.html