zoukankan      html  css  js  c++  java
  • easyloader源码

      1 /**
      2  * easyloader - jQuery EasyUI
      3  * 
      4  * Licensed under the GPL:
      5  *   http://www.gnu.org/licenses/gpl.txt
      6  *
      7  * Copyright 2010 stworthy [ stworthy@gmail.com ] 
      8  * 
      9  */
     10 (function(){
     11     //将所有的插件,和插件资源和依赖文件放进modules对象中。
     12     var modules = {
     13         
     14         draggable:{
     15             js:'jquery.draggable.js'
     16         },
     17         droppable:{
     18             js:'jquery.droppable.js'
     19         },
     20         resizable:{
     21             js:'jquery.resizable.js'
     22         },
     23         linkbutton:{
     24             js:'jquery.linkbutton.js',
     25             css:'linkbutton.css'
     26         },
     27         pagination:{
     28             js:'jquery.pagination.js',
     29             css:'pagination.css',
     30             dependencies:['linkbutton']
     31         },
     32         datagrid:{
     33             js:'jquery.datagrid.js',
     34             css:'datagrid.css',
     35             dependencies:['panel','resizable','linkbutton','pagination']
     36         },
     37         treegrid:{
     38             js:'jquery.treegrid.js',
     39             css:'tree.css',
     40             dependencies:['datagrid']
     41         },
     42         panel: {
     43             js:'jquery.panel.js',
     44             css:'panel.css'
     45         },
     46         window:{
     47             js:'jquery.window.js',
     48             css:'window.css',
     49             dependencies:['resizable','draggable','panel']
     50         },
     51         dialog:{
     52             js:'jquery.dialog.js',
     53             css:'dialog.css',
     54             dependencies:['linkbutton','window']
     55         },
     56         messager:{
     57             js:'jquery.messager.js',
     58             css:'messager.css',
     59             dependencies:['linkbutton','window']
     60         },
     61         layout:{
     62             js:'jquery.layout.js',
     63             css:'layout.css',
     64             dependencies:['resizable','panel']
     65         },
     66         form:{
     67             js:'jquery.form.js'
     68         },
     69         menu:{
     70             js:'jquery.menu.js',
     71             css:'menu.css'
     72         },
     73         tabs:{
     74             js:'jquery.tabs.js',
     75             css:'tabs.css',
     76             dependencies:['panel','linkbutton']
     77         },
     78         splitbutton:{
     79             js:'jquery.splitbutton.js',
     80             css:'splitbutton.css',
     81             dependencies:['linkbutton','menu']
     82         },
     83         menubutton:{
     84             js:'jquery.menubutton.js',
     85             css:'menubutton.css',
     86             dependencies:['linkbutton','menu']
     87         },
     88         accordion:{
     89             js:'jquery.accordion.js',
     90             css:'accordion.css',
     91             dependencies:['panel']
     92         },
     93         calendar:{
     94             js:'jquery.calendar.js',
     95             css:'calendar.css'
     96         },
     97         combo:{
     98             js:'jquery.combo.js',
     99             css:'combo.css',
    100             dependencies:['panel','validatebox']
    101         },
    102         combobox:{
    103             js:'jquery.combobox.js',
    104             css:'combobox.css',
    105             dependencies:['combo']
    106         },
    107         combotree:{
    108             js:'jquery.combotree.js',
    109             dependencies:['combo','tree']
    110         },
    111         combogrid:{
    112             js:'jquery.combogrid.js',
    113             dependencies:['combo','datagrid']
    114         },
    115         validatebox:{
    116             js:'jquery.validatebox.js',
    117             css:'validatebox.css'
    118         },
    119         numberbox:{
    120             js:'jquery.numberbox.js',
    121             dependencies:['validatebox']
    122         },
    123         spinner:{
    124             js:'jquery.spinner.js',
    125             css:'spinner.css',
    126             dependencies:['validatebox']
    127         },
    128         numberspinner:{
    129             js:'jquery.numberspinner.js',
    130             dependencies:['spinner','numberbox']
    131         },
    132         timespinner:{
    133             js:'jquery.timespinner.js',
    134             dependencies:['spinner']
    135         },
    136         tree:{
    137             js:'jquery.tree.js',
    138             css:'tree.css',
    139             dependencies:['draggable','droppable']
    140         },
    141         datebox:{
    142             js:'jquery.datebox.js',
    143             css:'datebox.css',
    144             dependencies:['calendar','validatebox']
    145         },
    146         parser:{
    147             js:'jquery.parser.js'
    148         }
    149     };
    150     //将国际化文件放入一个locales对象中
    151     var locales = {
    152         'af':'easyui-lang-af.js',
    153         'bg':'easyui-lang-bg.js',
    154         'ca':'easyui-lang-ca.js',
    155         'cs':'easyui-lang-cs.js',
    156         'da':'easyui-lang-da.js',
    157         'de':'easyui-lang-de.js',
    158         'en':'easyui-lang-en.js',
    159         'fr':'easyui-lang-fr.js',
    160         'nl':'easyui-lang-nl.js',
    161         'zh_CN':'easyui-lang-zh_CN.js',
    162         'zh_TW':'easyui-lang-zh_TW.js'
    163     };
    164     
    165     //定义一个局部变量,做循环遍历时候,存放状态
    166     var queues = {};
    167     
    168     //加载js方法
    169     function loadJs(url, callback){
    170         //标志变量,js是否加载并执行
    171         var done = false;
    172         var script = document.createElement('script');//创建script dom
    173         script.type = 'text/javascript';
    174         script.language = 'javascript';
    175         script.src = url;
    176         script.onload = script.onreadystatechange = function(){ //onload是firefox 浏览器事件,onreadystatechange,是ie的,为了兼容,两个都写上,这样写会导致内存泄露
    177             //script.readyState只是ie下有这个属性,如果这个值为undefined,说明是在firefox,就直接可以执行下面的代码了。反之为ie,需要对script.readyState
    178             //状态具体值进行判别,loaded和complete状态表示,脚本加载了并执行了。
    179             if (!done && (!script.readyState || script.readyState == 'loaded' || script.readyState == 'complete')){
    180                 done = true;
    181                 
    182                 script.onload = script.onreadystatechange = null;//释放内存,还会泄露。
    183                 if (callback){//加载后执行回调
    184                     callback.call(script);
    185                 }
    186             }
    187         }
    188         //具体加载动作,上面的onload是注册事件,
    189         document.getElementsByTagName("head")[0].appendChild(script);
    190     }
    191     //运行js ,看代码逻辑可知,运行js,只是在js执行后,将这个script删除而已,主要用来加载国际化文件
    192     function runJs(url, callback){
    193         loadJs(url, function(){
    194             document.getElementsByTagName("head")[0].removeChild(this);
    195             if (callback){
    196                 callback();
    197             }
    198         });
    199     }
    200     
    201     //加载css没什么好说的
    202     function loadCss(url, callback){
    203         var link = document.createElement('link');
    204         link.rel = 'stylesheet';
    205         link.type = 'text/css';
    206         link.media = 'screen';
    207         link.href = url;
    208         document.getElementsByTagName('head')[0].appendChild(link);
    209         if (callback){
    210             callback.call(link);
    211         }
    212     }
    213     //加载单一一个plugin,仔细研究module ,可以发现,pingin之间通过dependence,构造成了一颗依赖树,
    214     //这个方法,就是加载具体树中的一个节点
    215     function loadSingle(name, callback){
    216         //把整个plugin的状态设置为loading
    217         queues[name] = 'loading';
    218         
    219         var module = modules[name];
    220         //把js状态设置为loading
    221         var jsStatus = 'loading';
    222         //如果允许css,并且plugin有css,则加载css,否则设置加载过了,其实是不加载
    223         var cssStatus = (easyloader.css && module['css']) ? 'loading' : 'loaded';
    224         //加载css,plugin 的css,如果是全称,就用全称,否则把简写换成全称,所以简写的css文件要放入到themes/type./文件下
    225         if (easyloader.css && module['css']){
    226             if (/^http/i.test(module['css'])){
    227                 var url = module['css'];
    228             } else {
    229                 var url = easyloader.base + 'themes/' + easyloader.theme + '/' + module['css'];
    230             }
    231             loadCss(url, function(){
    232                 cssStatus = 'loaded';
    233                 //js, css加载完,才调用回调
    234                 if (jsStatus == 'loaded' && cssStatus == 'loaded'){
    235                     finish();
    236                 }
    237             });
    238         }
    239         //加载js,全称用全称,简写补全。
    240         if (/^http/i.test(module['js'])){
    241             var url = module['js'];
    242         } else {
    243             var url = easyloader.base + 'plugins/' + module['js'];
    244         }
    245         loadJs(url, function(){
    246             jsStatus = 'loaded';
    247             if (jsStatus == 'loaded' && cssStatus == 'loaded'){
    248                 finish();
    249             }
    250         });
    251         //加载完调用的方法,改plugin状态
    252         function finish(){
    253             queues[name] = 'loaded';
    254             //调用正在加载的方法,其实已经加载完了,
    255             easyloader.onProgress(name);
    256             if (callback){
    257                 callback();
    258             }
    259         }
    260     }
    261     //加载主模块入口,
    262     function loadModule(name, callback){
    263         //定义数组,最后是形成的是依赖插件列表,最独立的插件放在首位,name是末尾
    264         var mm = [];
    265         var doLoad = false;
    266         //name有两种,一种是string ,一种是string array,这样一次可以加载多个plugin,都是调用add方法进行添加
    267         if (typeof name == 'string'){
    268             add(name);
    269         } else {
    270             for(var i=0; i<name.length; i++){
    271                 add(name[i]);
    272             }
    273         }
    274         
    275         function add(name){
    276             //如果modules中没有这个plugin那退出
    277             if (!modules[name]) return;
    278             //如果有,查看它是否依赖其他plugin
    279             var d = modules[name]['dependencies'];
    280             //如果依赖,就加载依赖的plugin.同时在加载依赖的plugin的依赖。注意循环中调用了add,是递归
    281             if (d){
    282                 for(var i=0; i<d.length; i++){
    283                     add(d[i]);
    284                 }
    285             }
    286             mm.push(name);
    287         }
    288         
    289         function finish(){
    290             if (callback){
    291                 callback();
    292             }
    293             //调用onLoad,传递name 为参数
    294             easyloader.onLoad(name);
    295         }
    296         //形成依赖树,不行还没有做实质性工作呢,那就是加载。打起精神来,最核心的代码就是以下的了
    297         //超时用
    298         var time = 0;
    299         //定义一个加载方法,定义后直接调用
    300         function loadMm(){
    301             //如果mm有长度,长度!=0,加载plugin,为0,即加载完毕,开始加载国际化文件。
    302             if (mm.length){
    303                 var m = mm[0];    // the first module
    304                 if (!queues[m]){//状态序列中没有这个plugin的信息,说明没有加载这个plug,调用laodSingle进行加载
    305                     doLoad = true; 
    306                     loadSingle(m, function(){
    307                         mm.shift();//加载完成后,将这个元素从数组去除,在继续加载,直到数组
    308                         loadMm();
    309                     });
    310                 } else if (queues[m] == 'loaded'){//如果这个plugin已经加载,就不用加载,以为mm中可能有重复项
    311                     mm.shift();
    312                     loadMm();
    313                 } else {
    314                     if (time < easyloader.timeout){//超时时候,10秒钟调用一次loadMn().注意arguments.callee代表函数本身
    315                         time += 10;
    316                         setTimeout(arguments.callee, 10); 
    317                     }
    318                 }
    319             } else {
    320                 if (easyloader.locale && doLoad == true && locales[easyloader.locale]){
    321                     var url = easyloader.base + 'locale/' + locales[easyloader.locale];
    322                     runJs(url, function(){
    323                         finish();
    324                     });
    325                 } else {
    326                     finish();
    327                 }
    328             }
    329         }
    330         
    331         loadMm();
    332     }
    333 //    定义一个加载器,注意,是全局变量,没有var,
    334     easyloader = {
    335         modules:modules,
    336         locales:locales,
    337         
    338         base:'.',//该属性是为了加载js,记录文件夹路径的
    339         theme:'default', //默认主题
    340         css:true,  
    341         locale:null,
    342         timeout:2000,//加载超时事件
    343     //easyloader.load(),该模块加载的调用方法,先加载css,然后加载js
    344         load: function(name, callback){
    345             //如果加载是*.css文件,判断是不是以http开头,如果是,直接调用
    346             if (/.css$/i.test(name)){
    347                 if (/^http/i.test(name)){
    348                     loadCss(name, callback);
    349                 } else {
    350                     //不是http的,加上base.文件夹路径
    351                     loadCss(easyloader.base + name, callback);
    352                 }
    353             } 
    354             //加载js文件
    355             else if (/.js$/i.test(name)){
    356                 if (/^http/i.test(name)){
    357                     loadJs(name, callback);
    358                 } else {
    359                     loadJs(easyloader.base + name, callback);
    360                 }
    361             } else {
    362                 //如果直接传递一个插件名,就去modole数组中加载。改方法是重点,也是easyui自带的plugin加载方式
    363                 loadModule(name, callback);
    364             }
    365         },
    366         
    367         onProgress: function(name){},
    368         onLoad: function(name){}
    369     };
    370 //以上一直在定义函数,和变量,此处为真正执行处
    371 //获取页面的所有的script,主要是为了获取我们现在解释的easyloader.js文件路径,来设置base属性
    372     var scripts = document.getElementsByTagName('script');
    373     for(var i=0; i<scripts.length; i++){
    374         var src = scripts[i].src;
    375         if (!src) continue;
    376         var m = src.match(/easyloader.js(W|$)/i);//判断文件是否含有easyloadr.js
    377         if (m){
    378             //如果有,base为easyloadr.js 的相同前缀
    379             easyloader.base = src.substring(0, m.index);
    380         }
    381     }
    382 //定义一个简化调用接口
    383     window.using = easyloader.load;
    384     
    385     if (window.jQuery){
    386         jQuery(function(){
    387             //系统数据加载完后,加载parser.js插件,该插件是渲染界面的
    388             easyloader.load('parser', function(){
    389                 jQuery.parser.parse();//渲染方法
    390             });
    391         });
    392     }
    393     
    394 })();
  • 相关阅读:
    Candy leetcode java
    Trapping Rain Water leetcode java
    Best Time to Buy and Sell Stock III leetcode java
    Best Time to Buy and Sell Stock II leetcode java
    Best Time to Buy and Sell Stock leetcode java
    Maximum Subarray leetcode java
    Word Break II leetcode java
    Word Break leetcode java
    Anagrams leetcode java
    Clone Graph leetcode java(DFS and BFS 基础)
  • 原文地址:https://www.cnblogs.com/dhl-2013/p/4562990.html
Copyright © 2011-2022 走看看