在html内容之间插入标记

时间:2016-12-30 19:25:40

标签: javascript jquery html

我的示例位于mydiv

中的内容之下
<div id="mydiv">
   sample text sample text sample text...
   ......
   <i>inner text </i> <i>sample text </i>
   ......
   <b>sample text </b> <i>sample text </i>
</div>

现在我想在mydiv内容之间添加突出显示div。样品如下。

<div class="highlight">highlight text</div>

我想在每200个单词中插入这个div,但问题是它不应该进入任何子标签内。例如,如果第200个单词是内部的,它不应该像

那样追加
<div id="mydiv">
   sample text sample text sample text...
   ......
   <i>inner<div class="highlight">highlight text</div> text </i> <i>sample text </i>
   ......
   <b>sample text </b> <i>sample text </i>
</div>

它应该在内部标签后附加

<div id="mydiv">
   sample text sample text sample text...
   ......
   <i>inner text </i> <div class="highlight">highlight text</div> <i>sample text </i>
   ......
   <b>sample text </b> <i>sample text </i>
</div>

我尝试使用子字符串,但它在子标记内部。有没有办法实现这个目标?我们可以使用任何js库。

9 个答案:

答案 0 :(得分:6)

最简单的方法是遍历div的内容并在正确的位置插入突出显示。这是代码:

$(document).ready(function () {
    // count of characters (modulo the period) and selected period
    var count = 0, period = 200;

    // iterator and highlight
    var words = '', highlight = '<div class="highlight">highlight text</div>';

    // loop through the contents
    $('#mydiv').contents().each(function () {
        // we only care about text contents
        if (this.nodeType === 3) {
            // get the individual words
            words = $(this).text().split(' ');
            // loop through them
            for (var j = 0; j < words.length; j++) {
                // increase count except if the word is empty (mutiple spaces)
                if (words[j] && words[j] !== '\n') { count++; }
                // if the period is exceeded, add the highlight and reset the count
                if (count === period) {
                    words.splice(1 + j++, 0, highlight);
                    count = 0;
                }
            }
            // replace the text
            $(this).replaceWith(words.join(' '));
        }
    });
});

答案 1 :(得分:4)

您可以使用JQuery afterinsertAfter在目标之后插入元素。

append方法将指定的内容作为jQuery集合中每个元素的last child插入

