I'm writing simple slider for my website. This slider contains list items. I want to use OOP approach.
My actual code:
var miniSlider = function(objId)
{
this.obj = $("#" + objId);
this.obj.settings = [];
this.obj.settings['items'] = $('ul li', this.obj).length;
this.pagerNext = this.obj.find("i.next");
this.pagerPrev = this.obj.find("i.prev");
this.pagerNext.on("click", function() {
alert(this.obj.settings['items']);
});
};
I can invoke a few other sliders (yes, that's why I introduced a class):
miniSlider("mini-slider");
The problem is that when I'm in jQuery this.pagerNext.on("click", function() { }); this is no longer my object but - it's become a clicked element. How can I access this.obj.settings after click in a well done way (and with multi sliders support)?
EDIT:
Here is a full code created with a cooperation with SOF community :)
var MiniSlider = function(objId)
{
this.obj = $("#" + objId);
this.obj.settings = {
items: $("ul li", this.obj).length,
autoChangeTime: 8000
};
this.obj.activeElement = null;
this.pagerNext = this.obj.find("i.next");
this.pagerPrev = this.obj.find("i.prev");
var self = this;
this.pagerNext.on("click", function() {
self.obj.activeElement = $('li.active', self.obj);
if(self.obj.settings.items > 0)
{
if(self.obj.activeElement.is(':last-child'))
{
$('li.active', self.obj).removeClass('active');
$('li', self.obj).first().addClass('active');
}
else
{
self.obj.activeElement.next().addClass('active').prev().removeClass('active');
}
}
});
this.pagerPrev.on("click", function()
{
self.obj.activeElement = $('li.active', self.obj);
if(self.obj.settings.items > 0)
{
if(self.obj.activeElement.is(':first-child'))
{
self.obj.activeElement.removeClass('active');
$('li', self.obj).last().addClass('active');
}
else
{
self.obj.activeElement.prev().addClass('active').next().removeClass('active');
}
}
});
this.obj.parent().on('mouseenter mouseleave', function(e) {
if (e.type == 'mouseenter')
{
$(this).addClass('stop');
}
else
{
$(this).removeClass('stop');
}
});
setInterval(function() {
if(self.obj.settings.items > 0 && !self.obj.parent().hasClass("stop"))
{
self.pagerNext.click();
}
}, this.obj.settings.autoChangeTime);
};
and invoke:
new MiniSlider("mini-slider");
Alex gave you the solution to the
this
problem in your callback, but there is another problem in your code.You are calling the
miniSlider()
function without anew
operator:That means that inside the function,
this
is not a unique object, but is actually thewindow
object!You need to use the
new
operator to create an individual object for each call:But you should also change the name of this function to follow the JavaScript convention that constructors begin with a capital letter. Call it
MiniSlider
and use it like so:If you follow this convention (which most experienced JavaScript programmers do), it will help you remember when to use
new
. If the function begins with a capital letter, it's a constructor and you need to usenew
with it. Otherwise, you don't.If you'd like to be able to use your constructor without
new
, that is also possible with a bit more code, e.g.:But generally people don't bother with that and just use the initial capital letter on the constructor as a reminder to use
new
.Also, as a suggestion, I like to use a meaningful name when I save
this
in a variable, and then I use that name consistently instead of usingthis
at all. Doing it this way it might look like:Why do I prefer that approach over using
this
in most places and another variable likeself
where you need it? This way I don't have to remember which to use: I can always useslider
in the code instead ofthis
. (Of course you could useself
or any other name; I just like to have a more meaningful name if I'm going to the trouble of making up a name at all.)Another minor problem in the code is in these two statements:
You shouldn't use an
Array
when you are going to be giving it named properties like this. Use anObject
instead. Arrays should only be used when you have numeric indexes like 0, 1, 2, etc. And with an object literal you can set the property at the same time:Also, when you use that property:
you can write it more simply as:
Either way it does the same thing.
Save a reference to this in a local variable, and use that variable instead of
this
in the nested function.