matchMedia.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas, David Knight. Dual MIT/BSD license */
  2. window.matchMedia || (window.matchMedia = function() {
  3. "use strict";
  4. // For browsers that support matchMedium api such as IE 9 and webkit
  5. var styleMedia = (window.styleMedia || window.media);
  6. // For those that don't support matchMedium
  7. if (!styleMedia) {
  8. var style = document.createElement('style'),
  9. script = document.getElementsByTagName('script')[0],
  10. info = null;
  11. style.type = 'text/css';
  12. style.id = 'matchmediajs-test';
  13. script.parentNode.insertBefore(style, script);
  14. // 'style.currentStyle' is used by IE <= 8 and 'window.getComputedStyle' for all other browsers
  15. info = ('getComputedStyle' in window) && window.getComputedStyle(style, null) || style.currentStyle;
  16. styleMedia = {
  17. matchMedium: function(media) {
  18. var text = '@media ' + media + '{ #matchmediajs-test { width: 1px; } }';
  19. // 'style.styleSheet' is used by IE <= 8 and 'style.textContent' for all other browsers
  20. if (style.styleSheet) {
  21. style.styleSheet.cssText = text;
  22. } else {
  23. style.textContent = text;
  24. }
  25. // Test if media query is true or false
  26. return info.width === '1px';
  27. }
  28. };
  29. }
  30. return function(media) {
  31. return {
  32. matches: styleMedia.matchMedium(media || 'all'),
  33. media: media || 'all'
  34. };
  35. };
  36. }());
  37. /*! matchMedia() polyfill addListener/removeListener extension. Author & copyright (c) 2012: Scott Jehl. Dual MIT/BSD license */
  38. (function() {
  39. // Bail out for browsers that have addListener support
  40. if (window.matchMedia && window.matchMedia('all').addListener) {
  41. return false;
  42. }
  43. var localMatchMedia = window.matchMedia,
  44. hasMediaQueries = localMatchMedia('only all').matches,
  45. isListening = false,
  46. timeoutID = 0, // setTimeout for debouncing 'handleChange'
  47. queries = [], // Contains each 'mql' and associated 'listeners' if 'addListener' is used
  48. handleChange = function(evt) {
  49. // Debounce
  50. clearTimeout(timeoutID);
  51. timeoutID = setTimeout(function() {
  52. for (var i = 0, il = queries.length; i < il; i++) {
  53. var mql = queries[i].mql,
  54. listeners = queries[i].listeners || [],
  55. matches = localMatchMedia(mql.media).matches;
  56. // Update mql.matches value and call listeners
  57. // Fire listeners only if transitioning to or from matched state
  58. if (matches !== mql.matches) {
  59. mql.matches = matches;
  60. for (var j = 0, jl = listeners.length; j < jl; j++) {
  61. listeners[j].call(window, mql);
  62. }
  63. }
  64. }
  65. }, 30);
  66. };
  67. window.matchMedia = function(media) {
  68. var mql = localMatchMedia(media),
  69. listeners = [],
  70. index = 0;
  71. mql.addListener = function(listener) {
  72. // Changes would not occur to css media type so return now (Affects IE <= 8)
  73. if (!hasMediaQueries) {
  74. return;
  75. }
  76. // Set up 'resize' listener for browsers that support CSS3 media queries (Not for IE <= 8)
  77. // There should only ever be 1 resize listener running for performance
  78. if (!isListening) {
  79. isListening = true;
  80. window.addEventListener('resize', handleChange, true);
  81. }
  82. // Push object only if it has not been pushed already
  83. if (index === 0) {
  84. index = queries.push({
  85. mql: mql,
  86. listeners: listeners
  87. });
  88. }
  89. listeners.push(listener);
  90. };
  91. mql.removeListener = function(listener) {
  92. for (var i = 0, il = listeners.length; i < il; i++) {
  93. if (listeners[i] === listener) {
  94. listeners.splice(i, 1);
  95. }
  96. }
  97. };
  98. return mql;
  99. };
  100. }());
  101. window.mediaCheck = function(options) {
  102. var mq;
  103. function mqChange(mq, options) {
  104. if (mq.matches) {
  105. if (typeof options.entry === "function") {
  106. options.entry();
  107. }
  108. } else if (typeof options.exit === "function") {
  109. options.exit();
  110. }
  111. };
  112. mq = window.matchMedia(options.media);
  113. mq.addListener(function() {
  114. mqChange(mq, options);
  115. });
  116. mqChange(mq, options);
  117. };