unit-caniuse.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. var myscript = document.createElement('script'),
  2. ref = document.getElementsByTagName('script')[0];
  3. myscript.src = 'http://caniuse.com/jsonp.php?callback=caniusecb';
  4. setTimeout(function(){
  5. ref.parentNode.insertBefore(myscript, ref);
  6. }, 100);
  7. // mapping Modernizr terms over to caniuse terms
  8. var map = {
  9. audio : 'audio',
  10. borderimage : 'border-image',
  11. borderradius : 'border-radius',
  12. canvas : 'canvas',
  13. canvastext : 'canvas-text',
  14. cssanimations : 'css-animation',
  15. boxshadow : 'css-boxshadow',
  16. cssgradients : 'css-gradients',
  17. opacity : 'css-opacity',
  18. cssreflections : 'css-reflections',
  19. textshadow : 'css-textshadow',
  20. csstransitions : 'css-transitions',
  21. hsla : 'css3-colors',
  22. rgba : 'css3-colors',
  23. draganddrop : 'dragndrop',
  24. flexbox : 'flexbox',
  25. fontface : 'fontface',
  26. geolocation : 'geolocation',
  27. hashchange : 'hashchange',
  28. history : 'history',
  29. indexeddb : 'indexeddb',
  30. multiplebgs : 'multibackgrounds',
  31. csscolumns : 'multicolumn',
  32. localstorage : 'namevalue-storage',
  33. applicationcache : 'offline-apps',
  34. websqldatabase : 'sql-storage',
  35. svg : 'svg',
  36. touch : 'touch',
  37. csstransforms : 'transforms2d',
  38. csstransforms3d : 'transforms3d',
  39. video: 'video',
  40. webgl: 'webgl',
  41. websockets : 'websockets',
  42. webworkers : 'webworkers',
  43. postmessage : 'x-doc-messaging'
  44. };
  45. window.caniusecb = function(scriptdata) {
  46. window.doo = scriptdata;
  47. // quit if JSONSelect didn't make it.
  48. if (!window.JSONSelect) return;
  49. var testdata = scriptdata.data,
  50. // parse the current UA with uaparser
  51. ua = uaparse(navigator.userAgent),
  52. // match the UA from uaparser into the browser used by caniuse
  53. browserKey = JSONSelect.match('.agents .browser', scriptdata).indexOf(ua.family),
  54. currBrowser = Object.keys(scriptdata.agents)[browserKey];
  55. // So Phantom doesn't kill the caniuse.com matching exit out as it's useless anyway within PhantomJS
  56. if(navigator.userAgent.indexOf("PhantomJS") != -1) {
  57. return;
  58. }
  59. // translate 'y' 'n' or 'a' into a boolean that Modernizr uses
  60. function bool(ciuresult){
  61. if (ciuresult == 'y' || ciuresult == 'a') return true;
  62. // 'p' is for polyfill
  63. if (ciuresult == 'n' || ciuresult == 'p') return false;
  64. throw 'unknown return value from can i use';
  65. }
  66. function testify(o){
  67. var ciubool = bool(o.ciuresult);
  68. // caniuse says audio/video are yes/no, Modernizr has more detail which we'll dumb down.
  69. if (~TEST.audvid.indexOf(o.feature))
  70. o.result = !!o.result;
  71. // if caniuse gave us a 'partial', lets let it pass with a note.
  72. if (o.ciuresult == 'a'){
  73. return ok(true,
  74. o.browser + o.version + ': Caniuse reported partial support for ' + o.ciufeature +
  75. '. So.. Modernizr\'s ' + o.result + ' is good enough...'
  76. );
  77. }
  78. // change the *documented* false positives
  79. if ((o.feature == 'textshadow' && o.browser == 'firefox' && o.version == 3)
  80. && ciubool == false
  81. ) {
  82. ciubool = o.fp = true;
  83. }
  84. // where we actually do most our assertions
  85. equal(o.result, ciubool,
  86. o.browser + o.version + ': Caniuse result for ' + o.ciufeature +
  87. ' matches Modernizr\'s ' + (o.fp ? '*false positive*' : 'result') + ' for ' + o.feature
  88. );
  89. }
  90. module('caniuse.com data matches', {
  91. setup:function() {
  92. },
  93. teardown:function() {
  94. }
  95. });
  96. test("we match caniuse data", function() {
  97. for (var feature in Modernizr){
  98. var ciufeatname = map[feature];
  99. if (ciufeatname === undefined) continue;
  100. var ciufeatdata = testdata[ciufeatname];
  101. if (ciufeatdata === undefined) throw 'unknown key of caniusedata';
  102. // get results for this feature for all versions of this browser
  103. var browserResults = ciufeatdata.stats[currBrowser];
  104. // let's get our versions in order..
  105. var minorver = ua.minor && // caniuse doesn't use two digit minors
  106. ua.minor.toString().replace(/(\d)\d$/,'$1'), // but opera does.
  107. majorminor = (ua.major + '.' + minorver)
  108. // opera gets grouped in some cases by caniuse
  109. .replace(/(9\.(6|5))/ , ua.family == 'opera' ? '9.5-9.6' : "$1")
  110. .replace(/(10\.(0|1))/, ua.family == 'opera' ? '10.0-10.1' : "$1"),
  111. mmResult = browserResults[majorminor],
  112. mResult = browserResults[ua.major];
  113. // check it against the major.minor: eg. FF 3.6
  114. if (mmResult && mmResult != 'u'){ // 'y' 'n' or 'a'
  115. // data ends w/ ` x` if its still prefixed in the imp
  116. mmResult = mmResult.replace(' x','');
  117. // match it against our data.
  118. testify({ feature : feature
  119. , ciufeature : ciufeatname
  120. , result : Modernizr[feature]
  121. , ciuresult : mmResult
  122. , browser : currBrowser
  123. , version : majorminor
  124. });
  125. continue; // don't check the major version
  126. }
  127. // check it against just the major version: eg. FF 3
  128. if (mResult){
  129. // unknown support from caniuse... He would probably like to know our data, though!
  130. if (mResult == 'u') continue;
  131. // data ends w/ ` x` if its still prefixed in the imp
  132. mResult = mResult.replace(' x','');
  133. testify({ feature : feature
  134. , ciufeature : ciufeatname
  135. , result : Modernizr[feature]
  136. , ciuresult : mResult
  137. , browser : currBrowser
  138. , version : ua.major
  139. });
  140. }
  141. } // for in loop
  142. }); // eo test()
  143. }; // eo caniusecallback()