UNPKG

kekule

Version:

Open source JavaScript toolkit for chemoinformatics

1,081 lines (1,007 loc) 33.2 kB
(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);