Migrate most of core dygraphs to ES6 modules.
[dygraphs.git] / src / plugins / chart-labels.js
CommitLineData
3a7f87be
DV
1/**
2 * @license
3 * Copyright 2012 Dan Vanderkam (danvdk@gmail.com)
4 * MIT-licensed (http://opensource.org/licenses/MIT)
5 */
0cd1ad15
DV
6/*global Dygraph:false */
7
13f8b047
DV
8"use strict";
9
3a7f87be 10// TODO(danvk): move chart label options out of dygraphs and into the plugin.
60c695cc 11// TODO(danvk): only tear down & rebuild the DIVs when it's necessary.
3a7f87be
DV
12
13var chart_labels = function() {
14 this.title_div_ = null;
15 this.xlabel_div_ = null;
16 this.ylabel_div_ = null;
17 this.y2label_div_ = null;
18};
19
20chart_labels.prototype.toString = function() {
21 return "ChartLabels Plugin";
22};
23
24chart_labels.prototype.activate = function(g) {
25 return {
1748a51c
DV
26 layout: this.layout,
27 // clearChart: this.clearChart,
98eb4713 28 didDrawChart: this.didDrawChart
3a7f87be
DV
29 };
30};
31
32// QUESTION: should there be a plugin-utils.js?
33var 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';
40 return div;
41};
42
1748a51c
DV
43// Detach and null out any existing nodes.
44chart_labels.prototype.detachLabels_ = function() {
45 var els = [ this.title_div_,
46 this.xlabel_div_,
47 this.ylabel_div_,
48 this.y2label_div_ ];
49 for (var i = 0; i < els.length; i++) {
50 var el = els[i];
51 if (!el) continue;
52 if (el.parentNode) el.parentNode.removeChild(el);
53 }
54
55 this.title_div_ = null;
56 this.xlabel_div_ = null;
57 this.ylabel_div_ = null;
58 this.y2label_div_ = null;
59};
60
441e4a56
DV
61var createRotatedDiv = function(g, box, axis, classes, html) {
62 // TODO(danvk): is this outer div actually necessary?
13f8b047 63 var div = document.createElement("div");
441e4a56
DV
64 div.style.position = 'absolute';
65 if (axis == 1) {
1c177b6a
DV
66 // NOTE: this is cheating. Should be positioned relative to the box.
67 div.style.left = '0px';
441e4a56 68 } else {
1c177b6a 69 div.style.left = box.x + 'px';
441e4a56 70 }
1c177b6a
DV
71 div.style.top = box.y + 'px';
72 div.style.width = box.w + 'px';
73 div.style.height = box.h + 'px';
441e4a56
DV
74 div.style.fontSize = (g.getOption('yLabelWidth') - 2) + 'px';
75
76 var inner_div = document.createElement("div");
77 inner_div.style.position = 'absolute';
1c177b6a
DV
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';
441e4a56
DV
82 inner_div.style.textAlign = 'center';
83
84 // CSS rotation is an HTML5 feature which is not standardized. Hence every
85 // browser has its own name for the CSS style.
86 var val = 'rotate(' + (axis == 1 ? '-' : '') + '90deg)';
87 inner_div.style.transform = val; // HTML5
88 inner_div.style.WebkitTransform = val; // Safari/Chrome
89 inner_div.style.MozTransform = val; // Firefox
90 inner_div.style.OTransform = val; // Opera
91 inner_div.style.msTransform = val; // IE9
92
13f8b047 93 var class_div = document.createElement("div");
441e4a56
DV
94 class_div.className = classes;
95 class_div.innerHTML = html;
96
97 inner_div.appendChild(class_div);
98 div.appendChild(inner_div);
99 return div;
42a9ebb8 100};
441e4a56 101
6dca682f 102chart_labels.prototype.layout = function(e) {
1748a51c
DV
103 this.detachLabels_();
104
3a7f87be
DV
105 var g = e.dygraph;
106 var div = e.chart_div;
107 if (g.getOption('title')) {
108 // QUESTION: should this return an absolutely-positioned div instead?
109 var title_rect = e.reserveSpaceTop(g.getOption('titleHeight'));
110 this.title_div_ = createDivInRect(title_rect);
3a7f87be
DV
111 this.title_div_.style.textAlign = 'center';
112 this.title_div_.style.fontSize = (g.getOption('titleHeight') - 8) + 'px';
113 this.title_div_.style.fontWeight = 'bold';
077e41ff 114 this.title_div_.style.zIndex = 10;
1c177b6a
DV
115
116 var class_div = document.createElement("div");
117 class_div.className = 'dygraph-label dygraph-title';
118 class_div.innerHTML = g.getOption('title');
119 this.title_div_.appendChild(class_div);
3a7f87be
DV
120 div.appendChild(this.title_div_);
121 }
122
1c177b6a
DV
123 if (g.getOption('xlabel')) {
124 var x_rect = e.reserveSpaceBottom(g.getOption('xLabelHeight'));
125 this.xlabel_div_ = createDivInRect(x_rect);
126 this.xlabel_div_.style.textAlign = 'center';
127 this.xlabel_div_.style.fontSize = (g.getOption('xLabelHeight') - 2) + 'px';
128
129 var class_div = document.createElement("div");
130 class_div.className = 'dygraph-label dygraph-xlabel';
131 class_div.innerHTML = g.getOption('xlabel');
132 this.xlabel_div_.appendChild(class_div);
133 div.appendChild(this.xlabel_div_);
134 }
135
3a7f87be 136 if (g.getOption('ylabel')) {
441e4a56
DV
137 // It would make sense to shift the chart here to make room for the y-axis
138 // label, but the default yAxisLabelWidth is large enough that this results
139 // in overly-padded charts. The y-axis label should fit fine. If it
140 // doesn't, the yAxisLabelWidth option can be increased.
3a7f87be 141 var y_rect = e.reserveSpaceLeft(0);
441e4a56
DV
142
143 this.ylabel_div_ = createRotatedDiv(
144 g, y_rect,
145 1, // primary (left) y-axis
146 'dygraph-label dygraph-ylabel',
147 g.getOption('ylabel'));
148 div.appendChild(this.ylabel_div_);
149 }
150
1c177b6a
DV
151 if (g.getOption('y2label') && g.numAxes() == 2) {
152 // same logic applies here as for ylabel.
3a7f87be 153 var y2_rect = e.reserveSpaceRight(0);
1c177b6a
DV
154 this.y2label_div_ = createRotatedDiv(
155 g, y2_rect,
156 2, // secondary (right) y-axis
157 'dygraph-label dygraph-y2label',
158 g.getOption('y2label'));
159 div.appendChild(this.y2label_div_);
3a7f87be 160 }
3a7f87be
DV
161};
162
98eb4713 163chart_labels.prototype.didDrawChart = function(e) {
1748a51c
DV
164 var g = e.dygraph;
165 if (this.title_div_) {
1c177b6a
DV
166 this.title_div_.children[0].innerHTML = g.getOption('title');
167 }
168 if (this.xlabel_div_) {
169 this.xlabel_div_.children[0].innerHTML = g.getOption('xlabel');
1748a51c 170 }
441e4a56 171 if (this.ylabel_div_) {
1c177b6a
DV
172 this.ylabel_div_.children[0].children[0].innerHTML = g.getOption('ylabel');
173 }
174 if (this.y2label_div_) {
175 this.y2label_div_.children[0].children[0].innerHTML = g.getOption('y2label');
441e4a56 176 }
1748a51c
DV
177};
178
179chart_labels.prototype.clearChart = function() {
180};
181
3a7f87be 182chart_labels.prototype.destroy = function() {
42a9ebb8 183 this.detachLabels_();
3a7f87be
DV
184};
185
6ecc0739 186export default chart_labels;