closurize dygraph-layout.js
authorDan Vanderkam <danvdk@gmail.com>
Mon, 22 Jul 2013 02:12:01 +0000 (22:12 -0400)
committerDan Vanderkam <danvdk@gmail.com>
Mon, 22 Jul 2013 02:12:01 +0000 (22:12 -0400)
closure-todo.txt
dygraph-externs.js
dygraph-gviz.js
dygraph-layout.js
dygraph-options.js
dygraph-tickers.js
dygraph-utils.js

index 392ede4..f9c0357 100644 (file)
@@ -11,7 +11,7 @@ under the Closure Compiler without any errors or warnings.
 Core:
 - dygraph-canvas.js
 - dygraph-interaction-model.js
-- dygraph-layout.js
+x dygraph-layout.js
 x dygraph-options.js
 - dygraph.js
 x dygraph-gviz.js
@@ -32,6 +32,6 @@ Plugins:
 
 Here's a command that can be used to build dygraphs using the closure
 compiler:
-java -jar ../../closure-compiler-read-only/build/compiler.jar --js=dygraph-utils.js --js=dashed-canvas.js --js=dygraph-options-reference.js --js=dygraph-tickers.js --js=dygraph-gviz.js --js=dygraph-options.js --js_output_file=/tmp/out.js --compilation_level ADVANCED_OPTIMIZATIONS --warning_level VERBOSE --externs dygraph-externs.js
+java -jar ../../closure-compiler-read-only/build/compiler.jar --js=dygraph-utils.js --js=dashed-canvas.js --js=dygraph-options-reference.js --js=dygraph-tickers.js --js=dygraph-gviz.js --js=dygraph-options.js --js=dygraph-layout.js --js_output_file=/tmp/out.js --compilation_level ADVANCED_OPTIMIZATIONS --warning_level VERBOSE --externs dygraph-externs.js
 
 As each file is closurized, it can be added as a "--js" parameter.
index ed5de4c..c40139c 100644 (file)
@@ -63,14 +63,32 @@ function GVizDataTable() {}
 function Dygraph(div, file, attrs) {}
 
 /**
- * @constructor
- */
-function DygraphLayout() {}
-
-/**
- * @type {Array}
+ * @typedef {{
+ *     idx: number,
+ *     name: string,
+ *     x: ?number,
+ *     xval: ?number,
+ *     y_bottom: ?number,
+ *     y: ?number,
+ *     y_stacked: ?number,
+ *     y_top: ?number,
+ *     yval_minus: ?number,
+ *     yval: ?number,
+ *     yval_plus: ?number,
+ *     yval_stacked
+ * }}
  */
-DygraphLayout.prototype.datasets;
+Dygraph.PointType;
+
+// /**
+//  * @constructor
+//  */
+// function DygraphLayout() {}
+// 
+// /**
+//  * @type {Array.<Array.<Dygraph.PointType>>}
+//  */
+// DygraphLayout.prototype.points;
 
 // TODO: DygraphOptions should not reach inside Dygraph private data like this.
 /** @type {Object} */
@@ -79,15 +97,122 @@ Dygraph.prototype.attrs_;
 Dygraph.prototype.user_attrs_;
 
 /**
+ * @param {string} name the name of the option.
+ */
+Dygraph.prototype.attr_ = function(name) {};
+
+/**
+ * @return {{w: number, h: number}} object.
+ */
+Dygraph.prototype.size;
+
+/**
  * @type {DygraphLayout}
  */
 Dygraph.prototype.layout_;
 
+/**
+ * @type {!HTMLDivElement}
+ */
+Dygraph.prototype.graphDiv;
+
+/**
+ * @type {!DygraphOptions}
+ */
+Dygraph.prototype.attributes_;
+
 /** @type {function(): string} */
 Dygraph.prototype.getHighlightSeries;
 
