3 * Copyright 2012 Dan Vanderkam (danvdk@gmail.com)
4 * MIT-licensed (http://opensource.org/licenses/MIT)
6 /*global Dygraph:false */
10 // TODO(danvk): move chart label options out of dygraphs and into the plugin.
11 // TODO(danvk): only tear down & rebuild the DIVs when it's necessary.
13 var chart_labels
= function() {
14 this.title_div_
= null;
15 this.xlabel_div_
= null;
16 this.ylabel_div_
= null;
17 this.y2label_div_
= null;
20 chart_labels
.prototype.toString
= function() {
21 return "ChartLabels Plugin";
24 chart_labels
.prototype.activate
= function(g
) {
27 // clearChart: this.clearChart,
28 didDrawChart
: this.didDrawChart
32 // QUESTION: should there be a plugin-utils.js?
33 var createDivInRect
= function(r
) {
34 var div
= document
.createElement('div');
35 div
.style
.position
= 'absolute';
36 div
.style
.left
= r
.x
+ 'px';
37 div
.style
.top
= r
.y
+ 'px';
38 div
.style
.width
= r
.w
+ 'px';
39 div
.style
.height
= r
.h
+ 'px';
43 // Detach and null out any existing nodes.
44 chart_labels
.prototype.detachLabels_
= function() {
45 var els
= [ this.title_div_
,
49 for (var i
= 0; i
< els
.length
; i
++) {
52 if (el
.parentNode
) el
.parentNode
.removeChild(el
);
55 this.title_div_
= null;
56 this.xlabel_div_
= null;
57 this.ylabel_div_
= null;
58 this.y2label_div_
= null;
61 var createRotatedDiv
= function(g
, box
, axis
, classes
, html
) {
62 // TODO(danvk): is this outer div actually necessary?
63 var div
= document
.createElement("div");
64 div
.style
.position
= 'absolute';
66 // NOTE: this is cheating. Should be positioned relative to the box.
67 div
.style
.left
= '0px';
69 div
.style
.left
= box
.x
+ 'px';
71 div
.style
.top
= box
.y
+ 'px';
72 div
.style
.width
= box
.w
+ 'px';
73 div
.style
.height
= box
.h
+ 'px';
74 div
.style
.fontSize
= (g
.getOption('yLabelWidth') - 2) + 'px';
76 var inner_div
= document
.createElement("div");
77 inner_div
.style
.position
= 'absolute';
78 inner_div
.style
.width
= box
.h
+ 'px';
79 inner_div
.style
.height
= box
.w
+ 'px';
80 inner_div
.style
.top
= (box
.h
/ 2 - box.w / 2) + 'px';
81 inner_div
.style
.left
= (box
.w
/ 2 - box.h / 2) + 'px';
82 // TODO: combine inner_div and class_div.
83 inner_div
.className
= 'dygraph-label-rotate-' + (axis
== 1 ? 'right' : 'left');
85 var class_div
= document
.createElement("div");
86 class_div
.className
= classes
;
87 class_div
.innerHTML
= html
;
89 inner_div
.appendChild(class_div
);
90 div
.appendChild(inner_div
);
94 chart_labels
.prototype.layout
= function(e
) {
98 var div
= e
.chart_div
;
99 if (g
.getOption('title')) {
100 // QUESTION: should this return an absolutely-positioned div instead?
101 var title_rect
= e
.reserveSpaceTop(g
.getOption('titleHeight'));
102 this.title_div_
= createDivInRect(title_rect
);
103 this.title_div_
.style
.fontSize
= (g
.getOption('titleHeight') - 8) + 'px';
105 var class_div
= document
.createElement("div");
106 class_div
.className
= 'dygraph-label dygraph-title';
107 class_div
.innerHTML
= g
.getOption('title');
108 this.title_div_
.appendChild(class_div
);
109 div
.appendChild(this.title_div_
);
112 if (g
.getOption('xlabel')) {
113 var x_rect
= e
.reserveSpaceBottom(g
.getOption('xLabelHeight'));
114 this.xlabel_div_
= createDivInRect(x_rect
);
115 this.xlabel_div_
.style
.fontSize
= (g
.getOption('xLabelHeight') - 2) + 'px';
117 var class_div
= document
.createElement("div");
118 class_div
.className
= 'dygraph-label dygraph-xlabel';
119 class_div
.innerHTML
= g
.getOption('xlabel');
120 this.xlabel_div_
.appendChild(class_div
);
121 div
.appendChild(this.xlabel_div_
);
124 if (g
.getOption('ylabel')) {
125 // It would make sense to shift the chart here to make room for the y-axis
126 // label, but the default yAxisLabelWidth is large enough that this results
127 // in overly-padded charts. The y-axis label should fit fine. If it
128 // doesn't, the yAxisLabelWidth option can be increased.
129 var y_rect
= e
.reserveSpaceLeft(0);
131 this.ylabel_div_
= createRotatedDiv(
133 1, // primary (left) y-axis
134 'dygraph-label dygraph-ylabel',
135 g
.getOption('ylabel'));
136 div
.appendChild(this.ylabel_div_
);
139 if (g
.getOption('y2label') && g
.numAxes() == 2) {
140 // same logic applies here as for ylabel.
141 var y2_rect
= e
.reserveSpaceRight(0);
142 this.y2label_div_
= createRotatedDiv(
144 2, // secondary (right) y-axis
145 'dygraph-label dygraph-y2label',
146 g
.getOption('y2label'));
147 div
.appendChild(this.y2label_div_
);
151 chart_labels
.prototype.didDrawChart
= function(e
) {
153 if (this.title_div_
) {
154 this.title_div_
.children
[0].innerHTML
= g
.getOption('title');
156 if (this.xlabel_div_
) {
157 this.xlabel_div_
.children
[0].innerHTML
= g
.getOption('xlabel');
159 if (this.ylabel_div_
) {
160 this.ylabel_div_
.children
[0].children
[0].innerHTML
= g
.getOption('ylabel');
162 if (this.y2label_div_
) {
163 this.y2label_div_
.children
[0].children
[0].innerHTML
= g
.getOption('y2label');
167 chart_labels
.prototype.clearChart
= function() {
170 chart_labels
.prototype.destroy
= function() {
171 this.detachLabels_();
174 export default chart_labels
;