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