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);
};
});