-/** @type {Array.<{elem:Element,type:string,fn:function(!Event):(boolean|undefined|null)}>} */
+/**
+ * @param {string} name Event name.
+ * @param {Object} extra_props Event-specific properties.
+ * @return {boolean} Whether to perform the default action.
+ */
+Dygraph.prototype.cascadeEvents_ = function(name, extra_props) {};
+
+/**
+ * @type {Array.<{
+ *   elem: !Element,
+ *   type: string,
+ *   fn: function(?Event):(boolean|undefined)
+ * }>}
+ */
 Dygraph.prototype.registeredEvents_;
 
+/**
+ * @return {!Array.<number>} two element [left, right] array.
+ */
+Dygraph.prototype.xAxisRange = function() {};
+
+/**
+ * @param {string} setName Set name.
+ * @return {Object} axis properties for the series.
+ */
+Dygraph.prototype.axisPropertiesForSeries = function(setName) {};
+
+/**
+ * @param {number} y The data y-coordinate.
+ * @param {number} axis The axis number on which the data coordinate lives.
+ * @return {number} A fraction in [0, 1] where 0 = the top edge.
+ */
+Dygraph.prototype.toPercentYCoord = function(y, axis) {};
+
 /** @type {{axes: Object}} */
 Dygraph.DEFAULT_ATTRS;
