From b08852a7a3473bb96a4eda905cba906d0b44a085 Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Tue, 5 Feb 2019 09:34:12 +0000 Subject: [PATCH 01/21] Allow array of initialisation functions Closes part of #8 Allow the passing of array of values to run once polyfills have been loaded. --- dynamicpolyfill.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/dynamicpolyfill.js b/dynamicpolyfill.js index 36662cb..e56df9c 100644 --- a/dynamicpolyfill.js +++ b/dynamicpolyfill.js @@ -66,8 +66,18 @@ function loadMyScript(url) { } function initialiseMyScript(functionToRunonLoad) { - console.log("The following script will now be initialised:", functionToRunonLoad); - return new Function(functionToRunonLoad); + if(functionToRunonLoad.isArray) { + var fnlen = functionToRunonLoad.length + for (var n = 0; n < fnlen; n++) { + var fn = functionToRunonLoad[n] + console.log("The following script will now be initialised:", fn); + return new Function(fn); + } + + } else { + console.log("The following script will now be initialised:", functionToRunonLoad); + return new Function(functionToRunonLoad); + } } function loadPolyfill(url) { From 735030e54ee19989065cc5dcb65fe54e4492aee1 Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Tue, 5 Feb 2019 10:31:58 +0000 Subject: [PATCH 02/21] Major work - array all the things! Allow array to be passed for: * `features` (parameter 1) * `scriptURL` (parameter 2) * `initFunction` (parameter 3) You can still pass strings if you want though --- dynamicpolyfill.js | 109 ++++++++++++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 42 deletions(-) diff --git a/dynamicpolyfill.js b/dynamicpolyfill.js index e56df9c..fbe51b7 100644 --- a/dynamicpolyfill.js +++ b/dynamicpolyfill.js @@ -6,26 +6,23 @@ function dynamicPolyfill (features, scriptURL, initFunction) { } function pageLoaded(polyfillFeatures, scriptToPolyfill, functionToRunonLoad) { - Promise.all([checkNativeSupport(polyfillFeatures)]) - .then( - function() { - loadMyScript(scriptToPolyfill) - .then( +Promise.all([checkNativeSupport(polyfillFeatures), loadMyScript(scriptToPolyfill)]) + .then( + function() { initialiseMyScript(functionToRunonLoad) - ).catch(function(error){return error}) - } - ).catch(function(error){return error}) - ,function () { - console.error("There was an issue polyfilling",mayneedpolyfill," which means that I can't preload future pages for you. Sorry! :("); - console.warn("If you want this to work, I'd recommend upgrading to a browser that supports",mayneedpolyfill,"natively. You can find out which browsers do by visting: https://caniuse.com/"); - } + } + ).catch(function(error){return error}) + ,function () { + console.error("There was an issue polyfilling",mayneedpolyfill," which means that I can't preload future pages for you. Sorry! :("); + console.warn("If you want this to work, I'd recommend upgrading to a browser that supports",mayneedpolyfill,"natively. You can find out which browsers do by visting: https://caniuse.com/"); +} } function checkNativeSupport(tocheck) { - var num = tocheck.length; //cache value out of the for loop + var polen = tocheck.length; //cache value out of the for loop var polyfillNeeded = []; - for (var i = 0; i < num; i++) { - var pol = tocheck[i]; + for (var p = 0; p < polen; p++) { + var pol = tocheck[p]; var splitChars = '.'; var split = pol.split(splitChars); var firstWord = window[split[0]]; @@ -42,38 +39,66 @@ function checkNativeSupport(tocheck) { } function loadMyScript(url) { - if(url !== null && url !== '') { - return new Promise( - function(resolve, reject) { - var thescript = document.createElement('script'); - thescript.src = encodeURI(url); - document.getElementsByTagName('body')[0].appendChild(thescript); - thescript.onerror = function(response) { - return reject("Loading the script failed!", response); - } - thescript.onload = function() { - return resolve("Script setup and ready to load!"); - } + if(Array.isArray(url)) { + var urlen = url.length; + console.log(urlen); + for (var u = 0; u < urlen; u++) { + var uri = url[u]; + if(uri !== null && uri !== '') { + return new Promise( + function(resolve, reject) { + var thescript = document.createElement('script'); + thescript.src = encodeURI(uri); + document.body.appendChild(thescript); + thescript.onerror = function(response) { + return reject("Loading the script failed!", response); + } + thescript.onload = function() { + return resolve("Script setup and ready to load!"); + } + } + ) + } else { + return new Promise( + function(resolve, reject) { + return resolve ("No script to load"); + } + ) } - ) + } } else { - return new Promise( - function(resolve, reject) { - return resolve ("No script to load"); - } - ) + if(url !== null && url !== '') { + return new Promise( + function(resolve, reject) { + var thescript = document.createElement('script'); + thescript.src = encodeURI(url); + document.body.appendChild(thescript); + thescript.onerror = function(response) { + return reject("Loading the script failed!", response); + } + thescript.onload = function() { + return resolve("Script setup and ready to load!"); + } + } + ) + } else { + return new Promise( + function(resolve, reject) { + return resolve ("No script to load"); + } + ) + } } } function initialiseMyScript(functionToRunonLoad) { - if(functionToRunonLoad.isArray) { - var fnlen = functionToRunonLoad.length - for (var n = 0; n < fnlen; n++) { - var fn = functionToRunonLoad[n] - console.log("The following script will now be initialised:", fn); - return new Function(fn); - } - + var fns = []; + if(Array.isArray(functionToRunonLoad)) { + var fnlen = functionToRunonLoad.length; + for (var f = 0; f < fnlen; f++) { + var fn = new Function(functionToRunonLoad[f]); + try {fn();} catch(err) {console.error('There was an error: ', err.name, err.stack)} + } } else { console.log("The following script will now be initialised:", functionToRunonLoad); return new Function(functionToRunonLoad); @@ -85,7 +110,7 @@ function loadPolyfill(url) { function(resolve, reject) { var polyfill = document.createElement('script'); polyfill.src = ('https://polyfill.io/v3/polyfill.min.js?features='+encodeURIComponent(url)); - document.getElementsByTagName('body')[0].appendChild(polyfill); + document.body.appendChild(polyfill); polyfill.onerror = function(response) { return reject("Loading the polyfill(s) failed!", response); } From d89c2b15d1f513a05607eacbd25d78018ba28f86 Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Tue, 5 Feb 2019 10:34:33 +0000 Subject: [PATCH 03/21] Remove console.log It thought it could stay here... it couldn't! --- dynamicpolyfill.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/dynamicpolyfill.js b/dynamicpolyfill.js index fbe51b7..e11948e 100644 --- a/dynamicpolyfill.js +++ b/dynamicpolyfill.js @@ -6,16 +6,16 @@ function dynamicPolyfill (features, scriptURL, initFunction) { } function pageLoaded(polyfillFeatures, scriptToPolyfill, functionToRunonLoad) { -Promise.all([checkNativeSupport(polyfillFeatures), loadMyScript(scriptToPolyfill)]) - .then( - function() { - initialiseMyScript(functionToRunonLoad) - } + Promise.all([checkNativeSupport(polyfillFeatures), loadMyScript(scriptToPolyfill)]) + .then( + function() { + initialiseMyScript(functionToRunonLoad) + } ).catch(function(error){return error}) ,function () { - console.error("There was an issue polyfilling",mayneedpolyfill," which means that I can't preload future pages for you. Sorry! :("); - console.warn("If you want this to work, I'd recommend upgrading to a browser that supports",mayneedpolyfill,"natively. You can find out which browsers do by visting: https://caniuse.com/"); -} + console.error("There was an issue polyfilling",mayneedpolyfill," which means that I can't preload future pages for you. Sorry! :("); + console.warn("If you want this to work, I'd recommend upgrading to a browser that supports",mayneedpolyfill,"natively. You can find out which browsers do by visting: https://caniuse.com/"); + } } function checkNativeSupport(tocheck) { @@ -41,7 +41,6 @@ function checkNativeSupport(tocheck) { function loadMyScript(url) { if(Array.isArray(url)) { var urlen = url.length; - console.log(urlen); for (var u = 0; u < urlen; u++) { var uri = url[u]; if(uri !== null && uri !== '') { From c6076945cf0ba671d1facfcf5db204ff4cfea304 Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Tue, 5 Feb 2019 11:07:15 +0000 Subject: [PATCH 04/21] try catch fix Fix try/catch for init functions --- dynamicpolyfill.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dynamicpolyfill.js b/dynamicpolyfill.js index e11948e..2ddd9d8 100644 --- a/dynamicpolyfill.js +++ b/dynamicpolyfill.js @@ -96,8 +96,8 @@ function initialiseMyScript(functionToRunonLoad) { var fnlen = functionToRunonLoad.length; for (var f = 0; f < fnlen; f++) { var fn = new Function(functionToRunonLoad[f]); - try {fn();} catch(err) {console.error('There was an error: ', err.name, err.stack)} - } + try {fn();console.log(functionToRunonLoad[f], 'initialised successfully');} catch(err) {console.error('There was an error: ', err.name, err.stack)} + } } else { console.log("The following script will now be initialised:", functionToRunonLoad); return new Function(functionToRunonLoad); From 6164fd142a9f3abf31e7bd9a9dc8fea20e22d5f8 Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Tue, 5 Feb 2019 11:24:20 +0000 Subject: [PATCH 05/21] new dynamicPolyfill.js, with all the consoles Debugging/troubleshooting/fun messages added to each step, so you know where things go wrong - based on the new version of dynamicPolyfill.js --- dynamicpolyfill-consolemessages.js | 150 +++++++++++++++++++---------- 1 file changed, 97 insertions(+), 53 deletions(-) diff --git a/dynamicpolyfill-consolemessages.js b/dynamicpolyfill-consolemessages.js index 6b164f0..bad6133 100644 --- a/dynamicpolyfill-consolemessages.js +++ b/dynamicpolyfill-consolemessages.js @@ -1,80 +1,124 @@ //This file includes a bunch of console.log()/console.error()/console.warn() messages. Aides with troubleshooting, but is also a little fun if someone happens to come across them. They're not necessary at all tho'! function dynamicPolyfill (features, scriptURL, initFunction) { - var polyfillFeatures = features; - var scriptToPolyfill = scriptURL; - var functionToRunonLoad = initFunction; - return pageLoaded(polyfillFeatures, scriptToPolyfill, functionToRunonLoad); + var polyfillFeatures = features; + var scriptToPolyfill = scriptURL; + var functionToRunonLoad = initFunction; + return pageLoaded(polyfillFeatures, scriptToPolyfill, functionToRunonLoad); } function pageLoaded(polyfillFeatures, scriptToPolyfill, functionToRunonLoad) { - Promise.all([checkNativeSupport(polyfillFeatures)]) + Promise.all([checkNativeSupport(polyfillFeatures), loadMyScript(scriptToPolyfill)]) .then( - function() { - loadMyScript(scriptToPolyfill) - .then( - console.log("As the script is ready, let's initialise it..."); - initialiseMyScript(functionToRunonLoad) - ).catch(function(error){return error}) - } - ).catch(function(error){return error}) - ,function () { + function() { + console.log("As the script is ready, let's initialise it..."); + initialiseMyScript(functionToRunonLoad) + } + ).catch(function(error){return error}) + ,function () { console.error("There was an issue polyfilling",mayneedpolyfill," which means that I can't preload future pages for you. Sorry! :("); console.warn("If you want this to work, I'd recommend upgrading to a browser that supports",mayneedpolyfill,"natively. You can find out which browsers do by visting: https://caniuse.com/"); } } function checkNativeSupport(tocheck) { - var num = tocheck.length; //cache value out of the for loop - var polyfillNeeded = []; - for (var i = 0; i < num; i++) { - var pol = tocheck[i]; - var splitChars = '.'; - var split = pol.split(splitChars); - var firstWord = window[split[0]]; - var lastWord = new Object(split[split.length - 1]); + var polen = tocheck.length; //cache value out of the for loop + var polyfillNeeded = []; //we'll need this later to know if/what to polyfill + for (var p = 0; p < polen; p++) { //iterate through array + var pol = tocheck[p]; //cache this outside of if + var splitChars = '.'; //values to check for within array strings to know where to split + var split = pol.split(splitChars); //split string based on splitChars (in this case, a dot) + var firstWord = window[split[0]]; //cache outside of if - the first word (array item 0) + var lastWord = new Object(split[split.length - 1]); //cache outside of if - last word (last array value) if (typeof (window.pol) !== 'undefined' || pol in window || (pol.indexOf(splitChars) >= 1 && lastWord in firstWord) || pol in this) { console.log(pol,'has native support'); } else { - console.warn("Ahhh, your browser doesn't support",pol,". I'm gonna have to polyfill it so stuff works. Hang on one sec!"); + console.warn("Ahhh, your browser doesn't support",pol,". I'm gonna have to polyfill it so stuff works."); polyfillNeeded.push(pol); } } - if (polyfillNeeded.length > 0) { + if (polyfillNeeded.length > 0) { //this is where we "push" values and check whether we need to polyfill or not + console.warn('Right, we need to polyfill',polyfillNeeded); return loadPolyfill(polyfillNeeded); } } function loadMyScript(url) { - if(url !== null && url !== '') { - return new Promise( - function(resolve, reject) { - var thescript = document.createElement('script'); - thescript.src = encodeURI(url); - document.getElementsByTagName('body')[0].appendChild(thescript); - console.log('Loading ',thescript.src,'!'); - thescript.onerror = function(response) { - console.error ('Loading the script failed!'); - return reject("Loading the script failed!", response); - } - thescript.onload = function() { - console.log("Script setup and ready to load!"); - return resolve("Script setup and ready to load!"); - } + if(Array.isArray(url)) { //cater for array + var urlen = url.length; //cache value out of the for loop + for (var u = 0; u < urlen; u++) { + var uri = url[u]; //cache value out of if + if(uri !== null && uri !== '') { //handle blank or null values + return new Promise( + function(resolve, reject) { + var thescript = document.createElement('script'); + thescript.src = encodeURI(uri); + console.log('Loading ',uri); + document.body.appendChild(thescript); + thescript.onerror = function(response) { + console.error("Loading the script failed!); + return reject("Loading the script failed!", response); + } + thescript.onload = function() { + console.log("Script setup andready for use!"); + return resolve("Script setup and ready to load!"); + } + } + ) + } else { //blank or null values + return new Promise( + function(resolve, reject) { + console.log("No script to load"); + return resolve ("No script to load"); + } + ) } - ) - } else { - return new Promise( - function(resolve, reject) { - console.log("No script to load!"); - return resolve ("No script to load"); - } - ) + } + } else { //if not array + if(url !== null && url !== '') { //handle blank or null values + return new Promise( + function(resolve, reject) { + var thescript = document.createElement('script'); + thescript.src = encodeURI(url); + console.log("Loading ",url); + document.body.appendChild(thescript); + thescript.onerror = function(response) { + console.error("Loading the script failed"); + return reject("Loading the script failed!", response); + } + thescript.onload = function() { + console.log("Script setup andready for use!"); + return resolve("Script setup and ready to load!"); + } + } + ) + } else { //blank or null values + return new Promise( + function(resolve, reject) { + console.log("No script to load!"); + return resolve ("No script to load"); + } + ) + } } } function initialiseMyScript(functionToRunonLoad) { - console.log("The following script will now be initialised:", functionToRunonLoad); - return new Function(functionToRunonLoad); + if(Array.isArray(functionToRunonLoad)) { //cater for array + var fnlen = functionToRunonLoad.length; //cache outside of for loop + for (var f = 0; f < fnlen; f++) { + var fn = new Function(functionToRunonLoad[f]); //convert the strings to functions + try { + fn(); //execute the functions + console.log(functionToRunonLoad[f], 'initialised successfully'); //confirm execution + } + catch(err) { + console.error('There was an error: ', err.name, err.stack) + } + } + } else { //if not array + console.log("The following script will now be initialised:", functionToRunonLoad); + return new Function(functionToRunonLoad); //convert string to function and execute + } } function loadPolyfill(url) { @@ -82,14 +126,14 @@ function loadPolyfill(url) { function(resolve, reject) { var polyfill = document.createElement('script'); polyfill.src = ('https://polyfill.io/v3/polyfill.min.js?features='+encodeURIComponent(url)); - document.getElementsByTagName('body')[0].appendChild(polyfill); - console.log('Grabbing',url,'polyfill from: ', polyfill.src); + console.log('Grabbing',url,'polyfill from: ',polyfill.src); + document.body.appendChild(polyfill); polyfill.onerror = function(response) { - console.error ('Loading the polyfill(s) failed!'); + console.error("Loading the polyfill(s) failed!"); return reject("Loading the polyfill(s) failed!", response); } polyfill.onload = function() { - console.log("Polyfill(s) loaded!"); + console.log("Polyfill(s) loaded and ready for use!"); return resolve("Polyfill(s) loaded!"); } } From dd0a4c90c7340e3d6a4642774918b24859d78097 Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Tue, 5 Feb 2019 11:25:39 +0000 Subject: [PATCH 06/21] Allow arrays Allow arrays for all parameters Try catch Minification and uglification --- dynamicpolyfill.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dynamicpolyfill.min.js b/dynamicpolyfill.min.js index 6021d91..f5a9939 100644 --- a/dynamicpolyfill.min.js +++ b/dynamicpolyfill.min.js @@ -1 +1 @@ -function dynamicPolyfill(n,o,e){var t=n;var i=o;var r=e;return u(t,i,r)}function u(n,o,e){Promise.all([t(n)]).then(function(){i(o).then(r(e)).catch(function(n){return n})}).catch(function(n){return n}),function(){console.error("There was an issue polyfilling",mayneedpolyfill," which means that I can't preload future pages for you. Sorry! :(");console.warn("If you want this to work, I'd recommend upgrading to a browser that supports",mayneedpolyfill,"natively. You can find out which browsers do by visting: https://caniuse.com/")}}function t(n){var o=n.length;var e=[];for(var t=0;t=1&&c in a||i in this){console.log(i,"has native support")}else{e.push(i)}}if(e.length>0){return l(e)}}function i(t){if(t!==null&&t!==""){return new Promise(function(n,o){var e=document.createElement("script");e.src=encodeURI(t);document.getElementsByTagName("body")[0].appendChild(e);e.onerror=function(n){return o("Loading the script failed!",n)};e.onload=function(){return n("Script setup and ready to load!")}})}else{return new Promise(function(n,o){return n("No script to load")})}}function r(n){console.log("The following script will now be initialised:",n);return new Function(n)}function l(t){return new Promise(function(n,o){var e=document.createElement("script");e.src="https://polyfill.io/v3/polyfill.min.js?features="+encodeURIComponent(t);document.getElementsByTagName("body")[0].appendChild(e);e.onerror=function(n){return o("Loading the polyfill(s) failed!",n)};e.onload=function(){return n("Polyfill(s) loaded!")}})} +function dynamicPolyfill(n,e,o){var r=n;var t=e;var i=o;return u(r,t,i)}function u(n,e,o){Promise.all([r(n),t(e)]).then(function(){i(o)}).catch(function(n){return n}),function(){console.error("There was an issue polyfilling",mayneedpolyfill," which means that I can't preload future pages for you. Sorry! :(");console.warn("If you want this to work, I'd recommend upgrading to a browser that supports",mayneedpolyfill,"natively. You can find out which browsers do by visting: https://caniuse.com/")}}function r(n){var e=n.length;var o=[];for(var r=0;r=1&&c in a||t in this){console.log(t,"has native support")}else{o.push(t)}}if(o.length>0){return s(o)}}function t(r){if(Array.isArray(r)){var n=r.length;for(var e=0;e Date: Tue, 5 Feb 2019 11:36:24 +0000 Subject: [PATCH 07/21] Updated README stats and guide Updated parameter details Updated example scripts Updated stats --- README.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b1d9074..a6b56d6 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ A little script that allows you to only polyfill a feature when absolutely necessary - no wasted requests on browsers that have native support! 😆🤓 -This script is ~2.64KB **un**minified _(1KB **un**minified and gzipped)_ or ~1.55KB minified _(762B minified and gzipped)_, so it's _fairly_ light. :smile: +This script is ~3.78KB **un**minified _(1.24KB **un**minified and gzipped)_ or ~2.17KB minified _(889B minified and gzipped)_, so it's _fairly_ light. :smile: ## Getting Started @@ -27,19 +27,27 @@ Make sure you know what features your script is reliant on and polyfill those no 1. Example: `` 2. Add an `onLoad` attribute to the tag calling the `dynamicPolyfill()` function and passing your parameters 1. Note: the first parameter is the feature polyfills you want to pass. This is expected as an array. - 1. Note: the second paramter is the URL of the script you want to use. This is expected as a string, but can be blank (`''`) or `null` if you're not loading a third party script. - 1. Note: the third parameter is the function that you would run once the script has loaded. This is expected as a string. + 1. Note: the second paramter is the URL of the script you want to use. This is expected as a either a `string` or an `array`, but can be blank (`''`) or `null` if you're not loading a third party script. + 1. Note: the third parameter is the function that you would run once the script has loaded. This is expected as a `string` or an `array` . 1. Note: the 4th parameter has now been deprecated. -#### Full CDN example script tag: +#### CDN example script tag +##### String variables: ``` ``` +##### Array variables: +``` + +``` + Note: You need to ensure that before you call the `dynamicPolyfill()` function that the actual script itself has loaded. If you're going to host the script yourself (rather than calling out to a CDN), make sure you include the script code first, then call the function. You can do this in the same manner as above, but replace the CDN URL with the path to your own JS file! An example of this would be: `dynamicPolyfill(["IntersectionObserver", "Object.assign"], 'https://cdn.jsdelivr.net/npm/quicklink@1.0.0/dist/quicklink.umd.js', 'quicklink();');`. ## Built With From 23704a64d22a587eab78be0f9957ee8f85421a9f Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Wed, 6 Feb 2019 10:56:37 +0000 Subject: [PATCH 08/21] Fix init function If the function wasn't being passed as an array, it wouldn't execute. Fixed now! --- dynamicpolyfill.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dynamicpolyfill.js b/dynamicpolyfill.js index 2ddd9d8..e6b3e44 100644 --- a/dynamicpolyfill.js +++ b/dynamicpolyfill.js @@ -99,8 +99,8 @@ function initialiseMyScript(functionToRunonLoad) { try {fn();console.log(functionToRunonLoad[f], 'initialised successfully');} catch(err) {console.error('There was an error: ', err.name, err.stack)} } } else { - console.log("The following script will now be initialised:", functionToRunonLoad); - return new Function(functionToRunonLoad); + var fn = new Function(functionToRunonLoad); + try {fn();console.log(functionToRunonLoad, 'initialised successfully');} catch(err) {console.error('There was an error: ', err.name, err.stack)} } } From 441cddaf02af7db5bc4a6ebfbbee96b00e66b3ec Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Wed, 6 Feb 2019 12:22:19 +0000 Subject: [PATCH 09/21] Remove unnecessary array `fns` in `loadPolyfill` was unused... not sure how it even got there! --- dynamicpolyfill.js | 1 - 1 file changed, 1 deletion(-) diff --git a/dynamicpolyfill.js b/dynamicpolyfill.js index e6b3e44..4911b65 100644 --- a/dynamicpolyfill.js +++ b/dynamicpolyfill.js @@ -91,7 +91,6 @@ function loadMyScript(url) { } function initialiseMyScript(functionToRunonLoad) { - var fns = []; if(Array.isArray(functionToRunonLoad)) { var fnlen = functionToRunonLoad.length; for (var f = 0; f < fnlen; f++) { From 432263899873bd4562bd46115c5755f507b1cc4a Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Wed, 6 Feb 2019 12:39:04 +0000 Subject: [PATCH 10/21] Remove unnecessary var and reorder functions `initialiseMyScript` had an unnecessary `var` (`var fn = new Function`) which has been instead moved inline into the `try{}` Also reordered functions so they are in a more "vertically readable" format (they now are ordered logically!) --- dynamicpolyfill.js | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/dynamicpolyfill.js b/dynamicpolyfill.js index 4911b65..8b4f6e6 100644 --- a/dynamicpolyfill.js +++ b/dynamicpolyfill.js @@ -38,6 +38,22 @@ function checkNativeSupport(tocheck) { } } +function loadPolyfill(url) { + return new Promise( + function(resolve, reject) { + var polyfill = document.createElement('script'); + polyfill.src = ('https://polyfill.io/v3/polyfill.min.js?features='+encodeURIComponent(url)); + document.body.appendChild(polyfill); + polyfill.onerror = function(response) { + return reject("Loading the polyfill(s) failed!", response); + } + polyfill.onload = function() { + return resolve("Polyfill(s) loaded!"); + } + } + ) +} + function loadMyScript(url) { if(Array.isArray(url)) { var urlen = url.length; @@ -94,27 +110,17 @@ function initialiseMyScript(functionToRunonLoad) { if(Array.isArray(functionToRunonLoad)) { var fnlen = functionToRunonLoad.length; for (var f = 0; f < fnlen; f++) { - var fn = new Function(functionToRunonLoad[f]); - try {fn();console.log(functionToRunonLoad[f], 'initialised successfully');} catch(err) {console.error('There was an error: ', err.name, err.stack)} + try { + new Function(functionToRunonLoad[f])(); + } catch(err) { + console.error('There was an error: ', err.name, err.stack); + } } } else { - var fn = new Function(functionToRunonLoad); - try {fn();console.log(functionToRunonLoad, 'initialised successfully');} catch(err) {console.error('There was an error: ', err.name, err.stack)} - } -} - -function loadPolyfill(url) { - return new Promise( - function(resolve, reject) { - var polyfill = document.createElement('script'); - polyfill.src = ('https://polyfill.io/v3/polyfill.min.js?features='+encodeURIComponent(url)); - document.body.appendChild(polyfill); - polyfill.onerror = function(response) { - return reject("Loading the polyfill(s) failed!", response); - } - polyfill.onload = function() { - return resolve("Polyfill(s) loaded!"); - } + try { + new Function(functionToRunonLoad)(); + } catch(err) { + console.error('There was an error: ', err.name, err.stack); } - ) + } } From af0ab1609fd5e762419512f06c83f2b5fd09e2ea Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Fri, 8 Feb 2019 15:57:51 +0000 Subject: [PATCH 11/21] Major overhaul + resolve complexity 1) Iterate through array values using `Array.forEach()` 2) Split out `loadMyScript` repeated code into a helper function - minimising duplication! 3) `initialiseMyScript` is no longer called from the "core" `pageLoaded` function - instead it is called depending on whether the scripts that are to be used have loaded or not. 4) Inline comments to explain what each step is doing 5) Retain backwards compatibility! --- dynamicpolyfill.js | 155 ++++++++++++++++++++------------------------- 1 file changed, 70 insertions(+), 85 deletions(-) diff --git a/dynamicpolyfill.js b/dynamicpolyfill.js index 8b4f6e6..c5095ab 100644 --- a/dynamicpolyfill.js +++ b/dynamicpolyfill.js @@ -1,27 +1,25 @@ function dynamicPolyfill (features, scriptURL, initFunction) { - var polyfillFeatures = features; - var scriptToPolyfill = scriptURL; - var functionToRunonLoad = initFunction; - return pageLoaded(polyfillFeatures, scriptToPolyfill, functionToRunonLoad); + var polyfillFeatures = features; //these are the features that may need polyfilling depending on browser support + var scriptToPolyfill = scriptURL; //this is the script(s) that need to be used to execute a function and is dependent on certain feature support + var functionToRunonLoad = initFunction; //this is the function(s) that need to be executed, dependent on the above script(s) + return pageLoaded(polyfillFeatures, scriptToPolyfill, functionToRunonLoad); //Let's do it... } function pageLoaded(polyfillFeatures, scriptToPolyfill, functionToRunonLoad) { - Promise.all([checkNativeSupport(polyfillFeatures), loadMyScript(scriptToPolyfill)]) - .then( - function() { - initialiseMyScript(functionToRunonLoad) - } - ).catch(function(error){return error}) - ,function () { - console.error("There was an issue polyfilling",mayneedpolyfill," which means that I can't preload future pages for you. Sorry! :("); - console.warn("If you want this to work, I'd recommend upgrading to a browser that supports",mayneedpolyfill,"natively. You can find out which browsers do by visting: https://caniuse.com/"); - } + checkNativeSupport(polyfillFeatures) //check whether we need to polyfill anything + .then( //if we do or don't, then... + loadMyScript(scriptToPolyfill, functionToRunonLoad) //load the scripts and execute their dependent functions + ).catch( //report any errors during promise + function(error){ + return error + } + ) } function checkNativeSupport(tocheck) { var polen = tocheck.length; //cache value out of the for loop var polyfillNeeded = []; - for (var p = 0; p < polen; p++) { + for (var p = 0; p < polen; p++) { //swap out for Array.forEach or leave as-is? var pol = tocheck[p]; var splitChars = '.'; var split = pol.split(splitChars); @@ -39,88 +37,75 @@ function checkNativeSupport(tocheck) { } function loadPolyfill(url) { - return new Promise( - function(resolve, reject) { - var polyfill = document.createElement('script'); - polyfill.src = ('https://polyfill.io/v3/polyfill.min.js?features='+encodeURIComponent(url)); - document.body.appendChild(polyfill); - polyfill.onerror = function(response) { - return reject("Loading the polyfill(s) failed!", response); + return new Promise( //Need to return a promise response + function(resolve, reject) { //can resolve or reject, depending on load success or failure + var polyfill = document.createElement('script'); //create script element + polyfill.src = ('https://polyfill.io/v3/polyfill.min.js?features='+encodeURIComponent(url)); //add the polyfill src value to the aforementioned new script element + document.body.appendChild(polyfill); //add the new script to the end of the body tag + polyfill.onerror = function(response) { //if the script errors when loading... + return reject("Loading the polyfill(s) failed!", response); //... return Promise.reject response } - polyfill.onload = function() { - return resolve("Polyfill(s) loaded!"); + polyfill.onload = function() { //if the script loads successfully... + return resolve("Polyfill(s) loaded!"); //... return Promise.resolve response } } ) } -function loadMyScript(url) { - if(Array.isArray(url)) { - var urlen = url.length; - for (var u = 0; u < urlen; u++) { - var uri = url[u]; - if(uri !== null && uri !== '') { - return new Promise( - function(resolve, reject) { - var thescript = document.createElement('script'); - thescript.src = encodeURI(uri); - document.body.appendChild(thescript); - thescript.onerror = function(response) { - return reject("Loading the script failed!", response); - } - thescript.onload = function() { - return resolve("Script setup and ready to load!"); - } - } - ) - } else { - return new Promise( - function(resolve, reject) { - return resolve ("No script to load"); - } - ) - } - } - } else { - if(url !== null && url !== '') { - return new Promise( - function(resolve, reject) { - var thescript = document.createElement('script'); - thescript.src = encodeURI(url); - document.body.appendChild(thescript); - thescript.onerror = function(response) { - return reject("Loading the script failed!", response); - } - thescript.onload = function() { - return resolve("Script setup and ready to load!"); - } +function loadMyScript(url, functionToRunonLoad) { + if(Array.isArray(url)) { //Check whether array is being passed or just string + var promises = []; //Gotta catch 'em all... as an array + url.forEach( //iterate through the array using Array.forEach() + function(url){ //pass each item in the array through to the "get script" function + promises.push(nonblankURL(url)); //push the resolve/reject into the promises array } - ) - } else { - return new Promise( - function(resolve, reject) { - return resolve ("No script to load"); - } - ) - } + ); + Promise.all(promises) //Make sure that all promises that are returned come back as resolved + .then( + () => initialiseMyScript(functionToRunonLoad) //run the init function! + ).catch(function(error){return error}) //report any errors during promise + } else if (!Array.isArray(url) && url !== null && url !== '') { //if not an array and not blank values + nonblankURL(url) //resolve or reject getting the script + .then( + () => initialiseMyScript(functionToRunonLoad) //run the init function! + ).catch(function(error){return error}) //report any errors during promise + } else { //not array, blank values + return initialiseMyScript(functionToRunonLoad) //straight to init because no dependency (blank) } } +function nonblankURL(uri){ + return new Promise( //Need to return a promise response + function(resolve, reject) { //can resolve or reject, depending on load success or failure + var thescript = document.createElement('script'); //create script element + thescript.src = encodeURI(uri); //add the src value to the aforementioned new script element + document.body.appendChild(thescript); //add the new script to the end of the body tag + thescript.onerror = function(response) { //if the script errors when loading... + return reject("Loading the script failed!", response); //... return Promise.reject response + } + thescript.onload = function() { //if the script loads successfully... + return resolve(uri); //... return Promise.resolve response + } + } + ) +} + function initialiseMyScript(functionToRunonLoad) { - if(Array.isArray(functionToRunonLoad)) { - var fnlen = functionToRunonLoad.length; - for (var f = 0; f < fnlen; f++) { - try { - new Function(functionToRunonLoad[f])(); - } catch(err) { - console.error('There was an error: ', err.name, err.stack); + if(Array.isArray(functionToRunonLoad)) { //Check whether array is being passed or just string + functionToRunonLoad.forEach( //iterate through the array using Array.forEach() + function(functionToRunonLoad){ //pass each item in the array through to the "get script" function + try { //attempt to load - using try means we can catch any errors + new Function(functionToRunonLoad)(); //convert string to function then execute + } catch(err) { //catch any errors trying to run the init function + console.error('There was an error: ', err.name, err.stack); //report error to console + } } - } - } else { - try { - new Function(functionToRunonLoad)(); - } catch(err) { - console.error('There was an error: ', err.name, err.stack); + ) + } else { //not an array, just a string + try { //attempt to load - using try means we can catch any errors + new Function(functionToRunonLoad)(); //convert string to function then execute + } catch(err) { //catch any errors trying to run the init function + console.error('There was an error: ', err.name, err.stack); //report error to console } } } From 955328b961fb2d7c92be2df20f736a286f4fdb65 Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Fri, 8 Feb 2019 16:01:16 +0000 Subject: [PATCH 12/21] Minify new dynamicPolyfill script --- dynamicpolyfill.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dynamicpolyfill.min.js b/dynamicpolyfill.min.js index f5a9939..019af6c 100644 --- a/dynamicpolyfill.min.js +++ b/dynamicpolyfill.min.js @@ -1 +1 @@ -function dynamicPolyfill(n,e,o){var r=n;var t=e;var i=o;return u(r,t,i)}function u(n,e,o){Promise.all([r(n),t(e)]).then(function(){i(o)}).catch(function(n){return n}),function(){console.error("There was an issue polyfilling",mayneedpolyfill," which means that I can't preload future pages for you. Sorry! :(");console.warn("If you want this to work, I'd recommend upgrading to a browser that supports",mayneedpolyfill,"natively. You can find out which browsers do by visting: https://caniuse.com/")}}function r(n){var e=n.length;var o=[];for(var r=0;r=1&&c in a||t in this){console.log(t,"has native support")}else{o.push(t)}}if(o.length>0){return s(o)}}function t(r){if(Array.isArray(r)){var n=r.length;for(var e=0;e=1&&f in c||e in this||i.push(e)}if(i.length>0)return r(i)}function r(n){return new Promise(function(t,i){var r=document.t("script");r.i="https://polyfill.io/v3/polyfill.min.js?features="+encodeURIComponent(n),document.o.r(r),r.e=function(n){return i("Loading the polyfill(s) failed!",n)},r.u=function(){return t("Polyfill(s) loaded!")}})}function o(n,t){if(Array.isArray(n)){var i=[];n.forEach(function(n){i.push(e(n))}),Promise.all(i).then(()=>u(t)).catch(function(n){return n})}else{if(Array.isArray(n)||null===n||""===n)return u(t);e(n).then(()=>u(t)).catch(function(n){return n})}}function e(n){return new Promise(function(t,i){var r=document.t("script");r.i=encodeURI(n),document.o.r(r),r.e=function(n){return i("Loading the script failed!",n)},r.u=function(){return t(n)}})}function u(n){if(Array.isArray(n))n.forEach(function(n){try{new Function(n)()}catch(n){}});else try{new Function(n)()}catch(n){}} From 73a38f57d1be3fe5bb6d474d75bfb493698f9c33 Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Fri, 8 Feb 2019 16:02:20 +0000 Subject: [PATCH 13/21] Deprecate -consolemessages.js version Pain to maintain and generally unuseful unless doing in-depth troubleshooting (at which point, you'd add your own `console.log`s). --- dynamicpolyfill-consolemessages.js | 141 ----------------------------- 1 file changed, 141 deletions(-) delete mode 100644 dynamicpolyfill-consolemessages.js diff --git a/dynamicpolyfill-consolemessages.js b/dynamicpolyfill-consolemessages.js deleted file mode 100644 index bad6133..0000000 --- a/dynamicpolyfill-consolemessages.js +++ /dev/null @@ -1,141 +0,0 @@ -//This file includes a bunch of console.log()/console.error()/console.warn() messages. Aides with troubleshooting, but is also a little fun if someone happens to come across them. They're not necessary at all tho'! -function dynamicPolyfill (features, scriptURL, initFunction) { - var polyfillFeatures = features; - var scriptToPolyfill = scriptURL; - var functionToRunonLoad = initFunction; - return pageLoaded(polyfillFeatures, scriptToPolyfill, functionToRunonLoad); -} - -function pageLoaded(polyfillFeatures, scriptToPolyfill, functionToRunonLoad) { - Promise.all([checkNativeSupport(polyfillFeatures), loadMyScript(scriptToPolyfill)]) - .then( - function() { - console.log("As the script is ready, let's initialise it..."); - initialiseMyScript(functionToRunonLoad) - } - ).catch(function(error){return error}) - ,function () { - console.error("There was an issue polyfilling",mayneedpolyfill," which means that I can't preload future pages for you. Sorry! :("); - console.warn("If you want this to work, I'd recommend upgrading to a browser that supports",mayneedpolyfill,"natively. You can find out which browsers do by visting: https://caniuse.com/"); - } -} - -function checkNativeSupport(tocheck) { - var polen = tocheck.length; //cache value out of the for loop - var polyfillNeeded = []; //we'll need this later to know if/what to polyfill - for (var p = 0; p < polen; p++) { //iterate through array - var pol = tocheck[p]; //cache this outside of if - var splitChars = '.'; //values to check for within array strings to know where to split - var split = pol.split(splitChars); //split string based on splitChars (in this case, a dot) - var firstWord = window[split[0]]; //cache outside of if - the first word (array item 0) - var lastWord = new Object(split[split.length - 1]); //cache outside of if - last word (last array value) - if (typeof (window.pol) !== 'undefined' || pol in window || (pol.indexOf(splitChars) >= 1 && lastWord in firstWord) || pol in this) { - console.log(pol,'has native support'); - } else { - console.warn("Ahhh, your browser doesn't support",pol,". I'm gonna have to polyfill it so stuff works."); - polyfillNeeded.push(pol); - } - } - if (polyfillNeeded.length > 0) { //this is where we "push" values and check whether we need to polyfill or not - console.warn('Right, we need to polyfill',polyfillNeeded); - return loadPolyfill(polyfillNeeded); - } -} - -function loadMyScript(url) { - if(Array.isArray(url)) { //cater for array - var urlen = url.length; //cache value out of the for loop - for (var u = 0; u < urlen; u++) { - var uri = url[u]; //cache value out of if - if(uri !== null && uri !== '') { //handle blank or null values - return new Promise( - function(resolve, reject) { - var thescript = document.createElement('script'); - thescript.src = encodeURI(uri); - console.log('Loading ',uri); - document.body.appendChild(thescript); - thescript.onerror = function(response) { - console.error("Loading the script failed!); - return reject("Loading the script failed!", response); - } - thescript.onload = function() { - console.log("Script setup andready for use!"); - return resolve("Script setup and ready to load!"); - } - } - ) - } else { //blank or null values - return new Promise( - function(resolve, reject) { - console.log("No script to load"); - return resolve ("No script to load"); - } - ) - } - } - } else { //if not array - if(url !== null && url !== '') { //handle blank or null values - return new Promise( - function(resolve, reject) { - var thescript = document.createElement('script'); - thescript.src = encodeURI(url); - console.log("Loading ",url); - document.body.appendChild(thescript); - thescript.onerror = function(response) { - console.error("Loading the script failed"); - return reject("Loading the script failed!", response); - } - thescript.onload = function() { - console.log("Script setup andready for use!"); - return resolve("Script setup and ready to load!"); - } - } - ) - } else { //blank or null values - return new Promise( - function(resolve, reject) { - console.log("No script to load!"); - return resolve ("No script to load"); - } - ) - } - } -} - -function initialiseMyScript(functionToRunonLoad) { - if(Array.isArray(functionToRunonLoad)) { //cater for array - var fnlen = functionToRunonLoad.length; //cache outside of for loop - for (var f = 0; f < fnlen; f++) { - var fn = new Function(functionToRunonLoad[f]); //convert the strings to functions - try { - fn(); //execute the functions - console.log(functionToRunonLoad[f], 'initialised successfully'); //confirm execution - } - catch(err) { - console.error('There was an error: ', err.name, err.stack) - } - } - } else { //if not array - console.log("The following script will now be initialised:", functionToRunonLoad); - return new Function(functionToRunonLoad); //convert string to function and execute - } -} - -function loadPolyfill(url) { - return new Promise( - function(resolve, reject) { - var polyfill = document.createElement('script'); - polyfill.src = ('https://polyfill.io/v3/polyfill.min.js?features='+encodeURIComponent(url)); - console.log('Grabbing',url,'polyfill from: ',polyfill.src); - document.body.appendChild(polyfill); - polyfill.onerror = function(response) { - console.error("Loading the polyfill(s) failed!"); - return reject("Loading the polyfill(s) failed!", response); - } - polyfill.onload = function() { - console.log("Polyfill(s) loaded and ready for use!"); - return resolve("Polyfill(s) loaded!"); - } - } - ) -} From b76bc48c8f3057974838869217f9ee597441beae Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Fri, 8 Feb 2019 16:13:05 +0000 Subject: [PATCH 14/21] Refactor init function as there was duplicate code Refactored init function to include a micro-helper function to avoid duplication! --- dynamicpolyfill.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/dynamicpolyfill.js b/dynamicpolyfill.js index c5095ab..260a526 100644 --- a/dynamicpolyfill.js +++ b/dynamicpolyfill.js @@ -91,21 +91,21 @@ function nonblankURL(uri){ } function initialiseMyScript(functionToRunonLoad) { - if(Array.isArray(functionToRunonLoad)) { //Check whether array is being passed or just string - functionToRunonLoad.forEach( //iterate through the array using Array.forEach() - function(functionToRunonLoad){ //pass each item in the array through to the "get script" function - try { //attempt to load - using try means we can catch any errors - new Function(functionToRunonLoad)(); //convert string to function then execute - } catch(err) { //catch any errors trying to run the init function - console.error('There was an error: ', err.name, err.stack); //report error to console - } + if(Array.isArray(functionToRunonLoad)) { + functionToRunonLoad.forEach( + function(functionToRunonLoad){ + init(functionToRunonLoad) } ) - } else { //not an array, just a string - try { //attempt to load - using try means we can catch any errors - new Function(functionToRunonLoad)(); //convert string to function then execute - } catch(err) { //catch any errors trying to run the init function - console.error('There was an error: ', err.name, err.stack); //report error to console + } else { + init(functionToRunonLoad) + } + function init(fn) { + try { + console.log(fn,"loaded"); + new Function(fn)(); + } catch(err) { + console.error('There was an error: ', err.name, err.stack); } } } From a94c0be91fb9ca7644891ddfb874f69db42e7e22 Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Fri, 8 Feb 2019 16:14:01 +0000 Subject: [PATCH 15/21] Update dynamicpolyfill.min.js --- dynamicpolyfill.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dynamicpolyfill.min.js b/dynamicpolyfill.min.js index 019af6c..5070409 100644 --- a/dynamicpolyfill.min.js +++ b/dynamicpolyfill.min.js @@ -1 +1 @@ -function dynamicPolyfill(n,i,r){return t(n,i,r)}function t(n,t,r){i(n).then(o(t,r)).catch(function(n){return n})}function i(n){for(var t=n.length,i=[],o=0;o=1&&f in c||e in this||i.push(e)}if(i.length>0)return r(i)}function r(n){return new Promise(function(t,i){var r=document.t("script");r.i="https://polyfill.io/v3/polyfill.min.js?features="+encodeURIComponent(n),document.o.r(r),r.e=function(n){return i("Loading the polyfill(s) failed!",n)},r.u=function(){return t("Polyfill(s) loaded!")}})}function o(n,t){if(Array.isArray(n)){var i=[];n.forEach(function(n){i.push(e(n))}),Promise.all(i).then(()=>u(t)).catch(function(n){return n})}else{if(Array.isArray(n)||null===n||""===n)return u(t);e(n).then(()=>u(t)).catch(function(n){return n})}}function e(n){return new Promise(function(t,i){var r=document.t("script");r.i=encodeURI(n),document.o.r(r),r.e=function(n){return i("Loading the script failed!",n)},r.u=function(){return t(n)}})}function u(n){if(Array.isArray(n))n.forEach(function(n){try{new Function(n)()}catch(n){}});else try{new Function(n)()}catch(n){}} +function dynamicPolyfill(n,i,o){return t(n,i,o)}function t(n,t,o){i(n).then(r(t,o)).catch(function(n){return n})}function i(n){for(var t=n.length,i=[],r=0;r=1&&f in c||e in this||i.push(e)}if(i.length>0)return o(i)}function o(n){return new Promise(function(t,i){var o=document.t("script");o.i="https://polyfill.io/v3/polyfill.min.js?features="+encodeURIComponent(n),document.r.o(o),o.e=function(n){return i("Loading the polyfill(s) failed!",n)},o.u=function(){return t("Polyfill(s) loaded!")}})}function r(n,t){if(Array.isArray(n)){var i=[];n.forEach(function(n){i.push(e(n))}),Promise.all(i).then(()=>u(t)).catch(function(n){return n})}else{if(Array.isArray(n)||null===n||""===n)return u(t);e(n).then(()=>u(t)).catch(function(n){return n})}}function e(n){return new Promise(function(t,i){var o=document.t("script");o.i=encodeURI(n),document.r.o(o),o.e=function(n){return i("Loading the script failed!",n)},o.u=function(){return t(n)}})}function u(n){function t(n){try{new Function(n)()}catch(n){}}Array.isArray(n)?n.forEach(function(n){t(n)}):t(n)} From 1195cfa71b3e48df8a1c1d93891bb9751f9f6784 Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Fri, 8 Feb 2019 16:16:18 +0000 Subject: [PATCH 16/21] Update size stats --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index a6b56d6..13e686b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ A little script that allows you to only polyfill a feature when absolutely necessary - no wasted requests on browsers that have native support! 😆🤓 -This script is ~3.78KB **un**minified _(1.24KB **un**minified and gzipped)_ or ~2.17KB minified _(889B minified and gzipped)_, so it's _fairly_ light. :smile: +This script is ~4.76KB **un**minified (with comments!) _(1.52KB **un**minified and gzipped)_ or ~1.15KB minified _(520B minified and gzipped)_, so it's _fairly_ light. :smile: ## Getting Started @@ -77,4 +77,3 @@ This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md * [PurpleBooth](https://gist.github.com/PurpleBooth) for this awesome README template! * [Polyfill.io](https://github.com/Financial-Times/polyfill-library) for the awesome polyfill service! - From 204b508c889436e8aa03b9a0a68d974c8e804847 Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Sun, 10 Feb 2019 20:47:43 +0000 Subject: [PATCH 17/21] Update dynamicpolyfill.js --- dynamicpolyfill.js | 185 ++++++++++++++++++++++++--------------------- 1 file changed, 98 insertions(+), 87 deletions(-) diff --git a/dynamicpolyfill.js b/dynamicpolyfill.js index 260a526..0c7fa1b 100644 --- a/dynamicpolyfill.js +++ b/dynamicpolyfill.js @@ -1,111 +1,122 @@ -function dynamicPolyfill (features, scriptURL, initFunction) { - var polyfillFeatures = features; //these are the features that may need polyfilling depending on browser support - var scriptToPolyfill = scriptURL; //this is the script(s) that need to be used to execute a function and is dependent on certain feature support - var functionToRunonLoad = initFunction; //this is the function(s) that need to be executed, dependent on the above script(s) - return pageLoaded(polyfillFeatures, scriptToPolyfill, functionToRunonLoad); //Let's do it... -} - -function pageLoaded(polyfillFeatures, scriptToPolyfill, functionToRunonLoad) { - checkNativeSupport(polyfillFeatures) //check whether we need to polyfill anything - .then( //if we do or don't, then... - loadMyScript(scriptToPolyfill, functionToRunonLoad) //load the scripts and execute their dependent functions - ).catch( //report any errors during promise - function(error){ +function dynamicPolyfill(tocheck, scriptToPolyfill, functionToRunonLoad) { + var checkPromises = []; + if(Array.isArray(tocheck)) { + tocheck.forEach( + function(tocheck) { + checkPromises.push(checking(tocheck)) + } + ) + } else { + checkPromises.push(checking(tocheck)) + } + Promise.all(checkPromises) + .then( + function() { + loadMyScript(scriptToPolyfill, functionToRunonLoad) + } + ) + .catch( + function(error) { return error } - ) + ) } -function checkNativeSupport(tocheck) { - var polen = tocheck.length; //cache value out of the for loop - var polyfillNeeded = []; - for (var p = 0; p < polen; p++) { //swap out for Array.forEach or leave as-is? - var pol = tocheck[p]; - var splitChars = '.'; - var split = pol.split(splitChars); - var firstWord = window[split[0]]; - var lastWord = new Object(split[split.length - 1]); - if (typeof (window.pol) !== 'undefined' || pol in window || (pol.indexOf(splitChars) >= 1 && lastWord in firstWord) || pol in this) { - console.log(pol,'has native support'); - } else { - polyfillNeeded.push(pol); - } - } - if (polyfillNeeded.length > 0) { - return loadPolyfill(polyfillNeeded); +function checking(check) { + var splitChars = '.'; + var split = check.split(splitChars); + var firstWord = window[split[0]]; + var lastWord = new Object(split[split.length - 1]); + if(typeof (window.check) == 'undefined' || !check in window || (check.indexOf(splitChars) >= 1 && !lastWord in firstWord) || !check in this) { + loadPolyfill(check); } } function loadPolyfill(url) { - return new Promise( //Need to return a promise response - function(resolve, reject) { //can resolve or reject, depending on load success or failure - var polyfill = document.createElement('script'); //create script element - polyfill.src = ('https://polyfill.io/v3/polyfill.min.js?features='+encodeURIComponent(url)); //add the polyfill src value to the aforementioned new script element - document.body.appendChild(polyfill); //add the new script to the end of the body tag - polyfill.onerror = function(response) { //if the script errors when loading... - return reject("Loading the polyfill(s) failed!", response); //... return Promise.reject response - } - polyfill.onload = function() { //if the script loads successfully... - return resolve("Polyfill(s) loaded!"); //... return Promise.resolve response - } - } - ) + return new Promise( + function(resolve, reject) { + var polyfill = document.createElement('script'); + polyfill.src = ('https://polyfill.io/v3/polyfill.min.js?features=' + encodeURIComponent(url)); + document.body.appendChild(polyfill); + polyfill.onerror = function(response) { + return reject("Loading the polyfill(s) failed!", response) + } + polyfill.onload = function() { + return resolve + } + } + ) } function loadMyScript(url, functionToRunonLoad) { - if(Array.isArray(url)) { //Check whether array is being passed or just string - var promises = []; //Gotta catch 'em all... as an array - url.forEach( //iterate through the array using Array.forEach() - function(url){ //pass each item in the array through to the "get script" function - promises.push(nonblankURL(url)); //push the resolve/reject into the promises array - } - ); - Promise.all(promises) //Make sure that all promises that are returned come back as resolved - .then( - () => initialiseMyScript(functionToRunonLoad) //run the init function! - ).catch(function(error){return error}) //report any errors during promise - } else if (!Array.isArray(url) && url !== null && url !== '') { //if not an array and not blank values - nonblankURL(url) //resolve or reject getting the script - .then( - () => initialiseMyScript(functionToRunonLoad) //run the init function! - ).catch(function(error){return error}) //report any errors during promise - } else { //not array, blank values - return initialiseMyScript(functionToRunonLoad) //straight to init because no dependency (blank) + if(Array.isArray(url)) { + var promises = []; + url.forEach( + function(url) { + promises.push(nonblankURL(url)) + } + ); + Promise.all(promises) + .then( + function() { + initialiseMyScript(functionToRunonLoad) + } + ) + .catch( + function(error) { + return error + } + ) + } + else if (!Array.isArray(url) && url !== null && url !== '') { + nonblankURL(url) + .then( + function() { + initialiseMyScript(functionToRunonLoad) + } + ) + .catch( + function(error) { + return error + } + ) + } else { + initialiseMyScript(functionToRunonLoad) } } -function nonblankURL(uri){ - return new Promise( //Need to return a promise response - function(resolve, reject) { //can resolve or reject, depending on load success or failure - var thescript = document.createElement('script'); //create script element - thescript.src = encodeURI(uri); //add the src value to the aforementioned new script element - document.body.appendChild(thescript); //add the new script to the end of the body tag - thescript.onerror = function(response) { //if the script errors when loading... - return reject("Loading the script failed!", response); //... return Promise.reject response - } - thescript.onload = function() { //if the script loads successfully... - return resolve(uri); //... return Promise.resolve response - } - } - ) +function nonblankURL(uri) { + return new Promise( + function(resolve, reject) { + var thescript = document.createElement('script'); + thescript.src = encodeURI(uri); + document.body.appendChild(thescript); + thescript.onerror = function(response) { + return reject("Loading the script failed!", response) + } + thescript.onload = function() { + return resolve(uri) + } + } + ) } function initialiseMyScript(functionToRunonLoad) { if(Array.isArray(functionToRunonLoad)) { functionToRunonLoad.forEach( - function(functionToRunonLoad){ - init(functionToRunonLoad) - } - ) - } else { - init(functionToRunonLoad) + function(functionToRunonLoad) { + initScript(functionToRunonLoad) + } + ) + } else { + initScript(functionToRunonLoad) } - function init(fn) { + function initScript(fn) { try { - console.log(fn,"loaded"); - new Function(fn)(); - } catch(err) { - console.error('There was an error: ', err.name, err.stack); + window[fn] + } + catch (err) { + console.error('There was an error: ', err, err.name, err.stack) } } } From 30b4573fa12a07b65fc649a575d017ab7a550673 Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Sun, 10 Feb 2019 21:03:45 +0000 Subject: [PATCH 18/21] I realised something Not only did I forget a commit message/details on the last commit (sorry - this is simply making up for that - no code changes!), but also... I realised I had two functions that were simply there to call other functions. They weren't doing anything for themselves! Therefore, `function dynamicPolyfill`, `function pageLoaded` and `function checkNativeSupport` have now all been combined into a single, function: `function dynamicPolyfill` Also as part of this commit - support for Safari and it's weird behaviours. Finally, some general tidying up of code Now all I need to do is re-add the inline comments? From bcd37e604ce169dca6e777a158b48d85a841db50 Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Mon, 11 Feb 2019 00:22:48 +0000 Subject: [PATCH 19/21] Formatting fixes --- dynamicpolyfill.js | 121 +++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 70 deletions(-) diff --git a/dynamicpolyfill.js b/dynamicpolyfill.js index 0c7fa1b..e8ccfd5 100644 --- a/dynamicpolyfill.js +++ b/dynamicpolyfill.js @@ -2,24 +2,18 @@ function dynamicPolyfill(tocheck, scriptToPolyfill, functionToRunonLoad) { var checkPromises = []; if(Array.isArray(tocheck)) { tocheck.forEach( - function(tocheck) { - checkPromises.push(checking(tocheck)) - } - ) + function(tocheck) { + checkPromises.push(checking(tocheck)) + } + ) } else { checkPromises.push(checking(tocheck)) } - Promise.all(checkPromises) - .then( - function() { - loadMyScript(scriptToPolyfill, functionToRunonLoad) - } - ) - .catch( - function(error) { - return error - } - ) + Promise.all(checkPromises).then( + function() { + loadMyScript(scriptToPolyfill, functionToRunonLoad) + } + ).catch(function(error){return error}) } function checking(check) { @@ -34,52 +28,39 @@ function checking(check) { function loadPolyfill(url) { return new Promise( - function(resolve, reject) { - var polyfill = document.createElement('script'); - polyfill.src = ('https://polyfill.io/v3/polyfill.min.js?features=' + encodeURIComponent(url)); - document.body.appendChild(polyfill); - polyfill.onerror = function(response) { - return reject("Loading the polyfill(s) failed!", response) - } - polyfill.onload = function() { - return resolve - } - } - ) + function(resolve, reject) { + var polyfill = document.createElement('script'); + polyfill.src = ('https://polyfill.io/v3/polyfill.min.js?features=' + encodeURIComponent(url)); + document.body.appendChild(polyfill); + polyfill.onerror = function(response) { + return reject("Loading the polyfill(s) failed!", response) + } + polyfill.onload = function() { + return resolve + } + } + ) } function loadMyScript(url, functionToRunonLoad) { if(Array.isArray(url)) { var promises = []; url.forEach( - function(url) { + function(url) { promises.push(nonblankURL(url)) } - ); - Promise.all(promises) - .then( - function() { - initialiseMyScript(functionToRunonLoad) - } - ) - .catch( - function(error) { - return error - } - ) - } - else if (!Array.isArray(url) && url !== null && url !== '') { - nonblankURL(url) - .then( - function() { - initialiseMyScript(functionToRunonLoad) - } - ) - .catch( - function(error) { - return error - } - ) + ); + Promise.all(promises).then( + function() { + initialiseMyScript(functionToRunonLoad) + } + ).catch(function(error){return error}) + } else if (!Array.isArray(url) && url !== null && url !== '') { + nonblankURL(url).then( + function() { + initialiseMyScript(functionToRunonLoad) + } + ).catch(function(error){return error}) } else { initialiseMyScript(functionToRunonLoad) } @@ -87,27 +68,27 @@ function loadMyScript(url, functionToRunonLoad) { function nonblankURL(uri) { return new Promise( - function(resolve, reject) { - var thescript = document.createElement('script'); - thescript.src = encodeURI(uri); - document.body.appendChild(thescript); - thescript.onerror = function(response) { - return reject("Loading the script failed!", response) - } - thescript.onload = function() { - return resolve(uri) - } - } - ) + function(resolve, reject) { + var thescript = document.createElement('script'); + thescript.src = encodeURI(uri); + document.body.appendChild(thescript); + thescript.onerror = function(response) { + return reject("Loading the script failed!", response) + } + thescript.onload = function() { + return resolve(uri) + } + } + ) } function initialiseMyScript(functionToRunonLoad) { if(Array.isArray(functionToRunonLoad)) { functionToRunonLoad.forEach( - function(functionToRunonLoad) { - initScript(functionToRunonLoad) - } - ) + function(functionToRunonLoad) { + initScript(functionToRunonLoad) + } + ) } else { initScript(functionToRunonLoad) } @@ -115,7 +96,7 @@ function initialiseMyScript(functionToRunonLoad) { try { window[fn] } - catch (err) { + catch(err) { console.error('There was an error: ', err, err.name, err.stack) } } From a09343f16b197315a2bb1f85e4f2b096bda03c57 Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Mon, 11 Feb 2019 09:16:23 +0000 Subject: [PATCH 20/21] Update dynamicpolyfill.min.js --- dynamicpolyfill.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dynamicpolyfill.min.js b/dynamicpolyfill.min.js index 5070409..cc6001a 100644 --- a/dynamicpolyfill.min.js +++ b/dynamicpolyfill.min.js @@ -1 +1 @@ -function dynamicPolyfill(n,i,o){return t(n,i,o)}function t(n,t,o){i(n).then(r(t,o)).catch(function(n){return n})}function i(n){for(var t=n.length,i=[],r=0;r=1&&f in c||e in this||i.push(e)}if(i.length>0)return o(i)}function o(n){return new Promise(function(t,i){var o=document.t("script");o.i="https://polyfill.io/v3/polyfill.min.js?features="+encodeURIComponent(n),document.r.o(o),o.e=function(n){return i("Loading the polyfill(s) failed!",n)},o.u=function(){return t("Polyfill(s) loaded!")}})}function r(n,t){if(Array.isArray(n)){var i=[];n.forEach(function(n){i.push(e(n))}),Promise.all(i).then(()=>u(t)).catch(function(n){return n})}else{if(Array.isArray(n)||null===n||""===n)return u(t);e(n).then(()=>u(t)).catch(function(n){return n})}}function e(n){return new Promise(function(t,i){var o=document.t("script");o.i=encodeURI(n),document.r.o(o),o.e=function(n){return i("Loading the script failed!",n)},o.u=function(){return t(n)}})}function u(n){function t(n){try{new Function(n)()}catch(n){}}Array.isArray(n)?n.forEach(function(n){t(n)}):t(n)} +function dynamicPolyfill(n,i,t){var o=[];if(Array.isArray(n)){n.forEach(function(n){o.push(e(n))})}else{o.push(e(n))}Promise.all(o).then(function(){u(i,t)}).catch(function(n){return n})}function e(n){var i=".";var t=n.split(i);var o=window[t[0]];var e=new Object(t[t.length-1]);if(typeof window.i=="undefined"||!n in window||n.indexOf(i)>=1&&!e in o||!n in this){r(n)}}function r(o){return new Promise(function(n,i){var t=document.createElement("script");t.src="https://polyfill.io/v3/polyfill.min.js?features="+encodeURIComponent(o);document.body.appendChild(t);t.onerror=function(n){return i("Loading the polyfill(s) failed!",n)};t.onload=function(){return n}})}function u(n,i){if(Array.isArray(n)){var t=[];n.forEach(function(n){t.push(o(n))});Promise.all(t).then(function(){c(i)}).catch(function(n){return n})}else if(!Array.isArray(n)&&n!==null&&n!==""){o(n).then(function(){c(i)}).catch(function(n){return n})}else{c(i)}}function o(o){return new Promise(function(n,i){var t=document.createElement("script");t.src=encodeURI(o);document.body.appendChild(t);t.onerror=function(n){return i("Loading the script failed!",n)};t.onload=function(){return n(o)}})}function c(n){if(Array.isArray(n)){n.forEach(function(n){i(n)})}else{i(n)}function i(n){try{window[n]}catch(n){console.error("There was an error: ",n,n.name,n.stack)}}} From a873dab1a6f2ca2391a808cc1ca891a4b6ea513c Mon Sep 17 00:00:00 2001 From: willstocks-tech <43744514+willstocks-tech@users.noreply.github.com> Date: Mon, 11 Feb 2019 09:18:26 +0000 Subject: [PATCH 21/21] Update stats and deployment instructions "Local" and CDN deployment now included! --- README.md | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 13e686b..269c372 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ A little script that allows you to only polyfill a feature when absolutely necessary - no wasted requests on browsers that have native support! 😆🤓 -This script is ~4.76KB **un**minified (with comments!) _(1.52KB **un**minified and gzipped)_ or ~1.15KB minified _(520B minified and gzipped)_, so it's _fairly_ light. :smile: +This script is ~2.54KB **un**minified (104 lines) _(841B **un**minified and gzipped)_ or ~1.3KB minified (1 line) _(565B minified and gzipped)_, so it's _fairly_ light. :smile: ## Getting Started @@ -22,7 +22,18 @@ Make sure you know what features your script is reliant on and polyfill those no ## Deployment -### Loading from CDN: +### Loading locally (recommended): +1. Copy the contents of [dynamicpolyfill.js](https://github.com/willstocks-tech/dynamically-polyfill-features-for-a-script/blob/master/dynamicpolyfill.js) +1. Paste it into your existing JS file(s) +1. Add a new line after it and call `dynamicPolyfill();` _Note: Case-sensitive_ + 1. Example: `dynamicPolyfill( ["IntersectionObserver", "Object.assign"], 'https://cdn.jsdelivr.net/npm/quicklink@1.0.0/dist/quicklink.umd.js', 'quicklink();')` +2. Add an `onLoad` attribute to the tag calling the `dynamicPolyfill()` function and passing your parameters + 1. Note: the first parameter is the feature polyfills you want to pass. This is expected as an array. + 1. Note: the second paramter is the URL of the script you want to use. This is expected as a either a `string` or an `array`, but can be blank (`''`) or `null` if you're not loading a third party script. + 1. Note: the third parameter is the function that you would run once the script has loaded. This is expected as a `string` or an `array` . + 1. Note: the 4th parameter has now been deprecated. + +### Loading from CDN (less recommended): 1. Add a `` tag linking to this script 1. Example: `` 2. Add an `onLoad` attribute to the tag calling the `dynamicPolyfill()` function and passing your parameters @@ -31,8 +42,25 @@ Make sure you know what features your script is reliant on and polyfill those no 1. Note: the third parameter is the function that you would run once the script has loaded. This is expected as a `string` or an `array` . 1. Note: the 4th parameter has now been deprecated. -#### CDN example script tag -##### String variables: +Note: Loading from a CDN would still result in a potentially wasted request :disappointed: + +#### Example method of usage + +##### Local + +###### String variables + +`dynamicPolyfill( 'IntersectionObserver', 'https://cdn.jsdelivr.net/npm/quicklink@1.0.0/dist/quicklink.umd.js', 'quicklink();');` + +##### Array variables + +`dynamicPolyfill( ["IntersectionObserver", "Object.assign"], ['https://cdn.jsdelivr.net/npm/quicklink@1.0.0/dist/quicklink.umd.js', 'https://other.cdn.net/script.js'], ['quicklink();', 'otherFunction();'] );` + +##### CDN + +Note: You need to ensure that before you call the `dynamicPolyfill()` function that the actual script itself has loaded. If you're going to host the script yourself (rather than calling out to a CDN), make sure you include the script code first, then call the function. You can do this in the same manner as above, but replace the CDN URL with the path to your own JS file, if you're not going to call it from the same file. + +###### String variables: ``` ``` -Note: You need to ensure that before you call the `dynamicPolyfill()` function that the actual script itself has loaded. If you're going to host the script yourself (rather than calling out to a CDN), make sure you include the script code first, then call the function. You can do this in the same manner as above, but replace the CDN URL with the path to your own JS file! An example of this would be: `dynamicPolyfill(["IntersectionObserver", "Object.assign"], 'https://cdn.jsdelivr.net/npm/quicklink@1.0.0/dist/quicklink.umd.js', 'quicklink();');`. - ## Built With -* Vanilla Javascript - no framework dependencies! +* Vanilla Javascript - no framework dependencies whatsoever! * [Polyfill.io](https://github.com/Financial-Times/polyfill-library) - for the actual polyfills! ## Versioning