/** * esl (enterprise standard loader) * copyright 2013 baidu inc. all rights reserved. * * @file browser端标准加载器,符合amd规范 * @author errorrik(errorrik@gmail.com) * firede(firede@firede.us) */ /* jshint ignore:start */ var define; var require; var esl; /* jshint ignore:end */ /* eslint-disable guard-for-in */ /* eslint-env amd:false */ (function (global) { // "mod"开头的变量或函数为内部模块管理函数 // 为提高压缩率,不使用function或object包装 /** * 模块容器 * * @inner * @type {object} */ var modmodules = {}; // 模块状态枚举量 var module_pre_defined = 1; var module_analyzed = 2; var module_prepared = 3; var module_defined = 4; /** * 自动定义的模块表 * * 模块define factory是用到时才执行,但是以下几种情况需要自动马上执行: * 1. require([moduleid], callback) * 2. plugin module and plugin resource: require('plugin!resource') * 3. shim module * * @inner * @type {object} */ var modautodefinemodules = {}; /** * 标记模块自动进行定义 * * @inner * @param {string} id 模块id */ function modflagautodefine(id) { if (!modis(id, module_defined)) { modautodefinemodules[id] = 1; } } /** * 内建module名称集合 * * @inner * @type {object} */ var buildin_module = { require: globalrequire, exports: 1, module: 1 }; /** * 全局require函数 * * @inner * @type {function} */ var actualglobalrequire = createlocalrequire(); // #begin-ignore /** * 超时提醒定时器 * * @inner * @type {number} */ var waittimeout; // #end-ignore /* eslint-disable fecs-key-spacing */ /* eslint-disable key-spacing */ /** * require配置 * * @inner * @type {object} */ var requireconf = { baseurl : './', paths : {}, config : {}, map : {}, packages : [], shim : {}, // #begin-ignore waitseconds: 0, // #end-ignore bundles : {}, urlargs : {} }; /* eslint-enable key-spacing */ /** * 加载模块 * * @param {string|array} requireid 模块id或模块id数组, * @param {function=} callback 加载完成的回调函数 * @return {*} requireid为string时返回模块暴露对象 */ function globalrequire(requireid, callback) { // #begin-ignore // #begin assertnotcontainrelativeid // 确定require的模块id不包含相对id。用于global require,提前预防难以跟踪的错误出现 var invalidids = []; /** * 监测模块id是否relative id * * @inner * @param {string} id 模块id */ function monitor(id) { if (id.indexof('.') === 0) { invalidids.push(id); } } if (typeof requireid === 'string') { monitor(requireid); } else { each( requireid, function (id) { monitor(id); } ); } // 包含相对id时,直接抛出错误 if (invalidids.length > 0) { throw new error( '[require_fatal]relative id is not allowed in global require: ' + invalidids.join(', ') ); } // #end assertnotcontainrelativeid // 超时提醒 var timeout = requireconf.waitseconds; if (timeout && (requireid instanceof array)) { if (waittimeout) { cleartimeout(waittimeout); } waittimeout = settimeout(waittimeoutnotice, timeout * 1000); } // #end-ignore return actualglobalrequire(requireid, callback); } /** * 版本号 * * @type {string} */ globalrequire.version = '2.0.2'; /** * loader名称 * * @type {string} */ globalrequire.loader = 'esl'; /** * 将模块标识转换成相对的url * * @param {string} id 模块标识 * @return {string} */ globalrequire.tourl = actualglobalrequire.tourl; // #begin-ignore /** * 超时提醒函数 * * @inner */ function waittimeoutnotice() { var hangmodules = []; var missmodules = []; var hangmodulesmap = {}; var missmodulesmap = {}; var visited = {}; /** * 检查模块的加载错误 * * @inner * @param {string} id 模块id * @param {boolean} hard 是否装载时依赖 */ function checkerror(id, hard) { if (visited[id] || modis(id, module_defined)) { return; } visited[id] = 1; if (!modis(id, module_prepared)) { // hack: 为gzip后体积优化,不做抽取 if (!hangmodulesmap[id]) { hangmodulesmap[id] = 1; hangmodules.push(id); } } var mod = modmodules[id]; if (!mod) { if (!missmodulesmap[id]) { missmodulesmap[id] = 1; missmodules.push(id); } } else if (hard) { if (!hangmodulesmap[id]) { hangmodulesmap[id] = 1; hangmodules.push(id); } each( mod.depms, function (dep) { checkerror(dep.absid, dep.hard); } ); } } for (var id in modautodefinemodules) { checkerror(id, 1); } if (hangmodules.length || missmodules.length) { throw new error( '[module_timeout]hang( ' + (hangmodules.join(', ') || 'none') + ' ) miss( ' + (missmodules.join(', ') || 'none') + ' )' ); } } // #end-ignore /** * 未预定义的模块集合 * 主要存储匿名方式define的模块 * * @inner * @type {array} */ var wait4predefine = []; /** * 完成模块预定义,此时处理的模块是匿名define的模块 * * @inner * @param {string} currentid 匿名define的模块的id */ function modcompletepredefine(currentid) { // hack: 这里在ie下有个性能陷阱,不能使用任何变量。 // 否则貌似会形成变量引用和修改的读写锁,导致wait4predefine释放困难 each(wait4predefine, function (mod) { modpredefine( currentid, mod.deps, mod.factory ); }); wait4predefine.length = 0; } /** * 定义模块 * * @param {string=} id 模块标识 * @param {array=} dependencies 依赖模块列表 * @param {function=} factory 创建模块的工厂方法 */ function globaldefine(id, dependencies, factory) { // define(factory) // define(dependencies, factory) // define(id, factory) // define(id, dependencies, factory) if (factory == null) { if (dependencies == null) { factory = id; id = null; } else { factory = dependencies; dependencies = null; if (id instanceof array) { dependencies = id; id = null; } } } if (factory == null) { return; } var opera = window.opera; // ie下通过current script的data-require-id获取当前id if ( !id && document.attachevent && (!(opera && opera.tostring() === '[object opera]')) ) { var currentscript = getcurrentscript(); id = currentscript && currentscript.getattribute('data-require-id'); } if (id) { modpredefine(id, dependencies, factory); } else { // 纪录到共享变量中,在load或readystatechange中处理 // 标准浏览器下,使用匿名define时,将进入这个分支 wait4predefine[0] = { deps: dependencies, factory: factory }; } } globaldefine.amd = {}; /** * 模块配置获取函数 * * @inner * @return {object} 模块配置对象 */ function moduleconfiggetter() { var conf = requireconf.config[this.id]; if (conf && typeof conf === 'object') { return conf; } return {}; } /** * 预定义模块 * * @inner * @param {string} id 模块标识 * @param {array.} dependencies 显式声明的依赖模块列表 * @param {*} factory 模块定义函数或模块对象 */ function modpredefine(id, dependencies, factory) { // 将模块存入容器 // // 模块内部信息包括 // ----------------------------------- // id: module id // depsdec: 模块定义时声明的依赖 // deps: 模块依赖,默认为['require', 'exports', 'module'] // factory: 初始化函数或对象 // factorydeps: 初始化函数的参数依赖 // exports: 模块的实际暴露对象(amd定义) // config: 用于获取模块配置信息的函数(amd定义) // state: 模块当前状态 // require: local require函数 // depms: 实际依赖的模块集合,数组形式 // depmkv: 实际依赖的模块集合,表形式,便于查找 // deprs: 实际依赖的资源集合 // ------------------------------------ if (!modmodules[id]) { /* eslint-disable key-spacing */ modmodules[id] = { id : id, depsdec : dependencies, deps : dependencies || ['require', 'exports', 'module'], factorydeps : [], factory : factory, exports : {}, config : moduleconfiggetter, state : module_pre_defined, require : createlocalrequire(id), depms : [], depmkv : {}, deprs : [] }; /* eslint-enable key-spacing */ } } /** * 开始执行模块定义前的准备工作 * * 首先,完成对factory中声明依赖的分析提取 * 然后,尝试加载"资源加载所需模块" * * 需要先加载模块的原因是:如果模块不存在,无法进行resourceid normalize化 * * @inner * @param {string} id 模块id */ function modprepare(id) { var mod = modmodules[id]; if (!mod || modis(id, module_analyzed)) { return; } var deps = mod.deps; var factory = mod.factory; var harddependscount = 0; // 分析function body中的require // 如果包含显式依赖声明,根据amd规定和性能考虑,可以不分析factorybody if (typeof factory === 'function') { harddependscount = math.min(factory.length, deps.length); // if the dependencies argument is present, the module loader // should not scan for dependencies within the factory function. !mod.depsdec && factory.tostring() .replace(/(\/\*([\s\s]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, '') .replace(/require\(\s*(['"'])([^'"]+)\1\s*\)/g, function ($0, $1, depid) { deps.push(depid); } ); } var requiremodules = []; var depresources = []; each(deps, function (depid, index) { var idinfo = parseid(depid); var absid = normalize(idinfo.mod, id); var moduleinfo; var resinfo; if (absid && !buildin_module[absid]) { // 如果依赖是一个资源,将其信息添加到module.deprs // // module.deprs中的项有可能是重复的。 // 在这个阶段,加载resource的module可能还未defined, // 导致此时resource id无法被normalize。 // // 比如对a/b/c而言,下面几个resource可能指的是同一个资源: // - js!../name.js // - js!a/name.js // - ../../js!../name.js // // 所以加载资源的module ready时,需要遍历module.deprs进行处理 if (idinfo.res) { resinfo = { id: depid, mod: absid, res: idinfo.res }; depresources.push(depid); mod.deprs.push(resinfo); } // 对依赖模块的id normalize能保证正确性,在此处进行去重 moduleinfo = mod.depmkv[absid]; if (!moduleinfo) { moduleinfo = { id: idinfo.mod, absid: absid, hard: index < harddependscount }; mod.depms.push(moduleinfo); mod.depmkv[absid] = moduleinfo; requiremodules.push(absid); } } else { moduleinfo = {absid: absid}; } // 如果当前正在分析的依赖项是define中声明的, // 则记录到module.factorydeps中 // 在factory invoke前将用于生成invoke arguments if (index < harddependscount) { mod.factorydeps.push(resinfo || moduleinfo); } }); mod.state = module_analyzed; modinitfactoryinvoker(id); nativeasyncrequire(requiremodules); depresources.length && mod.require( depresources, function () { each(mod.deprs, function (res) { if (!res.absid) { res.absid = normalize(res.id, id); } }); modautodefine(); } ); } /** * 对一些需要自动定义的模块进行自动定义 * * @inner */ function modautodefine() { for (var id in modautodefinemodules) { modprepare(id); modupdatepreparedstate(id); modtryinvokefactory(id); } } /** * 更新模块的准备状态 * * @inner * @param {string} id 模块id */ function modupdatepreparedstate(id) { var visited = {}; update(id); function update(id) { modprepare(id); if (!modis(id, module_analyzed)) { return false; } if (modis(id, module_prepared) || visited[id]) { return true; } visited[id] = 1; var mod = modmodules[id]; var prepared = true; each( mod.depms, function (dep) { return (prepared = update(dep.absid)); } ); // 判断resource是否加载完成。如果resource未加载完成,则认为未准备好 /* jshint ignore:start */ prepared && each( mod.deprs, function (dep) { prepared = !!dep.absid; return prepared; } ); /* jshint ignore:end */ if (prepared) { mod.state = module_prepared; } return prepared; } } /** * 初始化模块定义时所需的factory执行器 * * @inner * @param {string} id 模块id */ function modinitfactoryinvoker(id) { var mod = modmodules[id]; var invoking; mod.invokefactory = invokefactory; /** * 初始化模块 * * @inner */ function invokefactory() { if (invoking || mod.state !== module_prepared) { return; } invoking = 1; // 拼接factory invoke所需的arguments var factoryready = 1; each( mod.factorydeps, function (dep) { var depid = dep.absid; if (!buildin_module[depid]) { modtryinvokefactory(depid); return (factoryready = modis(depid, module_defined)); } } ); if (factoryready) { try { // 调用factory函数初始化module var factory = mod.factory; var exports = typeof factory === 'function' ? factory.apply(global, modgetmodulesexports( mod.factorydeps, { require: mod.require, exports: mod.exports, module: mod } )) : factory; if (exports != null) { mod.exports = exports; } mod.invokefactory = null; } catch (ex) { if (/^\[module_miss\]"([^"]+)/.test(ex.message)) { // 出错,则说明在factory的运行中,该require的模块是需要的 // 所以把它加入强依赖中 var hardcirclurdep = mod.depmkv[regexp.$1]; hardcirclurdep && (hardcirclurdep.hard = 1); // 如果是模块本身有问题导致的运行错误 // 就不要把invoking置回去了,避免影响autoinvoke其他模块的初始化 invoking = 0; return; } throw ex; } // 完成define // 不放在try里,避免后续的运行错误被这里吞掉 moddefined(id); } } } /** * 判断模块是否完成相应的状态 * * @inner * @param {string} id 模块标识 * @param {number} state 状态码,使用时传入相应的枚举变量,比如`module_defined` * @return {boolean} 是否完成相应的状态 */ function modis(id, state) { return modmodules[id] && modmodules[id].state >= state; } /** * 尝试执行模块factory函数,进行模块初始化 * * @inner * @param {string} id 模块id */ function modtryinvokefactory(id) { var mod = modmodules[id]; if (mod && mod.invokefactory) { mod.invokefactory(); } } /** * 根据模块id数组,获取其的exports数组 * 用于模块初始化的factory参数或require的callback参数生成 * * @inner * @param {array} modules 模块id数组 * @param {object} buildinmodules 内建模块对象 * @return {array} 模块exports数组 */ function modgetmodulesexports(modules, buildinmodules) { var args = []; each( modules, function (id, index) { if (typeof id === 'object') { id = id.absid; } args[index] = buildinmodules[id] || modmodules[id].exports; } ); return args; } /** * 模块定义完成事件监听器容器 * * @inner * @type {object} */ var moddefinedlisteners = {}; /** * 添加模块定义完成时间的监听器 * * @inner * @param {string} id 模块标识 * @param {function} listener 监听函数 */ function modadddefinedlistener(id, listener) { if (modis(id, module_defined)) { listener(); return; } var listeners = moddefinedlisteners[id]; if (!listeners) { listeners = moddefinedlisteners[id] = []; } listeners.push(listener); } /** * 模块状态切换为定义完成 * 因为需要触发事件,module_defined状态切换通过该函数 * * @inner * @param {string} id 模块标识 */ function moddefined(id) { var mod = modmodules[id]; mod.state = module_defined; delete modautodefinemodules[id]; var listeners = moddefinedlisteners[id] || []; var len = listeners.length; while (len--) { // 这里不做function类型的检测 // 因为listener都是通过modon传入的,modon为内部调用 listeners[len](); } // 清理listeners listeners.length = 0; moddefinedlisteners[id] = null; } /** * 异步加载模块 * 内部使用,模块id必须是经过normalize的top-level id * * @inner * @param {array} ids 模块名称或模块名称列表 * @param {function=} callback 获取模块完成时的回调函数 * @param {string} baseid 基础id,用于当ids是relative id时的normalize */ function nativeasyncrequire(ids, callback, baseid) { var iscallbackcalled = 0; each(ids, function (id) { if (!(buildin_module[id] || modis(id, module_defined))) { modadddefinedlistener(id, tryfinishrequire); (id.indexof('!') > 0 ? loadresource : loadmodule )(id, baseid); } }); tryfinishrequire(); /** * 尝试完成require,调用callback * 在模块与其依赖模块都加载完时调用 * * @inner */ function tryfinishrequire() { if (typeof callback === 'function' && !iscallbackcalled) { var isallcompleted = 1; each(ids, function (id) { if (!buildin_module[id]) { return (isallcompleted = !!modis(id, module_defined)); } }); // 检测并调用callback if (isallcompleted) { iscallbackcalled = 1; callback.apply( global, modgetmodulesexports(ids, buildin_module) ); } } } } /** * 正在加载的模块列表 * * @inner * @type {object} */ var loadingmodules = {}; /** * 加载模块 * * @inner * @param {string} moduleid 模块标识 */ function loadmodule(moduleid) { // 加载过的模块,就不要再继续了 if (loadingmodules[moduleid] || modmodules[moduleid]) { return; } loadingmodules[moduleid] = 1; // 初始化相关 shim 的配置 var shimconf = requireconf.shim[moduleid]; if (shimconf instanceof array) { requireconf.shim[moduleid] = shimconf = { deps: shimconf }; } // shim依赖的模块需要自动标识为shim // 无论是纯正的shim模块还是hybird模块 var shimdeps = shimconf && (shimconf.deps || []); if (shimdeps) { each(shimdeps, function (dep) { if (!requireconf.shim[dep]) { requireconf.shim[dep] = {}; } }); actualglobalrequire(shimdeps, load); } else { load(); } /** * 发送请求去加载模块 * * @inner */ function load() { /* eslint-disable no-use-before-define */ var bundlemoduleid = bundlesindex[moduleid]; createscript(bundlemoduleid || moduleid, loaded); /* eslint-enable no-use-before-define */ } /** * script标签加载完成的事件处理函数 * * @inner */ function loaded() { if (shimconf) { var exports; if (typeof shimconf.init === 'function') { exports = shimconf.init.apply( global, modgetmodulesexports(shimdeps, buildin_module) ); } if (exports == null && shimconf.exports) { exports = global; each( shimconf.exports.split('.'), function (prop) { exports = exports[prop]; return !!exports; } ); } globaldefine(moduleid, shimdeps, exports || {}); } else { modcompletepredefine(moduleid); } modautodefine(); } } /** * 加载资源 * * @inner * @param {string} pluginandresource 插件与资源标识 * @param {string} baseid 当前环境的模块标识 */ function loadresource(pluginandresource, baseid) { if (modmodules[pluginandresource]) { return; } /* eslint-disable no-use-before-define */ var bundlemoduleid = bundlesindex[pluginandresource]; if (bundlemoduleid) { loadmodule(bundlemoduleid); return; } /* eslint-enable no-use-before-define */ var idinfo = parseid(pluginandresource); var resource = { id: pluginandresource, state: module_analyzed }; modmodules[pluginandresource] = resource; /** * plugin加载完成的回调函数 * * @inner * @param {*} value resource的值 */ function pluginonload(value) { resource.exports = value || true; moddefined(pluginandresource); } /* jshint ignore:start */ /** * 该方法允许plugin使用加载的资源声明模块 * * @param {string} id 模块id * @param {string} text 模块声明字符串 */ pluginonload.fromtext = function (id, text) { new function(text)(); modcompletepredefine(id); }; /* jshint ignore:end */ /** * 加载资源 * * @inner * @param {object} plugin 用于加载资源的插件模块 */ function load(plugin) { var pluginrequire = baseid ? modmodules[baseid].require : actualglobalrequire; plugin.load( idinfo.res, pluginrequire, pluginonload, moduleconfiggetter.call({id: pluginandresource}) ); } load(actualglobalrequire(idinfo.mod)); } /** * 配置require * * @param {object} conf 配置对象 */ globalrequire.config = function (conf) { if (conf) { for (var key in requireconf) { var newvalue = conf[key]; var oldvalue = requireconf[key]; if (!newvalue) { continue; } if (key === 'urlargs' && typeof newvalue === 'string') { requireconf.urlargs['*'] = newvalue; } else { // 简单的多处配置还是需要支持,所以配置实现为支持二级mix if (oldvalue instanceof array) { oldvalue.push.apply(oldvalue, newvalue); } else if (typeof oldvalue === 'object') { for (var k in newvalue) { oldvalue[k] = newvalue[k]; } } else { requireconf[key] = newvalue; } } } createconfindex(); } }; // 初始化时需要创建配置索引 createconfindex(); /** * paths内部索引 * * @inner * @type {array} */ var pathsindex; /** * packages内部索引 * * @inner * @type {array} */ var packagesindex; /** * mapping内部索引 * * @inner * @type {array} */ var mappingidindex; /** * bundles内部索引 * * @inner * @type {object} */ var bundlesindex; /** * urlargs内部索引 * * @inner * @type {array} */ var urlargsindex; /** * 将key为module id prefix的object,生成数组形式的索引,并按照长度和字面排序 * * @inner * @param {object} value 源值 * @param {boolean} allowasterisk 是否允许*号表示匹配所有 * @return {array} 索引对象 */ function createkvsortedindex(value, allowasterisk) { var index = kv2list(value, 1, allowasterisk); index.sort(descsorterbykorname); return index; } /** * 创建配置信息内部索引 * * @inner */ function createconfindex() { requireconf.baseurl = requireconf.baseurl.replace(/\/$/, '') + '/'; // create paths index pathsindex = createkvsortedindex(requireconf.paths); // create mappingid index mappingidindex = createkvsortedindex(requireconf.map, 1); each( mappingidindex, function (item) { item.v = createkvsortedindex(item.v); } ); // create packages index packagesindex = []; each( requireconf.packages, function (packageconf) { var pkg = packageconf; if (typeof packageconf === 'string') { pkg = { name: packageconf.split('/')[0], location: packageconf, main: 'main' }; } pkg.location = pkg.location || pkg.name; pkg.main = (pkg.main || 'main').replace(/\.js$/i, ''); pkg.reg = createprefixregexp(pkg.name); packagesindex.push(pkg); } ); packagesindex.sort(descsorterbykorname); // create urlargs index urlargsindex = createkvsortedindex(requireconf.urlargs, 1); // create bundles index bundlesindex = {}; /* eslint-disable no-use-before-define */ function bundlesiterator(id) { bundlesindex[id] = key; } /* eslint-enable no-use-before-define */ for (var key in requireconf.bundles) { each(requireconf.bundles[key], bundlesiterator); } } /** * 对配置信息的索引进行检索 * * @inner * @param {string} value 要检索的值 * @param {array} index 索引对象 * @param {function} hitbehavior 索引命中的行为函数 */ function indexretrieve(value, index, hitbehavior) { each(index, function (item) { if (item.reg.test(value)) { hitbehavior(item.v, item.k, item); return false; } }); } /** * 将`模块标识+'.extension'`形式的字符串转换成相对的url * * @inner * @param {string} source 源字符串 * @return {string} url */ function tourl(source) { // 分离 模块标识 和 .extension var extreg = /(\.[a-z0-9]+)$/i; var queryreg = /(\?[^#]*)$/; var extname = ''; var id = source; var query = ''; if (queryreg.test(source)) { query = regexp.$1; source = source.replace(queryreg, ''); } if (extreg.test(source)) { extname = regexp.$1; id = source.replace(extreg, ''); } var url = id; // paths处理和匹配 var ispathmap; indexretrieve(id, pathsindex, function (value, key) { url = url.replace(key, value); ispathmap = 1; }); // packages处理和匹配 if (!ispathmap) { indexretrieve(id, packagesindex, function (value, key, item) { url = url.replace(item.name, item.location); }); } // 相对路径时,附加baseurl if (!/^([a-z]{2,10}:\/)?\//i.test(url)) { url = requireconf.baseurl + url; } // 附加 .extension 和 query url += extname + query; // urlargs处理和匹配 indexretrieve(id, urlargsindex, function (value) { url += (url.indexof('?') > 0 ? '&' : '?') + value; }); return url; } /** * 创建local require函数 * * @inner * @param {number} baseid 当前module id * @return {function} local require函数 */ function createlocalrequire(baseid) { var requiredcache = {}; function req(requireid, callback) { if (typeof requireid === 'string') { if (!requiredcache[requireid]) { var toplevelid = normalize(requireid, baseid); // 根据 https://github.com/amdjs/amdjs-api/wiki/require // it must throw an error if the module has not // already been loaded and evaluated. modtryinvokefactory(toplevelid); if (!modis(toplevelid, module_defined)) { throw new error('[module_miss]"' + toplevelid + '" is not exists!'); } requiredcache[requireid] = modmodules[toplevelid].exports; } return requiredcache[requireid]; } else if (requireid instanceof array) { // 分析是否有resource,取出pluginmodule先 var puremodules = []; var normalizedids = []; each( requireid, function (id, i) { var idinfo = parseid(id); var absid = normalize(idinfo.mod, baseid); var resid = idinfo.res; var normalizedid = absid; if (resid) { var trueresid = absid + '!' + resid; if (resid.indexof('.') !== 0 && bundlesindex[trueresid]) { absid = normalizedid = trueresid; } else { normalizedid = null; } } normalizedids[i] = normalizedid; modflagautodefine(absid); puremodules.push(absid); } ); // 加载模块 nativeasyncrequire( puremodules, function () { /* jshint ignore:start */ each(normalizedids, function (id, i) { if (id == null) { id = normalizedids[i] = normalize(requireid[i], baseid); modflagautodefine(id); } }); /* jshint ignore:end */ // modautodefine中,factory invoke可能发生错误 // 从而导致nativeasyncrequire没有被调用,callback没挂上 // 所以nativeasyncrequire要先运行 nativeasyncrequire(normalizedids, callback, baseid); modautodefine(); }, baseid ); modautodefine(); } } /** * 将[module id] + '.extension'格式的字符串转换成url * * @inner * @param {string} id 符合描述格式的源字符串 * @return {string} url */ req.tourl = function (id) { return tourl(normalize(id, baseid)); }; return req; } /** * id normalize化 * * @inner * @param {string} id 需要normalize的模块标识 * @param {string} baseid 当前环境的模块标识 * @return {string} normalize结果 */ function normalize(id, baseid) { if (!id) { return ''; } baseid = baseid || ''; var idinfo = parseid(id); if (!idinfo) { return id; } var resourceid = idinfo.res; var moduleid = relative2absolute(idinfo.mod, baseid); each( packagesindex, function (packageconf) { var name = packageconf.name; if (name === moduleid) { moduleid = name + '/' + packageconf.main; return false; } } ); // 根据config中的map配置进行module id mapping indexretrieve( baseid, mappingidindex, function (value) { indexretrieve( moduleid, value, function (mdvalue, mdkey) { moduleid = moduleid.replace(mdkey, mdvalue); } ); } ); if (resourceid) { var mod = modis(moduleid, module_defined) && actualglobalrequire(moduleid); resourceid = mod && mod.normalize ? mod.normalize( resourceid, function (resid) { return normalize(resid, baseid); } ) : normalize(resourceid, baseid); moduleid += '!' + resourceid; } return moduleid; } /** * 相对id转换成绝对id * * @inner * @param {string} id 要转换的相对id * @param {string} baseid 当前所在环境id * @return {string} 绝对id */ function relative2absolute(id, baseid) { if (id.indexof('.') === 0) { var basepath = baseid.split('/'); var namepath = id.split('/'); var baselen = basepath.length - 1; var namelen = namepath.length; var cutbaseterms = 0; var cutnameterms = 0; /* eslint-disable block-scoped-var */ pathloop: for (var i = 0; i < namelen; i++) { switch (namepath[i]) { case '..': if (cutbaseterms < baselen) { cutbaseterms++; cutnameterms++; } else { break pathloop; } break; case '.': cutnameterms++; break; default: break pathloop; } } /* eslint-enable block-scoped-var */ basepath.length = baselen - cutbaseterms; namepath = namepath.slice(cutnameterms); return basepath.concat(namepath).join('/'); } return id; } /** * 解析id,返回带有module和resource属性的object * * @inner * @param {string} id 标识 * @return {object} id解析结果对象 */ function parseid(id) { var segs = id.split('!'); if (segs[0]) { return { mod: segs[0], res: segs[1] }; } } /** * 将对象数据转换成数组,数组每项是带有k和v的object * * @inner * @param {object} source 对象数据 * @param {boolean} keymatchable key是否允许被前缀匹配 * @param {boolean} allowasterisk 是否支持*匹配所有 * @return {array.} 对象转换数组 */ function kv2list(source, keymatchable, allowasterisk) { var list = []; for (var key in source) { if (source.hasownproperty(key)) { var item = { k: key, v: source[key] }; list.push(item); if (keymatchable) { item.reg = key === '*' && allowasterisk ? /^/ : createprefixregexp(key); } } } return list; } // 感谢requirejs,通过currentlyaddingscript兼容老旧ie // // for some cache cases in ie 6-8, the script executes before the end // of the appendchild execution, so to tie an anonymous define // call to the module name (which is stored on the node), hold on // to a reference to this node, but clear after the dom insertion. var currentlyaddingscript; var interactivescript; /** * 获取当前script标签 * 用于ie下define未指定module id时获取id * * @inner * @return {htmlscriptelement} 当前script标签 */ function getcurrentscript() { if (currentlyaddingscript) { return currentlyaddingscript; } else if ( interactivescript && interactivescript.readystate === 'interactive' ) { return interactivescript; } var scripts = document.getelementsbytagname('script'); var scriptlen = scripts.length; while (scriptlen--) { var script = scripts[scriptlen]; if (script.readystate === 'interactive') { interactivescript = script; return script; } } } var headelement = document.getelementsbytagname('head')[0]; var baseelement = document.getelementsbytagname('base')[0]; if (baseelement) { headelement = baseelement.parentnode; } function createscript(moduleid, onload) { // 创建script标签 // // 这里不挂接onerror的错误处理 // 因为高级浏览器在devtool的console面板会报错 // 再throw一个error多此一举了 var script = document.createelement('script'); script.setattribute('data-require-id', moduleid); script.src = tourl(moduleid + '.js'); script.async = true; if (script.readystate) { script.onreadystatechange = inneronload; } else { script.onload = inneronload; } function inneronload() { var readystate = script.readystate; if ( typeof readystate === 'undefined' || /^(loaded|complete)$/.test(readystate) ) { script.onload = script.onreadystatechange = null; script = null; onload(); } } currentlyaddingscript = script; // if base tag is in play, using appendchild is a problem for ie6. // see: http://dev.jquery.com/ticket/2709 baseelement ? headelement.insertbefore(script, baseelement) : headelement.appendchild(script); currentlyaddingscript = null; } /** * 创建id前缀匹配的正则对象 * * @inner * @param {string} prefix id前缀 * @return {regexp} 前缀匹配的正则对象 */ function createprefixregexp(prefix) { return new regexp('^' + prefix + '(/|$)'); } /** * 循环遍历数组集合 * * @inner * @param {array} source 数组源 * @param {function(array,number):boolean} iterator 遍历函数 */ function each(source, iterator) { if (source instanceof array) { for (var i = 0, len = source.length; i < len; i++) { if (iterator(source[i], i) === false) { break; } } } } /** * 根据元素的k或name项进行数组字符数逆序的排序函数 * * @inner * @param {object} a 要比较的对象a * @param {object} b 要比较的对象b * @return {number} 比较结果 */ function descsorterbykorname(a, b) { var avalue = a.k || a.name; var bvalue = b.k || b.name; if (bvalue === '*') { return -1; } if (avalue === '*') { return 1; } return bvalue.length - avalue.length; } // 暴露全局对象 if (!define) { define = globaldefine; // 可能碰到其他形式的loader,所以,不要覆盖人家 if (!require) { require = globalrequire; } // 如果存在其他版本的esl,在define那里就判断过了,不会进入这个分支 // 所以这里就不判断了,直接写 esl = globalrequire; } })(this); define('echarts', ['echarts/echarts'], function (main) {return main;}); define('echarts/echarts', [ 'require', './config', 'zrender/tool/util', 'zrender/tool/event', 'zrender/tool/env', 'zrender', 'zrender/config', './chart/island', './component/toolbox', './component', './component/title', './component/tooltip', './component/legend', './util/ecdata', './chart', 'zrender/tool/color', './component/timeline', 'zrender/shape/image', 'zrender/loadingeffect/bar', 'zrender/loadingeffect/bubble', 'zrender/loadingeffect/dynamicline', 'zrender/loadingeffect/ring', 'zrender/loadingeffect/spin', 'zrender/loadingeffect/whirling', './theme/macarons', './theme/infographic' ], function (require) { var ecconfig = require('./config'); var zrutil = require('zrender/tool/util'); var zrevent = require('zrender/tool/event'); var self = {}; var _canvassupported = require('zrender/tool/env').canvassupported; var _idbase = new date() - 0; var _instances = {}; var dom_attribute_key = '_echarts_instance_'; self.version = '2.2.7'; self.dependencies = { zrender: '2.1.1' }; self.init = function (dom, theme) { var zrender = require('zrender'); if (zrender.version.replace('.', '') - 0 < self.dependencies.zrender.replace('.', '') - 0) { console.error('zrender ' + zrender.version + ' is too old for echarts ' + self.version + '. current version need zrender ' + self.dependencies.zrender + '+'); } dom = dom instanceof array ? dom[0] : dom; var key = dom.getattribute(dom_attribute_key); if (!key) { key = _idbase++; dom.setattribute(dom_attribute_key, key); } if (_instances[key]) { _instances[key].dispose(); } _instances[key] = new echarts(dom); _instances[key].id = key; _instances[key].canvassupported = _canvassupported; _instances[key].settheme(theme); return _instances[key]; }; self.getinstancebyid = function (key) { return _instances[key]; }; function messagecenter() { zrevent.dispatcher.call(this); } zrutil.merge(messagecenter.prototype, zrevent.dispatcher.prototype, true); function echarts(dom) { dom.innerhtml = ''; this._themeconfig = {}; this.dom = dom; this._connected = false; this._status = { dragin: false, dragout: false, needrefresh: false }; this._cureventtype = false; this._chartlist = []; this._messagecenter = new messagecenter(); this._messagecenteroutside = new messagecenter(); this.resize = this.resize(); this._init(); } var zr_event = require('zrender/config').event; var zr_event_listens = [ 'click', 'dblclick', 'mouseover', 'mouseout', 'dragstart', 'dragend', 'dragenter', 'dragover', 'dragleave', 'drop' ]; function callchartlistmethodreverse(ecinstance, methodname, arg0, arg1, arg2) { var chartlist = ecinstance._chartlist; var len = chartlist.length; while (len--) { var chart = chartlist[len]; if (typeof chart[methodname] === 'function') { chart[methodname](arg0, arg1, arg2); } } } echarts.prototype = { _init: function () { var self = this; var _zr = require('zrender').init(this.dom); this._zr = _zr; this._messagecenter.dispatch = function (type, event, eventpackage, that) { eventpackage = eventpackage || {}; eventpackage.type = type; eventpackage.event = event; self._messagecenter.dispatchwithcontext(type, eventpackage, that); self._messagecenteroutside.dispatchwithcontext(type, eventpackage, that); }; this._onevent = function (param) { return self.__onevent(param); }; for (var e in ecconfig.event) { if (e != 'click' && e != 'dblclick' && e != 'hover' && e != 'mouseout' && e != 'map_roam') { this._messagecenter.bind(ecconfig.event[e], this._onevent, this); } } var eventbehaviors = {}; this._onzrevent = function (param) { return self[eventbehaviors[param.type]](param); }; for (var i = 0, len = zr_event_listens.length; i < len; i++) { var eventname = zr_event_listens[i]; var eventvalue = zr_event[eventname]; eventbehaviors[eventvalue] = '_on' + eventname.tolowercase(); _zr.on(eventvalue, this._onzrevent); } this.chart = {}; this.component = {}; var island = require('./chart/island'); this._island = new island(this._themeconfig, this._messagecenter, _zr, {}, this); this.chart.island = this._island; var toolbox = require('./component/toolbox'); this._toolbox = new toolbox(this._themeconfig, this._messagecenter, _zr, {}, this); this.component.toolbox = this._toolbox; var componentlibrary = require('./component'); componentlibrary.define('title', require('./component/title')); componentlibrary.define('tooltip', require('./component/tooltip')); componentlibrary.define('legend', require('./component/legend')); if (_zr.getwidth() === 0 || _zr.getheight() === 0) { console.error('dom’s width & height should be ready before init.'); } }, __onevent: function (param) { param.__echartsid = param.__echartsid || this.id; var frommyself = param.__echartsid === this.id; if (!this._cureventtype) { this._cureventtype = param.type; } switch (param.type) { case ecconfig.event.legend_selected: this._onlegendselected(param); break; case ecconfig.event.data_zoom: if (!frommyself) { var dz = this.component.datazoom; if (dz) { dz.silence(true); dz.absolutezoom(param.zoom); dz.silence(false); } } this._ondatazoom(param); break; case ecconfig.event.data_range: frommyself && this._ondatarange(param); break; case ecconfig.event.magic_type_changed: if (!frommyself) { var tb = this.component.toolbox; if (tb) { tb.silence(true); tb.setmagictype(param.magictype); tb.silence(false); } } this._onmagictypechanged(param); break; case ecconfig.event.data_view_changed: frommyself && this._ondataviewchanged(param); break; case ecconfig.event.tooltip_hover: frommyself && this._tooltiphover(param); break; case ecconfig.event.restore: this._onrestore(); break; case ecconfig.event.refresh: frommyself && this._onrefresh(param); break; case ecconfig.event.tooltip_in_grid: case ecconfig.event.tooltip_out_grid: if (!frommyself) { var grid = this.component.grid; if (grid) { this._zr.trigger('mousemove', { connecttrigger: true, zrenderx: grid.getx() + param.x * grid.getwidth(), zrendery: grid.gety() + param.y * grid.getheight() }); } } else if (this._connected) { var grid = this.component.grid; if (grid) { param.x = (param.event.zrenderx - grid.getx()) / grid.getwidth(); param.y = (param.event.zrendery - grid.gety()) / grid.getheight(); } } break; } if (this._connected && frommyself && this._cureventtype === param.type) { for (var c in this._connected) { this._connected[c].connectedeventhandler(param); } this._cureventtype = null; } if (!frommyself || !this._connected && frommyself) { this._cureventtype = null; } }, _onclick: function (param) { callchartlistmethodreverse(this, 'onclick', param); if (param.target) { var ecdata = this._eventpackage(param.target); if (ecdata && ecdata.seriesindex != null) { this._messagecenter.dispatch(ecconfig.event.click, param.event, ecdata, this); } } }, _ondblclick: function (param) { callchartlistmethodreverse(this, 'ondblclick', param); if (param.target) { var ecdata = this._eventpackage(param.target); if (ecdata && ecdata.seriesindex != null) { this._messagecenter.dispatch(ecconfig.event.dblclick, param.event, ecdata, this); } } }, _onmouseover: function (param) { if (param.target) { var ecdata = this._eventpackage(param.target); if (ecdata && ecdata.seriesindex != null) { this._messagecenter.dispatch(ecconfig.event.hover, param.event, ecdata, this); } } }, _onmouseout: function (param) { if (param.target) { var ecdata = this._eventpackage(param.target); if (ecdata && ecdata.seriesindex != null) { this._messagecenter.dispatch(ecconfig.event.mouseout, param.event, ecdata, this); } } }, _ondragstart: function (param) { this._status = { dragin: false, dragout: false, needrefresh: false }; callchartlistmethodreverse(this, 'ondragstart', param); }, _ondragenter: function (param) { callchartlistmethodreverse(this, 'ondragenter', param); }, _ondragover: function (param) { callchartlistmethodreverse(this, 'ondragover', param); }, _ondragleave: function (param) { callchartlistmethodreverse(this, 'ondragleave', param); }, _ondrop: function (param) { callchartlistmethodreverse(this, 'ondrop', param, this._status); this._island.ondrop(param, this._status); }, _ondragend: function (param) { callchartlistmethodreverse(this, 'ondragend', param, this._status); this._timeline && this._timeline.ondragend(param, this._status); this._island.ondragend(param, this._status); if (this._status.needrefresh) { this._syncbackupdata(this._option); var messagecenter = this._messagecenter; messagecenter.dispatch(ecconfig.event.data_changed, param.event, this._eventpackage(param.target), this); messagecenter.dispatch(ecconfig.event.refresh, null, null, this); } }, _onlegendselected: function (param) { this._status.needrefresh = false; callchartlistmethodreverse(this, 'onlegendselected', param, this._status); if (this._status.needrefresh) { this._messagecenter.dispatch(ecconfig.event.refresh, null, null, this); } }, _ondatazoom: function (param) { this._status.needrefresh = false; callchartlistmethodreverse(this, 'ondatazoom', param, this._status); if (this._status.needrefresh) { this._messagecenter.dispatch(ecconfig.event.refresh, null, null, this); } }, _ondatarange: function (param) { this._cleareffect(); this._status.needrefresh = false; callchartlistmethodreverse(this, 'ondatarange', param, this._status); if (this._status.needrefresh) { this._zr.refreshnextframe(); } }, _onmagictypechanged: function () { this._cleareffect(); this._render(this._toolbox.getmagicoption()); }, _ondataviewchanged: function (param) { this._syncbackupdata(param.option); this._messagecenter.dispatch(ecconfig.event.data_changed, null, param, this); this._messagecenter.dispatch(ecconfig.event.refresh, null, null, this); }, _tooltiphover: function (param) { var tipshape = []; callchartlistmethodreverse(this, 'ontooltiphover', param, tipshape); }, _onrestore: function () { this.restore(); }, _onrefresh: function (param) { this._refreshinside = true; this.refresh(param); this._refreshinside = false; }, _syncbackupdata: function (curoption) { this.component.datazoom && this.component.datazoom.syncbackupdata(curoption); }, _eventpackage: function (target) { if (target) { var ecdata = require('./util/ecdata'); var seriesindex = ecdata.get(target, 'seriesindex'); var dataindex = ecdata.get(target, 'dataindex'); dataindex = seriesindex != -1 && this.component.datazoom ? this.component.datazoom.getrealdataindex(seriesindex, dataindex) : dataindex; return { seriesindex: seriesindex, seriesname: (ecdata.get(target, 'series') || {}).name, dataindex: dataindex, data: ecdata.get(target, 'data'), name: ecdata.get(target, 'name'), value: ecdata.get(target, 'value'), special: ecdata.get(target, 'special') }; } return; }, _nodatacheck: function (magicoption) { var series = magicoption.series; for (var i = 0, l = series.length; i < l; i++) { if (series[i].type == ecconfig.chart_type_map || series[i].data && series[i].data.length > 0 || series[i].markpoint && series[i].markpoint.data && series[i].markpoint.data.length > 0 || series[i].markline && series[i].markline.data && series[i].markline.data.length > 0 || series[i].nodes && series[i].nodes.length > 0 || series[i].links && series[i].links.length > 0 || series[i].matrix && series[i].matrix.length > 0 || series[i].eventlist && series[i].eventlist.length > 0) { return false; } } var loadoption = this._option && this._option.nodataloadingoption || this._themeconfig.nodataloadingoption || ecconfig.nodataloadingoption || { text: this._option && this._option.nodatatext || this._themeconfig.nodatatext || ecconfig.nodatatext, effect: this._option && this._option.nodataeffect || this._themeconfig.nodataeffect || ecconfig.nodataeffect }; this.clear(); this.showloading(loadoption); return true; }, _render: function (magicoption) { this._mergeglobalconifg(magicoption); if (this._nodatacheck(magicoption)) { return; } var bgcolor = magicoption.backgroundcolor; if (bgcolor) { if (!_canvassupported && bgcolor.indexof('rgba') != -1) { var clist = bgcolor.split(','); this.dom.style.filter = 'alpha(opacity=' + clist[3].substring(0, clist[3].lastindexof(')')) * 100 + ')'; clist.length = 3; clist[0] = clist[0].replace('a', ''); this.dom.style.backgroundcolor = clist.join(',') + ')'; } else { this.dom.style.backgroundcolor = bgcolor; } } this._zr.clearanimation(); this._chartlist = []; var chartlibrary = require('./chart'); var componentlibrary = require('./component'); if (magicoption.xaxis || magicoption.yaxis) { magicoption.grid = magicoption.grid || {}; magicoption.datazoom = magicoption.datazoom || {}; } var componentlist = [ 'title', 'legend', 'tooltip', 'datarange', 'roamcontroller', 'grid', 'datazoom', 'xaxis', 'yaxis', 'polar' ]; var componentclass; var componenttype; var component; for (var i = 0, l = componentlist.length; i < l; i++) { componenttype = componentlist[i]; component = this.component[componenttype]; if (magicoption[componenttype]) { if (component) { component.refresh && component.refresh(magicoption); } else { componentclass = componentlibrary.get(/^[xy]axis$/.test(componenttype) ? 'axis' : componenttype); component = new componentclass(this._themeconfig, this._messagecenter, this._zr, magicoption, this, componenttype); this.component[componenttype] = component; } this._chartlist.push(component); } else if (component) { component.dispose(); this.component[componenttype] = null; delete this.component[componenttype]; } } var chartclass; var charttype; var chart; var chartmap = {}; for (var i = 0, l = magicoption.series.length; i < l; i++) { charttype = magicoption.series[i].type; if (!charttype) { console.error('series[' + i + '] chart type has not been defined.'); continue; } if (!chartmap[charttype]) { chartmap[charttype] = true; chartclass = chartlibrary.get(charttype); if (chartclass) { if (this.chart[charttype]) { chart = this.chart[charttype]; chart.refresh(magicoption); } else { chart = new chartclass(this._themeconfig, this._messagecenter, this._zr, magicoption, this); } this._chartlist.push(chart); this.chart[charttype] = chart; } else { console.error(charttype + ' has not been required.'); } } } for (charttype in this.chart) { if (charttype != ecconfig.chart_type_island && !chartmap[charttype]) { this.chart[charttype].dispose(); this.chart[charttype] = null; delete this.chart[charttype]; } } this.component.grid && this.component.grid.refixaxisshape(this.component); this._island.refresh(magicoption); this._toolbox.refresh(magicoption); magicoption.animation && !magicoption.renderasimage ? this._zr.refresh() : this._zr.render(); var imgid = 'img' + this.id; var img = document.getelementbyid(imgid); if (magicoption.renderasimage && _canvassupported) { if (img) { img.src = this.getdataurl(magicoption.renderasimage); } else { img = this.getimage(magicoption.renderasimage); img.id = imgid; img.style.position = 'absolute'; img.style.left = 0; img.style.top = 0; this.dom.firstchild.appendchild(img); } this.un(); this._zr.un(); this._disposechartlist(); this._zr.clear(); } else if (img) { img.parentnode.removechild(img); } img = null; this._option = magicoption; }, restore: function () { this._cleareffect(); this._option = zrutil.clone(this._optionrestore); this._disposechartlist(); this._island.clear(); this._toolbox.reset(this._option, true); this._render(this._option); }, refresh: function (param) { this._cleareffect(); param = param || {}; var magicoption = param.option; if (!this._refreshinside && magicoption) { magicoption = this.getoption(); zrutil.merge(magicoption, param.option, true); zrutil.merge(this._optionrestore, param.option, true); this._toolbox.reset(magicoption); } this._island.refresh(magicoption); this._toolbox.refresh(magicoption); this._zr.clearanimation(); for (var i = 0, l = this._chartlist.length; i < l; i++) { this._chartlist[i].refresh && this._chartlist[i].refresh(magicoption); } this.component.grid && this.component.grid.refixaxisshape(this.component); this._zr.refresh(); }, _disposechartlist: function () { this._cleareffect(); this._zr.clearanimation(); var len = this._chartlist.length; while (len--) { var chart = this._chartlist[len]; if (chart) { var charttype = chart.type; this.chart[charttype] && delete this.chart[charttype]; this.component[charttype] && delete this.component[charttype]; chart.dispose && chart.dispose(); } } this._chartlist = []; }, _mergeglobalconifg: function (magicoption) { var mergelist = [ 'backgroundcolor', 'calculable', 'calculablecolor', 'calculableholdercolor', 'nameconnector', 'valueconnector', 'animation', 'animationthreshold', 'animationduration', 'animationdurationupdate', 'animationeasing', 'adddataanimation', 'symbollist', 'drag_enable_time' ]; var len = mergelist.length; while (len--) { var mergeitem = mergelist[len]; if (magicoption[mergeitem] == null) { magicoption[mergeitem] = this._themeconfig[mergeitem] != null ? this._themeconfig[mergeitem] : ecconfig[mergeitem]; } } var themecolor = magicoption.color; if (!(themecolor && themecolor.length)) { themecolor = this._themeconfig.color || ecconfig.color; } this._zr.getcolor = function (idx) { var zrcolor = require('zrender/tool/color'); return zrcolor.getcolor(idx, themecolor); }; if (!_canvassupported) { magicoption.animation = false; magicoption.adddataanimation = false; } }, setoption: function (option, notmerge) { if (!option.timeline) { return this._setoption(option, notmerge); } else { return this._settimelineoption(option); } }, _setoption: function (option, notmerge, keeptimeline) { if (!notmerge && this._option) { this._option = zrutil.merge(this.getoption(), zrutil.clone(option), true); } else { this._option = zrutil.clone(option); !keeptimeline && this._timeline && this._timeline.dispose(); } this._optionrestore = zrutil.clone(this._option); if (!this._option.series || this._option.series.length === 0) { this._zr.clear(); return; } if (this.component.datazoom && (this._option.datazoom || this._option.toolbox && this._option.toolbox.feature && this._option.toolbox.feature.datazoom && this._option.toolbox.feature.datazoom.show)) { this.component.datazoom.syncoption(this._option); } this._toolbox.reset(this._option); this._render(this._option); return this; }, getoption: function () { var magicoption = zrutil.clone(this._option); var self = this; function restoreoption(prop) { var restoresource = self._optionrestore[prop]; if (restoresource) { if (restoresource instanceof array) { var len = restoresource.length; while (len--) { magicoption[prop][len].data = zrutil.clone(restoresource[len].data); } } else { magicoption[prop].data = zrutil.clone(restoresource.data); } } } restoreoption('xaxis'); restoreoption('yaxis'); restoreoption('series'); return magicoption; }, setseries: function (series, notmerge) { if (!notmerge) { this.setoption({ series: series }); } else { this._option.series = series; this.setoption(this._option, notmerge); } return this; }, getseries: function () { return this.getoption().series; }, _settimelineoption: function (option) { this._timeline && this._timeline.dispose(); var timeline = require('./component/timeline'); var timeline = new timeline(this._themeconfig, this._messagecenter, this._zr, option, this); this._timeline = timeline; this.component.timeline = this._timeline; return this; }, adddata: function (seriesidx, data, ishead, datagrow, additiondata) { var params = seriesidx instanceof array ? seriesidx : [[ seriesidx, data, ishead, datagrow, additiondata ]]; var magicoption = this.getoption(); var optionrestore = this._optionrestore; var self = this; for (var i = 0, l = params.length; i < l; i++) { seriesidx = params[i][0]; data = params[i][1]; ishead = params[i][2]; datagrow = params[i][3]; additiondata = params[i][4]; var seriesitem = optionrestore.series[seriesidx]; var inmethod = ishead ? 'unshift' : 'push'; var outmethod = ishead ? 'pop' : 'shift'; if (seriesitem) { var seriesitemdata = seriesitem.data; var mseriesitemdata = magicoption.series[seriesidx].data; seriesitemdata[inmethod](data); mseriesitemdata[inmethod](data); if (!datagrow) { seriesitemdata[outmethod](); data = mseriesitemdata[outmethod](); } if (additiondata != null) { var legend; var legenddata; if (seriesitem.type === ecconfig.chart_type_pie && (legend = optionrestore.legend) && (legenddata = legend.data)) { var mlegenddata = magicoption.legend.data; legenddata[inmethod](additiondata); mlegenddata[inmethod](additiondata); if (!datagrow) { var legenddataidx = zrutil.indexof(legenddata, data.name); legenddataidx != -1 && legenddata.splice(legenddataidx, 1); legenddataidx = zrutil.indexof(mlegenddata, data.name); legenddataidx != -1 && mlegenddata.splice(legenddataidx, 1); } } else if (optionrestore.xaxis != null && optionrestore.yaxis != null) { var axisdata; var maxisdata; var axisidx = seriesitem.xaxisindex || 0; if (optionrestore.xaxis[axisidx].type == null || optionrestore.xaxis[axisidx].type === 'category') { axisdata = optionrestore.xaxis[axisidx].data; maxisdata = magicoption.xaxis[axisidx].data; axisdata[inmethod](additiondata); maxisdata[inmethod](additiondata); if (!datagrow) { axisdata[outmethod](); maxisdata[outmethod](); } } axisidx = seriesitem.yaxisindex || 0; if (optionrestore.yaxis[axisidx].type === 'category') { axisdata = optionrestore.yaxis[axisidx].data; maxisdata = magicoption.yaxis[axisidx].data; axisdata[inmethod](additiondata); maxisdata[inmethod](additiondata); if (!datagrow) { axisdata[outmethod](); maxisdata[outmethod](); } } } } this._option.series[seriesidx].data = magicoption.series[seriesidx].data; } } this._zr.clearanimation(); var chartlist = this._chartlist; var chartanimationcount = 0; var chartanimationdone = function () { chartanimationcount--; if (chartanimationcount === 0) { animationdone(); } }; for (var i = 0, l = chartlist.length; i < l; i++) { if (magicoption.adddataanimation && chartlist[i].adddataanimation) { chartanimationcount++; chartlist[i].adddataanimation(params, chartanimationdone); } } this.component.datazoom && this.component.datazoom.syncoption(magicoption); this._option = magicoption; function animationdone() { if (!self._zr) { return; } self._zr.clearanimation(); for (var i = 0, l = chartlist.length; i < l; i++) { chartlist[i].motionlessonce = magicoption.adddataanimation && chartlist[i].adddataanimation; } self._messagecenter.dispatch(ecconfig.event.refresh, null, { option: magicoption }, self); } if (!magicoption.adddataanimation) { settimeout(animationdone, 0); } return this; }, addmarkpoint: function (seriesidx, markdata) { return this._addmark(seriesidx, markdata, 'markpoint'); }, addmarkline: function (seriesidx, markdata) { return this._addmark(seriesidx, markdata, 'markline'); }, _addmark: function (seriesidx, markdata, marktype) { var series = this._option.series; var seriesitem; if (series && (seriesitem = series[seriesidx])) { var seriesr = this._optionrestore.series; var seriesritem = seriesr[seriesidx]; var markopt = seriesitem[marktype]; var markoptr = seriesritem[marktype]; markopt = seriesitem[marktype] = markopt || { data: [] }; markoptr = seriesritem[marktype] = markoptr || { data: [] }; for (var key in markdata) { if (key === 'data') { markopt.data = markopt.data.concat(markdata.data); markoptr.data = markoptr.data.concat(markdata.data); } else if (typeof markdata[key] != 'object' || markopt[key] == null) { markopt[key] = markoptr[key] = markdata[key]; } else { zrutil.merge(markopt[key], markdata[key], true); zrutil.merge(markoptr[key], markdata[key], true); } } var chart = this.chart[seriesitem.type]; chart && chart.addmark(seriesidx, markdata, marktype); } return this; }, delmarkpoint: function (seriesidx, markname) { return this._delmark(seriesidx, markname, 'markpoint'); }, delmarkline: function (seriesidx, markname) { return this._delmark(seriesidx, markname, 'markline'); }, _delmark: function (seriesidx, markname, marktype) { var series = this._option.series; var seriesitem; var mark; var dataarray; if (!(series && (seriesitem = series[seriesidx]) && (mark = seriesitem[marktype]) && (dataarray = mark.data))) { return this; } markname = markname.split(' > '); var targetindex = -1; for (var i = 0, l = dataarray.length; i < l; i++) { var dataitem = dataarray[i]; if (dataitem instanceof array) { if (dataitem[0].name === markname[0] && dataitem[1].name === markname[1]) { targetindex = i; break; } } else if (dataitem.name === markname[0]) { targetindex = i; break; } } if (targetindex > -1) { dataarray.splice(targetindex, 1); this._optionrestore.series[seriesidx][marktype].data.splice(targetindex, 1); var chart = this.chart[seriesitem.type]; chart && chart.delmark(seriesidx, markname.join(' > '), marktype); } return this; }, getdom: function () { return this.dom; }, getzrender: function () { return this._zr; }, getdataurl: function (imgtype) { if (!_canvassupported) { return ''; } if (this._chartlist.length === 0) { var imgid = 'img' + this.id; var img = document.getelementbyid(imgid); if (img) { return img.src; } } var tooltip = this.component.tooltip; tooltip && tooltip.hidetip(); switch (imgtype) { case 'jpeg': break; default: imgtype = 'png'; } var bgcolor = this._option.backgroundcolor; if (bgcolor && bgcolor.replace(' ', '') === 'rgba(0,0,0,0)') { bgcolor = '#fff'; } return this._zr.todataurl('image/' + imgtype, bgcolor); }, getimage: function (imgtype) { var title = this._optionrestore.title; var imgdom = document.createelement('img'); imgdom.src = this.getdataurl(imgtype); imgdom.title = title && title.text || 'echarts'; return imgdom; }, getconnecteddataurl: function (imgtype) { if (!this.isconnected()) { return this.getdataurl(imgtype); } var tempdom = this.dom; var imglist = { 'self': { img: this.getdataurl(imgtype), left: tempdom.offsetleft, top: tempdom.offsettop, right: tempdom.offsetleft + tempdom.offsetwidth, bottom: tempdom.offsettop + tempdom.offsetheight } }; var minleft = imglist.self.left; var mintop = imglist.self.top; var maxright = imglist.self.right; var maxbottom = imglist.self.bottom; for (var c in this._connected) { tempdom = this._connected[c].getdom(); imglist[c] = { img: this._connected[c].getdataurl(imgtype), left: tempdom.offsetleft, top: tempdom.offsettop, right: tempdom.offsetleft + tempdom.offsetwidth, bottom: tempdom.offsettop + tempdom.offsetheight }; minleft = math.min(minleft, imglist[c].left); mintop = math.min(mintop, imglist[c].top); maxright = math.max(maxright, imglist[c].right); maxbottom = math.max(maxbottom, imglist[c].bottom); } var zrdom = document.createelement('div'); zrdom.style.position = 'absolute'; zrdom.style.left = '-4000px'; zrdom.style.width = maxright - minleft + 'px'; zrdom.style.height = maxbottom - mintop + 'px'; document.body.appendchild(zrdom); var zrimg = require('zrender').init(zrdom); var imageshape = require('zrender/shape/image'); for (var c in imglist) { zrimg.addshape(new imageshape({ style: { x: imglist[c].left - minleft, y: imglist[c].top - mintop, image: imglist[c].img } })); } zrimg.render(); var bgcolor = this._option.backgroundcolor; if (bgcolor && bgcolor.replace(/ /g, '') === 'rgba(0,0,0,0)') { bgcolor = '#fff'; } var image = zrimg.todataurl('image/png', bgcolor); settimeout(function () { zrimg.dispose(); zrdom.parentnode.removechild(zrdom); zrdom = null; }, 100); return image; }, getconnectedimage: function (imgtype) { var title = this._optionrestore.title; var imgdom = document.createelement('img'); imgdom.src = this.getconnecteddataurl(imgtype); imgdom.title = title && title.text || 'echarts'; return imgdom; }, on: function (eventname, eventlistener) { this._messagecenteroutside.bind(eventname, eventlistener, this); return this; }, un: function (eventname, eventlistener) { this._messagecenteroutside.unbind(eventname, eventlistener); return this; }, connect: function (connecttarget) { if (!connecttarget) { return this; } if (!this._connected) { this._connected = {}; } if (connecttarget instanceof array) { for (var i = 0, l = connecttarget.length; i < l; i++) { this._connected[connecttarget[i].id] = connecttarget[i]; } } else { this._connected[connecttarget.id] = connecttarget; } return this; }, disconnect: function (connecttarget) { if (!connecttarget || !this._connected) { return this; } if (connecttarget instanceof array) { for (var i = 0, l = connecttarget.length; i < l; i++) { delete this._connected[connecttarget[i].id]; } } else { delete this._connected[connecttarget.id]; } for (var k in this._connected) { return k, this; } this._connected = false; return this; }, connectedeventhandler: function (param) { if (param.__echartsid != this.id) { this._onevent(param); } }, isconnected: function () { return !!this._connected; }, showloading: function (loadingoption) { var effectlist = { bar: require('zrender/loadingeffect/bar'), bubble: require('zrender/loadingeffect/bubble'), dynamicline: require('zrender/loadingeffect/dynamicline'), ring: require('zrender/loadingeffect/ring'), spin: require('zrender/loadingeffect/spin'), whirling: require('zrender/loadingeffect/whirling') }; this._toolbox.hidedataview(); loadingoption = loadingoption || {}; var textstyle = loadingoption.textstyle || {}; loadingoption.textstyle = textstyle; var finaltextstyle = zrutil.merge(zrutil.merge(zrutil.clone(textstyle), this._themeconfig.textstyle), ecconfig.textstyle); textstyle.textfont = finaltextstyle.fontstyle + ' ' + finaltextstyle.fontweight + ' ' + finaltextstyle.fontsize + 'px ' + finaltextstyle.fontfamily; textstyle.text = loadingoption.text || this._option && this._option.loadingtext || this._themeconfig.loadingtext || ecconfig.loadingtext; if (loadingoption.x != null) { textstyle.x = loadingoption.x; } if (loadingoption.y != null) { textstyle.y = loadingoption.y; } loadingoption.effectoption = loadingoption.effectoption || {}; loadingoption.effectoption.textstyle = textstyle; var effect = loadingoption.effect; if (typeof effect === 'string' || effect == null) { effect = effectlist[loadingoption.effect || this._option && this._option.loadingeffect || this._themeconfig.loadingeffect || ecconfig.loadingeffect] || effectlist.spin; } this._zr.showloading(new effect(loadingoption.effectoption)); return this; }, hideloading: function () { this._zr.hideloading(); return this; }, settheme: function (theme) { if (theme) { if (typeof theme === 'string') { switch (theme) { case 'macarons': theme = require('./theme/macarons'); break; case 'infographic': theme = require('./theme/infographic'); break; default: theme = {}; } } else { theme = theme || {}; } this._themeconfig = theme; } if (!_canvassupported) { var textstyle = this._themeconfig.textstyle; textstyle && textstyle.fontfamily && textstyle.fontfamily2 && (textstyle.fontfamily = textstyle.fontfamily2); textstyle = ecconfig.textstyle; textstyle.fontfamily = textstyle.fontfamily2; } this._timeline && this._timeline.settheme(true); this._optionrestore && this.restore(); }, resize: function () { var self = this; return function () { self._cleareffect(); self._zr.resize(); if (self._option && self._option.renderasimage && _canvassupported) { self._render(self._option); return self; } self._zr.clearanimation(); self._island.resize(); self._toolbox.resize(); self._timeline && self._timeline.resize(); for (var i = 0, l = self._chartlist.length; i < l; i++) { self._chartlist[i].resize && self._chartlist[i].resize(); } self.component.grid && self.component.grid.refixaxisshape(self.component); self._zr.refresh(); self._messagecenter.dispatch(ecconfig.event.resize, null, null, self); return self; }; }, _cleareffect: function () { this._zr.modlayer(ecconfig.effect_zlevel, { motionblur: false }); this._zr.painter.clearlayer(ecconfig.effect_zlevel); }, clear: function () { this._disposechartlist(); this._zr.clear(); this._option = {}; this._optionrestore = {}; this.dom.style.backgroundcolor = null; return this; }, dispose: function () { var key = this.dom.getattribute(dom_attribute_key); key && delete _instances[key]; this._island.dispose(); this._toolbox.dispose(); this._timeline && this._timeline.dispose(); this._messagecenter.unbind(); this.clear(); this._zr.dispose(); this._zr = null; } }; return self; });define('echarts/config', [], function () { var config = { chart_type_line: 'line', chart_type_bar: 'bar', chart_type_scatter: 'scatter', chart_type_pie: 'pie', chart_type_radar: 'radar', chart_type_venn: 'venn', chart_type_treemap: 'treemap', chart_type_tree: 'tree', chart_type_map: 'map', chart_type_k: 'k', chart_type_island: 'island', chart_type_force: 'force', chart_type_chord: 'chord', chart_type_gauge: 'gauge', chart_type_funnel: 'funnel', chart_type_eventriver: 'eventriver', chart_type_wordcloud: 'wordcloud', chart_type_heatmap: 'heatmap', component_type_title: 'title', component_type_legend: 'legend', component_type_datarange: 'datarange', component_type_dataview: 'dataview', component_type_datazoom: 'datazoom', component_type_toolbox: 'toolbox', component_type_tooltip: 'tooltip', component_type_grid: 'grid', component_type_axis: 'axis', component_type_polar: 'polar', component_type_x_axis: 'xaxis', component_type_y_axis: 'yaxis', component_type_axis_category: 'categoryaxis', component_type_axis_value: 'valueaxis', component_type_timeline: 'timeline', component_type_roamcontroller: 'roamcontroller', backgroundcolor: 'rgba(0,0,0,0)', color: [ '#ff7f50', '#87cefa', '#da70d6', '#32cd32', '#6495ed', '#ff69b4', '#ba55d3', '#cd5c5c', '#ffa500', '#40e0d0', '#1e90ff', '#ff6347', '#7b68ee', '#00fa9a', '#ffd700', '#6699ff', '#ff6666', '#3cb371', '#b8860b', '#30e0e0' ], markpoint: { clickable: true, symbol: 'pin', symbolsize: 10, large: false, effect: { show: false, loop: true, period: 15, type: 'scale', scalesize: 2, bouncedistance: 10 }, itemstyle: { normal: { borderwidth: 2, label: { show: true, position: 'inside' } }, emphasis: { label: { show: true } } } }, markline: { clickable: true, symbol: [ 'circle', 'arrow' ], symbolsize: [ 2, 4 ], smoothness: 0.2, precision: 2, effect: { show: false, loop: true, period: 15, scalesize: 2 }, bundling: { enable: false, maxturningangle: 45 }, itemstyle: { normal: { borderwidth: 1.5, label: { show: true, position: 'end' }, linestyle: { type: 'dashed' } }, emphasis: { label: { show: false }, linestyle: {} } } }, textstyle: { decoration: 'none', fontfamily: 'arial, verdana, sans-serif', fontfamily2: '微软雅黑', fontsize: 12, fontstyle: 'normal', fontweight: 'normal' }, event: { refresh: 'refresh', restore: 'restore', resize: 'resize', click: 'click', dblclick: 'dblclick', hover: 'hover', mouseout: 'mouseout', data_changed: 'datachanged', data_zoom: 'datazoom', data_range: 'datarange', data_range_selected: 'datarangeselected', data_range_hoverlink: 'datarangehoverlink', legend_selected: 'legendselected', legend_hoverlink: 'legendhoverlink', map_selected: 'mapselected', pie_selected: 'pieselected', magic_type_changed: 'magictypechanged', data_view_changed: 'dataviewchanged', timeline_changed: 'timelinechanged', map_roam: 'maproam', force_layout_end: 'forcelayoutend', tooltip_hover: 'tooltiphover', tooltip_in_grid: 'tooltipingrid', tooltip_out_grid: 'tooltipoutgrid', roamcontroller: 'roamcontroller' }, drag_enable_time: 120, effect_zlevel: 10, effectblendalpha: 0.95, symbollist: [ 'circle', 'rectangle', 'triangle', 'diamond', 'emptycircle', 'emptyrectangle', 'emptytriangle', 'emptydiamond' ], loadingeffect: 'spin', loadingtext: '数据读取中...', nodataeffect: 'bubble', nodatatext: '暂无数据', calculable: false, calculablecolor: 'rgba(255,165,0,0.6)', calculableholdercolor: '#ccc', nameconnector: ' & ', valueconnector: ': ', animation: true, adddataanimation: true, animationthreshold: 2000, animationduration: 2000, animationdurationupdate: 500, animationeasing: 'exponentialout' }; return config; });define('zrender/tool/util', [ 'require', '../dep/excanvas' ], function (require) { var arrayproto = array.prototype; var nativeforeach = arrayproto.foreach; var nativemap = arrayproto.map; var nativefilter = arrayproto.filter; var builtin_object = { '[object function]': 1, '[object regexp]': 1, '[object date]': 1, '[object error]': 1, '[object canvasgradient]': 1 }; var objtostring = object.prototype.tostring; function isdom(obj) { return obj && obj.nodetype === 1 && typeof obj.nodename == 'string'; } function clone(source) { if (typeof source == 'object' && source !== null) { var result = source; if (source instanceof array) { result = []; for (var i = 0, len = source.length; i < len; i++) { result[i] = clone(source[i]); } } else if (!builtin_object[objtostring.call(source)] && !isdom(source)) { result = {}; for (var key in source) { if (source.hasownproperty(key)) { result[key] = clone(source[key]); } } } return result; } return source; } function mergeitem(target, source, key, overwrite) { if (source.hasownproperty(key)) { var targetprop = target[key]; if (typeof targetprop == 'object' && !builtin_object[objtostring.call(targetprop)] && !isdom(targetprop)) { merge(target[key], source[key], overwrite); } else if (overwrite || !(key in target)) { target[key] = source[key]; } } } function merge(target, source, overwrite) { for (var i in source) { mergeitem(target, source, i, overwrite); } return target; } var _ctx; function getcontext() { if (!_ctx) { require('../dep/excanvas'); if (window['g_vmlcanvasmanager']) { var _div = document.createelement('div'); _div.style.position = 'absolute'; _div.style.top = '-1000px'; document.body.appendchild(_div); _ctx = g_vmlcanvasmanager.initelement(_div).getcontext('2d'); } else { _ctx = document.createelement('canvas').getcontext('2d'); } } return _ctx; } function indexof(array, value) { if (array.indexof) { return array.indexof(value); } for (var i = 0, len = array.length; i < len; i++) { if (array[i] === value) { return i; } } return -1; } function inherits(clazz, baseclazz) { var clazzprototype = clazz.prototype; function f() { } f.prototype = baseclazz.prototype; clazz.prototype = new f(); for (var prop in clazzprototype) { clazz.prototype[prop] = clazzprototype[prop]; } clazz.constructor = clazz; } function each(obj, cb, context) { if (!(obj && cb)) { return; } if (obj.foreach && obj.foreach === nativeforeach) { obj.foreach(cb, context); } else if (obj.length === +obj.length) { for (var i = 0, len = obj.length; i < len; i++) { cb.call(context, obj[i], i, obj); } } else { for (var key in obj) { if (obj.hasownproperty(key)) { cb.call(context, obj[key], key, obj); } } } } function map(obj, cb, context) { if (!(obj && cb)) { return; } if (obj.map && obj.map === nativemap) { return obj.map(cb, context); } else { var result = []; for (var i = 0, len = obj.length; i < len; i++) { result.push(cb.call(context, obj[i], i, obj)); } return result; } } function filter(obj, cb, context) { if (!(obj && cb)) { return; } if (obj.filter && obj.filter === nativefilter) { return obj.filter(cb, context); } else { var result = []; for (var i = 0, len = obj.length; i < len; i++) { if (cb.call(context, obj[i], i, obj)) { result.push(obj[i]); } } return result; } } function bind(func, context) { return function () { func.apply(context, arguments); }; } return { inherits: inherits, clone: clone, merge: merge, getcontext: getcontext, indexof: indexof, each: each, map: map, filter: filter, bind: bind }; });define('zrender/tool/event', [ 'require', '../mixin/eventful' ], function (require) { 'use strict'; var eventful = require('../mixin/eventful'); function getx(e) { return typeof e.zrenderx != 'undefined' && e.zrenderx || typeof e.offsetx != 'undefined' && e.offsetx || typeof e.layerx != 'undefined' && e.layerx || typeof e.clientx != 'undefined' && e.clientx; } function gety(e) { return typeof e.zrendery != 'undefined' && e.zrendery || typeof e.offsety != 'undefined' && e.offsety || typeof e.layery != 'undefined' && e.layery || typeof e.clienty != 'undefined' && e.clienty; } function getdelta(e) { return typeof e.zrenderdelta != 'undefined' && e.zrenderdelta || typeof e.wheeldelta != 'undefined' && e.wheeldelta || typeof e.detail != 'undefined' && -e.detail; } var stop = typeof window.addeventlistener === 'function' ? function (e) { e.preventdefault(); e.stoppropagation(); e.cancelbubble = true; } : function (e) { e.returnvalue = false; e.cancelbubble = true; }; return { getx: getx, gety: gety, getdelta: getdelta, stop: stop, dispatcher: eventful }; });define('zrender/tool/env', [], function () { function detect(ua) { var os = this.os = {}; var browser = this.browser = {}; var webkit = ua.match(/web[kk]it[\/]{0,1}([\d.]+)/); var android = ua.match(/(android);?[\s\/]+([\d.]+)?/); var ipad = ua.match(/(ipad).*os\s([\d_]+)/); var ipod = ua.match(/(ipod)(.*os\s([\d_]+))?/); var iphone = !ipad && ua.match(/(iphone\sos)\s([\d_]+)/); var webos = ua.match(/(webos|hpwos)[\s\/]([\d.]+)/); var touchpad = webos && ua.match(/touchpad/); var kindle = ua.match(/kindle\/([\d.]+)/); var silk = ua.match(/silk\/([\d._]+)/); var blackberry = ua.match(/(blackberry).*version\/([\d.]+)/); var bb10 = ua.match(/(bb10).*version\/([\d.]+)/); var rimtabletos = ua.match(/(rim\stablet\sos)\s([\d.]+)/); var playbook = ua.match(/playbook/); var chrome = ua.match(/chrome\/([\d.]+)/) || ua.match(/crios\/([\d.]+)/); var firefox = ua.match(/firefox\/([\d.]+)/); var ie = ua.match(/msie ([\d.]+)/); var safari = webkit && ua.match(/mobile\//) && !chrome; var webview = ua.match(/(iphone|ipod|ipad).*applewebkit(?!.*safari)/) && !chrome; var ie = ua.match(/msie\s([\d.]+)/); if (browser.webkit = !!webkit) browser.version = webkit[1]; if (android) os.android = true, os.version = android[2]; if (iphone && !ipod) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.'); if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.'); if (ipod) os.ios = os.ipod = true, os.version = ipod[3] ? ipod[3].replace(/_/g, '.') : null; if (webos) os.webos = true, os.version = webos[2]; if (touchpad) os.touchpad = true; if (blackberry) os.blackberry = true, os.version = blackberry[2]; if (bb10) os.bb10 = true, os.version = bb10[2]; if (rimtabletos) os.rimtabletos = true, os.version = rimtabletos[2]; if (playbook) browser.playbook = true; if (kindle) os.kindle = true, os.version = kindle[1]; if (silk) browser.silk = true, browser.version = silk[1]; if (!silk && os.android && ua.match(/kindle fire/)) browser.silk = true; if (chrome) browser.chrome = true, browser.version = chrome[1]; if (firefox) browser.firefox = true, browser.version = firefox[1]; if (ie) browser.ie = true, browser.version = ie[1]; if (safari && (ua.match(/safari/) || !!os.ios)) browser.safari = true; if (webview) browser.webview = true; if (ie) browser.ie = true, browser.version = ie[1]; os.tablet = !!(ipad || playbook || android && !ua.match(/mobile/) || firefox && ua.match(/tablet/) || ie && !ua.match(/phone/) && ua.match(/touch/)); os.phone = !!(!os.tablet && !os.ipod && (android || iphone || webos || blackberry || bb10 || chrome && ua.match(/android/) || chrome && ua.match(/crios\/([\d.]+)/) || firefox && ua.match(/mobile/) || ie && ua.match(/touch/))); return { browser: browser, os: os, canvassupported: document.createelement('canvas').getcontext ? true : false }; } return detect(navigator.useragent); });define('zrender', ['zrender/zrender'], function (main) {return main;}); define('zrender/zrender', [ 'require', './dep/excanvas', './tool/util', './tool/log', './tool/guid', './handler', './painter', './storage', './animation/animation', './tool/env' ], function (require) { require('./dep/excanvas'); var util = require('./tool/util'); var log = require('./tool/log'); var guid = require('./tool/guid'); var handler = require('./handler'); var painter = require('./painter'); var storage = require('./storage'); var animation = require('./animation/animation'); var _instances = {}; var zrender = {}; zrender.version = '2.1.1'; zrender.init = function (dom) { var zr = new zrender(guid(), dom); _instances[zr.id] = zr; return zr; }; zrender.dispose = function (zr) { if (zr) { zr.dispose(); } else { for (var key in _instances) { _instances[key].dispose(); } _instances = {}; } return zrender; }; zrender.getinstance = function (id) { return _instances[id]; }; zrender.delinstance = function (id) { delete _instances[id]; return zrender; }; function getframecallback(zrinstance) { return function () { if (zrinstance._needsrefreshnextframe) { zrinstance.refresh(); } }; } var zrender = function (id, dom) { this.id = id; this.env = require('./tool/env'); this.storage = new storage(); this.painter = new painter(dom, this.storage); this.handler = new handler(dom, this.storage, this.painter); this.animation = new animation({ stage: { update: getframecallback(this) } }); this.animation.start(); var self = this; this.painter.refreshnextframe = function () { self.refreshnextframe(); }; this._needsrefreshnextframe = false; var self = this; var storage = this.storage; var olddelfrommap = storage.delfrommap; storage.delfrommap = function (elid) { var el = storage.get(elid); self.stopanimation(el); olddelfrommap.call(storage, elid); }; }; zrender.prototype.getid = function () { return this.id; }; zrender.prototype.addshape = function (shape) { this.addelement(shape); return this; }; zrender.prototype.addgroup = function (group) { this.addelement(group); return this; }; zrender.prototype.delshape = function (shapeid) { this.delelement(shapeid); return this; }; zrender.prototype.delgroup = function (groupid) { this.delelement(groupid); return this; }; zrender.prototype.modshape = function (shapeid, shape) { this.modelement(shapeid, shape); return this; }; zrender.prototype.modgroup = function (groupid, group) { this.modelement(groupid, group); return this; }; zrender.prototype.addelement = function (el) { this.storage.addroot(el); this._needsrefreshnextframe = true; return this; }; zrender.prototype.delelement = function (el) { this.storage.delroot(el); this._needsrefreshnextframe = true; return this; }; zrender.prototype.modelement = function (el, params) { this.storage.mod(el, params); this._needsrefreshnextframe = true; return this; }; zrender.prototype.modlayer = function (zlevel, config) { this.painter.modlayer(zlevel, config); this._needsrefreshnextframe = true; return this; }; zrender.prototype.addhovershape = function (shape) { this.storage.addhover(shape); return this; }; zrender.prototype.render = function (callback) { this.painter.render(callback); this._needsrefreshnextframe = false; return this; }; zrender.prototype.refresh = function (callback) { this.painter.refresh(callback); this._needsrefreshnextframe = false; return this; }; zrender.prototype.refreshnextframe = function () { this._needsrefreshnextframe = true; return this; }; zrender.prototype.refreshhover = function (callback) { this.painter.refreshhover(callback); return this; }; zrender.prototype.refreshshapes = function (shapelist, callback) { this.painter.refreshshapes(shapelist, callback); return this; }; zrender.prototype.resize = function () { this.painter.resize(); return this; }; zrender.prototype.animate = function (el, path, loop) { var self = this; if (typeof el === 'string') { el = this.storage.get(el); } if (el) { var target; if (path) { var pathsplitted = path.split('.'); var prop = el; for (var i = 0, l = pathsplitted.length; i < l; i++) { if (!prop) { continue; } prop = prop[pathsplitted[i]]; } if (prop) { target = prop; } } else { target = el; } if (!target) { log('property "' + path + '" is not existed in element ' + el.id); return; } if (el.__animators == null) { el.__animators = []; } var animators = el.__animators; var animator = this.animation.animate(target, { loop: loop }).during(function () { self.modshape(el); }).done(function () { var idx = util.indexof(el.__animators, animator); if (idx >= 0) { animators.splice(idx, 1); } }); animators.push(animator); return animator; } else { log('element not existed'); } }; zrender.prototype.stopanimation = function (el) { if (el.__animators) { var animators = el.__animators; var len = animators.length; for (var i = 0; i < len; i++) { animators[i].stop(); } animators.length = 0; } return this; }; zrender.prototype.clearanimation = function () { this.animation.clear(); return this; }; zrender.prototype.showloading = function (loadingeffect) { this.painter.showloading(loadingeffect); return this; }; zrender.prototype.hideloading = function () { this.painter.hideloading(); return this; }; zrender.prototype.getwidth = function () { return this.painter.getwidth(); }; zrender.prototype.getheight = function () { return this.painter.getheight(); }; zrender.prototype.todataurl = function (type, backgroundcolor, args) { return this.painter.todataurl(type, backgroundcolor, args); }; zrender.prototype.shapetoimage = function (e, width, height) { var id = guid(); return this.painter.shapetoimage(id, e, width, height); }; zrender.prototype.on = function (eventname, eventhandler, context) { this.handler.on(eventname, eventhandler, context); return this; }; zrender.prototype.un = function (eventname, eventhandler) { this.handler.un(eventname, eventhandler); return this; }; zrender.prototype.trigger = function (eventname, event) { this.handler.trigger(eventname, event); return this; }; zrender.prototype.clear = function () { this.storage.delroot(); this.painter.clear(); return this; }; zrender.prototype.dispose = function () { this.animation.stop(); this.clear(); this.storage.dispose(); this.painter.dispose(); this.handler.dispose(); this.animation = this.storage = this.painter = this.handler = null; zrender.delinstance(this.id); }; return zrender; });define('zrender/config', [], function () { var config = { event: { resize: 'resize', click: 'click', dblclick: 'dblclick', mousewheel: 'mousewheel', mousemove: 'mousemove', mouseover: 'mouseover', mouseout: 'mouseout', mousedown: 'mousedown', mouseup: 'mouseup', globalout: 'globalout', dragstart: 'dragstart', dragend: 'dragend', dragenter: 'dragenter', dragover: 'dragover', dragleave: 'dragleave', drop: 'drop', touchclickdelay: 300 }, elementclassname: 'zr-element', catchbrushexception: false, debugmode: 0, devicepixelratio: math.max(window.devicepixelratio || 1, 1) }; return config; });define('echarts/chart/island', [ 'require', './base', 'zrender/shape/circle', '../config', '../util/ecdata', 'zrender/tool/util', 'zrender/tool/event', 'zrender/tool/color', '../util/accmath', '../chart' ], function (require) { var chartbase = require('./base'); var circleshape = require('zrender/shape/circle'); var ecconfig = require('../config'); ecconfig.island = { zlevel: 0, z: 5, r: 15, calculatestep: 0.1 }; var ecdata = require('../util/ecdata'); var zrutil = require('zrender/tool/util'); var zrevent = require('zrender/tool/event'); function island(ectheme, messagecenter, zr, option, mychart) { chartbase.call(this, ectheme, messagecenter, zr, option, mychart); this._nameconnector; this._valueconnector; this._zrheight = this.zr.getheight(); this._zrwidth = this.zr.getwidth(); var self = this; self.shapehandler.onmousewheel = function (param) { var shape = param.target; var event = param.event; var delta = zrevent.getdelta(event); delta = delta > 0 ? -1 : 1; shape.style.r -= delta; shape.style.r = shape.style.r < 5 ? 5 : shape.style.r; var value = ecdata.get(shape, 'value'); var dvalue = value * self.option.island.calculatestep; value = dvalue > 1 ? math.round(value - dvalue * delta) : +(value - dvalue * delta).tofixed(2); var name = ecdata.get(shape, 'name'); shape.style.text = name + ':' + value; ecdata.set(shape, 'value', value); ecdata.set(shape, 'name', name); self.zr.modshape(shape.id); self.zr.refreshnextframe(); zrevent.stop(event); }; } island.prototype = { type: ecconfig.chart_type_island, _combine: function (tarshape, srcshape) { var zrcolor = require('zrender/tool/color'); var accmath = require('../util/accmath'); var value = accmath.accadd(ecdata.get(tarshape, 'value'), ecdata.get(srcshape, 'value')); var name = ecdata.get(tarshape, 'name') + this._nameconnector + ecdata.get(srcshape, 'name'); tarshape.style.text = name + this._valueconnector + value; ecdata.set(tarshape, 'value', value); ecdata.set(tarshape, 'name', name); tarshape.style.r = this.option.island.r; tarshape.style.color = zrcolor.mix(tarshape.style.color, srcshape.style.color); }, refresh: function (newoption) { if (newoption) { newoption.island = this.reformoption(newoption.island); this.option = newoption; this._nameconnector = this.option.nameconnector; this._valueconnector = this.option.valueconnector; } }, getoption: function () { return this.option; }, resize: function () { var newwidth = this.zr.getwidth(); var newhieght = this.zr.getheight(); var xscale = newwidth / (this._zrwidth || newwidth); var yscale = newhieght / (this._zrheight || newhieght); if (xscale === 1 && yscale === 1) { return; } this._zrwidth = newwidth; this._zrheight = newhieght; for (var i = 0, l = this.shapelist.length; i < l; i++) { this.zr.modshape(this.shapelist[i].id, { style: { x: math.round(this.shapelist[i].style.x * xscale), y: math.round(this.shapelist[i].style.y * yscale) } }); } }, add: function (shape) { var name = ecdata.get(shape, 'name'); var value = ecdata.get(shape, 'value'); var seriesname = ecdata.get(shape, 'series') != null ? ecdata.get(shape, 'series').name : ''; var font = this.getfont(this.option.island.textstyle); var islandoption = this.option.island; var islandshape = { zlevel: islandoption.zlevel, z: islandoption.z, style: { x: shape.style.x, y: shape.style.y, r: this.option.island.r, color: shape.style.color || shape.style.strokecolor, text: name + this._valueconnector + value, textfont: font }, draggable: true, hoverable: true, onmousewheel: this.shapehandler.onmousewheel, _type: 'island' }; if (islandshape.style.color === '#fff') { islandshape.style.color = shape.style.strokecolor; } this.setcalculable(islandshape); islandshape.dragenabletime = 0; ecdata.pack(islandshape, { name: seriesname }, -1, value, -1, name); islandshape = new circleshape(islandshape); this.shapelist.push(islandshape); this.zr.addshape(islandshape); }, del: function (shape) { this.zr.delshape(shape.id); var newshapelist = []; for (var i = 0, l = this.shapelist.length; i < l; i++) { if (this.shapelist[i].id != shape.id) { newshapelist.push(this.shapelist[i]); } } this.shapelist = newshapelist; }, ondrop: function (param, status) { if (!this.isdrop || !param.target) { return; } var target = param.target; var dragged = param.dragged; this._combine(target, dragged); this.zr.modshape(target.id); status.dragin = true; this.isdrop = false; return; }, ondragend: function (param, status) { var target = param.target; if (!this.isdragend) { if (!status.dragin) { target.style.x = zrevent.getx(param.event); target.style.y = zrevent.gety(param.event); this.add(target); status.needrefresh = true; } } else { if (status.dragin) { this.del(target); status.needrefresh = true; } } this.isdragend = false; return; } }; zrutil.inherits(island, chartbase); require('../chart').define('island', island); return island; });define('echarts/component/toolbox', [ 'require', './base', 'zrender/shape/line', 'zrender/shape/image', 'zrender/shape/rectangle', '../util/shape/icon', '../config', 'zrender/tool/util', 'zrender/config', 'zrender/tool/event', './dataview', '../component' ], function (require) { var base = require('./base'); var lineshape = require('zrender/shape/line'); var imageshape = require('zrender/shape/image'); var rectangleshape = require('zrender/shape/rectangle'); var iconshape = require('../util/shape/icon'); var ecconfig = require('../config'); ecconfig.toolbox = { zlevel: 0, z: 6, show: false, orient: 'horizontal', x: 'right', y: 'top', color: [ '#1e90ff', '#22bb22', '#4b0082', '#d2691e' ], disablecolor: '#ddd', effectivecolor: 'red', backgroundcolor: 'rgba(0,0,0,0)', bordercolor: '#ccc', borderwidth: 0, padding: 5, itemgap: 10, itemsize: 16, showtitle: true, feature: { mark: { show: false, title: { mark: '辅助线开关', markundo: '删除辅助线', markclear: '清空辅助线' }, linestyle: { width: 1, color: '#1e90ff', type: 'dashed' } }, datazoom: { show: false, title: { datazoom: '区域缩放', datazoomreset: '区域缩放后退' } }, dataview: { show: false, title: '数据视图', readonly: false, lang: [ '数据视图', '关闭', '刷新' ] }, magictype: { show: false, title: { line: '折线图切换', bar: '柱形图切换', stack: '堆积', tiled: '平铺', force: '力导向布局图切换', chord: '和弦图切换', pie: '饼图切换', funnel: '漏斗图切换' }, type: [] }, restore: { show: false, title: '还原' }, saveasimage: { show: false, title: '保存为图片', type: 'png', lang: ['点击保存'] } } }; var zrutil = require('zrender/tool/util'); var zrconfig = require('zrender/config'); var zrevent = require('zrender/tool/event'); var _magictype_stack = 'stack'; var _magictype_tiled = 'tiled'; function toolbox(ectheme, messagecenter, zr, option, mychart) { base.call(this, ectheme, messagecenter, zr, option, mychart); this.dom = mychart.dom; this._magictype = {}; this._magicmap = {}; this._issilence = false; this._iconlist; this._iconshapemap = {}; this._featuretitle = {}; this._featureicon = {}; this._featurecolor = {}; this._featureoption = {}; this._enablecolor = 'red'; this._disablecolor = '#ccc'; this._markshapelist = []; var self = this; self._onmark = function (param) { self.__onmark(param); }; self._onmarkundo = function (param) { self.__onmarkundo(param); }; self._onmarkclear = function (param) { self.__onmarkclear(param); }; self._ondatazoom = function (param) { self.__ondatazoom(param); }; self._ondatazoomreset = function (param) { self.__ondatazoomreset(param); }; self._ondataview = function (param) { self.__ondataview(param); }; self._onrestore = function (param) { self.__onrestore(param); }; self._onsaveasimage = function (param) { self.__onsaveasimage(param); }; self._onmagictype = function (param) { self.__onmagictype(param); }; self._oncustomhandler = function (param) { self.__oncustomhandler(param); }; self._onmousemove = function (param) { return self.__onmousemove(param); }; self._onmousedown = function (param) { return self.__onmousedown(param); }; self._onmouseup = function (param) { return self.__onmouseup(param); }; self._onclick = function (param) { return self.__onclick(param); }; } toolbox.prototype = { type: ecconfig.component_type_toolbox, _buildshape: function () { this._iconlist = []; var toolboxoption = this.option.toolbox; this._enablecolor = toolboxoption.effectivecolor; this._disablecolor = toolboxoption.disablecolor; var feature = toolboxoption.feature; var iconname = []; for (var key in feature) { if (feature[key].show) { switch (key) { case 'mark': iconname.push({ key: key, name: 'mark' }); iconname.push({ key: key, name: 'markundo' }); iconname.push({ key: key, name: 'markclear' }); break; case 'magictype': for (var i = 0, l = feature[key].type.length; i < l; i++) { feature[key].title[feature[key].type[i] + 'chart'] = feature[key].title[feature[key].type[i]]; if (feature[key].option) { feature[key].option[feature[key].type[i] + 'chart'] = feature[key].option[feature[key].type[i]]; } iconname.push({ key: key, name: feature[key].type[i] + 'chart' }); } break; case 'datazoom': iconname.push({ key: key, name: 'datazoom' }); iconname.push({ key: key, name: 'datazoomreset' }); break; case 'saveasimage': if (this.canvassupported) { iconname.push({ key: key, name: 'saveasimage' }); } break; default: iconname.push({ key: key, name: key }); break; } } } if (iconname.length > 0) { var name; var key; for (var i = 0, l = iconname.length; i < l; i++) { name = iconname[i].name; key = iconname[i].key; this._iconlist.push(name); this._featuretitle[name] = feature[key].title[name] || feature[key].title; if (feature[key].icon) { this._featureicon[name] = feature[key].icon[name] || feature[key].icon; } if (feature[key].color) { this._featurecolor[name] = feature[key].color[name] || feature[key].color; } if (feature[key].option) { this._featureoption[name] = feature[key].option[name] || feature[key].option; } } this._itemgrouplocation = this._getitemgrouplocation(); this._buildbackground(); this._builditem(); for (var i = 0, l = this.shapelist.length; i < l; i++) { this.zr.addshape(this.shapelist[i]); } if (this._iconshapemap['mark']) { this._icondisable(this._iconshapemap['markundo']); this._icondisable(this._iconshapemap['markclear']); } if (this._iconshapemap['datazoomreset'] && this._zoomqueue.length === 0) { this._icondisable(this._iconshapemap['datazoomreset']); } } }, _builditem: function () { var toolboxoption = this.option.toolbox; var iconlength = this._iconlist.length; var lastx = this._itemgrouplocation.x; var lasty = this._itemgrouplocation.y; var itemsize = toolboxoption.itemsize; var itemgap = toolboxoption.itemgap; var itemshape; var color = toolboxoption.color instanceof array ? toolboxoption.color : [toolboxoption.color]; var textfont = this.getfont(toolboxoption.textstyle); var textposition; var textalign; var textbaseline; if (toolboxoption.orient === 'horizontal') { textposition = this._itemgrouplocation.y / this.zr.getheight() < 0.5 ? 'bottom' : 'top'; textalign = this._itemgrouplocation.x / this.zr.getwidth() < 0.5 ? 'left' : 'right'; textbaseline = this._itemgrouplocation.y / this.zr.getheight() < 0.5 ? 'top' : 'bottom'; } else { textposition = this._itemgrouplocation.x / this.zr.getwidth() < 0.5 ? 'right' : 'left'; } this._iconshapemap = {}; var self = this; for (var i = 0; i < iconlength; i++) { itemshape = { type: 'icon', zlevel: this.getzlevelbase(), z: this.getzbase(), style: { x: lastx, y: lasty, width: itemsize, height: itemsize, icontype: this._iconlist[i], linewidth: 1, strokecolor: this._featurecolor[this._iconlist[i]] || color[i % color.length], brushtype: 'stroke' }, highlightstyle: { linewidth: 1, text: toolboxoption.showtitle ? this._featuretitle[this._iconlist[i]] : undefined, textfont: textfont, textposition: textposition, strokecolor: this._featurecolor[this._iconlist[i]] || color[i % color.length] }, hoverable: true, clickable: true }; if (this._featureicon[this._iconlist[i]]) { itemshape.style.image = this._featureicon[this._iconlist[i]].replace(new regexp('^image:\\/\\/'), ''); itemshape.style.opacity = 0.8; itemshape.highlightstyle.opacity = 1; itemshape.type = 'image'; } if (toolboxoption.orient === 'horizontal') { if (i === 0 && textalign === 'left') { itemshape.highlightstyle.textposition = 'specific'; itemshape.highlightstyle.textalign = textalign; itemshape.highlightstyle.textbaseline = textbaseline; itemshape.highlightstyle.textx = lastx; itemshape.highlightstyle.texty = textbaseline === 'top' ? lasty + itemsize + 10 : lasty - 10; } if (i === iconlength - 1 && textalign === 'right') { itemshape.highlightstyle.textposition = 'specific'; itemshape.highlightstyle.textalign = textalign; itemshape.highlightstyle.textbaseline = textbaseline; itemshape.highlightstyle.textx = lastx + itemsize; itemshape.highlightstyle.texty = textbaseline === 'top' ? lasty + itemsize + 10 : lasty - 10; } } switch (this._iconlist[i]) { case 'mark': itemshape.onclick = self._onmark; break; case 'markundo': itemshape.onclick = self._onmarkundo; break; case 'markclear': itemshape.onclick = self._onmarkclear; break; case 'datazoom': itemshape.onclick = self._ondatazoom; break; case 'datazoomreset': itemshape.onclick = self._ondatazoomreset; break; case 'dataview': if (!this._dataview) { var dataview = require('./dataview'); this._dataview = new dataview(this.ectheme, this.messagecenter, this.zr, this.option, this.mychart); } itemshape.onclick = self._ondataview; break; case 'restore': itemshape.onclick = self._onrestore; break; case 'saveasimage': itemshape.onclick = self._onsaveasimage; break; default: if (this._iconlist[i].match('chart')) { itemshape._name = this._iconlist[i].replace('chart', ''); itemshape.onclick = self._onmagictype; } else { itemshape.onclick = self._oncustomhandler; } break; } if (itemshape.type === 'icon') { itemshape = new iconshape(itemshape); } else if (itemshape.type === 'image') { itemshape = new imageshape(itemshape); } this.shapelist.push(itemshape); this._iconshapemap[this._iconlist[i]] = itemshape; if (toolboxoption.orient === 'horizontal') { lastx += itemsize + itemgap; } else { lasty += itemsize + itemgap; } } }, _buildbackground: function () { var toolboxoption = this.option.toolbox; var padding = this.reformcssarray(this.option.toolbox.padding); this.shapelist.push(new rectangleshape({ zlevel: this.getzlevelbase(), z: this.getzbase(), hoverable: false, style: { x: this._itemgrouplocation.x - padding[3], y: this._itemgrouplocation.y - padding[0], width: this._itemgrouplocation.width + padding[3] + padding[1], height: this._itemgrouplocation.height + padding[0] + padding[2], brushtype: toolboxoption.borderwidth === 0 ? 'fill' : 'both', color: toolboxoption.backgroundcolor, strokecolor: toolboxoption.bordercolor, linewidth: toolboxoption.borderwidth } })); }, _getitemgrouplocation: function () { var toolboxoption = this.option.toolbox; var padding = this.reformcssarray(this.option.toolbox.padding); var iconlength = this._iconlist.length; var itemgap = toolboxoption.itemgap; var itemsize = toolboxoption.itemsize; var totalwidth = 0; var totalheight = 0; if (toolboxoption.orient === 'horizontal') { totalwidth = (itemsize + itemgap) * iconlength - itemgap; totalheight = itemsize; } else { totalheight = (itemsize + itemgap) * iconlength - itemgap; totalwidth = itemsize; } var x;