admin管理员组文章数量:1394611
I wish to test in jQuery for the existence of a <br />
as the very first, or very last element (including text nodes) within a paragraph. The 2 examples below would be true:
<p>
<br />
Lorem ipsum dolor sit amet consectetur, adiscipling elit.
</p>
<p>
Lorem ipsum dolor sit amet consectetur, adiscipling elit.
<br />
</p>
While this example would be false:
<!-- This is false -->
<p>
Lorem ipsum dolor sit amet consectetur, adiscipling elit
<br />
Lorem ipsum dolor sit amet consectetur, adiscipling elit.
</p>
If true, the following class
’s of diog-fail brbr
are to be applied to the containing paragraph element.
I wish to test in jQuery for the existence of a <br />
as the very first, or very last element (including text nodes) within a paragraph. The 2 examples below would be true:
<p>
<br />
Lorem ipsum dolor sit amet consectetur, adiscipling elit.
</p>
<p>
Lorem ipsum dolor sit amet consectetur, adiscipling elit.
<br />
</p>
While this example would be false:
<!-- This is false -->
<p>
Lorem ipsum dolor sit amet consectetur, adiscipling elit
<br />
Lorem ipsum dolor sit amet consectetur, adiscipling elit.
</p>
If true, the following class
’s of diog-fail brbr
are to be applied to the containing paragraph element.
-
Does it have to be text nodes, or can you change the markup so the text is in, say, a
<span>
? It's typically much easier to ignore text nodes. – Matt Ball Commented Feb 6, 2011 at 17:41 - Yes, it has to be text nodes. This is a diagnostic test to check for correct usage of line breaks within an HTML document. – DigiKev Commented Feb 6, 2011 at 17:43
- 1 ...also, unless you remove the white space in your "true" examples, those do actually have text nodes (the white space) as first/last elements, respectively. – Matt Ball Commented Feb 6, 2011 at 17:53
8 Answers
Reset to default 3This is easy using universally supported DOM properties. jQuery isn't much use here.
function isBr(el) {
return el && el.nodeType == 1 && el.tagName == "BR";
}
function isWhitespaceNode(node) {
return node.nodeType == 3 && /^\s*$/.test(node.data);
}
function isFirstOrLastChildBr(el) {
var first = el.firstChild;
if (isWhitespaceNode(first)) first = first.nextSibling;
if (isBr(first)) return true;
var last = el.lastChild;
if (isWhitespaceNode(last)) last = last.previousSibling;
if (isBr(last)) return true;
return false;
}
So if your <p>
element had id "foo":
var $foo = $("#foo");
if ( isFirstOrLastChildBr($foo[0]) ) {
$foo.addClass("diog-fail brbr");
}
UPDATE WITH EXAMPLE FOR MULTIPLE ELEMENTS
To apply this to a set of matched elements:
// All paragraphs
$("p").filter(function() {
return isFirstOrLastChildBr(this);
}).addClass("diog-fail brbr");
As per the test cases you have provided, this will work:
$('p').each(function ()
{
var $this = $(this),
$brs = $this.children('br'),
numBRs = $brs.length,
firstBR = $brs.get(0),
firstBRprev = firstBR ? firstBR.previousSibling : null,
firstBRnext = (firstBR && numBRs == 1) ? firstBR.nextSibling : null,
lastBR = numBRs > 1 ? $brs.get(numBRs) : null,
lastBRnext = lastBR ? lastBR.nextSibling : null;
if ((firstBRprev && !firstBRprev.nodeValue.trim()) ||
(firstBRnext && !firstBRnext.nodeValue.trim()) ||
(lastBRnext && !lastBRnext.nodeValue.trim()))
{
console.log(this);
$this.addClass('diog-fail brbr');
}
});
Not much jQuery because jQuery hides lots of the nasty DOM business from you, including text nodes.
Demo →
Here is the jsfiddle:
Using RegEx and If Else condition
$('p').each(function() {
var temp = this.innerHTML.replace(/^\s*|\s(?=\s)|\s*$/g, "").toLowerCase();
if (temp.substring(0, 5) == '<br/>' || temp.substring(0, 4) == '<br>' || temp.substring(0, 6) == '<br />') {
$(this).addClass('diog-fail brbr');
console.log('start: true');
} else if (temp.substring(temp.length - 5, temp.length) == '<br/>' || temp.substring(temp.length - 4, temp.length) == '<br>' || temp.substring(temp.length - 6, temp.length) == '<br />') {
$(this).addClass('diog-fail brbr');
console.log('end: true');
} else {
console.log('none: ' + false);
}
});
First get all paragraphs and then use RegEx on the innerHTML and flatted it by removing whitespace, newline and etc. Then do if else condition to see if first and last few substrings matches <br>, <br/> or <br />
How about:
function brIsFirstOrLast(selector) {
var contents = $(selector).contents().filter(function() {
return this.nodeType !== 3 || $.trim($(this).text().replace("\n", "")) !== "";
});
var last = contents.last()[0];
var first = contents.first()[0];
return (!!last.tagName && last.tagName.toLowerCase() === "br") ||
(!!first.tagName && first.tagName.toLowerCase() === "br");
}
Usage:
brIsFirstOrLast("p:first");
Note that this function expects the selector to return one result. You could probably add some more validation too, but this should get you started.
See it working: http://jsfiddle/andrewwhitaker/F2dwm/
I would suggest using a little bit of RegExp:
//returns true if there is a <br/> at begin or end, otherwise false
$.trim($('p').html()).match(/(^<br\s*\/?>|<br\s*\/?>$)/i)
Otherwise you will have to struggle with browser-dependencies on handling whitespaces as textNodes
Okay, here's one (only slightly clunky) way to do it, given the following html for demo purposes:
html
<div class="testThis">
<p>Some text, or other with a 'br' at the end.<br /></p>
</div>
<div class="testThis">
<p><br />Some more text, with a 'br' at the beginning.</p>
</div>
<div class="testThis">
<p>Some text with a 'br' <br /> in the middle</p>
</div>
css
.testThis {
border: 1px solid #ccc;
margin: 0 auto 1em auto;
padding: 0.5em;
width: 80%;
border-radius: 1em;
}
.brFirst {
border-color: #f00;
}
.brLast {
border-color: #00f;
}
jQuery
$('.testThis').each(
function(){
var haystack = $(this).find('p').html();
var needle = '<br>';
//alert(haystack.indexOf('<br>'));
if (haystack.indexOf(needle) == 0) {
$(this).addClass('brFirst');
}
else if (haystack.indexOf(needle) == (haystack.length - needle.length)) {
$(this).addClass('brLast');
}
});
JS Fiddle demo.
Edited to update the jQuery, to use the trim()
method (so whitespace at the beginning, and end, of the variable haystack
will be removed):
$('.testThis').each(
function(){
var haystack = $(this).find('p').html().trim();
var needle = '<br>'; // Tested in Chrome the `<br />` element is converted to `<br>`
if (haystack.indexOf(needle) == 0) {
$(this).addClass('brFirst');
}
else if (haystack.indexOf(needle) == (haystack.length - needle.length)) {
$(this).addClass('brLast');
}
});
Updated JS Fiddle demo.
For removing <br>
from inside <p>
in embedded editor, I use:
target.find('p').find('br').each(function () {
if(! $(this)[0].nextSibling || ! $(this)[0].previousSibling) $(this).remove();
});
For test and change <p>
class:
target.find('p').each(function () {
let ancestor = $(this);
$(this).find('br').each(function () {
console.log(! $(this)[0].nextSibling || ! $(this)[0].previousSibling ? 'edge' : '!edge');
ancestor.addClass('zorglubissime');
});
});
I hope this helps...
Ooops. This better:
target.find('p').each(function () {
let ancestor = $(this);
$(this).find('br').each(function () {
if(! $(this)[0].nextSibling || ! $(this)[0].previousSibling)
ancestor.addClass('zorglubissime');
});
});
Use the :first-child
and :last-child
selectors
So $('p > br:first-child, p > br:last-child').length > 0
本文标签:
版权声明:本文标题:javascript - jQuery: Check for existence of BR as first or last element, including text nodes within a paragraph - Stack Overflo 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744095891a2590274.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论