function Graphs(aggChartElem, rawChartElem, histoChartElem, numEmbedGraphs,
    aggResize, instantInfoElem, buttonColumnElem, loadingSpinnerElem, stackAgg,
    headerLinksElem, graphsContainerElem, dataRangeWidgetsElem,
    aggregateResizeButtonDivElem, lowerThirdsElem, metricButtonsElem,
    metricSelectorIdPrefix, metricButtonsDivId, checkAllButtonId) {
  this.aggChartElem_ = $(aggChartElem);
  this.rawChartElem_ = $(rawChartElem);
  this.histoChartElem_ = $(histoChartElem);
  this.srcList = null;
  this.numEmbedGraphs = numEmbedGraphs;
  this.aggResize = aggResize;  // Updated in a session by this.makeAggResize().
  this.instantInfoElem = $(instantInfoElem);
  this.buttonColumnElem = $(buttonColumnElem);

  this.loadingSpinnerElem = $(loadingSpinnerElem);

  // For page resizing only.
  this.headerLinksElem = $(headerLinksElem);
  this.graphsContainerElem = $(graphsContainerElem);
  this.dataRangeWidgetsElem = $(dataRangeWidgetsElem);
  this.aggregateResizeButtonDivElem = $(aggregateResizeButtonDivElem);
  this.lowerThirdsElem = $(lowerThirdsElem);

  this.metricButtonsElem = $(metricButtonsElem);
  this.metricSelectorIdPrefix = metricSelectorIdPrefix;
  this.metricButtonsDivId = metricButtonsDivId;
  this.checkAllButtonId = checkAllButtonId;

  this.visibilityArray = null;
  // Old-style metrics-to-display list from URL.
  this.urlVisibilityArray = null;

  this.aggChart = null;
  this.rawChart = null;
  this.histoChart = null;

  this.rawChartHasRealData = null;
  this.histoChartHasRealData = null;

  this.aggData = null;  // The raw, precomputed aggregate data.
  // This object is used in generating the scale and mouseover data; indexed by
  // actual ordinal; returning [display_ordinal, timestamp_in_millis, cl, ID,
  // srcId].  src_id is a key into srcDict.
  this.clId = {0: [0, 0, 0, 0]};
  this.srcDict = {};  // Used to map srcId to src string.
  this.labelsArray = null;
  this.labelsArrayFull = null;  // With full paths (set by Ajax call).
  this.numSrcIds = null;
  this.configsArray = null;  // Holds current configs.
  this.unit = null;  // Holds unit to display on aggregate graph.

  this.histogram = null;  // Holds the histogram object.

  // Mapping visibilityArray index to base-64 48-bit md5 hash.  This is a list
  // of hashes for all loaded metrics.
  this.labelsHashArray = null;
  // Metrics selected by user.  Key is base-64 md5 hash.  Selected if present.
  this.displayMap = null;

  // Remap aggChart indices to lower chart indices, because lower charts
  // can include any subset of the aggChart metrics.
  // We can access attributes before they're set, and for speed we don't have
  // checks in the code which uses them.  Faster to set a default object here.
  this.indexRemap = {};

  // Each element of the cache object is:
  //  {data: <JSON data for invocation ID>,
  //   colors: [remappedColors],
  //   remap: indexRemapped, configs_string}
  this.cache = null;

  // Set only for equalXscale: used to map the actual data X value to a value
  // which can be used as an index into clId.  This is created simply by sorting
  // the clId keys numerically.
  this.equalXMap = null;

  this.stackAgg = stackAgg;  // If true, produce a stacked graph.

  // The maximum wrapped label length for the aggregate graph.  Used to adjust
  // Dygraph labelsDivWidth.
  this.maxLabelLength = null;

  // These two are needed for the mouseover highlight handler:
  this.timeXScale = null;
  this.equalXScale = null;
}
/**
 * @constructor
 * @param {jQuerySelector} aggChartElem The div to use to create the aggregate
 *   graph.
 * @param {jQuerySelector} rawChartElem The div to use to create the raw/samples
 *   graph.
 * @param {jQuerySelector} histoChartElem The div to use to create the histogram
 *   graph.
 * @param {number} numEmbedGraphs The number of embedded graphs requested.
 * @param {boolean} aggResize If true then we want only the aggregate graph
 *   instead of all three.
 * @param {jQuerySelector} instantInfoElem The div to use to update with the
 *   mouseover extra info.  For now, this is just the config data for each
 *   record.
 * @param {jQuerySelector} buttonColumnElem The div for the button column.
 * @param {jQuerySelector} loadingSpinnerElem The busy spinner element.  By
 *   default this is hidden.
 * @param {boolean} stackAgg The initial value for the stacking/separated state.
 *   If true we want stacked graphs; separated otherwise.
 * @param {jQuerySelector} headerLinksElem The top header links div (embedded
 *   graphs links, help, etc.).
 * @param {jQuerySelector} graphsContainerElem The outer graph containing div.
 * @param {jQuerySelector} dataRangeWidgetsElem The outer container for any data
 *   range selection widgets.  This includes the *date* range widget, last
 *   points selection (which is just a title right now), or anything else we may
 *   add.
 * @param {jQuerySelector} aggregateResizeButtonDivElem The div-based button
 *   used to toggle between different aggregate graph sizes.
 * @param {jQuerySelector} lowerThirdsElem The outer div for the lower-thirds
 *   section of the UI (the user function and help divs).
 * @param {jQuerySelector} metricButtonsElem The containing div for the metric
 *   buttons and all other related UI elements (search box, select-all button,
 *   etc.).
 * @param {string} metricSelectorIdPrefix The id prefix for the individual
 *   metric buttons.  These are dynamically created.  So this must be a string.
 * @param {string} metricButtonsDivId The closest containing div for the
 *   individual metric buttons.
 * @param {string} checkAllButtonId The id for the check-all button.  This is
 *   dynamically created.  So this must be a string.
 */
