Perf dashboard should automatically select ranges for A/B testing
[WebKit-https.git] / Websites / perf.webkit.org / public / v2 / interactive-chart.js
index 68871697592d86f201920286e3f70c6866fa1ab9..6eaeac3dca44cd76cf604f64faf8cc0ced62670e 100644 (file)
@@ -128,7 +128,7 @@ App.InteractiveChartComponent = Ember.Component.extend({
                 .attr("class", "target"));
         }
 
-        var movingAverageIsVisible = this._movingAverageTimeSeries && !chartData.hideMovingAverage;
+        var movingAverageIsVisible = this._movingAverageTimeSeries;
         var foregroundClass = movingAverageIsVisible ? '' : ' foreground';
         this._areas.push(this._clippedContainer
             .append("path")
@@ -153,12 +153,10 @@ App.InteractiveChartComponent = Ember.Component.extend({
                 .datum(this._movingAverageTimeSeries.series())
                 .attr("class", "movingAverage"));
 
-            if (!chartData.hideEnvelope) {
-                this._areas.push(this._clippedContainer
-                    .append("path")
-                    .datum(this._movingAverageTimeSeries.series())
-                    .attr("class", "envelope"));
-            }
+            this._areas.push(this._clippedContainer
+                .append("path")
+                .datum(this._movingAverageTimeSeries.series())
+                .attr("class", "envelope"));
         }
 
         if (isInteractive) {
@@ -199,6 +197,8 @@ App.InteractiveChartComponent = Ember.Component.extend({
     _updateDomain: function ()
     {
         var xDomain = this.get('domain');
+        if (!xDomain || !this._currentTimeSeriesData)
+            return null;
         var intrinsicXDomain = this._computeXAxisDomain(this._currentTimeSeriesData);
         if (!xDomain)
             xDomain = intrinsicXDomain;
@@ -208,7 +208,7 @@ App.InteractiveChartComponent = Ember.Component.extend({
         var currentYDomain = this._y.domain();
         if (currentXDomain && App.domainsAreEqual(currentXDomain, xDomain)
             && currentYDomain && App.domainsAreEqual(currentYDomain, yDomain))
-            return currentDomain;
+            return currentXDomain;
 
         this._x.domain(xDomain);
         this._y.domain(yDomain);
@@ -238,8 +238,8 @@ App.InteractiveChartComponent = Ember.Component.extend({
             margin.left += 3 * rem;
 
         this._margin = margin;
-        this._contentWidth = this._totalWidth - margin.left - margin.right;
-        this._contentHeight = this._totalHeight - margin.top - margin.bottom;
+        this._contentWidth = Math.max(0, this._totalWidth - margin.left - margin.right);
+        this._contentHeight = Math.max(0, this._totalHeight - margin.top - margin.bottom);
 
         this._svg.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
 
@@ -251,12 +251,15 @@ App.InteractiveChartComponent = Ember.Component.extend({
         this._y.range([this._contentHeight, 0]);
 
         if (this._xAxis) {
+            this._xAxis.ticks(Math.round(this._contentWidth / 4 / rem));
             this._xAxis.tickSize(-this._contentHeight);
             this._xAxisLabels.attr("transform", "translate(0," + this._contentHeight + ")");
         }
 
-        if (this._yAxis)
+        if (this._yAxis) {
+            this._yAxis.ticks(Math.round(this._contentHeight / 2 / rem));
             this._yAxis.tickSize(-this._contentWidth);
+        }
 
         if (this._currentItemLine) {
             this._currentItemLine
@@ -272,7 +275,7 @@ App.InteractiveChartComponent = Ember.Component.extend({
             .call(this._brush)
         .selectAll("rect")
             .attr("y", 1)
-            .attr("height", this._contentHeight - 2);
+            .attr("height", Math.max(0, this._contentHeight - 2));
         this._updateSelectionToolbar();
     },
     _relayoutDataAndAxes: function (selection)
@@ -336,33 +339,43 @@ App.InteractiveChartComponent = Ember.Component.extend({
     },
     _computeYAxisDomain: function (startTime, endTime)
     {
-        var range = this._minMaxForAllTimeSeries(startTime, endTime);
+        var shouldShowFullYAxis = this.get('showFullYAxis');
+        var range = this._minMaxForAllTimeSeries(startTime, endTime, !shouldShowFullYAxis);
         var min = range[0];
         var max = range[1];
+
+        var highlightedItems = this.get('highlightedItems');
+        if (highlightedItems) {
+            var data = this._currentTimeSeriesData
+                .filter(function (point) { return startTime <= point.time && point.time <= endTime && highlightedItems[point.measurement.id()]; })
+                .map(function (point) { return point.value });
+            min = Math.min(min, Statistics.min(data));
+            max = Math.max(max, Statistics.max(data));
+        }
+
         if (max < min)
             min = max = 0;
+        else if (shouldShowFullYAxis)
+            min = Math.min(min, 0);
         var diff = max - min;
         var margin = diff * 0.05;
 
         yExtent = [min - margin, max + margin];
-//        if (yMin !== undefined)
-//            yExtent[0] = parseInt(yMin);
         return yExtent;
     },
-    _minMaxForAllTimeSeries: function (startTime, endTime)
+    _minMaxForAllTimeSeries: function (startTime, endTime, ignoreOutliners)
     {
-        var shouldShowFullYAxis = this.get('showFullYAxis');
-        var mainTimeSeries = this._movingAverageTimeSeries && !shouldShowFullYAxis ? this._movingAverageTimeSeries : this._currentTimeSeries;
-        var currentRange = mainTimeSeries.minMaxForTimeRange(startTime, endTime);
-        if (shouldShowFullYAxis)
-            currentRange[0] = Math.min(0, currentRange[0]);
-
-        var baselineRange = this._baselineTimeSeries ? this._baselineTimeSeries.minMaxForTimeRange(startTime, endTime) : [Number.MAX_VALUE, Number.MIN_VALUE];
-        var targetRange = this._targetTimeSeries ? this._targetTimeSeries.minMaxForTimeRange(startTime, endTime) : [Number.MAX_VALUE, Number.MIN_VALUE];
-        return [
-            Math.min(currentRange[0], baselineRange[0], targetRange[0]),
-            Math.max(currentRange[1], baselineRange[1], targetRange[1]),
-        ];
+        var seriesList = [this._currentTimeSeries, this._movingAverageTimeSeries, this._baselineTimeSeries, this._targetTimeSeries];
+        var min = Infinity;
+        var max = -Infinity;
+        for (var i = 0; i < seriesList.length; i++) {
+            if (seriesList[i]) {
+                var minMax = seriesList[i].minMaxForTimeRange(startTime, endTime, ignoreOutliners);
+                min = Math.min(min, minMax[0]);
+                max = Math.max(max, minMax[1]);
+            }
+        }
+        return [min, max];
     },
     _currentSelection: function ()
     {
@@ -372,6 +385,8 @@ App.InteractiveChartComponent = Ember.Component.extend({
     {
         var selection = this._currentSelection() || this.get('sharedSelection');
         var newXDomain = this._updateDomain();
+        if (!newXDomain)
+            return;
 
         if (selection && newXDomain && selection[0] <= newXDomain[0] && newXDomain[1] <= selection[1])
             selection = null; // Otherwise the user has no way of clearing the selection.
@@ -509,9 +524,6 @@ App.InteractiveChartComponent = Ember.Component.extend({
             var yDiff = mY - point.y;
             return xDiff * xDiff + yDiff * yDiff / 16; // Favor horizontal affinity.
         };
-        distanceHeuristics = function (m) {
-            return Math.abs(xScale(m.time) - point.x);
-        }
 
         var newItemIndex;
         if (point && !this._currentSelection()) {
@@ -610,7 +622,7 @@ App.InteractiveChartComponent = Ember.Component.extend({
                 .attr("class", "highlight")
                 .attr("r", (this.get('chartPointRadius') || 1) * 1.8);
 
-        this._updateHighlightPositions();
+        this._domainChanged();
     }.observes('highlightedItems'),
     _rangesChanged: function ()
     {
@@ -641,6 +653,7 @@ App.InteractiveChartComponent = Ember.Component.extend({
                 linkRoute: linkRoute,
                 linkId: range.get('id'),
                 label: range.get('label'),
+                status: range.get('status'),
             });
         }));
 
@@ -752,7 +765,7 @@ App.InteractiveChartComponent = Ember.Component.extend({
     },
     _updateSelectionToolbar: function ()
     {
-        if (!this.get('interactive'))
+        if (!this.get('zoomable'))
             return;
 
         var selection = this._currentSelection();