All Downloads are FREE. Search and download functionalities are using the official Maven repository.

META-INF.resources.bower_components.jqplot-jwebswing.plugins.jqplot.mekkoRenderer.js Maven / Gradle / Ivy

There is a newer version: 1.2.2.1-jre17
Show newest version
/**
 * jqPlot
 * Pure JavaScript plotting plugin using jQuery
 *
 * Version: 1.0.9
 * Revision: d96a669
 *
 * Copyright (c) 2009-2016 Chris Leonello
 * jqPlot is currently available for use in all personal or commercial projects
 * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL
 * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can
 * choose the license that best suits your project and use it accordingly.
 *
 * Although not required, the author would appreciate an email letting him
 * know of any substantial use of jqPlot.  You can reach the author at:
 * chris at jqplot dot com or see http://www.jqplot.com/info.php .
 *
 * If you are feeling kind and generous, consider supporting the project by
 * making a donation at: http://www.jqplot.com/donate.php .
 *
 * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
 *
 *     version 2007.04.27
 *     author Ash Searle
 *     http://hexmen.com/blog/2007/03/printf-sprintf/
 *     http://hexmen.com/js/sprintf.js
 *     The author (Ash Searle) has placed this code in the public domain:
 *     "This code is unrestricted: you are free to use it however you like."
 *
 */
