On Github denisgursky / denisgursky.github.io
ResponsiveJS is our highspeed, easy-to-implement JavaScript framework that transforms your desktop website into a Responsive Design website, optimized across screen sizes for mobile and tablet.
The idea is simple, we're writing CSS and JS code to make a site looks well on devicesInsert the library 5thfinger.responsive.js
Insert an inline script, that begins responsifying
To make it work you need to include two things the library script and an inline script, that begins the responsifying processInsert the following markup inside the <head> section
To minimize the impact on your site,
place the tag as close as possible the </head> tag.
<script src="//your-hostname//5thfinger.responsive.js" type="text/javascript"></script> <script type="text/javascript"> responsify.start({ remoteDebug: false, mobileOnly: true, clientMapSrc: "//your-hostname/clientMap.js" }); </script>Here's an example. Read the slide.
<html> <head> <!--here your scripts, styles, whatever--> <script src="//your-hostname//5thfinger.responsive.js" type="text/javascript"></script> <script type="text/javascript"> responsify.start({ remoteDebug: false, mobileOnly: true, clientMapSrc: "//your-hostname/clientMap.js" }); </script> </head> <body>Here is your page</body> </html>It's is the same example, just to show you how it looks in the page markup
Configuration object to setup project settings before executing client scripts
It's an object that allows setup setting in a declarative wayresponsify.clientMap = { viewport: "", bounds: { phone: { maxWidth: 669 }, tablet: { minWidth: 670, maxWidth: 1280 }, desktop: { minWidth: 1281 } }, controls: ["footerLinks"], sources: { timeout: 10000, js: [{ src: "./js/master.js", callback: "runMaster"}], css: [{ href:"./css/master.css" }] } };This is how the client map usually looks. Let's consider we can do here and all available properties in detail
Allows you to set your value for the viewport meta tag.
Default value:
width=device-width, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0, user-scalable=no
Using the viewport meta tag allows to control layout on mobile browsers. You can define what viewport the library adds to the page. Here's default viewport on the slideDeclares ranges in pixels for the screen width
bounds: { phone: { maxWidth: 669 }, tablet: { minWidth: 670, maxWidth: 1280 }, desktop: { minWidth: 1281 } }Read the slide. You can define so many bounds, how much you need
Ability to separate the behavior for different bounds
The library creates some media queries to manage visibility of elements
//element1 is visible only for phones RD.boundManager.applyFor($(".element1-selector"), [bounds.phone]); //element2 is visible for all bounds except phone RD.boundManager.applyForOther($(".element2-selector"), [bounds.phone]);Bounds abstraction is a good way to separate different behaviors for different screens widths. And provide the best UI/UX for any devices. The library internally creates some media queries to support this feature, and appends them as a style tag to the page. Read the example. The library provides API that allows you detect the current bound for example. And it fires an event when bound is changed.
List of controls the library loads
controls: [ "footerLinks", "fullSiteLink", "menuBlock" ]The library provides a set of controls. You can use them to build UI/UX very quickly. Here you define which of the them you'd like to use, and controls will be loaded asynchronously. We'll consider the full list later on.
The heart of the clientmap
Defines where the code must be applied
sources:{ timeout:10000, js:[ { src:"master.js", callback:"runMaster" }, { src:"productList.js", contentCondition:[".products"], callback:"runProductList" }, { src:"product.js", urlCondition:["product"], contentCondition:[".product"], callback:"runProduct" }, { src:"iphone-ipad-only.js", uaCondition:["iphone", "ipad"], callback:"runIphoneIpadOnly" } ], css:[ { href:"../css/master.css" }, { href:"../css/productList.css", contentCondition:[".products"] }, { href:"../css/product.css", urlCondition:["product"], contentCondition:[".product"] } ] }Read the slide. It's a huge object, that has a lot of options. Let's look at them.
number of milliseconds for downloading the sources
the timeout is exceeded, the library reverts changes
This first option is timeout. Read the slides. I'll tell you what reverting changes really means in deep a bit later, but for now it's enough to know that it rollbacks some changes the library already didAll types of conditions are arrays, except customCondition
Condition is true, if any sub-condition in the array is true
Source is applied, if all conditions are true
Conditions say to the library can a source be applied to the page or not. All types of conditions are arrays, except customCondition. Let's call an item in a condition array - sub-condition. Read the slide.The following source is applied, when:
var isRetina = function(){ return window.devicePixelRatio === 2; }; //... sources:{ js:[ { src:"test.js", uaCondition:["iphone", "ipad"], urlCondition:["product"], customCondition: isRetina, contentCondition:[".someElement"], callback:"runTest" } ] }Here's an example. Read the slide.
The library executes JS callbacks after the CSS file is loaded
clientMap.js
sources:{ css:[ { href: "master.css", id: "master-css" } ] }
master.css
link#master-css { visibility: hidden; }Sometimes you need to execute some code after styles are loaded and applied. Usually, it happens when you need to get a size of an element and then use it some how. The styles can affect on this size, you want to be sure that they are already applied. Bad news. Browsers don't provide onload event for the link tag as they do for the script tag. So there's no way on the box to know exactly when a CSS file is loaded. Good news. There's a workaround in the library that works across all browsers. Just two steps: 1) add an unique id attribute 2) add this css rule in the CSS file All javascript callback will be executed after the CSS file is loaded.
can be divided into 3 phases
Read the slide. First happens when the browser loaded the library. Second when responsify.start method is called Third when callbacks are executed
Just 3 things happens here. It initializes some default values, then initializes helpers that used internally, and adds the viewport.
var defaults = { waitForJQueryTimeout: 30000, viewport: "width=device-width, minimum-scale=1.0, maximum-scale=1.0," + " initial-scale=1.0, user-scalable=no", log: true, jQueryLink: "//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js", jQueryMinSupportedVersion: "1.8", formatDetection: false };It's an object that used internally, it contains default values.
the following flow happens when responsify.start({...}) method is called
A lot of things happens in background when the method is called. In short, you pass some settings and it starts the responsifying process. But we're going to talk about in details.
responsify.start({ clientMapSrc: "//your-hostname/clientMap.js" remoteDebug: false, mobileOnly: true, jQueryObject: "jQuery", formatDetection: false, log: true });As you probably remember such code is placed in the inline script below the library script. Now I'll show what properties we have and may change here.
Required
Location of the clientmap file
It's the only one required property. Declares where the clientmap file is.Optional. Default: false
Based on jsconsole
Useful for simple debugging, logging on a mobile device
Read the slide. Internally, it adds a script to the page. The script is a bridge between your page and jsconsole. But it's much better to use native tools to debug.Optional. Default: false
Applies the responsive code only for touch devices
There's a simple condition that check touch. It checks ontouchstart property in the window object. So if you'll open the page on a laptop with touch screen you may see the responsive version of the page.Optional. Default: "jQuery"
Declares what object is used as jQuery
More details about jQuery
If you have jQuery that has a different name. By default, it jQuery in lower camelcase. You may provide the different name, it must be a string. The library tries to take it from the window object by the given name. If jQuery is loaded asynchronously for example via RequireJS or any other module loader, in this case library checks jQuery availability 30 seconds and then fails.Optional. Default: "//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"
Location of jQuery, that would be used
More details about jQuery
You may provide a link to load jQuery, be default it refers to the Google CDN.Optional. Default: false
Adds meta tag format-detection
<meta name="format-detection" content="telephone=no"/>
By default, phone numbers look like hypertext links, you can tap to call a number. This options allows you set off this, and phone numbers will look like on desktop.Optional. Default: true
Writes logs into the browser console
Read the slide.
The library adds the code below to the <head>
<style id="RDhideAll" type="text/css"> html, body { background:none; } body>* { opacity:0; filter:alpha(opacity=0); position:absolute; left:-3000px; } <style>The library adds this styles to the head tag. They remove background on body and html elements and move all body's child elements far away to the left
The Library removes
and shows content
Read the slide.when any from the list below fails
JS and CSS code are concatenated and minified in a single file
It's usually called clientMap.js
Sources are not loaded separately
Users don't like to wait while the site loads. And our goal here is decreasing the loading time. The popular solution is decreasing amount of additional resources like scripts, css files, images, whatever which is loaded separately. And of course decreasing file sizes. Typical optimization for ResponsiveJS is 1) converting background images to base64 and include them in the css files 2) minifying CSS and JS 3) concatenate all of them in a single file So in the end we have just a single file, that is usually called clientMap.jsclientMap object
sources: { js: [{ src: "js/master.js", callback: "runMaster"}] }
Code in the same file, callback matches the first argument
RD.clientFnManager.set("runMaster", function () { //do something });Read the slide.
clientMap object
sources: { css: [{ href: "css/master.css"}] }
Code in the same file, href matches the first argument
RD.clientCssManager.set('css/master.css', 'body{ background: red; }');
The second argument is added to style tag
So if you add such JS code into your sources, the library won't load 'css/master.css' it adds a style tag with string inside that you pass as the second argument. You'll see how to do this automatically with GruntJS in the next training session. Let's back to that checking that I mentioned couple slides before. Checks that all href's in the clientmap match resources in the clientCssManger same for JS callbacks and clientFnManager.memories the current screen width
triggers resize event
triggers boundChange event
Read the slide.triggers ready event
adds CSS sources to the page, in the production version
executes JS callbacks
a callback is executed one time
setTimeout's, setInterval's, event handlers live until the next page loading
Read the slide. Whatever you write in callbacks will work from there.The library is fully documented using JSDoc
Documentation are available by these links.describes public APIs
has examples