Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
matchMedia Polyfill w/ Listeners - IE8
// Modernizr style test
if (!(window.webkitMatchMedia || window.mozMatchMedia || window.oMatchMedia || window.msMatchMedia || window.matchMedia)) {
var root = document.getElementsByTagName( 'html' )[0];
root.className += ' no-matchmedia';
}
/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license - IE8 VERSION! */
window.matchMedia = window.matchMedia || (function(doc, undefined){
var docElem = doc.documentElement,
refNode = docElem.firstElementChild || docElem.firstChild,
// fakeBody required for <FF4 when executed in <head>
fakeBody = doc.createElement('body'),
div = doc.createElement('div');
div.id = 'mq-test-1';
div.style.cssText = "position:absolute;top:-100em";
fakeBody.style.background = "none";
fakeBody.appendChild(div);
var mqRun = function ( mq ) {
div.innerHTML = '&shy;<style media="' + mq + '"> #mq-test-1 { width: 42px; }</style>';
docElem.insertBefore( fakeBody, refNode );
bool = div.offsetWidth === 42;
docElem.removeChild( fakeBody );
return { matches: bool, media: mq };
},
getEmValue = function () {
var ret,
body = docElem.body,
fakeUsed = false;
div.style.cssText = "position:absolute;font-size:1em;width:1em";
if( !body ) {
body = fakeUsed = doc.createElement( "body" );
body.style.background = "none";
}
body.appendChild( div );
docElem.insertBefore( body, docElem.firstChild );
if( fakeUsed ) {
docElem.removeChild( body );
} else {
body.removeChild( div );
}
//also update eminpx before returning
ret = eminpx = parseFloat( div.offsetWidth );
return ret;
},
//cached container for 1em value, populated the first time it's needed
eminpx,
// verify that we have support for a simple media query
mqSupport = mqRun( '(min-width: 0px)' ).matches;
return function ( mq ) {
if( mqSupport ) {
return mqRun( mq );
} else {
if (doc.body) {
var min = mq.match( /\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ),
max = mq.match( /\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ),
minnull = min === null,
maxnull = max === null,
currWidth = doc.body.offsetWidth,
em = 'em';
if( !!min ) { min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 ); }
if( !!max ) { max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 ); }
bool = ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max );
return { matches: bool, media: mq };
} else {
return { matches: false, media: {} };
}
}
};
}( document ));
/*! matchMedia() polyfill addListener/removeListener extension. Author & copyright (c) 2012: Scott Jehl. Dual MIT/BSD license - IE8 VERSION! */
(function(){
// monkeypatch unsupported addListener/removeListener with polling
if(typeof window.matchMedia( "" ) !== "undefined"){
var oldMM = window.matchMedia;
window.matchMedia = function( q ){
var ret = oldMM( q ),
listeners = [],
last = false,
timer,
check = function(){
var list = oldMM( q ),
unmatchToMatch = list.matches && !last,
matchToUnmatch = !list.matches && last;
//fire callbacks only if transitioning to or from matched state
if( unmatchToMatch || matchToUnmatch ){
for( var i =0, il = listeners.length; i< il; i++ ){
listeners[ i ].call( ret, list );
}
}
last = list.matches;
};
ret.addListener = function( cb ){
listeners.push( cb );
if( !timer ){
timer = setInterval( check, 1000 );
}
};
ret.removeListener = function( cb ){
for( var i =0, il = listeners.length; i< il; i++ ){
if( listeners[ i ] === cb ){
listeners.splice( i, 1 );
}
}
if( !listeners.length && timer ){
clearInterval( timer );
}
};
return ret;
};
}
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment