I am trying to figure out a way to structure a new structure for work that is capable of introducing plugins. The idea is for each file to be loaded asynchronously.
Here is how I would like to configure my plugins:
<script id="target_root" src="assets/js/target/target.js" async="true"></script> <script> var target = target || {}; target.cmd = target.cmd || []; target.cmd.push(function () { target.loadPlugins([ {"name": "root", "src": "assets/js/target/target.root.js"}, {"name": "krux", "src": "assets/js/target/target.krux.js"} ]).then( target.init([ { 'plugin': 'root', 'opts': { 'foo': 'bar' } }, { 'plugin': 'krux', 'opts': { 'foo': 'bar' } } ]) ) }); </script>
As I would use the built-in functions (inside the DOM), I was thinking about using a command queue that, when loaded, will call all the pressed functions (a bit like cmd DFP).
As indicated above, each plugin will be loaded asynchronously, so the initialization of each of them should begin only when all of them are loaded (therefore, the then () function).
Here I have a script:
var target = (function(root, w, d, c) { var queueIndex = 0, amountPluginsLoaded = 0, pluginsLoaded = []; root.cmd = { 'queue': root && root.cmd ? root.cmd : [], 'push': function(fn) { this.queue.push(fn); this.next(); }, 'next': function() { if (this.queue.length > 0) { this.queue.shift()(); } } }; root.init = function(plugins) { }; root.loadPlugins = function(plugins) { var i = 0, len = plugins.length; for(; i < len; i++) { _loadExternalJS(plugins[i]); } }; function _loadExternalJS(plugin) { var scriptRoot = d.getElementById('target_root'), scriptElement = d.createElement('script'); scriptElement.setAttribute('type', 'text/javascript'); scriptElement.setAttribute('async', 'true'); scriptElement.onload = function() { amountPluginsLoaded++; pluginsLoaded.push(plugin.name); }; scriptElement.setAttribute('src', plugin.src); scriptRoot.parentNode.insertBefore(scriptElement, scriptRoot.nextSibling); } function _initPlugin(plugin) { } for (; queueIndex < root.cmd.queue.length; queueIndex++) { root.cmd.next(); } }(target || {}, window, document, console));
Here you have the basic function cmd, which will be overridden and load each of the scripts.
What I seem to be unable to understand is how to run if (). I suppose you will track it in _loadExternalJS () in the onload event (as you can see in the code). But just adding if (amountPluginsLoaded === pluginsLoaded.length) {fire all inits} seems unproductive and not what the function belongs to. so I would like to implement some then () function.
Any ideas / opinions?