最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Find text between two tagsnodes - Stack Overflow

programmeradmin4浏览0评论

I thought that this would be rather straightforward, but I think the keywords are just too general so I keep getting query results for things like this and this.

Basically, I have the following HTML:

<div id="test">
    Lorem
    <span class="highlighted">ipsum</span>
    dolor sit amet,
    <span class="highlighted">consectetur</span>
    <span class="highlighted">adipiscing</span>
    elit. Sed massa.
<div>

I'd like to merge adjacent span tags into a single span tag, which means finding spans with only whitespace between them (this could include spaces, tabs and newlines).

The result I'm looking for is this:

<div id="test">
    Lorem
    <span class="highlighted">ipsum</span>
    dolor sit amet,
    <span class="highlighted">consectetur adipiscing</span>
    elit. Sed massa.
<div>

I've examined the nextUntil function, but it seems to only return tags, not text. The result, for example, of

$("span.highlighted").nextUntil("span.highlighted").andSelf().text();

is

ipsumconsecteturadipiscing

rather than

ipsum dolor sit amet, consecteturadipiscing

Given two tags, how can I find the text between them?

I thought that this would be rather straightforward, but I think the keywords are just too general so I keep getting query results for things like this and this.

Basically, I have the following HTML:

<div id="test">
    Lorem
    <span class="highlighted">ipsum</span>
    dolor sit amet,
    <span class="highlighted">consectetur</span>
    <span class="highlighted">adipiscing</span>
    elit. Sed massa.
<div>

I'd like to merge adjacent span tags into a single span tag, which means finding spans with only whitespace between them (this could include spaces, tabs and newlines).

The result I'm looking for is this:

<div id="test">
    Lorem
    <span class="highlighted">ipsum</span>
    dolor sit amet,
    <span class="highlighted">consectetur adipiscing</span>
    elit. Sed massa.
<div>

I've examined the nextUntil function, but it seems to only return tags, not text. The result, for example, of

$("span.highlighted").nextUntil("span.highlighted").andSelf().text();

is

ipsumconsecteturadipiscing

rather than

ipsum dolor sit amet, consecteturadipiscing

Given two tags, how can I find the text between them?

Share Improve this question edited Jul 15, 2013 at 19:41 Paul Roub 36.4k27 gold badges86 silver badges95 bronze badges asked Jul 15, 2013 at 19:08 JDBJDB 25.9k5 gold badges79 silver badges132 bronze badges 8
  • You want to find the text between tags or concat them? – Oscar Jara Commented Jul 15, 2013 at 19:20
  • @OscarJara: He wants to concat the tags if the text between them is whitespace. – gen_Eric Commented Jul 15, 2013 at 19:23
  • Is it possible for two spans to not have a space, tab, or newline between them, or will they always have only one of those? – j08691 Commented Jul 15, 2013 at 19:24
  • 1 I also want to know if the OP will handle more than 2 or 3 tags – Oscar Jara Commented Jul 15, 2013 at 19:28
  • @j08691 - If you check my example, you will see 3 span tags. One of them is separated by non-whitespace, two of them are separated only by whitespace. If, and only if, the tags contain only whitespace between them, I want to merge them together. – JDB Commented Jul 15, 2013 at 19:41
 |  Show 3 more ments

6 Answers 6

Reset to default 5

Dropping down to the DOM lets you see text node contents when checking siblings.

Something like:

function bineSpans(span, nextspan)
{
  var follower = span.nextSibling;
  var concat = true;

   while (follower != nextspan)
   {
     if (follower.nodeName != '#text')
     {
       concat = false;
       break;
     }

     var len = follower.data.trim().length;
     if (len > 0)
     {
       concat = false;
       break;
     }

     follower = follower.nextSibling;
   }

  if (concat)
  {
    $(span).text($(span).text() + " " + $(follower).text());
    $(follower).remove();
  }
}

Using this with your HTML in this CodePen.

Well, you can try this...

At least it works perfect when using 2 spans to merge them like your example (when an "empty" element is present). Otherwise, you will need to think a little to handle the span that lasts.

(To check what I am talking about just take a look menting the last line: nextElem.remove() and check the new div html).

Live Demo: http://jsfiddle/oscarj24/t45MR/


HTML:

<div id="test">
    Lorem
    <span class="highlighted">ipsum</span>
    dolor sit amet,
    <span class="highlighted">consectetur</span>
    <span class="highlighted">adipiscing</span>
    elit. Sed massa.
</div>

jQuery:

