All files / src/domain/MediaQuery index.js

0% Statements 0/51
0% Branches 0/25
0% Functions 0/7
0% Lines 0/49
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107                                                                                                                                                                                                                     
let styleMedia = window.styleMedia || window.media;
 
// For those that don't support matchMedium
if (! styleMedia) {
  const style = document.createElement('style');
  const script = document.getElementsByTagName('script')[0];
 
  style.type = 'text/css';
  style.id = 'matchmediajs-test';
 
  script.parentNode.insertBefore(style, script);
 
  // 'style.currentStyle' is used by IE <= 8 and 'window.getComputedStyle' for all other browsers
  const info = ('getComputedStyle' in window && window.getComputedStyle(style, null)) ||
    style.currentStyle;
 
  styleMedia = {
    matchMedium: (media) => {
      const text = `@media ${media}{ #matchmediajs-test { width: 1px; } }`;
 
      // 'style.styleSheet' is used by IE <= 8 and 'style.textContent' for all other browsers
      if (style.styleSheet) {
        style.styleSheet.cssText = text;
      } else {
        style.textContent = text;
      }
 
      // Test if media query is true or false
      return info.width === '1px';
    },
  };
}
 
const localMatchMedia = (media) => ({
  matches: styleMedia.matchMedium(media || 'all'),
  media: media || 'all',
});
 
const hasMediaQueries = localMatchMedia('only all').matches;
let isListening = false;
let timeoutID = 0;// setTimeout for debouncing 'handleChange'
const queries = [];// Contains each 'mql' and associated 'listeners' if 'addListener' is used
const handleChange = () => {
  // Debounce
  clearTimeout(timeoutID);
 
  timeoutID = setTimeout(() => {
    for (let i = 0, il = queries.length; i < il; i++) {
      const mql = queries[i].mql;
      const listeners = queries[i].listeners || [];
      const matches = localMatchMedia(mql.media).matches;
 
      // Update mql.matches value and call listeners
      // Fire listeners only if transitioning to or from matched state
      if (matches !== mql.matches) {
        mql.matches = matches;
 
        for (let j = 0, jl = listeners.length; j < jl; j++) {
          listeners[j].call(window, mql);
        }
      }
    }
  }, 30);
};
 
export const mediaQuery = (media) => {
  const mql = localMatchMedia(media);
  const listeners = [];
  let index = 0;
 
  mql.addListener = (listener) => {
    // Changes would not occur to css media type so return now (Affects IE <= 8)
    if (! hasMediaQueries) {
      return;
    }
 
    // Set up 'resize' listener for browsers that support CSS3 media queries (Not for IE <= 8)
    // There should only ever be 1 resize listener running for performance
    if (! isListening) {
      isListening = true;
      window.addEventListener('resize', handleChange, true);
    }
 
    // Push object only if it has not been pushed already
    if (index === 0) {
      index = queries.push({
        mql,
        listeners,
      });
    }
 
    listeners.push(listener);
  };
 
  mql.removeListener = (listener) => {
    for (let i = 0, il = listeners.length; i < il; i++) {
      if (listeners[i] === listener) {
        listeners.splice(i, 1);
      }
    }
  };
 
  return mql;
};
 
export default mediaQuery;