*/
var DygraphOptions = (function() {
+/*jshint strict:false */
+// For "production" code, this gets set to false by uglifyjs.
+// Need to define it outside of "use strict", hence the nested IIFEs.
+if (typeof(DEBUG) === 'undefined') DEBUG=true;
+
+return (function() {
+
+// TODO: remove this jshint directive & fix the warnings.
/*jshint sub:true */
/*global Dygraph:false */
"use strict";
/*
- * Interesting member variables:
- * dygraph_ - the graph.
+ * Interesting member variables: (REMOVING THIS LIST AS I CLOSURIZE)
* global_ - global attributes (common among all graphs, AIUI)
* user - attributes set by the user
- * yAxes_ - array of axis index to { series : [ series names ] , options : { axis-specific options. }
- * xAxis_ - { options : { axis-specific options. }
* series_ - { seriesName -> { idx, yAxis, options }}
- * labels_ - used as mapping from index to series name.
*/
/**
* @constructor
*/
var DygraphOptions = function(dygraph) {
+ /**
+ * The dygraph.
+ * @type {!Dygraph}
+ */
this.dygraph_ = dygraph;
- /** @type {Array.<{options: Object, series: string}>} @private */
+ /**
+ * Array of axis index to { series : [ series names ] , options : { axis-specific options. }
+ * @type {Array.<{series : Array.<string>, options : Object}>} @private
+ */
this.yAxes_ = [];
- /** @type {{options: Object}} @private */
- this.xAxis_ = {options: {}};
- /** @type {Object} @private */
+
+ /**
+ * 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
+ */
+ this.xAxis_ = {};
this.series_ = {};
// Once these two objects are initialized, you can call get();
this.global_ = this.dygraph_.attrs_;
this.user_ = this.dygraph_.user_attrs_ || {};
+ /**
+ * A list of series in columnar order.
+ * @type {Array.<string>}
+ */
+ this.labels_ = [];
+
this.highlightSeries_ = this.get("highlightSeriesOpts") || {};
this.reparseSeries();
};
-/*
+/**
* 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.
+ *
+ * @type {Object.<number>}
+ * @private
*/
DygraphOptions.AXIS_STRING_MAPPINGS_ = {
'y' : 0,
if (typeof(axis) == 'string') {
if (!this.series_.hasOwnProperty(axis)) {
- Dygraph.error("Series " + seriesName + " wants to share a y-axis with " +
+ console.error("Series " + seriesName + " wants to share a y-axis with " +
"series " + axis + ", which does not define its own axis.");
return;
}
Dygraph.update(this.yAxes_[1].options, axis_opts["y2"] || {});
}
Dygraph.update(this.xAxis_.options, axis_opts["x"] || {});
+
+ if (DEBUG) this.validateOptions_();
};
/**
}
// User-specified global options second.
- var result = this.getGlobalUser_(name);
- if (result !== null) {
- return result;
+ // But, hack, ignore globally-specified 'logscale' for 'x' axis declaration.
+ if (!(axis === 'x' && name === 'logscale')) {
+ var result = this.getGlobalUser_(name);
+ if (result !== null) {
+ return result;
+ }
}
-
// Default axis options third.
var defaultAxisOptions = Dygraph.DEFAULT_ATTRS.axes[axisString];
if (defaultAxisOptions.hasOwnProperty(name)) {
return this.labels_;
};
-/* Are we using this? */
+if (DEBUG) {
+
/**
- * Return the index of the specified series.
- * @param {string} series the series name.
+ * Validate all options.
+ * This requires Dygraph.OPTIONS_REFERENCE, which is only available in debug builds.
+ * @private
*/
-DygraphOptions.prototype.indexOfSeries = function(series) {
- return this.series_[series].idx;
+DygraphOptions.prototype.validateOptions_ = function() {
+ if (typeof Dygraph.OPTIONS_REFERENCE === 'undefined') {
+ throw 'Called validateOptions_ in prod build.';
+ }
+
+ var that = this;
+ var validateOption = function(optionName) {
+ if (!Dygraph.OPTIONS_REFERENCE[optionName]) {
+ that.warnInvalidOption_(optionName);
+ }
+ };
+
+ var optionsDicts = [this.xAxis_.options,
+ this.yAxes_[0].options,
+ this.yAxes_[1] && this.yAxes_[1].options,
+ this.global_,
+ this.user_,
+ this.highlightSeries_];
+ var names = this.seriesNames();
+ for (var i = 0; i < names.length; i++) {
+ var name = names[i];
+ if (this.series_.hasOwnProperty(name)) {
+ optionsDicts.push(this.series_[name].options);
+ }
+ }
+ for (var i = 0; i < optionsDicts.length; i++) {
+ var dict = optionsDicts[i];
+ if (!dict) continue;
+ for (var optionName in dict) {
+ if (dict.hasOwnProperty(optionName)) {
+ validateOption(optionName);
+ }
+ }
+ }
+};
+
+var WARNINGS = {}; // Only show any particular warning once.
+
+/**
+ * Logs a warning about invalid options.
+ * TODO: make this throw for testing
+ * @private
+ */
+DygraphOptions.prototype.warnInvalidOption_ = function(optionName) {
+ if (!WARNINGS[optionName]) {
+ WARNINGS[optionName] = true;
+ var isSeries = (this.labels_.indexOf(optionName) >= 0);
+ if (isSeries) {
+ console.warn('Use new-style per-series options (saw ' + optionName + ' as top-level options key). See http://bit.ly/1tceaJs');
+ } else {
+ console.warn('Unknown option ' + optionName + ' (full list of options at dygraphs.com/options.html');
+ throw "invalid option " + optionName;
+ }
+ }
};
+// Reset list of previously-shown warnings. Used for testing.
+DygraphOptions.resetWarnings_ = function() {
+ WARNINGS = {};
+};
+
+}
+
return DygraphOptions;
})();
+})();