data.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. import CLASS from './class';
  2. import { c3_chart_internal_fn } from './core';
  3. import { isValue, isFunction, isArray, notEmpty, hasValue } from './util';
  4. c3_chart_internal_fn.isX = function (key) {
  5. var $$ = this, config = $$.config;
  6. return (config.data_x && key === config.data_x) || (notEmpty(config.data_xs) && hasValue(config.data_xs, key));
  7. };
  8. c3_chart_internal_fn.isNotX = function (key) {
  9. return !this.isX(key);
  10. };
  11. c3_chart_internal_fn.getXKey = function (id) {
  12. var $$ = this, config = $$.config;
  13. return config.data_x ? config.data_x : notEmpty(config.data_xs) ? config.data_xs[id] : null;
  14. };
  15. c3_chart_internal_fn.getXValuesOfXKey = function (key, targets) {
  16. var $$ = this,
  17. xValues, ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : [];
  18. ids.forEach(function (id) {
  19. if ($$.getXKey(id) === key) {
  20. xValues = $$.data.xs[id];
  21. }
  22. });
  23. return xValues;
  24. };
  25. c3_chart_internal_fn.getXValue = function (id, i) {
  26. var $$ = this;
  27. return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i]) ? $$.data.xs[id][i] : i;
  28. };
  29. c3_chart_internal_fn.getOtherTargetXs = function () {
  30. var $$ = this,
  31. idsForX = Object.keys($$.data.xs);
  32. return idsForX.length ? $$.data.xs[idsForX[0]] : null;
  33. };
  34. c3_chart_internal_fn.getOtherTargetX = function (index) {
  35. var xs = this.getOtherTargetXs();
  36. return xs && index < xs.length ? xs[index] : null;
  37. };
  38. c3_chart_internal_fn.addXs = function (xs) {
  39. var $$ = this;
  40. Object.keys(xs).forEach(function (id) {
  41. $$.config.data_xs[id] = xs[id];
  42. });
  43. };
  44. c3_chart_internal_fn.addName = function (data) {
  45. var $$ = this, name;
  46. if (data) {
  47. name = $$.config.data_names[data.id];
  48. data.name = name !== undefined ? name : data.id;
  49. }
  50. return data;
  51. };
  52. c3_chart_internal_fn.getValueOnIndex = function (values, index) {
  53. var valueOnIndex = values.filter(function (v) { return v.index === index; });
  54. return valueOnIndex.length ? valueOnIndex[0] : null;
  55. };
  56. c3_chart_internal_fn.updateTargetX = function (targets, x) {
  57. var $$ = this;
  58. targets.forEach(function (t) {
  59. t.values.forEach(function (v, i) {
  60. v.x = $$.generateTargetX(x[i], t.id, i);
  61. });
  62. $$.data.xs[t.id] = x;
  63. });
  64. };
  65. c3_chart_internal_fn.updateTargetXs = function (targets, xs) {
  66. var $$ = this;
  67. targets.forEach(function (t) {
  68. if (xs[t.id]) {
  69. $$.updateTargetX([t], xs[t.id]);
  70. }
  71. });
  72. };
  73. c3_chart_internal_fn.generateTargetX = function (rawX, id, index) {
  74. var $$ = this, x;
  75. if ($$.isTimeSeries()) {
  76. x = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index));
  77. }
  78. else if ($$.isCustomX() && !$$.isCategorized()) {
  79. x = isValue(rawX) ? +rawX : $$.getXValue(id, index);
  80. }
  81. else {
  82. x = index;
  83. }
  84. return x;
  85. };
  86. c3_chart_internal_fn.cloneTarget = function (target) {
  87. return {
  88. id : target.id,
  89. id_org : target.id_org,
  90. values : target.values.map(function (d) {
  91. return {x: d.x, value: d.value, id: d.id};
  92. })
  93. };
  94. };
  95. c3_chart_internal_fn.getMaxDataCount = function () {
  96. var $$ = this;
  97. return $$.d3.max($$.data.targets, function (t) { return t.values.length; });
  98. };
  99. c3_chart_internal_fn.mapToIds = function (targets) {
  100. return targets.map(function (d) { return d.id; });
  101. };
  102. c3_chart_internal_fn.mapToTargetIds = function (ids) {
  103. var $$ = this;
  104. return ids ? [].concat(ids) : $$.mapToIds($$.data.targets);
  105. };
  106. c3_chart_internal_fn.hasTarget = function (targets, id) {
  107. var ids = this.mapToIds(targets), i;
  108. for (i = 0; i < ids.length; i++) {
  109. if (ids[i] === id) {
  110. return true;
  111. }
  112. }
  113. return false;
  114. };
  115. c3_chart_internal_fn.isTargetToShow = function (targetId) {
  116. return this.hiddenTargetIds.indexOf(targetId) < 0;
  117. };
  118. c3_chart_internal_fn.isLegendToShow = function (targetId) {
  119. return this.hiddenLegendIds.indexOf(targetId) < 0;
  120. };
  121. c3_chart_internal_fn.filterTargetsToShow = function (targets) {
  122. var $$ = this;
  123. return targets.filter(function (t) { return $$.isTargetToShow(t.id); });
  124. };
  125. c3_chart_internal_fn.mapTargetsToUniqueXs = function (targets) {
  126. var $$ = this;
  127. var xs = $$.d3.set($$.d3.merge(targets.map(function (t) { return t.values.map(function (v) { return +v.x; }); }))).values();
  128. xs = $$.isTimeSeries() ? xs.map(function (x) { return new Date(+x); }) : xs.map(function (x) { return +x; });
  129. return xs.sort(function (a, b) { return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; });
  130. };
  131. c3_chart_internal_fn.addHiddenTargetIds = function (targetIds) {
  132. targetIds = (targetIds instanceof Array) ? targetIds : new Array(targetIds);
  133. for (var i = 0; i < targetIds.length; i++) {
  134. if (this.hiddenTargetIds.indexOf(targetIds[i]) < 0) {
  135. this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds[i]);
  136. }
  137. }
  138. };
  139. c3_chart_internal_fn.removeHiddenTargetIds = function (targetIds) {
  140. this.hiddenTargetIds = this.hiddenTargetIds.filter(function (id) { return targetIds.indexOf(id) < 0; });
  141. };
  142. c3_chart_internal_fn.addHiddenLegendIds = function (targetIds) {
  143. targetIds = (targetIds instanceof Array) ? targetIds : new Array(targetIds);
  144. for (var i = 0; i < targetIds.length; i++) {
  145. if (this.hiddenLegendIds.indexOf(targetIds[i]) < 0) {
  146. this.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds[i]);
  147. }
  148. }
  149. };
  150. c3_chart_internal_fn.removeHiddenLegendIds = function (targetIds) {
  151. this.hiddenLegendIds = this.hiddenLegendIds.filter(function (id) { return targetIds.indexOf(id) < 0; });
  152. };
  153. c3_chart_internal_fn.getValuesAsIdKeyed = function (targets) {
  154. var ys = {};
  155. targets.forEach(function (t) {
  156. ys[t.id] = [];
  157. t.values.forEach(function (v) {
  158. ys[t.id].push(v.value);
  159. });
  160. });
  161. return ys;
  162. };
  163. c3_chart_internal_fn.checkValueInTargets = function (targets, checker) {
  164. var ids = Object.keys(targets), i, j, values;
  165. for (i = 0; i < ids.length; i++) {
  166. values = targets[ids[i]].values;
  167. for (j = 0; j < values.length; j++) {
  168. if (checker(values[j].value)) {
  169. return true;
  170. }
  171. }
  172. }
  173. return false;
  174. };
  175. c3_chart_internal_fn.hasNegativeValueInTargets = function (targets) {
  176. return this.checkValueInTargets(targets, function (v) { return v < 0; });
  177. };
  178. c3_chart_internal_fn.hasPositiveValueInTargets = function (targets) {
  179. return this.checkValueInTargets(targets, function (v) { return v > 0; });
  180. };
  181. c3_chart_internal_fn.isOrderDesc = function () {
  182. var config = this.config;
  183. return typeof(config.data_order) === 'string' && config.data_order.toLowerCase() === 'desc';
  184. };
  185. c3_chart_internal_fn.isOrderAsc = function () {
  186. var config = this.config;
  187. return typeof(config.data_order) === 'string' && config.data_order.toLowerCase() === 'asc';
  188. };
  189. c3_chart_internal_fn.getOrderFunction = function() {
  190. var $$ = this, config = $$.config, orderAsc = $$.isOrderAsc(), orderDesc = $$.isOrderDesc();
  191. if (orderAsc || orderDesc) {
  192. var reducer = function (p, c) { return p + Math.abs(c.value); };
  193. return function (t1, t2) {
  194. var t1Sum = t1.values.reduce(reducer, 0),
  195. t2Sum = t2.values.reduce(reducer, 0);
  196. return orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum;
  197. };
  198. } else if (isFunction(config.data_order)) {
  199. return config.data_order;
  200. } else if (isArray(config.data_order)) {
  201. var order = config.data_order;
  202. return function (t1, t2) {
  203. return order.indexOf(t1.id) - order.indexOf(t2.id);
  204. };
  205. }
  206. };
  207. c3_chart_internal_fn.orderTargets = function (targets) {
  208. var fct = this.getOrderFunction();
  209. if (fct) {
  210. targets.sort(fct);
  211. }
  212. return targets;
  213. };
  214. c3_chart_internal_fn.filterByX = function (targets, x) {
  215. return this.d3.merge(targets.map(function (t) { return t.values; })).filter(function (v) { return v.x - x === 0; });
  216. };
  217. c3_chart_internal_fn.filterRemoveNull = function (data) {
  218. return data.filter(function (d) { return isValue(d.value); });
  219. };
  220. c3_chart_internal_fn.filterByXDomain = function (targets, xDomain) {
  221. return targets.map(function (t) {
  222. return {
  223. id: t.id,
  224. id_org: t.id_org,
  225. values: t.values.filter(function (v) {
  226. return xDomain[0] <= v.x && v.x <= xDomain[1];
  227. })
  228. };
  229. });
  230. };
  231. c3_chart_internal_fn.hasDataLabel = function () {
  232. var config = this.config;
  233. if (typeof config.data_labels === 'boolean' && config.data_labels) {
  234. return true;
  235. } else if (typeof config.data_labels === 'object' && notEmpty(config.data_labels)) {
  236. return true;
  237. }
  238. return false;
  239. };
  240. c3_chart_internal_fn.getDataLabelLength = function (min, max, key) {
  241. var $$ = this,
  242. lengths = [0, 0], paddingCoef = 1.3;
  243. $$.selectChart.select('svg').selectAll('.dummy')
  244. .data([min, max])
  245. .enter().append('text')
  246. .text(function (d) { return $$.dataLabelFormat(d.id)(d); })
  247. .each(function (d, i) {
  248. lengths[i] = this.getBoundingClientRect()[key] * paddingCoef;
  249. })
  250. .remove();
  251. return lengths;
  252. };
  253. c3_chart_internal_fn.isNoneArc = function (d) {
  254. return this.hasTarget(this.data.targets, d.id);
  255. },
  256. c3_chart_internal_fn.isArc = function (d) {
  257. return 'data' in d && this.hasTarget(this.data.targets, d.data.id);
  258. };
  259. c3_chart_internal_fn.findClosestFromTargets = function (targets, pos) {
  260. var $$ = this, candidates;
  261. // map to array of closest points of each target
  262. candidates = targets.map(function (target) {
  263. return $$.findClosest(target.values, pos);
  264. });
  265. // decide closest point and return
  266. return $$.findClosest(candidates, pos);
  267. };
  268. c3_chart_internal_fn.findClosest = function (values, pos) {
  269. var $$ = this, minDist = $$.config.point_sensitivity, closest;
  270. // find mouseovering bar
  271. values.filter(function (v) { return v && $$.isBarType(v.id); }).forEach(function (v) {
  272. var shape = $$.main.select('.' + CLASS.bars + $$.getTargetSelectorSuffix(v.id) + ' .' + CLASS.bar + '-' + v.index).node();
  273. if (!closest && $$.isWithinBar($$.d3.mouse(shape), shape)) {
  274. closest = v;
  275. }
  276. });
  277. // find closest point from non-bar
  278. values.filter(function (v) { return v && !$$.isBarType(v.id); }).forEach(function (v) {
  279. var d = $$.dist(v, pos);
  280. if (d < minDist) {
  281. minDist = d;
  282. closest = v;
  283. }
  284. });
  285. return closest;
  286. };
  287. c3_chart_internal_fn.dist = function (data, pos) {
  288. var $$ = this, config = $$.config,
  289. xIndex = config.axis_rotated ? 1 : 0,
  290. yIndex = config.axis_rotated ? 0 : 1,
  291. y = $$.circleY(data, data.index),
  292. x = $$.x(data.x);
  293. return Math.sqrt(Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2));
  294. };
  295. c3_chart_internal_fn.convertValuesToStep = function (values) {
  296. var converted = [].concat(values), i;
  297. if (!this.isCategorized()) {
  298. return values;
  299. }
  300. for (i = values.length + 1; 0 < i; i--) {
  301. converted[i] = converted[i - 1];
  302. }
  303. converted[0] = {
  304. x: converted[0].x - 1,
  305. value: converted[0].value,
  306. id: converted[0].id
  307. };
  308. converted[values.length + 1] = {
  309. x: converted[values.length].x + 1,
  310. value: converted[values.length].value,
  311. id: converted[values.length].id
  312. };
  313. return converted;
  314. };
  315. c3_chart_internal_fn.updateDataAttributes = function (name, attrs) {
  316. var $$ = this, config = $$.config, current = config['data_' + name];
  317. if (typeof attrs === 'undefined') { return current; }
  318. Object.keys(attrs).forEach(function (id) {
  319. current[id] = attrs[id];
  320. });
  321. $$.redraw({withLegend: true});
  322. return current;
  323. };