JavaScript vs jQuery Selector - javascript

I was wondering what the difference between jQuery selectors $("#fake-div) and JavaScript selectors getElementById("fake-div"). First, are these even called JavaScript selectors?. I know jQuery returns the jQuery object whereas JavaScript selectors returns the DOM element; however, given these two blocks of code:
jQuery Selector
var post = $("#postid");
var reply_list = post.find(".replies_ul");
var current_reply = document.createElement("li");
current_reply.setAttribute("class", "reply_li");
reply_list.insertBefore(current_reply, reply_list.firstChild);
JS Selector
var content_list = document.getElementById("content_ul");
var current_post = document.createElement("li");
current_post.setAttribute("class","content_li");
content_list.insertBefore(current_post, content_list.firstChild);
The jQuery Selector ends up removing the list from the DOM when the last line of code is called, and the JavaScript selector successfully inserts the list item at the top of the list. I'm looking for an explanation as to what is going on.

The jQuery insertBefore in your code is invalid, it takes two arguments whereas the jQuery accepts only one:
.insertBefore( target )
Description: Insert every element in the set of matched elements before the target.
And the normal one:
Node.insertBefore
Description: Inserts the specified node before a reference element as a child of the current node.
parentElement.insertBefore(newElement, referenceElement)

The difference is not on the selector but on the method / function that you are calling.
You are using the jQuery insertBefore function and comparing it with the javascript insertBefore function.
In jQuery the insertBefore function has only one parameter and therefore you are using it wrong.
If you want to make use of the Javascript function insertBefore instead of the jQuery one, then you have to convert your jQuery object reply_list to a Javascript one.
You can do this by using .get(0) or [0] like so:
reply_list[0].insertBefore(current_post, content_list.firstChild);
//or like this
reply_list.get(0).insertBefore(current_post, content_list.firstChild);

In your first block of code, the reply_list is a jQuery object; meaning it doesn't actually have a .firstChild property.
Change it to this:
reply_list.get(0).insertBefore(current_reply, reply_list.get(0).firstChild);
Please note the differences between jQuery's insertBefore and JavaScript's insertBefore

Related

why does $('el')[0].className work but not $('el').className?

I noticed that className property doesn't work inside jQuery without the index, why is that?
Also, are there other common JS properties / methods that don't work as expected inside jQuery?
HTML:
<div class="par">test</div>
JQuery:
$(function () {
var el = $('.par');
el.className += ' new class'; // doesn't work
el[0].className += ' new class'; // works
});
var el = $('.par'); returns a jQuery object. className is a property on Element and not on jQuery object.
The jQuery object has an array like definition so el[0] returns the underlying Element which has className property.
As far as I know, jQuery doesn't like developer updating its property directly. It simply exposes variety of utility functions for easy developement.
Quoting on a nice comment from David Thomas below,
jQuery methods can only be used on jQuery objects; native DOM properties/methods can only be used on native DOM nodes
Note: var el = $('.par'); returns a collection of Element and el[0] returns the first element in that list.
You could use .addClass to add a class to the element.
To the first element,
el.eq(0).addClass('new_class');
To all elements,
el.addClass('new_class');
More Reading:
https://developer.mozilla.org/en-US/docs/Web/API/element
https://developer.mozilla.org/en-US/docs/DOM/element.className
var el = $('.par');
gives you a jQuery object, which may contain one or more DOM elements.
var el = $('.par')[0];
returns the first DOM object in the selection of that jQuery object. className is a property on a DOM element, not on a jQuery object
$('.par').attr('class');
would be the jQuery way to get the className of the first element.
If you just want to add a particular class to elements matching another class, you can use
$('.par').addClass('testclass');
This will add the test class to all elements with the par class, while your method will only add it to the first element on the page.
Other properties
Also, are there other common JS properties / methods that don't work as expected inside jQuery?
Most dom properties will not work directly on a jQuery object. You can use [0] to get the raw dom element for the first matched element for those. However most of them also have straightforward equivalents in jQuery. The advantage of using the jQuery versions is that they're often simpler, and work consistently across browsers. Native dom properties tend to be faster to access though.
className is part of the api for a DOM element.
var el = $('.par'); will return a jQuery object with an array of elements.
Using el[0] accesses the first element which has access to the api.
jQuery provides an easy method for adding classes to an element or group of elements matched by a selector called addClass. You could use this:
var el = $('.par');
el.addClass('new class');
Also note that it is usually best practice to name variables which contain a jQuery object with $ like this:
var $el = $('.par');
The jQuery DOM object is actually a list of matching elements. Since you're setting a variable on a list of DOM elements, jQuery can't apply them to the entire list. el[0] is the first matched element. (If you have more than one element, using el[0] will only set the first matched element, and if there aren't any matches, el[0] will raise a ValueError.) You should probably use jQuery's builtin class manipulation functions:
el.addClass("new class");
to remove the classes:
el.removeClass("new class");
and to toggle them:
el.toggleClass("new class");
This might not be directly related to the question, but if you're working with jQuery, then you should also be using jQuery's easy to use methods to modify the classname's of all DOM elements within a jQuery object.
http://api.jquery.com/addClass/
http://api.jquery.com/toggleClass/
http://api.jquery.com/removeClass/
$(function () {
var cname = $('.par').attr('class'); // get class attribute
if (!$('.par').hasClass('some-new-class')) {
$('.par').addClass('some-new-class');
}
});

JQuery select by ID vs document.GetElementByID

I'm just starting with JQuery and am working through a tutorial vid. At one point the presenters go for javascript instead of a JQuery selector. Just wondering why the javascript getElementById below works fine when passing an object to a function, but the second one doesn't?
Thanks!
// works
addTask(document.getElementById('taskText'), evt);
// doesn't
addTask($('#taskText'), evt);
getElementById() returns a DOM element reference.
jQuery's selector returns a jQuery object. You can get the element reference from the jQuery object using
$('#taskText').get(0);
See http://api.jquery.com/get/
To add to the other answer, regarding the result, if you want to use jQuery (which is easier to read), you can get the dom node directly like so:
addTask($('#taskText')[0], evt);
$('#taskText') returns a jQuery object reference.
document.getElementById('taskText') returns a DOM element reference.
If your addTask() function doesn't know how to convert them to what it needs, then that would be the issue since one of them will need a conversion.
If you want to get the first DOM element reference from the jQuery object, you can do so with this:
$('#taskText').get(0)
So these two should be identical:
$('#taskText').get(0)
document.getElementById('taskText')
Both are not exactly same
document.getElementById('taskText'); //returns a HTML DOM Object
var contents = $('#taskText'); //returns a jQuery Object
var contents = $('#taskText')[0]; //returns a HTML DOM Object
so you have to change it to get HTML Dom Object
addTask($('#taskText')[0], evt);
As #Phil and #jfriend00 have pointed out, document.getElementById('taskText') is a DOM element, and $('#taskText') is a jQuery object. The latter is an object of all DOM elements that match the selector.
Think of it as a zero based array, you could pass in the DOM element by doing this:
addTask($('#taskText')[0], evt);

jQuery object and DOM element

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.

How i can do this in jQuery? any trick to pass selector instead of jQuery object in $

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

jQuery replaceWith find new element

I'm writing a script to replace some images with divs in jQuery. I'm currently using the replaceWith() method, which works fine, but returns the original (removed) element instead of the new element.
The .replaceWith() method, like most
jQuery methods, returns the jQuery
object so that other methods can be
chained onto it. However, it must be
noted that the original jQuery object
is returned. This object refers to the
element that has been removed from the
DOM, not the new element that has
replaced it.
How can I get a reference to the new DOM element I just created?
$.fn.replaceWithPush = function(a) {
var $a = $(a);
this.replaceWith($a);
return $a;
};
See a working demo
I believe replaceAll() returns the new content. It has the target and source reversed from replaceWith().
var newobj = $( "<p>New paragraph" ).replaceAll( "#replaceme" );
Precede your call to replaceWith() with a jQuery call to find the parent node and then use the parent to find the new node that was inserted with the replaceWith() function.
Here's an example inside the success handler of a $.ajax() function that replaces a form:
success: function(data,textStatus,jqXHR){
var $li=$form.parents('li');
$form.replaceWith(data);
var $form=$li.find('form');
//...
},
In this example, there was a unique form for each li. You may need to tailor your approach depending on how you construct your DOM.

Categories

Resources