@constructor
@param {jQuerySelector} aggChartElem The div to use to create the aggregate
graph.
@param {jQuerySelector} rawChartElem The div to use to create the raw/samples
graph.
@param {jQuerySelector} histoChartElem The div to use to create the histogram
graph.
@param {number} numEmbedGraphs The number of embedded graphs requested.
@param {boolean} aggResize If true then we want only the aggregate graph
instead of all three.
@param {jQuerySelector} instantInfoElem The div to use to update with the
mouseover extra info.  For now, this is just the config data for each
record.
@param {jQuerySelector} buttonColumnElem The div for the button column.
@param {jQuerySelector} loadingSpinnerElem The busy spinner element.  By
default this is hidden.
@param {boolean} stackAgg The initial value for the stacking/separated state.
If true we want stacked graphs; separated otherwise.
@param {jQuerySelector} headerLinksElem The top header links div (embedded
graphs links, help, etc.).
@param {jQuerySelector} graphsContainerElem The outer graph containing div.
@param {jQuerySelector} dataRangeWidgetsElem The outer container for any data
range selection widgets.  This includes the *date* range widget, last
points selection (which is just a title right now), or anything else we may
add.
@param {jQuerySelector} aggregateResizeButtonDivElem The div-based button
used to toggle between different aggregate graph sizes.
@param {jQuerySelector} lowerThirdsElem The outer div for the lower-thirds
section of the UI (the user function and help divs).
@param {jQuerySelector} metricButtonsElem The containing div for the metric
buttons and all other related UI elements (search box, select-all button,
etc.).
@param {string} metricSelectorIdPrefix The id prefix for the individual
metric buttons.  These are dynamically created.  So this must be a string.
@param {string} metricButtonsDivId The closest containing div for the
individual metric buttons.
@param {string} checkAllButtonId The id for the check-all button.  This is
dynamically created.  So this must be a string.
@constructor @param { jQuerySelector } aggChartElem The div to use to create the aggregate graph . @param { jQuerySelector } rawChartElem The div to use to create the raw / samples graph . @param { jQuerySelector } histoChartElem The div to use to create the histogram graph . @param { number } numEmbedGraphs The number of embedded graphs requested . @param { boolean } aggResize If true then we want only the aggregate graph instead of all three . @param { jQuerySelector } instantInfoElem The div to use to update with the mouseover extra info . For now this is just the config data for each record . @param { jQuerySelector } buttonColumnElem The div for the button column . @param { jQuerySelector } loadingSpinnerElem The busy spinner element . By default this is hidden . @param { boolean } stackAgg The initial value for the stacking / separated state . If true we want stacked graphs ; separated otherwise . @param { jQuerySelector } headerLinksElem The top header links div ( embedded graphs links help etc . ) . @param { jQuerySelector } graphsContainerElem The outer graph containing div . @param { jQuerySelector } dataRangeWidgetsElem The outer container for any data range selection widgets . This includes the * date * range widget last points selection ( which is just a title right now ) or anything else we may add . @param { jQuerySelector } aggregateResizeButtonDivElem The div - based button used to toggle between different aggregate graph sizes . @param { jQuerySelector } lowerThirdsElem The outer div for the lower - thirds section of the UI ( the user function and help divs ) . @param { jQuerySelector } metricButtonsElem The containing div for the metric buttons and all other related UI elements ( search box select - all button etc . ) . @param { string } metricSelectorIdPrefix The id prefix for the individual metric buttons . These are dynamically created . So this must be a string . @param { string } metricButtonsDivId The closest containing div for the individual metric buttons . @param { string } checkAllButtonId The id for the check - all button . This is dynamically created . So this must be a string .
function Graphs(aggChartElem, rawChartElem, histoChartElem, numEmbedGraphs,
    aggResize, instantInfoElem, buttonColumnElem, loadingSpinnerElem, stackAgg,
    headerLinksElem, graphsContainerElem, dataRangeWidgetsElem,
    aggregateResizeButtonDivElem, lowerThirdsElem, metricButtonsElem,
    metricSelectorIdPrefix, metricButtonsDivId, checkAllButtonId) {
  this.aggChartElem_ = $(aggChartElem);
  this.rawChartElem_ = $(rawChartElem);
  this.histoChartElem_ = $(histoChartElem);
  this.srcList = null;
  this.numEmbedGraphs = numEmbedGraphs;
  this.aggResize = aggResize;  
  this.instantInfoElem = $(instantInfoElem);
  this.buttonColumnElem = $(buttonColumnElem);
  this.loadingSpinnerElem = $(loadingSpinnerElem);
  this.headerLinksElem = $(headerLinksElem);
  this.graphsContainerElem = $(graphsContainerElem);
  this.dataRangeWidgetsElem = $(dataRangeWidgetsElem);
  this.aggregateResizeButtonDivElem = $(aggregateResizeButtonDivElem);
  this.lowerThirdsElem = $(lowerThirdsElem);
  this.metricButtonsElem = $(metricButtonsElem);
  this.metricSelectorIdPrefix = metricSelectorIdPrefix;
  this.metricButtonsDivId = metricButtonsDivId;
  this.checkAllButtonId = checkAllButtonId;
  this.visibilityArray = null;
  this.urlVisibilityArray = null;
  this.aggChart = null;
  this.rawChart = null;
  this.histoChart = null;
  this.rawChartHasRealData = null;
  this.histoChartHasRealData = null;
  this.aggData = null;  
  this.clId = {0: [0, 0, 0, 0]};
  this.srcDict = {};  
  this.labelsArray = null;
  this.labelsArrayFull = null;  
  this.numSrcIds = null;
  this.configsArray = null;  
  this.unit = null;  
  this.histogram = null;  
  this.labelsHashArray = null;
  this.displayMap = null;
  this.indexRemap = {};
  this.cache = null;
  this.equalXMap = null;
  this.stackAgg = stackAgg;  
  this.maxLabelLength = null;
  this.timeXScale = null;
  this.equalXScale = null;
}
function Graphs ( aggChartElem , rawChartElem , histoChartElem , numEmbedGraphs , aggResize , instantInfoElem , buttonColumnElem , loadingSpinnerElem , stackAgg , headerLinksElem , graphsContainerElem , dataRangeWidgetsElem , aggregateResizeButtonDivElem , lowerThirdsElem , metricButtonsElem , metricSelectorIdPrefix , metricButtonsDivId , checkAllButtonId ) { this . aggChartElem_ = $ ( aggChartElem ) ; this . rawChartElem_ = $ ( rawChartElem ) ; this . histoChartElem_ = $ ( histoChartElem ) ; this . srcList = null ; this . numEmbedGraphs = numEmbedGraphs ; this . aggResize = aggResize ; this . instantInfoElem = $ ( instantInfoElem ) ; this . buttonColumnElem = $ ( buttonColumnElem ) ; this . loadingSpinnerElem = $ ( loadingSpinnerElem ) ; this . headerLinksElem = $ ( headerLinksElem ) ; this . graphsContainerElem = $ ( graphsContainerElem ) ; this . dataRangeWidgetsElem = $ ( dataRangeWidgetsElem ) ; this . aggregateResizeButtonDivElem = $ ( aggregateResizeButtonDivElem ) ; this . lowerThirdsElem = $ ( lowerThirdsElem ) ; this . metricButtonsElem = $ ( metricButtonsElem ) ; this . metricSelectorIdPrefix = metricSelectorIdPrefix ; this . metricButtonsDivId = metricButtonsDivId ; this . checkAllButtonId = checkAllButtonId ; this . visibilityArray = null ; this . urlVisibilityArray = null ; this . aggChart = null ; this . rawChart = null ; this . histoChart = null ; this . rawChartHasRealData = null ; this . histoChartHasRealData = null ; this . aggData = null ; this . clId = { 0 : [ 0 , 0 , 0 , 0 ] } ; this . srcDict = { } ; this . labelsArray = null ; this . labelsArrayFull = null ; this . numSrcIds = null ; this . configsArray = null ; this . unit = null ; this . histogram = null ; this . labelsHashArray = null ; this . displayMap = null ; this . indexRemap = { } ; this . cache = null ; this . equalXMap = null ; this . stackAgg = stackAgg ; this . maxLabelLength = null ; this . timeXScale = null ; this . equalXScale = null ; }
@constructor
 @param {jQuerySelector} aggChartElem The div to use to create the aggregate
   graph.
