Spontaneous.Require = { pending: [], current: false, _completed: [], position: 0, async: true, init: function(asynchronous) { this.async = asynchronous; var body = document.body; var splash = document.createElement('div'); splash.id = 'script-load-splash'; var progress_outer = document.createElement('div'); progress_outer.id = 'script-load-progress'; if (this.async) { var progress_inner = document.createElement('div'); progress_outer.appendChild(progress_inner); this.bar = progress_inner; this.progress(0); } else { progress_outer.className = 'synchronous'; progress_outer.innerHTML = 'Loading...'; } splash.appendChild(progress_outer); body.appendChild(splash); this.container = splash; }, remove: function() { document.body.removeChild(this.container); }, progress: function(position) { this.position = position; var percent = ((this.completed()/this.total()) * 100); if (isNaN(percent)) { percent = 0; } this.bar.style.width = percent + '%'; }, completed: function() { var total = 0; for (var i = 0, ii = this._completed.length; i < ii; i++) { total += this._completed[i][1]; } total += this.position; return total; }, total: function() { var total = 0; for (var i = 0, ii = this.pending.length; i < ii; i++) { total += this.pending[i][1]; } if (this.current) { total += this.current[1]; } for (i = 0, ii = this._completed.length; i < ii; i++) { total += this._completed[i][1]; } return total; }, add: function(script) { this.pending.push(script); if (!this.current) { this.next(); } }, script_url: function(src) { var url = src; if (Spontaneous.development) { url += '?'+(new Date()).valueOf(); } return url; }, next: function() { if (this.pending.length === 0) { this.container.className = 'loaded'; this.remove(); Spontaneous.onload(); return; } var s = this.pending.shift(); this.current = s; if (this.async) { var xhr = new XMLHttpRequest(); xhr.open('GET', this.script_url(s[0]), true); var onprogress = (function(req) { return function(event) { req.onprogress(event); }; })(this); var onreadystatechange = (function(req) { return function(event) { req.onreadystatechange(event); }; })(this); xhr.onprogress = onprogress; xhr.onreadystatechange = onreadystatechange; xhr.send(); } else { var body = document.body; var script = document.createElement('script'); script.type = 'text/javascript'; script.src = this.script_url(this.current[0]); var onload = (function(req) { return function() { req._completed.push(req.current); req.current = false; req.next(); }; })(this); script.onload = onload; body.appendChild(script); // this.current = false; } }, onprogress: function(event) { this.progress(event.position); }, onreadystatechange: function(event) { var xhr = event.currentTarget; if (xhr.readyState == 4 && xhr.status === 200) { var body = document.body; var script = document.createElement('script'); script.type = 'text/javascript'; script.text = xhr.responseText; body.appendChild(script); this._completed.push(this.current); this.position = 0; this.next(); } } }; Spontaneous.require = function(script) { Spontaneous.Require.add(script); };