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;