PageSourceSearch

https://www.cpagrip.com/plugins/flot/jquery.flot.axislabels.js

js cpagrip.com collected 2026-10-02 05:32:18 UTC 19,541 bytes, 466 lines download raw bytes

1/*
2Axis Labels Plugin for flot.
3http://github.com/markrcote/flot-axislabels
4
5Original code is Copyright (c) 2010 Xuan Luo.
6Original code was released under the GPLv3 license by Xuan Luo, September 2010.
7Original code was rereleased under the MIT license by Xuan Luo, April 2012.
8
9Permission is hereby granted, free of charge, to any person obtaining
10a copy of this software and associated documentation files (the
11"Software"), to deal in the Software without restriction, including
12without limitation the rights to use, copy, modify, merge, publish,
13distribute, sublicense, and/or sell copies of the Software, and to
14permit persons to whom the Software is furnished to do so, subject to
15the following conditions:
16
17The above copyright notice and this permission notice shall be
18included in all copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29(function ($) {
30    var options = {
31      axisLabels: {
32        show: true
33      }
34    };
35
36    function canvasSupported() {
37        return !!document.createElement('canvas').getContext;
38    }
39
40    function canvasTextSupported() {
41        if (!canvasSupported()) {
42            return false;
43        }
44        var dummy_canvas = document.createElement('canvas');
45        var context = dummy_canvas.getContext('2d');
46        return typeof context.fillText == 'function';
47    }
48
49    function css3TransitionSupported() {
50        var div = document.createElement('div');
51        return typeof div.style.MozTransition != 'undefined'    // Gecko
52            || typeof div.style.OTransition != 'undefined'      // Opera
53            || typeof div.style.webkitTransition != 'undefined' // WebKit
54            || typeof div.style.transition != 'undefined';
55    }
56
57
58    function AxisLabel(axisName, position, padding, plot, opts) {
59        this.axisName = axisName;
60        this.position = position;
61        this.padding = padding;
62        this.plot = plot;
63        this.opts = opts;
64        this.width = 0;
65        this.height = 0;
66    }
67
68    AxisLabel.prototype.cleanup = function() {
69    };
70
71
72    CanvasAxisLabel.prototype = new AxisLabel();
73    CanvasAxisLabel.prototype.constructor = CanvasAxisLabel;
74    function CanvasAxisLabel(axisName, position, padding, plot, opts) {
75        AxisLabel.prototype.constructor.call(this, axisName, position, padding,
76                                             plot, opts);
77    }
78
79    CanvasAxisLabel.prototype.calculateSize = function() {
80        if (!this.opts.axisLabelFontSizePixels)
81            this.opts.axisLabelFontSizePixels = 14;
82        if (!this.opts.axisLabelFontFamily)
83            this.opts.axisLabelFontFamily = 'sans-serif';
84
85        var textWidth = this.opts.axisLabelFontSizePixels + this.padding;
86        var textHeight = this.opts.axisLabelFontSizePixels + this.padding;
87        if (this.position == 'left' || this.position == 'right') {
88            this.width = this.opts.axisLabelFontSizePixels + this.padding;
89            this.height = 0;
90        } else {
91            this.width = 0;
92            this.height = this.opts.axisLabelFontSizePixels + this.padding;
93        }
94    };
95
96    CanvasAxisLabel.prototype.draw = function(box) {
97        if (!this.opts.axisLabelColour)
98            this.opts.axisLabelColour = 'black';
99        var ctx = this.plot.getCanvas().getContext('2d');
100        ctx.save();
101        ctx.font = this.opts.axisLabelFontSizePixels + 'px ' +
102            this.opts.axisLabelFontFamily;
103        ctx.fillStyle = this.opts.axisLabelColour;
104        var width = ctx.measureText(this.opts.axisLabel).width;
105        var height = this.opts.axisLabelFontSizePixels;
106        var x, y, angle = 0;
107        if (this.position == 'top') {
108            x = box.left + box.width/2 - width/2;
109            y = box.top + height*0.72;
110        } else if (this.position == 'bottom') {
111            x = box.left + box.width/2 - width/2;
112            y = box.top + box.height - height*0.72;
113        } else if (this.position == 'left') {
114            x = box.left + height*0.72;
115            y = box.height/2 + box.top + width/2;
116            angle = -Math.PI/2;
117        } else if (this.position == 'right') {
118            x = box.left + box.width - height*0.72;
119            y = box.height/2 + box.top - width/2;
120            angle = Math.PI/2;
121        }
122        ctx.translate(x, y);
123        ctx.rotate(angle);
124        ctx.fillText(this.opts.axisLabel, 0, 0);
125        ctx.restore();
126    };
127
128
129    HtmlAxisLabel.prototype = new AxisLabel();
130    HtmlAxisLabel.prototype.constructor = HtmlAxisLabel;
131    function HtmlAxisLabel(axisName, position, padding, plot, opts) {
132        AxisLabel.prototype.constructor.call(this, axisName, position,
133                                             padding, plot, opts);
134        this.elem = null;
135    }
136
137    HtmlAxisLabel.prototype.calculateSize = function() {
138        var elem = $('<div class="axisLabels" style="position:absolute;">' +
139                     this.opts.axisLabel + '</div>');
140        this.plot.getPlaceholder().append(elem);
141        // store height and width of label itself, for use in draw()
142        this.labelWidth = elem.outerWidth(true);
143        this.labelHeight = elem.outerHeight(true);
144        elem.remove();
145
146        this.width = this.height = 0;
147        if (this.position == 'left' || this.position == 'right') {
148            this.width = this.labelWidth + this.padding;
149        } else {
150            this.height = this.labelHeight + this.padding;
151        }
152    };
153
154    HtmlAxisLabel.prototype.cleanup = function() {
155        if (this.elem) {
156            this.elem.remove();
157        }
158    };
159
160    HtmlAxisLabel.prototype.draw = function(box) {
161        this.plot.getPlaceholder().find('#' + this.axisName + 'Label').remove();
162        this.elem = $('<div id="' + this.axisName +
163                      'Label" " class="axisLabels" style="position:absolute;">'
164                      + this.opts.axisLabel + '</div>');
165        this.plot.getPlaceholder().append(this.elem);
166        if (this.position == 'top') {
167            this.elem.css('left', box.left + box.width/2 - this.labelWidth/2 +
168                          'px');
169            this.elem.css('top', box.top + 'px');
170        } else if (this.position == 'bottom') {
171            this.elem.css('left', box.left + box.width/2 - this.labelWidth/2 +
172                          'px');
173            this.elem.css('top', box.top + box.height - this.labelHeight +
174                          'px');
175        } else if (this.position == 'left') {
176            this.elem.css('top', box.top + box.height/2 - this.labelHeight/2 +
177                          'px');
178            this.elem.css('left', box.left + 'px');
179        } else if (this.position == 'right') {
180            this.elem.css('top', box.top + box.height/2 - this.labelHeight/2 +
181                          'px');
182            this.elem.css('left', box.left + box.width - this.labelWidth +
183                          'px');
184        }
185    };
186
187
188    CssTransformAxisLabel.prototype = new HtmlAxisLabel();
189    CssTransformAxisLabel.prototype.constructor = CssTransformAxisLabel;
190    function CssTransformAxisLabel(axisName, position, padding, plot, opts) {
191        HtmlAxisLabel.prototype.constructor.call(this, axisName, position,
192                                                 padding, plot, opts);
193    }
194
195    CssTransformAxisLabel.prototype.calculateSize = function() {
196        HtmlAxisLabel.prototype.calculateSize.call(this);
197        this.width = this.height = 0;
198        if (this.position == 'left' || this.position == 'right') {
199            this.width = this.labelHeight + this.padding;
200        } else {
201            this.height = this.labelHeight + this.padding;
202        }
203    };
204
205    CssTransformAxisLabel.prototype.transforms = function(degrees, x, y) {
206        var stransforms = {
207            '-moz-transform': '',
208            '-webkit-transform': '',
209            '-o-transform': '',
210            '-ms-transform': ''
211        };
212        if (x != 0 || y != 0) {
213            var stdTranslate = ' translate(' + x + 'px, ' + y + 'px)';
214            stransforms['-moz-transform'] += stdTranslate;
215            stransforms['-webkit-transform'] += stdTranslate;
216            stransforms['-o-transform'] += stdTranslate;
217            stransforms['-ms-transform'] += stdTranslate;
218        }
219        if (degrees != 0) {
220            var rotation = degrees / 90;
221            var stdRotate = ' rotate(' + degrees + 'deg)';
222            stransforms['-moz-transform'] += stdRotate;
223            stransforms['-webkit-transform'] += stdRotate;
224            stransforms['-o-transform'] += stdRotate;
225            stransforms['-ms-transform'] += stdRotate;
226        }
227        var s = 'top: 0; left: 0; ';
228        for (var prop in stransforms) {
229            if (stransforms[prop]) {
230                s += prop + ':' + stransforms[prop] + ';';
231            }
232        }
233        s += ';';
234        return s;
235    };
236
237    CssTransformAxisLabel.prototype.calculateOffsets = function(box) {
238        var offsets = { x: 0, y: 0, degrees: 0 };
239        if (this.position == 'bottom') {
240            offsets.x = box.left + box.width/2 - this.labelWidth/2;
241            offsets.y = box.top + box.height - this.labelHeight;
242        } else if (this.position == 'top') {
243            offsets.x = box.left + box.width/2 - this.labelWidth/2;
244            offsets.y = box.top;
245        } else if (this.position == 'left') {
246            offsets.degrees = -90;
247            offsets.x = box.left - this.labelWidth/2 + this.labelHeight/2;
248            offsets.y = box.height/2 + box.top;
249        } else if (this.position == 'right') {
250            offsets.degrees = 90;
251            offsets.x = box.left + box.width - this.labelWidth/2
252                        - this.labelHeight/2;
253            offsets.y = box.height/2 + box.top;
254        }
255        offsets.x = Math.round(offsets.x);
256        offsets.y = Math.round(offsets.y);
257
258        return offsets;
259    };
260
261    CssTransformAxisLabel.prototype.draw = function(box) {
262        this.plot.getPlaceholder().find("." + this.axisName + "Label").remove();
263        var offsets = this.calculateOffsets(box);
264        this.elem = $('<div class="axisLabels ' + this.axisName +
265                      'Label" style="position:absolute; ' +
266                      this.transforms(offsets.degrees, offsets.x, offsets.y) +
267                      '">' + this.opts.axisLabel + '</div>');
268        this.plot.getPlaceholder().append(this.elem);
269    };
270
271
272    IeTransformAxisLabel.prototype = new CssTransformAxisLabel();
273    IeTransformAxisLabel.prototype.constructor = IeTransformAxisLabel;
274    function IeTransformAxisLabel(axisName, position, padding, plot, opts) {
275        CssTransformAxisLabel.prototype.constructor.call(this, axisName,
276                                                         position, padding,
277                                                         plot, opts);
278        this.requiresResize = false;
279    }
280
281    IeTransformAxisLabel.prototype.transforms = function(degrees, x, y) {
282        // I didn't feel like learning the crazy Matrix stuff, so this uses
283        // a combination of the rotation transform and CSS positioning.
284        var s = '';
285        if (degrees != 0) {
286            var rotation = degrees/90;
287            while (rotation < 0) {
288                rotation += 4;
289            }
290            s += ' filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=' + rotation + '); ';
291            // see below
292            this.requiresResize = (this.position == 'right');
293        }
294        if (x != 0) {
295            s += 'left: ' + x + 'px; ';
296        }
297        if (y != 0) {
298            s += 'top: ' + y + 'px; ';
299        }
300        return s;
301    };
302
303    IeTransformAxisLabel.prototype.calculateOffsets = function(box) {
304        var offsets = CssTransformAxisLabel.prototype.calculateOffsets.call(
305                          this, box);
306        // adjust some values to take into account differences between
307        // CSS and IE rotations.
308        if (this.position == 'top') {
309            // FIXME: not sure why, but placing this exactly at the top causes
310            // the top axis label to flip to the bottom...
311            offsets.y = box.top + 1;
312        } else if (this.position == 'left') {
313            offsets.x = box.left;
314            offsets.y = box.height/2 + box.top - this.labelWidth/2;
315        } else if (this.position == 'right') {
316            offsets.x = box.left + box.width - this.labelHeight;
317            offsets.y = box.height/2 + box.top - this.labelWidth/2;
318        }
319        return offsets;
320    };
321
322    IeTransformAxisLabel.prototype.draw = function(box) {
323        CssTransformAxisLabel.prototype.draw.call(this, box);
324        if (this.requiresResize) {
325            this.elem = this.plot.getPlaceholder().find("." + this.axisName +
326                                                        "Label");
327            // Since we used CSS positioning instead of transforms for
328            // translating the element, and since the positioning is done
329            // before any rotations, we have to reset the width and height
330            // in case the browser wrapped the text (specifically for the
331            // y2axis).
332            this.elem.css('width', this.labelWidth);
333            this.elem.css('height', this.labelHeight);
334        }
335    };
336
337
338    function init(plot) {
339        plot.hooks.processOptions.push(function (plot, options) {
340
341            if (!options.axisLabels.show)
342                return;
343
344            // This is kind of a hack. There are no hooks in Flot between
345            // the creation and measuring of the ticks (setTicks, measureTickLabels
346            // in setupGrid() ) and the drawing of the ticks and plot box
347            // (insertAxisLabels in setupGrid() ).
348            //
349            // Therefore, we use a trick where we run the draw routine twice:
350            // the first time to get the tick measurements, so that we can change
351            // them, and then have it draw it again.
352            var secondPass = false;
353
354            var axisLabels = {};
355            var axisOffsetCounts = { left: 0, right: 0, top: 0, bottom: 0 };
356
357            var defaultPadding = 2;  // padding between axis and tick labels
358            plot.hooks.draw.push(function (plot, ctx) {
359                var hasAxisLabels = false;
360                if (!secondPass) {
361                    // MEASURE AND SET OPTIONS
362                    $.each(plot.getAxes(), function(axisName, axis) {
363                        var opts = axis.options // Flot 0.7
364                            || plot.getOptions()[axisName]; // Flot 0.6
365
366                        // Handle redraws initiated outside of this plug-in.
367                        if (axisName in axisLabels) {
368                            axis.labelHeight = axis.labelHeight -
369                                axisLabels[axisName].height;
370                            axis.labelWidth = axis.labelWidth -
371                                axisLabels[axisName].width;
372                            opts.labelHeight = axis.labelHeight;
373                            opts.labelWidth = axis.labelWidth;
374                            axisLabels[axisName].cleanup();
375                            delete axisLabels[axisName];
376                        }
377
378                        if (!opts || !opts.axisLabel || !axis.show)
379                            return;
380
381                        hasAxisLabels = true;
382                        var renderer = null;
383
384                        if (!opts.axisLabelUseHtml &&
385                            navigator.appName == 'Microsoft Internet Explorer') {
386                            var ua = navigator.userAgent;
387                            var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
388                            if (re.exec(ua) != null) {
389                                rv = parseFloat(RegExp.$1);
390                            }
391                            if (rv >= 9 && !opts.axisLabelUseCanvas && !opts.axisLabelUseHtml) {
392                                renderer = CssTransformAxisLabel;
393                            } else if (!opts.axisLabelUseCanvas && !opts.axisLabelUseHtml) {
394                                renderer = IeTransformAxisLabel;
395                            } else if (opts.axisLabelUseCanvas) {
396                                renderer = CanvasAxisLabel;
397                            } else {
398                                renderer = HtmlAxisLabel;
399                            }
400                        } else {
401                            if (opts.axisLabelUseHtml || (!css3TransitionSupported() && !canvasTextSupported()) && !opts.axisLabelUseCanvas) {
402                                renderer = HtmlAxisLabel;
403                            } else if (opts.axisLabelUseCanvas || !css3TransitionSupported()) {
404                                renderer = CanvasAxisLabel;
405                            } else {
406                                renderer = CssTransformAxisLabel;
407                            }
408                        }
409
410                        var padding = opts.axisLabelPadding === undefined ?
411                                      defaultPadding : opts.axisLabelPadding;
412
413                        axisLabels[axisName] = new renderer(axisName,
414                                                            axis.position, padding,
415                                                            plot, opts);
416
417                        // flot interprets axis.labelHeight and .labelWidth as
418                        // the height and width of the tick labels. We increase
419                        // these values to make room for the axis label and
420                        // padding.
421
422                        axisLabels[axisName].calculateSize();
423
424                        // AxisLabel.height and .width are the size of the
425                        // axis label and padding.
426                        // Just set opts here because axis will be sorted out on
427                        // the redraw.
428
429                        opts.labelHeight = axis.labelHeight +
430                            axisLabels[axisName].height;
431                        opts.labelWidth = axis.labelWidth +
432                            axisLabels[axisName].width;
433                    });
434
435                    // If there are axis labels, re-draw with new label widths and
436                    // heights.
437
438                    if (hasAxisLabels) {
439                        secondPass = true;
440                        plot.setupGrid();
441                        plot.draw();
442                    }
443                } else {
444                    secondPass = false;
445                    // DRAW
446                    $.each(plot.getAxes(), function(axisName, axis) {
447                        var opts = axis.options // Flot 0.7
448                            || plot.getOptions()[axisName]; // Flot 0.6
449                        if (!opts || !opts.axisLabel || !axis.show)
450                            return;
451
452                        axisLabels[axisName].draw(axis.box);
453                    });
454                }
455            });
456        });
457    }
458
459
460    $.plot.plugins.push({
461        init: init,
462        options: options,
463        name: 'axisLabels',
464        version: '2.0'
465    });
466})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.