completeDimensions.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. var zrUtil = require("zrender/lib/core/util");
  2. var _model = require("../../util/model");
  3. var normalizeToArray = _model.normalizeToArray;
  4. /**
  5. * Complete dimensions by data (guess dimension).
  6. */
  7. var each = zrUtil.each;
  8. var isString = zrUtil.isString;
  9. var defaults = zrUtil.defaults;
  10. var OTHER_DIMS = {
  11. tooltip: 1,
  12. label: 1,
  13. itemName: 1
  14. };
  15. /**
  16. * Complete the dimensions array, by user defined `dimension` and `encode`,
  17. * and guessing from the data structure.
  18. * If no 'value' dimension specified, the first no-named dimension will be
  19. * named as 'value'.
  20. *
  21. * @param {Array.<string>} sysDims Necessary dimensions, like ['x', 'y'], which
  22. * provides not only dim template, but also default order.
  23. * `name` of each item provides default coord name.
  24. * [{dimsDef: []}, ...] can be specified to give names.
  25. * @param {Array} data Data list. [[1, 2, 3], [2, 3, 4]].
  26. * @param {Object} [opt]
  27. * @param {Array.<Object|string>} [opt.dimsDef] option.series.dimensions User defined dimensions
  28. * For example: ['asdf', {name, type}, ...].
  29. * @param {Object} [opt.encodeDef] option.series.encode {x: 2, y: [3, 1], tooltip: [1, 2], label: 3}
  30. * @param {string} [opt.extraPrefix] Prefix of name when filling the left dimensions.
  31. * @param {string} [opt.extraFromZero] If specified, extra dim names will be:
  32. * extraPrefix + 0, extraPrefix + extraBaseIndex + 1 ...
  33. * If not specified, extra dim names will be:
  34. * extraPrefix, extraPrefix + 0, extraPrefix + 1 ...
  35. * @param {number} [opt.dimCount] If not specified, guess by the first data item.
  36. * @return {Array.<Object>} [{
  37. * name: string mandatory,
  38. * coordDim: string mandatory,
  39. * coordDimIndex: number mandatory,
  40. * type: string optional,
  41. * tooltipName: string optional,
  42. * otherDims: {
  43. * tooltip: number optional,
  44. * label: number optional
  45. * },
  46. * isExtraCoord: boolean true or undefined.
  47. * other props ...
  48. * }]
  49. */
  50. function completeDimensions(sysDims, data, opt) {
  51. data = data || [];
  52. opt = opt || {};
  53. sysDims = (sysDims || []).slice();
  54. var dimsDef = (opt.dimsDef || []).slice();
  55. var encodeDef = zrUtil.createHashMap(opt.encodeDef);
  56. var dataDimNameMap = zrUtil.createHashMap();
  57. var coordDimNameMap = zrUtil.createHashMap(); // var valueCandidate;
  58. var result = [];
  59. var dimCount = opt.dimCount;
  60. if (dimCount == null) {
  61. var value0 = retrieveValue(data[0]);
  62. dimCount = Math.max(zrUtil.isArray(value0) && value0.length || 1, sysDims.length, dimsDef.length);
  63. each(sysDims, function (sysDimItem) {
  64. var sysDimItemDimsDef = sysDimItem.dimsDef;
  65. sysDimItemDimsDef && (dimCount = Math.max(dimCount, sysDimItemDimsDef.length));
  66. });
  67. } // Apply user defined dims (`name` and `type`) and init result.
  68. for (var i = 0; i < dimCount; i++) {
  69. var dimDefItem = isString(dimsDef[i]) ? {
  70. name: dimsDef[i]
  71. } : dimsDef[i] || {};
  72. var userDimName = dimDefItem.name;
  73. var resultItem = result[i] = {
  74. otherDims: {}
  75. }; // Name will be applied later for avoiding duplication.
  76. if (userDimName != null && dataDimNameMap.get(userDimName) == null) {
  77. // Only if `series.dimensions` is defined in option, tooltipName
  78. // will be set, and dimension will be diplayed vertically in
  79. // tooltip by default.
  80. resultItem.name = resultItem.tooltipName = userDimName;
  81. dataDimNameMap.set(userDimName, i);
  82. }
  83. dimDefItem.type != null && (resultItem.type = dimDefItem.type);
  84. } // Set `coordDim` and `coordDimIndex` by `encodeDef` and normalize `encodeDef`.
  85. encodeDef.each(function (dataDims, coordDim) {
  86. dataDims = encodeDef.set(coordDim, normalizeToArray(dataDims).slice());
  87. each(dataDims, function (resultDimIdx, coordDimIndex) {
  88. // The input resultDimIdx can be dim name or index.
  89. isString(resultDimIdx) && (resultDimIdx = dataDimNameMap.get(resultDimIdx));
  90. if (resultDimIdx != null && resultDimIdx < dimCount) {
  91. dataDims[coordDimIndex] = resultDimIdx;
  92. applyDim(result[resultDimIdx], coordDim, coordDimIndex);
  93. }
  94. });
  95. }); // Apply templetes and default order from `sysDims`.
  96. var availDimIdx = 0;
  97. each(sysDims, function (sysDimItem, sysDimIndex) {
  98. var coordDim;
  99. var sysDimItem;
  100. var sysDimItemDimsDef;
  101. var sysDimItemOtherDims;
  102. if (isString(sysDimItem)) {
  103. coordDim = sysDimItem;
  104. sysDimItem = {};
  105. } else {
  106. coordDim = sysDimItem.name;
  107. sysDimItem = zrUtil.clone(sysDimItem); // `coordDimIndex` should not be set directly.
  108. sysDimItemDimsDef = sysDimItem.dimsDef;
  109. sysDimItemOtherDims = sysDimItem.otherDims;
  110. sysDimItem.name = sysDimItem.coordDim = sysDimItem.coordDimIndex = sysDimItem.dimsDef = sysDimItem.otherDims = null;
  111. }
  112. var dataDims = normalizeToArray(encodeDef.get(coordDim)); // dimensions provides default dim sequences.
  113. if (!dataDims.length) {
  114. for (var i = 0; i < (sysDimItemDimsDef && sysDimItemDimsDef.length || 1); i++) {
  115. while (availDimIdx < result.length && result[availDimIdx].coordDim != null) {
  116. availDimIdx++;
  117. }
  118. availDimIdx < result.length && dataDims.push(availDimIdx++);
  119. }
  120. } // Apply templates.
  121. each(dataDims, function (resultDimIdx, coordDimIndex) {
  122. var resultItem = result[resultDimIdx];
  123. applyDim(defaults(resultItem, sysDimItem), coordDim, coordDimIndex);
  124. if (resultItem.name == null && sysDimItemDimsDef) {
  125. resultItem.name = resultItem.tooltipName = sysDimItemDimsDef[coordDimIndex];
  126. }
  127. sysDimItemOtherDims && defaults(resultItem.otherDims, sysDimItemOtherDims);
  128. });
  129. }); // Make sure the first extra dim is 'value'.
  130. var extra = opt.extraPrefix || 'value'; // Set dim `name` and other `coordDim` and other props.
  131. for (var resultDimIdx = 0; resultDimIdx < dimCount; resultDimIdx++) {
  132. var resultItem = result[resultDimIdx] = result[resultDimIdx] || {};
  133. var coordDim = resultItem.coordDim;
  134. coordDim == null && (resultItem.coordDim = genName(extra, coordDimNameMap, opt.extraFromZero), resultItem.coordDimIndex = 0, resultItem.isExtraCoord = true);
  135. resultItem.name == null && (resultItem.name = genName(resultItem.coordDim, dataDimNameMap));
  136. resultItem.type == null && guessOrdinal(data, resultDimIdx) && (resultItem.type = 'ordinal');
  137. }
  138. return result;
  139. function applyDim(resultItem, coordDim, coordDimIndex) {
  140. if (OTHER_DIMS[coordDim]) {
  141. resultItem.otherDims[coordDim] = coordDimIndex;
  142. } else {
  143. resultItem.coordDim = coordDim;
  144. resultItem.coordDimIndex = coordDimIndex;
  145. coordDimNameMap.set(coordDim, true);
  146. }
  147. }
  148. function genName(name, map, fromZero) {
  149. if (fromZero || map.get(name) != null) {
  150. var i = 0;
  151. while (map.get(name + i) != null) {
  152. i++;
  153. }
  154. name += i;
  155. }
  156. map.set(name, true);
  157. return name;
  158. }
  159. } // The rule should not be complex, otherwise user might not
  160. // be able to known where the data is wrong.
  161. var guessOrdinal = completeDimensions.guessOrdinal = function (data, dimIndex) {
  162. for (var i = 0, len = data.length; i < len; i++) {
  163. var value = retrieveValue(data[i]);
  164. if (!zrUtil.isArray(value)) {
  165. return false;
  166. }
  167. var value = value[dimIndex]; // Consider usage convenience, '1', '2' will be treated as "number".
  168. // `isFinit('')` get `true`.
  169. if (value != null && isFinite(value) && value !== '') {
  170. return false;
  171. } else if (isString(value) && value !== '-') {
  172. return true;
  173. }
  174. }
  175. return false;
  176. };
  177. function retrieveValue(o) {
  178. return zrUtil.isArray(o) ? o : zrUtil.isObject(o) ? o.value : o;
  179. }
  180. var _default = completeDimensions;
  181. module.exports = _default;