L.DeferredLayer = L.LayerGroup.extend({ options: { js: [], init: null }, _script_cache: {}, initialize: function(options) { L.Util.setOptions(this, options); L.LayerGroup.prototype.initialize.apply(this); this._loaded = false; }, onAdd: function(map) { L.LayerGroup.prototype.onAdd.apply(this, [map]); if (this._loaded) return; //console.info('Script cache', this._script_cache); var loaded = function() { //console.info('Loaded', this, this.options); this._loaded = true; var l = this.options.init(); if (l) this.addLayer(l); }; this._loadScripts(this.options.js.reverse(), L.Util.bind(loaded, this)); }, _loadScripts: function(scripts, cb, args) { if (!scripts || scripts.length === 0) return cb(args); var _this = this, s = scripts.pop(), c; c = this._script_cache[s]; if (c === undefined) { c = {url: s, wait: []}; //console.info('Load ', s); var script = document.createElement('script'); script.src = s; script.type = 'text/javascript'; script.onload = function () { //console.info('Element(cb)', c.e.readyState); c.e.readyState = 'completed'; var i = 0; for (i = 0; i < c.wait.length; i++) c.wait[i](); }; c.e = script; document.getElementsByTagName('head')[0].appendChild(script); } function _cb() { _this._loadScripts(scripts, cb, args); } c.wait.push(_cb); //console.info('Element', c.e.readyState); if (c.e.readyState === 'completed') _cb(); this._script_cache[s] = c; } });