In the following code, when $(this) is called, does jQuery re-query the DOM as though a selector has been passed to it (using some property of the object as a selector), or does jQuery retain the previously returned object?
$('.someButton').on('click', function() {
$(this).remove(); // Is this another lookup, or just a wrapper for the previously returned object?
});
It doesn't re-query the DOM, this is already an element. jQuery simply sets the context to the element, adjusts the length, and returns itself. This code is from the init function, which runs when you do $(something), this is part of a big if..else statement, where it also checks for selectors, arrays among other things:
// HANDLE: $(DOMElement)
} else if (selector.nodeType) {
this.context = this[0] = selector;
this.length = 1;
return this;
So basically it just wraps the element in a new jQuery object.
Related
I'm working on a jQuery widget that attaches events to the widget's parent, but I'm unable to tell if it has a parent.
For example;
var x = $('<div>');
x.mywidget();
........... in mywidget
_create : function () {
var y = this.element.parent() === undefined ? this.element : this.element.parent();
y.bind(....);
}
I need to check if the widget has been added to the DOM before I do the bind statement. If it has not been added to the DOM, then I'll just bind this.element.bind(....) instead.
The problem is that $('<div>').parent() returns a jQuery object! I was expecting that it would return undefined.
So I'm wondering what parent could it be returning when it shouldn't have a parent?
You may use myDiv.parent().length to know if the jQuery set is empty or not.
But this will yield false positives if the object wasn't removed from the DOM directly but it parent was.
If you want a reliable detection, then, you should use jQuery.contains(document.documentElement, myDiv).
It will always return an object. If you want to see whether anythings in the object, you can check for .length == 0, so $("<div>").parent().length == 0 would be your check.
Check the length of the jQuery object returned. If your div has no parent, the jQuery object returned by .parent will wrap zero elements.
All jQuery DOM searching and manipulation methods return a jQuery collection with 0 or more elements. $("<div>").parent() returns a collection with no elements (an empty collection). You can still call any jQuery method on it, but without being tied to a DOM element what you can do is very limited. It will have .length of zero, and the callback will not be reached when iterating over with .each.
I would check the length of the jQuery object since jQuery will always return an object.
it will be always a parent, can be the body for example
use jquery data for example to set your init marker
var wasInit = ( $(this).data("mypluginwasinit") !== undefined );
if(wasInit) return;
$(this).data("mypluginwasinit","yes");
Given the following code, why does the selector property work in the first instance but not the second? Aren't they both jQuery objects?
<span class='tst'>span</span>
var tst = $('.tst');
console.log(tst.selector);
// prints '.tst'
$('.tst').each(function() { console.log(this.selector);});
// prints undefined
this, in the context of the .each() loop, is not a jQuery object, so the selector property is undefined.
You need to make it a jQuery object first: $(this).selector
However, it should be noted that the selector property will return an empty string while inside the .each() loop.
Edit
If you absolutely need the selector property within the .each(), one option would be to cache your selector:
var cached = $('.tst');
cached.each(function() {
console.log(cached.selector); // Will display ".tst"
});
this != $(this)
In your first case tst is a reference to the jQuery object, but in the second this is simply the corresponding DOM element.
Within an .each() loop the .selector property is not available, however. To access '.tst' you can do $(this).attr("class") (when you use a class selector) -- though if you already use it in the each you can just cache it in a variable before hand.
Note that this will return all of the classes for that elements, so you can parse it later if it has more than one.
The best workaround based on your exact description is this:
var $tst = $(".tst");
$tst.each(function() {
console.log($tst.selector); //prints .tst
});
However I can't see any reason why you really need to do this.
Working Demo http://jsfiddle.net/wA6Yv/ or http://jsfiddle.net/a3CYR/2/
this != $(this)
If you keen: jQuery: What's the difference between '$(this)' and 'this'?
code
var tst = $('.tst');
console.log(tst.selector);
// prints '.tst'
$('.tst').each(function() {
alert($(this).text());
});
// prints undefined
So I tried to build a cache of the DOM:
var DOM = document.getElementsByTagName('*');
However, the DOM variable seems to be a dynamic reference, so that if I change an element in the DOM, the DOM variable changes as well.
I tried iterating through the DOM variable and using the cloneNode method to create a deep copy of each node. This works in that it does not change when I change the DOM. However, the problem is that a cloned node does not equal its original DOM node when you compare them with the === operator.
So to sum up, I'm looking to create a cache of the DOM that does not change but whose nodes are still equal to the original DOM nodes.
document.getElementsByTagName returns a "live" NodeList, which isn't what you think at all. When you access the list, the DOM is traversed (implementation may cache it) every time to get the result. This gives the illusion of the list being live.
document.getElementsByTagName("div") === document.getElementsByTagName("div")
//true
To do what you want, simply convert it to an array. DOM = [].slice.call(DOM)
You seem open to a jQuery solution, so:
$("*")
will return a jQuery object containing all the elements. It will not be updated as the DOM changes.
Or if you just want elements within the <body> (i.e., not <script> or <meta> elements, etc., from the <head>) then:
$("body *")
Being a jQuery object it will of course allow you to access jQuery methods, but you can also access the DOM elements directly with array notation:
var DOM = $("body *");
DOM.show(); // example jQuery method call
alert(DOM.length); // show count of elements in DOM
alert(DOM[4].value) // example of direct access to fifth DOM element
I prefer to use the following methodology:
https://gist.github.com/3841424#file-domcache-js
Or, you may replace the DOM object with a method in this implementation:
var myNS = {
myEventHandler: function(event){
this.DOM.$el.doSomething();
},
cacheDOM: function(){
return {
$el: $("#matrix")
};
},
initialize: function(){
this.DOM = this.cacheDOM();
}
};
I want to be able to see what's inside the tags that jQuery finds. How come the following doesn't work?
$("div.UIImageBlock_Content.UIImageBlock_ICON_Content").each ( function() {
alert(($this).html);
});
What's the right way to do this?
$this => $(this)
.html => .html()
So this should do it:
$("div.UIImageBlock_Content.UIImageBlock_ICON_Content").each ( function() {
alert($(this).html());
});
Note that html() function just uses the innerHTML property, so it can be a lot simpler:
$("div.UIImageBlock_Content.UIImageBlock_ICON_Content").each ( function() {
alert(this.innerHTML);
});
The current element within a jQuery each iteration can be accessed via this (not $this).
There's a small caveat, however: the this in a jQuery iteration refers to each element's underlying DOM object, not the jQuery object. You can use this code, then:
$("div.UIImageBlock_Content.UIImageBlock_ICON_Content").each ( function() {
alert(this.innerHTML);
});
You don't need to build a jQuery object from the raw DOM object on each iteration — an element's inner HTML is already present in the DOM object, and there's no need for extra work.
Like
$(":input")
How do you return each object if there are multiple inputs? Maybe in somekind of array?
Also, is it possible to return the individual objects while using $(":input").after(x) ?
jQuery each
$('input').each(function () {
$(this); // A Single Input
})
Or
$('input')[0]; // HTMLElement Input
Alternatively, jQuery's .get:
supports a little more than [...], e.g. .get(-1) returns the last
element (which can be useful) - pimvdb
How to get length: $('input').length
$('input')
will select all inputs
If you wanted to do something to them...
$('input').each(function(){
$(this).css('background','red')
})
see this http://jsfiddle.net/jasongennaro/RczBh/
the jQuery factory function, jQuery(...selector...) or $(...selector...), returns a jQuery.init object, which is essentially a fancy array of elements.
the each function is a simple way to continue to chain function calls while iterating through the entire selection of elements.
The .each() method is designed to make DOM looping constructs concise and less error-prone. When called it iterates over the DOM elements that are part of the jQuery object. Each time the callback runs, it is passed the current loop iteration, beginning from 0. More importantly, the callback is fired in the context of the current DOM element, so the keyword this refers to the element.
The function parameter has two parameters function( index, element ), you could use i in place of index as it has the same basic effect. this will also refer to the element, so the second parameter is largely unnecessary unless you plan on executing a function within inner scope while retaining the reference to the element.
var vals=[];
$('input').each(function(index,element){
var $this, val;
$this = $(this);
val = $this.val();
vals.push(val);
...do more stuff...
});
console.log( vals );
$(":input") // Returns a collection of DOM elements at 0-based indices wrapped
// in an object that contains jQuery methods
$(":input").length // Is used to discover the quantity of elements matched.
$(":input").after('something') // Implicitly applies .after() to each element.
// Most jQuery methods work this way.
$(":input").each(function() { // Lets you operate on each element individually.
alert( this.nodeName ); // "this" will reference the current element.
});
"Also, is it possible to return the individual objects while using $(":input").after(x)"
If you mean you want a collection of the resulting elements created by .after(), it will depend upon what x is.
If it's a single element (not a text node), just do this:
var new_elems = $(":input").after(x).next();
This places the new element after each input, then uses the next()[docs] method to traverse to the next element sibling of each input, which should be the new element that was inserted.