Global.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. /**
  20. * AUTO-GENERATED FILE. DO NOT MODIFY.
  21. */
  22. /*
  23. * Licensed to the Apache Software Foundation (ASF) under one
  24. * or more contributor license agreements. See the NOTICE file
  25. * distributed with this work for additional information
  26. * regarding copyright ownership. The ASF licenses this file
  27. * to you under the Apache License, Version 2.0 (the
  28. * "License"); you may not use this file except in compliance
  29. * with the License. You may obtain a copy of the License at
  30. *
  31. * http://www.apache.org/licenses/LICENSE-2.0
  32. *
  33. * Unless required by applicable law or agreed to in writing,
  34. * software distributed under the License is distributed on an
  35. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  36. * KIND, either express or implied. See the License for the
  37. * specific language governing permissions and limitations
  38. * under the License.
  39. */
  40. import { __extends } from "tslib";
  41. /**
  42. * Caution: If the mechanism should be changed some day, these cases
  43. * should be considered:
  44. *
  45. * (1) In `merge option` mode, if using the same option to call `setOption`
  46. * many times, the result should be the same (try our best to ensure that).
  47. * (2) In `merge option` mode, if a component has no id/name specified, it
  48. * will be merged by index, and the result sequence of the components is
  49. * consistent to the original sequence.
  50. * (3) In `replaceMerge` mode, keep the result sequence of the components is
  51. * consistent to the original sequence, even though there might result in "hole".
  52. * (4) `reset` feature (in toolbox). Find detailed info in comments about
  53. * `mergeOption` in module:echarts/model/OptionManager.
  54. */
  55. import { each, filter, isArray, isObject, isString, createHashMap, assert, clone, merge, extend, mixin, isFunction } from 'zrender/lib/core/util.js';
  56. import * as modelUtil from '../util/model.js';
  57. import Model from './Model.js';
  58. import ComponentModel from './Component.js';
  59. import globalDefault from './globalDefault.js';
  60. import { resetSourceDefaulter } from '../data/helper/sourceHelper.js';
  61. import { concatInternalOptions } from './internalComponentCreator.js';
  62. import { PaletteMixin } from './mixin/palette.js';
  63. import { error, warn } from '../util/log.js';
  64. // -----------------------
  65. // Internal method names:
  66. // -----------------------
  67. var reCreateSeriesIndices;
  68. var assertSeriesInitialized;
  69. var initBase;
  70. var OPTION_INNER_KEY = '\0_ec_inner';
  71. var OPTION_INNER_VALUE = 1;
  72. var BUITIN_COMPONENTS_MAP = {
  73. grid: 'GridComponent',
  74. polar: 'PolarComponent',
  75. geo: 'GeoComponent',
  76. singleAxis: 'SingleAxisComponent',
  77. parallel: 'ParallelComponent',
  78. calendar: 'CalendarComponent',
  79. matrix: 'MatrixComponent',
  80. graphic: 'GraphicComponent',
  81. toolbox: 'ToolboxComponent',
  82. tooltip: 'TooltipComponent',
  83. axisPointer: 'AxisPointerComponent',
  84. brush: 'BrushComponent',
  85. title: 'TitleComponent',
  86. timeline: 'TimelineComponent',
  87. markPoint: 'MarkPointComponent',
  88. markLine: 'MarkLineComponent',
  89. markArea: 'MarkAreaComponent',
  90. legend: 'LegendComponent',
  91. dataZoom: 'DataZoomComponent',
  92. visualMap: 'VisualMapComponent',
  93. // aria: 'AriaComponent',
  94. // dataset: 'DatasetComponent',
  95. // Dependencies
  96. xAxis: 'GridComponent',
  97. yAxis: 'GridComponent',
  98. angleAxis: 'PolarComponent',
  99. radiusAxis: 'PolarComponent'
  100. };
  101. var BUILTIN_CHARTS_MAP = {
  102. line: 'LineChart',
  103. bar: 'BarChart',
  104. pie: 'PieChart',
  105. scatter: 'ScatterChart',
  106. radar: 'RadarChart',
  107. map: 'MapChart',
  108. tree: 'TreeChart',
  109. treemap: 'TreemapChart',
  110. graph: 'GraphChart',
  111. chord: 'ChordChart',
  112. gauge: 'GaugeChart',
  113. funnel: 'FunnelChart',
  114. parallel: 'ParallelChart',
  115. sankey: 'SankeyChart',
  116. boxplot: 'BoxplotChart',
  117. candlestick: 'CandlestickChart',
  118. effectScatter: 'EffectScatterChart',
  119. lines: 'LinesChart',
  120. heatmap: 'HeatmapChart',
  121. pictorialBar: 'PictorialBarChart',
  122. themeRiver: 'ThemeRiverChart',
  123. sunburst: 'SunburstChart',
  124. custom: 'CustomChart'
  125. };
  126. var componetsMissingLogPrinted = {};
  127. function checkMissingComponents(option) {
  128. each(option, function (componentOption, mainType) {
  129. if (!ComponentModel.hasClass(mainType)) {
  130. var componentImportName = BUITIN_COMPONENTS_MAP[mainType];
  131. if (componentImportName && !componetsMissingLogPrinted[componentImportName]) {
  132. error("Component " + mainType + " is used but not imported.\nimport { " + componentImportName + " } from 'echarts/components';\necharts.use([" + componentImportName + "]);");
  133. componetsMissingLogPrinted[componentImportName] = true;
  134. }
  135. }
  136. });
  137. }
  138. var GlobalModel = /** @class */function (_super) {
  139. __extends(GlobalModel, _super);
  140. function GlobalModel() {
  141. return _super !== null && _super.apply(this, arguments) || this;
  142. }
  143. GlobalModel.prototype.init = function (option, parentModel, ecModel, theme, locale, optionManager) {
  144. theme = theme || {};
  145. this.option = null; // Mark as not initialized.
  146. this._theme = new Model(theme);
  147. this._locale = new Model(locale);
  148. this._optionManager = optionManager;
  149. };
  150. GlobalModel.prototype.setOption = function (option, opts, optionPreprocessorFuncs) {
  151. if (process.env.NODE_ENV !== 'production') {
  152. assert(option != null, 'option is null/undefined');
  153. assert(option[OPTION_INNER_KEY] !== OPTION_INNER_VALUE, 'please use chart.getOption()');
  154. }
  155. var innerOpt = normalizeSetOptionInput(opts);
  156. this._optionManager.setOption(option, optionPreprocessorFuncs, innerOpt);
  157. this._resetOption(null, innerOpt);
  158. };
  159. /**
  160. * @param type null/undefined: reset all.
  161. * 'recreate': force recreate all.
  162. * 'timeline': only reset timeline option
  163. * 'media': only reset media query option
  164. * @return Whether option changed.
  165. */
  166. GlobalModel.prototype.resetOption = function (type, opt) {
  167. return this._resetOption(type, normalizeSetOptionInput(opt));
  168. };
  169. GlobalModel.prototype._resetOption = function (type, opt) {
  170. var optionChanged = false;
  171. var optionManager = this._optionManager;
  172. if (!type || type === 'recreate') {
  173. var baseOption = optionManager.mountOption(type === 'recreate');
  174. if (process.env.NODE_ENV !== 'production') {
  175. checkMissingComponents(baseOption);
  176. }
  177. if (!this.option || type === 'recreate') {
  178. initBase(this, baseOption);
  179. } else {
  180. this.restoreData();
  181. this._mergeOption(baseOption, opt);
  182. }
  183. optionChanged = true;
  184. }
  185. if (type === 'timeline' || type === 'media') {
  186. this.restoreData();
  187. }
  188. // By design, if `setOption(option2)` at the second time, and `option2` is a `ECUnitOption`,
  189. // it should better not have the same props with `MediaUnit['option']`.
  190. // Because either `option2` or `MediaUnit['option']` will be always merged to "current option"
  191. // rather than original "baseOption". If they both override a prop, the result might be
  192. // unexpected when media state changed after `setOption` called.
  193. // If we really need to modify a props in each `MediaUnit['option']`, use the full version
  194. // (`{baseOption, media}`) in `setOption`.
  195. // For `timeline`, the case is the same.
  196. if (!type || type === 'recreate' || type === 'timeline') {
  197. var timelineOption = optionManager.getTimelineOption(this);
  198. if (timelineOption) {
  199. optionChanged = true;
  200. this._mergeOption(timelineOption, opt);
  201. }
  202. }
  203. if (!type || type === 'recreate' || type === 'media') {
  204. var mediaOptions = optionManager.getMediaOption(this);
  205. if (mediaOptions.length) {
  206. each(mediaOptions, function (mediaOption) {
  207. optionChanged = true;
  208. this._mergeOption(mediaOption, opt);
  209. }, this);
  210. }
  211. }
  212. return optionChanged;
  213. };
  214. GlobalModel.prototype.mergeOption = function (option) {
  215. this._mergeOption(option, null);
  216. };
  217. GlobalModel.prototype._mergeOption = function (newOption, opt) {
  218. var option = this.option;
  219. var componentsMap = this._componentsMap;
  220. var componentsCount = this._componentsCount;
  221. var newCmptTypes = [];
  222. var newCmptTypeMap = createHashMap();
  223. var replaceMergeMainTypeMap = opt && opt.replaceMergeMainTypeMap;
  224. resetSourceDefaulter(this);
  225. // If no component class, merge directly.
  226. // For example: color, animaiton options, etc.
  227. each(newOption, function (componentOption, mainType) {
  228. if (componentOption == null) {
  229. return;
  230. }
  231. if (!ComponentModel.hasClass(mainType)) {
  232. // globalSettingTask.dirty();
  233. option[mainType] = option[mainType] == null ? clone(componentOption) : merge(option[mainType], componentOption, true);
  234. } else if (mainType) {
  235. newCmptTypes.push(mainType);
  236. newCmptTypeMap.set(mainType, true);
  237. }
  238. });
  239. if (replaceMergeMainTypeMap) {
  240. // If there is a mainType `xxx` in `replaceMerge` but not declared in option,
  241. // we trade it as it is declared in option as `{xxx: []}`. Because:
  242. // (1) for normal merge, `{xxx: null/undefined}` are the same meaning as `{xxx: []}`.
  243. // (2) some preprocessor may convert some of `{xxx: null/undefined}` to `{xxx: []}`.
  244. replaceMergeMainTypeMap.each(function (val, mainTypeInReplaceMerge) {
  245. if (ComponentModel.hasClass(mainTypeInReplaceMerge) && !newCmptTypeMap.get(mainTypeInReplaceMerge)) {
  246. newCmptTypes.push(mainTypeInReplaceMerge);
  247. newCmptTypeMap.set(mainTypeInReplaceMerge, true);
  248. }
  249. });
  250. }
  251. ComponentModel.topologicalTravel(newCmptTypes, ComponentModel.getAllClassMainTypes(), visitComponent, this);
  252. function visitComponent(mainType) {
  253. var newCmptOptionList = concatInternalOptions(this, mainType, modelUtil.normalizeToArray(newOption[mainType]));
  254. var oldCmptList = componentsMap.get(mainType);
  255. var mergeMode =
  256. // `!oldCmptList` means init. See the comment in `mappingToExists`
  257. !oldCmptList ? 'replaceAll' : replaceMergeMainTypeMap && replaceMergeMainTypeMap.get(mainType) ? 'replaceMerge' : 'normalMerge';
  258. var mappingResult = modelUtil.mappingToExists(oldCmptList, newCmptOptionList, mergeMode);
  259. // Set mainType and complete subType.
  260. modelUtil.setComponentTypeToKeyInfo(mappingResult, mainType, ComponentModel);
  261. // Empty it before the travel, in order to prevent `this._componentsMap`
  262. // from being used in the `init`/`mergeOption`/`optionUpdated` of some
  263. // components, which is probably incorrect logic.
  264. option[mainType] = null;
  265. componentsMap.set(mainType, null);
  266. componentsCount.set(mainType, 0);
  267. var optionsByMainType = [];
  268. var cmptsByMainType = [];
  269. var cmptsCountByMainType = 0;
  270. var tooltipExists;
  271. var tooltipWarningLogged;
  272. each(mappingResult, function (resultItem, index) {
  273. var componentModel = resultItem.existing;
  274. var newCmptOption = resultItem.newOption;
  275. if (!newCmptOption) {
  276. if (componentModel) {
  277. // Consider where is no new option and should be merged using {},
  278. // see removeEdgeAndAdd in topologicalTravel and
  279. // ComponentModel.getAllClassMainTypes.
  280. componentModel.mergeOption({}, this);
  281. componentModel.optionUpdated({}, false);
  282. }
  283. // If no both `resultItem.exist` and `resultItem.option`,
  284. // either it is in `replaceMerge` and not matched by any id,
  285. // or it has been removed in previous `replaceMerge` and left a "hole" in this component index.
  286. } else {
  287. var isSeriesType = mainType === 'series';
  288. var ComponentModelClass = ComponentModel.getClass(mainType, resultItem.keyInfo.subType, !isSeriesType // Give a more detailed warn later if series don't exists
  289. );
  290. if (!ComponentModelClass) {
  291. if (process.env.NODE_ENV !== 'production') {
  292. var subType = resultItem.keyInfo.subType;
  293. var seriesImportName = BUILTIN_CHARTS_MAP[subType];
  294. if (!componetsMissingLogPrinted[subType]) {
  295. componetsMissingLogPrinted[subType] = true;
  296. if (seriesImportName) {
  297. error("Series " + subType + " is used but not imported.\nimport { " + seriesImportName + " } from 'echarts/charts';\necharts.use([" + seriesImportName + "]);");
  298. } else {
  299. error("Unknown series " + subType);
  300. }
  301. }
  302. }
  303. return;
  304. }
  305. // TODO Before multiple tooltips get supported, we do this check to avoid unexpected exception.
  306. if (mainType === 'tooltip') {
  307. if (tooltipExists) {
  308. if (process.env.NODE_ENV !== 'production') {
  309. if (!tooltipWarningLogged) {
  310. warn('Currently only one tooltip component is allowed.');
  311. tooltipWarningLogged = true;
  312. }
  313. }
  314. return;
  315. }
  316. tooltipExists = true;
  317. }
  318. if (componentModel && componentModel.constructor === ComponentModelClass) {
  319. componentModel.name = resultItem.keyInfo.name;
  320. // componentModel.settingTask && componentModel.settingTask.dirty();
  321. componentModel.mergeOption(newCmptOption, this);
  322. componentModel.optionUpdated(newCmptOption, false);
  323. } else {
  324. // PENDING Global as parent ?
  325. var extraOpt = extend({
  326. componentIndex: index
  327. }, resultItem.keyInfo);
  328. componentModel = new ComponentModelClass(newCmptOption, this, this, extraOpt);
  329. // Assign `keyInfo`
  330. extend(componentModel, extraOpt);
  331. if (resultItem.brandNew) {
  332. componentModel.__requireNewView = true;
  333. }
  334. componentModel.init(newCmptOption, this, this);
  335. // Call optionUpdated after init.
  336. // newCmptOption has been used as componentModel.option
  337. // and may be merged with theme and default, so pass null
  338. // to avoid confusion.
  339. componentModel.optionUpdated(null, true);
  340. }
  341. }
  342. if (componentModel) {
  343. optionsByMainType.push(componentModel.option);
  344. cmptsByMainType.push(componentModel);
  345. cmptsCountByMainType++;
  346. } else {
  347. // Always do assign to avoid elided item in array.
  348. optionsByMainType.push(void 0);
  349. cmptsByMainType.push(void 0);
  350. }
  351. }, this);
  352. option[mainType] = optionsByMainType;
  353. componentsMap.set(mainType, cmptsByMainType);
  354. componentsCount.set(mainType, cmptsCountByMainType);
  355. // Backup series for filtering.
  356. if (mainType === 'series') {
  357. reCreateSeriesIndices(this);
  358. }
  359. }
  360. // If no series declared, ensure `_seriesIndices` initialized.
  361. if (!this._seriesIndices) {
  362. reCreateSeriesIndices(this);
  363. }
  364. };
  365. /**
  366. * Get option for output (cloned option and inner info removed)
  367. */
  368. GlobalModel.prototype.getOption = function () {
  369. var option = clone(this.option);
  370. each(option, function (optInMainType, mainType) {
  371. if (ComponentModel.hasClass(mainType)) {
  372. var opts = modelUtil.normalizeToArray(optInMainType);
  373. // Inner cmpts need to be removed.
  374. // Inner cmpts might not be at last since ec5.0, but still
  375. // compatible for users: if inner cmpt at last, splice the returned array.
  376. var realLen = opts.length;
  377. var metNonInner = false;
  378. for (var i = realLen - 1; i >= 0; i--) {
  379. // Remove options with inner id.
  380. if (opts[i] && !modelUtil.isComponentIdInternal(opts[i])) {
  381. metNonInner = true;
  382. } else {
  383. opts[i] = null;
  384. !metNonInner && realLen--;
  385. }
  386. }
  387. opts.length = realLen;
  388. option[mainType] = opts;
  389. }
  390. });
  391. delete option[OPTION_INNER_KEY];
  392. return option;
  393. };
  394. GlobalModel.prototype.setTheme = function (theme) {
  395. this._theme = new Model(theme);
  396. this._resetOption('recreate', null);
  397. };
  398. GlobalModel.prototype.getTheme = function () {
  399. return this._theme;
  400. };
  401. GlobalModel.prototype.getLocaleModel = function () {
  402. return this._locale;
  403. };
  404. GlobalModel.prototype.setUpdatePayload = function (payload) {
  405. this._payload = payload;
  406. };
  407. GlobalModel.prototype.getUpdatePayload = function () {
  408. return this._payload;
  409. };
  410. /**
  411. * @param idx If not specified, return the first one.
  412. */
  413. GlobalModel.prototype.getComponent = function (mainType, idx) {
  414. var list = this._componentsMap.get(mainType);
  415. if (list) {
  416. var cmpt = list[idx || 0];
  417. if (cmpt) {
  418. return cmpt;
  419. } else if (idx == null) {
  420. for (var i = 0; i < list.length; i++) {
  421. if (list[i]) {
  422. return list[i];
  423. }
  424. }
  425. }
  426. }
  427. };
  428. /**
  429. * @return Never be null/undefined.
  430. */
  431. GlobalModel.prototype.queryComponents = function (condition) {
  432. var mainType = condition.mainType;
  433. if (!mainType) {
  434. return [];
  435. }
  436. var index = condition.index;
  437. var id = condition.id;
  438. var name = condition.name;
  439. var cmpts = this._componentsMap.get(mainType);
  440. if (!cmpts || !cmpts.length) {
  441. return [];
  442. }
  443. var result;
  444. if (index != null) {
  445. result = [];
  446. each(modelUtil.normalizeToArray(index), function (idx) {
  447. cmpts[idx] && result.push(cmpts[idx]);
  448. });
  449. } else if (id != null) {
  450. result = queryByIdOrName('id', id, cmpts);
  451. } else if (name != null) {
  452. result = queryByIdOrName('name', name, cmpts);
  453. } else {
  454. // Return all non-empty components in that mainType
  455. result = filter(cmpts, function (cmpt) {
  456. return !!cmpt;
  457. });
  458. }
  459. return filterBySubType(result, condition);
  460. };
  461. /**
  462. * The interface is different from queryComponents,
  463. * which is convenient for inner usage.
  464. *
  465. * @usage
  466. * let result = findComponents(
  467. * {mainType: 'dataZoom', query: {dataZoomId: 'abc'}}
  468. * );
  469. * let result = findComponents(
  470. * {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}}
  471. * );
  472. * let result = findComponents(
  473. * {mainType: 'series',
  474. * filter: function (model, index) {...}}
  475. * );
  476. * // result like [component0, componnet1, ...]
  477. */
  478. GlobalModel.prototype.findComponents = function (condition) {
  479. var query = condition.query;
  480. var mainType = condition.mainType;
  481. var queryCond = getQueryCond(query);
  482. var result = queryCond ? this.queryComponents(queryCond)
  483. // Retrieve all non-empty components.
  484. : filter(this._componentsMap.get(mainType), function (cmpt) {
  485. return !!cmpt;
  486. });
  487. return doFilter(filterBySubType(result, condition));
  488. function getQueryCond(q) {
  489. var indexAttr = mainType + 'Index';
  490. var idAttr = mainType + 'Id';
  491. var nameAttr = mainType + 'Name';
  492. return q && (q[indexAttr] != null || q[idAttr] != null || q[nameAttr] != null) ? {
  493. mainType: mainType,
  494. // subType will be filtered finally.
  495. index: q[indexAttr],
  496. id: q[idAttr],
  497. name: q[nameAttr]
  498. } : null;
  499. }
  500. function doFilter(res) {
  501. return condition.filter ? filter(res, condition.filter) : res;
  502. }
  503. };
  504. GlobalModel.prototype.eachComponent = function (mainType, cb, context) {
  505. var componentsMap = this._componentsMap;
  506. if (isFunction(mainType)) {
  507. var ctxForAll_1 = cb;
  508. var cbForAll_1 = mainType;
  509. componentsMap.each(function (cmpts, componentType) {
  510. for (var i = 0; cmpts && i < cmpts.length; i++) {
  511. var cmpt = cmpts[i];
  512. cmpt && cbForAll_1.call(ctxForAll_1, componentType, cmpt, cmpt.componentIndex);
  513. }
  514. });
  515. } else {
  516. var cmpts = isString(mainType) ? componentsMap.get(mainType) : isObject(mainType) ? this.findComponents(mainType) : null;
  517. for (var i = 0; cmpts && i < cmpts.length; i++) {
  518. var cmpt = cmpts[i];
  519. cmpt && cb.call(context, cmpt, cmpt.componentIndex);
  520. }
  521. }
  522. };
  523. /**
  524. * Get series list before filtered by name.
  525. */
  526. GlobalModel.prototype.getSeriesByName = function (name) {
  527. var nameStr = modelUtil.convertOptionIdName(name, null);
  528. return filter(this._componentsMap.get('series'), function (oneSeries) {
  529. return !!oneSeries && nameStr != null && oneSeries.name === nameStr;
  530. });
  531. };
  532. /**
  533. * Get series list before filtered by index.
  534. */
  535. GlobalModel.prototype.getSeriesByIndex = function (seriesIndex) {
  536. return this._componentsMap.get('series')[seriesIndex];
  537. };
  538. /**
  539. * Get series list before filtered by type.
  540. * FIXME: rename to getRawSeriesByType?
  541. */
  542. GlobalModel.prototype.getSeriesByType = function (subType) {
  543. return filter(this._componentsMap.get('series'), function (oneSeries) {
  544. return !!oneSeries && oneSeries.subType === subType;
  545. });
  546. };
  547. /**
  548. * Get all series before filtered.
  549. */
  550. GlobalModel.prototype.getSeries = function () {
  551. return filter(this._componentsMap.get('series'), function (oneSeries) {
  552. return !!oneSeries;
  553. });
  554. };
  555. /**
  556. * Count series before filtered.
  557. */
  558. GlobalModel.prototype.getSeriesCount = function () {
  559. return this._componentsCount.get('series');
  560. };
  561. /**
  562. * After filtering, series may be different
  563. * from raw series.
  564. */
  565. GlobalModel.prototype.eachSeries = function (cb, context) {
  566. assertSeriesInitialized(this);
  567. each(this._seriesIndices, function (rawSeriesIndex) {
  568. var series = this._componentsMap.get('series')[rawSeriesIndex];
  569. cb.call(context, series, rawSeriesIndex);
  570. }, this);
  571. };
  572. /**
  573. * Iterate raw series before filtered.
  574. *
  575. * @param {Function} cb
  576. * @param {*} context
  577. */
  578. GlobalModel.prototype.eachRawSeries = function (cb, context) {
  579. each(this._componentsMap.get('series'), function (series) {
  580. series && cb.call(context, series, series.componentIndex);
  581. });
  582. };
  583. /**
  584. * After filtering, series may be different.
  585. * from raw series.
  586. */
  587. GlobalModel.prototype.eachSeriesByType = function (subType, cb, context) {
  588. assertSeriesInitialized(this);
  589. each(this._seriesIndices, function (rawSeriesIndex) {
  590. var series = this._componentsMap.get('series')[rawSeriesIndex];
  591. if (series.subType === subType) {
  592. cb.call(context, series, rawSeriesIndex);
  593. }
  594. }, this);
  595. };
  596. /**
  597. * Iterate raw series before filtered of given type.
  598. */
  599. GlobalModel.prototype.eachRawSeriesByType = function (subType, cb, context) {
  600. return each(this.getSeriesByType(subType), cb, context);
  601. };
  602. GlobalModel.prototype.isSeriesFiltered = function (seriesModel) {
  603. assertSeriesInitialized(this);
  604. return this._seriesIndicesMap.get(seriesModel.componentIndex) == null;
  605. };
  606. GlobalModel.prototype.getCurrentSeriesIndices = function () {
  607. return (this._seriesIndices || []).slice();
  608. };
  609. GlobalModel.prototype.filterSeries = function (cb, context) {
  610. assertSeriesInitialized(this);
  611. var newSeriesIndices = [];
  612. each(this._seriesIndices, function (seriesRawIdx) {
  613. var series = this._componentsMap.get('series')[seriesRawIdx];
  614. cb.call(context, series, seriesRawIdx) && newSeriesIndices.push(seriesRawIdx);
  615. }, this);
  616. this._seriesIndices = newSeriesIndices;
  617. this._seriesIndicesMap = createHashMap(newSeriesIndices);
  618. };
  619. GlobalModel.prototype.restoreData = function (payload) {
  620. reCreateSeriesIndices(this);
  621. var componentsMap = this._componentsMap;
  622. var componentTypes = [];
  623. componentsMap.each(function (components, componentType) {
  624. if (ComponentModel.hasClass(componentType)) {
  625. componentTypes.push(componentType);
  626. }
  627. });
  628. ComponentModel.topologicalTravel(componentTypes, ComponentModel.getAllClassMainTypes(), function (componentType) {
  629. each(componentsMap.get(componentType), function (component) {
  630. if (component && (componentType !== 'series' || !isNotTargetSeries(component, payload))) {
  631. component.restoreData();
  632. }
  633. });
  634. });
  635. };
  636. GlobalModel.internalField = function () {
  637. reCreateSeriesIndices = function (ecModel) {
  638. var seriesIndices = ecModel._seriesIndices = [];
  639. each(ecModel._componentsMap.get('series'), function (series) {
  640. // series may have been removed by `replaceMerge`.
  641. series && seriesIndices.push(series.componentIndex);
  642. });
  643. ecModel._seriesIndicesMap = createHashMap(seriesIndices);
  644. };
  645. assertSeriesInitialized = function (ecModel) {
  646. // Components that use _seriesIndices should depends on series component,
  647. // which make sure that their initialization is after series.
  648. if (process.env.NODE_ENV !== 'production') {
  649. if (!ecModel._seriesIndices) {
  650. throw new Error('Option should contains series.');
  651. }
  652. }
  653. };
  654. initBase = function (ecModel, baseOption) {
  655. // Using OPTION_INNER_KEY to mark that this option cannot be used outside,
  656. // i.e. `chart.setOption(chart.getModel().option);` is forbidden.
  657. ecModel.option = {};
  658. ecModel.option[OPTION_INNER_KEY] = OPTION_INNER_VALUE;
  659. // Init with series: [], in case of calling findSeries method
  660. // before series initialized.
  661. ecModel._componentsMap = createHashMap({
  662. series: []
  663. });
  664. ecModel._componentsCount = createHashMap();
  665. // If user spefied `option.aria`, aria will be enable. This detection should be
  666. // performed before theme and globalDefault merge.
  667. var airaOption = baseOption.aria;
  668. if (isObject(airaOption) && airaOption.enabled == null) {
  669. airaOption.enabled = true;
  670. }
  671. mergeTheme(baseOption, ecModel._theme.option);
  672. // TODO Needs clone when merging to the unexisted property
  673. merge(baseOption, globalDefault, false);
  674. ecModel._mergeOption(baseOption, null);
  675. };
  676. }();
  677. return GlobalModel;
  678. }(Model);
  679. function isNotTargetSeries(seriesModel, payload) {
  680. if (payload) {
  681. var index = payload.seriesIndex;
  682. var id = payload.seriesId;
  683. var name_1 = payload.seriesName;
  684. return index != null && seriesModel.componentIndex !== index || id != null && seriesModel.id !== id || name_1 != null && seriesModel.name !== name_1;
  685. }
  686. }
  687. function mergeTheme(option, theme) {
  688. // PENDING
  689. // NOT use `colorLayer` in theme if option has `color`
  690. var notMergeColorLayer = option.color && !option.colorLayer;
  691. each(theme, function (themeItem, name) {
  692. if (name === 'colorLayer' && notMergeColorLayer || name === 'color' && option.color) {
  693. return;
  694. }
  695. // If it is component model mainType, the model handles that merge later.
  696. // otherwise, merge them here.
  697. if (!ComponentModel.hasClass(name)) {
  698. if (typeof themeItem === 'object') {
  699. option[name] = !option[name] ? clone(themeItem) : merge(option[name], themeItem, false);
  700. } else {
  701. if (option[name] == null) {
  702. option[name] = themeItem;
  703. }
  704. }
  705. }
  706. });
  707. }
  708. function queryByIdOrName(attr, idOrName, cmpts) {
  709. // Here is a break from echarts4: string and number are
  710. // treated as equal.
  711. if (isArray(idOrName)) {
  712. var keyMap_1 = createHashMap();
  713. each(idOrName, function (idOrNameItem) {
  714. if (idOrNameItem != null) {
  715. var idName = modelUtil.convertOptionIdName(idOrNameItem, null);
  716. idName != null && keyMap_1.set(idOrNameItem, true);
  717. }
  718. });
  719. return filter(cmpts, function (cmpt) {
  720. return cmpt && keyMap_1.get(cmpt[attr]);
  721. });
  722. } else {
  723. var idName_1 = modelUtil.convertOptionIdName(idOrName, null);
  724. return filter(cmpts, function (cmpt) {
  725. return cmpt && idName_1 != null && cmpt[attr] === idName_1;
  726. });
  727. }
  728. }
  729. function filterBySubType(components, condition) {
  730. // Using hasOwnProperty for restrict. Consider
  731. // subType is undefined in user payload.
  732. return condition.hasOwnProperty('subType') ? filter(components, function (cmpt) {
  733. return cmpt && cmpt.subType === condition.subType;
  734. }) : components;
  735. }
  736. function normalizeSetOptionInput(opts) {
  737. var replaceMergeMainTypeMap = createHashMap();
  738. opts && each(modelUtil.normalizeToArray(opts.replaceMerge), function (mainType) {
  739. if (process.env.NODE_ENV !== 'production') {
  740. assert(ComponentModel.hasClass(mainType), '"' + mainType + '" is not valid component main type in "replaceMerge"');
  741. }
  742. replaceMergeMainTypeMap.set(mainType, true);
  743. });
  744. return {
  745. replaceMergeMainTypeMap: replaceMergeMainTypeMap
  746. };
  747. }
  748. mixin(GlobalModel, PaletteMixin);
  749. export default GlobalModel;