loadCSS.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
  2. (function(w){
  3. "use strict";
  4. /* exported loadCSS */
  5. var loadCSS = function( href, before, media ){
  6. // Arguments explained:
  7. // `href` [REQUIRED] is the URL for your CSS file.
  8. // `before` [OPTIONAL] is the element the script should use as a reference for injecting our stylesheet <link> before
  9. // By default, loadCSS attempts to inject the link after the last stylesheet or script in the DOM. However, you might desire a more specific location in your document.
  10. // `media` [OPTIONAL] is the media type or query of the stylesheet. By default it will be 'all'
  11. var doc = w.document;
  12. var ss = doc.createElement( "link" );
  13. var ref;
  14. if( before ){
  15. ref = before;
  16. }
  17. else {
  18. var refs = ( doc.body || doc.getElementsByTagName( "head" )[ 0 ] ).childNodes;
  19. ref = refs[ refs.length - 1];
  20. }
  21. var sheets = doc.styleSheets;
  22. ss.rel = "stylesheet";
  23. ss.href = href;
  24. // temporarily set media to something inapplicable to ensure it'll fetch without blocking render
  25. ss.media = "only x";
  26. // wait until body is defined before injecting link. This ensures a non-blocking load in IE11.
  27. function ready( cb ){
  28. if( doc.body ){
  29. return cb();
  30. }
  31. setTimeout(function(){
  32. ready( cb );
  33. });
  34. }
  35. // Inject link
  36. // Note: the ternary preserves the existing behavior of "before" argument, but we could choose to change the argument to "after" in a later release and standardize on ref.nextSibling for all refs
  37. // Note: `insertBefore` is used instead of `appendChild`, for safety re: http://www.paulirish.com/2011/surefire-dom-element-insertion/
  38. ready( function(){
  39. ref.parentNode.insertBefore( ss, ( before ? ref : ref.nextSibling ) );
  40. });
  41. // A method (exposed on return object for external use) that mimics onload by polling document.styleSheets until it includes the new sheet.
  42. var onloadcssdefined = function( cb ){
  43. var resolvedHref = ss.href;
  44. var i = sheets.length;
  45. while( i-- ){
  46. if( sheets[ i ].href === resolvedHref ){
  47. return cb();
  48. }
  49. }
  50. setTimeout(function() {
  51. onloadcssdefined( cb );
  52. });
  53. };
  54. function loadCB(){
  55. if( ss.addEventListener ){
  56. ss.removeEventListener( "load", loadCB );
  57. }
  58. ss.media = media || "all";
  59. }
  60. // once loaded, set link's media back to `all` so that the stylesheet applies once it loads
  61. if( ss.addEventListener ){
  62. ss.addEventListener( "load", loadCB);
  63. }
  64. ss.onloadcssdefined = onloadcssdefined;
  65. onloadcssdefined( loadCB );
  66. return ss;
  67. };
  68. // commonjs
  69. if( typeof exports !== "undefined" ){
  70. exports.loadCSS = loadCSS;
  71. }
  72. else {
  73. w.loadCSS = loadCSS;
  74. }
  75. }( typeof global !== "undefined" ? global : this ));