Ok, so as i am working on a development project, i started doing my normal object reference acquisition var obj = $(".selector"); but then noticed that when i tried to operate on this reference it was not the root object.
Currently have JQuery 2.1 & JQuery UI 1.10.4 in the link folder.
Any explanation as to why i have use the Index 0 to get a reference to the html control?
The jQuery selector returns a jQuery QuerySet object, which includes the set of results matching the query. It also allows you to call jQuery functions on the result, such as .text(), .addClass(), etc., instead of using the JavaScript DOM API.
As for why elements are accessible through indexing (vs, say, a property called domElement or something): remember that jQuery selector queries can return multiple elements. Imagine, for example, if you had multiple elements with the class "selector". Then wnd[0] will return the first matching DOM element, and wnd[1] will return the second matching DOM element.
Related
I'm learning Javascript right now, and attempting to change the text title of a particular tab. It's actually part of a larger Shiny dashboard project, but I want to add some custom functionality to a few tabs. Below are the tabs in question:
Simple enough. I first access my tabs in my Javascript file:
var tabScrub2 = $(document).find('[data-value="scrubTab2"]');
console.log(tabScrub2);
When I use Firefox's developer console, I see that the tab is an object:
Moreover, it looks like I need to change the innerText property of 0, whatever this is, since that corresponds to the title of my tab (the innerText of 1 corresponds to the text inside scrubTab2). However, I'm not familiar with the actual object type being returned here:
Simply put, how the heck do I access and manipulate properties from this? And am I actually accessing an array? When I type in
var scrub2 = tabScrub2["1"];
console.log(scrub2);
I get an HTML element. I'm seen the a element in CSS and jQuery, but am not super familiar with how to manipulate its properties programmatically? How do I go about accessing and manipulating the innerText properties of this via Javascript? For instance, how would I hide scrubTab2, or change its title to something else?
The first object you're seeing is jQuery's wrapper around the real DOM elements. It's not an actual array, but it does contain all of the elements that matched your query under zero-indexed properties (e.g. "0" and "1") which allows you to access to them via an array-like API (e.g. tabScrub[1]).
Your method of grabbing a node using tabScrub2["1"] is correct (see this question in the jQuery FAQ). It's more likely to see that done with a numeric key though (i.e. tabScrub[1]) because that matches the way you would access an element in a normal array.
As far as manipulating properties of the DOM node, the DOM's API is notoriously inconsistent and quirky (hence the need for things like jQuery in the first place). However, for your use case you can just assign a string to the innerText property directly (e.g. tagScrub2[1].innerText = "Tab title"). MDN is a great resource if you're looking for reference material on other parts of the DOM.
A side note: if you're looking for a specific element you should use a query that will only match that element. It's generally a bad sign if you're grabbing extra elements and then accessing the element you want at a key other than 0. If you're doing this then your code depends on other (potentially unrelated) nodes in the DOM existing before your node, and if/when you change those nodes your original code will break.
Just use jQuery eq method to get the relevant object index from the array.
For an example
//Query and get first element.
var tabScrub2 = $(document).find('[data-value="scrubTab2"]:eq(0)');
//Hide
tabScrub2.hide();
//Change title
tabScrub2.attr("title", "New Title Text");
Lean more about jQuery eq here.
https://api.jquery.com/eq/
Since you use jquery selectors tabScrub2[0] returns the native DOM element instead of another jQuery object. Therefore the hide function won't work in that object since the native DOM element doesn't implement such type of functionality for an element. That's why you have to use jQuery pseudo selector as above. Because hide will only work with a jQuery object.
When you want to get the HTML of an entire DOM element (wrapper included), you can do the following (as explained here):
$('#myElementId')[0].outerHTML
But what you can't do is call outerHTML on $(this) inside e.g. a click listener or selector function body scope:
$(this).outerHTML //Doesn't complete in IntelliSense, returns undefined in browser
or
$(this)[0].outerHTML //Correction, this DOES work, but it doesn't complete in IntelliSense
because IntelliSense won't show innerHTML or outerHTML in those circumstances, although with vanilla JavaScript you can do:
document.getElementById($(this).attr('id')).outerHTML
So... what's up with that?
outerHTML is a DOM property; jQuery doesn't expose all DOM properties.
If you have a jQuery object, you can only directly access those properties and methods that jQuery exposes, and vice versa for DOM objects.
In object-oriented terms, jQuery objects don't inherit from DOM objects, they contain them.
Saying $x[0] gets you the DOM object for the first element represented by a jQuery object.
You can use directly this to access outerHTML of the current object instead of indirectly going through $(this) as this represents the DOM object (which has outerHTML property) whereas $(this) represents jQuery object.
this.outerHTML
jQuery selector returns an array-like jQuery object which has no outerHTML property.
However, the jQuery resulting array contains DOM elements.
It means that you can actually access it this way.
$(".someClass")[0].outerHTML // it works for me
Update:
It works for me in every browser.
I can access array-like jQuery object in a click event handler as well.
$(".someClass").click(function()
{
alert($(this)[0].outerHTML); // it works me too
});
Here is my JSFiddle: http://jsfiddle.net/13btf60p/
Update 2:
OK, now I get your question. It should have worked.
Do you really need an IntelliSense to complete such a plain and simple construction?
I will add what I found to be the correct solution to what ended up being a simple flaw in the default Visual Studio settings for future reference.
Since I didn't want to let this go, I searched further and found out that, by default, jQuery IntelliSense is somewhat deplorable out of the box in Visual Studio 2013.
Under
Tools > Options > Text Editor > Javascript > IntelliSense > References
I set
Reference Group: "Implicit (Web)"
and added an existing jQuery file. This solved all issues of my question and IntelliSense now suggests all members and methods correctly, although this should have simply worked out of the box instead of costing everyone a bunch of time.
this.outerHTML is enough.
If you use getElementById maybe you can use:
var table = document.getElementById('blablabla');
I am migrating my code to jQuery from mootools. There is a line of code that uses mootools '$$' to get an array of elements with the given selectors
var myMenu = $$('#outerDiv .menu');
I have tried jQuery('#outerDiv .menu') but it doesn't return an array.
Is there a way to use '.find()' from jQuery on the whole document ? (since I don't have a parent element to make it like parent.find().)
The closest jQuery equivalent to Mootools' $$ would be calling .get() on a jQuery object:
var myMenu = jQuery('#outerDiv .menu').get();
From jQuery.fn.get docs:
Without a parameter, .get() returns all of the elements [...]
All of matched DOM nodes are returned by this call, contained in a standard array.
When using jQuery though, you usually don't do this very often as the returned elements array won't support any jQuery method. Remember that jQuery handles iteration over DOM collections and methods chaining out of the box.
I would like to understand relationship between jQuery object and DOM element..
When jQuery returns an element it shows up as [object Object] in an alert.
When getElementByID returns an element it shows up as [object HTMLDivElement]. What does that mean exactly? I mean are both of them objects with a difference ?
Also what methods can operate on jQuery object vs DOM element? Can a single jQuery object represent multiple DOM elements ?
I would like to understand relationship between jQuery object and DOM element
A jQuery object is an array-like object that contains DOM element(s). A jQuery object can contain multiple DOM elements depending on the selector you use.
Also what methods can operate on jQuery object vs DOM element? Can a single jQuery object represent multiple DOM elements ?
jQuery functions (a full list is on the website) operate on jQuery objects and not on DOM elements. You can access the DOM elements inside a jQuery function using .get() or accessing the element at the desired index directly:
$("selector")[0] // Accesses the first DOM element in this jQuery object
$("selector").get(0) // Equivalent to the code above
$("selector").get() // Retrieve a true array of DOM elements matched by this selector
In other words, the following should get you the same result:
<div id="foo"></div>
alert($("#foo")[0]);
alert($("#foo").get(0));
alert(document.getElementById("foo"));
For more information on the jQuery object, see the documentation. Also check out the documentation for .get()
When you use jQuery to obtain an DOM element, the jQuery object returns contains a reference to the element. When you use a native function like getElementById, you get the reference to the element directly, not contained within a jQuery object.
A jQuery object is an array-like object that can contain multiple DOM elements:
var jQueryCollection = $("div"); //Contains all div elements in DOM
The above line could be performed without jQuery:
var normalCollection = document.getElementsByTagName("div");
In fact, that's exactly what jQuery will do internally when you pass in a simple selector like div. You can access the actual elements within a jQuery collection using the get method:
var div1 = jQueryCollection.get(0); //Gets the first element in the collection
When you have an element, or set of elements, inside a jQuery object, you can use any of the methods available in the jQuery API, whereas when you have the raw element you can only use native JavaScript methods.
I just barely started playing with jQuery this last month, and I had a similar question running around in my mind. All the answers you have received so far are valid and on the dot, but a very precise answer may be this:
Let's say you are in a function, and to refer to the calling element, you can either use this, or $(this); but what is the difference? Turns out, when you use $(this), you are wrapping this inside a jQuery object. The benefit is that once an object is a jQuery object, you can use all the jQuery functions on it.
It's pretty powerful, since you can even wrap a string representation of elements, var s = '<div>hello <a href='#'>world</a></div><span>!</span>', inside a jQuery object just by literally wrapping it in $(): $(s). Now you can manipulate all those elements with jQuery.
Most jQuery member Functions do not have a return value but rather return the current jQuery Object or another jQuery Object.
So,
console.log("(!!) jquery >> " + $("#id") ) ;
will return [object Object], i.e. a jQuery Object which maintains the collection which is the result of evaluating the selector String ("#id") against the Document,
while ,
console.log("(!!) getElementById >> " + document.getElementById("id") ) ;
will return [object HTMLDivElement] (or in fact [object Object] in IE) because/if the return value is a div Element.
Also what methods can operate on jQuery object vs DOM element? (1) Can a single jQuery object represent multiple DOM elements ? (2)
(1) There is a host of member Functions in jQuery that pertain to DOM Objects. The best thing to do imo is search the jQuery API documentation for a relevant Function once you have a specific task (such as selecting Nodes or manipulating them).
jQuery documentation
(2) Yes, a single jQuery Object may maintain a list of multiple DOM Elements. There are multiple Functions (such as jQuery.find or jQuery.each) that build upon this automatic caching behaviour.
That's just your browser being clever. They're both objects but DOMElements are special objects. jQuery just wraps DOMElements in a Javascript object.
If you want to get more debug info I recommend you look at debugging tools like Firebug for Firefox and Chrome's built-in inspector (very similar to Firebug).
Besides what has been mentioned, I'd like to add something about why jQuery object is imported according to description from jquery-object
Compatibility
The implementation of element methods varies across browser vendors and versions.
As an example, set innerHTML of element may not work in most versions of Internet Explorer.
You can set innerHTML in jQuery way and jQuery will help you hide the differences of browser.
// Setting the inner HTML with jQuery.
var target = document.getElementById( "target" );
$( target ).html( "<td>Hello <b>World</b>!</td>" );
Convenience
jQuery provides a list of methods bound to jQuery object to smooth developer's experience, please check some of them under http://api.jquery.com/. The website also provides a common DOM manipulation, let's see how to insert an element stored in newElement after the target element in both way.
The DOM way,
// Inserting a new element after another with the native DOM API.
var target = document.getElementById( "target" );
var newElement = document.createElement( "div" );
target.parentNode.insertBefore( newElement, target.nextSibling );
The jQuery way,
// Inserting a new element after another with jQuery.
var target = document.getElementById( "target" );
var newElement = document.createElement( "div" );
$( target ).after( newElement );
Hope this is a supplement.
In JavaScript if I append a child which has an ID to another place then it's removed from original location where they currently are.
In javascript I have an event where I can get selector by using this inside the function
$('.').event(function(){
this
});
This is passed to another function and they work fine. Now I want to pass the clone instead of the object; and remember that this does not have ID.
The old code works by passing this to function as DoSomething(this)
if I make a clone using jQuery clone then I have the jQuery object. So how do I get a reference to this instead of the jQuery object when working with the clone?
var clone = $(this).clone() // this is jQuery object.
//how do I get this out of clone?
if I append a child which has an ID to another place then it's removed from original location where they currently are.
Yes, but the same is true of a child node that doesn't have an id attribute as well. An id is only an easy way for you to get a reference to the Element node object; it makes no difference to DOM insertion of cloning behaviour.
In javascript I have an event where I can get selector by using this inside the function
No, this in an event handler gives you the DOM Element node object, not a selector string. A Node can be turned into a jQuery wrapper around it using $(node) and a selector can be turned into a jQuery wrapper on the list of matching nodes using $(selector) but other than this overloading in the jQuery API they're completely different animals.
To pull a Node back out of a jQuery wrapper you can use the get() method or simple array-like access:
var clonedNode= $(this).clone()[0];
var clonedNode= $(this).clone().get(0);
to taste. (get() has some extra features which you don't need here.)
To get the selector used to create a jQuery wrapper you can use the selector property, but this won't return anything if the wrapper was created from a node object ($(this)) rather than a selector.
$(this).clone().get(0). This will get the first matching DOMElement from the jQUery object.
To get the DOMElement object from a jQuery object use get(0):
var clone = $(this).clone(); // this is jQuery object.
var el = clone.get(0); // this is DOMElement object