0

I am trying to practice different module patterns. Below is IIFE pattern for a scroll function that can be used for different elements in different pages (not sure this is the right pattern for the purpose).

My question is 1. how to replace the config = {} options outside IIFE module? 2. I name every single functions, not sure if this is an overkill or suggested way in write this kind of code. 3. What would be a better module pattern for the purpose?

  ;(function($, ScrollToTop, undefined) {
    'use strict';

    var clickedElem = $('[data-scroll]');
    var config = {
      scrollDistance: 500,
      speed: 300
    };

    var _scrollToTargetAnimation = function () {
      $('body').animate({
        scrollTop: $($(this).data('scroll')).offset().top
      }, config.speed);
      return false; //stop bubbling
    };

    var _showHideAnimation = function () {
        if ($(this).scrollTop() > config.scrollDistance) {
          clickedElem.fadeIn(config.speed);
        } else {
          clickedElem.fadeOut(config.speed);
        }
    };

    ScrollToTop.showHide = function() {
      if ($('.top-bar').length) return;
      $(document).scroll( _showHideAnimation );
    };

    ScrollToTop.clickBtn = function() {
      clickedElem.on('click', _scrollToTargetAnimation );
    };

    ScrollToTop.init = function (config) {
      $.extend(this.config, config);
      ScrollToTop.showHide();
      ScrollToTop.clickBtn();
    };

  })(jQuery, window.ScrollToTop = window.ScrollToTop || {});

  $(function() {
    config = {
      scrollDistance: 500,
      speed: 300
    };
    ScrollToTop.init(config);
  });
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
user2734550
  • 952
  • 1
  • 12
  • 35

1 Answers1

1

First, what you have isn't a module pattern. A module pattern is concerned with creating an object from scratch and hiding some of its properties and methods. Your example is a decorator -- you pass in an object ScrollToTop and decorate it with additional methods. Some of the techniques are similar to that of the module pattern -- the use of an IIFE, using closure to hide private variables -- but the intent is different. I'd recommend that you read this post to understand the difference between the module pattern variants.

As I understand your question, you have a default config object inside your decorator you'd like to modify. Since your decorator function accomplishes it objective using a side effect, you can use your decorator to return a configManager which you can use to mutate the inner default config.

var configManager = (function($, ScrollToTop, undefined) {

  var clickedElem = $('[data-scroll]');
  var defaultConfig = {
    scrollDistance: 500,
    speed: 300
  };

  var _scrollToTargetAnimation = function () {
    // ...
  };

  var _showHideAnimation = function () {
    // ...
  };

  ScrollToTop.showHide = function() {
    // ...
  };

  ScrollToTop.clickBtn = function() {
    // ...  
  };

  ScrollToTop.init = function (config) {
    // ...
  };

  return {
    setConfig: function(config){
        defaultConfig = config;
    }
  };
})(jQuery, window.ScrollToTop = window.ScrollToTop || {});

$(function() {
  config = {
    scrollDistance: 500,
    speed: 300
  };
  ScrollToTop.init(config);
});

configManager.setConfig({
  scrollDistance: 400,
  speed: 200
});

ADDED in response to OP's question: The reason why $.extend doesn't work in

ScrollToTop.init = function (config) {
  $.extend(this.config, config);

is because the parameter config is hiding the closure's config and this.config doesn't point to anything at all. This is easily changed by renaming the parameter so it doesn't hide the closure's config

ScrollToTop.init = function (config2) {
  $.extend(config, config2);
Community
  • 1
  • 1
I-Lin Kuo
  • 3,220
  • 2
  • 18
  • 25
  • Thanks for the solution. I still have few questions. 1. Why $.extend doesn't work when I pass in a new config outside the module? – user2734550 Feb 09 '15 at 21:54