Last active
February 1, 2017 21:37
-
-
Save benplum/8045336 to your computer and use it in GitHub Desktop.
matchMedia Polyfill w/ Listeners - IE8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 = '­<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