views:

100

answers:

2

Currently I have a jQuery plugin which not only sets up its function in $.fn but also $ itself, checking if (typeof(this) == 'function') to see if it has been called through $.pluginname or $(elm).pluginname... is this bad practice, and if so, is there a better way to make providing the element optional?

+1  A: 

The jquery extend function is exposed on both namespaces:

The jQuery source defines both as:

$.extend = $.fn.extend = ...

This would lead me to believe that they intended for you to be able to do this. However, if you look at the way the jQuery authors have set up their own functions to use both, you may get a better idea of the best practice.

For instance, you would normally want the $.fn function to call the $ function. (Much like the $.data function in the jQuery source)

$.extend({
  data: function(elem, key, value) {...}
});

and (a bit simplified):

$.fn.extend({
  data: function(key, value){
    return this.each(function(){
      $.data(this, key, value);
    };
  }
});

This way, one calls the other and takes care of the check for which version you are using, and if you wanted to, you could just check for an undefined 'elem' param in the $ namespace.

Alex Sexton
The thing is, when I tried calling $.pluginname without attaching it to the jQuery object, Firebug told me that it was not a function.
a2h
You have to specifically attach it to the jQuery object like I showed above, and then write a plugin in the $.fn namespace that shortcuts each element into the function on the $ namespace.jQuery.staticPlugin = function(elem, options) {}andjQuery.fn.plugin = function(options){ return this.each(function(){ $.staticPlugin(this, options); }); };
Alex Sexton
What I currently have is $.fn.pluginname = function() { /* */ } and after that $.pluginname = $.fn.pluginname
a2h
That causes you to have to do the silly typeof x === "function" stuff in order to see which version you are using. If you notice, in the current accepted answer, the $.log function they create is not the same as what you asked, because it does not connect to both the plugin architecture and the $ namespace. The jQuery source, however, does address your issue in the manner I have stated. It is the preferred way to manage static functions that also double as plugins by virtue of its use in the jQuery source.
Alex Sexton
OK, so your answer now seems to make more sense, and I've set it to accepted. However, I'm still trying to get my head around the whole concept right now...
a2h
Its a bit scary, but check out the current jquery 1.3.2 source and check out lines 1274 and 1368. The first one (1274) defines the data function on the $ namespace. Its first parameter is the element. In your function, you could make a check to see if the 'elem' variable exists in order to know which version to run. Then on 1368, the data function is defined on the $.fn namespace. That function USES the first function in order to get its job done by passing in its inherit element(s) (which are contained in 'this') into the original $ level function.
Alex Sexton
Is it preferable to define the actual function itself in the $ object or $.fn?
a2h
It is preferable to define on the $ object, and then call that function with a preloaded elem in $.fn - It wouldn't work the other way around because $.fn works on elements, specifically.
Alex Sexton
+2  A: 

Have you had a read through the jquery authoring docs? The log function in the example is considered the standard way of adding functions to the jquery object for developers.

Steerpike
So it isn't bad practice and is actually something many plugin authors do?
a2h
Yes. This is how plugins are built.
Lance Fisher
Hah, looks like I didn't notice that. Silly me >_<
a2h