Iterate over every element and get only the content that is directly in the node

让人想犯罪 __ 提交于 2019-12-24 13:33:26

问题


let's assume I have this code

<p>FirstLevelP
    <span>SecondLevelSpan</span>
</p>
<p>FirstLevelP
    <span>SecondLevelSpan
        <p>ThirdLevelP</p>
    </span>
</p>

Is it possible to iterate through every element that I have right now, but only get the content, that's in the direct node of it, modify the text and then have it in the original content?

Example, If I go through every $('p').each and would extract the text I would also get the text inside the span.

Basically this:

FirstelElement: FirstLevelPSecondLevelSpan
SecondElement: SecondLevelSpanSecondLevelSpanThirdLevelP

But I want to have it like this

FirstelElement: FirstLevelP
SecondElement: SecondLevelSpan
ThirdElement: FirstLevelP
FourthElement: SecondLevelSpan
FifthElement: ThirdLevelP

Is this possible?

In my research I already found this answer here

$("#foo")
    .clone()    //clone the element
    .children() //select all the children
    .remove()   //remove all the children
    .end()  //again go back to selected element
    .text();

But this would only solve half of my problems. I would still need to modify the text in the original content! Thanks in advance guys.

EDIT FOR CLARIFICATION

So basically, want I want to achieve is something like this:

For every element, I want to check if there is a dot at the end. If not I want to add one. I already managed to do this for headlines, like this:

foreach (pq($content)->filter(':header') as $headline) {
    if (substr(pq($headline)->text(), 0, -1) != '.') {
        $content = preg_replace('#(' . pq($headline) . ')#', pq($headline) . '.', pq($content));
    }
}

The problem, as I stated, is, that when I have nested elements it would add the dot after the whole element, and not after each sub element if neccessary.

To work with my "assumed" code, it should look like this

<p>FirstLevelP.
    <span>SecondLevelSpan.</span>
</p>
<p>FirstLevelP.
    <span>SecondLevelSpan.
        <p>ThirdLevelP.</p>
    </span>
</p>

But unfortunatley, it currently looks like this

<p>FirstLevelP
    <span>SecondLevelSpan</span>.
</p>
<p>FirstLevelP
    <span>SecondLevelSpan
        <p>ThirdLevelP</p>
    </span>.
</p>

Note the dots.


回答1:


finding and changing text without child elements works this ways:

// search every element
    $("body *").each(function(index, el) {
        // find first text node
        var node = $(el).contents().filter(function() {
            return this.nodeType === 3;
        })[0];

        // change text
        node.textContent = "new text";
    });



回答2:


Edit, Updated

Try

    $("body *").each(function (i, el) {
        if ($(el).is("p, span")) {
            $(el).text(function (idx, text) {
               var t = text.split("\n")[0];
               // if `text` string's last character is not `.`
               // concat `.` to `text` string ,
               // return `text` original string's with `.` added
               return t.slice(-1) !== "." ? t + "." : t
            })
        }
    })

$("body *").each(function (i, el) {
        if ($(el).is("p, span")) {
            $(el).text(function (idx, text) {
               var t = text.split("\n")[0];
               return t.slice(-1) !== "." ? t + "." : t
            })
        }
    })
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>FirstLevelP
    <span>SecondLevelSpan</span>
</p>
<p>FirstLevelP
    <span>SecondLevelSpan
        <p>ThirdLevelP</p>
    </span>
</p>


来源:https://stackoverflow.com/questions/26385939/iterate-over-every-element-and-get-only-the-content-that-is-directly-in-the-node

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!