Skip to content

Instantly share code, notes, and snippets.

@pakpenyo
Forked from benplum/matchMedia - IE8
Created May 15, 2014 15:42

Revisions

  1. @benplum benplum created this gist Dec 19, 2013.
    130 changes: 130 additions & 0 deletions matchMedia - IE8
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,130 @@
    /*! 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;
    };
    }
    }());