首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

【转载】easyUi源码分析03-easyloader源码详细诠释

2012-08-30 
【转载】easyUi源码分析03--easyloader源码详细注释原帖地址: http://blog.csdn.net/baozhifei/article/deta

【转载】easyUi源码分析03--easyloader源码详细注释

原帖地址: http://blog.csdn.net/baozhifei/article/details/6430586

?

本人观点:这个作者的注释更详细,所以转载记录之。【本人还是不建议使用easyloader.js】

------------以下为转载内容----------------------------

?

Jquery easyui是一个javascript UI 组件库,使用它可以快速开发企业级的业务系统。如果你正准备开发系统后台,可以选择jquery easyui,也可以选择Ext JS。我个人的看法是,如果开发团队就两三个人,开发工期很短,就一两个月。那么选择jquery easyui就对了,jquery easyui源代码量不多,便于阅读和自行修改。而Ext JSy源代码太多,短时间很难看完,学习曲线也比较陡峭。如果人手充足,时间也富裕,可以考虑使用Ext JS来开发,毕竟Ext JS更强大,控件更多。


Jquery easyui是基于Jquery插件机制扩展的,所以如果你很熟悉Jquery,那么使用它开发会很简单。

?

Jquery easyui的源代码svn地址:http://jquery-easyui.googlecode.com/svn

?

