Like the title says. If it's not then what would be the same as .innerHTML = "" ?
It's nearly the same. If you look at the source for the method, you'll see that it's:
empty: function() {
var elem,
i = 0;
for ( ; ( elem = this[ i ] ) != null; i++ ) {
if ( elem.nodeType === 1 ) {
// Prevent memory leaks
jQuery.cleanData( getAll( elem, false ) );
// Remove any remaining nodes
elem.textContent = "";
}
}
return this;
},
And assigning the empty string to the .textContent of an element is the same as assigning the empty string to the .innerHTML of an element.
The only difference is that .empty calls .cleanData, which removes a number of jQuery-specific data/events associated with the element, if there happen to be any.
Related
Let's say I have the following element TEXT in HTML:
<div id="TEXT">
<p>First <strong>Line</strong></p>
<p>Seond <em>Line</em></p>
</div>
How should one extract the raw text from this element, without HTML tags, but preserving the line breaks?
I know about the following two options but neither of them seems to be perfect:
document.getElementById("TEXT").textContent
returns
First LineSecond Line
problem: ignores the line break that should be included between paragraphs
document.getElementById("TEXT").innerText
returns
First Line
Second Line
problem: is not part of W3C standard and is not guaranteed to work in all browsers
Here's a handy function for getting text contents of any element and it works well on all platforms, and yes, it preserves line breaks.
function text(e){
var t = "";
e = e.childNodes || e;
for(var i = 0;i<e.length;i++){
t+= e[i].nodeType !=1 ? e[i].nodeValue : text(e[i].childNodes);
}
return t;
}
You can check how jQuery does it. It uses sizzle js. Here is the function that you can use.
<div id="TEXT">
<p>First <strong>Line</strong></p>
<p>Seond <em>Line</em></p>
</div>
<script>
var getText = function( elem ) {
var node,
ret = "",
i = 0,
nodeType = elem.nodeType;
if ( !nodeType ) {
// If no nodeType, this is expected to be an array
while ( (node = elem[i++]) ) {
// Do not traverse comment nodes
ret += getText( node );
}
} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
// Use textContent for elements
// innerText usage removed for consistency of new lines (jQuery #11153)
if ( typeof elem.textContent === "string" ) {
return elem.textContent;
} else {
// Traverse its children
for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
ret += getText( elem );
}
}
} else if ( nodeType === 3 || nodeType === 4 ) {
return elem.nodeValue;
}
// Do not include comment or processing instruction nodes
return ret;
};
console.log(getText(document.getElementById('TEXT')));
<script>
I'm reading Sizzle source code. I saw the definition below
function Sizzle(selector, context, results, seed)
My question is what's the meaning about the parameter seed? I can't find it in API document
Thanks
addendum
The seed parameter is used in jQuery's event handler source (from 2.1.4):
jQuery.find = Sizzle;
// [...]
jQuery.event = {
// [..]
handlers: function( event, handlers ) {
// [..]
// Find delegate handlers
if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
for ( ; cur !== this; cur = cur.parentNode || this ) {
// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
if ( cur.disabled !== true || event.type !== "click" ) {
matches = [];
for ( i = 0; i < delegateCount; i++ ) {
handleObj = handlers[ i ];
// Don't conflict with Object.prototype properties (#13203)
sel = handleObj.selector + " ";
if ( matches[ sel ] === undefined ) {
matches[ sel ] = handleObj.needsContext ?
jQuery( sel, this ).index( cur ) >= 0 :
//
// Right here to find if cur matches the
// delegated event handler's selector.
//
jQuery.find( sel, this, null, [ cur ] ).length;
// There: -----------------------^
}
if ( matches[ sel ] ) {
matches.push( handleObj );
}
}
if ( matches.length ) {
handlerQueue.push({ elem: cur, handlers: matches });
}
}
}
}
},
You can use the seed parameter to limit the selection to a list of candidates. Just pass in an array of DOM elements.
For example let's say we have the following DOM:
<div id="id1"></div>
<div id="id2"></div>
Then, perform the following selections:
Sizzle("#id1", null, null, null);
// [<div id="id1"></div>]
And:
var candidates = [
document.getElementById("id1"),
document.getElementById("id2")
];
Sizzle("#id1", null, null, candidates);
// [<div id="id1"></div>]
But:
var candidates = [
document.getElementById("id2")
];
Sizzle("#id1", null, null, candidates);
// []
Note: This functionality doesn't seem to be part of the public API.
A seed is usually used to determine specific sequences of pseudo-random numbers. If you want the same repeated order of numbers on every run you use the same seed. Random number generators can use time stamps to make sure seeds vary, but for testing it it extremely useful to be able to set such seeds.
I assume the seed in this case will have a similar meaning, it will mean the outcome of Sizzle will be identical on every run if the seed is the same, if it is different the outcomes will be different.
I have this html structure :
<body>
<a>
<b>
<c>
<d>
</d>
</c>
</b>
</a>
</body>
I use the <d> element as the first node to start with.
Question :
var s= $("d").parentsUntil("body").andSelf().map(function(){
return this.tagName;
}).get();
It should start from the bottom and to top meaning the s array should look like d,c,b,a.
But it apparently look like : ["A", "B", "C", "D"]
Why is that ?
Jsbin
.andSelf() causes jQuery to re-order the array.
You can try :
var s= $("d").parentsUntil("body").map(function(){
return this.tagName;
}).get();
The output of this code looks like:["C", "B","A" ].
If you look at addBack's code (to which andSelf is an alias), you see this :
add: function( selector, context ) {
var set = typeof selector === "string" ?
jQuery( selector, context ) :
jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
all = jQuery.merge( this.get(), set );
return this.pushStack( jQuery.unique(all) );
},
addBack: function( selector ) {
return this.add( selector == null ?
this.prevObject : this.prevObject.filter(selector)
);
}
So you see it calls unique.
By looking further, you see
jQuery.unique = Sizzle.uniqueSort;
and
Sizzle.uniqueSort = function( results ) {
var elem,
duplicates = [],
i = 1,
j = 0;
// Unless we *know* we can detect duplicates, assume their presence
hasDuplicate = !support.detectDuplicates;
results.sort( sortOrder );
if ( hasDuplicate ) {
for ( ; (elem = results[i]); i++ ) {
if ( elem === results[ i - 1 ] ) {
j = duplicates.push( i );
}
}
while ( j-- ) {
results.splice( duplicates[ j ], 1 );
}
}
return results;
};
So, addBack sorts the set as it ensures the added element isn't yet inside.
I wonder how I can write the jQuery is method using only javascript?
You can't use any third party libraries. Only the javascript provided from the browser.
FYI the method is in jQuery:
Check the current matched set of elements against a selector, element,
or jQuery object and return true if at least one of these elements
matches the given arguments.
If you need support for older browsers, you should use jQuery. This should work in IE9, Firefox and Chrome.
//returns true if element matches selector or if element is equal to the node passed as selector
function is( elem, selector ) {
var div = document.createElement("div");
var matchesSelector = div.webkitMatchesSelector || div.mozMatchesSelector || div.msMatchesSelector;
return typeof selector == "string" ? matchesSelector.call( elem, selector ) : selector === elem;
}
//returns true if any elements in the array/nodelist "is" selector
function anyIs( elems, selector ) {
var l = elems.length, i;
for( i = 0; i < l; ++i ) {
if( is( elems[i], selector ) ) {
return true;
}
}
return false;
}
is(document.createElement("div"), "div")
//true
is(document.createElement("div"), "li")
//false
anyIs(document.getElementsByTagName("div"), document.getElementsByTagName("div")[3])
//true
anyIs(document.getElementsByTagName("div"), "div")
//true
function is( elem, selector ) {
var sel = elem.ownerDocument.querySelectorAll( selector );
return [].some.call( sel, function( el ) {
return elem === el;
} );
}
Will return true if any element matches.
In this simple script i get the error "obj.parentNode.getElementById is not a function", and I have no idea, what is wrong.
<script type="text/javascript">
function dosomething (obj) {
sibling=obj.parentNode.getElementById("2");
alert(sibling.getAttribute("attr"));
}
</script>
<body>
<div>
<a id="1" onclick="dosomething(this)">1</a>
<a id="2" attr="some attribute">2</a>
</div>
</body>
.getElementById() is on document, like this:
document.getElementById("2");
Since IDs are supposed to be unique, there's no need for a method that finds an element by ID relative to any other element (in this case, inside that parent). Also, they shouldn't start with a number if using HTML4, a numberic ID is valid in HTML5.
replace .getElementById(id) with .querySelector('#'+id);
document.getElementById() won't work if the node was created on the fly and not yet attached into the main document dom.
For example with Ajax, not all nodes are attached at any given point. In this case, you'd either need to explicitly track a handle to each node (generally best for performance), or use something like this to look the objects back up:
function domGet( id , rootNode ) {
if ( !id ) return null;
if ( rootNode === undefined ) {
// rel to doc base
var o = document.getElementById( id );
return o;
} else {
// rel to current node
var nodes = [];
nodes.push(rootNode);
while ( nodes && nodes.length > 0 ) {
var children = [];
for ( var i = 0; i<nodes.length; i++ ) {
var node = nodes[i];
if ( node && node['id'] !== undefined ) {
if ( node.id == id ) {
return node; // found!
}
}
// else keep searching
var childNodes = node.childNodes;
if ( childNodes && childNodes.length > 0 ) {
for ( var j = 0 ; j < childNodes.length; j++ ) {
children.push( childNodes[j] );
}
}
}
nodes = children;
}
// nothing found
return null;
}
}