l.js

l.js is another simple/tiny javascript/css loader

This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.greatest.deepsurf.us/scripts/23419/634829/ljs.js

  1. //https://github.com/jae-jae/l.js
  2. ;(function(window, undefined){
  3. /*
  4. * script for js/css parallel loading with dependancies management
  5. * @author Jonathan Gotti < jgotti at jgotti dot net >
  6. * @licence dual licence mit / gpl
  7. * @since 2012-04-12
  8. * @todo add prefetching using text/cache for js files
  9. * @changelog
  10. * - 2016-08-22 - remove global eval and fix issue #13
  11. * - 2014-06-26 - bugfix in css loaded check when hashbang is used
  12. * - 2014-05-25 - fallback support rewrite + null id bug correction + minification work
  13. * - 2014-05-21 - add cdn fallback support with hashbang url
  14. * - 2014-05-22 - add support for relative paths for stylesheets in checkLoaded
  15. * - 2014-05-21 - add support for relative paths for scripts in checkLoaded
  16. * - 2013-01-25 - add parrallel loading inside single load call
  17. * - 2012-06-29 - some minifier optimisations
  18. * - 2012-04-20 - now sharp part of url will be used as tag id
  19. * - add options for checking already loaded scripts at load time
  20. * - 2012-04-19 - add addAliases method
  21. * @note coding style is implied by the target usage of this script not my habbits
  22. */
  23. var isA = function(a,b){ return a instanceof (b || Array);}
  24. //-- some minifier optimisation
  25. , D = document
  26. , getElementsByTagName = 'getElementsByTagName'
  27. , length = 'length'
  28. , readyState = 'readyState'
  29. , onreadystatechange = 'onreadystatechange'
  30. //-- get the current script tag for further evaluation of it's eventual content
  31. , scripts = D[getElementsByTagName]("script")
  32. , scriptTag = scripts[scripts[length]-1]
  33. , script = scriptTag.innerHTML.replace(/^\s+|\s+$/g,'')
  34. ;
  35. //avoid multiple inclusion to override current loader but allow tag content evaluation
  36. if( ! window.ljs ){
  37. var checkLoaded = scriptTag.src.match(/checkLoaded/)?1:0
  38. //-- keep trace of header as we will make multiple access to it
  39. ,header = D[getElementsByTagName]("head")[0] || D.documentElement
  40. , urlParse = function(url){
  41. var parts={}; // u => url, i => id, f = fallback
  42. parts.u = url.replace(/#(=)?([^#]*)?/g,function(m,a,b){ parts[a?'f':'i'] = b; return '';});
  43. return parts;
  44. }
  45. ,appendElmt = function(type,attrs,cb){
  46. var e = D.createElement(type), i;
  47. if( cb ){ //-- this is not intended to be used for link
  48. if(e[readyState]){
  49. e[onreadystatechange] = function(){
  50. if (e[readyState] === "loaded" || e[readyState] === "complete"){
  51. e[onreadystatechange] = null;
  52. cb();
  53. }
  54. };
  55. }else{
  56. e.onload = cb;
  57. }
  58. }
  59. for( i in attrs ){ attrs[i] && (e[i]=attrs[i]); }
  60. header.appendChild(e);
  61. // return e; // unused at this time so drop it
  62. }
  63. ,ajaxExec = function (url,success,error) {
  64.  
  65. GM_xmlhttpRequest({
  66. method: "GET",
  67. url:url,
  68. onload:function(res){
  69. //eval.call(global,res.responseText);
  70. eval(res.responseText);
  71. success();
  72. },
  73. onerror:function(){
  74. error && error();
  75. }
  76. });
  77.  
  78. }
  79. ,load = function(url,cb){
  80. if( this.aliases && this.aliases[url] ){
  81. var args = this.aliases[url].slice(0);
  82. isA(args) || (args=[args]);
  83. cb && args.push(cb);
  84. return this.load.apply(this,args);
  85. }
  86. if( isA(url) ){ // parallelized request
  87. for( var l=url[length]; l--;){
  88. this.load(url[l]);
  89. }
  90. cb && url.push(cb); // relaunch the dependancie queue
  91. return this.load.apply(this,url);
  92. }
  93. if( url.match(/\.css\b/) ){
  94. return this.loadcss(url,cb);
  95. }
  96. return this.loadjs(url,cb);
  97. }
  98. ,exec = function(url,cb){
  99. if( this.aliases && this.aliases[url] ){
  100. var args = this.aliases[url].slice(0);
  101. isA(args) || (args=[args]);
  102. cb && args.push(cb);
  103. return this.exec.apply(this,args);
  104. }
  105. if( isA(url) ){ // parallelized request
  106. for( var l=url[length]; l--;){
  107. this.exec(url[l]);
  108. }
  109. cb && url.push(cb); // relaunch the dependancie queue
  110. return this.exec.apply(this,url);
  111. }
  112. if( url.match(/\.css\b/) ){
  113. return this.loadcss(url,cb);
  114. }
  115. return this.execJs(url,cb);
  116. }
  117. ,loaded = {} // will handle already loaded urls
  118. ,loader = {
  119. aliases:{}
  120. ,loadjs: function(url,cb){
  121. var parts = urlParse(url);
  122. url = parts.u;
  123. if( loaded[url] === true ){ // already loaded exec cb if any
  124. cb && cb();
  125. return this;
  126. }else if( loaded[url]!== undefined ){ // already asked for loading we append callback if any else return
  127. if( cb ){
  128. loaded[url] = (function(ocb,cb){ return function(){ ocb && ocb(); cb && cb(); }; })(loaded[url],cb);
  129. }
  130. return this;
  131. }
  132. // first time we ask this script
  133. loaded[url] = (function(cb){ return function(){loaded[url]=true; cb && cb();};})(cb);
  134. cb = function(){ loaded[url](); };
  135. appendElmt('script',{type:'text/javascript',src:url,id:parts.i,onerror:function(error){
  136. if( parts.f ){
  137. var c = error.currentTarget;
  138. c.parentNode.removeChild(c);
  139. appendElmt('script',{type:'text/javascript',src:parts.f,id:parts.i},cb);
  140. }
  141. }},cb);
  142. return this;
  143. }
  144. ,execJs:function(url,cb){
  145. var parts = urlParse(url);
  146. url = parts.u;
  147. if( loaded[url] === true ){ // already loaded exec cb if any
  148. cb && cb();
  149. return this;
  150. }else if( loaded[url]!== undefined ){ // already asked for loading we append callback if any else return
  151. if( cb ){
  152. loaded[url] = (function(ocb,cb){ return function(){ ocb && ocb(); cb && cb(); }; })(loaded[url],cb);
  153. }
  154. return this;
  155. }
  156. // first time we ask this script
  157. loaded[url] = (function(cb){ return function(){loaded[url]=true; cb && cb();};})(cb);
  158. cb = function(){ loaded[url](); };
  159. /*appendElmt('script',{type:'text/javascript',src:url,id:parts.i,onerror:function(error){
  160. if( parts.f ){
  161. var c = error.currentTarget;
  162. c.parentNode.removeChild(c);
  163. appendElmt('script',{type:'text/javascript',src:parts.f,id:parts.i},cb);
  164. }
  165. }},cb);*/
  166. ajaxExec(url,cb,function(){
  167. if( parts.f ){
  168. ajaxExec(parts.f,cb);
  169. }
  170. });
  171. return this;
  172. }
  173. ,loadcss: function(url,cb){
  174. var parts = urlParse(url);
  175. url = parts.u;
  176. loaded[url] || appendElmt('link',{type:'text/css',rel:'stylesheet',href:url,id:parts.i});
  177. loaded[url] = true;
  178. cb && cb();
  179. return this;
  180. }
  181. ,load: function(){
  182. var argv=arguments,argc = argv[length];
  183. if( argc === 1 && isA(argv[0],Function) ){
  184. argv[0]();
  185. return this;
  186. }
  187. load.call(this,argv[0], argc <= 1 ? undefined : function(){ loader.load.apply(loader,[].slice.call(argv,1));} );
  188. return this;
  189. }
  190. ,exec:function(){
  191. var argv=arguments,argc = argv[length];
  192. if( argc === 1 && isA(argv[0],Function) ){
  193. argv[0]();
  194. return this;
  195. }
  196. exec.call(this,argv[0], argc <= 1 ? undefined : function(){ loader.exec.apply(loader,[].slice.call(argv,1));} );
  197. return this;
  198. }
  199. ,addAliases:function(aliases){
  200. for(var i in aliases ){
  201. this.aliases[i]= isA(aliases[i]) ? aliases[i].slice(0) : aliases[i];
  202. }
  203. return this;
  204. }
  205. }
  206. ;
  207. if( checkLoaded ){
  208. var i,l,links,url;
  209. for(i=0,l=scripts[length];i<l;i++){
  210. (url = scripts[i].getAttribute('src')) && (loaded[url.replace(/#.*$/,'')] = true);
  211. }
  212. links = D[getElementsByTagName]('link');
  213. for(i=0,l=links[length];i<l;i++){
  214. (links[i].rel==='stylesheet' || links[i].type==='text/css') && (loaded[links[i].getAttribute('href').replace(/#.*$/,'')]=true);
  215. }
  216. }
  217. //export ljs
  218. window.ljs = loader;
  219. // eval inside tag code if any
  220. }
  221. // eval script tag content if needed
  222. scriptTag.src && script && appendElmt('script', {innerHTML: script});
  223. })(window);