Landing!
[dygraphs.git] / plugins / annotations.js
CommitLineData
ee53deb9
DV
1/**
2 * @license
3 * Copyright 2012 Dan Vanderkam (danvdk@gmail.com)
4 * MIT-licensed (http://opensource.org/licenses/MIT)
5 */
6
7Dygraph.Plugins.Annotations = (function() {
8
9/**
10Current bits of jankiness:
11- Uses dygraph.layout_ to get the parsed annotations.
12- Uses dygraph.plotter_.area
d38c6191
DV
13
14It would be nice if the plugin didn't require so much special support inside
15the core dygraphs classes, but annotations involve quite a bit of parsing and
16layout.
17
18TODO(danvk): cache DOM elements.
19
ee53deb9
DV
20*/
21
22var annotations = function() {
23 this.annotations_ = [];
24};
25
26annotations.prototype.toString = function() {
27 return "Annotations Plugin";
28};
29
30annotations.prototype.activate = function(g) {
31 return {
32 clearChart: this.clearChart,
98eb4713 33 didDrawChart: this.didDrawChart
ee53deb9
DV
34 };
35};
36
37annotations.prototype.detachLabels = function() {
38 for (var i = 0; i < this.annotations_.length; i++) {
39 var a = this.annotations_[i];
40 if (a.parentNode) a.parentNode.removeChild(a);
41 this.annotations_[i] = null;
42 }
43 this.annotations_ = [];
44};
45
46annotations.prototype.clearChart = function(e) {
47 this.detachLabels();
48};
49
98eb4713 50annotations.prototype.didDrawChart = function(e) {
ee53deb9
DV
51 var g = e.dygraph;
52
53 // Early out in the (common) case of zero annotations.
54 var points = g.layout_.annotated_points;
55 if (!points || points.length == 0) return;
56
57 var containerDiv = e.canvas.parentNode;
58 var annotationStyle = {
59 "position": "absolute",
60 "fontSize": g.getOption('axisLabelFontSize') + "px",
61 "zIndex": 10,
62 "overflow": "hidden"
63 };
64
65 var bindEvt = function(eventName, classEventName, pt) {
66 return function(annotation_event) {
67 var a = pt.annotation;
68 if (a.hasOwnProperty(eventName)) {
69 a[eventName](a, pt, g, annotation_event);
70 } else if (g.getOption(classEventName)) {
71 g.getOption(classEventName)(a, pt, g, annotation_event );
72 }
73 };
74 };
75
76 // Add the annotations one-by-one.
77 var area = e.dygraph.plotter_.area;
78 for (var i = 0; i < points.length; i++) {
79 var p = points[i];
80 if (p.canvasx < area.x || p.canvasx > area.x + area.w ||
81 p.canvasy < area.y || p.canvasy > area.y + area.h) {
82 continue;
83 }
84
85 var a = p.annotation;
86 var tick_height = 6;
87 if (a.hasOwnProperty("tickHeight")) {
88 tick_height = a.tickHeight;
89 }
90
91 var div = document.createElement("div");
92 for (var name in annotationStyle) {
93 if (annotationStyle.hasOwnProperty(name)) {
94 div.style[name] = annotationStyle[name];
95 }
96 }
97 if (!a.hasOwnProperty('icon')) {
98 div.className = "dygraphDefaultAnnotation";
99 }
100 if (a.hasOwnProperty('cssClass')) {
101 div.className += " " + a.cssClass;
102 }
103
104 var width = a.hasOwnProperty('width') ? a.width : 16;
105 var height = a.hasOwnProperty('height') ? a.height : 16;
106 if (a.hasOwnProperty('icon')) {
107 var img = document.createElement("img");
108 img.src = a.icon;
109 img.width = width;
110 img.height = height;
111 div.appendChild(img);
112 } else if (p.annotation.hasOwnProperty('shortText')) {
113 div.appendChild(document.createTextNode(p.annotation.shortText));
114 }
115 div.style.left = (p.canvasx - width / 2) + "px";
116 if (a.attachAtBottom) {
117 div.style.top = (area.h - height - tick_height) + "px";
118 } else {
119 div.style.top = (p.canvasy - height - tick_height) + "px";
120 }
121 div.style.width = width + "px";
122 div.style.height = height + "px";
123 div.title = p.annotation.text;
124 div.style.color = g.colorsMap_[p.name];
125 div.style.borderColor = g.colorsMap_[p.name];
126 a.div = div;
127
128 g.addEvent(div, 'click',
129 bindEvt('clickHandler', 'annotationClickHandler', p, this));
130 g.addEvent(div, 'mouseover',
131 bindEvt('mouseOverHandler', 'annotationMouseOverHandler', p, this));
132 g.addEvent(div, 'mouseout',
133 bindEvt('mouseOutHandler', 'annotationMouseOutHandler', p, this));
134 g.addEvent(div, 'dblclick',
135 bindEvt('dblClickHandler', 'annotationDblClickHandler', p, this));
136
137 containerDiv.appendChild(div);
138 this.annotations_.push(div);
139
140 var ctx = e.drawingContext;
141 ctx.save();
142 ctx.strokeStyle = g.colorsMap_[p.name];
143 ctx.beginPath();
144 if (!a.attachAtBottom) {
145 ctx.moveTo(p.canvasx, p.canvasy);
146 ctx.lineTo(p.canvasx, p.canvasy - 2 - tick_height);
147 } else {
148 ctx.moveTo(p.canvasx, area.h);
149 ctx.lineTo(p.canvasx, area.h - 2 - tick_height);
150 }
151 ctx.closePath();
152 ctx.stroke();
153 ctx.restore();
154 }
155};
156
157annotations.prototype.destroy = function() {
158 this.detachLabels();
159};
160
161return annotations;
162
163})();