Skip to content

Instantly share code, notes, and snippets.

@jonathantneal
Created June 27, 2014 17:56
Show Gist options
  • Save jonathantneal/ccbafbba928225004ee9 to your computer and use it in GitHub Desktop.
Save jonathantneal/ccbafbba928225004ee9 to your computer and use it in GitHub Desktop.
window.matchMedia + addListener/removeListener for all browsers
if (!this.matchMedia) {
(function (WINDOW, LISTENER) {
function evalQuery(window, query) {
var
screen = window.screen,
screenHeight = screen.height,
screenWidth = screen.width,
documentElement = window.document.documentElement,
height = window.innerHeight || documentElement.clientHeight,
width = window.innerWidth || documentElement.clientWidth,
colorIndex = screen.colorDepth || 16;
return new Function(
'media',
'return (' + query
.replace(/^only\s+/, '')
.replace(/device-([\w-]+)/g, function ($0, $1) {
return 'device.'+$1.replace(/-/g, '');
})
.replace(/([\w.]+)\s*:/g, 'media.$1 ===')
.replace(/min-([\w.]+)\s*===/g, '$1 >=')
.replace(/max-([\w.]+)\s*===/g, '$1 <=')
.replace(/all|screen/g, '1')
.replace(/aural|braille|embossed|handheld|print|projection|tty|tv/g, '0')
.replace(/\s*,\s*/g, ')||(')
.replace(/and/g, '&&')
.replace(/(\d+)(cm|dpi|em|in|mm|pc|pt|px|rem)/, function ($0, $1, $2) {
return $1 * (
$2 === 'cm' ? 0.3937 * 96 : (
$2 === 'em' || $2 === 'rem' ? 16 : (
$2 === 'in' ? 96 : (
$2 === 'mm' ? 0.3937 * 96 / 10 : (
$2 === 'pc' ? 12 * 96 / 72 : (
$2 === 'pt' ? 96 / 72 : 1
)
)
)
)
)
);
}) + ')'
)({
aspectratio: height / width,
color: colorIndex > 2,
colorindex: colorIndex,
device: {
aspectratio: screenHeight / screenWidth,
height: screenHeight,
width: screenWidth
},
height: height,
monochrome: colorIndex <= 2,
orientation: window.orientation || height > width ? 'portrait' : 'landscape',
resolution: screen.deviceXDPI || window.devicePixelRatio * 96 || 96,
width: width
});
}
function MediaQueryList() {
this.matches = false;
this.media = 'invalid';
}
MediaQueryList.prototype.addListener = function addListener(listener) {
this._listeners.push(listener);
};
MediaQueryList.prototype.removeListener = function removeListener(listener) {
for (var index = 0, item; item = this._listeners[index]; ++index) {
if (item === listener) {
this._listeners.splice(index, 1);
return;
}
}
};
WINDOW.matchMedia = function (query) {
var
window = this,
list = new MediaQueryList();
list._listeners = [];
list.media = String(query);
list.matches = evalQuery(window, list.media);
window[LISTENER[0]](LISTENER[1] + 'resize', function () {
var listeners = [].concat(list._listeners), matches = evalQuery(window, list.media);
if (matches !== list.matches) {
list.matches = matches;
for (var index = 0, length = listeners.length; index < length; ++index) {
listeners[index].call(window, list);
}
}
});
return list;
};
})(
this.Window ? Window.prototype : this,
this.addEventListener ? ['addEventListener', ''] : ['attachEvent', 'on']
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment