[ 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 var objCounter = 0; 33 // class: $.jqplot.CanvasOverlay 34 $.jqplot.CanvasOverlay = function(opts){ 35 var options = opts || {}; 36 this.options = { 37 show: $.jqplot.config.enablePlugins, 38 deferDraw: false 39 }; 40 // prop: objects 41 this.objects = []; 42 this.objectNames = []; 43 this.canvas = null; 44 this.markerRenderer = new $.jqplot.MarkerRenderer({style:'line'}); 45 this.markerRenderer.init(); 46 this.highlightObjectIndex = null; 47 if (options.objects) { 48 var objs = options.objects, 49 obj; 50 for (var i=0; i<objs.length; i++) { 51 obj = objs[i]; 52 for (var n in obj) { 53 switch (n) { 54 case 'line': 55 this.addLine(obj[n]); 56 break; 57 case 'horizontalLine': 58 this.addHorizontalLine(obj[n]); 59 break; 60 case 'dashedHorizontalLine': 61 this.addDashedHorizontalLine(obj[n]); 62 break; 63 case 'verticalLine': 64 this.addVerticalLine(obj[n]); 65 break; 66 case 'dashedVerticalLine': 67 this.addDashedVerticalLine(obj[n]); 68 break; 69 default: 70 break; 71 } 72 } 73 } 74 } 75 $.extend(true, this.options, options); 76 }; 77 78 // called with scope of a plot object 79 $.jqplot.CanvasOverlay.postPlotInit = function (target, data, opts) { 80 var options = opts || {}; 81 // add a canvasOverlay attribute to the plot 82 this.plugins.canvasOverlay = new $.jqplot.CanvasOverlay(options.canvasOverlay); 83 }; 84 85 86 function LineBase() { 87 this.uid = null; 88 this.type = null; 89 this.gridStart = null; 90 this.gridStop = null; 91 this.tooltipWidthFactor = 0; 92 this.options = { 93 // prop: name 94 // Optional name for the overlay object. 95 // Can be later used to retrieve the object by name. 96 name: null, 97 // prop: show 98 // true to show (draw), false to not draw. 99 show: true, 100 // prop: lineWidth 101 // Width of the line. 102 lineWidth: 2, 103 // prop: lineCap 104 // Type of ending placed on the line ['round', 'butt', 'square'] 105 lineCap: 'round', 106 // prop: color 107 // color of the line 108 color: '#666666', 109 // prop: shadow 110 // wether or not to draw a shadow on the line 111 shadow: true, 112 // prop: shadowAngle 113 // Shadow angle in degrees 114 shadowAngle: 45, 115 // prop: shadowOffset 116 // Shadow offset from line in pixels 117 shadowOffset: 1, 118 // prop: shadowDepth 119 // Number of times shadow is stroked, each stroke offset shadowOffset from the last. 120 shadowDepth: 3, 121 // prop: shadowAlpha 122 // Alpha channel transparency of shadow. 0 = transparent. 123 shadowAlpha: '0.07', 124 // prop: xaxis 125 // X axis to use for positioning/scaling the line. 126 xaxis: 'xaxis', 127 // prop: yaxis 128 // Y axis to use for positioning/scaling the line. 129 yaxis: 'yaxis', 130 // prop: showTooltip 131 // Show a tooltip with data point values. 132 showTooltip: false, 133 // prop: showTooltipPrecision 134 // Controls how close to line cursor must be to show tooltip. 135 // Higher number = closer to line, lower number = farther from line. 136 // 1.0 = cursor must be over line. 137 showTooltipPrecision: 0.6, 138 // prop: tooltipLocation 139 // Where to position tooltip, 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw' 140 tooltipLocation: 'nw', 141 // prop: fadeTooltip 142 // true = fade in/out tooltip, flase = show/hide tooltip 143 fadeTooltip: true, 144 // prop: tooltipFadeSpeed 145 // 'slow', 'def', 'fast', or number of milliseconds. 146 tooltipFadeSpeed: "fast", 147 // prop: tooltipOffset 148 // Pixel offset of tooltip from the highlight. 149 tooltipOffset: 4, 150 // prop: tooltipFormatString 151 // Format string passed the x and y values of the cursor on the line. 152 // e.g., 'Dogs: %.2f, Cats: %d'. 153 tooltipFormatString: '%d, %d' 154 }; 155 } 156 157 /** 158 * Class: Line 159 * A straight line. 160 */ 161 function Line(options) { 162 LineBase.call(this); 163 this.type = 'line'; 164 var opts = { 165 // prop: start 166 // [x, y] coordinates for the start of the line. 167 start: [], 168 // prop: stop 169 // [x, y] coordinates for the end of the line. 170 stop: [] 171 }; 172 $.extend(true, this.options, opts, options); 173 174 if (this.options.showTooltipPrecision < 0.01) { 175 this.options.showTooltipPrecision = 0.01; 176 } 177 } 178 179 Line.prototype = new LineBase(); 180 Line.prototype.constructor = Line; 181 182 183 /** 184 * Class: HorizontalLine 185 * A straight horizontal line. 186 */ 187 function HorizontalLine(options) { 188 LineBase.call(this); 189 this.type = 'horizontalLine'; 190 var opts = { 191 // prop: y 192 // y value to position the line 193 y: null, 194 // prop: xmin 195 // x value for the start of the line, null to scale to axis min. 196 xmin: null, 197 // prop: xmax 198 // x value for the end of the line, null to scale to axis max. 199 xmax: null, 200 // prop xOffset 201 // offset ends of the line inside the grid. Number 202 xOffset: '6px', // number or string. Number interpreted as units, string as pixels. 203 xminOffset: null, 204 xmaxOffset: null 205 }; 206 $.extend(true, this.options, opts, options); 207 208 if (this.options.showTooltipPrecision < 0.01) { 209 this.options.showTooltipPrecision = 0.01; 210 } 211 } 212 213 HorizontalLine.prototype = new LineBase(); 214 HorizontalLine.prototype.constructor = HorizontalLine; 215 216 217 /** 218 * Class: DashedHorizontalLine 219 * A straight dashed horizontal line. 220 */ 221 function DashedHorizontalLine(options) { 222 LineBase.call(this); 223 this.type = 'dashedHorizontalLine'; 224 var opts = { 225 y: null, 226 xmin: null, 227 xmax: null, 228 xOffset: '6px', // number or string. Number interpreted as units, string as pixels. 229 xminOffset: null, 230 xmaxOffset: null, 231 // prop: dashPattern 232 // Array of line, space settings in pixels. 233 // Default is 8 pixel of line, 8 pixel of space. 234 // Note, limit to a 2 element array b/c of bug with higher order arrays. 235 dashPattern: [8,8] 236 }; 237 $.extend(true, this.options, opts, options); 238 239 if (this.options.showTooltipPrecision < 0.01) { 240 this.options.showTooltipPrecision = 0.01; 241 } 242 } 243 244 DashedHorizontalLine.prototype = new LineBase(); 245 DashedHorizontalLine.prototype.constructor = DashedHorizontalLine; 246 247 248 /** 249 * Class: VerticalLine 250 * A straight vertical line. 251 */ 252 function VerticalLine(options) { 253 LineBase.call(this); 254 this.type = 'verticalLine'; 255 var opts = { 256 x: null, 257 ymin: null, 258 ymax: null, 259 yOffset: '6px', // number or string. Number interpreted as units, string as pixels. 260 yminOffset: null, 261 ymaxOffset: null 262 }; 263 $.extend(true, this.options, opts, options); 264 265 if (this.options.showTooltipPrecision < 0.01) { 266 this.options.showTooltipPrecision = 0.01; 267 } 268 } 269 270 VerticalLine.prototype = new LineBase(); 271 VerticalLine.prototype.constructor = VerticalLine; 272 273 274 /** 275 * Class: DashedVerticalLine 276 * A straight dashed vertical line. 277 */ 278 function DashedVerticalLine(options) { 279 LineBase.call(this); 280 this.type = 'dashedVerticalLine'; 281 this.start = null; 282 this.stop = null; 283 var opts = { 284 x: null, 285 ymin: null, 286 ymax: null, 287 yOffset: '6px', // number or string. Number interpreted as units, string as pixels. 288 yminOffset: null, 289 ymaxOffset: null, 290 // prop: dashPattern 291 // Array of line, space settings in pixels. 292 // Default is 8 pixel of line, 8 pixel of space. 293 // Note, limit to a 2 element array b/c of bug with higher order arrays. 294 dashPattern: [8,8] 295 }; 296 $.extend(true, this.options, opts, options); 297 298 if (this.options.showTooltipPrecision < 0.01) { 299 this.options.showTooltipPrecision = 0.01; 300 } 301 } 302 303 DashedVerticalLine.prototype = new LineBase(); 304 DashedVerticalLine.prototype.constructor = DashedVerticalLine; 305 306 $.jqplot.CanvasOverlay.prototype.addLine = function(opts) { 307 var line = new Line(opts); 308 line.uid = objCounter++; 309 this.objects.push(line); 310 this.objectNames.push(line.options.name); 311 }; 312 313 $.jqplot.CanvasOverlay.prototype.addHorizontalLine = function(opts) { 314 var line = new HorizontalLine(opts); 315 line.uid = objCounter++; 316 this.objects.push(line); 317 this.objectNames.push(line.options.name); 318 }; 319 320 $.jqplot.CanvasOverlay.prototype.addDashedHorizontalLine = function(opts) { 321 var line = new DashedHorizontalLine(opts); 322 line.uid = objCounter++; 323 this.objects.push(line); 324 this.objectNames.push(line.options.name); 325 }; 326 327 $.jqplot.CanvasOverlay.prototype.addVerticalLine = function(opts) { 328 var line = new VerticalLine(opts); 329 line.uid = objCounter++; 330 this.objects.push(line); 331 this.objectNames.push(line.options.name); 332 }; 333 334 $.jqplot.CanvasOverlay.prototype.addDashedVerticalLine = function(opts) { 335 var line = new DashedVerticalLine(opts); 336 line.uid = objCounter++; 337 this.objects.push(line); 338 this.objectNames.push(line.options.name); 339 }; 340 341 $.jqplot.CanvasOverlay.prototype.removeObject = function(idx) { 342 // check if integer, remove by index 343 if ($.type(idx) == 'number') { 344 this.objects.splice(idx, 1); 345 this.objectNames.splice(idx, 1); 346 } 347 // if string, remove by name 348 else { 349 var id = $.inArray(idx, this.objectNames); 350 if (id != -1) { 351 this.objects.splice(id, 1); 352 this.objectNames.splice(id, 1); 353 } 354 } 355 }; 356 357 $.jqplot.CanvasOverlay.prototype.getObject = function(idx) { 358 // check if integer, remove by index 359 if ($.type(idx) == 'number') { 360 return this.objects[idx]; 361 } 362 // if string, remove by name 363 else { 364 var id = $.inArray(idx, this.objectNames); 365 if (id != -1) { 366 return this.objects[id]; 367 } 368 } 369 }; 370 371 // Set get as alias for getObject. 372 $.jqplot.CanvasOverlay.prototype.get = $.jqplot.CanvasOverlay.prototype.getObject; 373 374 $.jqplot.CanvasOverlay.prototype.clear = function(plot) { 375 this.canvas._ctx.clearRect(0,0,this.canvas.getWidth(), this.canvas.getHeight()); 376 }; 377 378 $.jqplot.CanvasOverlay.prototype.draw = function(plot) { 379 var obj, 380 objs = this.objects, 381 mr = this.markerRenderer, 382 start, 383 stop; 384 if (this.options.show) { 385 this.canvas._ctx.clearRect(0,0,this.canvas.getWidth(), this.canvas.getHeight()); 386 for (var k=0; k<objs.length; k++) { 387 obj = objs[k]; 388 var opts = $.extend(true, {}, obj.options); 389 if (obj.options.show) { 390 // style and shadow properties should be set before 391 // every draw of marker renderer. 392 mr.shadow = obj.options.shadow; 393 obj.tooltipWidthFactor = obj.options.lineWidth / obj.options.showTooltipPrecision; 394 switch (obj.type) { 395 case 'line': 396 // style and shadow properties should be set before 397 // every draw of marker renderer. 398 mr.style = 'line'; 399 opts.closePath = false; 400 start = [plot.axes[obj.options.xaxis].series_u2p(obj.options.start[0]), plot.axes[obj.options.yaxis].series_u2p(obj.options.start[1])]; 401 stop = [plot.axes[obj.options.xaxis].series_u2p(obj.options.stop[0]), plot.axes[obj.options.yaxis].series_u2p(obj.options.stop[1])]; 402 obj.gridStart = start; 403 obj.gridStop = stop; 404 mr.draw(start, stop, this.canvas._ctx, opts); 405 break; 406 case 'horizontalLine': 407 408 // style and shadow properties should be set before 409 // every draw of marker renderer. 410 if (obj.options.y != null) { 411 mr.style = 'line'; 412 opts.closePath = false; 413 var xaxis = plot.axes[obj.options.xaxis], 414 xstart, 415 xstop, 416 y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y), 417 xminoff = obj.options.xminOffset || obj.options.xOffset, 418 xmaxoff = obj.options.xmaxOffset || obj.options.xOffset; 419 if (obj.options.xmin != null) { 420 xstart = xaxis.series_u2p(obj.options.xmin); 421 } 422 else if (xminoff != null) { 423 if ($.type(xminoff) == "number") { 424 xstart = xaxis.series_u2p(xaxis.min + xminoff); 425 } 426 else if ($.type(xminoff) == "string") { 427 xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff); 428 } 429 } 430 if (obj.options.xmax != null) { 431 xstop = xaxis.series_u2p(obj.options.xmax); 432 } 433 else if (xmaxoff != null) { 434 if ($.type(xmaxoff) == "number") { 435 xstop = xaxis.series_u2p(xaxis.max - xmaxoff); 436 } 437 else if ($.type(xmaxoff) == "string") { 438 xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff); 439 } 440 } 441 if (xstop != null && xstart != null) { 442 obj.gridStart = [xstart, y]; 443 obj.gridStop = [xstop, y]; 444 mr.draw([xstart, y], [xstop, y], this.canvas._ctx, opts); 445 } 446 } 447 break; 448 449 case 'dashedHorizontalLine': 450 451 var dashPat = obj.options.dashPattern; 452 var dashPatLen = 0; 453 for (var i=0; i<dashPat.length; i++) { 454 dashPatLen += dashPat[i]; 455 } 456 457 // style and shadow properties should be set before 458 // every draw of marker renderer. 459 if (obj.options.y != null) { 460 mr.style = 'line'; 461 opts.closePath = false; 462 var xaxis = plot.axes[obj.options.xaxis], 463 xstart, 464 xstop, 465 y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y), 466 xminoff = obj.options.xminOffset || obj.options.xOffset, 467 xmaxoff = obj.options.xmaxOffset || obj.options.xOffset; 468 if (obj.options.xmin != null) { 469 xstart = xaxis.series_u2p(obj.options.xmin); 470 } 471 else if (xminoff != null) { 472 if ($.type(xminoff) == "number") { 473 xstart = xaxis.series_u2p(xaxis.min + xminoff); 474 } 475 else if ($.type(xminoff) == "string") { 476 xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff); 477 } 478 } 479 if (obj.options.xmax != null) { 480 xstop = xaxis.series_u2p(obj.options.xmax); 481 } 482 else if (xmaxoff != null) { 483 if ($.type(xmaxoff) == "number") { 484 xstop = xaxis.series_u2p(xaxis.max - xmaxoff); 485 } 486 else if ($.type(xmaxoff) == "string") { 487 xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff); 488 } 489 } 490 if (xstop != null && xstart != null) { 491 obj.gridStart = [xstart, y]; 492 obj.gridStop = [xstop, y]; 493 var numDash = Math.ceil((xstop - xstart)/dashPatLen); 494 var b=xstart, e; 495 for (var i=0; i<numDash; i++) { 496 for (var j=0; j<dashPat.length; j+=2) { 497 e = b+dashPat[j]; 498 mr.draw([b, y], [e, y], this.canvas._ctx, opts); 499 b += dashPat[j]; 500 if (j < dashPat.length-1) { 501 b += dashPat[j+1]; 502 } 503 } 504 } 505 } 506 } 507 break; 508 509 case 'verticalLine': 510 511 // style and shadow properties should be set before 512 // every draw of marker renderer. 513 if (obj.options.x != null) { 514 mr.style = 'line'; 515 opts.closePath = false; 516 var yaxis = plot.axes[obj.options.yaxis], 517 ystart, 518 ystop, 519 x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x), 520 yminoff = obj.options.yminOffset || obj.options.yOffset, 521 ymaxoff = obj.options.ymaxOffset || obj.options.yOffset; 522 if (obj.options.ymin != null) { 523 ystart = yaxis.series_u2p(obj.options.ymin); 524 } 525 else if (yminoff != null) { 526 if ($.type(yminoff) == "number") { 527 ystart = yaxis.series_u2p(yaxis.min - yminoff); 528 } 529 else if ($.type(yminoff) == "string") { 530 ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff); 531 } 532 } 533 if (obj.options.ymax != null) { 534 ystop = yaxis.series_u2p(obj.options.ymax); 535 } 536 else if (ymaxoff != null) { 537 if ($.type(ymaxoff) == "number") { 538 ystop = yaxis.series_u2p(yaxis.max + ymaxoff); 539 } 540 else if ($.type(ymaxoff) == "string") { 541 ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff); 542 } 543 } 544 if (ystop != null && ystart != null) { 545 obj.gridStart = [x, ystart]; 546 obj.gridStop = [x, ystop]; 547 mr.draw([x, ystart], [x, ystop], this.canvas._ctx, opts); 548 } 549 } 550 break; 551 552 case 'dashedVerticalLine': 553 554 var dashPat = obj.options.dashPattern; 555 var dashPatLen = 0; 556 for (var i=0; i<dashPat.length; i++) { 557 dashPatLen += dashPat[i]; 558 } 559 560 // style and shadow properties should be set before 561 // every draw of marker renderer. 562 if (obj.options.x != null) { 563 mr.style = 'line'; 564 opts.closePath = false; 565 var yaxis = plot.axes[obj.options.yaxis], 566 ystart, 567 ystop, 568 x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x), 569 yminoff = obj.options.yminOffset || obj.options.yOffset, 570 ymaxoff = obj.options.ymaxOffset || obj.options.yOffset; 571 if (obj.options.ymin != null) { 572 ystart = yaxis.series_u2p(obj.options.ymin); 573 } 574 else if (yminoff != null) { 575 if ($.type(yminoff) == "number") { 576 ystart = yaxis.series_u2p(yaxis.min - yminoff); 577 } 578 else if ($.type(yminoff) == "string") { 579 ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff); 580 } 581 } 582 if (obj.options.ymax != null) { 583 ystop = yaxis.series_u2p(obj.options.ymax); 584 } 585 else if (ymaxoff != null) { 586 if ($.type(ymaxoff) == "number") { 587 ystop = yaxis.series_u2p(yaxis.max + ymaxoff); 588 } 589 else if ($.type(ymaxoff) == "string") { 590 ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff); 591 } 592 } 593 594 595 if (ystop != null && ystart != null) { 596 obj.gridStart = [x, ystart]; 597 obj.gridStop = [x, ystop]; 598 var numDash = Math.ceil((ystart - ystop)/dashPatLen); 599 var firstDashAdjust = ((numDash * dashPatLen) - (ystart - ystop))/2.0; 600 var b=ystart, e, bs, es; 601 for (var i=0; i<numDash; i++) { 602 for (var j=0; j<dashPat.length; j+=2) { 603 e = b - dashPat[j]; 604 if (e < ystop) { 605 e = ystop; 606 } 607 if (b < ystop) { 608 b = ystop; 609 } 610 // es = e; 611 // if (i == 0) { 612 // es += firstDashAdjust; 613 // } 614 mr.draw([x, b], [x, e], this.canvas._ctx, opts); 615 b -= dashPat[j]; 616 if (j < dashPat.length-1) { 617 b -= dashPat[j+1]; 618 } 619 } 620 } 621 } 622 } 623 break; 624 625 default: 626 break; 627 } 628 } 629 } 630 } 631 }; 632 633 // called within context of plot 634 // create a canvas which we can draw on. 635 // insert it before the eventCanvas, so eventCanvas will still capture events. 636 $.jqplot.CanvasOverlay.postPlotDraw = function() { 637 var co = this.plugins.canvasOverlay; 638 // Memory Leaks patch 639 if (co && co.highlightCanvas) { 640 co.highlightCanvas.resetCanvas(); 641 co.highlightCanvas = null; 642 } 643 co.canvas = new $.jqplot.GenericCanvas(); 644 645 this.eventCanvas._elem.before(co.canvas.createElement(this._gridPadding, 'jqplot-overlayCanvas-canvas', this._plotDimensions, this)); 646 co.canvas.setContext(); 647 if (!co.deferDraw) { 648 co.draw(this); 649 } 650 651 var elem = document.createElement('div'); 652 co._tooltipElem = $(elem); 653 elem = null; 654 co._tooltipElem.addClass('jqplot-canvasOverlay-tooltip'); 655 co._tooltipElem.css({position:'absolute', display:'none'}); 656 657 this.eventCanvas._elem.before(co._tooltipElem); 658 this.eventCanvas._elem.bind('mouseleave', { elem: co._tooltipElem }, function (ev) { ev.data.elem.hide(); }); 659 660 var co = null; 661 }; 662 663 664 function showTooltip(plot, obj, gridpos, datapos) { 665 var co = plot.plugins.canvasOverlay; 666 var elem = co._tooltipElem; 667 668 var opts = obj.options, x, y; 669 670 elem.html($.jqplot.sprintf(opts.tooltipFormatString, datapos[0], datapos[1])); 671 672 switch (opts.tooltipLocation) { 673 case 'nw': 674 x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset; 675 y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true); 676 break; 677 case 'n': 678 x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true)/2; 679 y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true); 680 break; 681 case 'ne': 682 x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset; 683 y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true); 684 break; 685 case 'e': 686 x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset; 687 y = gridpos[1] + plot._gridPadding.top - elem.outerHeight(true)/2; 688 break; 689 case 'se': 690 x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset; 691 y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset; 692 break; 693 case 's': 694 x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true)/2; 695 y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset; 696 break; 697 case 'sw': 698 x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset; 699 y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset; 700 break; 701 case 'w': 702 x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset; 703 y = gridpos[1] + plot._gridPadding.top - elem.outerHeight(true)/2; 704 break; 705 default: // same as 'nw' 706 x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset; 707 y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true); 708 break; 709 } 710 711 elem.css('left', x); 712 elem.css('top', y); 713 if (opts.fadeTooltip) { 714 // Fix for stacked up animations. Thnanks Trevor! 715 elem.stop(true,true).fadeIn(opts.tooltipFadeSpeed); 716 } 717 else { 718 elem.show(); 719 } 720 elem = null; 721 } 722 723 724 function isNearLine(point, lstart, lstop, width) { 725 // r is point to test, p and q are end points. 726 var rx = point[0]; 727 var ry = point[1]; 728 var px = Math.round(lstop[0]); 729 var py = Math.round(lstop[1]); 730 var qx = Math.round(lstart[0]); 731 var qy = Math.round(lstart[1]); 732 733 var l = Math.sqrt(Math.pow(px-qx, 2) + Math.pow(py-qy, 2)); 734 735 // scale error term by length of line. 736 var eps = width*l; 737 var res = Math.abs((qx-px) * (ry-py) - (qy-py) * (rx-px)); 738 var ret = (res < eps) ? true : false; 739 return ret; 740 } 741 742 743 function handleMove(ev, gridpos, datapos, neighbor, plot) { 744 var co = plot.plugins.canvasOverlay; 745 var objs = co.objects; 746 var l = objs.length; 747 var obj, haveHighlight=false; 748 var elem; 749 for (var i=0; i<l; i++) { 750 obj = objs[i]; 751 if (obj.options.showTooltip) { 752 var n = isNearLine([gridpos.x, gridpos.y], obj.gridStart, obj.gridStop, obj.tooltipWidthFactor); 753 datapos = [plot.axes[obj.options.xaxis].series_p2u(gridpos.x), plot.axes[obj.options.yaxis].series_p2u(gridpos.y)]; 754 755 // cases: 756 // near line, no highlighting 757 // near line, highliting on this line 758 // near line, highlighting another line 759 // not near any line, highlighting 760 // not near any line, no highlighting 761 762 // near line, not currently highlighting 763 if (n && co.highlightObjectIndex == null) { 764 switch (obj.type) { 765 case 'line': 766 showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos); 767 break; 768 769 case 'horizontalLine': 770 case 'dashedHorizontalLine': 771 showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]); 772 break; 773 774 case 'verticalLine': 775 case 'dashedVerticalLine': 776 showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]); 777 break; 778 default: 779 break; 780 } 781 co.highlightObjectIndex = i; 782 haveHighlight = true; 783 break; 784 } 785 786 // near line, highlighting another line. 787 else if (n && co.highlightObjectIndex !== i) { 788 // turn off tooltip. 789 elem = co._tooltipElem; 790 if (obj.fadeTooltip) { 791 elem.fadeOut(obj.tooltipFadeSpeed); 792 } 793 else { 794 elem.hide(); 795 } 796 797 // turn on right tooltip. 798 switch (obj.type) { 799 case 'line': 800 showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos); 801 break; 802 803 case 'horizontalLine': 804 case 'dashedHorizontalLine': 805 showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]); 806 break; 807 808 case 'verticalLine': 809 case 'dashedVerticalLine': 810 showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]); 811 break; 812 default: 813 break; 814 } 815 816 co.highlightObjectIndex = i; 817 haveHighlight = true; 818 break; 819 } 820 821 // near line, already highlighting this line, update 822 else if (n) { 823 switch (obj.type) { 824 case 'line': 825 showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos); 826 break; 827 828 case 'horizontalLine': 829 case 'dashedHorizontalLine': 830 showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]); 831 break; 832 833 case 'verticalLine': 834 case 'dashedVerticalLine': 835 showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]); 836 break; 837 default: 838 break; 839 } 840 841 haveHighlight = true; 842 break; 843 } 844 } 845 } 846 847 // check if we are highlighting and not near a line, turn it off. 848 if (!haveHighlight && co.highlightObjectIndex !== null) { 849 elem = co._tooltipElem; 850 obj = co.getObject(co.highlightObjectIndex); 851 if (obj.fadeTooltip) { 852 elem.fadeOut(obj.tooltipFadeSpeed); 853 } 854 else { 855 elem.hide(); 856 } 857 co.highlightObjectIndex = null; 858 } 859 } 860 861 $.jqplot.postInitHooks.push($.jqplot.CanvasOverlay.postPlotInit); 862 $.jqplot.postDrawHooks.push($.jqplot.CanvasOverlay.postPlotDraw); 863 $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]); 864 865 })(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 |