&#13;
&#13;
$(function(){
    
  // your logic to find position goes here...
  
  // append  text after an element 
  $("#mydiv i:first-child").after("<div class='highlight'>highlight text</div>");
  
});
&#13;
.highlight{
   color: red;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="mydiv">
  sample1 text1 sample1 text1 sample1 text1sample1 tex1 sample1 text1 sample text1 sample2 text2 sample2 text sample2 textsample2 text2 sample2 text2 sample2 text2 sample3 text3 sample3 text3 sample3 textsample3 text3 sample3 text3 sample3 text3 sample
  3 text 3sample 3text sample3 textsample3 text4 sample 4text sample4 text

  <i>1inner text 1 </i>  <i>sample text 1</i>
  <i>2inner text 2</i>  <i>sample text2 </i>
  <i>3inner text 3</i>  <i>sample text 3</i>
  <i>4inner text 4</i>  <i>sample text4 </i>
  <i>5inner text 5</i>  <i>sample text5 </i>
  <i>6inner text 6</i>  <i>sample text6 </i>
  <i>7inner text 7</i>  <i>sample text 7</i>

  <b>8sample text 8</b>  <i>sample text 8</i>
  <b>9sample text 9</b>  <i>sample text 9</i>
  <b>10sample text 10</b>  <i>sample text10 </i>
  <b>11sample text 11</b>  <i>sample text 11</i>
  <b>12sample text 12</b>  <i>sample text 12</i>

</div>
&#13;
&#13;
&#13;

答案 2 :(得分:3)

<强>已更新 我将在每第二个单词后添加的div。

var some_div = '<div style="display:inline-block;color:red;">some_text</div>';

var text = $('#mydiv').text().match(/\w+/g);

其次,遍历所有单词并在div的html中使用唯一标识符文本作为前缀。

在这里,我添加一个字符串<index>$$,其中<index>在每次遍历时递增。

var i = 1;
var count = 1;
var html = $('#mydiv').html();

text.forEach(function(word, index) {

  var offset = html.indexOf(word);
  while (html[offset - 1] == '$' && html[offset - 2] == '$') {
    offset = html.indexOf(word, offset + 1);
  }

  if ((count % up_index) == 0) {
    html = html.slice(0, offset) + (i++) + '$$' + html.slice(offset)
    $('#mydiv').html(html);
  }

  count++;
});

最后,遍历所有独特的令牌并用你的html替换它们。

找到令牌使用jquery的$('#mydiv').find(':contains(' + j + '$$)');

for (var j = 1; j < i; j++) {
  var elm = $('#mydiv').find(':contains(' + j + '$$)');
  if (elm.length == 0) {
    console.log('inroot>>' + ':contains(' + j + '$$)');
    var offset = $(':contains(' + j + '$$)').last().html().indexOf(j + '$$');
    var t_html = $(':contains(' + j + '$$)').last().html().slice(0, (offset + (("" + j + '$$').length))).replace(/[0-9]\$\$/ig, '');
    t_html += some_div;
    t_html += $(':contains(' + j + '$$)').last().html().slice(offset + (("" + j + '$$').length));
    $('#mydiv').html(t_html);

  } else {
    console.log('not inroot>>' + ':contains(' + j + '$$)');
    $(some_div).insertAfter(elm.last());
  }
}

以下是我在div

之后添加2nd word的示例

首先,我按照以下方式获取感兴趣容器内的所有单词,

var some_div = '<div style="display:inline-block;color:red;">some text</div>';

var up_index = 2; // Word index that will be updated every 2nd word.

var text = $('#mydiv').text().match(/\w+/g);

var i = 1;
var count = 1;
var html = $('#mydiv').html();

text.forEach(function(word, index) {

  var offset = html.indexOf(word);
  while (html[offset - 1] == '$' && html[offset - 2] == '$') {
    offset = html.indexOf(word, offset + 1);
  }

  if ((count % up_index) == 0) {
    html = html.slice(0, offset) + (i++) + '$$' + html.slice(offset)
    $('#mydiv').html(html);
  }

  count++;
});

for (var j = 1; j < i; j++) {
  var elm = $('#mydiv').find(':contains(' + j + '$$)');
  if (elm.length == 0) {
    console.log('inroot>>' + ':contains(' + j + '$$)');
    var offset = $(':contains(' + j + '$$)').last().html().indexOf(j + '$$');
    var t_html = $(':contains(' + j + '$$)').last().html().slice(0, (offset + (("" + j + '$$').length))).replace(/[0-9]\$\$/ig, '');
    t_html += some_div;
    t_html += $(':contains(' + j + '$$)').last().html().slice(offset + (("" + j + '$$').length));
    $('#mydiv').html(t_html);

  } else {
    console.log('not inroot>>' + ':contains(' + j + '$$)');
    $(some_div).insertAfter(elm.last());
  }
}

$('#mydiv').html($('#mydiv').html().replace(/[0-9]\$\$/ig, ''));
.highlight {
  color: red;
  display: inline-block;
}
b {
  background-color: blue;
}
i {
  background-color: yellow;
}
i,
b {
  border: 1px solid green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="mydiv">
  sample text
  <b><a>sample text</a></b>  <i>sample text </i>
  ......
  <i>inner text </i>  <i>sample text </i>
  ......
  <b>sample text </b>  <i>sample text </i>
</div>

答案 3 :(得分:3)

您还没有详细说明 如何到达DOM中的文本(我假设您正在使用DOM)。但是如果文本节点包含感兴趣的单词,那么应该这样做。为方便起见,我使用的是最小量的jQuery,几乎没有必要。

// use jQuery to find the text node "inner text" from your example
let textNode = $("#mydiv i")
    .first()
    .contents()
    .filter(function () {
        return this.nodeType == 3; /* text node */
    }).get(0);

// find the parent element of the text node
let el = textNode;
while (el.parentNode) {
    if (el.nodeType == 1) break; /* element */
    el = el.parentNode;
}
// append the html after the parent of the text node.
 $(el).after(`<div class="highlight">highlight text</div>`);

您可以在此plnkr上看到这一点。

基本上,代码获取第N个感兴趣的单词的文本节点,找到它的父元素,然后插入所需的html作为父元素的第一个右兄弟。

答案 4 :(得分:3)

无论如何,我希望这会有所帮助。

注意:使用的HTML是示例内容
尝试拆分div 内容并从中开展工作。请参阅注释以获取解释:

        //1.Get mydiv content
        //2. Split spaces and newlines
        //3. Remove empty array values
        var div =     $("#mydiv").html().toString().split(/[\s+\n]/).filter(String);

        var allowAdd = true, appendNow;
        for(var a=0; a < div.length ; a++){
            if(div[a].match(/^</) && div[a].match(/>$/)){ //search for end tags ie. </i>, </b>
                if(div[a].match(/<\//)){ //if end tag, 
                    allowAdd = true;    //allow append
                }
            }else if (div[a].match(/</)){ //if start stag,
                allowAdd = false;   //disallow append (inside block)

            }

            if((a+1)%200 == 0){
                //every 200 words
                appendNow = true;
            }

            //append if 200th word and end tag is passed
            if(appendNow && allowAdd){
                div[a] += ' <div class="highlight">highlight text </div> ';
                appendNow = false;
            }
        }

        //join array values and assign value to mydiv content
        $("#mydiv").html(div.join(" ")); 

答案 5 :(得分:3)

这是一个代码,可以为您提供所需的结果。 此代码的优势在于它不检查每个元素是否为标记,方法是检查它是否包含<</ ,我认为这是好的,因为我们的代码并不像它那样复杂,我们不需要检查所有值,无论它们是否包含<</。 (减少计算,理论上应该运行得更快。)

var elements = $("#mydiv").contents(); //Get all contents of #mydiv
$("#mydiv").html(null); //Delete all elements from #mydiv

var count = 0; //This will be counting our elements

for(var i = 0; i < elements.length; i++){ //Go through all elements of #mydiv
    if(elements[i].nodeName == "#text"){ //If the element is a text block, then:

        var textElements = $(elements[i]).text().split(/\s+/g); //Split the text by all the spaces

        for(var j = 0; j < textElements.length; j++){ //Go through all elements inside the text block

            if(textElements[j] == "") continue; //The splitting of the text-block elements is not perfect, so we have to skip some elements manually

            count++; //Add to our count

            $("#mydiv").append(textElements[j] + " "); //Add this element to our cleared #mydiv

            if(count != 0 && count % 200 == 0){ //Every 200 elements, do this:
                $("#mydiv").append(" <span class='highlight'>highlight</span> "); //Add our highlight
            }
        }
    }else{ //If the element is not a text block, then:

        $("#mydiv").append(elements[i]); //Add the non-text element

        count++; //Add to our counter

        if(count != 0 && count % 200 == 0){ //Every 200 elements, do this:
            $("#mydiv").append(" <span class='highlight'>highlight</span> "); //Add our highlight

        }
    }
}

答案 6 :(得分:3)

如果您可以将#mydiv的HTML作为字符串进行操作,则一种解决方案是将string.replace与正则表达式和替换函数一起使用,例如:

function insertInHTMLEveryNWords(n, htmlString, insertString) {
  var wordCounter = 0,
      tagDepth = 0;
  return htmlString.replace(
    /<(\/?)([^>]+)>|[^<\s]+/g,
    function(match, forwardSlash, tagContent) {
      if (tagContent) { //matched a tag
        tagDepth += forwardSlash ? -1 : 1;
      } else { //matched a word
        wordCounter++;
      }
      if (!tagDepth && wordCounter >= n) {
        //if not inside tag and words are at least n,
        wordCounter = 0;
        return match + insertString;
      } else {
        return match;
      }
    });
}

以下代码段包含该方法的工作演示,简化为每2个字后插入(如果不在任何标记中,或直接在下一个可能的结束标记之后,如OP所述):

&#13;
&#13;
var htmlOriginal = document.getElementById('mydiv').innerHTML;

var htmlWithInsertions = insertInHTMLEveryNWords(
  2,
  htmlOriginal,
  '<div>[Inserted DIV after every 2 words or when not in any tag]</div>'
);

//inspect result in console
console.log(htmlWithInsertions);

//replace html in #mydiv
document.getElementById('mydiv').innerHTML = htmlWithInsertions;

function insertInHTMLEveryNWords(n, htmlString, insertString) {
  var wordCounter = 0,
      tagDepth = 0;
  return htmlString.replace(
    /<(\/?)([^>]+)>|[^<\s]+/g,
    function(match, forwardSlash, tagContent) {
      if (tagContent) { //matched a tag
        tagDepth += forwardSlash ? -1 : 1;
      } else { //matched a word
        wordCounter++;
      }
      if (!tagDepth && wordCounter >= n) {
        //if not inside tag and words are at least n,
        wordCounter = 0;
        return match + insertString;
      } else {
        return match;
      }
    });
}
&#13;
<div id="mydiv">
  Some text, word3,
  <em>emphasized and <strong>strong</strong></em> text.
</div>
&#13;
&#13;
&#13;

一个潜在的限制是,操纵HTML会替换#mydiv中的现有DOM元素,并打破以前对它们的任何引用。如果这没有任何问题,这是一个简单的工作解决方案。

答案 7 :(得分:-1)

i 标记是一个内联元素,并且不可能在其中插入一个块元素,如 div 。并且&#34;突出显示&#34; 不是 div 的有效属性。

要实现插入,请使用 span 而不是 div 。并检查您的目标需要哪个属性。结果将是( id 作为属性):

<div id="mydiv">
   sample text sample text sample text...
   ......
   <i>inner<span id="highlight">highlight text</span> text </i> <i>sample text </i>
   ......
   <b>sample text </b> <i>sample text </i>
</div>

答案 8 :(得分:-1)

我假设你已经找到了单词200并在它之后附加你的div,这样的事情可能会这样吗?

varUntilSpace200 + '<div "highlight">highlight text</div>' + restOfInnerHTML;

然后您需要做的就是检查restOfInnerHTML,如果在空格200之后有一个

"</"

如果是这样,只需将该位置的所有内容附加到第一个

">"

var indof1 = restOfInnerHTML.indexOf("</");
var indof2 = restOfInnerHTML.indexOf("<");
var indof3 = restOfInnerHTML.indexOf(">");

if (indof1 < indof2) {
  varUntilSpace200 += restOfInnerHTML.substring(indof1,indof3);
  restOfInnerHTML = restOfInnerHTML.substring(indof3+1,restOfInnerHTML.length);
}