1

我想在页面加载后突出显示我的 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.replaceonlyChild.textContent.replace它将几乎像它需要的那样工作,但修改 textContent 不会创建一个新的跨度作为元素,而是将 HTML 内容添加为文本。

我的问题/要求是找到一种方法来逐个突出显示文档中遍历元素的单词。

4

5 回答 5

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);
于 2009-10-30T15:53:27.783 回答
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");

,并使用您选择的类名。您还可以删除高光。

于 2009-10-30T16:07:20.563 回答
1

如果您使用的是 Fabien 发布的原型版本,请确保将 className 作为参数添加到 innerHighlight 的调用中:

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

需要是

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

如果您关心您的亮点的自定义类名。

于 2010-03-03T17:12:03.450 回答
0

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

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

您在上面提供的方法(尽管已被注释掉)在替换可能位于 html 元素内的项目时会出现问题。即`搜索和替换可能会“突出显示”“事物”,而这不是您想要的。

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

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

它看起来很难转换为原型。

于 2009-10-30T15:43:29.440 回答
0

抓取 $(document.body) 并进行搜索/替换并围绕该术语包装一个跨度,然后一次性交换整个 $(document.body)。把它当作一个大字符串,忘记 DOM。这样,您只需更新 DOM 一次。它应该非常快。

于 2009-10-30T15:27:10.207 回答