1
\$\begingroup\$

I'm new to jQuery and JS and have recently tried turning a working slider into a plugin for the first time for a small project. I would love some feedback, code improvement, optimization and any do's/dont's as I know there will be a lot to pick through and I would definitely like to improve on this.

What should I build on from here?

(function($, window, document, undefined) {

    const pluginName = "customSlider";
    const defaults = {
        slideDuration: 4000,
        transitionSpeed: 500,
        pauseOnHover: true
    };

    function CustomSlider(element, options) {
        this.element = $(element);
        this.options = $.extend( {}, defaults, options);

        this._defaults = defaults;
        this._name = pluginName;

        this.startSlide = null;
        this.slideCount = 0;

        this.init();
    }

    CustomSlider.prototype.init = function() {
        const $slider = this.element;
        this.$sliderUl = $slider.find('ul');
        const $slides = $slider.find('li');
        
        this.slideWidth = $slides.width();
        this.slideHeight = $slides.height();
        const sliderUlWidth = this.slideWidth * $slides.length;

        // dynamically set the height and width of the slider
        $slider.css({width: this.slideWidth, height: this.slideHeight});
        this.$sliderUl.css({width: sliderUlWidth, marginLeft: -this.slideWidth});
        
        // prepend last slide.
        this.$sliderUl.children().last().prependTo(this.$sliderUl);

        // preload images before running
        this.preloader($slides);
    }

    CustomSlider.prototype.preloader = function($slides) {
        const slideCache = [];
    
        if (this.slideCount < $slides.length) {
            slideCache[this.slideCount] = new Image();
            slideCache[this.slideCount].src = $slides.eq(this.slideCount).find('img').attr('src');
            slideCache[this.slideCount].onload = function() {
                this.slideCount++;
                this.preloader($slides);
            }.bind(this);
        } else {
            this.startSlide = setInterval(function() {
                this.transitionSlide(true);
            }.bind(this), this.options.slideDuration);
        this.handleEvents();
        }
    };

    CustomSlider.prototype.transitionSlide = function(transitionForwards) {
        var _this = this;
        if (transitionForwards) {
            this.$sliderUl.animate({
                left: -this.slideWidth
            }, this.options.transitionSpeed, function() {
                _this.$sliderUl.children().first().appendTo(_this.$sliderUl);
                _this.$sliderUl.css('left', '');
            });
        } else {
            this.$sliderUl.animate({
                left: +this.slideWidth
            }, this.options.transitionSpeed, function() {
                _this.$sliderUl.children().last().prependTo(_this.$sliderUl);
                _this.$sliderUl.css('left', '');
            });
        }
    }

    CustomSlider.prototype.handleEvents = function() {
        const _this = this;
        var $slider = this.element;

        if(this.options.pauseOnHover) {
            $slider.on('mouseenter', function(){
                clearInterval(this.startSlide);
            }.bind(this));

            $slider.on('mouseleave', function(){
                this.startSlide = setInterval(function(){
                    this.transitionSlide(true);
                }.bind(this), this.options.slideDuration);
            }.bind(this));
        }


        $('.slideButton').on('click', function(e) {
            e.preventDefault();
            $btn = $(this);

            if(!$btn.hasClass('noClick')) {
                $btn.addClass('noClick');
                _this.transitionSlide($btn.hasClass('nextSlide'));

                setTimeout(function() {
                    $btn.removeClass('noClick')
                }, 600);
            }
        });


    }

    $.fn[pluginName] = function ( options ) {
        return this.each(function () {
            if (!$.data(this, "plugin_" + pluginName)) {
                $.data(this, "plugin_" + pluginName, new CustomSlider( this, options ));
            }
        });
    };

    })( jQuery, window, document );

    $(function() {
        $('.customSlider').customSlider({  
            slideDuration: 3000
        });
    });
.customSlider {
  position: relative;
  overflow: hidden;
  margin: 0 auto;
}
.customSlider img {
  max-width: 100%;
  height: auto;
}

.customSlider ul {
  margin: 0;
  padding: 0;
  position: relative;
  list-style: none;
}
.customSlider ul li {
  position: relative;
  display: block;
  float: left;
  margin: 0;
  padding: 0;
}

.slideButton {
  display: block;
  position: absolute;
  top: calc(50% - 22px);
  height: 44px;
  padding: 8px;
  background-color: #222;
  border: 0;
  outline: none;
  color: #FFF;
  font-weight: 500;
  font-size: 20px;
  line-height: 1.4;
  opacity: 0.4;
  cursor: pointer;
  transition: 0.3s ease;
}
.slideButton:hover {
  opacity: 0.8;
}

.prevSlide {
  border-radius: 0 2px 2px 0;
}

.nextSlide {
  right: 0;
  border-radius: 2px 0 0 2px;
}
<div class="customSlider">
<ul>
    <li><img src="https://i.imgsafe.org/66fa2b6b56.jpeg" alt="scenery1"/></li>
    <li><img src="https://i.imgsafe.org/66fa29f43d.jpeg" alt="scenery2"/></li>
    <li><img src="https://i.imgsafe.org/66fa37592b.jpeg" alt="scenery3"/></li>
    <li><img src="https://i.imgsafe.org/66fa416e26.jpeg" alt="scenery4"/></li>
</ul>
<button class="slideButton prevSlide">‹</button>
<button class="slideButton nextSlide">›</button>  
</div>

\$\endgroup\$
2
  • \$\begingroup\$ You do realize that jQuery UI contains a slider plugin, and thus you don't need to write your own. \$\endgroup\$
    – pppery
    Dec 12, 2016 at 1:35
  • \$\begingroup\$ Helpful comment @ppperry. Maybe if you read the description you would have seen I was doing it for a project and as a general learning curve. But thanks \$\endgroup\$
    – joshuaaron
    Dec 12, 2016 at 22:07

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.