jRespond.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*! jRespond.js v 0.10 | Author: Jeremy Fields [jeremy.fields@viget.com], 2013 | License: MIT */
  2. // Universal Module Definition
  3. ;(function (window, name, fn) {
  4. // Node module pattern
  5. if (typeof module === "object" && module && typeof module.exports === "object") {
  6. module.exports = fn;
  7. } else {
  8. // browser
  9. window[name] = fn;
  10. // AMD definition
  11. if (typeof define === "function" && define.amd) {
  12. define(name, [], function (module) {
  13. return fn;
  14. });
  15. }
  16. }
  17. }(this, 'jRespond', function(win,doc,undefined) {
  18. 'use strict';
  19. return function(breakpoints) {
  20. // array for registered functions
  21. var mediaListeners = [];
  22. // array that corresponds to mediaListeners and holds the current on/off state
  23. var mediaInit = [];
  24. // array of media query breakpoints; adjust as needed
  25. var mediaBreakpoints = breakpoints;
  26. // store the current breakpoint
  27. var curr = '';
  28. // the previous breakpoint
  29. var prev = '';
  30. // window resize event timer stuff
  31. var resizeTimer;
  32. var resizeW = 0;
  33. var resizeTmrFast = 100;
  34. var resizeTmrSlow = 500;
  35. var resizeTmrSpd = resizeTmrSlow;
  36. // cross browser window width
  37. var winWidth = function() {
  38. var w = 0;
  39. // IE
  40. if (typeof( window.innerWidth ) != 'number') {
  41. if (!(document.documentElement.clientWidth === 0)) {
  42. // strict mode
  43. w = document.documentElement.clientWidth;
  44. } else {
  45. // quirks mode
  46. w = document.body.clientWidth;
  47. }
  48. } else {
  49. // w3c
  50. w = window.innerWidth;
  51. }
  52. return w;
  53. };
  54. // determine input type
  55. var addFunction = function(elm) {
  56. if (elm.length === undefined) {
  57. addToStack(elm);
  58. } else {
  59. for (var i = 0; i < elm.length; i++) {
  60. addToStack(elm[i]);
  61. }
  62. }
  63. };
  64. // send media to the mediaListeners array
  65. var addToStack = function(elm) {
  66. var brkpt = elm['breakpoint'];
  67. var entr = elm['enter'] || undefined;
  68. // add function to stack
  69. mediaListeners.push(elm);
  70. // add corresponding entry to mediaInit
  71. mediaInit.push(false);
  72. if (testForCurr(brkpt)) {
  73. if (entr !== undefined) {
  74. entr.call(null, {entering : curr, exiting : prev});
  75. }
  76. mediaInit[(mediaListeners.length - 1)] = true;
  77. }
  78. };
  79. // loops through all registered functions and determines what should be fired
  80. var cycleThrough = function() {
  81. var enterArray = [];
  82. var exitArray = [];
  83. for (var i = 0; i < mediaListeners.length; i++) {
  84. var brkpt = mediaListeners[i]['breakpoint'];
  85. var entr = mediaListeners[i]['enter'] || undefined;
  86. var exit = mediaListeners[i]['exit'] || undefined;
  87. if (brkpt === '*') {
  88. if (entr !== undefined) {
  89. enterArray.push(entr);
  90. }
  91. if (exit !== undefined) {
  92. exitArray.push(exit);
  93. }
  94. } else if (testForCurr(brkpt)) {
  95. if (entr !== undefined && !mediaInit[i]) {
  96. enterArray.push(entr);
  97. }
  98. mediaInit[i] = true;
  99. } else {
  100. if (exit !== undefined && mediaInit[i]) {
  101. exitArray.push(exit);
  102. }
  103. mediaInit[i] = false;
  104. }
  105. }
  106. var eventObject = {
  107. entering : curr,
  108. exiting : prev
  109. };
  110. // loop through exit functions to call
  111. for (var j = 0; j < exitArray.length; j++) {
  112. exitArray[j].call(null, eventObject);
  113. }
  114. // then loop through enter functions to call
  115. for (var k = 0; k < enterArray.length; k++) {
  116. enterArray[k].call(null, eventObject);
  117. }
  118. };
  119. // checks for the correct breakpoint against the mediaBreakpoints list
  120. var returnBreakpoint = function(width) {
  121. var foundBrkpt = false;
  122. // look for existing breakpoint based on width
  123. for (var i = 0; i < mediaBreakpoints.length; i++) {
  124. // if registered breakpoint found, break out of loop
  125. if (width >= mediaBreakpoints[i]['enter'] && width <= mediaBreakpoints[i]['exit']) {
  126. foundBrkpt = true;
  127. break;
  128. }
  129. }
  130. // if breakpoint is found and it's not the current one
  131. if (foundBrkpt && curr !== mediaBreakpoints[i]['label']) {
  132. prev = curr;
  133. curr = mediaBreakpoints[i]['label'];
  134. // run the loop
  135. cycleThrough();
  136. // or if no breakpoint applies
  137. } else if (!foundBrkpt && curr !== '') {
  138. curr = '';
  139. // run the loop
  140. cycleThrough();
  141. }
  142. };
  143. // takes the breakpoint/s arguement from an object and tests it against the current state
  144. var testForCurr = function(elm) {
  145. // if there's an array of breakpoints
  146. if (typeof elm === 'object') {
  147. if (elm.join().indexOf(curr) >= 0) {
  148. return true;
  149. }
  150. // if the string is '*' then run at every breakpoint
  151. } else if (elm === '*') {
  152. return true;
  153. // or if it's a single breakpoint
  154. } else if (typeof elm === 'string') {
  155. if (curr === elm) {
  156. return true;
  157. }
  158. }
  159. };
  160. // self-calling function that checks the browser width and delegates if it detects a change
  161. var checkResize = function() {
  162. // get current width
  163. var w = winWidth();
  164. // if there is a change speed up the timer and fire the returnBreakpoint function
  165. if (w !== resizeW) {
  166. resizeTmrSpd = resizeTmrFast;
  167. returnBreakpoint(w);
  168. // otherwise keep on keepin' on
  169. } else {
  170. resizeTmrSpd = resizeTmrSlow;
  171. }
  172. resizeW = w;
  173. // calls itself on a setTimeout
  174. setTimeout(checkResize, resizeTmrSpd);
  175. };
  176. checkResize();
  177. // return
  178. return {
  179. addFunc: function(elm) { addFunction(elm); },
  180. getBreakpoint: function() { return curr; }
  181. };
  182. };
  183. }(this,this.document)));