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
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.
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} */
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;
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});
}
* 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.
*
* 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.
*
* @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);
};
* 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);
* 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_;
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 = {
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;
}
};
+/**
+ * @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;
};
annotations[a.xval + "," + a.series] = a;
}
+ /**
+ * @type {Array.<Dygraph.PointType>}
+ */
this.annotated_points = [];
// Exit the function early if there are no annotations.
* 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.
*
* 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) {
* 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_ = {};
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.
return this.labels_;
};
-return DygraphOptions;
-
})();
/*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;
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 = [];
};
-/** @type {Ticker} */
+/** @type {Dygraph.Ticker} */
Dygraph.dateTicker = function(a, b, pixels, opts, dygraph, vals) {
var chosen = Dygraph.pickDateTickGranularity(a, b, pixels, opts);
};
/**
- * 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)
* @param {number} granularity (one of the granularities enumerated above)
* @param {function(string):*} opts Function mapping from option name -> value.
* @param {Dygraph=} dg
- * @return {!TickList}
+ * @return {!Dygraph.TickList}
*/
Dygraph.getDateAxis = function(start_time, end_time, granularity, opts, dg) {
var formatter = /** @type{AxisLabelFormatter} */(
* 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
*/
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 {