Consider the following HTML where IDs #p1
, #p2
and #p3
are siblings (see fiddle):
<div id="container">
<span id="p1">Paragraph 1</span>
<span id="p2">Paragraph 2</span>
This is just loose text.
<p id="p3">Paragraph 3</p>
</div>
These are my definitions of strict and loose siblings:
I consider ID #p1
and #p2
strict siblings (because there is no text which is not encapsulated in any kind of html element between them.
And ID #p2
and #p3
to be loose siblings.
Given any element with a next sibling is it possible to know if the next sibling is strict or loose?
Edit: The siblings may be of different type and I updated the fiddle to reflect that.
Answering your question of
Given any element with a next sibling is it possible to know if the next sibling is strict or loose?
rather than following your lead from the fiddle, yes it's possible.
function isMyNextSiblingStrict(element)
{
return ("nodeType" in element && element.nodeType === 1 && element.nextSibling !== null && element.nextSibling.nodeType === 1);
}
This will return true
when an element's next sibling is another element. However, be careful with your example as it is incorrect by your own definition, the two spans have a text node between them made up of white space, so #1 and #2 are not "strict siblings".
<div id="container">
<span id="p1">Paragraph 1</span><!-- WHITESPACE
--><span id="p2">Paragraph 2</span>
This is just loose text.
<p id="p3">Paragraph 3</p>
</div>
These would be "strict siblings".
<div id="container">
<span id="p1">Paragraph 1</span><span id="p2">Paragraph 2</span>
This is just loose text.
<p id="p3">Paragraph 3</p>
</div>
edit - just for fun I've created a jQuery extension that should do what you want - you can see it in your updated jsFiddle, I've not tested it much but it seems to work as you describe
$.fn.extend({
siblingsStrict: function( until, selector ) {
var ret = jQuery.map( this, function( elem ) {
var n = ( elem.parentNode || {} ).firstChild,
r = [],
contig = false;
for ( ; n; n = n.nextSibling ) {
if ( n === elem ) {
contig = true;
}
else if ( n.nodeType === 1 && n !== elem ) {
r.push( n );
}
else if ( n.nodeType === 3 && n.textContent.replace(/\s/g, "") === "" ) {
continue;
}
else if ( n.nodeType === 3 && contig === true ) {
break;
}
else if ( n.nodeType === 3 && contig === false) {
r = [];
}
}
return r;
}, until );
if ( name.slice( -5 ) !== "Until" ) {
selector = until;
}
if ( selector && typeof selector === "string" ) {
ret = jQuery.filter( selector, ret );
}
if ( this.length > 1 ) {
// Remove duplicates
if ( !guaranteedUnique[ name ] ) {
ret = jQuery.unique( ret );
}
// Reverse order for parents* and prev-derivatives
if ( rparentsprev.test( name ) ) {
ret = ret.reverse();
}
}
return this.pushStack( ret );
}
});