kekule
Version:
Open source JavaScript toolkit for chemoinformatics
1,081 lines (1,007 loc) • 33.2 kB
JavaScript
(function($init_root){
var $root;
{
if (typeof(window) === 'object' && window && window.document)
$root = window;
else if (typeof(global) === 'object') // node env
$root = global;
else if (typeof(self) === 'object')
$root = self;
else
$root = $init_root || {};
}
// IE8 does not support array.indexOf
if (!Array.prototype.indexOf)
{
/** @ignore */
Array.prototype.indexOf = function(item, i) {
i || (i = 0);
var length = this.length;
if (i < 0) i = length + i;
for (; i < length; i++)
if (this[i] === item) return i;
return -1;
};
}
// avoid Node error
var document = $root.document;
if (!document)
{
if (typeof(window) !== 'undefined')
document = window.document;
}
// check if is in Node.js environment
var isInBrowser = (typeof(navigator) !== 'undefined') && (typeof(window) !== 'undefined') && (typeof(document) !== 'undefined');
var hasNodeEnv = (typeof process === 'object') && (typeof process.versions === 'object') && (typeof process.versions.node !== 'undefined');
var isNode = hasNodeEnv;
var isWebpack = (typeof(__webpack_require__) === 'function');
var loadedByImportOrRequire = (typeof(exports) !== 'undefined');
//if (!isWebpack && isNode)
if (typeof(__webpack_require__) !== 'function' && isNode)
{
var __nodeContext = {};
try
{
var vm = require("vm");
var fs = require("fs");
}
catch(e)
{
}
}
if (!isNode)
{
var readyState = document && document.readyState;
var isIE = window.attachEvent && !window.opera;
var docReady = (readyState === 'complete' || readyState === 'loaded' ||
(readyState === 'interactive' && !isIE)); // in IE8-10, handling this script cause readyState to 'interaction' but the whole page is not loaded yet
}
if (isNode && typeof(global) !== 'undefined')
{
$root = global; // set root as global object, share with the context of running Kekule code
}
function isDocReady()
{
if (!isNode)
{
var readyState = document && document.readyState;
var isIE = window.attachEvent && !window.opera;
return (readyState === 'complete' || readyState === 'loaded' ||
(readyState === 'interactive' && !isIE)); // in IE8-10, handling this script cause readyState to 'interaction' but the whole page is not loaded yet
}
else // no doc
return true;
}
function directAppend(doc, libName)
{
doc.write('<script type="text/javascript" src="'+libName+'"><\/script>');
}
function nodeAppend(url)
{
if (isNode)
{
try
{
var fileName = (url.indexOf('file:///') === 0)? url.substr(8): url; // remove possible file:/// protocal mark first
var data = fs.readFileSync(fileName, 'utf8');
vm.runInThisContext(data, {'filename': url});
//vm.runInNewContext(data, __nodeContext, {'filename': url});
//eval(data);
return true;
}
catch(e)
{
// may be in webpack? Need further investigation
/*
if ($root.require)
{
var extPos = url.toLowerCase().lastIndexOf('.js');
var coreFileName;
if (extPos >= 0)
{
coreFileName = url.substr(0, extPos);
}
if (coreFileName)
require('./' + fileName + '.js');
else
require('./' + fileName);
}
*/
//console.error(url, e.message);
return e;
}
}
}
var existedScriptUrls = [];
function appendScriptFile(doc, url, callback)
{
if (existedScriptUrls.indexOf(url) >= 0) // already loaded
{
if (callback)
callback(null);
return;
}
if (isNode)
{
var appendResult = nodeAppend(url);
if (callback)
{
if (appendResult === true)
callback(null);
else
callback(appendResult); // error
}
return appendResult;
}
else // browser
{
try
{
var result = doc.createElement('script');
result.src = url;
result.onerror = function(error){
if (callback)
callback(new Error('Loading script file ' + url + ' failed'));
};
result.onload = result.onreadystatechange = function(e) {
if (result._loaded)
return;
var readyState = result.readyState;
if (readyState === undefined || readyState === 'loaded' || readyState === 'complete')
{
result._loaded = true;
result.onload = result.onreadystatechange = null;
existedScriptUrls.push(url);
if (callback)
callback(null);
}
};
(doc.getElementsByTagName('head')[0] || doc.body).appendChild(result);
return result;
}
catch(e)
{
if (callback)
callback(e);
}
//console.log('load script', url);
}
}
function appendScriptFiles(doc, urls, callback)
{
var dupUrls = [].concat(urls);
_appendScriptFilesCore(doc, dupUrls, callback, []);
}
function _appendScriptFilesCore(doc, urls, callback, errors)
{
if (urls.length <= 0)
{
if (callback)
{
if (!errors.length)
callback(null);
else
callback(new Error(errors.join(', ')));
}
return;
}
var file = urls.shift();
appendScriptFile(doc, file, function(error)
{
if (error)
{
errors.push(error? (error.message || error): '');
}
_appendScriptFilesCore(doc, urls, callback, errors);
}
);
}
function loadChildScriptFiles(scriptUrls, forceDomLoader, callback)
{
if (isNode) // Node.js environment
{
appendScriptFiles(document, scriptUrls, function(error)
{
// set a marker indicate that all modules are loaded
if (this.Kekule || __nodeContext.Kekule)
(this.Kekule || __nodeContext.Kekule)._loaded();
if (callback)
callback(error);
});
}
else // in normal browser environment
{
if (!isDocReady() && !forceDomLoader) // can directly write to document
{
try
{
for (var i = 0, l = scriptUrls.length; i < l; ++i)
directAppend(document, scriptUrls[i]);
var sloadedCode = 'if (this.Kekule) Kekule._loaded();';
/*
if (window.btoa) // use data uri to insert loaded code, avoid inline script problem in Chrome extension (still no use in Chrome)
{
var sBase64 = btoa(sloadedCode);
var sdataUri = 'data:;base64,' + sBase64;
directAppend(document, sdataUri);
}
else // use simple inline code in IE below 10 (which do not support data uri)
*/
//directAppend(document, 'kekule.loaded.js'); // manully add small file to mark lib loaded
document.write('<script type="text/javascript">' + sloadedCode + '<\/script>');
if (callback)
callback(null);
}
catch(e)
{
callback(e);
}
}
else
appendScriptFiles(document, scriptUrls, function(error)
{
if (!error)
{
// set a marker indicate that all modules are loaded
Kekule._loaded();
}
if (callback)
callback(error);
});
}
}
var kekuleFiles = {
'lan': {
'files': [
'lan/classes.js',
'lan/xmlJsons.js',
'lan/serializations.js'
],
'category': 'lan',
'minFile': 'root.min.js'
},
'root': {
'files': [
'core/kekule.root.js'
],
'category': 'root',
'minFile': 'root.min.js'
},
'localization': {
'requires': ['lan', 'root'],
'files': [
'localization/kekule.localizations.js'
/*
'localization/en/kekule.localize.general.en.js',
'localization/en/kekule.localize.widget.en.js',
'localization/en/kekule.localize.objDefines.en.js'
/*
'localization/zh/kekule.localize.general.zh.js',
'localization/zh/kekule.localize.widget.zh.js'
*/
],
'category': 'localization',
'minFile': 'localization.min.js'
},
// Localization resources, must be put right after 'localization' module, since other modules may use them
'localizationData': {
'requires': ['localization'],
'files': [
'localization/en/kekule.localize.general.en.js',
'localization/en/kekule.localize.widget.en.js',
'localization/en/kekule.localize.objDefines.en.js'
],
'category': 'localization',
'minFile': 'localization.min.js'
},
'localizationData.zh': {
'requires': ['localization'],
'files': [
'localization/zh/kekule.localize.general.zh.js',
'localization/zh/kekule.localize.widget.zh.js'
//'localization/zh/kekule.localize.objDefines.zh.js'
],
'category': 'localizationData.zh',
'autoCompress': false // do not compress js automatically
},
'common': {
'requires': ['lan', 'root', 'localization'],
'files': [
'core/kekule.common.js',
'core/kekule.exceptions.js',
'utils/kekule.utils.js',
'utils/kekule.domHelper.js',
'utils/kekule.domUtils.js',
'core/kekule.externalResMgr.js',
'core/kekule.metrics.js'
],
'category': 'common',
'minFile': 'common.min.js'
},
'core': {
'requires': ['lan', 'root', 'common', 'data'],
'files': [
'core/kekule.configs.js',
'core/kekule.elements.js',
'core/kekule.electrons.js',
'core/kekule.valences.js',
'core/kekule.structures.js',
'core/kekule.structureBuilder.js',
'core/kekule.reactions.js',
'core/kekule.chemUtils.js',
'chemdoc/kekule.glyph.base.js',
'chemdoc/kekule.glyph.utils.js',
'chemdoc/kekule.glyph.pathGlyphs.js',
'chemdoc/kekule.glyph.lines.js',
'chemdoc/kekule.glyph.chemGlyphs.js',
'chemdoc/kekule.contentBlocks.js',
'chemdoc/kekule.attachedMarkers.js',
'chemdoc/kekule.commonChemMarkers.js'
],
'category': 'core'
},
'html': {
'requires': ['lan', 'root', 'common'],
'files': [
'xbrowsers/kekule.x.js',
'html/kekule.nativeServices.js',
'html/kekule.predefinedResLoaders.js',
'utils/kekule.htmlDomUtils.js'
],
'category': 'core'
},
'io': {
'requires': ['lan', 'root', 'common', 'core', 'algorithm'],
'files': [
'utils/kekule.textHelper.js',
'io/kekule.io.js',
'io/cml/kekule.io.cml.js',
'io/mdl/kekule.io.mdlBase.js',
'io/mdl/kekule.io.mdl2000.js',
'io/mdl/kekule.io.mdl3000.js',
'io/mdl/kekule.io.mdlIO.js',
'io/smiles/kekule.io.smiles.js',
'io/native/kekule.io.native.js'
],
'category': 'io'
},
'render': {
'requires': ['lan', 'root', 'common', 'core', 'html'],
'files': [
'render/kekule.render.extensions.js',
'render/kekule.render.base.js',
'render/kekule.render.renderColorData.js',
'render/kekule.render.utils.js',
'render/kekule.render.configs.js',
'render/kekule.render.baseTextRender.js',
'render/kekule.render.boundInfoRecorder.js',
'render/2d/kekule.render.renderer2D.js',
'render/2d/kekule.render.glyphRender2D.js',
'render/2d/kekule.render.canvasRenderer.js',
'render/2d/kekule.render.raphaelRenderer.js',
'render/3d/kekule.render.renderer3D.js',
'render/3d/kekule.render.threeRenderer.js',
'render/kekule.render.painter.js'
],
'category': 'render'
},
'spectroscopy': {
'requires': ['root', 'common', 'io'],
'files': [
'spectroscopy/kekule.spectrum.core.js',
'io/jcamp/kekule.io.jcamp.base.js',
'io/jcamp/kekule.io.jcamp.labels.js',
'io/jcamp/kekule.io.jcamp.dx.js',
'io/jcamp/kekule.io.jcamp.cs.js',
'io/jcamp/kekule.io.jcampIO.js',
'io/cmlspect/kekule.io.cmlspect.js',
'spectroscopy/kekule.spectrum.render.js'
]
},
'widget': {
'requires': ['lan', 'root', 'common', 'html'],
'files': [
'lib/hammer.js/hammer.min.js',
'widgets/operation/kekule.operations.js',
'widgets/operation/kekule.actions.js',
'widgets/kekule.widget.root.js',
'widgets/kekule.widget.bindings.js',
'widgets/kekule.widget.events.js',
'widgets/kekule.widget.base.js',
'widgets/kekule.widget.sys.js',
'widgets/kekule.widget.keys.js',
'widgets/kekule.widget.clipboards.js',
'widgets/kekule.widget.helpers.js',
'widgets/kekule.widget.styleResources.js',
'widgets/kekule.widget.autoLaunchers.js',
'widgets/transitions/kekule.widget.transitions.js',
'widgets/transitions/kekule.widget.transMgr.js',
'widgets/commonCtrls/kekule.widget.resizers.js',
'widgets/commonCtrls/kekule.widget.movers.js',
'widgets/commonCtrls/kekule.widget.images.js',
'widgets/commonCtrls/kekule.widget.containers.js',
'widgets/commonCtrls/kekule.widget.menus.js',
'widgets/commonCtrls/kekule.widget.buttons.js',
'widgets/commonCtrls/kekule.widget.formControls.js',
'widgets/commonCtrls/kekule.widget.nestedContainers.js',
'widgets/commonCtrls/kekule.widget.treeViews.js',
'widgets/commonCtrls/kekule.widget.listViews.js',
'widgets/commonCtrls/kekule.widget.dialogs.js',
'widgets/commonCtrls/kekule.widget.msgPanels.js',
'widgets/commonCtrls/kekule.widget.tabViews.js',
'widgets/advCtrls/kekule.widget.valueListEditors.js',
'widgets/advCtrls/kekule.widget.colorPickers.js',
'widgets/advCtrls/kekule.widget.textEditors.js',
'widgets/advCtrls/kekule.widget.widgetGrids.js',
'widgets/advCtrls/objInspector/kekule.widget.objInspectors.js',
'widgets/advCtrls/objInspector/kekule.widget.objInspector.propEditors.js',
'widgets/advCtrls/objInspector/kekule.widget.objInspector.operations.js',
'widgets/advCtrls/kekule.widget.configurators.js',
'widgets/advCtrls/grids/kekule.widget.dataSets.js',
'widgets/advCtrls/grids/kekule.widget.dataGrids.js',
'widgets/sys/kekule.widget.sysMsgs.js',
'widgets/operation/kekule.operHistoryTreeViews.js' // debug
],
'category': 'widget'
},
'chemWidget': {
'requires': ['lan', 'root', 'common', 'core', 'html', 'io', 'render', 'algorithm', 'widget'],
'files': [
'widgets/chem/kekule.chemWidget.base.js',
'widgets/chem/kekule.chemWidget.dialogs.js',
'widgets/chem/periodicTable/kekule.chemWidget.periodicTables.js',
'widgets/chem/kekule.chemWidget.chemObjDisplayers.js',
'widgets/chem/structureTreeView/kekule.chemWidget.structureTreeViews.js',
'widgets/chem/uiMarker/kekule.chemWidget.uiMarkers.js',
'widgets/chem/viewer/kekule.chemWidget.viewers.js',
'widgets/chem/viewer/kekule.chemWidget.spectrumViewers.js',
'widgets/chem/viewer/kekule.chemWidget.spectrumInspectors.js',
'widgets/chem/viewer/kekule.chemWidget.viewerGrids.js',
'widgets/chem/viewer/kekule.chemWidget.chemObjInserters.js',
'widgets/chem/editor/kekule.chemEditor.extensions.js',
'widgets/chem/editor/kekule.chemEditor.baseEditors.js',
'widgets/chem/editor/kekule.chemEditor.operations.js',
'widgets/chem/editor/kekule.chemEditor.editorUtils.js',
'widgets/chem/editor/kekule.chemEditor.configs.js',
'widgets/chem/editor/kekule.chemEditor.repositoryData.js',
'widgets/chem/editor/kekule.chemEditor.repositories.js',
'widgets/chem/editor/kekule.chemEditor.utilWidgets.js',
'widgets/chem/editor/kekule.chemEditor.chemSpaceEditors.js',
'widgets/chem/editor/kekule.chemEditor.nexus.js',
'widgets/chem/editor/kekule.chemEditor.actions.js',
'widgets/chem/editor/kekule.chemEditor.trackParser.js',
'widgets/chem/editor/kekule.chemEditor.objModifiers.js',
'widgets/chem/editor/modifiers/kekule.chemEditor.styleModifiers.js',
'widgets/chem/editor/modifiers/kekule.chemEditor.textModifiers.js',
'widgets/chem/editor/modifiers/kekule.chemEditor.structureModifiers.js',
'widgets/chem/editor/modifiers/kekule.chemEditor.glyphModifiers.js',
'chemdoc/issueCheckers/kekule.issueCheckers.js',
'widgets/chem/editor/issueInspectors/kekule.chemEditor.issueCheckers.js',
'widgets/chem/editor/issueInspectors/kekule.chemEditor.issueInspectors.js',
'widgets/advCtrls/objInspector/kekule.widget.objInspector.chemPropEditors.js',
'widgets/chem/editor/kekule.chemEditor.composers.js',
],
'category': 'chemWidget'
},
'webComponent': {
'requires': ['lan', 'root', 'common', 'core', 'html', 'io', 'render', 'algorithm', 'widget', 'chemWidget'],
'files': [
'webComponents/kekule.webComponent.base.js',
'webComponents/kekule.webComponent.widgetWrappers.js'
]
},
'algorithm': {
'requires': ['lan', 'root', 'common', 'core'],
'files': [
'algorithm/kekule.graph.js',
'algorithm/kekule.structures.helpers.js',
//'algorithm/kekule.structures.comparers.js',
'algorithm/kekule.structures.canonicalizers.js',
'algorithm/kekule.structures.ringSearches.js',
'algorithm/kekule.structures.aromatics.js',
'algorithm/kekule.structures.standardizers.js',
'algorithm/kekule.structures.searches.js',
'algorithm/kekule.structures.stereos.js'
],
'category': 'algorithm'
},
'calculation': {
'requires': ['lan', 'root', 'common', 'core', 'algorithm'],
'files': [
'calculation/kekule.calc.base.js'
]
},
'data': {
'requires': ['root'],
'files': [
'data/kekule.chemicalElementsData.js',
'data/kekule.isotopesData.organSet.js',
'data/kekule.structGenAtomTypesData.js',
'data/kekule.dataUtils.js'
]
},
'emscripten': {
'requires': ['root', 'common'],
'files': [
'_extras/kekule.emscriptenUtils.js'
],
'category': 'extra'
},
'openbabel': {
'requires': ['lan', 'root', 'core', 'emscripten', 'io'],
'files': [
'localization/en/kekule.localize.extras.openbabel.en.js',
'_extras/OpenBabel/kekule.openbabel.base.js',
'_extras/OpenBabel/kekule.openbabel.io.js',
'_extras/OpenBabel/kekule.openbabel.structures.js'
],
'category': 'extra'
},
'indigo': {
'requires': ['lan', 'root', 'core', 'emscripten', 'io'],
'files': [
'_extras/Indigo/kekule.indigo.base.js',
'_extras/Indigo/kekule.indigo.io.js',
'_extras/Indigo/kekule.indigo.structures.js'
],
'category': 'extra'
},
'inchi': {
'requires': ['lan', 'root', 'core', 'emscripten', 'io'],
'files': [
'_extras/InChI/kekule.inchi.js'
],
'category': 'extra'
}
};
var prequestModules = ['lan', 'root', 'localization', 'localizationData', 'common'];
var usualModules = prequestModules.concat(['core', 'html', 'io', 'spectroscopy', 'render', 'widget', 'chemWidget', 'algorithm', 'calculation', 'data']);
var allModules = usualModules.concat(['emscripten', 'inchi', 'openbabel', 'indigo']);
var nodeModules = prequestModules.concat(['core', 'io', 'spectroscopy', 'algorithm', 'calculation', 'data']);
var defaultLocals = [];
function getEssentialModules(modules)
{
var ms = modules || usualModules;
ms = prequestModules.concat(ms);
var result = [];
var pushModule = function(modules, moduleName)
{
if (modules.indexOf(moduleName) < 0)
{
var module = kekuleFiles[moduleName];
if (module && module.requires)
{
for (var j = 0, k = module.requires.length; j < k; ++j)
{
var rm = module.requires[j];
pushModule(modules, rm);
}
}
modules.push(moduleName);
}
};
for (var i = 0, l = ms.length; i < l; ++i)
{
var module = ms[i];
pushModule(result, module);
}
return result;
}
function getModuleJsFiles(moduleName, useMinFile, minFileSubPath)
{
var result = [];
var m = kekuleFiles[moduleName];
if (m && m.files)
{
if (useMinFile)
{
var minFileName = m.minFile || (moduleName + '.min.js');
if (minFileSubPath)
minFileName = minFileSubPath + minFileName;
if (result.indexOf(minFileName) < 0)
result.push(minFileName);
}
else
result = result.concat(m.files);
}
return result;
}
function getEssentialFiles(modules, useMinFile, minFileSubPath)
{
var ms = getEssentialModules(modules);
var result = [];
for (var i = 0, l = ms.length; i < l; ++i)
{
var moduleName = ms[i];
/*
var m = kekuleFiles[moduleName];
if (m && m.files)
{
if (useMinFile)
{
var minFileName = m.minFile || (moduleName + '.min.js');
if (minFileSubPath)
minFileName = minFileSubPath + minFileName;
if (result.indexOf(minFileName) < 0)
result.push(minFileName);
}
else
result = result.concat(m.files);
}
*/
result = result.concat(getModuleJsFiles(moduleName, useMinFile, minFileSubPath));
}
return result;
}
function analysisEntranceScriptSrc(doc)
{
var entranceSrc = /^(.*\/?)kekule(.min)?\.js(\?.*)?$/;
var scriptSrcPattern = /^(.*[\/\\])([^\/\\]*)\.js(\?.*)?$/;
var paramForceDomLoader = /^domloader\=(.+)$/;
var paramMinFile = /^min\=(.+)$/;
var paramModules = /^modules\=(.+)$/;
var paramLocalDatas = /^locals\=(.+)$/;
var paramLanguage = /^language\=(.+)$/;
var matchResult;
if (!loadedByImportOrRequire)
{
if (doc && doc.currentScript && doc.currentScript.src) // try get current script info by document.currentScript
{
var scriptSrc = decodeURIComponent(doc.currentScript.src); // sometimes the URL is escaped, ',' becomes '%2C'(e.g. in Moodle)
if (scriptSrc)
{
matchResult = scriptSrc.match(scriptSrcPattern);
}
}
else // use the traditional way, detect each <script> tags
{
var scriptElems = doc.getElementsByTagName('script');
for (var j = scriptElems.length - 1; j >= 0; --j)
{
var elem = scriptElems[j];
var scriptSrc = decodeURIComponent(elem.src); // sometimes the URL is escaped, ',' becomes '%2C'(e.g. in Moodle)
if (scriptSrc)
{
matchResult = scriptSrc.match(entranceSrc);
if (matchResult)
{
break;
}
}
}
}
}
if (matchResult)
{
var coreScriptName = matchResult[2]; // kekule.js or kekule.min.js
//var singleMinBundle = (coreScriptName.indexOf('.min') === coreScriptName.length - 4);
var pstr = matchResult[3]; // script params
if (pstr)
pstr = pstr.substr(1); // eliminate starting '?'
var result = {
'src': scriptSrc,
'path': matchResult[1],
//'singleMinBundle': singleMinBundle,
'paramStr': pstr,
'useMinFile': true,
};
if (result.paramStr) // analysis params
{
var modules;
var params = result.paramStr.split('&');
for (var i = 0, l = params.length; i < l; ++i)
{
// check min file usage
var minFileMatch = params[i].match(paramMinFile);
if (minFileMatch)
{
var pvalue = minFileMatch[1].toLowerCase();
var value = ['false', 'no', 'f', 'n'].indexOf(pvalue) < 0;
//var value = (pvalue === 'false') || (pvalue === 'f') || (pvalue === 'no') || (pvalue === 'n');
//var value = ['true', 'yes', 't', 'y'].indexOf(pvalue) >= 0;
result.useMinFile = value;
continue;
}
// check module param
var moduleMatch = params[i].match(paramModules);
if (moduleMatch)
{
var moduleStr = moduleMatch[1];
var modules = moduleStr.split(',');
continue;
}
// force dom loader
var forceDomLoaderMatch = params[i].match(paramForceDomLoader);
if (forceDomLoaderMatch)
{
var pvalue = forceDomLoaderMatch[1].toLowerCase();
var value = ['false', 'no', 'f', 'n'].indexOf(pvalue) < 0;
result.forceDomLoader = value;
continue;
}
// check required local data
var localsMatch = params[i].match(paramLocalDatas);
if (localsMatch)
{
var localsStr = localsMatch[1];
var locals = localsStr.split(',');
result.locals = locals;
continue;
}
// language
var forceLanguage = params[i].match(paramLanguage);
if (forceLanguage)
{
var pvalue = forceLanguage[1];
result.language = pvalue;
continue;
}
}
if (modules)
result.modules = modules;
else
result.modules = usualModules; // no modules appointed, use default setting
// handle local data
if (!result.locals)
result.locals = defaultLocals;
if (result.locals || result.language)
{
var localNames = [].concat(result.locals || []);
if (result.language && localNames.indexOf(result.language) < 0) // local resources of forced language should always be loaded
{
localNames.push(result.language);
}
if (localNames.length)
{
var localizationModuleIndex = result.modules.indexOf('localizationData');
if (localizationModuleIndex < 0) // local data module not listed, put local data as first module
localizationModuleIndex = -1;
for (var i = 0, l = localNames.length; i < l; ++i)
{
var localName = localNames[i];
if (localName === 'en') // default local resource, already be loaded, by pass
continue;
// insert resources, right after localization module, before other widget modules
result.modules.splice(localizationModuleIndex + 1, 0, 'localizationData.' + localName);
}
}
}
}
return result;
}
// no info found, returns the default settings
return {
'src': '',
'path': '',
'modules': usualModules,
//'useMinFile': false // for debug
'useMinFile': true
}; // return a default setting
}
function loadModuleScriptFiles(modules, useMinFile, rootPath, kekuleScriptInfo, callback) // return loaded files
{
if (typeof Kekule !== "undefined" && Kekule.LOADED)
Kekule.LOADED = false; // a flag, indicating now are loading script files
var loadedModules = kekuleScriptInfo.modules || [];
/*
var essentialModules = [];
for (var i = 0, l = modules.length; i < l; ++i)
{
if (loadedModules.indexOf(modules[i]) < 0)
essentialModules.push(modules[i]);
}
*/
var essentialModules = [];
var requiredModules = getEssentialModules(modules); // retrieve all required modules
for (var i = 0, l = requiredModules.length; i < l; ++i)
{
if (loadedModules.indexOf(requiredModules[i]) < 0)
essentialModules.push(requiredModules[i]);
}
if (!essentialModules.length) // no need to load additional modules
{
// do nothing here
callback();
}
else
{
//var files = getEssentialFiles(essentialModules, useMinFile, kekuleScriptInfo.dividedMinSubPath);
var files = [];
for (var i = 0, l = requiredModules.length; i < l; ++i)
{
files = files.concat(getModuleJsFiles(essentialModules[i], useMinFile, kekuleScriptInfo.dividedMinSubPath));
}
var essentialFiles = [];
var path = rootPath;
var loadedScriptUrls = kekuleScriptInfo.fileUrls || [];
var essentialUrls = [];
for (var i = 0, l = files.length; i < l; ++i)
{
var url = path + files[i];
if (loadedScriptUrls.indexOf(url) < 0)
{
essentialUrls.push(url);
essentialFiles.push(files[i]);
}
}
essentialUrls.push(path + 'kekule.loaded.js'); // manually add small file to indicate the end of Kekule loading
loadChildScriptFiles(essentialUrls, null, function (error)
{
kekuleScriptInfo.modules = kekuleScriptInfo.modules.concat(essentialModules);
kekuleScriptInfo.files = kekuleScriptInfo.files.concat(essentialFiles);
kekuleScriptInfo.fileUrls = kekuleScriptInfo.fileUrls.concat(essentialUrls);
if (callback)
callback(error);
});
}
return {
'modules': essentialModules,
'files': essentialFiles,
'fileUrls': essentialUrls
};
}
function init()
{
var scriptInfo, files, path;
var kekule_env_ops = (typeof(_kekule_environment_) === 'object')? _kekule_environment_:
(typeof($root._kekule_environment_) === 'object')? $root._kekule_environment_:
null;
if (kekule_env_ops) // if manually set the load info, use it directly
{
scriptInfo = kekule_env_ops.scriptInfo;
if (!scriptInfo && kekule_env_ops.scriptPath)
{
scriptInfo = {
'src': kekule_env_ops.scriptSrc,
'path': kekule_env_ops.scriptPath,
'dividedMinSubPath': kekule_env_ops.ScriptdividedMinSubPath,
'modules': kekule_env_ops.scriptModules,
'useMinFile': kekule_env_ops.scriptUseMinFile,
};
}
}
if (!scriptInfo) // auto determination
{
// sometimes there are both browser and node environment (e.g. Electron)
if (isInBrowser) // try get info from <script> tag first
{
scriptInfo = analysisEntranceScriptSrc(document);
var findScriptTag = scriptInfo.src && scriptInfo.path;
if (findScriptTag) // explicitly use script tag, load files in traditional way
{
isNode = false;
}
if (!findScriptTag && hasNodeEnv) // dual env
{
scriptInfo.src = this.__filename || '';
scriptInfo.path = (((typeof(__dirname) !== 'undefined')?__dirname: '') || '.') + '/';
isNode = true;
}
}
else if (isNode)
{
scriptInfo = {
'src': this.__filename || '',
'path': ((typeof(__dirname) !== 'undefined')?__dirname: '') + '/',
'modules': isInBrowser? usualModules: nodeModules, // if there is browser env (e.g. electron, load normal modules including widget)
//'useMinFile': false // for debug
'useMinFile': true,
'nodeModule': (typeof(module) !== 'undefined')? module: this.module, // record the node module, for using the module methods (e.g. require) later
'nodeRequire': (typeof(require) !== 'undefined')? require: this.require,
};
}
if (isNode)
{
// if min files not found, use dev files instead
var testFileName = scriptInfo.path + kekuleFiles.root.minFile;
var minFileExisted = false;
try
{
minFileExisted = fs.existsSync(testFileName);
}
catch(e)
{
//scriptInfo.path += 'src/'
minFileExisted = false;
}
if (!minFileExisted)
scriptInfo.useMinFile = false;
}
}
// if some fields of scriptInfo is still missed
if (!scriptInfo.dividedMinSubPath)
scriptInfo.dividedMinSubPath = 'mins/';
if (!scriptInfo.dividedModuleExporterSubPath)
scriptInfo.dividedModuleExporterSubPath = 'jsmods/';
if (!scriptInfo.modules)
scriptInfo.modules = isInBrowser? usualModules: nodeModules;
if (scriptInfo.useMinFile === undefined)
scriptInfo.useMinFile = true;
scriptInfo.singleMinBundle = $root && $root.__$kekule_single_min_bundle__; // a special flag bundled into kekule.min.js
scriptInfo.explicitModules = scriptInfo.modules;
var modules = getEssentialModules(scriptInfo.modules);
//scriptInfo.modules = modules;
scriptInfo.modules = [];
scriptInfo.files = [];
scriptInfo.fileUrls = [];
// save loaded module and file information
scriptInfo.allModuleStructures = kekuleFiles;
$root['__$kekule_load_info__'] = scriptInfo;
$root['__$kekule_scriptfile_utils__'] = {
'appendScriptFile': appendScriptFile,
'appendScriptFiles': appendScriptFiles,
'loadModuleScriptFiles': loadModuleScriptFiles,
'getModuleJsFiles': getModuleJsFiles,
'getEssentialFiles': getEssentialFiles,
'getEssentialModules': getEssentialModules
};
scriptInfo.manualLoadScriptFiles = kekule_env_ops && kekule_env_ops.manualLoadScriptFiles;
// when loading with a single bundle, or with a manual load flag (e.g., in ES6 module), no need to load modules
if ((!scriptInfo.singleMinBundle || typeof(scriptInfo.singleMinBundle) === 'undefined') && (!kekule_env_ops || !kekule_env_ops.manualLoadScriptFiles))
{
loadModuleScriptFiles(modules, scriptInfo.useMinFile, scriptInfo.path || '', scriptInfo, function(error){
if (/*isNode*/typeof(exports) !== 'undefined') // export Kekule namespace
{
// export Kekule in module
exports.Kekule = this.Kekule || __nodeContext.Kekule;
exports.Class = this.Class || __nodeContext.Class;
exports.ClassEx = this.ClassEx || __nodeContext.ClassEx;
exports.ObjectEx = this.ObjectEx || __nodeContext.ObjectEx;
exports.DataType = this.DataType || __nodeContext.DataType;
// and these common vars in global
this.Class = exports.Class;
this.ClassEx = exports.ClassEx;
this.ObjectEx = exports.ObjectEx;
this.DataType = exports.DataType;
// then store script info of Kekule
if (this && this.Kekule)
this.Kekule.scriptSrcInfo = scriptInfo;
}
});
}
/*
files = getEssentialFiles(scriptInfo.modules, scriptInfo.useMinFile);
path = scriptInfo.path;
var scriptUrls = [];
for (var i = 0, l = files.length; i < l; ++i)
{
scriptUrls.push(path + files[i]);
}
scriptUrls.push(path + 'kekule.loaded.js'); // manually add small file to indicate the end of Kekule loading
// save loaded module and file information
scriptInfo.files = files;
scriptInfo.fileUrls = scriptUrls; // already loaded file urls
scriptInfo.allModuleStructures = kekuleFiles;
$root['__$kekule_load_info__'] = scriptInfo;
$root['__$kekule_scriptfile_utils__'] = {
'appendScriptFile': appendScriptFile,
'appendScriptFiles': appendScriptFiles
};
loadChildScriptFiles(scriptUrls, scriptInfo.forceDomLoader, function(){
if (isNode) // export Kekule namespace
{
// export Kekule in module
exports.Kekule = this.Kekule || __nodeContext.Kekule;
exports.Class = this.Class || __nodeContext.Class;
exports.ClassEx = this.ClassEx || __nodeContext.ClassEx;
exports.ObjectEx = this.ObjectEx || __nodeContext.ObjectEx;
exports.DataType = this.DataType || __nodeContext.DataType;
// and these common vars in global
this.Class = exports.Class;
this.ClassEx = exports.ClassEx;
this.ObjectEx = exports.ObjectEx;
this.DataType = exports.DataType;
// then store script info of Kekule
this.Kekule.scriptSrcInfo = scriptInfo;
}
});
*/
}
if (isWebpack)
{
// now the import clause are all moved out to kekule.esm.js or kekule.cm.js, no need to exports here
//module.exports = require('./kekule.webpack.prod.js');
}
else
init();
})(this);