1

I am using the JQuery Boilerplate to write my first JQuery plugin - a responsive carousel. I am using another plugin (SSM - http://www.simplestatemanager.com/) to create states for each device view. So on mobile devices functionA will run, on tablets functionB and on desktops functionC, etc.

For each state created by SSM a corresponding onEnter callback function can be added and I've added 3 suitable functions to run when this occurs. As you can see from the code below a function onEnterDesktop runs on Desktop devices. I am then attempting to run a further function from within this called createCarousel() but am getting an error "createCarousel is not defined".

I believe this is because of a scoping problem and the browser can't find createCarousel from within the onEnterDesktop function. How can I fix this?

Any help would be great. Here's the code for my plugin:

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

// Create the defaults once
var pluginName = "dcResponsiveCarousel",
    defaults = {
        propertyName: "value"
    };

function Plugin( element, options ) {
    this.element = element;
    this.$element = $(element);
    this.options = $.extend( {}, defaults, options) ;
    this._defaults = defaults;
    this._name = pluginName;
    this.init();
}

Plugin.prototype = {

    init: function() {

        ssm.addStates([
            {
                id: 'mobile',
                maxWidth: 767,
                onEnter: this.onEnterMobile
            },            
            {
                id: 'tablet',
                maxWidth: 991,
                minWidth: 768,
                onEnter: this.onEnterTablet
            },
            {
                id: 'desktop',
                minWidth: 992,
                onEnter: this.onEnterDesktop
            }
        ]);
        ssm.ready();
    },

    onEnterMobile: function (){
        console.log("You've entered mobile screen dimension territory");
        var itemsPerPage = 1;
        console.log(itemsPerPage); 
    },

    onEnterTablet: function (){
        console.log("You've entered tablet screen dimension territory");
        var itemsPerPage = 2;
        console.log(itemsPerPage);         
    },

    onEnterDesktop: function (){
         console.log("You've entered desktop screen dimension territory");
         var itemsPerPage = 3;
         createCarousel();
    },

    createCarousel: function (){
        var $carouselItems = this.$element.children(".item"),
            $carouselItemsLength = $carouselItems.length,
            $carouselItemsWidth = 0;

            for (var i = 0; i < $carouselItemsLength; i++) {
                $carouselItemsWidth = $carouselItemsWidth + $carouselItems.eq(i).outerWidth();
            };

            console.log($carouselItemsWidth);
            this.$element
    }
};

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

})( jQuery, window, document );
James Howell
  • 1,392
  • 5
  • 24
  • 42

1 Answers1

1

It's an object literal so createCarousel is not defined, Plugin.prototype.createCarousel is, or in the scope you are in, this.createCarousel();

onEnterDesktop: function (){
     console.log("You've entered desktop screen dimension territory");
     var itemsPerPage = 3;
     Plugin.prototype.createCarousel();
},
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • Tried using the above and get: Uncaught TypeError: Object [object Array] has no method 'createCarousel' – James Howell Dec 29 '13 at 11:11
  • 1
    It's because of the way it's called, it has another scope, use `Plugin.prototype.createCarousel()` instead – adeneo Dec 29 '13 at 11:15
  • Thanks that seemed to do the trick. Also how can I pass this.$element through to onEnterDesktop and createCarousel. I appreciate your help. – James Howell Dec 29 '13 at 11:18
  • 1
    Again, because of the way it's called, it has a completely different scope, so you can either use apply to set the scope, or use `Plugin.$element` to get the element. – adeneo Dec 29 '13 at 11:21
  • Thanks again. I decided to remove the specificity on the this.$element variable and changed it to $element so I can access it from anywhere. – James Howell Dec 29 '13 at 11:37