//this module's functionality is to create instances of slide, //different instances will be easy to control, because everyone has different scope //it's a good practise to write maintainable js code //please refer: https://www.youtube.com/watch?v=OzjogCFO4Zo var SlideModule = (function () { var Slide = function (settings) { this.btns = settings.btns; this.pics = settings.pics; this.picWidth = settings.picWidth; this.container = settings.container; //to set the default value this.span = settings.span || 1000; this.currentIndex = 0; //I call the init function here to make sure the instances work immediately after initialization //but I can also let clients to call this method, if they want to control the behavior, it all depends. this.Init(); } Slide.prototype.Init = function () { $(this.btns[0]).css({ "background": "pink" }) //to change the context because of the closure var that = this; //to bind the callback functions according to the events $.each(this.btns, function (i, btn) { //to bind every button with the corresponding picture $(btn).on("mouseover", function () { that.interval && clearInterval(that.interval); that.currentIndex = i; that.Run(that.currentIndex); }); $(btn).on("mouseout", function () { that.GetNextIndex() }) }); this.GetNextIndex(); } //this function is only responsible to find out the next index of pictures to show Slide.prototype.GetNextIndex = function () { //clear the interval if it exists this.interval && clearInterval(this.interval); //to change the context because of the closure var that = this; this.interval = setInterval(function () { //to ensure the index should be smaller than the length of the buttons(the amount of the buttons and pictures are same) that.currentIndex = ++that.currentIndex >= that.btns.length ? 0 : that.currentIndex; //call the Run function of the current instance that.Run(that.currentIndex); }, this.span) } //this function is the true one to set the layout of the slide. Slide.prototype.Run = function (index) { //to compute the right position every time this.container.css({ "left": -1 * this.picWidth * index + "px" }); //to change the buttons' style this.btns.css({"background":"white"}) $(this.btns[index]).css({"background":"pink"}) } return Slide; }()) //this class is to demostrate inheritance and polymorphism var DerivedSlideModule = (function(){ if(SlideModule.constructor === Function){ var DerivedSlide = function(){ SlideModule.apply(this, arguments) } DerivedSlide.prototype = Object.create(SlideModule.prototype) //to override the same function of the base class DerivedSlide.prototype.GetNextIndex = function(){ this.interval && clearInterval(this.interval); //to change the context because of the closure var that = this; this.interval = setInterval(function () { //to set the every second picture's index that.currentIndex+=2; //to ensure the index should be smaller than the length of the buttons(the amount of the buttons and pictures are same) that.currentIndex = that.currentIndex >= that.btns.length ? 0 : that.currentIndex; //call the Run function of the current instance that.Run(that.currentIndex); }, this.span) }; return DerivedSlide; } return; }()) //in order to write testable and maintainable js code, //I tried to apply OOP principles to JS //abstract the relative class by using function //encapsulate properties in constructor function and inheritable functions to prototype chain //for polymorphism, I overrided the specific function on the prototype chain. $(function () { //to call this function, please make sure the amount of the buttons and pictures are same var slideModule = new SlideModule({ btns: $("#btns > input[type=button]"), pics: $("#container > img"), picWidth: 250, container: $("#container") }); //create an instance of the derived class var slideModule1 = new DerivedSlideModule({ btns: $("#btns1 > input[type=button]"), pics: $("#container1 > img"), picWidth: 250, container: $("#container1") }); })