@constructor @param { jQuerySelector } aggChartElem The div to use to create the aggregate graph .
// Updated in a session by this.makeAggResize(). // For page resizing only. // Old-style metrics-to-display list from URL. // The raw, precomputed aggregate data. // This object is used in generating the scale and mouseover data; indexed by // actual ordinal; returning [display_ordinal, timestamp_in_millis, cl, ID, // srcId].  src_id is a key into srcDict. // Used to map srcId to src string. // With full paths (set by Ajax call). // Holds current configs. // Holds unit to display on aggregate graph. // Holds the histogram object. // Mapping visibilityArray index to base-64 48-bit md5 hash.  This is a list // of hashes for all loaded metrics. // Metrics selected by user.  Key is base-64 md5 hash.  Selected if present. // Remap aggChart indices to lower chart indices, because lower charts // can include any subset of the aggChart metrics. // We can access attributes before they're set, and for speed we don't have // checks in the code which uses them.  Faster to set a default object here. // Each element of the cache object is: //  {data: <JSON data for invocation ID>, //   colors: [remappedColors], //   remap: indexRemapped, configs_string} // Set only for equalXscale: used to map the actual data X value to a value // which can be used as an index into clId.  This is created simply by sorting // the clId keys numerically. // If true, produce a stacked graph. // The maximum wrapped label length for the aggregate graph.  Used to adjust // Dygraph labelsDivWidth. // These two are needed for the mouseover highlight handler: