> From: Simon Corless
> Thanks for the help Mike, it's starting to come together.
> I've been testing it just now.
>
> If I do use return this.each() then how do I reference the
> jQuery methods? without this.hover() etc? Obviously as this
> is no longer what I am expecting this.hover (as you say)
> fails. So do I use my 'self' variable or another way?
If you are calling each(), that means your plugin may operate on more than
one element, right? If you do "var self = this;" outside the each() call,
that is a reference to the entire jQuery object - an array of all the DOM
elements. The reason you would call each() is to operate on those elements
one by one. So in most cases that 'self' isn't what you want inside the
each() inner function.
In that inner function 'this' is the individual DOM element, so if you want
a jQuery object for that element, use $(this).
Let's try some more descriptive names instead of "self" and "this":
(function( $ ) {
$.fn.twiddle = function() {
var $all = this;
$all.each( function() {
var element = this, $element = $(element);
// Now we have:
// $all - jQuery obect for all matching elements
// $element - jQuery obect for a single element
// element - a single element itself
});
};
})( jQuery );
Now you can write the entire plugin using meaningful names. In practice, I
tend to use shorter names like e and $e instead of element and $element, but
I used the longer ones here to make it more descriptive.
Remember that if the plugin doesn't need to work on the individual DOM
elements but only uses jQuery methods on the whole collection, then you
don't need an each() loop at all.
Contrast a plugin that sets all matching elements to the same random color:
(function( $ ) {
$.fn.twiddle = function() {
var $all = this;
$all.background( randomColor() );
};
})( jQuery );
vs. a plugin that sets each matching element to a different random color:
(function( $ ) {
$.fn.twiddle = function() {
$all.each( function() {
var element = this, $element = $(element);
$element.background( randomColor() );
});
};
})( jQuery );
Note the use of the $ prefix to indicate that a variable is a jQuery object,
and the use of matching names with and without the $ when you have both a
DOM element and a matching jQuery object for that element only. A similar
use of this pattern is:
var $foo = $('.foo'), foo = $foo[0];
This is for typical non-plugin code where you're starting with a query.
Instead of writing code like this:
$('.foo').zip();
// more code
$('.foo').zoom();
// more code
$('.foo').fly();
You'd write:
var $foo = $('.foo');
$foo.zip();
// more code
$foo.zoom();
// more code
$foo.fly();
In this case we're not using any DOM methods, so we only use $foo and not
foo.
> I thought I saw someone just using
> .hover() (without any prefix) but this just fails.
You probably saw code like:
$('.foo')
.zip()
.zoom()
.fly();
That's a single line of code split into multiple lines. It's the same as:
$('.foo').zip().zoom().fly();
> I don't fully understand the difference, currently I don't
> use any dom methods I just use jQuery (I partly thought
> that was the point of it? - Although I realise sometimes
> you need to go deeper).
jQuery doesn't try to provide its own equivalent of every possible DOM
property and method, so it's pretty handy to be able to mix and match when
you need to.
> Basically I have 3 internal functions defined in two ways as:
>
> nextItem = function ()
> or
> function pause()
>
> Am I right in thinking that nextItem() could be called
> through a jQuery chain and that pause() can only be called
> internally from my plugin? Or are they both the same just
> written differently?
Those are just different ways of writing functions - they have little or
nothing to do with how a function can be used.
For example, these are essentially identical, creating functions in the
current scope:
var foo = function(){};
function foo(){}
If I left off the "var", the first one would create a global function:
foo = function(){};
That is usually a mistake, as it is in your code - your nextItem should be
either:
var nextItem = function()...
or:
function nextItem()...
The latter would be more consistent with the rest of your code, so that's
what I'd use.
Another coding tip or two...
You have several places with code like this:
settings['blank']
That's OK, but you can substitute the simpler:
settings.blank
I would change this code:
if (items[i]['link']) {
self.html("<a href=\"\">" + items[i]['item'] + "</a>");
} else {
self.html(items[i]['item']);
}
to:
var item = items[i];
if (item.link) {
self.html('<a href="">' + item.item + '</a>');
} else {
self.html(item.item);
}
Or, even better:
var item = items[i];
self.html( item.link ? '<a href="">' + item.item + '</a>' : item.item );
-Mike
_______________________________________________
jQuery mailing list
[email protected]
http://jquery.com/discuss/