<!--
The chart-container element represents one chart and all related functionality,
including a legend listing different traces that can be plotted on the same
chart, a revision range selecting mini-chart at the bottom, and all of the alert
triaging functionality in the chart.
-->
<link rel="import" href="../../third_party/polymer/components/core-collapse/core-collapse.html">
<link rel="import" href="../../third_party/polymer/components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="chart-legend.html">
<link rel="import" href="chart-slider.html">
<link rel="import" href="chart-tooltip.html">

<polymer-element name="chart-container"
                 attributes="showCloseGraphButton chartTitle graphParams graphUncheckedParams
                             revisionInfo coreTraces selectedTraces indicesToGraph xsrfToken
                             warning alertKey showCompact collapseLegend">
  <template>
    <style>
    #container {
      width: 100%;
      display: flex;
      display: -webkit-flex;
      flex-direction: column;
      -webkit-flex-direction: column;
      align-items: center;
      -webkit-align-items: center;
      position: relative;
      min-width: 845px;  /* Minimum width of plot plus width of chart-legend. */
    }

    #container[compact] {
      min-width: 670px;  /* Minimum width of plot plus width of compacted chart-legend. */
    }

    #horizontal {
      display: flex;
      display: -webkit-flex;
      width: 100%;
      position: relative;
    }

    #chart-yaxis-label {
      transform: rotate(-90deg) translate(-50%);
      -webkit-transform: rotate(-90deg) translate(-50%);
      transform-origin: 0 0;
      -webkit-transform-origin: 0 0;
      top: 50%;
      position: absolute;
      padding-top: 5px;
      background-color: white;
      z-index: 1000;
    }

    #plots-container {
      -webkit-flex-grow: 1;
      flex-grow: 1;
      display: -webkit-flex;
      flex-direction: column;
      -webkit-flex-direction: column;
    }

    #plot {
      -webkit-flex-grow: 1;
      flex-grow: 1;
      min-height: 240px;
      min-width: 500px;
    }

    #slider {
      width: 100%;
      height: 60px;
    }

    #warning {
      position: absolute;
      left: 80px;
      top: 15px;
      z-index: 2000;
      font-size: 16px;
      font-weight: bold;
      color: #dd4b39;
    }

    #original {
      position: absolute;
      top: 10px;
      margin-left: -15px;
    }

    #rhs {
      margin-bottom: 20px;
      margin-top: 8px;
      margin-left: 5px;
      margin-right: 10px;
      padding: 16px;
      box-shadow: 0 4px 16px rgba(0,0,0,0.2);
      outline: 1px solid rgba(0,0,0,0.2);
      font-size: 11px;
      height: 246px;
      width: 312px;
      overflow: auto;
    }

    #rhs[compact] {
      width: 125px;
    }

    #rhs[collapse-legend] {
      margin-top: 8px;
      height: 25px;
      width: 25px;
      padding: 0;
    }

    #expand-legend-btn {
      position: absolute;
      right: 2px;
      top: 1px;
      opacity: .75;
    }

    #delta-off, #delta-drag {
      margin-bottom: 10px;
    }

    #traces {
      margin-bottom: 10px;
    }

    .trace-link {
      text-decoration: none;
    }

    .trace-selected {
      text-decoration: underline;
    }

    #loading-div {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: white;
      display: flex;
      display: -webkit-flex;
      align-items: center;
      -webkit-align-items: center;
      justify-content: center;
      -webkit-justify-content: center;
    }

    #anomaly-container {
      width: 0px;
      height: 0px;
      left: 0px;
      top: 0px;
      position: relative;
    }

    .anomaly {
      position: absolute;
      margin-top: -5px;
      margin-left: -1px;
      z-index: 1000;
    }

    .anomaly.highlighted {
      border: 3px solid #FFBA02;
      border-radius: 12px;
    }

    #tooltip {
      position: absolute;
      z-index: 2000;
    }

    #close-graph {
      position: absolute;
      right: 10px;
      top: 10px;
      opacity: 0;
    }

    #container:hover #close-graph {
      opacity: .75;
    }

    #container #close-graph:hover {
      opacity: 1;
      cursor: pointer;
    }
    </style>
    <div id="container" on-mouseleave="{{onMouseLeave}}" compact?="{{showCompact}}">
      <h3 id="chart-title">{{chartTitle}}</h3>
      <img src="/closebox_large.png"
           hidden?="{{!showCloseGraphButton}}"
           id="close-graph"
           on-click="{{closeGraphClicked}}">
      <div id="horizontal">
        <div id="chart-yaxis-container">
          <div id="chart-yaxis-label">{{chartYAxisLabel}}</div>
        </div>
        <div id="anomaly-container"></div>
        <chart-tooltip id="tooltip"
                       xsrfToken="{{xsrfToken}}"
                       hidden></chart-tooltip>
        <div id="plots-container">
          <div id="plot"></div>
          <chart-slider id="slider" on-revisionrange="{{onRevisionRange}}"></chart-slider>
        </div>
        <span hidden?="{{!warning}}" id="warning">{{warning}}</span>
        <a hidden id="original"
           on-click="{{onViewOriginal}}"
           href="javascript:void(0);">View original graph</a>

        <div id="rhs" compact?="{{showCompact}}" collapse-legend?="{{collapseLegend}}">
          <paper-icon-button id="expand-legend-btn" icon="arrow-drop-down" title="legend" role="button"
                             aria-label="menu" on-click="{{toggleLegend}}"></paper-icon-button>
          <core-collapse id="collapsible-legend" opened?="{{!collapseLegend}}">
            <div id="delta-off">Click and drag graph to measure or zoom.</div>
            <div id="delta-drag" hidden>
              Delta: {{deltaAbsolute}} or {{deltaPercent}}%.<br>
              Click selected range to zoom.
            </div>
            <div id="traces">Traces:
              <a href="javascript:void(0);"
                 class="trace-link"
                 on-click="{{onSelectAll}}">select all</a>
              &#124;
              <a href="javascript:void(0);"
                 class="trace-link"
                 on-click="{{onDeselectAll}}">deselect all</a>
              &#124;
              <a href="javascript:void(0);"
                 class="trace-link"
                 on-click="{{onSelectCore}}">core only</a>
            </div>
            <chart-legend tests={{legendTests}}
                          indicesToGraph={{indicesToGraph}}
                          coreEndIndex={{coreEndIndex}}
                          disableUnselected={{loadingUnselected}}>
          </core-collapse>
        </div>
      </div>
      <div id="loading-div">
        <img src="//www.google.com/images/loading.gif">
      </div>
    </div>
  </template>
  <script>
    (function() {

      // Minimum multiple standard deviation for a value to be considered
      // an outlier.
      var MULTIPLE_OF_STD_DEV = 5;

      /**
       * Gets the mean for list of numbers.
       *
       * @return {number} A number.
       */
      function calculateMean(values) {
        var len = values.length;
        var sum = values.reduce(function(v1, v2) { return v1 + v2;}, 0);
        return sum / len;
        var squaredDevianceSum = values.reduce(
            function(v1, v2) {return v1 + Math.pow(v2 - mean, 2);}, 0);
        var variance = squaredDevianceSum / len;
        var std = Math.sqrt(variance);
        return {mean: mean, std: std};
      }

      /**
       * Gets standard deviation for list of numbers and a mean.
       *
       * @return {number} A number.
       */
      function calculateStdDev(values, mean) {
        var squaredDevianceSum = values.reduce(
            function(v1, v2) {return v1 + Math.pow(v2 - mean, 2);}, 0);
        var variance = squaredDevianceSum / values.length;
        return Math.sqrt(variance);
      }

      /**
       * Finds outliers in a series, along with their directions.
       *
       * An outlier is defined as a value that deviates from the mean by over
       * MULTIPLE_OF_STD_DEV times the standard deviation. An outlier direction
       * is either 1 for positive, -1 for negative and 0 for non-outlier.
       *
       * Example:
       * Input values: [50, 50, 50, 100, 50, 10, 50, 50, 50]
       * Output directions: [0, 0, 0, 1, 0, -1, 0, 0, 0]
       *
       * @param {Array.<number>} values List of numbers.
       * @return {Array.<number>} List of outlier directions.
       */
      function getOutlierDirections(values) {
        var mean = calculateMean(values);
        var stddev = calculateStdDev(values, mean);
        var outlierDirections = [];
        for (var i = 0; i < values.length; i++) {
          var direction = 0;
          var value = values[i];
          var multDevFromMean = Math.abs(value - mean) / stddev;
          if (multDevFromMean > MULTIPLE_OF_STD_DEV) {
            if (value >= mean) {
              direction = 1;
            }
            direction = -1;
          }
          outlierDirections.push(direction);
        }
        return outlierDirections;
      }

      /**
       * Returns a date corresponding to the given timestamp, or null.
       * @param {string} rev A string that may contain a timestamp.
       * @return {(Date|null)} A date object if a timestamp was given, or
       *     null.
       */
      function getDateDisplay(rev) {
        var timestampSecondsRegex = /^[\d]{10}$/;
        var timestampMillisecondsRegex = /^[\d]{13}$/;
        var d = null;
        if (timestampSecondsRegex.test(rev)) {
          d = new Date(rev * 1000);
        } else if (timestampMillisecondsRegex.test(rev)) {
          d = new Date(rev);
        }
        if (d) {
          return d.toISOString();
        }
        return null;
      };

      /**
       * Returns a string to display, given a string that contains a
       * revision. This will be different depending on whether the given
       * revision is a git hash, a timestamp, or other.
       * Note: this is similar to the getDisplayRevision function for the
       * embed page (defined in static/embed.js)
       * @param {string|boolean} rev A string containing a "revision".
       *     False may also be passed, in which case it doesn't matter what
       * @return {string} A string to display for the given revision.
       */
      function getDisplayRevision(rev) {
        // Truncate git sha1 to 7 chars.
        var gitRegex = /^[a-f0-9]{40}$/;
        if (gitRegex.test(rev)) {
          return rev.substring(0, 7);
        }
        var d = getDateDisplay(rev);
        if (d) {
          return d;
        }
        return rev;
      };

      /**
       * Formats numbers in a human-readable way.
       * @param {(number|string)} val
       * @return {string}
       */
      function formatNumber(val) {
        // Truncate to at most 3 decimal points. Don't use toFixed() because
        // we don't want to add precision if it's not there.
        val = Math.round(val * 1000) / 1000;
        return val.toLocaleString()
      };

      Polymer('chart-container', {
        // The data fetched from the graph_json handler for this chart.
        /** @type {(Object|null)} */
        json: null,

        // The data from graph_json for unselected series.
        unselectedJson: null,

        // The colors of the series lines, used in the chart options.
        // Colors should be updated both here and in the chart-legend CSS.
        lineColors: [
          '#4d90fe', '#ffe83b', '#8e4efe', '#ffb83b', '#194fa5',
          '#a69413', '#4c19a5', '#a67113', '#9dc3ff', '#fff293',
          '#c19dff', '#ffd893', '#5b81bf', '#bfb251', '#805bbf',
          '#bf9751', '#79adff', '#ffee6c', '#aa7aff', '#ffca6c',
          '#3415b0', '#04819e', '#b40097', '#ffcf00', '#1c0772',
          '#38b2ce', '#750062', '#a68700', '#846fd7', '#60b9ce',
          '#d962c7', '#ffe573', '#3e2d84', '#206676', '#872277',
          '#bfa430', '#6549d7', '#015367', '#d936c0', '#ffdb40'
        ],

        /**
         * Initializes the chart-container element and all of its properties.
         *
         * This is a custom element lifecycle callback that's called when an
         * instance of the element is ready.
         * http://www.polymer-project.org/polymer.html#lifecyclemethods
         *
         * We use 'ready' instead of 'created' to know when the element has its
         * bindings, Shadow DOM has been created, and its on-* handlers and
         * property observers have been set up.
         * See https://github.com/Polymer/polymer/releases/tag/v0.0.20131025
         */
        ready: function() {
          // Data series index of the point that was most recently clicked.
          this.currentItem = null;

          // The data fetched from the graph_json handler for this chart,
          // for selected and non-selected series.
          this.json = null;
          this.unselectedJson = null;

          // Whether or not the non-selected traces are currently being loaded.
          this.loadingUnselected = false;

          // Meta-data about tests, which will be displayed in the legend.
          this.legendTests = [];

          // List of indices of series which are selected and will be plotted.
          this.indicesToGraph = [];

          // See updateIndiciesToGraph and indicesToGraphChanged.
          this.sendCheckedEvent = true;

          // Text to display above this chart and next to the y-axis.
          this.chartTitle = '';
          this.chartYAxisLabel = '';

          // Y-axis delta of current zoom selection, as an absolute number
          // and as a percentage of the original selection.
          this.deltaAbsolute = 0;
          this.deltaPercent = 0;

          // Information about the last selection range.
          this.lastSelectedDelta = null;

          // Whether or not the user is currently selecting a range.
          this.selecting = false;

          // Y-axis start value in the last selection range.
          this.firstSelectedValue = 0;

          // Whether or not the tooltip is "sticky". Sticky means that it will
          // stay visible when the user is no longer hovering over the point.
          this.stickyTooltip = false;

          // Map of series indexes to arrays with revision information.
          this.revisionMap = null;

          // Warning text to be shown over the chart, if any.
          this.warning = null;

          // Whether or not the chart can currently be drawn.
          this.drawable = true;

          // The Flot Plot object, returned by $.plot.
          this.chart = null;

          // Handler for the 'resize' event.
          this.resizeHandler = this.onResize.bind(this);

          // Timeout ID of the timer used by this.resizeHandler.
          this.resizeTimer = null;

          // Chart options to be given when initializing the Flot chart.
          // See: https://github.com/flot/flot/blob/master/API.md#plot-options
          this.chartOptions = {
            grid: {
              hoverable: true,
              clickable: true,
              borderWidth: 1,
              borderColor: 'rgba(0, 0, 0, 0.5)'
            },
            crosshair: {
              mode: 'xy',
              color: 'rgba(34, 34, 34, 0.3)',
              lineWidth: 0.3
            },
            xaxis: {
              tickFormatter: this.formatXAxis.bind(this)
            },
            yaxis: {
              labelWidth: 60,
              tickFormatter: this.formatYAxis.bind(this)
            },
            selection: {
              mode: 'y'
            },
            colors: this.lineColors
          };

          this.$.tooltip.addEventListener(
              'triaged', this.onBugTriaged.bind(this), true);
          this.$.tooltip.addEventListener(
              'alertChangedRevisions', this.onAlertChangedRevisions.bind(this),
              true);

          window.addEventListener('resize', this.resizeHandler);
          if (this.graphParams && Object.keys(this.graphParams).length) {
            this.graphParamsChanged();
          }
          if (this.graphUncheckedParams && Object.keys(this.graphUncheckedParams).length) {
            this.graphUncheckedParamsChanged();
          }

          this.initializePlotEventListeners();
        },

        /**
         * Binds event handlers for events that are fired by flot.
         */
        initializePlotEventListeners: function() {
          var plot = $(this.$.plot);
          plot.bind('plotselected', this.onPlotSelected.bind(this));
          plot.bind('plotselecting', this.onPlotSelecting.bind(this));
          plot.bind('plotunselected', this.onPlotUnselected.bind(this));
          plot.bind('plotclick', this.onPlotClick.bind(this));
          plot.bind('plothover', this.onPlotHover.bind(this));
        },

        /**
         * A custom element lifecycle callback, called when an instance of the
         * element is removed from the DOM.
         * See: http://www.polymer-project.org/polymer.html#lifecyclemethods
         */
        leftView: function() {
          this.drawable = false;
          window.removeEventListener('resize', this.resizeHandler);
        },

        /**
         * Handler for the click event of X button on the top-right corner.
         */
        closeGraphClicked: function() {
           this.parentNode.removeChild(this);
           this.fire('closeGraph')
        },

        /**
         * Handler for 'revisionrange' event, fired when revision range
         * changes.
         *
         * This event is fired by the chart-slider element. When this
         * event is fired, it indicates that a new start and end revision have
         * been selected.
         * Note: The properties 'graphParams' and 'graphUncheckedParams' are
         * both set in graph.js.
         *
         * @param {Event} event The revisionrange event.
         * @param {Object} detail The detail object given when firing the
         *     event. This is set in graph.js and it contains 'startrev' and
         *     'endrev'.
         * @param {Object} sender
         */
        onRevisionRange: function(event, detail, sender) {
          newGraphParams = deepCopy(this.graphParams);
          newUncheckedParams = deepCopy(this.graphUncheckedParams);
          delete newGraphParams['rev'];
          delete newUncheckedParams['rev'];
          delete newGraphParams['num_points'];
          delete newUncheckedParams['num_points'];
          newGraphParams['start_rev'] = detail.startrev;
          newUncheckedParams['start_rev'] = detail.startrev;
          newGraphParams['end_rev'] = detail.endrev;
          newUncheckedParams['end_rev'] = detail.endrev;
          this.graphParams = newGraphParams;
          this.graphUncheckedParams = newUncheckedParams;
        },

        /**
         * Updates the chart based on the graphParams property.
         *
         * This method is called when the graphParams property changes;
         * It's also called directly when the chart is first initialized.
         * The graphParams property should be set by the page that created
         * this chart-container element.
         */
        graphParamsChanged: function() {
          console.debug('graphParamsChanged', this);
          if (!this.graphParams || !Object.keys(this.graphParams).length) {
            return;
          }
          this.hideTooltipEvenIfSticky();
          this.$['anomaly-container'].innerHTML = '';
          this.$['loading-div'].style.display = '';
          this.json = null;
          this.indicesToGraph = [];
          var firstTestTestPath = this.graphParams.masters[0] + '/' +
                                  this.graphParams.bots[0] + '/' +
                                  this.graphParams.tests[0];
          this.$.slider.testpath = firstTestTestPath;

          // Make a request to /graph_json for the new set of checked graphs.
          var postdata =
              'graphs=' + encodeURIComponent(JSON.stringify(this.graphParams));
          var req = new XMLHttpRequest();
          var self = this;
          req.onload = function() {
            self.json = JSON.parse(req.responseText);
            if (self.unselectedJson) {
              self.mergeJson();
            }
            self.updateForNewJson();
          };
          req.open('post', '/graph_json', true);
          req.setRequestHeader('Content-type',
                               'application/x-www-form-urlencoded');
          req.send(postdata);
        },

        /**
         * This is called when the property 'graphUncheckedParams' changes.
         * Note: The property 'graphUncheckedParams' is set in graph.js.
         */
        graphUncheckedParamsChanged: function() {
          if (!this.graphUncheckedParams ||
              !Object.keys(this.graphUncheckedParams).length) {
            return;
          }
          this.unselectedJson = null;
          this.loadingUnselected = true;

          // Make a request to /graph_json for the new set of unchecked graphs.
          var postdata = 'graphs=' +
              encodeURIComponent(JSON.stringify(this.graphUncheckedParams));
          var req = new XMLHttpRequest();
          var self = this;
          req.onload = function() {
            self.unselectedJson = JSON.parse(req.responseText);
            self.loadingUnselected = false;
            if (self.json) {
              self.mergeJson();
            }
          };
          req.open('post', '/graph_json', true);
          req.setRequestHeader('Content-type',
                               'application/x-www-form-urlencoded');
          req.send(postdata);
        },

        /**
         * Updates the contents of this.json with the contents of
         * this.unselectedJson.
         */
        mergeJson: function() {
          if (this.json.warning && !this.unselectedJson.warning) {
            // Some data is stale/non-existent in the checked traces, but not
            // in unchecked.
            this.json.warning = null;
            this.warning = null;
          }
          for (var series = 0; series < this.json.data.length; series++) {
            if (this.json.data[series].data.length == 0) {
              // The main json was empty for this index;
              // copy it from unselected.
              this.json.data[series].data =
                  this.unselectedJson.data[series].data;
              this.json.annotations[series] =
                  this.unselectedJson.annotations[series];
              this.json['error_bars'][series] =
                  this.unselectedJson['error_bars'][series];
            }
          }
          this.updateSmartAutoscaleMap();
        },

        /**
         * Updates the chart when new data has been received from /graph_json.
         * Note: Properties 'coreTraces' and 'selectedTraces' are set in
         * graph.js.
         */
        updateForNewJson: function() {
          console.debug('updateForNewJson', this);
          if (!this.drawable) {
            return;
          }

          this.warning = this.json.warning;
          var tests = [];
          var series = this.json.annotations.series;

          if (series.length == 0) {
            this.$['loading-div'].style.display = 'none';
            return;
          }

          this.coreEndIndex = -1;
          for (var i = 0; i < series.length; i++) {
            if (this.coreTraces[series[i].name]) {
              this.coreEndIndex = i;
            }
            tests.push({
              name: series[i].name,
              path: series[i].path,
              direction: series[i].better,
              units: series[i].units,
              description: series[i].description,
              testColorClass: 'line-color-' + i,
              index: i,
              selected: true
            });
            if (this.selectedTraces[series[i].name]) {
              this.indicesToGraph.push(i);
            }
            // Flot's getData() method can return the data series out of order,
            // so maintain an index so that we can get back to the original
            // data series on click and hover events.
            this.json.data[i].index = i;
          }
          this.legendTests = tests;
          this.updateYAxisLabel();
          this.updateSmartAutoscaleMap();
          this.updateChart();
          this.$['loading-div'].style.display = 'none';
        },

        /**
         * Sets the Y-axis label based on the units of the data.
         */
        updateYAxisLabel: function() {
          // If the series annotations are properly populated, then there will
          // be at least one entry and it will have the properties 'units' and
          // 'better'. All traces in one chart should have the same units.
          var series = this.json.annotations.series;

          if (series[0].units) {
            this.chartYAxisLabel = series[0].units;
            // Some unit names have improvement direction information in them.
            if (series[0].units.indexOf('is better') == -1 &&
                series[0].better) {
              this.chartYAxisLabel += ' (' + series[0].better.toLowerCase();
              this.chartYAxisLabel += ' is better)';
            }
          }
        },

        /**
         *  Updates the map of series index to the adjusted scale.
         *
         *  This map is used to update y-axis scale base on selected traces.
         */
        updateSmartAutoscaleMap: function() {
          this.yAxisScaleMap = {};
          var numSeries = this.json.data.length;
          for (var seriesIndex = 0; seriesIndex < numSeries; seriesIndex++) {
            var data = this.json.data[seriesIndex].data;
            var values = [];
            for (var dataIndex = 0; dataIndex < data.length; dataIndex++) {
              values.push(data[dataIndex][1]);
            }
            if (values.length > 0) {
              var scale = this.determineMinMax(seriesIndex, values);
              this.yAxisScaleMap[seriesIndex] = scale;
            }
          }
        },

        /**
         * Determines a min and a max from a list of numbers without outliers.
         *
         * @param {number} seriesIndex Index into the data series list
         *     (this.json.data).
         * @param {Array.<number>} values List of series data values.
         * @return {Object} An object containing min and max number.
         */
        determineMinMax: function(seriesIndex, values) {
          values = values.filter(function(v) {
            return v != null;
          });
          var outlierDirections = getOutlierDirections(values);

          // Exclude value that is a stand-alone spike which has either
          // outlier direction 1 or -1 in between zeroes. Also include
          // points that has an Anomaly.
          var resultValues = [];
          for (var i = 0; i < outlierDirections.length; i++) {
            var direction = outlierDirections[i];
            if (direction == 0 || this.hasAnomaly(seriesIndex, i)) {
              resultValues.push(values[i]);
            } else if (i > 0 && i < outlierDirections.length - 1) {
              if (direction == outlierDirections[i-1] ||
                  direction == outlierDirections[i+1]) {
                resultValues.push(values[i]);
              }
            }
          }
          return {'min': Math.min.apply(Math, resultValues),
                  'max': Math.max.apply(Math, resultValues)};
        },

        /**
         * Checks whether a series at a point has an anomaly.
         */
        hasAnomaly: function(seriesIndex, dataIndex) {
          var annotations = this.json.annotations;
          if (!annotations[seriesIndex] ||
              !annotations[seriesIndex][dataIndex] ||
              !annotations[seriesIndex][dataIndex]['g_anomaly']) {
            return false;
          }
          return true;
        },

        /**
         * Sets scale for chart's y-axis for graphs in indicesToGraph.
         * This function sets values in this.chartOptions based on the
         * contents of this.yAxisScaleMap.
         */
        setSmartAutoscale: function() {
          if (!this.indicesToGraph.length || this.indicesToGraph.length <= 0 ||
              !this.yAxisScaleMap) {
            return;
          }

          // Get the min/max of the min/max of all graphs in indicesToGraph.
          var firstIndex = this.indicesToGraph[0];
          if (!(firstIndex in this.yAxisScaleMap)) {
            return;
          }
          var min = this.yAxisScaleMap[firstIndex].min;
          var max = this.yAxisScaleMap[firstIndex].max;
          for (var i = 0; i < this.indicesToGraph.length; i++) {
            var scale = this.yAxisScaleMap[this.indicesToGraph[i]];
            if (scale && scale.min < min) {
              min = scale.min;
            }
            if (scale && scale.max > max) {
              max = scale.max;
            }
          }
          this.chartOptions.yaxis.min = min;
          this.chartOptions.yaxis.max = max;
          this.addAxisMargin(this.chartOptions.yaxis);
        },

        /**
         * Adds margins to axis so lines don't touch the chart's borders.
         * Same as how flot does it.
         *
         * @param {Object} axis An object containing min and max number.
         */
        addAxisMargin: function(axis) {
          var margin = 0.2; // Flot's default for autoscaleMargin.
          var min = axis.min, max = axis.max;
          var delta = max - min;
          if (delta == 0.0) {
            min -= axis.min == 0 ? 1 : margin;
            max += axis.max == 0 ? 1 : margin;
          } else {
            min -= delta * margin;
            if (min < 0 && axis.min >= 0)
              min = 0;
            max += delta * margin;
            if (max > 0 && axis.max <= 0)
              max = 0;
          }
          axis.min = min;
          axis.max = max;
        },

        /**
         * Updates the list of indices of traces to plot without firing an
         * event. Note: This method is called in graph.js.
         * @param {Array.<number>} indices List of indices of traces.
         */
        updateIndicesToGraph: function(indices) {
          // Update this.indicesToGraph without causing a
          // 'checkedTracesChanged' event to be fired.
          this.sendCheckedEvent = false;
          this.indicesToGraph = indices;
          this.updateChart();
        },

        /**
         * This method is called when the property 'indicesToGraph' changes.
         * @param {(Array.<number>|null)} oldValue Old value of indicesToGraph.
         */
        indicesToGraphChanged: function(oldValue) {
          if (!oldValue || !this.json) {
            // Just initializing.
            return;
          }
          this.updateChart();
          this.updateChartTitle();
          var tests = [];
          var series = this.json.annotations.series;
          for (var i = 0; i < this.indicesToGraph.length; i++) {
            if (series[this.indicesToGraph[i]]) {
              tests.push(series[this.indicesToGraph[i]].name);
            }
          }

          // If indicesToGraph was changed in some way other than through the
          // updateIndicesToGraph method, fire a checkedTracesChanged event.
          // Note: The 'checkedTracesChanged' event is listened for and handled
          // in graph.js.
          if (this.sendCheckedEvent) {
            this.fire('checkedTracesChanged', {
              'indices': this.indicesToGraph,
              'tests': tests
            });
          }
          this.sendCheckedEvent = true;
        },

        /**
         * Sets the title of the chart based on the current state of the chart.
         */
        updateChartTitle: function() {
          this.chartTitle = makeChartTitle(
              this.getTestPaths(),
              this.getSelectedTestPaths());
        },

        getTestPaths: function() {
          var testPaths = [];
          var series = this.json.annotations.series;
          for (var i = 0; i < series.length; i++) {
            testPaths.push(series[i].path);
          }
          return testPaths;
        },

        getSelectedTestPaths: function() {
          var testPaths = [];
          var series = this.json.annotations.series;
          for (var i = 0; i < this.indicesToGraph.length; i++) {
            var selectedIndex = this.indicesToGraph[i];
            if (series[selectedIndex]) {
              testPaths.push(series[selectedIndex].path);
            }
          }
          return testPaths;
        },

        /**
         * This method is called when the property 'warning' changes.
         * If there's a warning, we want to update the background color of the
         * chart.
         */
        warningChanged: function() {
          if (this.warning) {
            this.chartOptions.grid.backgroundColor = '#e6e6e6';
          } else {
            this.chartOptions.grid.backgroundColor = null;
          }
          if (this.chart) {
            this.chart.getOptions().grid.backgroundColor =
                this.chartOptions.grid.backgroundColor;
            this.chart.setupGrid();
            this.chart.draw();
          }
        },

        /**
         * Updates the currently displayed chart.
         */
        updateChart: function() {
          if (!this.drawable) {
            return;
          }

          var data = this.getDataForFlot();
          if (data.length == 0) {
            this.chart = $.plot(this.$.plot, data, this.chartOptions);
            return;
          }

          var startRev = uri.getParameter('start_rev')
          var endRev = uri.getParameter('end_rev');
          var firstSeriesIsEmpty = data[0].data.length == 0;
          if (startRev && endRev && firstSeriesIsEmpty) {
            this.warning = 'Data not available for revision range ' +
                           startRev + ':' + endRev + '.';
          }

          var isNotZoomedIn = this.$.original.hidden;
          if (isNotZoomedIn) {
            this.setSmartAutoscale();
          }

          this.createFixedXAxis(data);
          this.chart = $.plot(this.$.plot, data, this.chartOptions);
          this.showAlerts();
        },

        /**
         * Puts together the array of series to pass to Flot's $.plot function.
         * The data to plot is based on this.json and this.indicesToGraph.
         * @return {Array.<Object>} Data to plot. This could be an empty array.
         */
        getDataForFlot: function() {
          if (!this.json) {
            console.debug('getDataForFlot: this.json not set.');
            return [];
          }
          if (!this.json['data'] || !this.json['error_bars']) {
            console.debug('getDataForFlot: data or error bars not set.');
            return [];
          }

          var data = [];
          for (var i = 0; i < this.indicesToGraph.length; i++) {
            var index = this.indicesToGraph[i];
            if (index >= 0 && this.json.data[index]) {
              data.push(deepCopy(this.json.data[index]));
            } else {
              console.debug('getDataForFlot: indicesToGraph: ',
                            this.indicesToGraph);
              return [];
            }
          }

          // Add in error bars after data.
          for (var i = 0; i < this.indicesToGraph.length; i++) {
            var index = this.indicesToGraph[i];
            if (index >= 0 && this.json['error_bars'][index]) {
              data.push(deepCopy(this.json['error_bars'][index][0]));
              data.push(deepCopy(this.json['error_bars'][index][1]));
            } else {
              console.debug('getDataForFlot: indicesToGraph: ',
                            this.indicesToGraph);
              return [];
            }
          }
          return data;
        },

        /**
         * Modifies the given series data so that the X-values are indexes
         * instead of revision numbers. This is called before plotting.
         *
         * We want a fixed x-axis, with points evenly spaced. Flot has
         * functions to scale the x-axis, but they break vertical zooming.
         * So we plot a copy of the JSON we get from the server, with the
         * revisions reordered starting from 0 and incrementing once for each
         * rev.
         *
         * We start by getting a list of all the revisions, and ordering them
         * from 0-N. Because there can be gaps in the graphs, we want to look
         * at all the charts, even ones that are not plotted, so that the gaps
         * are accounted for accurately.
         *
         * TODO(qyearsley): This function has at least two separate
         * responsibilities: constructing this.revisionMap and actually
         * changing the X-values. These could be separated out.
         *
         * @param {Array.<Object>} data
         */
        createFixedXAxis: function(data) {
          // Make a map of all revisions for all data series to a series index
          // and data index.
          var allRevisions = {};
          if (!this.json || !this.json.data) {
            console.debug('createFixedXAxis: !this.json or !this.json.data.');
            return;
          }
          for (var jsonSeriesIndex = 0;
               jsonSeriesIndex < this.json.data.length;
               jsonSeriesIndex++) {
            var series = this.json.data[jsonSeriesIndex];
            var numPoints = series.data.length;
            for (var dataIndex = 0; dataIndex < numPoints; dataIndex++) {
              var revision = series.data[dataIndex][0];
              allRevisions[revision] = [series.index, dataIndex];
            }
          }

          // Make an ordered list of all revision numbers for any series.
          var orderedRevisions = Object.keys(allRevisions).sort(function(a, b) {
            return a - b;
          });
          if (orderedRevisions.length == 0) {
            // If there's no data to plot, then this array will be empty.
            return;
          }
          this.$.slider.startrev = orderedRevisions[0];
          this.$.slider.endrev = orderedRevisions[orderedRevisions.length - 1];

          // We keep a map of the ordered revision index to the [revision,
          // series index, data index] so that it's easy to show the right
          // label on the X-axis. This is updated here but used in formatXAxis.
          this.revisionMap = {};

          // We also want to make a reverse-lookup object which maps values in
          // in |orderedRevisions| to their indexes. This will be used below.
          var revisionToIndexMap = {};

          for (var i = 0; i < orderedRevisions.length; i++) {
            var rev = orderedRevisions[i];
            this.revisionMap[i] =
                [rev, allRevisions[rev][0], allRevisions[rev][1]];
            revisionToIndexMap[rev] = i;
          }

          // Now that we have all the data we need cached, update the revisions
          // for each of the data points that will be shown on the graph.
          for (var seriesIndex = 0; seriesIndex < data.length; seriesIndex++) {
            var series = data[seriesIndex];
            var numPoints = series.data.length;
            for (var dataIndex = 0; dataIndex < numPoints; dataIndex++) {
              var revision = series.data[dataIndex][0];
              series.data[dataIndex][0] = revisionToIndexMap[revision];
            }
          }
          this.chartOptions.xaxis.minTickSize = orderedRevisions.length / 10;
        },

        /**
         * Formats numbers that are displayed at ticks on the X-axis.
         *
         * If there are annotations for the first data series and for this point
         * there is a revision type specified by "a_default_rev", then we can
         * display that on the x-axis. Otherwise, we can just use the revision
         * (point ID) as-is.
         *
         * Note: This is similar to xAxisTickFormatter in embed.js.
         *
         * @param {number} val An X-value.
         * @param {Object} axis Not used.
         * @return {string} A string that should be shown on the X-axis.
         */
        formatXAxis: function(val, axis) {
          var lookupIndex = Math.round(Math.max(val, 0));
          if (!this.revisionMap) {
            // this.revisionMap may not yet be set by this.createFixedXAxis.
            return '';
          }
          var lookup = this.revisionMap[lookupIndex];
          if (!lookup) {
            return '';
          }
          var rev = lookup[0];
          var seriesIndex = lookup[1];
          var dataIndex = lookup[2];

          var annotations = this.json.annotations;
          if (annotations[seriesIndex] && annotations[seriesIndex][dataIndex]) {
            var annotation = annotations[seriesIndex][dataIndex];
            var defaultRev = annotation['a_default_rev'];
            if (defaultRev && annotation[defaultRev]) {
              return getDisplayRevision(annotation[defaultRev]);
            }
          }
          return getDisplayRevision(rev);
        },

        /**
         * Formats numbers that are displayed at ticks on the Y-axis.
         * @param {(number|string)} val A Y value.
         * @param {Object} axis Not used.
         * @return {string}
         */
        formatYAxis: function(val, axis) {
          return formatNumber(val);
        },

        /**
         * Displays alerts on the chart.
         */
        showAlerts: function() {
          // Clear out old anomalies.
          var container = this.$['anomaly-container'];
          container.innerHTML = '';

          var minHeight = this.chart.getAxes().yaxis.min;
          var maxHeight = this.chart.getAxes().yaxis.max;
          var xOffset = this.chartOptions.yaxis.labelWidth;

          var flotData = this.chart.getData();
          var annotations = this.json.annotations;
          for (var flotSeriesIndex = 0;
               flotSeriesIndex < flotData.length;
               flotSeriesIndex++) {
            var jsonSeriesIndex = flotData[flotSeriesIndex].index;
            if (jsonSeriesIndex == null || !annotations[jsonSeriesIndex]) {
              continue;
            }
            for (var dataIndex = 0;
                 dataIndex < flotData[flotSeriesIndex].data.length;
                 dataIndex++) {
              // TODO(qyearsley): Extract the inside of this loop.
              if (!annotations[jsonSeriesIndex][dataIndex] ||
                  !annotations[jsonSeriesIndex][dataIndex]['g_anomaly'] ||
                  flotData[flotSeriesIndex].data[dataIndex][1] < minHeight ||
                  flotData[flotSeriesIndex].data[dataIndex][1] > maxHeight) {
                continue;
              }
              var annotation = annotations[jsonSeriesIndex]
                  [dataIndex]['g_anomaly'];
              var bugId = annotation['bug_id'];
              var improvement = annotation['improvement'];
              var recovered = annotation['recovered'];
              var key = annotation.key;
              var src = '/black_alert.png';
              if (!bugId && !improvement) {
                src = '/red_alert.png';
              } else if (!bugId && improvement) {
                src = '/green_alert.png';
              }

              var left = xOffset + Math.round(
                  flotData[flotSeriesIndex].xaxis.p2c(
                      flotData[flotSeriesIndex].data[dataIndex][0]));
              var top = Math.round(
                  flotData[flotSeriesIndex].yaxis.p2c(
                      flotData[flotSeriesIndex].data[dataIndex][1]));

              var img = document.createElement('img');
              img.src = src;
              img.style.left = left + 'px';
              img.style.top = top + 'px';
              if (bugId && bugId < 0 || recovered) {
                // Triaged as invalid, ignored, or recovered; lower opacity.
                img.style.opacity = 0.4;
              }
              img.classList.add('anomaly');
              // alertKey is an optional attribute to specify that this chart
              // is associated with an alert.
              if (this.alertKey == key) {
                 img.classList.add('highlighted');
              }
              img.onmouseover = this.showTooltip.bind(
                  this, flotSeriesIndex, dataIndex);
              img.onclick = this.onAlertClick.bind(
                  this, flotSeriesIndex, dataIndex);
              this.$['anomaly-container'].appendChild(img);
            }
          }
        },

        /**
         * Handler for 'mouseleave' event, hides the tooltip.
         */
        onMouseLeave: function(event) {
          this.hideTooltip();
        },

        /**
         * Handler for 'plotselected' event, fired when a plot selection is
         * made.
         * For more information about selection in flot, see:
         * http://www.flotcharts.org/flot/jquery.flot.selection.js
         * @param {Event} event
         * @param {Object} ranges
         */
        onPlotSelected: function(event, ranges) {
          this.selecting = false;
          this.lastSelectedDelta = ranges;
        },

        /**
         * Handler for 'plotselecting' event, fired repeatedly when selecting.
         * @param {Event} event
         * @param {Object} ranges
         */
        onPlotSelecting: function(event, ranges) {
          if (!ranges) {
            return;
          }
          if (!this.selecting) {
            this.firstSelectedValue = ranges.yaxis.from;
            this.selecting = true;
          }
          this.$['delta-off'].hidden = true;
          this.$['delta-drag'].hidden = false;
          var delta = Math.abs(ranges.yaxis.to - ranges.yaxis.from);
          this.deltaAbsolute = delta.toFixed(2);
          this.deltaPercent =
              (delta * 100 / this.firstSelectedValue).toFixed(2);
        },

        /**
         * Handler for 'plotunselected' event, fired when selection is
         * cancelled.
         */
        onPlotUnselected: function() {
          this.selecting = false;
          this.$['delta-off'].hidden = false;
          this.$['delta-drag'].hidden = true;
        },

        /**
         * Handler for the 'plotclick' event, fired when the chart is clicked.
         * @param {Event} event
         * @param {Object} pos An object which contains the keys "x" and "y".
         * @param {Object} item
         */
        onPlotClick: function(event, pos, item) {
          if (this.lastSelectedDelta) {
            var from = this.lastSelectedDelta.yaxis.from;
            var to = this.lastSelectedDelta.yaxis.to;
            if (pos.y == from || pos.y == to) {
              // Flot sends a spurious click event at the end of the selection.
              return;
            }
            var min = Math.min(from, to), max = Math.max(from, to);
            if (pos.y > min && pos.y < max) {
              this.chartOptions.yaxis.min = min;
              this.chartOptions.yaxis.max = max;
              this.$.original.hidden = false;
              this.updateChart();
              this.$.original.style.left =
                  (this.$.plot.offsetWidth - 120) + 'px';
            }
            this.lastSelectedDelta = null;
          } else if (item) {
            // Click on a data point; show revision history and sticky tooltip.
            if (this.stickyTooltip && item.dataIndex == this.currentItem) {
              // hide the tooltip if the user clicks the same point again
              this.stickyTooltip = false;
              this.hideTooltip();
            } else {
              // show the tooltip if the user clicked on a new one
              this.stickyTooltip = true;
              this.currentItem = item.dataIndex;
              this.showTooltip(item.seriesIndex, item.dataIndex);
            }
          } else {
            // clicked an empty place on the graph
            this.hideTooltipEvenIfSticky();
          }
        },

        /**
         * Brings up the triage dialog when an alert circle is clicked.
         * @param {number} flotSeriesIndex Index into the flot data series
         *     array `this.chart.getData()`.
         * @param {number} dataIndex Index into an array of points.
         * @param {Event} The click event.
         */
        onAlertClick: function(flotSeriesIndex, dataIndex, event) {
          // Note: this.chart.getData() returns a list of series objects
          // (including series objects for error regions).
          var jsonSeriesIndex = this.chart.getData()[flotSeriesIndex].index;
          if (jsonSeriesIndex == null) {
            return;
          }
          var data = this.json.data[jsonSeriesIndex].data;

          // Populate the nudgeList array with information about nearby
          // revisions. Each entry in the nudgeList is an object with basic
          // information about a point.
          var nudgeList = [];
          for (var i = Math.max(1, dataIndex - 5);
               i < Math.min(dataIndex + 5, data.length -1);
               i++) {
            // Get annotation information about this nearby point.
            // This might be null if there are gaps in the data series.
            // In that case, we can just not add the point to the nudge list.
            var annotation = this.json.annotations[jsonSeriesIndex][i];
            if (!annotation) {
              continue;
            }
            var displayRevision = data[i][0];
            if (annotation['a_default_rev']) {
              displayRevision = annotation[annotation.a_default_rev];
            }
            displayRevision = getDisplayRevision(displayRevision);
            var amount = ' 0: ';
            if (i < dataIndex) {
              amount = '-' + (dataIndex - i) + ': ';
            } else if (i > dataIndex) {
              amount = '+' + (i - dataIndex) + ': ';
            }
            nudgeList.push({
              startRevision: data[i - 1][0] + 1,
              endRevision: data[i][0],
              displayEndRevision: displayRevision,
              value: Math.round(data[i][1] * 100) / 100,
              selected: i == dataIndex,
              dataIndex: i,
              amount: amount
            })
          }

          // Get the anomaly info object, and add a few fields.
          var annotation = this.json.annotations[jsonSeriesIndex][dataIndex];
          var anomalyInfo = annotation.g_anomaly;
          anomalyInfo['nudgeList'] = nudgeList;
          anomalyInfo['seriesIndex'] = jsonSeriesIndex;
          anomalyInfo['dataIndex'] = dataIndex;

          // The alerts and triaged lists are attributes of chart-tooltip
          // which are used for showing information about anomalies. The alerts
          // list is also used for showing the triage dialog.
          var alerts = null, triaged = null;
          if (anomalyInfo.bug_id) {
            triaged = [anomalyInfo];
          } else {
            alerts = [anomalyInfo];
          }

          this.stickyTooltip = true;
          this.showTooltip(flotSeriesIndex, dataIndex, alerts, triaged);
        },

        /**
         * Updates the interface when a bug is triaged.
         * This is the event handler for a 'triaged' event on the
         * chart-tooltip.
         */
        onBugTriaged: function(event) {
          var jsonSeriesIndex = event.detail.alerts[0].seriesIndex;
          var dataIndex = event.detail.alerts[0].dataIndex;
          var bugId = event.detail.bugid;
          // Update the bug id locally.
          this.json.annotations[jsonSeriesIndex][dataIndex]
              ['g_anomaly']['bug_id'] = bugId;
          this.$.tooltip.bugId = bugId;
          if (!bugId) {
            this.$.tooltip.alerts = this.$.tooltip.triagedAlerts;
            this.$.tooltip.triagedAlerts = null;
          } else {
            this.$.tooltip.alertInvalidOrIgnored = bugId < 0;
            this.$.tooltip.triagedAlerts = this.$.tooltip.alerts;
            this.$.tooltip.alerts = null;
            var data = this.json.annotations[jsonSeriesIndex][dataIndex];
            this.$.tooltip.alertKey = data['g_anomaly'].key;
          }
          // Refresh the anomalies to make the one with the new bug id black.
          this.showAlerts();
        },

        /**
         * Handler for the alertChangedRevisions event.
         *
         * The alertChangedRevisions event is fired from the triage dialog when
         * an alert is nudged.
         */
        onAlertChangedRevisions: function(event) {
          var jsonSeriesIndex = event.detail.alerts[0].seriesIndex;
          var dataIndex = event.detail.alerts[0].dataIndex;
          var newDataIndex = event.detail.newDataIndex;
          var seriesAnnotations = this.json.annotations[jsonSeriesIndex];
          var alertInfo = seriesAnnotations[dataIndex]['g_anomaly'];
          alertInfo['start_revision'] = event.detail.startRev;
          alertInfo['end_revision'] = event.detail.endRev;
          seriesAnnotations[dataIndex]['g_anomaly'] = null;
          seriesAnnotations[newDataIndex]['g_anomaly'] = alertInfo;
          this.showAlerts();
        },

        /**
         * Handler for the 'plothover' event, fired when the mouse is hovering
         * over the plot area. If the user is hovering over a point, we want to
         * show the tooltip for that point.
         * @param {Event} event
         * @param {Object} pos
         * @param {Object} item
         */
        onPlotHover: function(event, pos, item) {
          // If the current tooltip is sticky, just leave it.
          if (this.stickyTooltip) {
            return;
          }
          // If the current tooltip isn't sticky but we're hovering over
          // nothing, hide the tooltip.
          if (!item) {
            this.hideTooltip();
            return;
          }
          // If the current tooltip isn't sticky and we're over a datapoint,
          // show the tooltip.
          this.showTooltip(item.seriesIndex, item.dataIndex);
        },

        /**
         * Displays a tooltip for the given point on the graph.
         * TODO(qyearsley): Refactor, extract sub-functions.
         * NOTE: Instead of taking lists of alerts and triaged alerts, it
         * would be possible for this function to just take one alert, since
         * there should never generally be more than one alert at one point.
         * @param {number} flotSeriesIndex The index of the series in
         *     `this.chart.getData()`.
         * @param {number} dataIndex The index of the data in the series.
         * @param {Array} opt_alerts Array of alerts.
         * @param {Array} opt_triaged
         */
        showTooltip: function(
            flotSeriesIndex, dataIndex, opt_alerts, opt_triaged) {
          // Reset the properties of the tooltip so that nothing is left over
          // from the last time that showTooltip was called on another point.
          this.resetTooltip();

          // Don't show the tooltip if we're selecting a range on the y axis.
          if (this.selecting) {
            return;
          }

          var flotData = this.chart.getData();
          var jsonSeriesIndex = this.chart.getData()[flotSeriesIndex].index;
          if (jsonSeriesIndex == null) {
            console.warn('showTooltip returned after ' + jsonSeriesIndex +
                         ' was null for flotSeriesIndex ' + flotSeriesIndex);
            return;
          }

          // Set the main properties of the tooltip.
          var series = this.json.annotations.series[jsonSeriesIndex];
          var annotation = this.json.annotations[jsonSeriesIndex][dataIndex];

          // In the data from this.chart.getData(), the series indexes are
          // different, and the point x-values are all converted to indexes.
          var pointFromChart = flotData[flotSeriesIndex].data[dataIndex];

          // The data from /graph_json is the data as it originally came,
          // and the x-values are the original Row IDs.
          var seriesFromJson = this.json.data[jsonSeriesIndex];
          var pointFromJson = seriesFromJson.data[dataIndex];

          var xValue = pointFromChart[0];
          var pointId = pointFromJson[0];
          var yValue = pointFromJson[1];

          this.$.tooltip.testPath = series.path;
          this.$.tooltip.value = formatNumber(yValue);
          if (annotation.error > 0) {
            this.$.tooltip.stddev = formatNumber(annotation.error);
          }
          this.$.tooltip.pointId = pointId;
          this.$.tooltip.revisions = this.getRevisions(
              jsonSeriesIndex, dataIndex);
          this.$.tooltip.links = this.getTooltipLinks(annotation, pointId);
          if (annotation.timestamp) {
            var d = new Date(annotation.timestamp);
            this.$.tooltip.timestamp = d.toISOString();
          }

          // Set the alert-related properties of the tooltip.
          this.$.tooltip.alerts = opt_alerts;
          this.$.tooltip.triagedAlerts = opt_triaged;
          if (annotation['g_anomaly']) {
            if (annotation.g_anomaly['bug_id']) {
              this.$.tooltip.bugId = annotation['g_anomaly']['bug_id'];
              this.$.tooltip.alertInvalidOrIgnored =
                  annotation['g_anomaly']['bug_id'] < 0;
              this.$.tooltip.alertKey = annotation['g_anomaly']['key'];
            }
            this.$.tooltip.recovered = annotation['g_anomaly']['recovered'];
          }

          // Show information in the tooltip for use by the bisect button.
          if (series.path.lastIndexOf('ref') + 3 == series.path.length) {
            hideBisect = true;
          }
          bisectRevisions = this.getRevisionForBisect(
              jsonSeriesIndex, dataIndex, series.path);

          var traceRerunInfo = [];
          if (annotation['a_trace_rerun_options']) {
            for (var i in annotation['a_trace_rerun_options']) {
              var currentOption = annotation['a_trace_rerun_options'][i];
              traceRerunInfo.push({
                  'name': i,
                  'option': currentOption
              });
            }
          } else {
              traceRerunInfo.push({
                  'name': 'Default Trace Profiler',
                  'option': '--profiler=trace'
              });
          }
          this.$.tooltip.bisectInfo = {
            badRev: bisectRevisions['bad_revision'],
            goodRev: bisectRevisions['good_revision'],
            testPath: series.path,
            traceRerunInfo: traceRerunInfo
          };

          // Un-hide and position the tooltip box.
          this.$.tooltip.hidden = false;
          this.$.tooltip.style.left =
              flotData[flotSeriesIndex].xaxis.p2c(xValue) +
              this.chartOptions.yaxis.labelWidth + 20 + 'px';
          this.$.tooltip.style.top =
              flotData[flotSeriesIndex].yaxis.p2c(yValue) + 20 + 'px';
        },

        /**
         * Reset the chart-tooltip's properties.
         */
        resetTooltip: function() {
          this.$.tooltip.testPath = null;
          this.$.tooltip.value = null;
          this.$.tooltip.stddev = null;
          this.$.tooltip.pointId = null;
          this.$.tooltip.revisions = null;
          this.$.tooltip.links = null;
          this.$.tooltip.alerts = null;
          this.$.tooltip.triagedAlerts = null;
          this.$.tooltip.bugId = null;
          this.$.tooltip.alertKey = null;
          this.$.tooltip.recovered = null;
          this.$.tooltip.timestamp = null;
          this.$.tooltip.bisectInfo = null;
        },

        /**
         * Returns good and bad revisions for bisect.
         */
        getRevisionForBisect: function(index, dataIndex, testPath) {
          bisectRange = this.getDefaultRevRangeFromAnnotations(
              index, dataIndex);
          if (bisectRange) {
            return bisectRange;
          }
          var dataPoint = this.json.data[index];
          var badRev = dataPoint.data[dataIndex][0];
          if (getDateDisplay(badRev)) {
            for (var i in this.$.tooltip.revisions) {
              var revObj = this.$.tooltip.revisions[i];
              if (revObj.hasOwnProperty('name') &&
                  revObj['name'].indexOf('Chromium Git Hash') != -1) {
                return {
                  'bad_revision': revObj['end'],
                  'good_revision': revObj['start'] ? revObj['start'] : null,
                }
              }
            }
          }
          return {
            'bad_revision': badRev,
            'good_revision': dataIndex ? dataPoint.data[dataIndex - 1][0] : null,
          }
        },

        /**
         * Returns good and bad revisions for bisect by checking a_default_rev.
         * @param {number} seriesIndex Index into the this.json.annotations.
         * @param {number} dataIndex The index of the point within the series.
         * @return {Object} A map object with the keys "bad_revision" and
         *     "good_revision".
         */
        getDefaultRevRangeFromAnnotations: function(seriesIndex, dataIndex) {
          var annotations = this.json.annotations;
          if (annotations[seriesIndex] && annotations[seriesIndex][dataIndex]) {
            var badAnnotation = annotations[seriesIndex][dataIndex];
            var badDefaultRevType = badAnnotation['a_default_rev'];
            if (badDefaultRevType && badAnnotation[badDefaultRevType]) {
              if (!dataIndex) {
                return {
                    'bad_revision': badAnnotation[badDefaultRevType],
                    'good_revision': null,
                  }
              }
              var goodAnnotation = annotations[seriesIndex][dataIndex - 1];
              if (goodAnnotation) {
                var goodDefaultRevType = goodAnnotation['a_default_rev'];
                if (goodDefaultRevType == badDefaultRevType) {
                  return {
                    'bad_revision': badAnnotation[badDefaultRevType],
                    'good_revision': goodAnnotation[goodDefaultRevType],
                  }
                }
              }
            }
          }
          return null;
        },

        /**
         * Hides the tooltip only if it's not sticky.
         */
        hideTooltip: function() {
          if (this.stickyTooltip) {
            return;
          }
          this.$.tooltip.hidden = true;
        },

        /**
         * Force-hides the tooltip.
         */
        hideTooltipEvenIfSticky: function() {
          this.stickyTooltip = false;
          this.hideTooltip();
        },

        /**
         * Gets a list of obj about links to put in the tooltip.
         * @param {Object} annotation Annotation object for this point.
         * @param {number} pointId Main revision at the given point.
         * @return {Array.<Object>} List of objects with properties text and
         *     url.
         */
        getTooltipLinks: function(annotation, pointId) {
          var links = [];
          if (annotation.a_stdio_uri) {
            links.push({
                'text': 'Buildbot stdio',
                'url': annotation['a_stdio_uri']
            });
          }
          if (annotation['g_anomaly']) {
            var testPath = this.graphParams.masters[0] + '/' +
                           this.graphParams.bots[0] + '/' +
                           this.graphParams.tests[0];
            var debugUrl = '/debug_alert?test_path=' + testPath +
                           '&rev=' + pointId;
            links.push({
              'text': 'Debug alert',
              'url': debugUrl
            });
          }
          if (annotation['a_tracing_uri']) {
            links.push({
                'text': 'Trace',
                'url': annotation['a_tracing_uri']
            })
          }
          return links;
        },

        /**
         * Returns an array of revision range info objects for the given point.
         *
         * This array is used to show revision ranges and change log links in
         * the tooltip.
         * Example format for the returned array:
         *   [
         *     {
         *       name: "Chrome Revision",
         *       start: 216441,
         *       end: 216538,
         *       displayStart: 216441,
         *       displayEnd: 216538,
         *       url: "http://x.chromium.org/changelog.html?range=216441:216538",
         *     },
         *     ...
         *   ]
         *
         * @param {number} seriesIndex An index in this.json.data.
         * @param {number} dataIndex The index of the point within the series.
         * @return {Array.<Object>} An array of information needed for showing
         *     change log links for different types of revisions.
         */
        getRevisions: function(seriesIndex, dataIndex) {
          var annotationSeries = this.json.annotations[seriesIndex];
          var annotation = annotationSeries[dataIndex];
          var previousAnnotation = annotationSeries[dataIndex - 1];
          var defaultRevisionRangeInfo = null;
          var revisionRangeInfoObjects = [];
          for (var revisionTypeKey in annotation) {
            if (revisionTypeKey.indexOf('r_') != 0) {
              continue;  // Not a revision.
            }
            if (!this.revisionInfo[revisionTypeKey]) {
              console.warn('No entry', revisionTypeKey, 'in', this.revisionInfo);
              continue;
            }
            var end = annotation[revisionTypeKey];
            var start = -1;
            if (dataIndex > 0 && previousAnnotation &&
                previousAnnotation[revisionTypeKey]) {
              start = previousAnnotation[revisionTypeKey];
            }
            var revisionRangeInfo = this.getRevisionRangeInfo(
                revisionTypeKey, start, end);
            if (revisionTypeKey == annotation['a_default_rev']) {
              // The default revision type will be inserted afterwards.
              defaultRevisionRangeInfo = revisionRangeInfo;
            } else {
              revisionRangeInfoObjects.push(revisionRangeInfo);
            }
          }
          // Revisions are sorted by name, with the default first.
          revisionRangeInfoObjects.sort(function(a, b) {
            var aName = a['name'].toLowerCase();
            var bName = b['name'].toLowerCase();
            return aName.localeCompare(bName);
          });
          if (defaultRevisionRangeInfo) {
            revisionRangeInfoObjects.unshift(defaultRevisionRangeInfo);
          }
          return revisionRangeInfoObjects;
        },

        /**
         * Returns an object with revision-related information for one type
         * of revision, for two revision numbers.
         *
         * The property this.revisionInfo is set in graph.js from the global
         * variable REVISION_INFO, which is embedded based on the content of
         * chart_handler.py.
         *
         * @param {string} revisionTypeKey A key in this.revisionInfo.
         *     This will be a string starting with "r_".
         * @param {(number|string|boolean)} start Optional start revision.
         *     False may be given if the start and end revision are the same.
         * @param {(number|string)} end End revision or only revision.
         * @return {Object} The information necessary for showing a link for
         *     a change log for a particular revision range.
         */
        getRevisionRangeInfo: function(revisionTypeKey, start, end) {
          var revisionInfo = this.revisionInfo[revisionTypeKey];
          if (!revisionInfo) {
            console.warn('No entry', revisionTypeKey, 'in', this.revisionInfo);
          }
          var revisionTypeKey = revisionInfo['name'];
          var urlTemplate = revisionInfo['url'];

          if (!isNaN(start) && !isNaN(end) && Number(start) > Number(end)) {
            console.warn('Start and end revisions flipped:', start, end);
            var temp = start;
            start = end;
            end = temp;
          }

          // For a regression range, start is the "last known good" revision.
          // We want the "first possible bad" revision.
          if (!isNaN(start) && (start != end)) {
            start = Number(start) + 1;
          }

          // If the substring R1_trim is found in the URL template, we assume
          // that it's the URL template for Crome OS versions.
          var url = '';
          if (urlTemplate.indexOf('{{R1_trim}}') != -1) {
            url = this.fillInChromeOSChangeLogURL(urlTemplate, start, end);
          } else {
            url = urlTemplate.replace('{{R1}}', start).replace('{{R2}}', end);
          }

          if (start == end || !start) {
            start = false;
          }

          return {
            'name': revisionTypeKey,
            'url': url,
            'start': start,
            'end': end,
            'displayStart': getDisplayRevision(start),
            'displayEnd': getDisplayRevision(end)
          };
        },

        /**
         * Fills in a Chrome OS or Chrome version change log URL.
         * The chromeOS diff tool expects version numbers to be composed of
         * only the right-most 3 components of the number (i.e., we need to
         * drop the  left-most component when constructing the URL below).
         * The format of the specified version number should be "X.Y.Z",
         * not "W.X.Y.Z".
         * @param {string} urlTemplate A string with the template fields
         *     R1_trim and R2_trim.
         * @param {string} start Start version string.
         * @param {string} end End version string.
         */
        fillInChromeOSChangeLogURL: function(urlTemplate, start, end) {
          var urlEndVersion = end.substring(end.indexOf('.') + 1);
          var urlStartVersion = '';
          if (start) {
            urlStartVersion = start.substring(start.indexOf('.') + 1);
          } else {
            urlStartVersion = urlEndVersion;
          }
          var url = urlTemplate.replace('{{R1_trim}}', urlStartVersion);
          url = url.replace('{{R2_trim}}', urlEndVersion);
          return url;
        },

        /**
         * Handler for the click event for the 'View original graph' link.
         *
         * This link only appears after zooming in on a smaller Y-axis range
         * (by clicking and dragging and then clicking). When the 'view
         * original graph' link has been clicked, the original Y-axis range
         * should be restored.
         */
        onViewOriginal: function() {
          this.chartOptions.yaxis.min = null;
          this.chartOptions.yaxis.max = null;
          this.$.original.hidden = true;
          this.updateChart();
        },

        /**
         * Handler for the click event of the select all traces button.
         * Updates this.indicesToGraph to contain all traces.
         * @param {Event} opt_noEvent The click event, not used.
         */
        onSelectAll: function(opt_noEvent) {
          if (this.loadingUnselected) {
            // Still loading.
            return;
          }
          var series = this.json.annotations.series, indices = [];
          for (var i = 0; i < series.length; i++) {
            indices.push(i);
          }
          this.indicesToGraph = indices;
        },

        /**
         * Handler for the click event of the deselect all traces button.
         * @param {Event} opt_noEvent The click event, not used.
         */
        onDeselectAll: function(opt_noEvent) {
          this.indicesToGraph = [];
        },

        /**
         * Handler for the click event of the select core traces button.
         * Selects only the core traces (i.e. important and ref traces).
         * Note: The property 'coreTraces' is set in graph.js.
         * @param {Event} opt_event The click event, not used.
         */
        onSelectCore: function(opt_noEvent) {
          if (this.loadingUnselected) {
            // Still loading.
            return;
          }
          var series = this.json.annotations.series, indices = [];
          for (var i = 0; i < series.length; i++) {
            if (this.coreTraces[series[i].name]) {
              indices.push(i);
            }
          }
          this.indicesToGraph = indices;
        },

        /**
         * Handler for resize event.
         * @param {Event} event
         */
        onResize: function(event) {
          // Try not to resize graphs until the user has stopped resizing
          clearTimeout(this.resizeTimer);
          this.resizeTimer = setTimeout(this.resizeGraph.bind(this), 100);
        },

        /**
         * Resizes the chart if it's present.
         */
        resizeGraph: function() {
          if (!this.chart) {
            return;
          }
          // The chart is resized when it's updated.
          this.updateChart();
         },

        /**
         * On collapseLegend change, updates graph and chart-revision sizes.
         */
        collapseLegendChanged: function() {
          this.onResize();
          this.$.slider.onResize();
        },

        /**
         * Toggles legend window to collapse or expand.
         */
        toggleLegend: function() {
          this.$['collapsible-legend'].toggle();
          this.collapseLegend = !this.collapseLegend;
        }
      });
    })();
  </script>
</polymer-element>
