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.
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);
If you cache a var:
var something = $('#something');
I have seen that being used later as:
$(something).doAction();
something.doAction();
Is there a difference in using either? I have started using something.doAction() as it looks cleaner and easier to read. But I'd like to know if this could cause any problems?
$(...) returns a jQuery object.
If you put a jQuery object in a variable, the variable will still hold a jQuery object in it when you check on it later, just like anything else you might put in a variable.
No magical gremlins will come and get rid of the jQuery object behind your back.
(unless you accidentally put something else in the variable elsewhere)
This has nothing to do with jQuery. This is just a fundamental of Javascript.
var x = foo();
x.something();
Is of course the same as foo().something(). Go study programming or Javascript until this makes sense.
something is a jQuery object and there is no need to put it in brackets with dollar sign as this: $(something)
jQuery selectors return jQuery objects, which is case here $('#something').
Good naming practice would be to name something as $something, so you know that variable contains jQuery object.
Also good use of $(..) example, would be wrapping html as string to get jQuery object, like this:
$divObject = $('<div>Some text</div>');
$divObject.text(); // value is 'Some text'
There is just hold this a jquery object to use it later or avoid repetition.
var $button = $('#button');
$button.click(function(){
//some code here
});
//now applying some style to it
$button.css({color:"#ccc",background:"#333"});
Or could be replace with
var $button = $('#button').css({color:"#ccc",background:"#333"});
$button.click(function(){
//some code here
});
Or
$('#button').css({color:"#ccc",background:"#333"}).click(function(){
//some code here
});;
Update:
Sometimes if you look for a button, jquery will return you the button, not the object so to edit or do some action you pass it as argument to the jquery constructor.
Here a little example. You are just looking for the button and jquery returns that button but if you need to apply some style,event, etc,etc, you would need to pass it as argument to the jquery contructor ($ or jQuery). And here another without the constructor that does not work
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 have a potentially strange question about this and jQuery plugins
As I understand it, the following is a very basic jQuery plugin:
$.fn.clickclone = function(param){
return this.click(function(){
param.apply(this);
});
};
(pretending that's a plugin that somehow extends click().)
So, if I pass a function as an argument, it does what it needs to do and properly accesses this as a DOM node. Easy.
That's all clear to me.
What's not clear is, is there any way I could pass a non-function argument to the plugin and have it properly access this from the arguments? ie, could I configure the plugin to do something like this:
$("#foo").pluginname(["foo", $(this).text() ]);
Such that for:
Bar
It would properly pass an array to the plugin, with the second item in the array returning the value Bar?
I'm doing this, basically, to provide syntactic sugar for my plugin, where you can pass an array as a shortcut (in addition to using a normal callback function as the main functionality). Except, doing that, I lose access to use of this. Hence my dilemma.
EDIT: This is evil, but, it seems like one work around is to pass the argument as a string and then eval it. Not a workable solution for me, but, it illustrates what I'd like to be able to do:
$.fn.clickclone = function(param){
return this.click(function(){
if(typeof param === "function"){
param.apply(this);
}
else if(typeof param[1] === "string"){
console.dir("This is evil: " + eval(param[1]));
}
});
};
There's no general way to do this without a function, since, in the purely mathematical sense, you are asking for a function of the input (that is, a function of this): something that depends on this in a certain way.
You could perhaps hack it with strings, like so, but you lose the flexibility of functions:
$.fn.alertMe = function (methodToAlert) {
alert(this[methodToAlert]());
};
// usage:
$("#foo").alertMe("text");
$("#foo").alertMe("width");
And if you find using a function acceptable but the this syntax confusing, you can simply do the following:
$.fn.alertMe = function (alertGetter) {
alert(alertGetter($(this));
};
// usage:
$("#foo").alertMe(function (x$) { return x$.text(); });
$("#foo").alertMe(function (x$) { return x$.width(); });
And for completeness I guess I should mention you could probably get away with an eval-based solution, looking something like $("#foo").alertMe("$(this).text()"), but eval is evil and I will neither write up nor condone such a solution. EDIT: oh, I see you have done so in an edit to your original post. Good job corrupting future generations ;)
I have been wondering how I can create functions like jQuery. For example: $(ID).function()
Where ID is the id of an HTML element, $ is a function that return the document.getElementById reference of the element "ID" and function is a custom javascript function.
I'm creating a little library which implements some functions. And I want to use that sintax without using jQuery.
Now, my questions are: how I can implement that? What is the name of the tecnique that allow that?
Edit:
What I want to do is this:
HTMLElement.prototype.alertMe = function() {alert(this.value);}
Then, when I call document.getElementById('html_input_id').alertMe(), it must show an alertbox with the input value. But HTMLElement.prototype doesn't work in IE.
$ = function(id) {
return document.getElementById(id);
}
Okay, look, what you're asking has a lot of details and implications. The code for jQuery is open source, you can read it for the details; you'd do well to find a good Javascript book as well, the the O'Reilly Definitive Guide.
$ is just a character for names in JS, so as some of the other answers have shown, there's no reason you can't just write a function with that name:
var $ = function(args){...}
Since everyone and his brother uses that trick, you want to have a longer name as well, so you can mix things.
var EstebansLibrary = function(args){...}
var $ = EstebansLibrary; // make an alias
Since you end up doing different things with the entry point function, you need to know how JS uses arguments -- look up the arguments object.
You'll want to package this so that your internals don't pollute the namespace; you'll want some variant of the module pattern, which will make it something like
var EstebansLibrary = (function(){
// process the arguments object
// do stuff
return {
opname : implementation,...
}
})();
And you'll eventually want to be prepared for inheritance and that means putting those functions into the prototype object.
You can use prototype to assign a new function to the Element prototype.
Element.prototype.testFunction=function(str){alert(str)};
This would provide the function 'testFunction' to all HTML elements.
You can extend any base Object this way, i.e. Array, String etc.
This will work without any plugin at all - although that said I don't think it will work in IE. I believe libraries such as MooTools and jQquery create their own inheritance with DOM elements to ensure cross-browser compatibility, although don't quote me on that.