├── .gitignore ├── js ├── util.js ├── jRespond.min.js └── jRespond.js ├── package.json ├── bower.json ├── LICENSE ├── index.html └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /js/util.js: -------------------------------------------------------------------------------- 1 | // make console.log safe to use 2 | window.console||(console={log:function(){}}); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jrespond", 3 | "version": "1.0.0", 4 | "description": "jRespond is a simple way to globally manage javascript on responsive websites.", 5 | "main": "js/jRespond.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/ten1seven/jRespond.git" 9 | }, 10 | "keywords": [ 11 | "responsive", 12 | "media", 13 | "queries" 14 | ], 15 | "author": "Jeremy Fields ", 16 | "license": "MIT", 17 | "bugs": { 18 | "url": "https://github.com/ten1seven/jRespond/issues" 19 | }, 20 | "homepage": "https://github.com/ten1seven/jRespond" 21 | } -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jrespond", 3 | "version": "1.0.0", 4 | "homepage": "https://github.com/ten1seven/jRespond", 5 | "authors": [ 6 | "Jeremy Fields " 7 | ], 8 | "description": "jRespond is a simple way to globally manage javascript on responsive websites.", 9 | "main": "js/jRespond.js", 10 | "moduleType": [ 11 | "amd" 12 | ], 13 | "keywords": [ 14 | "responsive", 15 | "media", 16 | "queries" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "tests" 25 | ], 26 | "repository": { 27 | "type": "git", 28 | "url": "git://github.com/ten1seven/jRespond.git" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jeremy Fields 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /js/jRespond.min.js: -------------------------------------------------------------------------------- 1 | /*! jRespond.js v 0.10 | Author: Jeremy Fields [jeremy.fields@viget.com], 2013 | License: MIT */ 2 | !function(a,b,c){"object"==typeof module&&module&&"object"==typeof module.exports?module.exports=c:(a[b]=c,"function"==typeof define&&define.amd&&define(b,[],function(){return c}))}(this,"jRespond",function(a,b,c){"use strict";return function(a){var b=[],d=[],e=a,f="",g="",i=0,j=100,k=500,l=k,m=function(){var a=0;return a="number"!=typeof window.innerWidth?0!==document.documentElement.clientWidth?document.documentElement.clientWidth:document.body.clientWidth:window.innerWidth},n=function(a){if(a.length===c)o(a);else for(var b=0;b=e[c].enter&&a<=e[c].exit){b=!0;break}b&&f!==e[c].label?(g=f,f=e[c].label,p()):b||""===f||(f="",p())},r=function(a){if("object"==typeof a){if(a.join().indexOf(f)>=0)return!0}else{if("*"===a)return!0;if("string"==typeof a&&f===a)return!0}},s=function(){var a=m();a!==i?(l=j,q(a)):l=k,i=a,setTimeout(s,l)};return s(),{addFunc:function(a){n(a)},getBreakpoint:function(){return f}}}}(this,this.document)); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | jRespond Test Page 18 | 19 | 20 | 31 | 32 | 33 | 34 | 35 |
36 | 37 |

