prototype.js突出显示单词。 DOM正确有效地遍历

时间:2009-10-30 15:12:02

标签: javascript html prototypejs highlight

我希望在加载页面后突出显示HTML页面中的特定单词。我不想使用哑巴:

document.innerHTML = document.innerHTML.replace(.....);

我想遍历每个DOM节点,找出包含文本的节点并修改那些单独节点的innerHTML。这就是我想出的:

function highlightSearchTerms(sword) {
$$('body').map(Element.extend).first().descendants().each(function (el) {
    if (el.nodeType == Node.ELEMENT_NODE && el.tagName != 'TD') {
        //$A(el.childNodes).each(function (onlyChild) {
            //if (onlyChild.nodeType == Node.TEXT_NODE) {
                //console.log(onlyChild);
                el.innerHTML = el.innerHTML.replace(new RegExp('('+sword+')', 'gi'), '<span class="highlight">$1</span>');
            //}
        //});
    }
});
//document.body.innerHTML.replace(new RegExp('('+sword+')', 'gi'), '<span class="highlight">$1</span>');
}

它现在正常工作,但它非常低效,并且几乎不比上面的单行更好,因为它可能会在同一文本上多次替换。 (嗯......,还是不?)

如果您取消注释评论的内容并将el.innerHTML.replace更改为onlyChild.textContent.replace,它几​​乎可以像它需要的那样工作,但修改textContent不会创建新的span作为元素,而是添加HTML内容为文本。

我的问题/要求是找到一种方法,它突出显示文档中逐字遍历的单词。

5 个答案:

答案 0 :(得分:1)

这很快就干净了:

function highlightSearchTerms(sword) {
$$('body').map(Element.extend).first().descendants().each(function (el) {
    if (el.nodeType == Node.ELEMENT_NODE && el.tagName != 'TEXTAREA' && el.tagName != 'INPUT' && el.tagName != 'SCRIPT') {
        $A(el.childNodes).each(function (onlyChild) {
            var pos = onlyChild.textContent.indexOf(sword);
            if (onlyChild.nodeType == Node.TEXT_NODE && pos >= 0) {
                //console.log(onlyChild);
                var spannode = document.createElement('span');
                spannode.className = 'highlight';
                var middlebit = onlyChild.splitText(pos);
                var endbit = middlebit.splitText(sword.length);
                var middleclone = middlebit.cloneNode(true);
                spannode.appendChild(middleclone);
                middlebit.parentNode.replaceChild(spannode, middlebit);

                //onlyChild. = el.innerHTML.replace(new RegExp('('+sword+')', 'gi'), '<span class="highlight">$1</span>');
            }
        });
    }
});
}

但我很难理解它究竟是如何运作的。这似乎是神奇的界限:

middlebit.parentNode.replaceChild(spannode, middlebit);

答案 1 :(得分:1)

前一段时间我将一个从jQuery转换为PrototypeJS:

Element.addMethods({
  highlight: function(element, term, className) {
    function innerHighlight(element, term, className) {
      className = className || 'highlight';
      term = (term || '').toUpperCase();

      var skip = 0;
      if ($(element).nodeType == 3) {
        var pos = element.data.toUpperCase().indexOf(term);
        if (pos >= 0) {
          var middlebit = element.splitText(pos),
              endbit = middlebit.splitText(term.length),
              middleclone = middlebit.cloneNode(true),
              spannode = document.createElement('span');

          spannode.className = 'highlight';
          spannode.appendChild(middleclone);
          middlebit.parentNode.replaceChild(spannode, middlebit);
          skip = 1;
        }
      }
      else if (element.nodeType == 1 && element.childNodes && !/(script|style)/i.test(element.tagName)) {
        for (var i = 0; i < element.childNodes.length; ++i)
          i += innerHighlight(element.childNodes[i], term);
      }
      return skip;
    }
    innerHighlight(element, term, className);
    return element;
  },
  removeHighlight: function(element, term, className) {
    className = className || 'highlight';
    $(element).select("span."+className).each(function(e) {
      e.parentNode.replaceChild(e.firstChild, e);
    });
    return element;
  }
});

您可以在每个元素上使用它:

$("someElementId").highlight("foo", "bar");

,并使用您选择的className。您也可以删除突出显示。

答案 2 :(得分:1)

如果您使用Fabien发布的原型版,请务必添加className 作为innerHighlight调用的参数:

i += innerHighlight(element.childNodes[i], term)

需要

i += innerHighlight(element.childNodes[i], term, className)

如果您关心高光的自定义classNames。

答案 3 :(得分:0)

抓取$(document.body)并进行搜索/替换并在术语周围换行,然后一次性交换整个$(document.body)。将它视为一个大字符串,忘记DOM。这样您只需更新DOM一次。它应该很快。

答案 4 :(得分:0)

我找到了一个可以做你想要的脚本(看起来非常快),它并不特定于任何库,所以你可能想要修改它:

http://www.nsftools.com/misc/SearchAndHighlight.htm

您在上面提供的方法(虽然已注释掉)在替换可能位于html元素中的项目时会遇到问题。即“搜索和替换可能会突出”“事物”,而这不是你想要的。

这是一个基于Jquery的高亮剧本:

http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html

看起来难以转换为原型。