stepPlot: false,
avoidMinZero: false,
+ drawAxesAtZero: false,
// Sizes of the various chart labels.
titleHeight: 28,
this.setIndexByName_ = {};
this.datasetIndex_ = [];
+ this.registeredEvents_ = [];
+
// Create the containing DIV and other interactive elements
this.createInterface_();
pluginOptions: {}
};
- var registerer = (function(pluginDict) {
- return {
- addEventListener: function(eventName, callback) {
- // TODO(danvk): validate eventName.
- pluginDict.events[eventName] = callback;
- }
- };
- })(pluginDict);
- pluginInstance.activate(this, registerer);
- // TODO(danvk): prevent activate() from holding a reference to registerer.
+ var handlers = pluginInstance.activate(this);
+ for (var eventName in handlers) {
+ // TODO(danvk): validate eventName.
+ pluginDict.events[eventName] = handlers[eventName];
+ }
this.plugins_.push(pluginDict);
}
},
propagationStopped: false,
stopPropagation: function() {
- propagationStopped = true;
+ e.propagationStopped = true;
}
};
Dygraph.update(e, extra_props);
var callback_plugin_pairs = this.eventListeners_[name];
- for (var i = callback_plugin_pairs.length - 1; i >= 0; i--) {
- var plugin = callback_plugin_pairs[i][0];
- var callback = callback_plugin_pairs[i][1];
- callback.call(plugin, e);
- if (e.propagationStopped) break;
+ if (callback_plugin_pairs) {
+ for (var i = callback_plugin_pairs.length - 1; i >= 0; i--) {
+ var plugin = callback_plugin_pairs[i][0];
+ var callback = callback_plugin_pairs[i][1];
+ callback.call(plugin, e);
+ if (e.propagationStopped) break;
+ }
}
return e.defaultPrevented;
};
this.mouseMoveHandler = function(e) {
dygraph.mouseMove_(e);
};
- Dygraph.addEvent(this.mouseEventElement_, 'mousemove', this.mouseMoveHandler);
+ this.addEvent(this.mouseEventElement_, 'mousemove', this.mouseMoveHandler);
this.mouseOutHandler = function(e) {
dygraph.mouseOut_(e);
};
- Dygraph.addEvent(this.mouseEventElement_, 'mouseout', this.mouseOutHandler);
+ this.addEvent(this.mouseEventElement_, 'mouseout', this.mouseOutHandler);
this.createDragInterface_();
// Update when the window is resized.
// TODO(danvk): drop frames depending on complexity of the chart.
- Dygraph.addEvent(window, 'resize', this.resizeHandler);
+ this.addEvent(window, 'resize', this.resizeHandler);
};
/**
node.removeChild(node.firstChild);
}
};
-
- // remove mouse event handlers
+
+ for (var idx = 0; idx < this.registeredEvents_.length; idx++) {
+ var reg = this.registeredEvents_[idx];
+ Dygraph.removeEvent(reg.elem, reg.type, reg.fn);
+ }
+ this.registeredEvents_ = [];
+
+ // remove mouse event handlers (This may not be necessary anymore)
Dygraph.removeEvent(this.mouseEventElement_, 'mouseout', this.mouseOutHandler);
Dygraph.removeEvent(this.mouseEventElement_, 'mousemove', this.mouseMoveHandler);
Dygraph.removeEvent(this.mouseEventElement_, 'mousemove', this.mouseUpHandler_);
* @private
*/
Dygraph.prototype.setColors_ = function() {
- var num = this.attr_("labels").length - 1;
+ var labels = this.getLabels();
+ var num = labels.length - 1;
this.colors_ = [];
+ this.colorsMap_ = {};
var colors = this.attr_('colors');
var i;
if (!colors) {
// alternate colors for high contrast.
var idx = i % 2 ? Math.ceil(i / 2) : (half + i / 2);
var hue = (1.0 * idx/ (1 + num));
- this.colors_.push(Dygraph.hsvToRGB(hue, sat, val));
+ var colorStr = Dygraph.hsvToRGB(hue, sat, val);
+ this.colors_.push(colorStr);
+ this.colorsMap_[labels[i]] = colorStr;
}
} else {
for (i = 0; i < num; i++) {
if (!this.visibility()[i]) continue;
var colorStr = colors[i % colors.length];
this.colors_.push(colorStr);
+ this.colorsMap_[labels[1 + i]] = colorStr;
}
}
boundedDates: null, // [minDate, maxDate]
boundedValues: null, // [[minValue, maxValue] ...]
- initializeMouseDown: function(event, g, context) {
+ // contextB is the same thing as this context object but renamed.
+ initializeMouseDown: function(event, g, contextB) {
// prevents mouse drags from selecting page text.
if (event.preventDefault) {
event.preventDefault(); // Firefox, Chrome, etc.
event.cancelBubble = true;
}
- context.px = Dygraph.findPosX(g.canvas_);
- context.py = Dygraph.findPosY(g.canvas_);
- context.dragStartX = g.dragGetX_(event, context);
- context.dragStartY = g.dragGetY_(event, context);
- context.cancelNextDblclick = false;
+ contextB.px = Dygraph.findPosX(g.canvas_);
+ contextB.py = Dygraph.findPosY(g.canvas_);
+ contextB.dragStartX = g.dragGetX_(event, contextB);
+ contextB.dragStartY = g.dragGetY_(event, contextB);
+ contextB.cancelNextDblclick = false;
}
};
for (var eventName in interactionModel) {
if (!interactionModel.hasOwnProperty(eventName)) continue;
- Dygraph.addEvent(this.mouseEventElement_, eventName,
+ this.addEvent(this.mouseEventElement_, eventName,
bindHandler(interactionModel[eventName]));
}
}
};
- Dygraph.addEvent(document, 'mouseup', this.mouseUpHandler_);
+ this.addEvent(document, 'mouseup', this.mouseUpHandler_);
};
/**
this.computeYAxes_();
// Create a new plotter.
- if (this.plotter_) this.plotter_.clear();
+ if (this.plotter_) {
+ this.cascadeEvents_('clearChart');
+ this.plotter_.clear();
+ }
this.plotter_ = new DygraphCanvasRenderer(this,
this.hidden_,
this.hidden_ctx_,
* @private
*/
Dygraph.prototype.renderGraph_ = function(is_initial_draw) {
+ this.cascadeEvents_('clearChart');
this.plotter_.clear();
+
this.plotter_.render();
+
+ // TODO(danvk): is this a performance bottleneck when panning?
+ // The interaction canvas should already be empty in that situation.
this.canvas_.getContext('2d').clearRect(0, 0, this.canvas_.width,
this.canvas_.height);
this.rangeSelector_.renderInteractiveLayer();
}
- this.cascadeEvents_('drawChart');
+ this.cascadeEvents_('drawChart', {
+ canvas: this.hidden_,
+ drawingContext: this.hidden_ctx_,
+ });
if (this.attr_("drawCallback") !== null) {
this.attr_("drawCallback")(this, is_initial_draw);
}
* called once -- all calls after the first will return immediately.
*/
Dygraph.addAnnotationRule = function() {
+ // TODO(danvk): move this function into plugins/annotations.js?
if (Dygraph.addedAnnotationCSS) return;
var rule = "border: 1px solid black; " +