问题:
I have problem facing selecting div/span elements via jQuery contains(arg) method. I want to count the total number of elements that contain specific text. But it is giving...
可以将文章内容翻译成中文,广告屏蔽插件会导致该功能失效:
问题:
I have problem facing selecting div
/span
elements via jQuery contains(arg)
method. I want to count the total number of elements that contain specific text. But it is giving different results to different HTML elelemts. See the code below.
$(document).ready(function(){
$("#co").text($("span:contains('cool')").length)
$("#co1").text($("div:contains('cool')").length)
$("#co2").text($("li:contains('cool')").length)
$("#co3").text($("p:contains('cool')").length)
});
Span -<span id="co"> </span>
<div></div>
Div -<span id="co1"> </span>
<div></div>
Li -<span id="co2"> </span>
<div></div>
p -<span id="co3"> </span>
<br><br>
<div> <div> cool </div> </div>
<p> <p> cool </p> </p>
<ul><li> <li> cool </li> </li></ul>
<span> <span> cool </span> </span>
The above code outputs result
Span -2
Div -2
Li -1
p -1
I just don't understand WHY, while every element should have same count.
回答1:
To understand why, look at the rendered HTML. When you have a <p>
inside another unclosed <p>
, the browser things you meant to end the previous <p>
and start a new one, because <p>
s cannot nest. Similarly, a <li>
cannot exist directly inside another <li>
- it may only exist as a child of a <ul>
(or <ol>
), so <li> <li> cool </li> </li>
gets interpreted as <li> </li><li> cool </li>
.
On the other hand, <span>
s and <div>
s can be nested in each other, so they appear in the document the same way your HTML is written.
console.log(document.body.innerHTML);
<div> <div> cool </div> </div>
<p> <p> cool </p> </p>
<ul><li> <li> cool </li> </li></ul>
<span> <span> cool </span> </span>
So, the rendered document has:
<span> <span> cool </span> </span>
- a cool
nested inside 2 <span>
s
<p> </p><p> cool </p> <p></p>
- a cool
nested inside one <p>
(the other <p>
s being empty)
<ul><li> </li><li> cool </li> </ul>
- a cool
nested inside one <li>
(the other <li>
s being empty)
<div> <div> cool </div> </div>
- a cool
nested inside 2 <div>
s
回答2:
The reason your jQuery outputs unexpected counts of each element is that your HTML is invalid. When you have invalid HTML, the browser automatically tries to correct it for you, by moving / removing sections that it knows is invalid. If you look at the DOM, you'll see that several of your elements don't exist.
For example, <p> <p> cool </p> </p>
produces the following during rendering:

In the above, you can see that indeed, only one <p>
element contains cool
, resulting in one match.
Fixing up the invalid HTML also displays the correct results:
$(document).ready(function() {
$("#co").text($("span:contains('cool')").length)
$("#co1").text($("div:contains('cool')").length)
$("#co2").text($("li:contains('cool')").length)
$("#co3").text($("p:contains('cool')").length)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Span -<span id="co"> </span>
<div></div>
Div -<span id="co1"> </span>
<div></div>
Li -<span id="co2"> </span>
<div></div>
p -<span id="co3"> </span>
<br><br>
<div>
<div>cool</div>
</div>
<p>cool</p>
<ul>
<li>cool</li>
</ul>
<span>cool</span>