This seems like such a basic question, but I swear I can't see it in the jQuery documentation.
I've inherited some code that does:
$('.tag', true);
The jQuery docs simply say:
jQuery( selector [, context ] )
And 'true' isn't a context in this case. Is this something to do with bubbling? What does 'true' do in a selector, and where does the documentation cover this use case?
Edit: As A. Wolff notes below, this isn't jQuery, it's an alias for document.querySelector & querySelectorAll.
function $(selector, all) {
return base['querySelector'+(all?'All':'')](selector);
}
So $ isn't referring to jQuery but to custom method. Then the true parameter has nothing to do with context. :)
There is actually a significant difference.
Passing true forces the context of the returned jQuery object to be undefined.
$('.tag'), $('.tag', false), $('.tag', 'body') etc will all set the context to be document, the default.
I dont know why the original programmer have had this need for working on elements with no context, and do not dare to guess.
check it out -> console.dir($('.tag', true));
Related
I have some code I am looking at that is using a variation on getElementByID that I do not understand. I have looked online but I am not finding anything that explains this.
I understand how to use something like document.getElementByID("bob"), however what I am looking at says:
if (document.getElementByID){}
When you use getElementByID in this fashion what is it doing?
document.getElementById returns the function which can be used to get some element by ID.
typeof document.getElementById; // 'function'
However, if some browser didn't implement getElementById, you would get undefined.
Therefore, this is just a test to ensure that the method exists before calling it, avoiding an error.
if(document.getElementById) {
// Hopefully it's safe to call it
document.getElementById("bob");
// ...
} else {
alert('What kind of stupid browser are you using? Install a proper one');
}
This will return false:
if (document.getElementByID){}
because there is no getElementByID on the document object. There is however, getElementById (notice the difference in the d at the end).
Therefore, this will return true
if (document.getElementById){}
In short, if getElementByID exists on document, which because of the typing, does not, but if it did then do something.
A more full example using the right spelling:
if (document.getElementById) {
// it is safe to use this method because it exists on document
var element = document.getElementById('foo');
}
document.getElementById returns a function which evaluates to true when in an expression. You can test this out yourself but running the code snippet.
console.log(document.getElementById);
// The !! forces a boolean
console.log(!!document.getElementById);
I used this selector in a function and I don't even know exactly what it means, but it worked - here is my piece of code:
else if($(this).hasClass('list')) {
listItem.stop(true,true).fadeOut(333, function(){
var $this = $(this);
if(listItem.hasClass('grid')) {
$this.find('h1', this).insertBefore($this.children());
}
The ".find()" method only pays attention to one argument, so it means exactly the same thing as
$this.find('h1')
JavaScript doesn't care if you pass too many arguments to a function; in fact there's no such concept as "too many arguments".
You can use a context in the $() function, like this:
$('element', this)
It will then only search among the decendants of the element that this referens to.
It's equivalent to using the find method:
$(this).find('element')
Using find with two parameters is pointless, though. It will only ignore the second parameter.
It is an alternative selector context to be used instead of the document root for the jQuery constructor.
The .find() method will ignore any other arguments than the selector. Its search context node is given as the context of the function call.
Is this phrase always true?
$("p").click(function(event) {
alert( event.currentTarget === this );
});
Is one method preferred over the other? I like to use $(this) instead of event.currentTarget but can one do better in some conditions? Which is better? Are absolutely the same?
And another nuance - When checking on firebug console.log(this) and console.log($(this)) gives me exactly the same element. If they are the same - what is different? (since I know I can write this $(this).css('color','white') but can't write this.css('color','white')
Generally, yes, it will be the same. You can make it different by using $.proxy to manipulate the context, but in practice you probably never will.
$(document.body).on('click', $.proxy(function(e) {
console.log(this); // window
console.log(e.currentTarget); // document.body
}, window));
As to the other question, this is a native DOM element, whereas $(this) is a jQuery object wrapping that DOM element. The jQuery wrapper means you can run jQuery functions such as css, which are not available on native DOM elements.
And, to answer the precise wording of your question, event.currentTarget is normally equal to this, not to $(this).
Part of your answer is above. I hope its clear enough.
No console.log(this) and console.log($j(this)) will not give you the same result. $(this) converts this to a jQuery Object and hence you can call .css like methods which can be called on jQuery objects($(this)) and not the HTML elements which will be this.
This property will typically be equal to the this of the function.
If you are using jQuery.proxy or another form of scope manipulation, this will be equal to whatever context you have provided, not event.currentTarget
Lines 10 - 16 of jquery.effects.core.js:
;jQuery.effects || (function($, undefined) {
var backCompat = $.uiBackCompat !== false; // Irrelevant
$.effects = {
effect: {}
};
})(jQuery); // At end of file
As I understand it, this adds an effects "namespace", but only if it doesn't already exist.
Can someone explain to me:
What is the initial semi-colon for?
What is the purpose of the undefined parameter? Is the meaning of undefined overridden in some way?
What's the difference between adding a function directly to the jQuery object, and adding one to jQuery.fn as recommended in the jQuery documentation?
Finally, if I wanted to create a bunch of jQuery plugins that would only be used by my own team, would it make sense to lump them all under a company namespace using something like the code above?
Edit: I realize now jQuery.effects is probably a bad example. I see jQuery.ui.core.js does it differently:
(function( $, undefined ) {
$.ui = $.ui || {};
// add some stuff to $.ui here
$.fn.extend({
// plugins go here
});
})(jQuery);
But what is the use of the ui object if plugins are added directly to $.fn anyway? Could I define my namespace under $.fn and add all my plugins to $.fn.acme, so that I use them like so: $('something').acme.doStuff()?
Is there a best practice for this sort of thing?
It checks if jQuery.effects exists
If not, it defines a function and calls in the same time
(function() { ... } (jquery), it passes jQuery object for reasons related to scope and conflict and such.
The first line in that function is said to be irrelevant, it seems to be checking a presence of a jQuery plugin property
It defines a placeholder (like namespace or container class) for the effects jQuery plugin property.
So, to your questions:
1 . What is the initial semi-colon for?
I think nothing special. Just ensuring clean statement. This has some edge cases if the last line before this one was a function declaration close.
2 . What is the purpose of the undefined parameter? Is the meaning of undefined overridden in some way?
It just ensures this doesn't happen later. Passes the global object directly. Common pattern I think.
3 . What's the difference between adding a function directly to the jQuery object, and adding one to jQuery.fn as recommended in the jQuery documentation?
It's the way jQuery is structured and general organization issue. The jQuery object is a function and returns an object. The .fn handles registering this one to apply on returned jQuery objects (from jQuery select or so), so, that's better so that jQuery actually knows about your added function.
4 . Finally, if I wanted to create a bunch of jQuery plugins that would only be used by my own team, would it make sense to lump them all under a company namespace using something like the code above?
Most people don't do it. Wouldn't recommend it. Maybe a common "small" prefix is enough.
I mean a wrap function like this:
function $(id) { return document.getElementById(id); }
but in some code like this:
oDiv1 = $("postInfoDiv");
oDiv2 = document.getElementById("postInfoDiv");
alert(oDiv1 == oDiv2); // return false
alert(oDiv1.style); // error
alert(oDiv2.style); // correct
alert(document.getElementById("postInfoDiv").style); // correct
I got strange results as the comments imply.
I thought the first alert should return the true since they are the same dom object.
I thought the second alert should alert something like "object" or "CSS StyleDeclaration" but not "defined".
So what are the problems? Have you ever met this kind of problems?
thanks.
Your $ function is probably being overridden, potentially by a framework.
You should try doing alert( oDiv1.nodeType ) to see if it's a DOM element. alert( oDiv1.length ) to see if it's an empty array because you may be using jQuery on the same page which overrides your $ function.
oDiv1 may be an array-like object containing that item if jQuery is included. oDiv2 is an actual DOM reference. You probably need to compare oDiv1[0] to oDiv1, in which you reference the first element in the array which points to the actual dom element to make a fair comparison.
function $(id){return document.getElementById(id)}
$('content') == document.getElementById('content')
true
The custom $ function will work perfectly but if you're using a framework function it will return that array-like object instead of the DOM element.
You can also rename your function to something like function getID which would be unique and not conflict with framework $s.
My main concern with this is that it will confuse the heck out of someone the first time they read your code, especially if they are used to coding with a JavaScript framework such as jQuery.
For this reason alone I recommend you do not use this particular syntax for your wrap function.
BTW note that even when jQuery is not loaded, Firebug provides its own $ function, which may participate to confusion.