javascriptjquerycallbackmatchmedia

pass argument to matchmedia addListener callback function


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!


Solution

  • 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).