方法一:easyloader模块是用来加载jquery easyui的js和css文件的,而且它可以分析模块的依赖关系,先加载依赖项。模块加载好了会调用parse模块来解析页面。把class是easyui开头的标签都转化成easyui的控件。

    /** * easyloader - jQuery EasyUI * * Licensed under the GPL: * http://www.gnu.org/licenses/gpl.txt * * Copyright 2010 stworthy [ stworthy@gmail.com ] * */(function(){// 模块文件定义var modules = {draggable:{js:'jquery.draggable.js'},droppable:{js:'jquery.droppable.js'},resizable:{js:'jquery.resizable.js'},linkbutton:{js:'jquery.linkbutton.js',css:'linkbutton.css'},pagination:{js:'jquery.pagination.js',css:'pagination.css',dependencies:['linkbutton']},datagrid:{js:'jquery.datagrid.js',css:'datagrid.css',dependencies:['panel','resizable','linkbutton','pagination']},treegrid:{js:'jquery.treegrid.js',css:'tree.css',dependencies:['datagrid']},panel: {js:'jquery.panel.js',css:'panel.css'},window:{js:'jquery.window.js',css:'window.css',dependencies:['resizable','draggable','panel']},dialog:{js:'jquery.dialog.js',css:'dialog.css',dependencies:['linkbutton','window']},messager:{js:'jquery.messager.js',css:'messager.css',dependencies:['linkbutton','window']},layout:{js:'jquery.layout.js',css:'layout.css',dependencies:['resizable','panel']},form:{js:'jquery.form.js'},menu:{js:'jquery.menu.js',css:'menu.css'},tabs:{js:'jquery.tabs.js',css:'tabs.css',dependencies:['panel','linkbutton']},splitbutton:{js:'jquery.splitbutton.js',css:'splitbutton.css',dependencies:['linkbutton','menu']},menubutton:{js:'jquery.menubutton.js',css:'menubutton.css',dependencies:['linkbutton','menu']},accordion:{js:'jquery.accordion.js',css:'accordion.css',dependencies:['panel']},calendar:{js:'jquery.calendar.js',css:'calendar.css'},combo:{js:'jquery.combo.js',css:'combo.css',dependencies:['panel','validatebox']},combobox:{js:'jquery.combobox.js',css:'combobox.css',dependencies:['combo']},combotree:{js:'jquery.combotree.js',dependencies:['combo','tree']},combogrid:{js:'jquery.combogrid.js',dependencies:['combo','datagrid']},validatebox:{js:'jquery.validatebox.js',css:'validatebox.css'},numberbox:{js:'jquery.numberbox.js',dependencies:['validatebox']},spinner:{js:'jquery.spinner.js',css:'spinner.css',dependencies:['validatebox']},numberspinner:{js:'jquery.numberspinner.js',dependencies:['spinner','numberbox']},timespinner:{js:'jquery.timespinner.js',dependencies:['spinner']},tree:{js:'jquery.tree.js',css:'tree.css',dependencies:['draggable','droppable']},datebox:{js:'jquery.datebox.js',css:'datebox.css',dependencies:['calendar','validatebox']},parser:{js:'jquery.parser.js'}};// 国际化资源文件var locales = {'af':'easyui-lang-af.js','bg':'easyui-lang-bg.js','ca':'easyui-lang-ca.js','cs':'easyui-lang-cs.js','da':'easyui-lang-da.js','de':'easyui-lang-de.js','en':'easyui-lang-en.js','fr':'easyui-lang-fr.js','nl':'easyui-lang-nl.js','zh_CN':'easyui-lang-zh_CN.js','zh_TW':'easyui-lang-zh_TW.js'};// 加载队列var queues = {};/** * 加载js文件函数,过程就是动态创建一个script标签,然后添加到head标签中去。 * 有一个问题是监听了script标签的两个事件函数,一个是onload,另一个是onreadystatechange,这个数要是针对IE和非IE浏览器准备的 * 万恶的IE浏览器!!! */function loadJs(url, callback){var done = false;var script = document.createElement('script');script.type = 'text/javascript';script.language = 'javascript';script.src = url;script.onload = script.onreadystatechange = function(){if (!done && (!script.readyState || script.readyState == 'loaded' || script.readyState == 'complete')){done = true;script.onload = script.onreadystatechange = null;if (callback){callback.call(script);}}}document.getElementsByTagName("head")[0].appendChild(script);}/** * 执行js文件。就是把js文件加载进来,再remove掉 * @param url js的url * @callback 回调函数,执行完js时会调用这个函数 */function runJs(url, callback){loadJs(url, function(){document.getElementsByTagName("head")[0].removeChild(this);if (callback){callback();}});}/** * 加载css文件。和加载js文件一样,动态创建一个link标签,然后追加到head标签中去 * @param url css的url * @param callback 回调函数,加载完成后调用此函数 */function loadCss(url, callback){var link = document.createElement('link');link.rel = 'stylesheet';link.type = 'text/css';link.media = 'screen';link.href = url;document.getElementsByTagName('head')[0].appendChild(link);if (callback){callback.call(link);}}/** * 加载单独的一个模块 */function loadSingle(name, callback){// 加载队列存入该模块名,并表示状态为loading。queues[name] = 'loading';// 根据模块名,取出该模块定义var module = modules[name];// js加载状态var jsStatus = 'loading';// css加载状态,从这里你就可以看出easyloader.css就是一个开关变量,控制是否加载模块相应的css文件var cssStatus = (easyloader.css && module['css']) ? 'loading' : 'loaded';// 是css文件,就使用loadCss来加载之if (easyloader.css && module['css']){if (/^http/i.test(module['css'])){var url = module['css'];} else {var url = easyloader.base + 'themes/' + easyloader.theme + '/' + module['css'];}loadCss(url, function(){cssStatus = 'loaded';if (jsStatus == 'loaded' && cssStatus == 'loaded'){finish();}});}// 是js文件,就是用LoadJs来加载之if (/^http/i.test(module['js'])){var url = module['js'];} else {var url = easyloader.base + 'plugins/' + module['js'];}loadJs(url, function(){jsStatus = 'loaded';if (jsStatus == 'loaded' && cssStatus == 'loaded'){finish();}});// 最终调用finish函数,来结束加载。并触发onProgress函数,每加载成功一个模块,就调用一次onProgressfunction finish(){queues[name] = 'loaded';easyloader.onProgress(name);if (callback){callback();}}}/** * easyui模块加载函数 * @param name 模块名,可以是string,也可以是数组 * @param callback 回调函数,当加载结束后会调用此函数 */function loadModule(name, callback){// 模块名,根据依赖关系,从前到后,依次排开var mm = [];// 加载标识,当其值为true时,表示需要加载的模块已经加载好了var doLoad = false;// 模块名支持两中,一种是string,一种是数组。这样就可以一次加载多个模块了if (typeof name == 'string'){// 是string的时候,调用add方法把模块名push到mm数组中去add(name);} else {for(var i=0; i<name.length; i++){// 是数组的时候,循环调用add方法把模块名统统push到mm数组中去add(name[i]);}}/** * loadModule函数中内嵌的一个函数,用来加载模块名到变量mm数组中去 * @param name 模块名,只能是string */function add(name){// 保护措施,如果该模块名不存在,我们就不要加载了if (!modules[name]) return;// 否则,就是该模块存在。然后,我们在看看其有没有依赖模块var d = modules[name]['dependencies'];if (d){// 如果有依赖模块,我们要先把依赖模块的名字push到mm中去// 这里用了递归调用for(var i=0; i<d.length; i++){add(d[i]);}}// 把模块名放到mm中mm.push(name);}/** * 当一个模块及其依赖模块加载完成时,执行回调函数,并且触发onLoad函数 */function finish(){if (callback){callback();}easyloader.onLoad(name);}// 加载用时var time = 0;/** * 加载所需要的模块,需要的模块,我们已经统计好了,并按依赖关系,先后push到mm中去了 */function loadMm(){// 判断mm是不是空的if (mm.length){// 第一个模块var m = mm[0];// 判断加载队列是否包含此模块if (!queues[m]){// 加载队列不包含此模块,开始加载该模块// 把doLoad置成true,表示开始加载doLoad = true;// 调用loadSingle方法来加载模块,加载成功后会把此模块从mm中shift掉,然后继续调用loadMM方法,就形成了递归调用loadSingle(m, function(){mm.shift();loadMm();});} else if (queues[m] == 'loaded'){// 加载队列已经加载过此模块了,不需要在加载了,直接从mm中shift掉即可mm.shift();loadMm();} else {// 表示正在加载该模块,累计所用时间如果没有超过timeout// 则过10毫秒再调用一次loadMm函数if (time < easyloader.timeout){time += 10;setTimeout(arguments.callee, 10);}}} else {// 走到这里,表示该加载的模块都已经加载好了if (easyloader.locale && doLoad == true && locales[easyloader.locale]){// 如果设置了国际化,并且已经加载好了,而且该国际化资源还存在,那么加载该资源jsvar url = easyloader.base + 'locale/' + locales[easyloader.locale];// 执行js完事后,调用finish方法runJs(url, function(){finish();});} else {// 没定义国际化文件,那么直接调用finish方法吧finish();}}}loadMm();}/** * easyloader定义为全局变量 */easyloader = {// 各个模块文件的定义,包括js、css和依赖模块modules:modules,// 国际化资源文件locales:locales,// jquery-easyui的根目录,在加载easyloader时,会自动根据你放置的位置而改变base:'.',// 控件的主题,一共就有两个,在theme目录中。还有一个gray主题,浅灰色的,很难看。theme:'default',// 这是一个开关变量,控制easyloader加载模块时,要不要加载相应的css文件,默认是需要加载的css:true,// 国际化语言,可以根据window.navigator.language或者window.navigator.userLanguage来获取当前浏览器的语言。// 有两个属性,主要因为IE浏览器只认识userLanguage和sysLanguage,万恶的IE浏览器啊!locale:null,// 加载一个模块的最长时间,超过这个时间,就开始加载下一个模块了。timeout:2000,// easyloader就公开了这么一个方法,用来加载模块。// name是模块名,callback是加载成功后执行的函数load: function(name, callback){if (//.css$/i.test(name)){// 如果模块名是以.css结尾if (/^http/i.test(name)){// 如果模块名是以http开头,那么css是一个文件的urlloadCss(name, callback);} else {// 否则,说明模块名相对于jquery easyui根目录来说的loadCss(easyloader.base + name, callback);}} else if (//.js$/i.test(name)){// 如果模块名是以.js结尾if (/^http/i.test(name)){// 如果模块名是以http开头,那么js是一个文件的urlloadJs(name, callback);} else {// 否则,说明模块名相对于jquery easyui根目录来说的loadJs(easyloader.base + name, callback);}} else {// 以上两种都不是,说明是easyui自己的模块,直接使用loadModule来加载,就可以了loadModule(name, callback);}},// 当一个模块加载完会触发此函数onProgress: function(name){},// 当一个模块和其依赖都加载完会触发此函数onLoad: function(name){}};/** * 这一小段代码就是查找jquery-easyui的根目录,并赋值给easyloader的base属性上。这样easyloader再加载css文件和js文件就很方便定位了。 */var scripts = document.getElementsByTagName('script');for(var i=0; i<scripts.length; i++){var src = scripts[i].src;if (!src) continue;var m = src.match(/easyloader/.js(/W|$)/i);if (m){easyloader.base = src.substring(0, m.index);}}/** * 这个就起一个别名的作用,比如页面中可以想如下这么下: * using('window'); * 这样window模块就加载进来了! */window.using = easyloader.load;/** * easyloader.js加载的第一模块是parse模块,parser模块调用parse方法,可以解析页面上的easyui控件 */if (window.jQuery){jQuery(function(){easyloader.load('parser', function(){jQuery.parser.parse();});});}})();?

    ?

热点排行