$(document).ready(function () {

    var elem = $('#test');

    elem.contents().filter(function(index) {
        //Get index of an empty element
        if($.trim($(this).text()) === '') 
            //Merge the previous index span with the next index span texts
            mergeSpan(index);
    });

    //Print new inner html
    alert(elem.html());
});

function mergeSpan(index){

    //Get all 'div' elements
    var elems = $('#test').contents();

    //Get previous and next element according to index
    var prevElem = elems.eq(index - 1);
    var nextElem = elems.eq(index + 1);

    //Concat both texts
    var concatText = prevElem.text() + ' ' + nextElem.text();

    //Set the new text in the first span
    prevElem.text(concatText);
    //Remove other span that lasts
    nextElem.remove();
};

Result:

<div id="test">
    Lorem
    <span class="highlighted">ipsum</span>
    dolor sit amet,
    <span class="highlighted">consectetur adipiscing</span>
    elit. Sed massa.
<div>

I know you have already accepted a solution, but I wanted to take the challenge to provide a pure javascript solution which can be incorporated into your toolset. Here's what I came up with, and would like any help to make this better.

http://jsfiddle/ryanwheale/JhZPK/

function joinNeighborsByClassName( className ) {
    var items = document.getElementsByClassName(className),
        next = null,
        remove = [],
        append = '',
        i = 0;

    while( i < items.length && (next = items[i++]) ) {
        while( (next = next.nextSibling) && next !== null ) {
            if((next.nodeType === 3  && /^\s+$/.test(next.nodeValue)) ||     
               (new RegExp("(?:^|\s)" + className + "(?!\S)", "g")).test(next.className) ) {
                append += (next.innerHTML || next.nodeValue);

                if(next.nodeType !== 3) {
                    remove.push(next);
                }
            } else {
                break;
            }
        }

        if(append) items[i-1].innerHTML += append;
        for(var n = 0; n < remove.length; n++) {
            remove[n].parentNode.removeChild(remove[n]);
        }

        remove = [];
        append = '';
    }
}

joinNeighborsByClassName('highlighted');

For your last question "Given two tags, how can i find the text between them?"

Well, I have this solution for you.

var divData = $("#test").html(); // Getting html code inside div

Now, using preg_match() you can obtain the text between two words, in your case the text between spans, like this:

preg_match('/'.preg_quote($word1).'(.*?)'.preg_quote($word2).'/is', $html, $matches);

$word1 = '<span class="highlighted">';
$word2 = '<';
$html = $_POST['divData']; // Via post/get you will have to send the html code gotten in "var divData"

and for each match(with a for cycle) concat em in a variable adding whitespaces between them. Then do an echo your result and in your call back function add it to your div

This link could help you in how make a POST call in jquery jquery post

As the title request it, here's a possible way to get text nodes between spans:

var textNodes=$('#test').contents().filter(function(){
    return this.nodeType == 3; // text node
});

It is also possible to manually check for consecutive spans that have no empty text node between them by paring each node with the precedent one. Something like this will do the trick:

function bineSpansIn(selector, spanClass) {
    // initialize precedent values
    var prec=null;
    var precNodeType;

    $(selector).contents().each(function(){
        if ($.trim( $(this).text() ) !== "") { // empty nodes will be useless here
            var nodeType = this.nodeType;

            // check if still a binable span
            if (nodeType == 1 && this.className==spanClass && nodeType == precNodeType) {
                // append current node to precedent one
                $(prec).append(" "+ $(this).text() );

                // remove current node
                $(this).remove();
            } else {
                // update precedent values
                prec=this;
                precNodeType = nodeType;
            }
        }
    });
}

bineSpansIn('#test', 'highlighted');

Please take a look at this FIDDLE.

Heh . . . looks like Oscar Jara and I came up with similar ideas around using the JQuery .contents() method, but ended up with some considerably different implementations:

$(document).ready(function () {
    $("#testDiv").contents().each(function() {
        var prevNode = this.previousSibling;
        var fillerText = "";
        while ((prevNode) && ($.trim($(prevNode).text()) === "")) {
            fillerText += prevNode.nodeValue;
            prevNode = prevNode.previousSibling;
        }

        if ((prevNode) && (this.nodeType === 1) && (prevNode.nodeType === 1)) {
            $(prevNode).text($(prevNode).text() + fillerText + $(this).text());
            $(this).remove();
        }
    });
});

I tested a few different sets of HTML data (three spans back-to-back, spans with spaces in between and without, etc.) all based on your original code, and it seems to work . . . the key was to skip over any "whitespace only" text nodes in between the <span> tags, while preserving any needed spacing that they may have contained.

发布评论

评论列表(0)

  1. 暂无评论