all files / chart/series/ box-and-whisker-series.js

97.06% Statements 165/170
91.67% Branches 66/72
100% Functions 21/21
97.01% Lines 162/167
9 statements, 5 functions, 9 branches Ignored     
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242        45×   47× 47× 47× 47× 47× 367× 367× 367× 367× 367× 359× 359× 359× 359× 359×         359× 354×       47× 47×     359× 359×   1261× 1261× 354× 354×     907× 907×   1261×   354× 354× 354× 354× 354×   354× 354× 354× 354× 354× 338× 338× 338× 338× 338×   338× 338× 338× 338×         16× 16× 16× 16× 16×   16× 16× 16× 16×       354×   354× 354× 354× 354× 354×   354×     354× 354× 194× 194× 194× 194×         354×   359× 359×           359× 31× 31× 31×   328× 10× 10× 10×     318× 318×   359× 359× 359× 359× 359× 359× 359× 359×   93×     93×   90× 90× 90× 90× 90×     90×       90×   90×   30×     30×   27× 27× 27× 27× 27× 27×   318×   317× 317× 317× 317× 317× 317×   359× 359× 359× 359×       359× 359×     359× 557× 198×     359× 359×         20665×          
/* istanbul ignore next */ 
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
define(["require", "exports", "../../common/utils/helper", "../../common/utils/helper", "@syncfusion/ej2-base", "./column-base", "../../common/utils/helper"], function (require, exports, helper_1, helper_2, ej2_base_1, column_base_1, helper_3) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var BoxAndWhiskerSeries = (function (_super) {
        __extends(BoxAndWhiskerSeries, _super);
        function BoxAndWhiskerSeries() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        BoxAndWhiskerSeries.prototype.render = function (series, xAxis, yAxis, isInverted) {
            var sideBySideInfo = this.getSideBySideInfo(series);
            var argsData;
            var centerRegion;
            var borderWidth = series.border.width || 1;
            for (var _i = 0, _a = series.points; _i < _a.length; _i++) {
                var point = _a[_i];
                point.symbolLocations = [];
                point.regions = [];
                var centerRegion_1 = void 0;
                if (point.visible && helper_1.withInRange(series.points[point.index - 1], point, series.points[point.index + 1], series)) {
                    this.findBoxPlotValues(point.y, point, series.boxPlotMode);
                    this.updateTipRegion(series, point, sideBySideInfo);
                    centerRegion_1 = this.getRectangle((point.xValue + sideBySideInfo.start), point.upperQuartile, (point.xValue + sideBySideInfo.end), point.lowerQuartile, series);
                    point.regions.push(centerRegion_1);
                    argsData = this.triggerEvent(series, point, series.interior, {
                        color: (!ej2_base_1.isNullOrUndefined(series.border.color) && series.border.color !== 'transparent') ? series.border.color :
                            helper_2.getSaturationColor(series.interior, -0.6),
                        width: series.border.width ? series.border.width : 1
                    });
                    if (!argsData.cancel) {
                        this.renderBoxAndWhisker(series, point, centerRegion_1, argsData, this.getPathString(point, series, helper_2.getPoint(point.xValue, point.median, xAxis, yAxis, isInverted), helper_2.getPoint(point.xValue + sideBySideInfo.median, point.average, xAxis, yAxis, isInverted)), sideBySideInfo.median);
                    }
                }
            }
            Eif (series.marker.visible) {
                series.chart.markerRender.render(series);
            }
        };
        BoxAndWhiskerSeries.prototype.updateTipRegion = function (series, point, sideBySideInfo) {
            var tipRegion = this.getRectangle((point.xValue + sideBySideInfo.median), point.maximum, (point.xValue + sideBySideInfo.median), point.minimum, series);
            this.updateTipSize(series, point, tipRegion, series.chart.requireInvertedAxis);
        };
        BoxAndWhiskerSeries.prototype.updateTipSize = function (series, point, region, isInverted) {
            var borderWidth = series.border.width || 1;
            if (!isInverted) {
                region.x -= borderWidth / 2;
                region.width = region.width || borderWidth;
            }
            else {
                region.y -= borderWidth / 2;
                region.height = region.height || borderWidth;
            }
            point.regions.push(region);
        };
        BoxAndWhiskerSeries.prototype.getPathString = function (point, series, median, average) {
            var topRect = point.regions[0];
            var midRect = point.regions[1];
            var direction = '';
            var width = series.chart.requireInvertedAxis ? topRect.height : topRect.width;
            var center = series.chart.requireInvertedAxis ? topRect.y + topRect.height / 2 :
                topRect.x + topRect.width / 2;
            var midWidth = midRect.x + midRect.width;
            var midHeight = midRect.y + midRect.height;
            var topWidth = topRect.x + topRect.width;
            var topHeight = topRect.y + topRect.height;
            if (!series.chart.requireInvertedAxis) {
                this.updateTipSize(series, point, { x: midRect.x, y: topRect.y, width: midWidth - midRect.x, height: 0 }, true);
                this.updateTipSize(series, point, { x: midRect.x, y: topHeight, width: midWidth - midRect.x, height: 0 }, true);
                direction += 'M ' + midRect.x + ' ' + topRect.y + ' ' + ' L ' + midWidth + ' ' + topRect.y;
                direction += ' M ' + center + ' ' + topRect.y + ' ' + ' L ' + center + ' ' + midRect.y;
                direction += ' M ' + midRect.x + ' ' + midRect.y + ' ' + ' L ' + midWidth + ' ' + midRect.y +
                    ' L ' + midWidth + ' ' + midHeight + ' L ' + midRect.x + ' ' + midHeight + ' Z';
                direction += ' M ' + center + ' ' + midHeight + ' L ' + center + ' ' + topHeight;
                direction += ' M ' + midRect.x + ' ' + topHeight + ' L ' + midWidth + ' ' + topHeight;
                direction += ' M ' + midRect.x + ' ' + median.y + ' L ' + midWidth + ' ' + median.y;
                direction += series.showMean ?
                    ' M ' + (average.x - 5) + ' ' + (average.y - 5) + ' L ' + (average.x + 5) + ' ' + (average.y + 5) +
                        ' M ' + (average.x + 5) + ' ' + (average.y - 5) + ' L ' + (average.x - 5) + ' ' + (average.y + 5) : '';
            }
            else {
                this.updateTipSize(series, point, { x: topRect.x, y: midRect.y, width: 0, height: midHeight - midRect.y }, false);
                this.updateTipSize(series, point, { x: topWidth, y: midRect.y, width: 0, height: midHeight - midRect.y }, true);
                direction += 'M ' + topRect.x + ' ' + midRect.y + ' L ' + topRect.x + ' ' + midHeight;
                direction += 'M ' + topRect.x + ' ' + center + ' ' + ' L ' + midRect.x + ' ' + center;
                direction += ' M ' + midRect.x + ' ' + midRect.y + ' ' + ' L ' + midWidth + ' ' + midRect.y +
                    ' L ' + midWidth + ' ' + midHeight + ' L ' + midRect.x + ' ' + midHeight + ' Z';
                direction += ' M ' + midWidth + ' ' + center + ' L ' + topWidth + ' ' + center;
                direction += ' M ' + topWidth + ' ' + midRect.y + ' L ' + topWidth + ' ' + midHeight;
                direction += ' M ' + median.x + ' ' + midRect.y + ' ' + ' L ' + median.x + ' ' + midHeight;
                direction += series.showMean ?
                    'M ' + (average.x + 5) + ' ' + (average.y - 5) + ' L ' + (average.x - 5) + ' ' + (average.y + 5) +
                        'M ' + (average.x - 5) + ' ' + (average.y - 5) + ' L ' + (average.x + 5) + ' ' + (average.y + 5) : '';
            }
            return direction;
        };
        BoxAndWhiskerSeries.prototype.renderBoxAndWhisker = function (series, point, rect, argsData, direction, median) {
            var location;
            var size;
            var symbolId = series.chart.element.id + '_Series_' + series.index + '_Point_' + point.index;
            var element = series.chart.renderer.drawPath(new helper_1.PathOption(symbolId + '_BoxPath', argsData.fill, argsData.border.width, argsData.border.color, series.opacity, series.dashArray, direction));
            element.setAttribute('aria-label', point.x.toString() + ':' + point.maximum.toString()
                + ':' + point.minimum.toString() + ':' + point.lowerQuartile.toString() + ':' + point.upperQuartile.toString());
            var parentElement = series.chart.renderer.createGroup({
                'id': symbolId
            });
            parentElement.appendChild(element);
            for (var i = 0; i < point.outliers.length; i++) {
                location = helper_2.getPoint((point.xValue + median), point.outliers[i], series.xAxis, series.yAxis, series.chart.requireInvertedAxis);
                size = new helper_2.Size(series.marker.width, series.marker.height);
                point.symbolLocations.push(location);
                this.updateTipSize(series, point, {
                    x: location.x - (size.width / 2), y: location.y - (size.height / 2),
                    width: size.width, height: size.height
                }, true);
            }
            series.seriesElement.appendChild(parentElement);
        };
        BoxAndWhiskerSeries.prototype.findBoxPlotValues = function (yValues, point, mode) {
            var yCount = yValues.length;
            var quartile = {
                average: helper_1.sum(yValues) / yCount,
                lowerQuartile: 0, upperQuartile: 0,
                maximum: 0, minimum: 0,
                median: 0, outliers: []
            };
            if (mode === 'Exclusive') {
                quartile.lowerQuartile = this.getExclusiveQuartileValue(yValues, yCount, 0.25);
                quartile.upperQuartile = this.getExclusiveQuartileValue(yValues, yCount, 0.75);
                quartile.median = this.getExclusiveQuartileValue(yValues, yCount, 0.5);
            }
            else if (mode === 'Inclusive') {
                quartile.lowerQuartile = this.getInclusiveQuartileValue(yValues, yCount, 0.25);
                quartile.upperQuartile = this.getInclusiveQuartileValue(yValues, yCount, 0.75);
                quartile.median = this.getInclusiveQuartileValue(yValues, yCount, 0.5);
            }
            else {
                quartile.median = helper_3.getMedian(yValues);
                this.getQuartileValues(yValues, yCount, quartile);
            }
            this.getMinMaxOutlier(yValues, yCount, quartile);
            point.minimum = quartile.minimum;
            point.maximum = quartile.maximum;
            point.lowerQuartile = quartile.lowerQuartile;
            point.upperQuartile = quartile.upperQuartile;
            point.median = quartile.median;
            point.outliers = quartile.outliers;
            point.average = quartile.average;
        };
        BoxAndWhiskerSeries.prototype.getExclusiveQuartileValue = function (yValues, count, percentile) {
            Iif (count === 0) {
                return 0;
            }
            else if (count === 1) {
                return yValues[0];
            }
            var value = 0;
            var rank = percentile * (count + 1);
            var integerRank = Math.floor(Math.abs(rank));
            var fractionRank = rank - integerRank;
            Iif (integerRank === 0) {
                value = yValues[0];
            }
            else Iif (integerRank > count - 1) {
                value = yValues[count - 1];
            }
            else {
                value = fractionRank * (yValues[integerRank] - yValues[integerRank - 1]) + yValues[integerRank - 1];
            }
            return value;
        };
        BoxAndWhiskerSeries.prototype.getInclusiveQuartileValue = function (yValues, count, percentile) {
            Iif (count === 0) {
                return 0;
            }
            else if (count === 1) {
                return yValues[0];
            }
            var value = 0;
            var rank = percentile * (count - 1);
            var integerRank = Math.floor(Math.abs(rank));
            var fractionRank = rank - integerRank;
            value = fractionRank * (yValues[integerRank + 1] - yValues[integerRank]) + yValues[integerRank];
            return value;
        };
        BoxAndWhiskerSeries.prototype.getQuartileValues = function (yValues, count, quartile) {
            if (count === 1) {
                quartile.lowerQuartile = yValues[0];
                quartile.upperQuartile = yValues[0];
                return null;
            }
            var isEvenList = count % 2 === 0;
            var halfLength = count / 2;
            var lowerQuartileArray = yValues.slice(0, halfLength);
            var upperQuartileArray = yValues.slice(isEvenList ? halfLength : halfLength + 1, count);
            quartile.lowerQuartile = helper_3.getMedian(lowerQuartileArray);
            quartile.upperQuartile = helper_3.getMedian(upperQuartileArray);
        };
        BoxAndWhiskerSeries.prototype.getMinMaxOutlier = function (yValues, count, quartile) {
            var interquartile = quartile.upperQuartile - quartile.lowerQuartile;
            var rangeIQR = 1.5 * interquartile;
            for (var i = 0; i < count; i++) {
                Iif (yValues[i] < quartile.lowerQuartile - rangeIQR) {
                    quartile.outliers.push(yValues[i]);
                }
                else {
                    quartile.minimum = yValues[i];
                    break;
                }
            }
            for (var i = count - 1; i >= 0; i--) {
                if (yValues[i] > quartile.upperQuartile + rangeIQR) {
                    quartile.outliers.push(yValues[i]);
                }
                else {
                    quartile.maximum = yValues[i];
                    break;
                }
            }
        };
        BoxAndWhiskerSeries.prototype.doAnimation = function (series) {
            this.animate(series);
        };
        BoxAndWhiskerSeries.prototype.getModuleName = function () {
            return 'BoxAndWhiskerSeries';
        };
        BoxAndWhiskerSeries.prototype.destroy = function (chart) {
        };
        return BoxAndWhiskerSeries;
    }(column_base_1.ColumnBase));
    exports.BoxAndWhiskerSeries = BoxAndWhiskerSeries;
});