+
+/**
+ * @typedef {{
+ *   xval: (number|undefined),
+ *   x: string,
+ *   series: string,
+ *   icon: (string|undefined),
+ *   width: (number|undefined),
+ *   height: (number|undefined),
+ *   shortText: (string|undefined),
+ *   text: (string|undefined)
+ * }}
+ */
+Dygraph.AnnotationType;
+
+/**
+ * @typedef {Array.<{
+ *   v:number,
+ *   label:string,
+ *   label_v:(string|undefined)
+ * }>}
+ */
+Dygraph.TickList;
+
+/**
+ * @typedef {(function(
+ *    number,
+ *    number,
+ *    number,
+ *    function(string):*,
+ *    Dygraph=,
+ *    Array.<number>=
+ *  ): Dygraph.TickList)}
+ */
+Dygraph.Ticker;
+
+/**
+ * @typedef {{
+ *   x: number,
+ *   y: number,
+ *   w: number,
+ *   h: number
+ * }}
+ */
+Dygraph.Rect;
+
+/**
+ * @typedef {{
+ *   g: !Dygraph,
+ *   minyval: number,
+ *   maxyval: number,
+ *   ticks: Array,
+ *   computedValueRange: Array.<number>
+ * }}
+ */
+Dygraph.AxisType;
index 988e0ac..58e14d2 100644 (file)
@@ -73,7 +73,8 @@ Dygraph.GVizChart.prototype.getSelection = function() {
 
   if (row < 0) return selection;
 
-  var points = this.date_graph.layout_.points;
+  var layout = /** @type {DygraphLayout} */(this.date_graph.layout_);
+  var points = layout.points;
   for (var setIdx = 0; setIdx < points.length; ++setIdx) {
     selection.push({row: row, column: setIdx + 1});
   }
index 2d80857..79f4b27 100644 (file)
@@ -9,11 +9,7 @@
  * dygraphs.
  */
 
-var DygraphLayout = (function() {
-
-/*jshint globalstrict: true */
-/*global Dygraph:false */
-"use strict";
+// Note: @constructor must live outside (function() {})() for Closure Compiler.
 
 /**
  * Creates a new DygraphLayout object.
@@ -29,10 +25,12 @@ var DygraphLayout = (function() {
  *
  * The naming is a vestige of Dygraph's original PlotKit roots.
  *
+ * @param {!Dygraph} dygraph The dygraph object.
  * @constructor
  */
 var DygraphLayout = function(dygraph) {
   this.dygraph_ = dygraph;
+
   /**
    * Array of points for each series.
    *
@@ -45,16 +43,45 @@ var DygraphLayout = function(dygraph) {
    * @type {Array.<Array.<Dygraph.PointType>>}
    */
   this.points = [];
+
+  /** @type {Array.<string>} */
   this.setNames = [];
+
+  /** @type {Array.<!Dygraph.AnnotationType>} */
   this.annotations = [];
+
+  /** @type {Array.<Dygraph.AxisType>} */
   this.yAxes_ = null;
 
   // TODO(danvk): it's odd that xTicks_ and yTicks_ are inputs, but xticks and
   // yticks are outputs. Clean this up.
+  /** @type {Dygraph.TickList} */
   this.xTicks_ = null;
+  /** @type {Dygraph.TickList} */
   this.yTicks_ = null;
+
+  /** @type {?Dygraph.Rect} */
+  this.area_ = null;
+
+  // TODO(danvk): these fields should be objects, not arrays of arrays, which
+  // can't be easily described in the closure type system.
+  /** @type {Array.<Array>} */
+  this.xticks = null;
+  /** @type {Array.<Array>} */
+  this.yticks = null;
 };
 
+
+(function() {
+
+/*jshint globalstrict: true */
+/*global Dygraph:false */
+"use strict";
+
+/**
+ * @param {string} name Name of the attribute.
+ * @return {*} Attribute value.
+ */
 DygraphLayout.prototype.attr_ = function(name) {
   return this.dygraph_.attr_(name);
 };
@@ -63,7 +90,7 @@ DygraphLayout.prototype.attr_ = function(name) {
  * Add points for a single series.
  *
  * @param {string} setname Name of the series.
- * @param {Array.<Dygraph.PointType>} set_xy Points for the series.
+ * @param {Array.<!Dygraph.PointType>} set_xy Points for the series.
  */
 DygraphLayout.prototype.addDataset = function(setname, set_xy) {
   this.points.push(set_xy);
@@ -74,7 +101,7 @@ DygraphLayout.prototype.addDataset = function(setname, set_xy) {
  * Returns the box which the chart should be drawn in. This is the canvas's
  * box, less space needed for the axis and chart labels.
  *
- * @return {{x: number, y: number, w: number, h: number}}
+ * @return {?Dygraph.Rect}
  */
 DygraphLayout.prototype.getPlotArea = function() {
   return this.area_;
@@ -90,8 +117,9 @@ DygraphLayout.prototype.computePlotArea = function() {
     y: 0
   };
 
-  area.w = this.dygraph_.width_ - area.x - this.attr_('rightGap');
-  area.h = this.dygraph_.height_;
+  var size = this.dygraph_.size();
+  area.w = size.w - area.x - /** @type{number} */(this.attr_('rightGap'));
+  area.h = size.h;
 
   // Let plugins reserve space.
   var e = {
@@ -147,13 +175,31 @@ DygraphLayout.prototype.computePlotArea = function() {
   this.area_ = area;
 };
 
+/**
+ * @param {Array.<!Dygraph.AnnotationType>} ann The annotations
+ */
 DygraphLayout.prototype.setAnnotations = function(ann) {
   // The Dygraph object's annotations aren't parsed. We parse them here and
   // save a copy. If there is no parser, then the user must be using raw format.
+
+  /** @type {Array.<!Dygraph.AnnotationType>} */
   this.annotations = [];
-  var parse = this.attr_('xValueParser') || function(x) { return x; };
+  
+  var parse = /** @type {function(string):number} */(this.attr_('xValueParser')) || function(x) { return parseFloat(x); };
+
   for (var i = 0; i < ann.length; i++) {
-    var a = {};
+    // lame that closure compiler wants all these undefineds!
+    /** @type {Dygraph.AnnotationType} */
+    var a = {
+      x: ann[i].x,
+      series: ann[i].series,
+      xval: undefined,
+      icon: undefined,
+      width: undefined,
+      height: undefined,
+      shortText: undefined,
+      text: undefined
+    };
     if (!ann[i].xval && ann[i].x === undefined) {
       Dygraph.error("Annotations must have an 'x' property");
       return;
@@ -171,11 +217,16 @@ DygraphLayout.prototype.setAnnotations = function(ann) {
   }
 };
 
+/**
+ * @param {!Dygraph.TickList} xTicks The x-axis ticks.
+ */
 DygraphLayout.prototype.setXTicks = function(xTicks) {
   this.xTicks_ = xTicks;
 };
 
-// TODO(danvk): add this to the Dygraph object's API or move it into Layout.
+/**
+ * @param {Array.<Dygraph.AxisType>} yAxes The y-axes.
+ */
 DygraphLayout.prototype.setYAxes = function (yAxes) {
   this.yAxes_ = yAxes;
 };
@@ -299,6 +350,9 @@ DygraphLayout.prototype._evaluateAnnotations = function() {
     annotations[a.xval + "," + a.series] = a;
   }
 
+  /**
+   * @type {Array.<Dygraph.PointType>}
+   */
   this.annotated_points = [];
 
   // Exit the function early if there are no annotations.
index e912aa7..de15512 100644 (file)
  * Still tightly coupled to Dygraphs, we could remove some of that, you know.
  */
 
-var DygraphOptions = (function() {
-
-/*jshint sub:true */
-/*global Dygraph:false */
-"use strict";
-
-/*
- * Interesting member variables: (REMOVING THIS LIST AS I CLOSURIZE)
- * global_ - global attributes (common among all graphs, AIUI)
- * user - attributes set by the user
- * series_ - { seriesName -> { idx, yAxis, options }}
- */
-
 /**
  * This parses attributes into an object that can be easily queried.
  *
@@ -30,7 +17,7 @@ var DygraphOptions = (function() {
  * if labels are not yet available, since those drive details of the per-series
  * and per-axis options.
  *
- * @param {Dygraph} dygraph The chart to which these options belong.
+ * @param {!Dygraph} dygraph The chart to which these options belong.
  * @constructor
  */
 var DygraphOptions = function(dygraph) {
@@ -50,7 +37,8 @@ var DygraphOptions = function(dygraph) {
    * Contains x-axis specific options, which are stored in the options key.
    * This matches the yAxes_ object structure (by being a dictionary with an
    * options element) allowing for shared code.
-   * @type {options: Object} @private
+   * @type {Object}
+   * @private
    */
   this.xAxis_ = {};
   this.series_ = {};
@@ -69,6 +57,20 @@ var DygraphOptions = function(dygraph) {
   this.reparseSeries();
 };
 
+(function() {
+
+/*jshint sub:true */
+/*global Dygraph:false */
+"use strict";
+
+/*
+ * Interesting member variables: (REMOVING THIS LIST AS I CLOSURIZE)
+ * global_ - global attributes (common among all graphs, AIUI)
+ * user - attributes set by the user
+ * series_ - { seriesName -> { idx, yAxis, options }}
+ */
+
+
 /**
  * Not optimal, but does the trick when you're only using two axes.
  * If we move to more axes, this can just become a function.
@@ -370,6 +372,4 @@ DygraphOptions.prototype.seriesNames = function() {
   return this.labels_;
 };
 
-return DygraphOptions;
-
 })();
index 2e8178c..9d799b1 100644 (file)
 /*global Dygraph:false */
 "use strict";
 
-// Constants, defined below.
-var PREFERRED_LOG_TICK_VALUES;
-
-/** @typedef {Array.<{v:number, label:string, label_v:(string|undefined)}>} */
-var TickList;
-
-/** @typedef {function(
- *    number,
- *    number,
- *    number,
- *    function(string):*,
- *    Dygraph=,
- *    Array.<number>=
- *  ): TickList}
- */
-var Ticker;
-
-/** @type {Ticker} */
+/** @type {Dygraph.Ticker} */
 Dygraph.numericLinearTicks = function(a, b, pixels, opts, dygraph, vals) {
   var nonLogscaleOpts = function(opt) {
     if (opt === 'logscale') return false;
@@ -90,7 +73,27 @@ Dygraph.numericLinearTicks = function(a, b, pixels, opts, dygraph, vals) {
   return Dygraph.numericTicks(a, b, pixels, nonLogscaleOpts, dygraph, vals);
 };
 
-/** @type {Ticker} */
+/**
+ * This is a list of human-friendly values at which to show tick marks on a log
+ * scale. It is k * 10^n, where k=1..9 and n=-39..+39, so:
+ * ..., 1, 2, 3, 4, 5, ..., 9, 10, 20, 30, ..., 90, 100, 200, 300, ...
+ * NOTE: this assumes that Dygraph.LOG_SCALE = 10.
+ * @type {Array.<number>}
+ */
+var PREFERRED_LOG_TICK_VALUES = (function() {
+  var vals = [];
+  for (var power = -39; power <= 39; power++) {
+    var range = Math.pow(10, power);
+    for (var mult = 1; mult <= 9; mult++) {
+      var val = range * mult;
+      vals.push(val);
+    }
+  }
+  return vals;
+})();
+
+
+/** @type {Dygraph.Ticker} */
 Dygraph.numericTicks = function(a, b, pixels, opts, dygraph, vals) {
   var pixels_per_tick = /** @type{number} */(opts('pixelsPerLabel'));
   var ticks = [];
@@ -209,7 +212,7 @@ Dygraph.numericTicks = function(a, b, pixels, opts, dygraph, vals) {
 };
 
 
-/** @type {Ticker} */
+/** @type {Dygraph.Ticker} */
 Dygraph.dateTicker = function(a, b, pixels, opts, dygraph, vals) {
   var chosen = Dygraph.pickDateTickGranularity(a, b, pixels, opts);
 
@@ -298,25 +301,6 @@ LONG_TICK_PLACEMENTS[CENTENNIAL] = {
 };
 
 /**
- * This is a list of human-friendly values at which to show tick marks on a log
- * scale. It is k * 10^n, where k=1..9 and n=-39..+39, so:
- * ..., 1, 2, 3, 4, 5, ..., 9, 10, 20, 30, ..., 90, 100, 200, 300, ...
- * NOTE: this assumes that Dygraph.LOG_SCALE = 10.
- * @type {Array.<number>}
- */
-PREFERRED_LOG_TICK_VALUES = function() {
-  var vals = [];
-  for (var power = -39; power <= 39; power++) {
-    var range = Math.pow(10, power);
-    for (var mult = 1; mult <= 9; mult++) {
-      var val = range * mult;
-      vals.push(val);
-    }
-  }
-  return vals;
-}();
-
-/**
  * Determine the correct granularity of ticks on a date axis.
  *
  * @param {number} a Left edge of the chart (ms)
@@ -364,7 +348,7 @@ Dygraph.numDateTicks = function(start_time, end_time, granularity) {
  * @param {number} granularity (one of the granularities enumerated above)
  * @param {function(string):*} opts Function mapping from option name -&gt; value.
  * @param {Dygraph=} dg
- * @return {!TickList}
+ * @return {!Dygraph.TickList}
  */
 Dygraph.getDateAxis = function(start_time, end_time, granularity, opts, dg) {
   var formatter = /** @type{AxisLabelFormatter} */(
index e7cb898..df4fcad 100644 (file)
@@ -194,7 +194,7 @@ Dygraph.prototype.addAndTrackEvent = function(elem, type, fn) {
  * of the world.
  * @param {!Element} elem The element to add the event to.
  * @param {string} type The type of the event, e.g. 'click' or 'mousemove'.
- * @param {function(Event):(boolean|undefined)} fn The function to call
+ * @param {function(?Event):(boolean|undefined)} fn The function to call
  *     on the event. The function takes one parameter: the event object.
  * @private
  */
@@ -1182,7 +1182,7 @@ Dygraph.toRGB_ = function(color_str) {
   div.style.backgroundColor = color_str;
   div.style.visibility = 'hidden';
   document.body.appendChild(div);
-  var rgb_str = window.getComputedStyle(div).backgroundColor;
+  var rgb_str = window.getComputedStyle(div, null).backgroundColor;
   document.body.removeChild(div);
   var bits = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/.exec(rgb_str);
   return {