2

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.

Bram Vanroy
  • 27,032
  • 24
  • 137
  • 239

2 Answers2

6

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/

WickyNilliams
  • 5,218
  • 2
  • 31
  • 43
  • 1
    It's indeed a (much) simplified case. I am trying to make Enquire work with Masonry on the one hand and Stellar on the other. I went with the last solution indeed. It kept a better overview of what I was doing. But at least now I understand why enquire.js works how it does. Thank you for that! One last thing, slightly off-topic: does Enquire.js take scrollbars into account the same way CSS media queries does? I haven't tested it, but I have encountered some behaviour that might be attributed to the width of the scrollbar that is or is not counted in either CSS or Enquire. – Bram Vanroy Jul 07 '14 at 19:33
  • @WickyNilliams, I tried to sort my problem like your last example but somewhat it doesn't happen..http://stackoverflow.com/q/38168744/3697102 – Ayan Jul 03 '16 at 11:33
  • @WickyNilliams Here another user that loves enquire.js. However, I spent nearly 1hour and a half trying to figure out what I was doing wrong. I was having the same problem. After I've read your answer I totally understand now why you made it like this, but I would suggest to make a small note on the demo page bellow the code snippet 'Unmatch', that first time loaded 'unmatch' will not work (something like that:)). It would prevent many headaches:) Thank you for this wonderful tool! – viery365 Apr 03 '17 at 08:05
0

Enquire js provides a method called setup inside of the register function that is triggered once (without any media query being detected), when the register handler is called. So you can extend your code to include it like this:

enquire.register("screen and (max-width: 640px)", {
    setup: function() {
     // do stuff here as soon as register is called.
    },
    match: function () {
        $("body").css("background","red");
    },
    unmatch: function () {
        $("body").css("background","blue");
    }
});

(referenced from their documentation http://wicky.nillia.ms/enquire.js/#quick-start)