(function ($) {
    /**
     * Class: $.jqplot.MekkoRenderer
     * Draws a Mekko style chart which shows 3 dimensional data on a 2 dimensional graph.
     * the <$.jqplot.MekkoAxisRenderer> should be used with mekko charts.  The mekko renderer
     * overrides the default legend renderer with its own $.jqplot.MekkoLegendRenderer
     * which allows more flexibility to specify number of rows and columns in the legend.
     *
     * Data is specified per bar in the chart.  You can specify data as an array of y values, or as
     * an array of [label, value] pairs.  Note that labels are used only on the first series.
     * Labels on subsequent series are ignored:
     *
     * > bar1 = [['shirts', 8],['hats', 14],['shoes', 6],['gloves', 16],['dolls', 12]];
     * > bar2 = [15,6,9,13,6];
     * > bar3 = [['grumpy',4],['sneezy',2],['happy',7],['sleepy',9],['doc',7]];
     *
     * If you want to place labels for each bar under the axis, you use the barLabels option on
     * the axes.  The bar labels can be styled with the ".jqplot-mekko-barLabel" css class.
     *
     * > barLabels = ['Mickey Mouse', 'Donald Duck', 'Goofy'];
     * > axes:{xaxis:{barLabels:barLabels}}
     *
     */


    $.jqplot.MekkoRenderer = function () {
        this.shapeRenderer = new $.jqplot.ShapeRenderer();
        // prop: borderColor
        // color of the borders between areas on the chart
        this.borderColor = null;
        // prop: showBorders
        // True to draw borders lines between areas on the chart.
        // False will draw borders lines with the same color as the area.
        this.showBorders = true;
    };

    // called with scope of series.
    $.jqplot.MekkoRenderer.prototype.init = function (options, plot) {
        this.fill = false;
        this.fillRect = true;
        this.strokeRect = true;
        this.shadow = false;
        // width of bar on x axis.
        this._xwidth = 0;
        this._xstart = 0;
        $.extend(true, this.renderer, options);
        // set the shape renderer options
        var opts = {
            lineJoin: 'miter',
            lineCap: 'butt',
            isarc: false,
            fillRect: this.fillRect,
            strokeRect: this.strokeRect
        };
        this.renderer.shapeRenderer.init(opts);
        plot.axes.x2axis._series.push(this);
        this._type = 'mekko';
    };

    // Method: setGridData
    // converts the user data values to grid coordinates and stores them
    // in the gridData array.  Will convert user data into appropriate
    // rectangles.
    // Called with scope of a series.
    $.jqplot.MekkoRenderer.prototype.setGridData = function (plot) {
        // recalculate the grid data
        var xp = this._xaxis.series_u2p;
        var yp = this._yaxis.series_u2p;
        var data = this._plotData;
        this.gridData = [];
        // figure out width on x axis.
        // this._xwidth = this._sumy / plot._sumy * this.canvas.getWidth();
        this._xwidth = xp(this._sumy) - xp(0);
        if (this.index > 0) {
            this._xstart = plot.series[this.index - 1]._xstart + plot.series[this.index - 1]._xwidth;
        }
        var totheight = this.canvas.getHeight();
        var sumy = 0;
        var cury;
        var curheight;
        for (var i = 0; i < data.length; i++) {
            if (data[i] != null) {
                sumy += data[i][1];
                cury = totheight - (sumy / this._sumy * totheight);
                curheight = data[i][1] / this._sumy * totheight;
                this.gridData.push([this._xstart, cury, this._xwidth, curheight]);
            }
        }
    };

    // Method: makeGridData
    // converts any arbitrary data values to grid coordinates and
    // returns them.  This method exists so that plugins can use a series'
    // linerenderer to generate grid data points without overwriting the
    // grid data associated with that series.
    // Called with scope of a series.
    $.jqplot.MekkoRenderer.prototype.makeGridData = function (data, plot) {
        // recalculate the grid data
        // figure out width on x axis.
        var xp = this._xaxis.series_u2p;
        var totheight = this.canvas.getHeight();
        var sumy = 0;
        var cury;
        var curheight;
        var gd = [];
        for (var i = 0; i < data.length; i++) {
            if (data[i] != null) {
                sumy += data[i][1];
                cury = totheight - (sumy / this._sumy * totheight);
                curheight = data[i][1] / this._sumy * totheight;
                gd.push([this._xstart, cury, this._xwidth, curheight]);
            }
        }
        return gd;
    };


    // called within scope of series.
    $.jqplot.MekkoRenderer.prototype.draw = function (ctx, gd, options) {
        var i;
        var opts = (options != undefined) ? options : {};
        var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;
        var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors);
        ctx.save();
        if (gd.length) {
            if (showLine) {
                for (i = 0; i < gd.length; i++) {
                    opts.fillStyle = colorGenerator.next();
                    if (this.renderer.showBorders) {
                        opts.strokeStyle = this.renderer.borderColor;
                    }
                    else {
                        opts.strokeStyle = opts.fillStyle;
                    }
                    this.renderer.shapeRenderer.draw(ctx, gd[i], opts);
                }
            }
        }

        ctx.restore();
    };

    $.jqplot.MekkoRenderer.prototype.drawShadow = function (ctx, gd, options) {
        // This is a no-op, no shadows on mekko charts.
    };

    /**
     * Class: $.jqplot.MekkoLegendRenderer
     * Legend renderer used by mekko charts with options for
     * controlling number or rows and columns as well as placement
     * outside of plot area.
     *
     */
    $.jqplot.MekkoLegendRenderer = function () {
        //
    };

    $.jqplot.MekkoLegendRenderer.prototype.init = function (options) {
        // prop: numberRows
        // Maximum number of rows in the legend.  0 or null for unlimited.
        this.numberRows = null;
        // prop: numberColumns
        // Maximum number of columns in the legend.  0 or null for unlimited.
        this.numberColumns = null;
        // this will override the placement option on the Legend object
        this.placement = "outside";
        $.extend(true, this, options);
    };

    // called with scope of legend
    $.jqplot.MekkoLegendRenderer.prototype.draw = function () {
        var legend = this;
        if (this.show) {
            var series = this._series;
            var ss = 'position:absolute;';
            ss += (this.background) ? 'background:' + this.background + ';' : '';
            ss += (this.border) ? 'border:' + this.border + ';' : '';
            ss += (this.fontSize) ? 'font-size:' + this.fontSize + ';' : '';
            ss += (this.fontFamily) ? 'font-family:' + this.fontFamily + ';' : '';
            ss += (this.textColor) ? 'color:' + this.textColor + ';' : '';
            this._elem = $('
'); // Mekko charts legends don't go by number of series, but by number of data points // in the series. Refactor things here for that. var pad = false, reverse = true, // mekko charts are always stacked, so reverse nr, nc; var s = series[0]; var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors); if (s.show) { var pd = s.data; if (this.numberRows) { nr = this.numberRows; if (!this.numberColumns) { nc = Math.ceil(pd.length / nr); } else { nc = this.numberColumns; } } else if (this.numberColumns) { nc = this.numberColumns; nr = Math.ceil(pd.length / this.numberColumns); } else { nr = pd.length; nc = 1; } var i, j, tr, td1, td2, lt, rs, color; var idx = 0; for (i = 0; i < nr; i++) { if (reverse) { tr = $('').prependTo(this._elem); } else { tr = $('').appendTo(this._elem); } for (j = 0; j < nc; j++) { if (idx < pd.length) { lt = this.labels[idx] || pd[idx][0].toString(); color = colorGenerator.next(); if (!reverse) { if (i > 0) { pad = true; } else { pad = false; } } else { if (i == nr - 1) { pad = false; } else { pad = true; } } rs = (pad) ? this.rowSpacing : '0'; td1 = $('' + '
' + '
'); td2 = $(''); if (this.escapeHtml) { td2.text(lt); } else { td2.html(lt); } if (reverse) { td2.prependTo(tr); td1.prependTo(tr); } else { td1.appendTo(tr); td2.appendTo(tr); } pad = true; } idx++; } } tr = null; td1 = null; td2 = null; } } return this._elem; }; $.jqplot.MekkoLegendRenderer.prototype.pack = function (offsets) { if (this.show) { // fake a grid for positioning var grid = { _top: offsets.top, _left: offsets.left, _right: offsets.right, _bottom: this._plotDimensions.height - offsets.bottom }; if (this.placement == 'insideGrid') { switch (this.location) { case 'nw': var a = grid._left + this.xoffset; var b = grid._top + this.yoffset; this._elem.css('left', a); this._elem.css('top', b); break; case 'n': var a = (offsets.left + (this._plotDimensions.width - offsets.right)) / 2 - this.getWidth() / 2; var b = grid._top + this.yoffset; this._elem.css('left', a); this._elem.css('top', b); break; case 'ne': var a = offsets.right + this.xoffset; var b = grid._top + this.yoffset; this._elem.css({right: a, top: b}); break; case 'e': var a = offsets.right + this.xoffset; var b = (offsets.top + (this._plotDimensions.height - offsets.bottom)) / 2 - this.getHeight() / 2; this._elem.css({right: a, top: b}); break; case 'se': var a = offsets.right + this.xoffset; var b = offsets.bottom + this.yoffset; this._elem.css({right: a, bottom: b}); break; case 's': var a = (offsets.left + (this._plotDimensions.width - offsets.right)) / 2 - this.getWidth() / 2; var b = offsets.bottom + this.yoffset; this._elem.css({left: a, bottom: b}); break; case 'sw': var a = grid._left + this.xoffset; var b = offsets.bottom + this.yoffset; this._elem.css({left: a, bottom: b}); break; case 'w': var a = grid._left + this.xoffset; var b = (offsets.top + (this._plotDimensions.height - offsets.bottom)) / 2 - this.getHeight() / 2; this._elem.css({left: a, top: b}); break; default: // same as 'se' var a = grid._right - this.xoffset; var b = grid._bottom + this.yoffset; this._elem.css({right: a, bottom: b}); break; } } else { switch (this.location) { case 'nw': var a = this._plotDimensions.width - grid._left + this.xoffset; var b = grid._top + this.yoffset; this._elem.css('right', a); this._elem.css('top', b); break; case 'n': var a = (offsets.left + (this._plotDimensions.width - offsets.right)) / 2 - this.getWidth() / 2; var b = this._plotDimensions.height - grid._top + this.yoffset; this._elem.css('left', a); this._elem.css('bottom', b); break; case 'ne': var a = this._plotDimensions.width - offsets.right + this.xoffset; var b = grid._top + this.yoffset; this._elem.css({left: a, top: b}); break; case 'e': var a = this._plotDimensions.width - offsets.right + this.xoffset; var b = (offsets.top + (this._plotDimensions.height - offsets.bottom)) / 2 - this.getHeight() / 2; this._elem.css({left: a, top: b}); break; case 'se': var a = this._plotDimensions.width - offsets.right + this.xoffset; var b = offsets.bottom + this.yoffset; this._elem.css({left: a, bottom: b}); break; case 's': var a = (offsets.left + (this._plotDimensions.width - offsets.right)) / 2 - this.getWidth() / 2; var b = this._plotDimensions.height - offsets.bottom + this.yoffset; this._elem.css({left: a, top: b}); break; case 'sw': var a = this._plotDimensions.width - grid._left + this.xoffset; var b = offsets.bottom + this.yoffset; this._elem.css({right: a, bottom: b}); break; case 'w': var a = this._plotDimensions.width - grid._left + this.xoffset; var b = (offsets.top + (this._plotDimensions.height - offsets.bottom)) / 2 - this.getHeight() / 2; this._elem.css({right: a, top: b}); break; default: // same as 'se' var a = grid._right - this.xoffset; var b = grid._bottom + this.yoffset; this._elem.css({right: a, bottom: b}); break; } } } }; // setup default renderers for axes and legend so user doesn't have to // called with scope of plot function preInit(target, data, options) { options = options || {}; options.axesDefaults = options.axesDefaults || {}; options.legend = options.legend || {}; options.seriesDefaults = options.seriesDefaults || {}; var setopts = false; if (options.seriesDefaults.renderer == $.jqplot.MekkoRenderer) { setopts = true; } else if (options.series) { for (var i = 0; i < options.series.length; i++) { if (options.series[i].renderer == $.jqplot.MekkoRenderer) { setopts = true; } } } if (setopts) { options.axesDefaults.renderer = $.jqplot.MekkoAxisRenderer; options.legend.renderer = $.jqplot.MekkoLegendRenderer; options.legend.preDraw = true; } } $.jqplot.preInitHooks.push(preInit); })(jQuery);




© 2015 - 2025 Weber Informatics LLC | Privacy Policy