JavaScript goodies for Responsive Design
- IE 7+
- Firefox 3.6+
- Chrome 4+
- Safari 5+
- Opera 10.10+
Note: Be aware that browsers that does not support media query will not trigger events of layout change.
- jQuery 1.4.4 + (..., 1.7.2, 1.8.2)
- Modernizr MediaQueries 2.6.2 (We only need media queries verification, we have a custom build in lib directory in case you do not have modernizr in your project)
The first thing to do is define what resolutions your web app can handle:
// After the document loads
$(function() {
$.responsiveHub({
layouts: {
320: "phone",
960: "tablet",
1024: "web"
},
defaultLayout: "web"
});
});
Important: This code should be the last script to run.
Here, our web app supports three distinct resolutions, or layouts: phone, tablet, and web. The key associated to each value is the corresponding minimum screen width, in pixels, which ResponsiveHub uses to determine how to call each screen range.
To make things easier to visualize, in this particular example, these are the ranges:
- Window width >= 1024 is called web
- Window width >= 960 and < 1024 is called tablet
- Window width >= 320 and < 960 is called phone
Another interesting parameter is the defaultLayout
; it is the layout
used when the browser doesn't support media queries.
If you are interested to know when the ResponsiveHub is ready, you can
use the ready
callback:
$.responsiveHub("ready", ["phone", "tablet", "web"], function(event) {
alert(event.layout); // Current layout
alert(event.touch); // Whether the browser supports touch events
});
As you can see, the event
parameter exposes what is the current
layout and whether the device is touch-enabled.
This callback is useful when you need to do further adjustments before the page is fully ready, i.e., re-initialize a pagination plugin with a different number of elements per page.
The second parameter indicates what layouts you are interested to be notified about. For example, if you just need to change things for relatively small screen sizes (like phones), this is what you need:
$.responsiveHub("ready", "phone", function(event) {
// This will not be called for bigger screen sizes
});
Important: Just remember that you must declare the callback before the initialization shown before runs. Otherwise, it would be too late.
Another common need in responsive-enabled web apps is to know when the user changes from one layout to another in order to adjust something that cannot be done entirely via CSS.
ResponsiveHub provides a callback just for that:
$.responsiveHub("change", "phone", function(event) {
// Do something radical when the user switches to phone layout
});
$.responsiveHub("change", ["tablet", "web"], function(event) {
// Restore things when the user goes back to more sane layouts :-)
});
Sometimes it's useful to know when the user initiates a resize gesture. Since the Window object doesn't provide a simple way to do that, ResponsiveHub implements the following callbacks:
$.responsiveHub("resizeStart", function() {
// Called when the user initiates a resize gesture
});
$.responsiveHub("resizeStop", function() {
// Called when the user finishes the resize gesture
});
To know if a resize gesture is happening at any moment:
$.responsiveHub("isResizing"); // true or false
When using technologies such as pjax or turbolinks you will need to call
the ready event after the page changes, for this scenario you will use the
triggerReadyEvent
method, like:
// For turbolinks, for example
$(document).on("page:load", function() {
$.responsiveHub("triggerReadyEvent");
});
// For pjax, for example
$(document).on("pjax:complete", function() {
$.responsiveHub("triggerReadyEvent");
});
When using technologies such as pjax or turbolinks you will need to unbind the "ready" and "change" events during page transitions to avoid the acumulation of events ending in a bad behavior of your javascripts. For that you can use the unbindAllEvents
method, like:
$.responsiveHub("unbindAllEvents");
If you need to check some properties of the browser at any moment, there's a few functions you can use.
Returns the layout corresponding to the current window size:
$.responsiveHub("layout"); // "tablet"
Returns whether the browser has Flash support enabled:
$.responsiveHub("hasFlash"); // true or false
Returns whether the browser supports touch gestures:
$.responsiveHub("isTouch"); // true or false
ResponsiveHub comes with some helpers to support your tests. There are 2 versions of it: src/responsive_hub.jasmine_helpers.js for Jasmine 1.x and src/responsive_hub.jasmine_helpers_2.0.js, for Jasmine 2.0. To install, include the helpers file for your Jasmine version and do something like:
beforeEach(function() {
window.helpers = (function() {
return {
responsiveHub: $.responsiveHub.jasmineHelpers
}
})();
});
it("should something...", function() {
helpers.responsiveHub.setLayout("phone");
// ...
});
it("should something...", function() {
helpers.responsiveHub.setTouch(true);
// ...
});
it("should something...", function() {
helpers.responsiveHub.hasFlash(false);
// ...
});
it("should something...", function() {
helpers.responsiveHub.setWidth(800);
// ...
});
it("should something...", function() {
helpers.responsiveHub.setWindow(win);
// ...
});
it("should something...", function() {
var callback = jasmine.createSpy("onChange");
$.responsiveHub("change", ["phone", "tablet"], callback);
helpers.responsiveHub.triggerChangeToLayout("phone");
expect(callback).toHaveBeenCalledWith({layout: "phone", touch: false});
// ...
});
it("should something...", function() {
expect(helpers.responsiveHub.getLayoutWidth("web")).toBe(960);
// ...
});
Copyright (c) 2012 Globo.com - Webmedia. See COPYING for more details.