linkList.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. var zrUtil = require("zrender/lib/core/util");
  2. /**
  3. * Link lists and struct (graph or tree)
  4. */
  5. var each = zrUtil.each;
  6. var DATAS = '\0__link_datas';
  7. var MAIN_DATA = '\0__link_mainData'; // Caution:
  8. // In most case, either list or its shallow clones (see list.cloneShallow)
  9. // is active in echarts process. So considering heap memory consumption,
  10. // we do not clone tree or graph, but share them among list and its shallow clones.
  11. // But in some rare case, we have to keep old list (like do animation in chart). So
  12. // please take care that both the old list and the new list share the same tree/graph.
  13. /**
  14. * @param {Object} opt
  15. * @param {module:echarts/data/List} opt.mainData
  16. * @param {Object} [opt.struct] For example, instance of Graph or Tree.
  17. * @param {string} [opt.structAttr] designation: list[structAttr] = struct;
  18. * @param {Object} [opt.datas] {dataType: data},
  19. * like: {node: nodeList, edge: edgeList}.
  20. * Should contain mainData.
  21. * @param {Object} [opt.datasAttr] {dataType: attr},
  22. * designation: struct[datasAttr[dataType]] = list;
  23. */
  24. function linkList(opt) {
  25. var mainData = opt.mainData;
  26. var datas = opt.datas;
  27. if (!datas) {
  28. datas = {
  29. main: mainData
  30. };
  31. opt.datasAttr = {
  32. main: 'data'
  33. };
  34. }
  35. opt.datas = opt.mainData = null;
  36. linkAll(mainData, datas, opt); // Porxy data original methods.
  37. each(datas, function (data) {
  38. each(mainData.TRANSFERABLE_METHODS, function (methodName) {
  39. data.wrapMethod(methodName, zrUtil.curry(transferInjection, opt));
  40. });
  41. }); // Beyond transfer, additional features should be added to `cloneShallow`.
  42. mainData.wrapMethod('cloneShallow', zrUtil.curry(cloneShallowInjection, opt)); // Only mainData trigger change, because struct.update may trigger
  43. // another changable methods, which may bring about dead lock.
  44. each(mainData.CHANGABLE_METHODS, function (methodName) {
  45. mainData.wrapMethod(methodName, zrUtil.curry(changeInjection, opt));
  46. }); // Make sure datas contains mainData.
  47. zrUtil.assert(datas[mainData.dataType] === mainData);
  48. }
  49. function transferInjection(opt, res) {
  50. if (isMainData(this)) {
  51. // Transfer datas to new main data.
  52. var datas = zrUtil.extend({}, this[DATAS]);
  53. datas[this.dataType] = res;
  54. linkAll(res, datas, opt);
  55. } else {
  56. // Modify the reference in main data to point newData.
  57. linkSingle(res, this.dataType, this[MAIN_DATA], opt);
  58. }
  59. return res;
  60. }
  61. function changeInjection(opt, res) {
  62. opt.struct && opt.struct.update(this);
  63. return res;
  64. }
  65. function cloneShallowInjection(opt, res) {
  66. // cloneShallow, which brings about some fragilities, may be inappropriate
  67. // to be exposed as an API. So for implementation simplicity we can make
  68. // the restriction that cloneShallow of not-mainData should not be invoked
  69. // outside, but only be invoked here.
  70. each(res[DATAS], function (data, dataType) {
  71. data !== res && linkSingle(data.cloneShallow(), dataType, res, opt);
  72. });
  73. return res;
  74. }
  75. /**
  76. * Supplement method to List.
  77. *
  78. * @public
  79. * @param {string} [dataType] If not specified, return mainData.
  80. * @return {module:echarts/data/List}
  81. */
  82. function getLinkedData(dataType) {
  83. var mainData = this[MAIN_DATA];
  84. return dataType == null || mainData == null ? mainData : mainData[DATAS][dataType];
  85. }
  86. function isMainData(data) {
  87. return data[MAIN_DATA] === data;
  88. }
  89. function linkAll(mainData, datas, opt) {
  90. mainData[DATAS] = {};
  91. each(datas, function (data, dataType) {
  92. linkSingle(data, dataType, mainData, opt);
  93. });
  94. }
  95. function linkSingle(data, dataType, mainData, opt) {
  96. mainData[DATAS][dataType] = data;
  97. data[MAIN_DATA] = mainData;
  98. data.dataType = dataType;
  99. if (opt.struct) {
  100. data[opt.structAttr] = opt.struct;
  101. opt.struct[opt.datasAttr[dataType]] = data;
  102. } // Supplement method.
  103. data.getLinkedData = getLinkedData;
  104. }
  105. var _default = linkList;
  106. module.exports = _default;