When extending the jQuery prototype (jQuery.fn
), the function you write is given as this
the complete jQuery object passed in, which in this case is the result of $('.carousel')
, i.e. a collection of all elements with the class carousel
. Therefore everything you do involving this
applies to that entire collection.
What you want to do, and indeed what is very common in such cases, is act individually on each element in the collection. To do that, you can use the .each()
function to run the same function on every element. Each time the function is run, this
is set to a single DOM element - not a jQuery object, which is why you need to re-wrap it with $(this)
.
Since the function has its own scope, your use of var $this = $(this)
allows you to create "closures", which carry the particular element around with them. Because it was declared inside the same scope, the function advanceSlide
is such a closure - each time your function runs, new variables are created for both $this
and advanceSlide
.
Make sure you always use $this
, though, as the actual this
variable will be different when the function runs than when it was defined. (The click-handler will set it to the element that was clicked on.) For this reason, it might be better to use a different variable name, say, $carousel
to remember which object it refers to.
Since advanceSlide
is already a local function, you don't need another function() { }
wrapper, just pass it in to the .click()
(or .on()
) call.
So what you end up with is the below, as demoed in this JSFiddle:
$.fn.swapify = function () {
// Here, `this` is a jQuery collection with multiple elements in
this.each(function () {
// Here, `this` is a single DOM node
// using `var`, we make a variable bound to this scope
// while we're at it, we wrap the DOM node with jQuery
// Rather than $this, I've named the variable something meaningful
var $carousel = $(this);
// Declaring a function in the same scope as our var
// creates a "closure", which can always see the scope it was created in
function advanceSlide() {
// When this runs, it will be in response to a click,
// and jQuery will set `this` to the element clicked on
// Our $carousel variable, however, is carried in the closure,
// so we know it will be the container we want
$carousel.find('li:first-child').appendTo($carousel);
}
// A function in JS is just another kind of object,
// so we can pass in advanceSlide like any variable
$carousel.find('li').on('click', advanceSlide);
});
}
$(document).ready(function () {
$('.swapify').swapify();
});