A Backbone.js view mixin that integrates Enquire.js and allows declarative media query callbacks in a style that should be comfortable to those familiar with Backbone.View's DOM event handling.
MyView = Backbone.View.extend({
breakpoints: {
"screen and (max-width:320px)": "renderPhone",
"screen and (min-width:320px)": function() { console.log("tablet"); },
"screen and (min-width:1024px)": {
match: function() { console.log("desktop"); },
unmatch: function() { console.log("smaller than desktop"); },
setup: function() { console.log("setup only called when this query matches"); },
deferSetup: true
},
initialize: function(options) {
this.enquire()
},
renderPhone: function() { console.log("phone"); },
remove: function() {
this.unenquire();
this.$el.remove();
}
}
});
_.extend(MyView.prototype, ResponsiveView);This example shows a number of things:
- Breakpoint callbacks can be defined in a property called
breakpoints(line 3). - The
breakpointsproperty is a hash in the form{"mediaquery" : callback}that takes a media query as a key and a handler callback as a value. - The
mediaquerycan be any ordinary media query and supports any media queries that are supported by Enquire.js - The
callbackcan be one of: - The name of a View's method as a string (similar to Backbone View's DOM 'events' callbacks) (line 4).
- A function (line 5).
- Any of the acceptable handler arguments that enquire.register() can handle (lines 6 — 11). See the Enquire.js docs for more info.
- If the value is either the name of a method or a function it will be called whenever the media query is matched. (See the Enquire.js docs for how to supply
matchandunmatchhandlers if you are supplying thecallbackin the third form). - To start subscribing to media query changes, you need to call
this.enquire()somewhere in your code (line 13). Depending on how and when your view is added to the page, you will likely want to do this in either theinitializeorrendermethod of your view. - You can unsubscribe from media query changes by calling
this.unenquire()(line 17). This delegates to enquire.js'enquire.unregister(mediaquery, callback)for each query handler inthis.breakpoints(see below for more).
ResponsiveView.enquire() takes an optional argument: breakpoints. breakpoints can either be the string name of a member property to use as the 'breakpoints' hash or a breakpoints hash can be supplied directly. If no argument is supplied then ResponsiveView will look for a property called breakpoints (the default behaviour). Finally, you can pass true as the first argument to ResponsiveView.enquire() which tells ResponsiveView to use the breakpoints member property (this is useful for passing options in the second argument to enquire);
Behind the scenes, a call to ResponsiveView.enquire()
- Registers all the callbacks supplied in
breakpointswith Enquaire.js. - Enquire.js starts listening for viewport changes using matchMedia.addListener().
ResponsiveView.unenquire() delegates to enquire.unregister(). By default unenquire, called with no arguments, will loop through all the query handlers in this.breakpoints and call enquire.unregister(key, value) on each one.
You may supply a different breakpoints hash as the optional first argument. This can take any of the forms outlined above for ResponsiveView.enquire(breakpoints).
If you pass false as the first argument, you can pass an individual media query to unsubscribe as the second argument. This is equivalent to calling enquire.unregister("some media query") (without the callback second argument) and allows you to nuke an entire media query and all its callbacks at once (note that this is not limited to callbacks defined by this view and will also nuke any callbacks for that media query registered elsewhere in your app):
this.unenquire(false, "screen and (max-width: 500px)");- Upgraded the Enquire.js version from 1.4.0 to 2.0.1
- ResponsiveView mixin no longer uses enquire.listen() and enquire.fire().
- Tested with Backbone 0.9.2 and Responsive.js 1.4.0