2

I'm building a plugin and for the toggling certain behaviour on/off, I'm using the matchMedia functions. However in the callback function, I need to pass an argument to retain the right reference to this. However, when I try to pass an argument to my callback function, it says my entire addListener callback function is undefined. The same applies when I try to bind this to the callback function.

TypeError: this.mediaQueryCheck(...) is undefined

There must be something really obvious I'm missing about addListener, so for now I'm only including a non-functional example of my code :

     MyPlugin.prototype = {
        version :   '0.0.1',
        mediaQuery : window.matchMedia(defaults.breakpoint),

        mediaQueryCheck : function(mql){

             if(mql.matches === true){ // if our mediaQuery matches
                this.evalScrollPosition();
                if(this.isLaunched === false){
                    // attach scroll handlers

                    $(window).on('scroll resize', this.evalScrollPosition.bind(this));
                    this.isLaunched = true;
                }
            }
            else if(mql.matches === false){ // if the mediaQuery isn't active atm
                if(this.isLaunched === true){
                // remove handlers
                $(window).off('scroll resize', this.evalScrollPosition.bind(this));
                    this.isLaunched = false;
                }
                this.fixedStatus = '';
                this.unstyleContainer(); // remove positioning set by plugin
                this.unstyleColumns(); // remove positioning set by plugin
            }

        },

        init: function(){

            // merge user options with defaults 
            this.config = $.extend({}, defaults, this.options, this.metadata);
            // define mql object

            this.mediaQuery = window.matchMedia(this.config.breakpoint);

             var thatMediaQuery = this.mediaQuery;
            // add listener to conditionally toggle scroll and resize listeners and bind this to not lose reference to this when running the mediaQueryCheck function

            this.mediaQuery.addListener( this.mediaQueryCheck(thatMediaQuery).bind(this) );

            // check mediaQuery to determine whether to apply eventListeners 

            // and run for a first time
            this.mediaQueryCheck(thatMediaQuery);


            return this;
        },
/* .. rest omitted for brevity */
}

So I've also tried passing the reference to this to my mediaQueryCheck function by adding a second parameter to that function and then passing in this like so :

mediaQueryCheck : function(mql, context){
    // '..'
},
init: function(){
    // 'rest omitted for brevity'
    this.mediaQuery.addListener( this.mediaQueryCheck(thatMediaQuery, this) );
},

but to no avail.. any ideas ? thanks in advance!

Tim Bakkum
  • 83
  • 7

1 Answers1

4

First of all - the second code you provided is not a valid way to bind this. To bind this you have to use either a bind function (as you did in the first piece of code) or provide something similar on your own.

Quick fix, replace:

this.mediaQuery.addListener( this.mediaQueryCheck(thatMediaQuery).bind(this) );

with

this.mediaQuery.addListener(this.mediaQueryCheck.bind(this));

You don't need to invoke the function when you try to bind "this". If it doesn't work, please paste more of your code (the whole function would be awesome).

Jakub Rożek
  • 2,110
  • 11
  • 12
  • Thanks, it worked! I thought what you suggested didn't work before, but something else was causing the rest of the code to fail and that's why I started to fiddle around with this part. – Tim Bakkum Apr 23 '16 at 22:30