UNPKG

39.5 kBJavaScriptView Raw
1/*!
2* Copyright (c) 2017 ~ present NAVER Corp.
3 * billboard.js project is licensed under the MIT license
4 *
5 * billboard.js, JavaScript chart library
6 * https://naver.github.io/billboard.js/
7 *
8 * @version 3.0.2
9 * @requires billboard.js
10 * @summary billboard.js plugin
11*/
12import { interpolateHslLong } from 'd3-interpolate';
13import { hsl } from 'd3-color';
14import { scaleSequential, scaleLog, scaleSequentialLog } from 'd3-scale';
15import 'd3-selection';
16import 'd3-brush';
17import { axisRight } from 'd3-axis';
18import { format } from 'd3-format';
19
20/*! *****************************************************************************
21Copyright (c) Microsoft Corporation.
22
23Permission to use, copy, modify, and/or distribute this software for any
24purpose with or without fee is hereby granted.
25
26THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
27REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
28AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
29INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
30LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
31OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
32PERFORMANCE OF THIS SOFTWARE.
33***************************************************************************** */
34
35/* global Reflect, Promise */
36var _extendStatics = function extendStatics(d, b) {
37 return _extendStatics = Object.setPrototypeOf || {
38 __proto__: []
39 } instanceof Array && function (d, b) {
40 d.__proto__ = b;
41 } || function (d, b) {
42 for (var p in b) Object.prototype.hasOwnProperty.call(b, p) && (d[p] = b[p]);
43 }, _extendStatics(d, b);
44};
45
46function __extends(d, b) {
47 function __() {
48 this.constructor = d;
49 }
50
51 if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + (b + "") + " is not a constructor or null");
52 _extendStatics(d, b), d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
53}
54function __spreadArray(to, from) {
55 for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) to[j] = from[i];
56
57 return to;
58}
59
60/**
61 * Copyright (c) 2017 ~ present NAVER Corp.
62 * billboard.js project is licensed under the MIT license
63 */
64/**
65 * CSS class names definition
66 * @private
67 */
68var CLASS$1 = {
69 arc: "bb-arc",
70 arcLabelLine: "bb-arc-label-line",
71 arcs: "bb-arcs",
72 area: "bb-area",
73 areas: "bb-areas",
74 axis: "bb-axis",
75 axisX: "bb-axis-x",
76 axisXLabel: "bb-axis-x-label",
77 axisY: "bb-axis-y",
78 axisY2: "bb-axis-y2",
79 axisY2Label: "bb-axis-y2-label",
80 axisYLabel: "bb-axis-y-label",
81 bar: "bb-bar",
82 bars: "bb-bars",
83 brush: "bb-brush",
84 button: "bb-button",
85 buttonZoomReset: "bb-zoom-reset",
86 candlestick: "bb-candlestick",
87 candlesticks: "bb-candlesticks",
88 chart: "bb-chart",
89 chartArc: "bb-chart-arc",
90 chartArcs: "bb-chart-arcs",
91 chartArcsBackground: "bb-chart-arcs-background",
92 chartArcsGaugeMax: "bb-chart-arcs-gauge-max",
93 chartArcsGaugeMin: "bb-chart-arcs-gauge-min",
94 chartArcsGaugeUnit: "bb-chart-arcs-gauge-unit",
95 chartArcsTitle: "bb-chart-arcs-title",
96 chartArcsGaugeTitle: "bb-chart-arcs-gauge-title",
97 chartBar: "bb-chart-bar",
98 chartBars: "bb-chart-bars",
99 chartCandlestick: "bb-chart-candlestick",
100 chartCandlesticks: "bb-chart-candlesticks",
101 chartCircles: "bb-chart-circles",
102 chartLine: "bb-chart-line",
103 chartLines: "bb-chart-lines",
104 chartRadar: "bb-chart-radar",
105 chartRadars: "bb-chart-radars",
106 chartText: "bb-chart-text",
107 chartTexts: "bb-chart-texts",
108 circle: "bb-circle",
109 circles: "bb-circles",
110 colorPattern: "bb-color-pattern",
111 colorScale: "bb-colorscale",
112 defocused: "bb-defocused",
113 dragarea: "bb-dragarea",
114 empty: "bb-empty",
115 eventRect: "bb-event-rect",
116 eventRects: "bb-event-rects",
117 eventRectsMultiple: "bb-event-rects-multiple",
118 eventRectsSingle: "bb-event-rects-single",
119 focused: "bb-focused",
120 gaugeValue: "bb-gauge-value",
121 grid: "bb-grid",
122 gridLines: "bb-grid-lines",
123 legend: "bb-legend",
124 legendBackground: "bb-legend-background",
125 legendItem: "bb-legend-item",
126 legendItemEvent: "bb-legend-item-event",
127 legendItemFocused: "bb-legend-item-focused",
128 legendItemHidden: "bb-legend-item-hidden",
129 legendItemPoint: "bb-legend-item-point",
130 legendItemTile: "bb-legend-item-tile",
131 level: "bb-level",
132 levels: "bb-levels",
133 line: "bb-line",
134 lines: "bb-lines",
135 main: "bb-main",
136 region: "bb-region",
137 regions: "bb-regions",
138 selectedCircle: "bb-selected-circle",
139 selectedCircles: "bb-selected-circles",
140 shape: "bb-shape",
141 shapes: "bb-shapes",
142 stanfordElements: "bb-stanford-elements",
143 stanfordLine: "bb-stanford-line",
144 stanfordLines: "bb-stanford-lines",
145 stanfordRegion: "bb-stanford-region",
146 stanfordRegions: "bb-stanford-regions",
147 subchart: "bb-subchart",
148 target: "bb-target",
149 text: "bb-text",
150 texts: "bb-texts",
151 title: "bb-title",
152 tooltip: "bb-tooltip",
153 tooltipContainer: "bb-tooltip-container",
154 tooltipName: "bb-tooltip-name",
155 valueDown: "bb-value-down",
156 valueUp: "bb-value-up",
157 xgrid: "bb-xgrid",
158 xgridFocus: "bb-xgrid-focus",
159 xgridLine: "bb-xgrid-line",
160 xgridLines: "bb-xgrid-lines",
161 xgrids: "bb-xgrids",
162 ygrid: "bb-ygrid",
163 ygridFocus: "bb-ygrid-focus",
164 ygridLine: "bb-ygrid-line",
165 ygridLines: "bb-ygrid-lines",
166 ygrids: "bb-ygrids",
167 zoomBrush: "bb-zoom-brush",
168 EXPANDED: "_expanded_",
169 SELECTED: "_selected_",
170 INCLUDED: "_included_",
171 TextOverlapping: "text-overlapping"
172};
173
174/**
175 * Copyright (c) 2017 ~ present NAVER Corp.
176 * billboard.js project is licensed under the MIT license
177 */
178var win = (function () {
179 var root = (typeof globalThis === "object" && globalThis !== null && globalThis.Object === Object && globalThis) ||
180 (typeof global === "object" && global !== null && global.Object === Object && global) ||
181 (typeof self === "object" && self !== null && self.Object === Object && self);
182 return root || Function("return this")();
183})();
184/* eslint-enable no-new-func, no-undef */
185var doc = win && win.document;
186
187var isFunction = function (v) { return typeof v === "function"; };
188var isString = function (v) { return typeof v === "string"; };
189var isNumber = function (v) { return typeof v === "number"; };
190var isUndefined = function (v) { return typeof v === "undefined"; };
191var isDefined = function (v) { return typeof v !== "undefined"; };
192var isObjectType = function (v) { return typeof v === "object"; };
193var isEmpty = function (o) { return (isUndefined(o) || o === null ||
194 (isString(o) && o.length === 0) ||
195 (isObjectType(o) && !(o instanceof Date) && Object.keys(o).length === 0) ||
196 (isNumber(o) && isNaN(o))); };
197/**
198 * Check if is array
199 * @param {Array} arr Data to be checked
200 * @returns {boolean}
201 * @private
202 */
203var isArray = function (arr) { return Array.isArray(arr); };
204/**
205 * Check if is object
206 * @param {object} obj Data to be checked
207 * @returns {boolean}
208 * @private
209 */
210var isObject = function (obj) { return obj && !obj.nodeType && isObjectType(obj) && !isArray(obj); };
211/**
212 * Merge object returning new object
213 * @param {object} target Target object
214 * @param {object} objectN Source object
215 * @returns {object} merged target object
216 * @private
217 */
218function mergeObj(target) {
219 var objectN = [];
220 for (var _i = 1; _i < arguments.length; _i++) {
221 objectN[_i - 1] = arguments[_i];
222 }
223 if (!objectN.length || (objectN.length === 1 && !objectN[0])) {
224 return target;
225 }
226 var source = objectN.shift();
227 if (isObject(target) && isObject(source)) {
228 Object.keys(source).forEach(function (key) {
229 var value = source[key];
230 if (isObject(value)) {
231 !target[key] && (target[key] = {});
232 target[key] = mergeObj(target[key], value);
233 }
234 else {
235 target[key] = isArray(value) ?
236 value.concat() : value;
237 }
238 });
239 }
240 return mergeObj.apply(void 0, __spreadArray([target], objectN));
241}
242/**
243 * Get range
244 * @param {number} start Start number
245 * @param {number} end End number
246 * @param {number} step Step number
247 * @returns {Array}
248 * @private
249 */
250var getRange = function (start, end, step) {
251 if (step === void 0) { step = 1; }
252 var res = [];
253 var n = Math.max(0, Math.ceil((end - start) / step)) | 0;
254 for (var i = start; i < n; i++) {
255 res.push(start + i * step);
256 }
257 return res;
258};
259// emulate event
260({
261 mouse: (function () {
262 var getParams = function () { return ({
263 bubbles: false, cancelable: false, screenX: 0, screenY: 0, clientX: 0, clientY: 0
264 }); };
265 try {
266 // eslint-disable-next-line no-new
267 new MouseEvent("t");
268 return function (el, eventType, params) {
269 if (params === void 0) { params = getParams(); }
270 el.dispatchEvent(new MouseEvent(eventType, params));
271 };
272 }
273 catch (e) {
274 // Polyfills DOM4 MouseEvent
275 return function (el, eventType, params) {
276 if (params === void 0) { params = getParams(); }
277 var mouseEvent = doc.createEvent("MouseEvent");
278 // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
279 mouseEvent.initMouseEvent(eventType, params.bubbles, params.cancelable, win, 0, // the event's mouse click count
280 params.screenX, params.screenY, params.clientX, params.clientY, false, false, false, false, 0, null);
281 el.dispatchEvent(mouseEvent);
282 };
283 }
284 })(),
285 touch: function (el, eventType, params) {
286 var touchObj = new Touch(mergeObj({
287 identifier: Date.now(),
288 target: el,
289 radiusX: 2.5,
290 radiusY: 2.5,
291 rotationAngle: 10,
292 force: 0.5
293 }, params));
294 el.dispatchEvent(new TouchEvent(eventType, {
295 cancelable: true,
296 bubbles: true,
297 shiftKey: true,
298 touches: [touchObj],
299 targetTouches: [],
300 changedTouches: [touchObj]
301 }));
302 }
303});
304/**
305 * Get parsed date value
306 * (It must be called in 'ChartInternal' context)
307 * @param {Date|string|number} date Value of date to be parsed
308 * @returns {Date}
309 * @private
310 */
311function parseDate(date) {
312 var parsedDate;
313 if (date instanceof Date) {
314 parsedDate = date;
315 }
316 else if (isString(date)) {
317 var _a = this, config = _a.config, format = _a.format;
318 parsedDate = format.dataTime(config.data_xFormat)(date);
319 }
320 else if (isNumber(date) && !isNaN(date)) {
321 parsedDate = new Date(+date);
322 }
323 if (!parsedDate || isNaN(+parsedDate)) {
324 console && console.error &&
325 console.error("Failed to parse x '" + date + "' to Date object");
326 }
327 return parsedDate;
328}
329
330/**
331 * Copyright (c) 2017 ~ present NAVER Corp.
332 * billboard.js project is licensed under the MIT license
333 */
334/**
335 * Load configuration option
336 * @param {object} config User's generation config value
337 * @private
338 */
339function loadConfig(config) {
340 var thisConfig = this.config;
341 var target;
342 var keys;
343 var read;
344 var find = function () {
345 var key = keys.shift();
346 if (key && target && isObjectType(target) && key in target) {
347 target = target[key];
348 return find();
349 }
350 else if (!key) {
351 return target;
352 }
353 return undefined;
354 };
355 Object.keys(thisConfig).forEach(function (key) {
356 target = config;
357 keys = key.split("_");
358 read = find();
359 if (isDefined(read)) {
360 thisConfig[key] = read;
361 }
362 });
363}
364
365/**
366 * Copyright (c) 2017 ~ present NAVER Corp.
367 * billboard.js project is licensed under the MIT license
368 */
369
370/**
371 * Base class to generate billboard.js plugin
372 * @class Plugin
373 */
374
375/**
376 * Version info string for plugin
377 * @name version
378 * @static
379 * @memberof Plugin
380 * @type {string}
381 * @example
382 * bb.plugin.stanford.version; // ex) 1.9.0
383 */
384var Plugin = /*#__PURE__*/function () {
385 /**
386 * Version info string for plugin
387 * @name version
388 * @static
389 * @memberof Plugin
390 * @type {String}
391 * @example
392 * bb.plugin.stanford.version; // ex) 1.9.0
393 */
394
395 /**
396 * Constructor
397 * @param {Any} options config option object
398 * @private
399 */
400 function Plugin(options) {
401 options === void 0 && (options = {}), this.$$, this.options = options;
402 }
403 /**
404 * Lifecycle hook for 'beforeInit' phase.
405 * @private
406 */
407
408
409 var _proto = Plugin.prototype;
410 return _proto.$beforeInit = function $beforeInit() {}
411 /**
412 * Lifecycle hook for 'init' phase.
413 * @private
414 */
415 , _proto.$init = function $init() {}
416 /**
417 * Lifecycle hook for 'afterInit' phase.
418 * @private
419 */
420 , _proto.$afterInit = function $afterInit() {}
421 /**
422 * Lifecycle hook for 'redraw' phase.
423 * @private
424 */
425 , _proto.$redraw = function $redraw() {}
426 /**
427 * Lifecycle hook for 'willDestroy' phase.
428 * @private
429 */
430 , _proto.$willDestroy = function $willDestroy() {
431 var _this = this;
432
433 Object.keys(this).forEach(function (key) {
434 _this[key] = null, delete _this[key];
435 });
436 }, Plugin;
437}();
438
439Plugin.version = "#3.0.2#";
440
441/**
442 * Copyright (c) 2017 ~ present NAVER Corp.
443 * billboard.js project is licensed under the MIT license
444 */
445/**
446 * Stanford diagram plugin option class
447 * @class StanfordOptions
448 * @param {Options} options Stanford plugin options
449 * @augments Plugin
450 * @returns {StanfordOptions}
451 * @private
452 */
453var Options = /** @class */ (function () {
454 function Options() {
455 return {
456 /**
457 * Set the color of the color scale. This function receives a value between 0 and 1, and should return a color.
458 * @name colors
459 * @memberof plugin-stanford
460 * @type {Function}
461 * @default undefined
462 * @example
463 * colors: d3.interpolateHslLong(
464 * d3.hsl(250, 1, 0.5), d3.hsl(0, 1, 0.5)
465 * )
466 */
467 colors: undefined,
468 /**
469 * Specify the key of epochs values in the data.
470 * @name epochs
471 * @memberof plugin-stanford
472 * @type {Array}
473 * @default []
474 * @example
475 * epochs: [ 1, 1, 2, 2, ... ]
476 */
477 epochs: [],
478 /**
479 * Show additional lines anywhere on the chart.
480 * - Each line object should consist with following options:
481 *
482 * | Key | Type | Description |
483 * | --- | --- | --- |
484 * | x1 | Number | Starting position on the x axis |
485 * | y1 | Number | Starting position on the y axis |
486 * | x2 | Number | Ending position on the x axis |
487 * | y2 | Number | Ending position on the y axis |
488 * | class | String | Optional value. Set a custom css class to this line. |
489 * @type {Array}
490 * @memberof plugin-stanford
491 * @default []
492 * @example
493 * lines: [
494 * { x1: 0, y1: 0, x2: 65, y2: 65, class: "line1" },
495 * { x1: 0, x2: 65, y1: 40, y2: 40, class: "line2" }
496 * ]
497 */
498 lines: [],
499 /**
500 * Set scale values
501 * @name scale
502 * @memberof plugin-stanford
503 * @type {object}
504 * @property {object} [scale] scale object
505 * @property {number} [scale.min=undefined] Minimum value of the color scale. Default: lowest value in epochs
506 * @property {number} [scale.max=undefined] Maximum value of the color scale. Default: highest value in epochs
507 * @property {number} [scale.width=20] Width of the color scale
508 * @property {string|Function} [scale.format=undefined] Format of the axis of the color scale. Use 'pow10' to format as powers of 10 or a custom function. Example: d3.format("d")
509 * @example
510 * scale: {
511 * max: 10000,
512 * min: 1,
513 * width: 500,
514 *
515 * // specify 'pow10' to format as powers of 10
516 * format: "pow10",
517 *
518 * // or specify a format function
519 * format: function(x) {
520 * return x +"%";
521 * }
522 * },
523 */
524 scale_min: undefined,
525 scale_max: undefined,
526 scale_width: 20,
527 scale_format: undefined,
528 /**
529 * The padding for color scale element
530 * @name padding
531 * @memberof plugin-stanford
532 * @type {object}
533 * @property {object} [padding] padding object
534 * @property {number} [padding.top=0] Top padding value.
535 * @property {number} [padding.right=0] Right padding value.
536 * @property {number} [padding.bottom=0] Bottom padding value.
537 * @property {number} [padding.left=0] Left padding value.
538 * @example
539 * padding: {
540 * top: 15,
541 * right: 0,
542 * bottom: 0,
543 * left: 0
544 * },
545 */
546 padding_top: 0,
547 padding_right: 0,
548 padding_bottom: 0,
549 padding_left: 0,
550 /**
551 * Show additional regions anywhere on the chart.
552 * - Each region object should consist with following options:
553 *
554 * | Key | Type | Default | Attributes | Description |
555 * | --- | --- | --- | --- | --- |
556 * | points | Array | | | Accepts a group of objects that has x and y.<br>These points should be added in a counter-clockwise fashion to make a closed polygon. |
557 * | opacity | Number | `0.2` | &lt;optional> | Sets the opacity of the region as value between 0 and 1 |
558 * | text | Function | | &lt;optional> | This function receives a value and percentage of the number of epochs in this region.<br>Return a string to place text in the middle of the region. |
559 * | class | String | | &lt;optional> | Se a custom css class to this region, use the fill property in css to set a background color. |
560 * @name regions
561 * @memberof plugin-stanford
562 * @type {Array}
563 * @default []
564 * @example
565 * regions: [
566 * {
567 * points: [ // add points counter-clockwise
568 * { x: 0, y: 0 },
569 * { x: 40, y: 40 },
570 * { x: 0, y: 40 },
571 * ],
572 * text: function (value, percentage) {
573 * return `Normal Operations: ${value} (${percentage}%)`;
574 * },
575 * opacity: 0.2, // 0 to 1
576 * class: "test-polygon1"
577 * },
578 * ...
579 * ]
580 */
581 regions: []
582 };
583 }
584 return Options;
585}());
586
587/**
588 * Copyright (c) 2017 ~ present NAVER Corp.
589 * billboard.js project is licensed under the MIT license
590 */
591/**
592 * CSS class names definition
593 * @private
594 */
595var CLASS = {
596 colorScale: "bb-colorscale",
597 stanfordElements: "bb-stanford-elements",
598 stanfordLine: "bb-stanford-line",
599 stanfordLines: "bb-stanford-lines",
600 stanfordRegion: "bb-stanford-region",
601 stanfordRegions: "bb-stanford-regions"
602};
603
604/**
605 * Copyright (c) 2017 ~ present NAVER Corp.
606 * billboard.js project is licensed under the MIT license
607 * @ignore
608 */
609/**
610 * Check if point is in region
611 * @param {object} point Point
612 * @param {Array} region Region
613 * @returns {boolean}
614 * @private
615 */
616function pointInRegion(point, region) {
617 // ray-casting algorithm based on
618 // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
619 var x = point.x;
620 var y = point.value;
621 var inside = false;
622 for (var i = 0, j = region.length - 1; i < region.length; j = i++) {
623 var xi = region[i].x;
624 var yi = region[i].y;
625 var xj = region[j].x;
626 var yj = region[j].y;
627 var intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
628 if (intersect) {
629 inside = !inside;
630 }
631 }
632 return inside;
633}
634/**
635 * Compare epochs
636 * @param {object} a Target
637 * @param {object} b Source
638 * @returns {number}
639 * @private
640 */
641function compareEpochs(a, b) {
642 if (a.epochs < b.epochs) {
643 return -1;
644 }
645 if (a.epochs > b.epochs) {
646 return 1;
647 }
648 return 0;
649}
650/**
651 * Get region area
652 * @param {Array} points Points
653 * @returns {number}
654 * @private
655 */
656function getRegionArea(points) {
657 var area = 0;
658 var point1;
659 var point2;
660 for (var i = 0, l = points.length, j = l - 1; i < l; j = i, i++) {
661 point1 = points[i];
662 point2 = points[j];
663 area += point1.x * point2.y;
664 area -= point1.y * point2.x;
665 }
666 area /= 2;
667 return area;
668}
669/**
670 * Get centroid
671 * @param {Array} points Points
672 * @returns {object}
673 * @private
674 */
675function getCentroid(points) {
676 var area = getRegionArea(points);
677 var x = 0;
678 var y = 0;
679 var f;
680 for (var i = 0, l = points.length, j = l - 1; i < l; j = i, i++) {
681 var point1 = points[i];
682 var point2 = points[j];
683 f = point1.x * point2.y - point2.x * point1.y;
684 x += (point1.x + point2.x) * f;
685 y += (point1.y + point2.y) * f;
686 }
687 f = area * 6;
688 return {
689 x: x / f,
690 y: y / f
691 };
692}
693
694/**
695 * Copyright (c) 2017 ~ present NAVER Corp.
696 * billboard.js project is licensed under the MIT license
697 */
698/**
699 * Stanford diagram plugin element class
700 * @class ColorScale
701 * @param {Stanford} owner Stanford instance
702 * @private
703 */
704var Elements = /** @class */ (function () {
705 function Elements(owner) {
706 this.owner = owner;
707 // MEMO: Avoid blocking eventRect
708 var elements = owner.$$.$el.main.select(".bb-chart")
709 .append("g")
710 .attr("class", CLASS.stanfordElements);
711 elements.append("g").attr("class", CLASS.stanfordLines);
712 elements.append("g").attr("class", CLASS.stanfordRegions);
713 }
714 Elements.prototype.updateStanfordLines = function (duration) {
715 var $$ = this.owner.$$;
716 var config = $$.config, main = $$.$el.main;
717 var isRotated = config.axis_rotated;
718 var xvCustom = this.xvCustom.bind($$);
719 var yvCustom = this.yvCustom.bind($$);
720 // Stanford-Lines
721 var stanfordLine = main.select("." + CLASS.stanfordLines)
722 .style("shape-rendering", "geometricprecision")
723 .selectAll("." + CLASS.stanfordLine)
724 .data(this.owner.config.lines);
725 // exit
726 stanfordLine.exit().transition()
727 .duration(duration)
728 .style("opacity", "0")
729 .remove();
730 // enter
731 var stanfordLineEnter = stanfordLine.enter().append("g");
732 stanfordLineEnter.append("line")
733 .style("opacity", "0");
734 stanfordLineEnter
735 .merge(stanfordLine)
736 .attr("class", function (d) { return CLASS.stanfordLine + (d["class"] ? " " + d["class"] : ""); })
737 .select("line")
738 .transition()
739 .duration(duration)
740 .attr("x1", function (d) { return (isRotated ? yvCustom(d, "y1") : xvCustom(d, "x1")); })
741 .attr("x2", function (d) { return (isRotated ? yvCustom(d, "y2") : xvCustom(d, "x2")); })
742 .attr("y1", function (d) { return (isRotated ? xvCustom(d, "x1") : yvCustom(d, "y1")); })
743 .attr("y2", function (d) { return (isRotated ? xvCustom(d, "x2") : yvCustom(d, "y2")); })
744 .transition()
745 .style("opacity", "1");
746 };
747 Elements.prototype.updateStanfordRegions = function (duration) {
748 var $$ = this.owner.$$;
749 var config = $$.config, main = $$.$el.main;
750 var isRotated = config.axis_rotated;
751 var xvCustom = this.xvCustom.bind($$);
752 var yvCustom = this.yvCustom.bind($$);
753 var countPointsInRegion = this.owner.countEpochsInRegion.bind($$);
754 // Stanford-Regions
755 var stanfordRegion = main.select("." + CLASS.stanfordRegions)
756 .selectAll("." + CLASS.stanfordRegion)
757 .data(this.owner.config.regions);
758 // exit
759 stanfordRegion.exit().transition()
760 .duration(duration)
761 .style("opacity", "0")
762 .remove();
763 // enter
764 var stanfordRegionEnter = stanfordRegion.enter().append("g");
765 stanfordRegionEnter.append("polygon")
766 .style("opacity", "0");
767 stanfordRegionEnter.append("text")
768 .attr("transform", isRotated ? "rotate(-90)" : "")
769 .style("opacity", "0");
770 stanfordRegion = stanfordRegionEnter.merge(stanfordRegion);
771 // update
772 stanfordRegion
773 .attr("class", function (d) { return CLASS.stanfordRegion + (d["class"] ? " " + d["class"] : ""); })
774 .select("polygon")
775 .transition()
776 .duration(duration)
777 .attr("points", function (d) { return d.points.map(function (value) { return [
778 isRotated ? yvCustom(value, "y") : xvCustom(value, "x"),
779 isRotated ? xvCustom(value, "x") : yvCustom(value, "y")
780 ].join(","); }).join(" "); })
781 .transition()
782 .style("opacity", function (d) { return String(d.opacity ? d.opacity : 0.2); });
783 stanfordRegion.select("text")
784 .transition()
785 .duration(duration)
786 .attr("x", function (d) { return (isRotated ? yvCustom(getCentroid(d.points), "y") : xvCustom(getCentroid(d.points), "x")); })
787 .attr("y", function (d) { return (isRotated ? xvCustom(getCentroid(d.points), "x") : yvCustom(getCentroid(d.points), "y")); })
788 .text(function (d) {
789 if (d.text) {
790 var _a = countPointsInRegion(d.points), value = _a.value, percentage = _a.percentage;
791 return d.text(value, percentage);
792 }
793 return "";
794 })
795 .attr("text-anchor", "middle")
796 .attr("dominant-baseline", "middle")
797 .transition()
798 .style("opacity", "1");
799 };
800 Elements.prototype.updateStanfordElements = function (duration) {
801 if (duration === void 0) { duration = 0; }
802 this.updateStanfordLines(duration);
803 this.updateStanfordRegions(duration);
804 };
805 Elements.prototype.xvCustom = function (d, xyValue) {
806 var $$ = this;
807 var axis = $$.axis, config = $$.config;
808 var value = xyValue ? d[xyValue] : $$.getBaseValue(d);
809 if (axis.isTimeSeries()) {
810 value = parseDate.call($$, value);
811 }
812 else if (axis.isCategorized() && isString(value)) {
813 value = config.axis_x_categories.indexOf(d.value);
814 }
815 return Math.ceil($$.scale.x(value));
816 };
817 Elements.prototype.yvCustom = function (d, xyValue) {
818 var $$ = this;
819 var yScale = d.axis && d.axis === "y2" ? $$.scale.y2 : $$.scale.y;
820 var value = xyValue ? d[xyValue] : $$.getBaseValue(d);
821 return Math.ceil(yScale(value));
822 };
823 return Elements;
824}());
825
826/**
827 * Copyright (c) 2017 ~ present NAVER Corp.
828 * billboard.js project is licensed under the MIT license
829 */
830/**
831 * Stanford diagram plugin color scale class
832 * @class ColorScale
833 * @param {Stanford} owner Stanford instance
834 * @private
835 */
836var ColorScale = /** @class */ (function () {
837 function ColorScale(owner) {
838 this.owner = owner;
839 }
840 ColorScale.prototype.drawColorScale = function () {
841 var _a = this.owner, $$ = _a.$$, config = _a.config;
842 var target = $$.data.targets[0];
843 var height = $$.state.height - config.padding_bottom - config.padding_top;
844 var barWidth = config.scale_width;
845 var barHeight = 5;
846 var points = getRange(config.padding_bottom, height, barHeight);
847 var inverseScale = scaleSequential(target.colors)
848 .domain([points[points.length - 1], points[0]]);
849 if (this.colorScale) {
850 this.colorScale.remove();
851 }
852 this.colorScale = $$.$el.svg.append("g")
853 .attr("width", 50)
854 .attr("height", height)
855 .attr("class", CLASS.colorScale);
856 this.colorScale.append("g")
857 .attr("transform", "translate(0, " + config.padding_top + ")")
858 .selectAll("bars")
859 .data(points)
860 .enter()
861 .append("rect")
862 .attr("y", function (d, i) { return i * barHeight; })
863 .attr("x", 0)
864 .attr("width", barWidth)
865 .attr("height", barHeight)
866 .attr("fill", function (d) { return inverseScale(d); });
867 // Legend Axis
868 var axisScale = scaleLog()
869 .domain([target.minEpochs, target.maxEpochs])
870 .range([
871 points[0] + config.padding_top + points[points.length - 1] + barHeight - 1,
872 points[0] + config.padding_top
873 ]);
874 var legendAxis = axisRight(axisScale);
875 var scaleFormat = config.scale_format;
876 if (scaleFormat === "pow10") {
877 legendAxis.tickValues([1, 10, 100, 1000, 10000, 100000, 1000000, 10000000]);
878 }
879 else if (isFunction(scaleFormat)) {
880 legendAxis.tickFormat(scaleFormat);
881 }
882 else {
883 legendAxis.tickFormat(format("d"));
884 }
885 // Draw Axis
886 var axis = this.colorScale.append("g")
887 .attr("class", "legend axis")
888 .attr("transform", "translate(" + barWidth + ",0)")
889 .call(legendAxis);
890 if (scaleFormat === "pow10") {
891 axis.selectAll(".tick text")
892 .text(null)
893 .filter(function (d) { return d / Math.pow(10, Math.ceil(Math.log(d) / Math.LN10 - 1e-12)) === 1; }) // Power of Ten
894 .text(10)
895 .append("tspan")
896 .attr("dy", "-.7em") // https://bl.ocks.org/mbostock/6738229
897 .text(function (d) { return Math.round(Math.log(d) / Math.LN10); });
898 }
899 this.colorScale.attr("transform", "translate(" + ($$.state.current.width - this.xForColorScale()) + ", 0)");
900 };
901 ColorScale.prototype.xForColorScale = function () {
902 return this.owner.config.padding_right +
903 this.colorScale.node().getBBox().width;
904 };
905 ColorScale.prototype.getColorScalePadding = function () {
906 return this.xForColorScale() + this.owner.config.padding_left + 20;
907 };
908 return ColorScale;
909}());
910
911/**
912 * Stanford diagram plugin
913 * - **NOTE:**
914 * - Plugins aren't built-in. Need to be loaded or imported to be used.
915 * - Non required modules from billboard.js core, need to be installed separately.
916 * - Is preferable use `scatter` as data.type
917 * - **Required modules:**
918 * - [d3-selection](https://github.com/d3/d3-selection)
919 * - [d3-interpolate](https://github.com/d3/d3-interpolate)
920 * - [d3-color](https://github.com/d3/d3-color)
921 * - [d3-scale](https://github.com/d3/d3-scale)
922 * - [d3-brush](https://github.com/d3/d3-brush)
923 * - [d3-axis](https://github.com/d3/d3-axis)
924 * - [d3-format](https://github.com/d3/d3-format)
925 * @class plugin-stanford
926 * @requires d3-selection
927 * @requires d3-interpolate
928 * @requires d3-color
929 * @requires d3-scale
930 * @requires d3-brush
931 * @requires d3-axis
932 * @requires d3-format
933 * @param {object} options Stanford plugin options
934 * @augments Plugin
935 * @returns {Stanford}
936 * @example
937 * // Plugin must be loaded before the use.
938 * <script src="$YOUR_PATH/plugin/billboardjs-plugin-stanford.js"></script>
939 *
940 * var chart = bb.generate({
941 * data: {
942 * columns: [ ... ],
943 * type: "scatter"
944 * }
945 * ...
946 * plugins: [
947 * new bb.plugin.stanford({
948 * colors: d3.interpolateHslLong(
949 * d3.hsl(250, 1, 0.5), d3.hsl(0, 1, 0.5)
950 * ),
951 * epochs: [ 1, 1, 2, 2, ... ],
952 * lines: [
953 * { x1: 0, y1: 0, x2: 65, y2: 65, class: "line1" },
954 * { x1: 0, x2: 65, y1: 40, y2: 40, class: "line2" }
955 * ],
956 * scale: {
957 * max: 10000,
958 * min: 1,
959 * width: 500,
960 * format: 'pow10',
961 * },
962 * padding: {
963 * top: 15,
964 * right: 0,
965 * bottom: 0,
966 * left: 0
967 * },
968 * regions: [
969 * {
970 * points: [ // add points counter-clockwise
971 * { x: 0, y: 0 },
972 * { x: 40, y: 40 },
973 * { x: 0, y: 40 }
974 * ],
975 * text: function (value, percentage) {
976 * return `Normal Operations: ${value} (${percentage}%)`;
977 * },
978 * opacity: 0.2, // 0 to 1
979 * class: "test-polygon1"
980 * },
981 * ...
982 * ]
983 * }
984 * ]
985 * });
986 * @example
987 * import {bb} from "billboard.js";
988 * import Stanford from "billboard.js/dist/billboardjs-plugin-stanford.esm";
989 *
990 * bb.generate({
991 * plugins: [
992 * new Stanford({ ... })
993 * ]
994 * })
995 */
996var Stanford = /** @class */ (function (_super) {
997 __extends(Stanford, _super);
998 function Stanford(options) {
999 var _this = _super.call(this, options) || this;
1000 _this.config = new Options();
1001 return _this;
1002 }
1003 Stanford.prototype.$beforeInit = function () {
1004 var _this = this;
1005 var $$ = this.$$;
1006 // override on config values & methods
1007 $$.config.data_xSort = false;
1008 $$.isMultipleX = function () { return true; };
1009 $$.showGridFocus = function () { };
1010 $$.labelishData = function (d) { return d.values; };
1011 $$.opacityForCircle = function () { return 1; };
1012 var getCurrentPaddingRight = $$.getCurrentPaddingRight.bind($$);
1013 $$.getCurrentPaddingRight = function () { return (getCurrentPaddingRight() + (_this.colorScale ? _this.colorScale.getColorScalePadding() : 0)); };
1014 };
1015 Stanford.prototype.$init = function () {
1016 var $$ = this.$$;
1017 loadConfig.call(this, this.options);
1018 $$.color = this.getStanfordPointColor.bind($$);
1019 this.colorScale = new ColorScale(this);
1020 this.elements = new Elements(this);
1021 this.convertData();
1022 this.initStanfordData();
1023 this.setStanfordTooltip();
1024 this.colorScale.drawColorScale();
1025 this.$redraw();
1026 };
1027 Stanford.prototype.$redraw = function (duration) {
1028 this.colorScale && this.colorScale.drawColorScale();
1029 this.elements && this.elements.updateStanfordElements(duration);
1030 };
1031 Stanford.prototype.getOptions = function () {
1032 return new Options();
1033 };
1034 Stanford.prototype.convertData = function () {
1035 var data = this.$$.data.targets;
1036 var epochs = this.options.epochs;
1037 data.forEach(function (d) {
1038 d.values.forEach(function (v, i) {
1039 v.epochs = epochs[i];
1040 });
1041 d.minEpochs = undefined;
1042 d.maxEpochs = undefined;
1043 d.colors = undefined;
1044 d.colorscale = undefined;
1045 });
1046 };
1047 Stanford.prototype.xvCustom = function (d, xyValue) {
1048 var $$ = this;
1049 var axis = $$.axis, config = $$.config;
1050 var value = xyValue ? d[xyValue] : $$.getBaseValue(d);
1051 if (axis.isTimeSeries()) {
1052 value = parseDate.call($$, value);
1053 }
1054 else if (axis.isCategorized() && isString(value)) {
1055 value = config.axis_x_categories.indexOf(d.value);
1056 }
1057 return Math.ceil($$.scale.x(value));
1058 };
1059 Stanford.prototype.yvCustom = function (d, xyValue) {
1060 var $$ = this;
1061 var scale = $$.scale;
1062 var yScale = d.axis && d.axis === "y2" ? scale.y2 : scale.y;
1063 var value = xyValue ? d[xyValue] : $$.getBaseValue(d);
1064 return Math.ceil(yScale(value));
1065 };
1066 Stanford.prototype.initStanfordData = function () {
1067 var config = this.config;
1068 var target = this.$$.data.targets[0];
1069 // TODO STANFORD see if (data.js -> orderTargets)+ can be used instead
1070 // Make larger values appear on top
1071 target.values.sort(compareEpochs);
1072 // Get array of epochs
1073 var epochs = target.values.map(function (a) { return a.epochs; });
1074 target.minEpochs = !isNaN(config.scale_min) ? config.scale_min : Math.min.apply(Math, epochs);
1075 target.maxEpochs = !isNaN(config.scale_max) ? config.scale_max : Math.max.apply(Math, epochs);
1076 target.colors = isFunction(config.colors) ?
1077 config.colors : interpolateHslLong(hsl(250, 1, 0.5), hsl(0, 1, 0.5));
1078 target.colorscale = scaleSequentialLog(target.colors)
1079 .domain([target.minEpochs, target.maxEpochs]);
1080 };
1081 Stanford.prototype.getStanfordPointColor = function (d) {
1082 var target = this.data.targets[0];
1083 return target.colorscale(d.epochs);
1084 };
1085 Stanford.prototype.setStanfordTooltip = function () {
1086 var config = this.$$.config;
1087 if (isEmpty(config.tooltip_contents)) {
1088 config.tooltip_contents = function (d, defaultTitleFormat, defaultValueFormat, color) {
1089 var html = "<table class=\"" + CLASS$1.tooltip + "\"><tbody>";
1090 d.forEach(function (v) {
1091 html += "<tr>\n\t\t\t\t\t\t\t<th>" + defaultTitleFormat(config.data_x) + "</th>\n\t\t\t\t\t\t\t<th class=\"value\">" + defaultValueFormat(v.x) + "</th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th>" + defaultTitleFormat(v.id) + "</th>\n\t\t\t\t\t\t\t<th class=\"value\">" + defaultValueFormat(v.value) + "</th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr class=\"" + CLASS$1.tooltipName + "-" + v.id + "\">\n\t\t\t\t\t\t\t<td class=\"name\"><span style=\"background-color:" + color(v) + "\"></span>" + defaultTitleFormat("Epochs") + "</td>\n\t\t\t\t\t\t\t<td class=\"value\">" + defaultValueFormat(v.epochs) + "</td>\n\t\t\t\t\t\t</tr>";
1092 });
1093 return html + "</tbody></table>";
1094 };
1095 }
1096 };
1097 Stanford.prototype.countEpochsInRegion = function (region) {
1098 var $$ = this;
1099 var target = $$.data.targets[0];
1100 var total = target.values.reduce(function (accumulator, currentValue) {
1101 return accumulator + Number(currentValue.epochs);
1102 }, 0);
1103 var value = target.values.reduce(function (accumulator, currentValue) {
1104 if (pointInRegion(currentValue, region)) {
1105 return accumulator + Number(currentValue.epochs);
1106 }
1107 return accumulator;
1108 }, 0);
1109 return {
1110 value: value,
1111 percentage: value !== 0 ? +(value / total * 100).toFixed(1) : 0
1112 };
1113 };
1114 return Stanford;
1115}(Plugin));
1116
1117export default Stanford;