Search code examples
jquerymedia-queriesenquire.js

Enquire.js - unmatch event on load


See this fiddle.

enquire.register("screen and (max-width: 640px)", {
    match: function () {
        $("body").css("background","red");
    },
    unmatch: function () {
        $("body").css("background","blue");
    }
});

when the browser window is 640px or less on load then the background-color will be set to red. (i.e. the match event is called). However, when the window is wider than 640px on load, nothing happens, i.e. the unmatch event is not called. Why not? And is there a way to force the unmatch event to fire if there is no match with the condition?

Basically what I want is that enquire behaves as an if-else statement that is immediatelly called.


Solution

  • When i designed enquire.js it was intended to be used with mobile-first RWD. Therefore it kind of assumes you're taking a progressive enhancement approach. That is, match is called when a query matches and unmatch is called only if match has occurred once already (and the query no longer matches). This may seem strange but the common use case is "do something when this query matches, undo it when it no longer matches". An example might be converting an element to a tabbed area on larger screens, and returning to stacked elements otherwise:

    enquire.register(desktopMediaQuery, {
      match : function() { 
        makeTabs(someElement);
      },
      unmatch : function() {
        makeStacked(someElement);
      }
    };
    

    If unmatch was called initially, when the query doesn't match, then you'd have to put logic in your unmatch callback to check whether match has already occurred (or worse yet, but such logic in makeStacked).

    If we were to strictly follow progressive enhancement, in your example, I would just have the background blue by default in CSS, and add a class in match, and remove the class in unmatch:

    enquire.register("screen and (max-width: 640px)", {
        match: function () {
            $("body").addClass("red-bg");
        },
        unmatch: function () {
            $("body").removeClass("red-bg");
        }
    });
    

    Though I assume your example is simplified version of what you actually want. So another approach is to use the setup callback to cover off the default case:

    enquire.register("(max-width: 640px)", {
        setup : function() {
            $("body").css("background","blue");
        },
        match : function() {
            $("body").css("background","red");
        },
        unmatch : function() {
            $("body").css("background","blue");
        }
    });
    

    You could also use two media queries, if this better suits what you need to do. I think this better conveys intentions than using setup as above.

    enquire.register("(max-width: 640px)", {
        match : function() {
            $("body").css("background","red");
        }
    })
    .register("(min-width: 641px)", {
        match : function() {
            $("body").css("background","blue");
        }
    });
    

    Here's a fiddle demonstrating both approaches: http://jsfiddle.net/7Pd3m/