38 | 39 |
40 | 41 | 42 | 43 | 44 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/) 2 | 3 | # DEPRECATED 4 | 5 | _jRespond is no longer supported. It was written to fill the gap before [`window.matchMedia()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia) was well supported. `window.matchMedia()` now enjoys support across [all modern browsers](https://caniuse.com/#feat=matchmedia), rendering jRespond obsolete._ 6 | 7 | --- 8 | 9 | #### jRespond is a simple way to globally manage JavaScript on responsive websites. 10 | 11 | Responsive websites that require JavaScript functionality for some breakpoints and not for others need some type of system for triggering the correct functions at the correct breakpoint and to also be aware of when a browser is resized across breakpoints. Although switching between breakpoints could be seen as an edge case, a few applications for jRespond are: 12 | 13 | * Managing functionality for initial page load: Even if the browser is never resized, jRespond can help manage what JavaScript functions are triggered when the page loads for a given breakpoint. 14 | * Development testing: jRespond makes it much easier to test in-browser. 15 | * Borderline device widths: Real user browser resizing and device rotation that crosses breakpoints. 16 | 17 | If your project only needs to support modern browsers I highly recommend checking out Rob Tarr's mediaCheck which uses the matchMedia method. But if you're using respond.js as a polyfill to ensure that your site responds on older browsers, jRespond is worth checking out. 18 | 19 | ## How does it work? 20 | 21 | jRespond is a script that holds a list of user-defined functions that are fired based on the browser's width compared to a list of customizable breakpoints. Entry and exit functions can be defined so transitions between breakpoints can be managed by removing and unbinding some page elements while creating and binding others. jRespond was built to be independent and browser agnostic. It does NOT sniff for media queries in the stylesheets. 22 | 23 | After including jRespond.js, call jRespond and define as many or as few media breakpoints as you need for your project. Labels can be any single-word string: 24 | 25 | ``` JavaScript 26 | // call jRespond and add breakpoints 27 | var jRes = jRespond([ 28 | { 29 | label: 'handheld', 30 | enter: 0, 31 | exit: 767 32 | },{ 33 | label: 'tablet', 34 | enter: 768, 35 | exit: 979 36 | },{ 37 | label: 'laptop', 38 | enter: 980, 39 | exit: 1199 40 | },{ 41 | label: 'desktop', 42 | enter: 1200, 43 | exit: 10000 44 | } 45 | ]); 46 | ``` 47 | 48 | Once running, functions can be registered with jRespond along with a desired breakpoint: 49 | 50 | ``` JavaScript 51 | // register enter and exit functions for a single breakpoint 52 | jRes.addFunc({ 53 | breakpoint: 'desktop', 54 | enter: function() { 55 | myInitFunc(); 56 | }, 57 | exit: function() { 58 | myUnInitFunc(); 59 | } 60 | }); 61 | ``` 62 | 63 | Or an array of breakpoints: 64 | 65 | ``` JavaScript 66 | // register enter and exit functions for multiple breakpoints 67 | jRes.addFunc({ 68 | breakpoint: ['desktop','laptop'], 69 | enter: function() { 70 | myInitFunc(); 71 | }, 72 | exit: function() { 73 | myUnInitFunc(); 74 | } 75 | }); 76 | ``` 77 | 78 | Or an array of breakpoints and functions: 79 | 80 | ``` JavaScript 81 | // register enter and exit functions for multiple breakpoints and functions 82 | jRes.addFunc([ 83 | { 84 | breakpoint: 'desktop', 85 | enter: function() { 86 | myInitFuncDesktop(); 87 | }, 88 | exit: function() { 89 | myUnInitFuncDesktop(); 90 | } 91 | },{ 92 | breakpoint: 'laptop', 93 | enter: function() { 94 | myInitFuncLaptop(); 95 | }, 96 | exit: function() { 97 | myUnInitFuncLaptop(); 98 | } 99 | },{ 100 | breakpoint: 'tablet', 101 | enter: function() { 102 | myInitFuncTablet(); 103 | }, 104 | exit: function() { 105 | myUnInitFuncTablet(); 106 | } 107 | } 108 | ]); 109 | ``` 110 | 111 | Use '*' to run a function at every breakpoint: 112 | 113 | ``` JavaScript 114 | // register enter and exit functions for every breakpoint 115 | jRes.addFunc({ 116 | breakpoint: '*', 117 | enter: function() { 118 | myInitFunc(); 119 | }, 120 | exit: function() { 121 | myUnInitFunc(); 122 | } 123 | }); 124 | ``` 125 | 126 | Ask jRespond what the current breakpoint is at any time: 127 | 128 | ``` JavaScript 129 | // get the current breakpoint 130 | jRes.getBreakpoint(); 131 | ``` 132 | 133 | The breakpoint parameter is required but the enter and exit parameters are optional (of course, at least one is required for something to happen). 134 | 135 | ## Use as a module 136 | 137 | You can also use jRespond as a browser or Node module. 138 | 139 | ### AMD module 140 | 141 | ```javascript 142 | require(['jRespond'], function (jRes) { 143 | var mediaQueries = jRes([ 144 | { 145 | label: 'tablet', 146 | enter: 768, 147 | exit: 979 148 | } 149 | ]); 150 | 151 | mediaQueries.addFunc({ 152 | breakpoint: 'tablet', 153 | enter: function() { 154 | myInitFunc(); 155 | }, 156 | exit: function() { 157 | myUnInitFunc(); 158 | } 159 | }); 160 | }); 161 | ``` 162 | 163 | ### CommonJS syntax 164 | 165 | ```javascript 166 | require(['require', 'jRespond'], function (require) { 167 | var jRes = require('jRespond'); 168 | 169 | var mediaQueries = jRes([ 170 | { 171 | label: 'tablet', 172 | enter: 768, 173 | exit: 979 174 | } 175 | ]); 176 | 177 | mediaQueries.addFunc({ 178 | breakpoint: 'tablet', 179 | enter: function() { 180 | myInitFunc(); 181 | }, 182 | exit: function() { 183 | myUnInitFunc(); 184 | } 185 | }); 186 | }); 187 | ``` 188 | 189 | ## Performance 190 | 191 | jRespond is 1.3kb minified and only polls for the browser width every 500ms. If it detects a change the polling speed is increased to 100ms only until the browser width stops changing. 192 | 193 | ## Browser Support 194 | 195 | IE 6+, Safari 5+, Firefox 3+, Chrome 1+ 196 | 197 | ## Dependencies 198 | 199 | None. 200 | 201 | ## Credits 202 | 203 | Thanks to Rob Tarr for inspiring the function registration pattern and Markup Boy for helping me with my JavaScript failings. 204 | -------------------------------------------------------------------------------- /js/jRespond.js: -------------------------------------------------------------------------------- 1 | /*! jRespond.js v 0.10 | Author: Jeremy Fields [jeremy.fields@viget.com], 2013 | License: MIT */ 2 | 3 | // Universal Module Definition 4 | ;(function (window, name, fn) { 5 | // Node module pattern 6 | if (typeof module === "object" && module && typeof module.exports === "object") { 7 | module.exports = fn; 8 | } else { 9 | // browser 10 | window[name] = fn; 11 | 12 | // AMD definition 13 | if (typeof define === "function" && define.amd) { 14 | define(name, [], function (module) { 15 | return fn; 16 | }); 17 | } 18 | } 19 | }(this, 'jRespond', function(win,doc,undefined) { 20 | 21 | 'use strict'; 22 | 23 | return function(breakpoints) { 24 | 25 | // array for registered functions 26 | var mediaListeners = []; 27 | 28 | // array that corresponds to mediaListeners and holds the current on/off state 29 | var mediaInit = []; 30 | 31 | // array of media query breakpoints; adjust as needed 32 | var mediaBreakpoints = breakpoints; 33 | 34 | // store the current breakpoint 35 | var curr = ''; 36 | 37 | // the previous breakpoint 38 | var prev = ''; 39 | 40 | // window resize event timer stuff 41 | var resizeTimer; 42 | var resizeW = 0; 43 | var resizeTmrFast = 100; 44 | var resizeTmrSlow = 500; 45 | var resizeTmrSpd = resizeTmrSlow; 46 | 47 | // cross browser window width 48 | var winWidth = function() { 49 | 50 | var w = 0; 51 | 52 | // IE 53 | if (typeof( window.innerWidth ) != 'number') { 54 | 55 | if (!(document.documentElement.clientWidth === 0)) { 56 | 57 | // strict mode 58 | w = document.documentElement.clientWidth; 59 | } else { 60 | 61 | // quirks mode 62 | w = document.body.clientWidth; 63 | } 64 | } else { 65 | 66 | // w3c 67 | w = window.innerWidth; 68 | } 69 | 70 | return w; 71 | }; 72 | 73 | // determine input type 74 | var addFunction = function(elm) { 75 | if (elm.length === undefined) { 76 | addToStack(elm); 77 | } else { 78 | for (var i = 0; i < elm.length; i++) { 79 | addToStack(elm[i]); 80 | } 81 | } 82 | }; 83 | 84 | // send media to the mediaListeners array 85 | var addToStack = function(elm) { 86 | var brkpt = elm['breakpoint']; 87 | var entr = elm['enter'] || undefined; 88 | 89 | // add function to stack 90 | mediaListeners.push(elm); 91 | 92 | // add corresponding entry to mediaInit 93 | mediaInit.push(false); 94 | 95 | if (testForCurr(brkpt)) { 96 | if (entr !== undefined) { 97 | entr.call(null, {entering : curr, exiting : prev}); 98 | } 99 | mediaInit[(mediaListeners.length - 1)] = true; 100 | } 101 | }; 102 | 103 | // loops through all registered functions and determines what should be fired 104 | var cycleThrough = function() { 105 | 106 | var enterArray = []; 107 | var exitArray = []; 108 | 109 | for (var i = 0; i < mediaListeners.length; i++) { 110 | var brkpt = mediaListeners[i]['breakpoint']; 111 | var entr = mediaListeners[i]['enter'] || undefined; 112 | var exit = mediaListeners[i]['exit'] || undefined; 113 | 114 | if (brkpt === '*') { 115 | if (entr !== undefined) { 116 | enterArray.push(entr); 117 | } 118 | if (exit !== undefined) { 119 | exitArray.push(exit); 120 | } 121 | } else if (testForCurr(brkpt)) { 122 | if (entr !== undefined && !mediaInit[i]) { 123 | enterArray.push(entr); 124 | } 125 | mediaInit[i] = true; 126 | } else { 127 | if (exit !== undefined && mediaInit[i]) { 128 | exitArray.push(exit); 129 | } 130 | mediaInit[i] = false; 131 | } 132 | } 133 | 134 | var eventObject = { 135 | entering : curr, 136 | exiting : prev 137 | }; 138 | 139 | // loop through exit functions to call 140 | for (var j = 0; j < exitArray.length; j++) { 141 | exitArray[j].call(null, eventObject); 142 | } 143 | 144 | // then loop through enter functions to call 145 | for (var k = 0; k < enterArray.length; k++) { 146 | enterArray[k].call(null, eventObject); 147 | } 148 | }; 149 | 150 | // checks for the correct breakpoint against the mediaBreakpoints list 151 | var returnBreakpoint = function(width) { 152 | 153 | var foundBrkpt = false; 154 | 155 | // look for existing breakpoint based on width 156 | for (var i = 0; i < mediaBreakpoints.length; i++) { 157 | 158 | // if registered breakpoint found, break out of loop 159 | if (width >= mediaBreakpoints[i]['enter'] && width <= mediaBreakpoints[i]['exit']) { 160 | foundBrkpt = true; 161 | 162 | break; 163 | } 164 | } 165 | 166 | // if breakpoint is found and it's not the current one 167 | if (foundBrkpt && curr !== mediaBreakpoints[i]['label']) { 168 | prev = curr; 169 | curr = mediaBreakpoints[i]['label']; 170 | 171 | // run the loop 172 | cycleThrough(); 173 | 174 | // or if no breakpoint applies 175 | } else if (!foundBrkpt && curr !== '') { 176 | curr = ''; 177 | 178 | // run the loop 179 | cycleThrough(); 180 | } 181 | 182 | }; 183 | 184 | // takes the breakpoint/s arguement from an object and tests it against the current state 185 | var testForCurr = function(elm) { 186 | 187 | // if there's an array of breakpoints 188 | if (typeof elm === 'object') { 189 | if (elm.join().indexOf(curr) >= 0) { 190 | return true; 191 | } 192 | 193 | // if the string is '*' then run at every breakpoint 194 | } else if (elm === '*') { 195 | return true; 196 | 197 | // or if it's a single breakpoint 198 | } else if (typeof elm === 'string') { 199 | if (curr === elm) { 200 | return true; 201 | } 202 | } 203 | }; 204 | 205 | // self-calling function that checks the browser width and delegates if it detects a change 206 | var checkResize = function() { 207 | 208 | // get current width 209 | var w = winWidth(); 210 | 211 | // if there is a change speed up the timer and fire the returnBreakpoint function 212 | if (w !== resizeW) { 213 | resizeTmrSpd = resizeTmrFast; 214 | 215 | returnBreakpoint(w); 216 | 217 | // otherwise keep on keepin' on 218 | } else { 219 | resizeTmrSpd = resizeTmrSlow; 220 | } 221 | 222 | resizeW = w; 223 | 224 | // calls itself on a setTimeout 225 | setTimeout(checkResize, resizeTmrSpd); 226 | }; 227 | checkResize(); 228 | 229 | // return 230 | return { 231 | addFunc: function(elm) { addFunction(elm); }, 232 | getBreakpoint: function() { return curr; } 233 | }; 234 | 235 | }; 236 | 237 | }(this,this.document))); --------------------------------------------------------------------------------