在html文档中标记文本

时间:2016-01-29 11:18:40

标签: highlight highlighting

假设我有以下标记:

<html>
    <head>
        <title>Page Title</title>
    </head>
    <body>
        <h1>Some title</h1>
        <p>First paragraph</p>
        <p>Second paragraph</p>
    </body>
<html>

我需要标记文本的某些部分,即“第一段secon” 它看起来像这样:

<html>
    <head>
        <title>Page Title</title>
    </head>
    <body>
        <h1>Some title</h1>
        <p>F
            <mark>
                irst paragraph</p><p>Secon
            </mark>
        d paragraph</p>
    </body>
<html>

但问题是html标记会被破坏。标记越复杂,这种方法就会遇到越多的问题。

问题:

寻找关于如何获取第一个HTML示例并应用函数来返回html结构的想法,其中“irst paragraph second”以某种方式被特别标记。

我目前拥有的是:

  • 字符串“First paragraph”的父容器
  • 文字“第一段第二”
  • “第一段”中文字“irst”的偏移量

2 个答案:

答案 0 :(得分:4)

如果您想突出显示文档中的文字,那么此插件对您有所帮助。

https://github.com/julmot/jquery.mark

示例小提琴:https://jsfiddle.net/julmot/vpav6tL1/

用法很简单:

$(".context").mark("keyword");

答案 1 :(得分:0)

原则上你必须:

  • 将文件拆分为文字
  • 通过父元素
  • 标识第一个单词
  • 跳过偏移
  • 标记匹配单词

在单词级别进行更改将阻止您破坏标记。 我在下面添加了一个工作示例。但是我不确定它是否适用于所有浏览器。

示例中没有使用mergeWords等一些函数,但我将它们包括在内,因为它们可以证明是有用的。

var splittedToWords = false;

function ignore(el) {
  return (el.nodeType == 8) || 
    (el.tagName == "BLOCKQUOTE") ||
    (el.tagName == "SCRIPT") ||
    (el.tagName == "DIV") ||
    (!el.hasChildNodes() && el.textContent.match(/\S+/) == null);
}

function splitToWords(el) {
  if (el.hasChildNodes()){
    var count = el.childNodes.length;
    for (var i = count - 1; i >= 0; i--) {
      var node = el.childNodes[i];
      if (!ignore(node))
        splitToWords(node);
    }
  }
  else {	//text node
    var words = el.textContent.match(/(\S+\s*)/g) || [];
    var count = words.length;
    var parentNode = el.parentNode;
    for (var i = 0; i < count; i++) {
      var wordNode = document.createElement("span");
      wordNode.className = "word";
      wordNode.innerText = words[i];

      wordNode.setAttribute["word-index"] = i;

      parentNode.insertBefore(wordNode, el);
    }
    parentNode.removeChild(el);
  }
  splittedToWords = true;
}

function unwrap(element) {
  var next = element.nextSibling;
  var parent = element.parentNode;
  parent.removeChild(element);
  var current;
  var frag = document.createDocumentFragment();
  do {
    current = element.nextSibling;
    frag.insertBefore(element, null);
  } while ((element = current));
  parent.insertBefore(frag, next);
}

function mergeWords(el) {
  var words = document.getElementsByClassName("word");
  count = words.length;
  if (count > 0)
    for (var i = 0; i < count; i++)
      uwrap(words[i]);
}

function markWord(el, pos, len) {
  var text = el.innerText;
  var pre = text.substr(0, pos);
  var mark = '<mark>' + text.substr(pos, len) + '</mark>';
  var post = text.substring(pos + len, text.length);
  el.innerHTML = pre + mark + post;
}

function mark(element, offset, text) {
  if (!splittedToWords) {
    var body = document.body;
    splitToWords(body);
  }

  var words = document.getElementsByClassName("word");
  var wordsCount = words.length;
  var first = null;
  for (var i = 0; i < wordsCount; i++ ) {
    if (words[i].parentElement == element) {
      first = i;
      break;
    }
  }

  done = false;
  var i = first;
  var pos = 0;

  do {
    var word = words[i];
    var wordLength = word.innerText.length;

    if (offset > pos + wordLength) {
      i++;
      pos += wordLength;
      continue;
    }
    else {
      done = true;
    }
  } while (!done);

  var tWords = text.match(/(\S+\s*)/g) || [];
  var tWordsCount = tWords.length;
  if (tWordsCount == 0)
    return;

  for (var ti = 0; ti < tWordsCount; ti++) {
    var wordEl = words[i++];
    var word = wordEl.innerText;
    var tWord = tWords[ti].trim();
    var pos = word.indexOf(tWord);

    if (pos == -1)
      continue;	//or maybe return.

    markWord(wordEl, pos, tWord.length);
  }

}
var e = document.getElementById("e");

//do the magic
mark(e, 1, 'irst paragraph Second');
<h1>Some title</h1>
<p id="e">First paragraph</p>
<p>Second paragraph</p>