【问题标题】:Highlight each word on a webpage, one at a time, with JavaScript使用 JavaScript 一次一个地突出显示网页上的每个单词
【发布时间】:2011-03-25 19:28:41
【问题描述】:

在视觉上突出显示页面上每个单词的最佳方式是什么,一次一个?我认为应该将单词分解成一个数组并以这种方式进行迭代,但是最好的方法是什么?

我已经知道如何执行字符串替换和设置单个元素的样式,诀窍是在页面上的每个单词上执行此操作,一次一个,以最有效的方式。

【问题讨论】:

    标签: javascript html string highlighting


    【解决方案1】:

    这是我的工作但未优化代码,它实现了一次突出显示每个单词以及在到达每行中的最后一个单词时滚动:

        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
        <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
        <title></title>
        <style type="text/css">
        span.highlight {background-color:red;}
        </style>
        <script>
        var height;
        var width;
        var spans = document.getElementsByTagName("span");
        var i = 0;
        var timePerChar = 100;
    
        function getPositionOfElement(el) {
            var elw =  el.offsetWidth;
            var elh =  el.offsetHeight;
            // yay readability
            for (var lx=0, ly=0;
                 el != null;
                 lx += el.offsetLeft, ly += el.offsetTop, el = el.offsetParent);
            return {x: lx,y: ly,w: elw, h: elh};
        }
    
        function highlightElements() {
            //alert(spans[i].innerHTML.length);
            var highlightSpeed = timePerChar * spans[i].innerHTML.length;
            spans[i].setAttribute("class", "highlight");
            var objInfo = new Object();
            var nxtObjInfo = new Object();
            objInfo = getPositionOfElement(spans[i]);
            nxtObjInfo = getPositionOfElement(spans[i+1]);
            var amt = (objInfo.x + objInfo.w + 50);
            console.log(amt);
            console.log(width);
            if(amt >= width && objInfo.x > nxtObjInfo.x){
                console.log('SCROLL ' +objInfo.h+ ' ');
                window.scrollBy(0,objInfo.h);
            }
            setTimeout('unHighlight()', highlightSpeed);
        }
    
        function unHighlight (){
            spans[i].removeAttribute("class");
            i++;
            if(i < spans.length) {
                highlightElements();
            }
        }
    
        // This is just a namespace 
        var CIRRO = function(){ 
         return { 
          /** 
           * Initialize the page behaviors 
           */ 
          init : function() { 
           CIRRO.wrapWordsWithSpan(); 
          },   
          /** 
           * Replace the contents of each paragraph with span wrapped words 
           */ 
          wrapWordsWithSpan : function() { 
           var paragraphs = document.getElementsByTagName("p");
           //alert(paragraphs.length);
           if(!paragraphs ) return; 
           var j = 0;
           while(j < paragraphs.length) {
                // Parse the text into an array 
               var arr = paragraphs[j].innerHTML.split(" "); 
               // Generate span's for each item/word in the array 
               for( var i = 0; i < arr.length; i++ ) { 
                arr[i] = "<span>" + arr[i] + "</span>"; 
               }    
               paragraphs[j].innerHTML = arr.join(" "); 
               //alert(paragraphs[j].innerHTML); 
               j++
           }
          } 
         }; 
        }(); 
        window.onload = CIRRO.init; 
        </script>
        </head>
        <body id="body">
        <input type="button" onclick="highlightElements();" value="Get selected elements" />
        <p>Test test test test test Test test test test test Test test test test test Test 
    test test test test Test test test test test Test test test test test Test test test test 
    test Test test test test test Test test test test test Test test test test test Test test 
    test test test Test test test test test Test test test test test Test test test test test 
    Test test test test test Test test test test test Test test test test test Test test test 
    test test</p>
        <script>
        var test = document.getElementById("body");
        height = (test.clientHeight + 1);
        width = (test.clientWidth + 1);
        //alert(width +' '+ height);
        </script>
        </body>
    
    </html>
    

    【讨论】:

    • 解决方案很好,只是代替``` var arr = paragraphs[j].innerHTML.split(" "); ``` 应​​该是 `` var arr = paragraphs[j].textContent.split(" "); ``` 因为 'p' 标签内可以有其他标签。
    【解决方案2】:

    这实际上有点取决于文本。如果您在要替换的区域内有标签,我不怀疑innerHTML 上的正则表达式替换将无法正常工作。

    类似这样的:

    &lt;p&gt;&lt;strong&gt;F&lt;/strong&gt;irst letter of paragraph&lt;/p&gt;

    另一种方法是遍历 DOM 中的文本节点。如果您的目标不是 IE,则可以使用TreeWalker 轻松获取按文档顺序排列的文本节点集合。如果需要针对IE,这似乎是other ways to iterate text nodes的一个很好的总结

    然后想法是遍历文本节点,对节点数据进行正则表达式拆分,并将每个子节点包装在一个带背景的跨度中以突出显示。

    这是一个写得很仓促的例子,但它应该给你一个想法。

    var iterator = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false),
     template = document.createElement('span'),
     span,
     node,
     text,
     newNode;
    
    template.style.backgroundColor = 'yellow';
    
    while ((node = iterator.nextNode())) {
     text = node.data.split(/\b/g);
    
     for (var i = 0, len = text.length; i < len; i++) {
      newNode = document.createTextNode(text[i]);
      if (text[i].search(/\w+/) >= 0) {
       span = template.cloneNode(false);
       span.appendChild(newNode);
       node.parentNode.insertBefore(span, node);
      } else {
       node.parentNode.insertBefore(newNode, node);
      }
      iterator.currentNode = newNode;
     }
     node.parentNode.removeChild(node);
    }

    这不是最快的可用方法,但它应该比在 innerHTML 上的正则表达式替换更准确。修改循环以使用 window.setTimeout 为突出显示设置动画也不是那么困难。

    【讨论】:

      【解决方案3】:

      这很简单。

      <script type="text/javascript">
      var str="ppshein is coldfusion developer.!";
      document.write(str.replace("coldfusion", "<span style='background:orange;'>coldfusion8</span>"));
      </script> 
      

      【讨论】:

      • 该答案仅解决了问题的一小部分。我已经知道如何在 DOM 上执行字符串替换。
      【解决方案4】:

      您将需要获取某些内容的 innerHTML,然后将其拆分为空间,然后使用不同的类围绕每个单词包裹一个跨度,并将其设置回文本的位置。

      使用 css 为这些着色或其他颜色。

      我不确定您打算如何“一次一个”地突出显示它们。是否涉及动画或其他内容?

      【讨论】:

      • @Andy E,您的“相关示例”可能会让我到达那里,我正在尝试。 @mkoryak,是的,涉及动画。你的答案是我脑子里想的那种东西,但我一直在寻找最好的方法。
      • @Cirro:希望你觉得它有用,它只是作为一个例子。如果您遇到任何我可以提供帮助的问题,请发表评论。
      • 事实证明这个例子不起作用,因为它没有考虑到文本中的 HTML 标签
      • @Cirrostratus:是的,这是一个很大的缺点,但解决它会非常复杂,花费的时间比我回答关于 SO 的问题的时间要多 :-) 回复:选择一整行,它是很难准确地知道一行在文本中的什么位置结束,而新的一行从换行开始。您应该查看我的另一个答案 - here - 它显示了“突出显示”单行文本的 sneaky 方法。
      猜你喜欢
      • 1970-01-01
      • 2010-09-12
      • 2014-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多