Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / pybind / mgr / dashboard / static / AdminLTE-2.3.7 / plugins / flot / jquery.flot.canvas.js
1 /* Flot plugin for drawing all elements of a plot on the canvas.
2
3 Copyright (c) 2007-2013 IOLA and Ole Laursen.
4 Licensed under the MIT license.
5
6 Flot normally produces certain elements, like axis labels and the legend, using
7 HTML elements. This permits greater interactivity and customization, and often
8 looks better, due to cross-browser canvas text inconsistencies and limitations.
9
10 It can also be desirable to render the plot entirely in canvas, particularly
11 if the goal is to save it as an image, or if Flot is being used in a context
12 where the HTML DOM does not exist, as is the case within Node.js. This plugin
13 switches out Flot's standard drawing operations for canvas-only replacements.
14
15 Currently the plugin supports only axis labels, but it will eventually allow
16 every element of the plot to be rendered directly to canvas.
17
18 The plugin supports these options:
19
20 {
21     canvas: boolean
22 }
23
24 The "canvas" option controls whether full canvas drawing is enabled, making it
25 possible to toggle on and off. This is useful when a plot uses HTML text in the
26 browser, but needs to redraw with canvas text when exporting as an image.
27
28 */
29
30 (function($) {
31
32         var options = {
33                 canvas: true
34         };
35
36         var render, getTextInfo, addText;
37
38         // Cache the prototype hasOwnProperty for faster access
39
40         var hasOwnProperty = Object.prototype.hasOwnProperty;
41
42         function init(plot, classes) {
43
44                 var Canvas = classes.Canvas;
45
46                 // We only want to replace the functions once; the second time around
47                 // we would just get our new function back.  This whole replacing of
48                 // prototype functions is a disaster, and needs to be changed ASAP.
49
50                 if (render == null) {
51                         getTextInfo = Canvas.prototype.getTextInfo,
52                         addText = Canvas.prototype.addText,
53                         render = Canvas.prototype.render;
54                 }
55
56                 // Finishes rendering the canvas, including overlaid text
57
58                 Canvas.prototype.render = function() {
59
60                         if (!plot.getOptions().canvas) {
61                                 return render.call(this);
62                         }
63
64                         var context = this.context,
65                                 cache = this._textCache;
66
67                         // For each text layer, render elements marked as active
68
69                         context.save();
70                         context.textBaseline = "middle";
71
72                         for (var layerKey in cache) {
73                                 if (hasOwnProperty.call(cache, layerKey)) {
74                                         var layerCache = cache[layerKey];
75                                         for (var styleKey in layerCache) {
76                                                 if (hasOwnProperty.call(layerCache, styleKey)) {
77                                                         var styleCache = layerCache[styleKey],
78                                                                 updateStyles = true;
79                                                         for (var key in styleCache) {
80                                                                 if (hasOwnProperty.call(styleCache, key)) {
81
82                                                                         var info = styleCache[key],
83                                                                                 positions = info.positions,
84                                                                                 lines = info.lines;
85
86                                                                         // Since every element at this level of the cache have the
87                                                                         // same font and fill styles, we can just change them once
88                                                                         // using the values from the first element.
89
90                                                                         if (updateStyles) {
91                                                                                 context.fillStyle = info.font.color;
92                                                                                 context.font = info.font.definition;
93                                                                                 updateStyles = false;
94                                                                         }
95
96                                                                         for (var i = 0, position; position = positions[i]; i++) {
97                                                                                 if (position.active) {
98                                                                                         for (var j = 0, line; line = position.lines[j]; j++) {
99                                                                                                 context.fillText(lines[j].text, line[0], line[1]);
100                                                                                         }
101                                                                                 } else {
102                                                                                         positions.splice(i--, 1);
103                                                                                 }
104                                                                         }
105
106                                                                         if (positions.length == 0) {
107                                                                                 delete styleCache[key];
108                                                                         }
109                                                                 }
110                                                         }
111                                                 }
112                                         }
113                                 }
114                         }
115
116                         context.restore();
117                 };
118
119                 // Creates (if necessary) and returns a text info object.
120                 //
121                 // When the canvas option is set, the object looks like this:
122                 //
123                 // {
124                 //     width: Width of the text's bounding box.
125                 //     height: Height of the text's bounding box.
126                 //     positions: Array of positions at which this text is drawn.
127                 //     lines: [{
128                 //         height: Height of this line.
129                 //         widths: Width of this line.
130                 //         text: Text on this line.
131                 //     }],
132                 //     font: {
133                 //         definition: Canvas font property string.
134                 //         color: Color of the text.
135                 //     },
136                 // }
137                 //
138                 // The positions array contains objects that look like this:
139                 //
140                 // {
141                 //     active: Flag indicating whether the text should be visible.
142                 //     lines: Array of [x, y] coordinates at which to draw the line.
143                 //     x: X coordinate at which to draw the text.
144                 //     y: Y coordinate at which to draw the text.
145                 // }
146
147                 Canvas.prototype.getTextInfo = function(layer, text, font, angle, width) {
148
149                         if (!plot.getOptions().canvas) {
150                                 return getTextInfo.call(this, layer, text, font, angle, width);
151                         }
152
153                         var textStyle, layerCache, styleCache, info;
154
155                         // Cast the value to a string, in case we were given a number
156
157                         text = "" + text;
158
159                         // If the font is a font-spec object, generate a CSS definition
160
161                         if (typeof font === "object") {
162                                 textStyle = font.style + " " + font.variant + " " + font.weight + " " + font.size + "px " + font.family;
163                         } else {
164                                 textStyle = font;
165                         }
166
167                         // Retrieve (or create) the cache for the text's layer and styles
168
169                         layerCache = this._textCache[layer];
170
171                         if (layerCache == null) {
172                                 layerCache = this._textCache[layer] = {};
173                         }
174
175                         styleCache = layerCache[textStyle];
176
177                         if (styleCache == null) {
178                                 styleCache = layerCache[textStyle] = {};
179                         }
180
181                         info = styleCache[text];
182
183                         if (info == null) {
184
185                                 var context = this.context;
186
187                                 // If the font was provided as CSS, create a div with those
188                                 // classes and examine it to generate a canvas font spec.
189
190                                 if (typeof font !== "object") {
191
192                                         var element = $("<div>&nbsp;</div>")
193                                                 .css("position", "absolute")
194                                                 .addClass(typeof font === "string" ? font : null)
195                                                 .appendTo(this.getTextLayer(layer));
196
197                                         font = {
198                                                 lineHeight: element.height(),
199                                                 style: element.css("font-style"),
200                                                 variant: element.css("font-variant"),
201                                                 weight: element.css("font-weight"),
202                                                 family: element.css("font-family"),
203                                                 color: element.css("color")
204                                         };
205
206                                         // Setting line-height to 1, without units, sets it equal
207                                         // to the font-size, even if the font-size is abstract,
208                                         // like 'smaller'.  This enables us to read the real size
209                                         // via the element's height, working around browsers that
210                                         // return the literal 'smaller' value.
211
212                                         font.size = element.css("line-height", 1).height();
213
214                                         element.remove();
215                                 }
216
217                                 textStyle = font.style + " " + font.variant + " " + font.weight + " " + font.size + "px " + font.family;
218
219                                 // Create a new info object, initializing the dimensions to
220                                 // zero so we can count them up line-by-line.
221
222                                 info = styleCache[text] = {
223                                         width: 0,
224                                         height: 0,
225                                         positions: [],
226                                         lines: [],
227                                         font: {
228                                                 definition: textStyle,
229                                                 color: font.color
230                                         }
231                                 };
232
233                                 context.save();
234                                 context.font = textStyle;
235
236                                 // Canvas can't handle multi-line strings; break on various
237                                 // newlines, including HTML brs, to build a list of lines.
238                                 // Note that we could split directly on regexps, but IE < 9 is
239                                 // broken; revisit when we drop IE 7/8 support.
240
241                                 var lines = (text + "").replace(/<br ?\/?>|\r\n|\r/g, "\n").split("\n");
242
243                                 for (var i = 0; i < lines.length; ++i) {
244
245                                         var lineText = lines[i],
246                                                 measured = context.measureText(lineText);
247
248                                         info.width = Math.max(measured.width, info.width);
249                                         info.height += font.lineHeight;
250
251                                         info.lines.push({
252                                                 text: lineText,
253                                                 width: measured.width,
254                                                 height: font.lineHeight
255                                         });
256                                 }
257
258                                 context.restore();
259                         }
260
261                         return info;
262                 };
263
264                 // Adds a text string to the canvas text overlay.
265
266                 Canvas.prototype.addText = function(layer, x, y, text, font, angle, width, halign, valign) {
267
268                         if (!plot.getOptions().canvas) {
269                                 return addText.call(this, layer, x, y, text, font, angle, width, halign, valign);
270                         }
271
272                         var info = this.getTextInfo(layer, text, font, angle, width),
273                                 positions = info.positions,
274                                 lines = info.lines;
275
276                         // Text is drawn with baseline 'middle', which we need to account
277                         // for by adding half a line's height to the y position.
278
279                         y += info.height / lines.length / 2;
280
281                         // Tweak the initial y-position to match vertical alignment
282
283                         if (valign == "middle") {
284                                 y = Math.round(y - info.height / 2);
285                         } else if (valign == "bottom") {
286                                 y = Math.round(y - info.height);
287                         } else {
288                                 y = Math.round(y);
289                         }
290
291                         // FIXME: LEGACY BROWSER FIX
292                         // AFFECTS: Opera < 12.00
293
294                         // Offset the y coordinate, since Opera is off pretty
295                         // consistently compared to the other browsers.
296
297                         if (!!(window.opera && window.opera.version().split(".")[0] < 12)) {
298                                 y -= 2;
299                         }
300
301                         // Determine whether this text already exists at this position.
302                         // If so, mark it for inclusion in the next render pass.
303
304                         for (var i = 0, position; position = positions[i]; i++) {
305                                 if (position.x == x && position.y == y) {
306                                         position.active = true;
307                                         return;
308                                 }
309                         }
310
311                         // If the text doesn't exist at this position, create a new entry
312
313                         position = {
314                                 active: true,
315                                 lines: [],
316                                 x: x,
317                                 y: y
318                         };
319
320                         positions.push(position);
321
322                         // Fill in the x & y positions of each line, adjusting them
323                         // individually for horizontal alignment.
324
325                         for (var i = 0, line; line = lines[i]; i++) {
326                                 if (halign == "center") {
327                                         position.lines.push([Math.round(x - line.width / 2), y]);
328                                 } else if (halign == "right") {
329                                         position.lines.push([Math.round(x - line.width), y]);
330                                 } else {
331                                         position.lines.push([Math.round(x), y]);
332                                 }
333                                 y += line.height;
334                         }
335                 };
336         }
337
338         $.plot.plugins.push({
339                 init: init,
340                 options: options,
341                 name: "canvas",
342                 version: "1.0"
343         });
344
345 })(jQuery);