diff --git a/src/assets/js/loadCSS.js b/src/assets/js/loadCSS.js new file mode 100644 index 0000000..68142a5 --- /dev/null +++ b/src/assets/js/loadCSS.js @@ -0,0 +1,89 @@ +/*! loadCSS. [c]2020 Filament Group, Inc. MIT License */ +// https://github.com/filamentgroup/loadCSS +(function(w){ + "use strict"; + /* exported loadCSS */ + var loadCSS = function( href, before, media, attributes ){ + // Arguments explained: + // `href` [REQUIRED] is the URL for your CSS file. + // `before` [OPTIONAL] is the element the script should use as a reference for injecting our stylesheet before + // 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. + // `media` [OPTIONAL] is the media type or query of the stylesheet. By default it will be 'all' + // `attributes` [OPTIONAL] is the Object of attribute name/attribute value pairs to set on the stylesheet's DOM Element. + var doc = w.document; + var ss = doc.createElement( "link" ); + var ref; + if( before ){ + ref = before; + } + else { + var refs = ( doc.body || doc.getElementsByTagName( "head" )[ 0 ] ).childNodes; + ref = refs[ refs.length - 1]; + } + + var sheets = doc.styleSheets; + // Set any of the provided attributes to the stylesheet DOM Element. + if( attributes ){ + for( var attributeName in attributes ){ + if( attributes.hasOwnProperty( attributeName ) ){ + ss.setAttribute( attributeName, attributes[attributeName] ); + } + } + } + ss.rel = "stylesheet"; + ss.href = href; + // temporarily set media to something inapplicable to ensure it'll fetch without blocking render + ss.media = "only x"; + + // wait until body is defined before injecting link. This ensures a non-blocking load in IE11. + function ready( cb ){ + if( doc.body ){ + return cb(); + } + setTimeout(function(){ + ready( cb ); + }); + } + // Inject link + // 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 + // Note: `insertBefore` is used instead of `appendChild`, for safety re: http://www.paulirish.com/2011/surefire-dom-element-insertion/ + ready( function(){ + ref.parentNode.insertBefore( ss, ( before ? ref : ref.nextSibling ) ); + }); + // A method (exposed on return object for external use) that mimics onload by polling document.styleSheets until it includes the new sheet. + var onloadcssdefined = function( cb ){ + var resolvedHref = ss.href; + var i = sheets.length; + while( i-- ){ + if( sheets[ i ].href === resolvedHref ){ + return cb(); + } + } + setTimeout(function() { + onloadcssdefined( cb ); + }); + }; + + function loadCB(){ + if( ss.addEventListener ){ + ss.removeEventListener( "load", loadCB ); + } + ss.media = media || "all"; + } + + // once loaded, set link's media back to `all` so that the stylesheet applies once it loads + if( ss.addEventListener ){ + ss.addEventListener( "load", loadCB); + } + ss.onloadcssdefined = onloadcssdefined; + onloadcssdefined( loadCB ); + return ss; + }; + // commonjs + if( typeof exports !== "undefined" ){ + exports.loadCSS = loadCSS; + } + else { + w.loadCSS = loadCSS; + } +}( typeof global !== "undefined" ? global : this )); \ No newline at end of file diff --git a/src/extend/Util.js b/src/extend/Util.js index 21398b2..f741557 100755 --- a/src/extend/Util.js +++ b/src/extend/Util.js @@ -1,4 +1,5 @@ import {modifyNodeId} from '../assets/js/common' +import {loadCSS} from '../assets/js/loadCSS' import Server from './Server' import htmlToCanvas from 'html2canvas' let config = require('../config/index') @@ -58,6 +59,48 @@ function loadJs (url = '') { } } +function loadCss (url = '') { + if (!url) return + if (!loadCss.cache) loadCss.cache = {} + + if (loadCss.cache[url]) return Promise.resolve() + + return new Promise((resolve) => { + var stylesheet = loadCSS(url) + + onloadCSS(stylesheet, () => { + loadCss.cache[url] = 'cached' + resolve() + }) + }) + + // https://github.com/filamentgroup/loadCSS/blob/master/src/onloadCSS.js + function onloadCSS (ss, callback) { + var called + function newcb() { + if (!called && callback) { + called = true + callback.call(ss) + } + } + if (ss.addEventListener) { + ss.addEventListener('load', newcb) + } + if (ss.attachEvent) { + ss.attachEvent('onload', newcb) + } + // This code is for browsers that don’t support onload + // No support for onload (it'll bind but never fire): + // * Android 4.3 (Samsung Galaxy S4, Browserstack) + // * Android 4.2 Browser (Samsung Galaxy SIII Mini GT-I8200L) + // * Android 2.3 (Pantech Burst P9070) + // Weak inference targets Android < 4.4 + if ('isApplicationInstalled' in navigator && 'onloadcssdefined' in ss) { + ss.onloadcssdefined(newcb) + } + } +} + function getBaseNode (node) { if (!node.id) return useComponent(node.id) @@ -156,6 +199,7 @@ export default { html2canvas, removeAttr, loadJs, + loadCss, getBaseNode, useComponent, getNumber, @@ -168,6 +212,7 @@ export { html2canvas, removeAttr, loadJs, + loadCss, getBaseNode, useComponent, getNumber,