[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 /** 2 * jqPlot 3 * Pure JavaScript plotting plugin using jQuery 4 * 5 * Version: 1.0.2 6 * Revision: 1108 7 * 8 * Copyright (c) 2009-2011 Chris Leonello 9 * jqPlot is currently available for use in all personal or commercial projects 10 * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 11 * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 12 * choose the license that best suits your project and use it accordingly. 13 * 14 * Although not required, the author would appreciate an email letting him 15 * know of any substantial use of jqPlot. You can reach the author at: 16 * chris at jqplot dot com or see http://www.jqplot.com/info.php . 17 * 18 * If you are feeling kind and generous, consider supporting the project by 19 * making a donation at: http://www.jqplot.com/donate.php . 20 * 21 * sprintf functions contained in jqplot.sprintf.js by Ash Searle: 22 * 23 * version 2007.04.27 24 * author Ash Searle 25 * http://hexmen.com/blog/2007/03/printf-sprintf/ 26 * http://hexmen.com/js/sprintf.js 27 * The author (Ash Searle) has placed this code in the public domain: 28 * "This code is unrestricted: you are free to use it however you like." 29 * 30 */ 31 (function($) { 32 /** 33 * Class: $.jqplot.MekkoRenderer 34 * Draws a Mekko style chart which shows 3 dimensional data on a 2 dimensional graph. 35 * the <$.jqplot.MekkoAxisRenderer> should be used with mekko charts. The mekko renderer 36 * overrides the default legend renderer with it's own $.jqplot.MekkoLegendRenderer 37 * which allows more flexibility to specify number of rows and columns in the legend. 38 * 39 * Data is specified per bar in the chart. You can specify data as an array of y values, or as 40 * an array of [label, value] pairs. Note that labels are used only on the first series. 41 * Labels on subsequent series are ignored: 42 * 43 * > bar1 = [['shirts', 8],['hats', 14],['shoes', 6],['gloves', 16],['dolls', 12]]; 44 * > bar2 = [15,6,9,13,6]; 45 * > bar3 = [['grumpy',4],['sneezy',2],['happy',7],['sleepy',9],['doc',7]]; 46 * 47 * If you want to place labels for each bar under the axis, you use the barLabels option on 48 * the axes. The bar labels can be styled with the ".jqplot-mekko-barLabel" css class. 49 * 50 * > barLabels = ['Mickey Mouse', 'Donald Duck', 'Goofy']; 51 * > axes:{xaxis:{barLabels:barLabels}} 52 * 53 */ 54 55 56 $.jqplot.MekkoRenderer = function(){ 57 this.shapeRenderer = new $.jqplot.ShapeRenderer(); 58 // prop: borderColor 59 // color of the borders between areas on the chart 60 this.borderColor = null; 61 // prop: showBorders 62 // True to draw borders lines between areas on the chart. 63 // False will draw borders lines with the same color as the area. 64 this.showBorders = true; 65 }; 66 67 // called with scope of series. 68 $.jqplot.MekkoRenderer.prototype.init = function(options, plot) { 69 this.fill = false; 70 this.fillRect = true; 71 this.strokeRect = true; 72 this.shadow = false; 73 // width of bar on x axis. 74 this._xwidth = 0; 75 this._xstart = 0; 76 $.extend(true, this.renderer, options); 77 // set the shape renderer options 78 var opts = {lineJoin:'miter', lineCap:'butt', isarc:false, fillRect:this.fillRect, strokeRect:this.strokeRect}; 79 this.renderer.shapeRenderer.init(opts); 80 plot.axes.x2axis._series.push(this); 81 this._type = 'mekko'; 82 }; 83 84 // Method: setGridData 85 // converts the user data values to grid coordinates and stores them 86 // in the gridData array. Will convert user data into appropriate 87 // rectangles. 88 // Called with scope of a series. 89 $.jqplot.MekkoRenderer.prototype.setGridData = function(plot) { 90 // recalculate the grid data 91 var xp = this._xaxis.series_u2p; 92 var yp = this._yaxis.series_u2p; 93 var data = this._plotData; 94 this.gridData = []; 95 // figure out width on x axis. 96 // this._xwidth = this._sumy / plot._sumy * this.canvas.getWidth(); 97 this._xwidth = xp(this._sumy) - xp(0); 98 if (this.index>0) { 99 this._xstart = plot.series[this.index-1]._xstart + plot.series[this.index-1]._xwidth; 100 } 101 var totheight = this.canvas.getHeight(); 102 var sumy = 0; 103 var cury; 104 var curheight; 105 for (var i=0; i<data.length; i++) { 106 if (data[i] != null) { 107 sumy += data[i][1]; 108 cury = totheight - (sumy / this._sumy * totheight); 109 curheight = data[i][1] / this._sumy * totheight; 110 this.gridData.push([this._xstart, cury, this._xwidth, curheight]); 111 } 112 } 113 }; 114 115 // Method: makeGridData 116 // converts any arbitrary data values to grid coordinates and 117 // returns them. This method exists so that plugins can use a series' 118 // linerenderer to generate grid data points without overwriting the 119 // grid data associated with that series. 120 // Called with scope of a series. 121 $.jqplot.MekkoRenderer.prototype.makeGridData = function(data, plot) { 122 // recalculate the grid data 123 // figure out width on x axis. 124 var xp = this._xaxis.series_u2p; 125 var totheight = this.canvas.getHeight(); 126 var sumy = 0; 127 var cury; 128 var curheight; 129 var gd = []; 130 for (var i=0; i<data.length; i++) { 131 if (data[i] != null) { 132 sumy += data[i][1]; 133 cury = totheight - (sumy / this._sumy * totheight); 134 curheight = data[i][1] / this._sumy * totheight; 135 gd.push([this._xstart, cury, this._xwidth, curheight]); 136 } 137 } 138 return gd; 139 }; 140 141 142 // called within scope of series. 143 $.jqplot.MekkoRenderer.prototype.draw = function(ctx, gd, options) { 144 var i; 145 var opts = (options != undefined) ? options : {}; 146 var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine; 147 var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors); 148 ctx.save(); 149 if (gd.length) { 150 if (showLine) { 151 for (i=0; i<gd.length; i++){ 152 opts.fillStyle = colorGenerator.next(); 153 if (this.renderer.showBorders) { 154 opts.strokeStyle = this.renderer.borderColor; 155 } 156 else { 157 opts.strokeStyle = opts.fillStyle; 158 } 159 this.renderer.shapeRenderer.draw(ctx, gd[i], opts); 160 } 161 } 162 } 163 164 ctx.restore(); 165 }; 166 167 $.jqplot.MekkoRenderer.prototype.drawShadow = function(ctx, gd, options) { 168 // This is a no-op, no shadows on mekko charts. 169 }; 170 171 /** 172 * Class: $.jqplot.MekkoLegendRenderer 173 * Legend renderer used by mekko charts with options for 174 * controlling number or rows and columns as well as placement 175 * outside of plot area. 176 * 177 */ 178 $.jqplot.MekkoLegendRenderer = function(){ 179 // 180 }; 181 182 $.jqplot.MekkoLegendRenderer.prototype.init = function(options) { 183 // prop: numberRows 184 // Maximum number of rows in the legend. 0 or null for unlimited. 185 this.numberRows = null; 186 // prop: numberColumns 187 // Maximum number of columns in the legend. 0 or null for unlimited. 188 this.numberColumns = null; 189 // this will override the placement option on the Legend object 190 this.placement = "outside"; 191 $.extend(true, this, options); 192 }; 193 194 // called with scope of legend 195 $.jqplot.MekkoLegendRenderer.prototype.draw = function() { 196 var legend = this; 197 if (this.show) { 198 var series = this._series; 199 var ss = 'position:absolute;'; 200 ss += (this.background) ? 'background:'+this.background+';' : ''; 201 ss += (this.border) ? 'border:'+this.border+';' : ''; 202 ss += (this.fontSize) ? 'font-size:'+this.fontSize+';' : ''; 203 ss += (this.fontFamily) ? 'font-family:'+this.fontFamily+';' : ''; 204 ss += (this.textColor) ? 'color:'+this.textColor+';' : ''; 205 this._elem = $('<table class="jqplot-table-legend" style="'+ss+'"></table>'); 206 // Mekko charts legends don't go by number of series, but by number of data points 207 // in the series. Refactor things here for that. 208 209 var pad = false, 210 reverse = true, // mekko charts are always stacked, so reverse 211 nr, nc; 212 var s = series[0]; 213 var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors); 214 215 if (s.show) { 216 var pd = s.data; 217 if (this.numberRows) { 218 nr = this.numberRows; 219 if (!this.numberColumns){ 220 nc = Math.ceil(pd.length/nr); 221 } 222 else{ 223 nc = this.numberColumns; 224 } 225 } 226 else if (this.numberColumns) { 227 nc = this.numberColumns; 228 nr = Math.ceil(pd.length/this.numberColumns); 229 } 230 else { 231 nr = pd.length; 232 nc = 1; 233 } 234 235 var i, j, tr, td1, td2, lt, rs, color; 236 var idx = 0; 237 238 for (i=0; i<nr; i++) { 239 if (reverse){ 240 tr = $('<tr class="jqplot-table-legend"></tr>').prependTo(this._elem); 241 } 242 else{ 243 tr = $('<tr class="jqplot-table-legend"></tr>').appendTo(this._elem); 244 } 245 for (j=0; j<nc; j++) { 246 if (idx < pd.length) { 247 lt = this.labels[idx] || pd[idx][0].toString(); 248 color = colorGenerator.next(); 249 if (!reverse){ 250 if (i>0){ 251 pad = true; 252 } 253 else{ 254 pad = false; 255 } 256 } 257 else{ 258 if (i == nr -1){ 259 pad = false; 260 } 261 else{ 262 pad = true; 263 } 264 } 265 rs = (pad) ? this.rowSpacing : '0'; 266 267 td1 = $('<td class="jqplot-table-legend" style="text-align:center;padding-top:'+rs+';">'+ 268 '<div><div class="jqplot-table-legend-swatch" style="border-color:'+color+';"></div>'+ 269 '</div></td>'); 270 td2 = $('<td class="jqplot-table-legend" style="padding-top:'+rs+';"></td>'); 271 if (this.escapeHtml){ 272 td2.text(lt); 273 } 274 else { 275 td2.html(lt); 276 } 277 if (reverse) { 278 td2.prependTo(tr); 279 td1.prependTo(tr); 280 } 281 else { 282 td1.appendTo(tr); 283 td2.appendTo(tr); 284 } 285 pad = true; 286 } 287 idx++; 288 } 289 } 290 291 tr = null; 292 td1 = null; 293 td2 = null; 294 } 295 } 296 return this._elem; 297 }; 298 299 $.jqplot.MekkoLegendRenderer.prototype.pack = function(offsets) { 300 if (this.show) { 301 // fake a grid for positioning 302 var grid = {_top:offsets.top, _left:offsets.left, _right:offsets.right, _bottom:this._plotDimensions.height - offsets.bottom}; 303 if (this.placement == 'insideGrid') { 304 switch (this.location) { 305 case 'nw': 306 var a = grid._left + this.xoffset; 307 var b = grid._top + this.yoffset; 308 this._elem.css('left', a); 309 this._elem.css('top', b); 310 break; 311 case 'n': 312 var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; 313 var b = grid._top + this.yoffset; 314 this._elem.css('left', a); 315 this._elem.css('top', b); 316 break; 317 case 'ne': 318 var a = offsets.right + this.xoffset; 319 var b = grid._top + this.yoffset; 320 this._elem.css({right:a, top:b}); 321 break; 322 case 'e': 323 var a = offsets.right + this.xoffset; 324 var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; 325 this._elem.css({right:a, top:b}); 326 break; 327 case 'se': 328 var a = offsets.right + this.xoffset; 329 var b = offsets.bottom + this.yoffset; 330 this._elem.css({right:a, bottom:b}); 331 break; 332 case 's': 333 var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; 334 var b = offsets.bottom + this.yoffset; 335 this._elem.css({left:a, bottom:b}); 336 break; 337 case 'sw': 338 var a = grid._left + this.xoffset; 339 var b = offsets.bottom + this.yoffset; 340 this._elem.css({left:a, bottom:b}); 341 break; 342 case 'w': 343 var a = grid._left + this.xoffset; 344 var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; 345 this._elem.css({left:a, top:b}); 346 break; 347 default: // same as 'se' 348 var a = grid._right - this.xoffset; 349 var b = grid._bottom + this.yoffset; 350 this._elem.css({right:a, bottom:b}); 351 break; 352 } 353 354 } 355 else { 356 switch (this.location) { 357 case 'nw': 358 var a = this._plotDimensions.width - grid._left + this.xoffset; 359 var b = grid._top + this.yoffset; 360 this._elem.css('right', a); 361 this._elem.css('top', b); 362 break; 363 case 'n': 364 var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; 365 var b = this._plotDimensions.height - grid._top + this.yoffset; 366 this._elem.css('left', a); 367 this._elem.css('bottom', b); 368 break; 369 case 'ne': 370 var a = this._plotDimensions.width - offsets.right + this.xoffset; 371 var b = grid._top + this.yoffset; 372 this._elem.css({left:a, top:b}); 373 break; 374 case 'e': 375 var a = this._plotDimensions.width - offsets.right + this.xoffset; 376 var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; 377 this._elem.css({left:a, top:b}); 378 break; 379 case 'se': 380 var a = this._plotDimensions.width - offsets.right + this.xoffset; 381 var b = offsets.bottom + this.yoffset; 382 this._elem.css({left:a, bottom:b}); 383 break; 384 case 's': 385 var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; 386 var b = this._plotDimensions.height - offsets.bottom + this.yoffset; 387 this._elem.css({left:a, top:b}); 388 break; 389 case 'sw': 390 var a = this._plotDimensions.width - grid._left + this.xoffset; 391 var b = offsets.bottom + this.yoffset; 392 this._elem.css({right:a, bottom:b}); 393 break; 394 case 'w': 395 var a = this._plotDimensions.width - grid._left + this.xoffset; 396 var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; 397 this._elem.css({right:a, top:b}); 398 break; 399 default: // same as 'se' 400 var a = grid._right - this.xoffset; 401 var b = grid._bottom + this.yoffset; 402 this._elem.css({right:a, bottom:b}); 403 break; 404 } 405 } 406 } 407 }; 408 409 // setup default renderers for axes and legend so user doesn't have to 410 // called with scope of plot 411 function preInit(target, data, options) { 412 options = options || {}; 413 options.axesDefaults = options.axesDefaults || {}; 414 options.legend = options.legend || {}; 415 options.seriesDefaults = options.seriesDefaults || {}; 416 var setopts = false; 417 if (options.seriesDefaults.renderer == $.jqplot.MekkoRenderer) { 418 setopts = true; 419 } 420 else if (options.series) { 421 for (var i=0; i < options.series.length; i++) { 422 if (options.series[i].renderer == $.jqplot.MekkoRenderer) { 423 setopts = true; 424 } 425 } 426 } 427 428 if (setopts) { 429 options.axesDefaults.renderer = $.jqplot.MekkoAxisRenderer; 430 options.legend.renderer = $.jqplot.MekkoLegendRenderer; 431 options.legend.preDraw = true; 432 } 433 } 434 435 $.jqplot.preInitHooks.push(preInit); 436 437 })(jQuery);
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:08:37 2014 | Cross-referenced by PHPXref 0.7.1 |