src/common/pluginloader.js 加载所有 cordova_plugins.js 中定义的模块,执行完成后会触发onPluginsReady
Js 代码
// file: src/common/pluginloader.js |
define("cordova/pluginloader", function(require, exports, module) { |
var modulemapper = require('cordova/modulemapper'); |
var urlutil = require('cordova/urlutil'); |
// 创建<script>tag,把js文件动态添加到head中 |
function injectScript(url, onload, onerror) { |
var script = document.createElement("script"); |
script.onload = onload; |
script.onerror = onerror || onload; // 出错的时候也执行onload处理 |
script.src = url; |
document.head.appendChild(script); |
} |
// 加载到head中的插件js脚本定义如下: |
// cordova.define("org.apache.cordova.xxx", function(require, exports, module) { ... }); |
// 模块名称是cordova_plugins.js中定义的id,所以要把该id指向定义好的clobbers |
function onScriptLoadingComplete(moduleList, finishPluginLoading) { |
for (var i = 0, module; module = moduleList[i]; i++) { |
if (module) { |
try { |
// 把该模块需要clobber的clobber到指定的clobbers里 |
if (module.clobbers && module.clobbers.length) { |
for (var j = 0; j < module.clobbers.length; j++) { |
modulemapper.clobbers(module.id, module.clobbers[j]); |
} |
} |
// 把该模块需要合并的部分合并到指定的模块里 |
if (module.merges && module.merges.length) { |
for (var k = 0; k < module.merges.length; k++) { |
modulemapper.merges(module.id, module.merges[k]); |
} |
} |
// 处理只希望require()的模块 |
// <js-module src="www/xxx.js" name="Xxx"> |
// <runs /> |
// </js-module> |
if (module.runs && !(module.clobbers && module.clobbers.length) && !(module.merges && module.merges.length)) { |
modulemapper.runs(module.id); |
} |
} |
catch(err) { |
} |
} |
} |
// 插件js脚本加载完成后,执行回调!!! |
finishPluginLoading(); |
} |
// 加载所有cordova_plugins.js中定义的js-module |
function handlePluginsObject(path, moduleList, finishPluginLoading) { |
var scriptCounter = moduleList.length; |
// 没有插件,直接执行回调后返回 |
if (!scriptCounter) { |
finishPluginLoading(); |
return; |
} |
// 加载每个插件js的脚本的回调 |
function scriptLoadedCallback() { |
// 加载完成一个就把计数器减1 |
if (!--scriptCounter) { |
// 直到所有插件的js脚本都被加载完成后clobber |
onScriptLoadingComplete(moduleList, finishPluginLoading); |
} |
} |
// 依次把插件的js脚本添加到head中后加载 |
for (var i = 0; i < moduleList.length; i++) { |
injectScript(path + moduleList[i].file, scriptLoadedCallback); |
} |
} |
// 注入插件的js脚本 |
function injectPluginScript(pathPrefix, finishPluginLoading) { |
var pluginPath = pathPrefix + 'cordova_plugins.js'; |
// 根据cordova.js文件的路径首先把cordova_plugins.js添加到head中后加载 |
injectScript(pluginPath, function() { |
try { |
// 导入cordova_plugins.jsz中定义的'cordova/plugin_list'模块 |
// 这个文件的内容是根据所有插件的plugin.xml生成的。 |
var moduleList = require("cordova/plugin_list"); |
// 加载所有cordova_plugins.js中定义的js-module |
handlePluginsObject(pathPrefix, moduleList, finishPluginLoading); |
} |
catch (e) { |
// 忽略cordova_plugins.js记载失败、或者文件不存在等错误 |
finishPluginLoading(); |
} |
}, finishPluginLoading); |
} |
// 获取cordova.js文件的路径 |
function findCordovaPath() { |
var path = null; |
var scripts = document.getElementsByTagName('script'); |
var term = 'cordova.js'; |
for (var n = scripts.length-1; n>-1; n--) { |
var src = scripts[n].src; |
if (src.indexOf(term) == (src.length - term.length)) { |
path = src.substring(0, src.length - term.length); |
break; |
} |
} |
return path; |
} |
// 加载所有cordova_plugins.js中定义的js-module |
// 执行完成后会触发onPluginsReady(异步执行) |
exports.load = function(callback) { |
// 取cordova.js文件所在的路径 |
var pathPrefix = findCordovaPath(); |
if (pathPrefix === null) { |
console.log('Could not find cordova.js script tag. Plugin loading may fail.'); |
pathPrefix = ''; |
} |
// 注入插件的js脚本,执行完成后回调onPluginsReady |
injectPluginScript(pathPrefix, callback); |
}; |
}); |