API Docs for:
Show:

File: development/js/utils/mq.js

import type from './type';


/**
 * Provides the mediaQuery helper
 *
 * @module Utils
 * @class Utils.MQ
 * @static
 */


/**
 * Creates a media query object with enhanced capabilities like adding event
 *     listeners
 *
 * @method mediaQuery
 * @for Utils.MQ
 * @param {string} mediaQuery The media query
 * @return {object} Media query object
 *
 * @example
 *     import mediaQuery from './utils/supports';
 *     
 *     var mq1 = mediaQuery('screen and (min-width: 600px)');
 *
 *     if (mq1.matches) {
 *         // do something if the screen is 600 or more pixels wide
 *     }
 *
 *
 *     mq1.addListener(function () {
 *         // called every time the media query matches
 *     });
 *     
 */
const mediaQuery = (function () {
    var styleMedia,
        isListening,
        hasQueries,
        timeoutId,
        listeningQueries,
        resizeHandle,
        docHead,
        style,
        info;

    if (type.isFunction(window.matchMedia) && type.isFunction(window.matchMedia('all').addListener)) {
        return (mediaQuery) => window.matchMedia(mediaQuery);
    }

    styleMedia = window.styleMedia || window.media;
    if (!styleMedia) {
        docHead = document.getElementsByTagName('head')[0];
        style = document.createElement('style');

        style.type = 'text/css';
        style.id = 'mediaquerypolyfill-test';

        docHead.appendChild(style);
        info = type.isFunction(window.getComputedStyle) ?
               window.getComputedStyle(style, null) :
               style.currentStyle;

        styleMedia = {
            matchMedium: function (m) {
                m = '@media ' + String(m).toLowerCase() + '{#mediaquerypolyfill-test { width: 1px; }}';

                if (style.styleSheet) {
                    style.styleSheet.cssText = m;
                } else {
                    style.textContent = m;
                }

                return info.width === '1px';
            }
        };
    }

    hasQueries = styleMedia.matchMedium('only all').matches;
    listeningQueries = [];
    resizeHandle = function () {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(function () {
            listeningQueries.forEach((query) => {
                var _match = styleMedia(query.media).matches;

                if (query.listeners === undefined) {
                    query.listeners = [];
                }

                if (_match !== query.matches) {
                    query.matches = _match;
                    query.listeners.forEach((f) => f(query));
                }
            })
        }, 50);
    };

    return function (mediaQuery) {
        var mql = {},
            fns = [],
            fst;

        mql.matches = styleMedia.matchMedium(mediaQuery || 'all');
        mql.media = mediaQuery || 'all';
        mql.addListener = function (fn) {
            if (!hasQueries) {
                // no support for mediaqueries, ignore
                return;
            }

            if (!isListening) {
                isListening = true;
                window.addEventListener('resize', resizeHandle, true);
            }

            fns.push(fn);
            if (!fst) {
                fst = !!listeningQueries.push({
                    media: mql.media,
                    matches: mql.matches,
                    listeners: fns
                });
            }
        }
        mql.removeListener = function (fn) {
            fns = fns.filter((f) => f !== fn);
        }

        return mql;
    }
})();



export default mediaQuery;