1// http://whiteposts.com/extsrc 2// Released as BSD license 3// Author: Slava <[email protected]> 4 5/* 6 7extlib.js is a script that allow to defer loading SCRIPTs in HTML page until 8after the page renders. It supports deferred document.write too by creating 9SPAN tag after the SCRIPT and then document.write actually set's that tag's 10innerHTML. 11 12** HOW TO USE ** 13 14<script src="extsrc.js"></script> 15 16<script extsrc="..."></script> <-- this form is used when external script 17 uses document.write 18 19<script asyncsrc="..."></script> <-- this form is used when external script 20 doesn't use document.write 21 22Keep in mind that if your external script writes unbalanced tag, like so: 23document.write('<a href=#>'), it will be automatically closed (since extsrc 24creates a SPAN element after <script> element and assigns '<a href=#>' 25to it as innerHTML to simluate document.write - the browser automatically 26will close the unbalanced A: '<a href="#"></a>'). 27 28 29** extsrc.complete ** 30 31You can also use extsrc.complete(). 32Note that it runs only after ALL extsrc's are finished loading (NOT when 33document is ready to render). 34 35extsrc.complete(function() { 36 alert('All extsrcs loaded!'); 37}); 38 39 40Thanks to: Kolyaj, arestov, Zitrix, it2days, DriverX, maxpain, dhj, rednaxi, 41 Panya, sirus, MiXei4, hyborg and everyone else who helped test and 42 develop. 43 44*/ 45 46var extsrc = null; 47 48(function(){ 49 extsrc = new Object; 50 51 extsrc.complete = function(f) { 52 this.complete.funcs.push(f); 53 }; 54 extsrc.complete.funcs = []; 55 56 57
58 //document.write('<div id=console></div>'); 59 //var console = document.getElementById('console'); 60 61 var document_write = document.write; 62 var document_writeln = document.writeln; 63 var buffer = ''; // catching things like d.w('<scr');d.w('ipt></sc');... 64 65 var span = ''; // this is the new element that acts as a placeholder for 66 // future document.write's 67 68 function dumpBuffer() { 69 if(buffer && span) { 70 document.write = document_write; 71 document.writeln = document_writeln; 72 var txt = document.createElement('span'); 73 txt.innerHTML = buffer; 74 span.appendChild(txt); 75 buffer = ''; 76 }; 77 }; 78 79 function runNextScript() { 80 dumpBuffer(); 81 82 var scripts = document.getElementsByTagName('script'); 83 for(var i=0;i<scripts.length;i++) { 84 // go through all scripts, looking for those with extsrc or asyncsrc 85 // attributes. when encountered - set attribute to empty and return 86 // from runNextScript. 87 // runNextScript will be called when the encountered scripts runs 88 // or fails (onload, onerror (404), readystatechange (good/404)). 89 90 var current_script = scripts[i]; 91 92 var cur_asyncsrc = current_script.getAttribute('asyncsrc'); 93 if(cur_asyncsrc) { 94 // asyncsrc means script doesn't use document.write - 95 // we can use it all in parallel 96 97 current_script.setAttribute('asyncsrc', ''); // don't run 2nd time 98 var s = document.createElement('script'); 99 s.async = true; 100 s.src = cur_asyncsrc; 101 document.getElementsByTagName('head')[0].appendChild(s); 102 }; 103 104 var cur_extsrc = current_script.getAttribute('extsrc'); 105 if(cur_extsrc) { 106 // extsrc means script does use document.write - we can have 107 // only one definition of document.write, so load sequentially 108 109 current_script.setAttribute('extsrc', ''); // don't run 2nd time 110 111 //console.innerHTML += 'start '+extsrc+'<br>'; 112 113 span = document.createElement('span'); 114 current_script.parentNode.insertBefore(span, current_script); 115 116 document.write = function(txt) { 117 buffer += txt; 118 }; 119 120 document.writeln = function(txt) { 121 buffer += txt; 122 buffer += '\n'; 123 }; 124 125 var s = document.createElement('script'); 126 s.async = true; 127 s.src = cur_extsrc; 128 129 if(isIE()) { 130 // IE 131 132 s.onreadystatechange = function() { 133 //console.innerHTML += 'readychange '+this.src+' '+this.readyState+'?<br>'; 134 135 if(this.readyState == 'loaded' || this.readyState == 'complete') { 136 runNextScript(); 137 }; 138 }; 139 } else { 140 if((navigator.userAgent.indexOf("Firefox")!=-1) || ('onerror' in s)) { 141 // Firefox 142 143 s.onload = runNextScript; 144 s.onerror = runNextScript; 145 } else { 146 // Opera 147 148 s.onload = runNextScript; 149 s.onreadystatechange = runNextScript; 150 }; 151 }; 152 document.getElementsByTagName('head')[0].appendChild(s); 153 return; 154 }; 155 }; 156 dumpBuffer(); 157 document.write = document_write; 158 document.writeln = document_writeln; 159 160 for(var i=0; i<extsrc.complete.funcs.length; i++) { 161 extsrc.complete.funcs[i](); 162 }; 163 }; 164 165 function isIE() { 166 return /msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent); 167 }; 168 169 // Below is the code by 170 // Dean Edwards/Matthias Miller/John Resig 171 // that just acts as window.onload, but in browser-specific way 172
173 function init() { 174 if (arguments.callee.done) return; 175 arguments.callee.done = true; 176 runNextScript(); 177 }; 178 179 /* Mozilla/Firefox/Opera 9 */ 180 if (document.addEventListener) { 181 document.addEventListener("DOMContentLoaded", init, false); 182 } 183 184 /* Internet Explorer */ 185 /*@cc_on @*/ 186 /*@if (@_win32) 187 document.write("<script id=\"__ie_onload\" defer=\"defer\" src=\"javascript:void(0)\"><\/script>"); 188 var script = document.getElementById("__ie_onload"); 189 script.onreadystatechange = function() { 190 if (this.readyState == "complete") { 191 init(); 192 } 193 }; 194 /*@end @*/ 195 196 /* Safari */ 197 if (/WebKit/i.test(navigator.userAgent)) { // ÑÑловие Ð´Ð»Ñ Safari 198 var _timer = setInterval(function() { 199 if (/loaded|complete/.test(document.readyState)) { 200 clearInterval(_timer); 201 init(); 202 } 203 }, 10); 204 } 205 206 /* rest */ 207 window.onload = init; 208 209})(); 210 211
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.