var myscript = document.createElement('script'), ref = document.getElementsByTagName('script')[0]; myscript.src = 'http://caniuse.com/jsonp.php?callback=caniusecb'; setTimeout(function(){ ref.parentNode.insertBefore(myscript, ref); }, 100); // mapping Modernizr terms over to caniuse terms var map = { audio : 'audio', borderimage : 'border-image', borderradius : 'border-radius', canvas : 'canvas', canvastext : 'canvas-text', cssanimations : 'css-animation', boxshadow : 'css-boxshadow', cssgradients : 'css-gradients', opacity : 'css-opacity', cssreflections : 'css-reflections', textshadow : 'css-textshadow', csstransitions : 'css-transitions', hsla : 'css3-colors', rgba : 'css3-colors', draganddrop : 'dragndrop', flexbox : 'flexbox', fontface : 'fontface', geolocation : 'geolocation', hashchange : 'hashchange', history : 'history', indexeddb : 'indexeddb', multiplebgs : 'multibackgrounds', csscolumns : 'multicolumn', localstorage : 'namevalue-storage', applicationcache : 'offline-apps', websqldatabase : 'sql-storage', svg : 'svg', touch : 'touch', csstransforms : 'transforms2d', csstransforms3d : 'transforms3d', video: 'video', webgl: 'webgl', websockets : 'websockets', webworkers : 'webworkers', postmessage : 'x-doc-messaging' }; window.caniusecb = function(scriptdata) { window.doo = scriptdata; // quit if JSONSelect didn't make it. if (!window.JSONSelect) return; var testdata = scriptdata.data, // parse the current UA with uaparser ua = uaparse(navigator.userAgent), // match the UA from uaparser into the browser used by caniuse browserKey = JSONSelect.match('.agents .browser', scriptdata).indexOf(ua.family), currBrowser = Object.keys(scriptdata.agents)[browserKey]; // So Phantom doesn't kill the caniuse.com matching exit out as it's useless anyway within PhantomJS if(navigator.userAgent.indexOf("PhantomJS") != -1) { return; } // translate 'y' 'n' or 'a' into a boolean that Modernizr uses function bool(ciuresult){ if (ciuresult == 'y' || ciuresult == 'a') return true; // 'p' is for polyfill if (ciuresult == 'n' || ciuresult == 'p') return false; throw 'unknown return value from can i use'; } function testify(o){ var ciubool = bool(o.ciuresult); // caniuse says audio/video are yes/no, Modernizr has more detail which we'll dumb down. if (~TEST.audvid.indexOf(o.feature)) o.result = !!o.result; // if caniuse gave us a 'partial', lets let it pass with a note. if (o.ciuresult == 'a'){ return ok(true, o.browser + o.version + ': Caniuse reported partial support for ' + o.ciufeature + '. So.. Modernizr\'s ' + o.result + ' is good enough...' ); } // change the *documented* false positives if ((o.feature == 'textshadow' && o.browser == 'firefox' && o.version == 3) && ciubool == false ) { ciubool = o.fp = true; } // where we actually do most our assertions equal(o.result, ciubool, o.browser + o.version + ': Caniuse result for ' + o.ciufeature + ' matches Modernizr\'s ' + (o.fp ? '*false positive*' : 'result') + ' for ' + o.feature ); } module('caniuse.com data matches', { setup:function() { }, teardown:function() { } }); test("we match caniuse data", function() { for (var feature in Modernizr){ var ciufeatname = map[feature]; if (ciufeatname === undefined) continue; var ciufeatdata = testdata[ciufeatname]; if (ciufeatdata === undefined) throw 'unknown key of caniusedata'; // get results for this feature for all versions of this browser var browserResults = ciufeatdata.stats[currBrowser]; // let's get our versions in order.. var minorver = ua.minor && // caniuse doesn't use two digit minors ua.minor.toString().replace(/(\d)\d$/,'$1'), // but opera does. majorminor = (ua.major + '.' + minorver) // opera gets grouped in some cases by caniuse .replace(/(9\.(6|5))/ , ua.family == 'opera' ? '9.5-9.6' : "$1") .replace(/(10\.(0|1))/, ua.family == 'opera' ? '10.0-10.1' : "$1"), mmResult = browserResults[majorminor], mResult = browserResults[ua.major]; // check it against the major.minor: eg. FF 3.6 if (mmResult && mmResult != 'u'){ // 'y' 'n' or 'a' // data ends w/ ` x` if its still prefixed in the imp mmResult = mmResult.replace(' x',''); // match it against our data. testify({ feature : feature , ciufeature : ciufeatname , result : Modernizr[feature] , ciuresult : mmResult , browser : currBrowser , version : majorminor }); continue; // don't check the major version } // check it against just the major version: eg. FF 3 if (mResult){ // unknown support from caniuse... He would probably like to know our data, though! if (mResult == 'u') continue; // data ends w/ ` x` if its still prefixed in the imp mResult = mResult.replace(' x',''); testify({ feature : feature , ciufeature : ciufeatname , result : Modernizr[feature] , ciuresult : mResult , browser : currBrowser , version : ua.major }); } } // for in loop }); // eo test() }; // eo caniusecallback()