Skip to content

Instantly share code, notes, and snippets.

@imlinus

imlinus/Async JS

Last active Jan 8, 2017
Embed
What would you like to do?
<html>
<head>
<script type="text/javascript">
"use strict";
(function() {
class ScriptAsync extends HTMLElement {
static get observedAttributes() {
return ['packages', 'oncomplete', 'locals'];
}
get packages() { return this.getAttribute('packages'); }
get oncomplete() { return this.getAttribute('oncomplete'); }
get locals() { return this.getAttribute('locals'); }
get api() { return 'http://api.jsdelivr.com/v1/jsdelivr/libraries'; }
get jsdelivr() { return 'https://cdn.jsdelivr.net'; }
constructor() {
super();
this._counter = 0;
this._packages = [];
this._locals = undefined;
document.addEventListener("DOMContentLoaded", () => this.windowLoaded());
}
attributeChangedCallback(name, oldValue, newValue) {
this._counter += 1;
if (this._counter === this.attributes.length) {
let packs = this.preparePackages(this.packages);
this.loadPackages(packs);
}
}
preparePackages(packs) {
packs.split(',').forEach(pack => {
let details = pack.split('@');
this._packages.push({
name: details[0],
version: details[1]
})
});
return this._packages;
};
loadPackages(packages) {
let proms = [],
proms2 = [];
packages.forEach(pack => {
let promise = new Promise((resolve, reject) => {
let url = this.packageUrl(pack);
proms2.push(this.appendScript(url));
resolve(pack);
});
proms.push(promise);
});
Promise.all(proms).then((packs) => {
packs.forEach(pack => console.info(`${pack.name}@${pack.version}`));
Promise.all(proms2).then(() => {
if (this.locals)
this.locals.split(',').forEach(local => this.appendScript(this.locals));
});
});
}
packageUrl(pack) {
pack.name = pack.name.replace(' ', '*');
if (pack.version) {
let packInfo = this.getPackageVersion(pack.name, pack.version);
if (packInfo) {
return `${this.jsdelivr}/${packInfo.name}/${packInfo.version}/${packInfo.mainfile}`;
}
console.warn(`Can't find package for ${pack.name}@${pack.version}`);
return;
} else {
let packInfo = this.getPackageInfo(pack.name)[0];
if (packInfo) {
pack.version = packInfo.lastversion;
return `${this.jsdelivr}/${packInfo.name}/${packInfo.lastversion}/${packInfo.mainfile}`;
}
console.warn(`Can't find package for ${pack.name}`);
return undefined;
}
}
getPackageInfo(packageName) {
let baseUri = `${this.api}?name=${packageName}&fields=name,lastversion,mainfile`;
return JSON.parse(this.httpsync(baseUri));
}
getPackageVersion(packageName, version) {
let baseUri = `${this.api}?name=${packageName}&fields=name,assets`;
let json = JSON.parse(this.httpsync(baseUri));
let foundPackage = undefined;
if (json.length > 0) {
json[0].assets.every((asset, index) => {
if (version === asset.version) {
console.info(`Found matching version for ${json[0].name}@${asset.version}`);
foundPackage = asset;
foundPackage.name = json[0].name;
return false;
}
return true;
});
}
return foundPackage;
}
appendScript(filename) {
let pr = new Promise((resolve, reject) => {
if (filename) {
eval(this.httpsync(filename));
}
resolve(filename);
});
return pr;
}
httpsync(url) {
var xhrObj = new XMLHttpRequest();
xhrObj.open('GET', url, false);
xhrObj.send('');
return xhrObj.responseText;
}
callback(resolve, filename) {
resolve();
}
windowLoaded() {
if (this.oncomplete)
eval(this.oncomplete);
}
}
customElements.define('script-async', ScriptAsync);
})();
</script>
<script-async packages="modernizr,jquery@2.1.3" locals="assets/js/lib/TweenMax.min.js,assets/js/main.js" oncomplete="initCallBack()" ></script-async>
</head>
<body>
<h1>Hello, World.</h1>
<script type="text/javascript">
function initCallback() {
console.log('Lets Go');
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.