[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/libraries/jquery/jqplot/plugins/ -> jqplot.cursor.js (source)

   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      /**
  34       * Class: $.jqplot.Cursor
  35       * Plugin class representing the cursor as displayed on the plot.
  36       */
  37      $.jqplot.Cursor = function(options) {
  38          // Group: Properties
  39          //
  40          // prop: style
  41          // CSS spec for cursor style
  42          this.style = 'crosshair';
  43          this.previousCursor = 'auto';
  44          // prop: show
  45          // wether to show the cursor or not.
  46          this.show = $.jqplot.config.enablePlugins;
  47          // prop: showTooltip
  48          // show a cursor position tooltip.  Location of the tooltip
  49          // will be controlled by followMouse and tooltipLocation.
  50          this.showTooltip = true;
  51          // prop: followMouse
  52          // Tooltip follows the mouse, it is not at a fixed location.
  53          // Tooltip will show on the grid at the location given by
  54          // tooltipLocation, offset from the grid edge by tooltipOffset.
  55          this.followMouse = false;
  56          // prop: tooltipLocation
  57          // Where to position tooltip.  If followMouse is true, this is
  58          // relative to the cursor, otherwise, it is relative to the grid.
  59          // One of 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'
  60          this.tooltipLocation = 'se';
  61          // prop: tooltipOffset
  62          // Pixel offset of tooltip from the grid boudaries or cursor center.
  63          this.tooltipOffset = 6;
  64          // prop: showTooltipGridPosition
  65          // show the grid pixel coordinates of the mouse.
  66          this.showTooltipGridPosition = false;
  67          // prop: showTooltipUnitPosition
  68          // show the unit (data) coordinates of the mouse.
  69          this.showTooltipUnitPosition = true;
  70          // prop: showTooltipDataPosition
  71          // Used with showVerticalLine to show intersecting data points in the tooltip.
  72          this.showTooltipDataPosition = false;
  73          // prop: tooltipFormatString
  74          // sprintf format string for the tooltip.
  75          // Uses Ash Searle's javascript sprintf implementation
  76          // found here: http://hexmen.com/blog/2007/03/printf-sprintf/
  77          // See http://perldoc.perl.org/functions/sprintf.html for reference
  78          // Note, if showTooltipDataPosition is true, the default tooltipFormatString
  79          // will be set to the cursorLegendFormatString, not the default given here.
  80          this.tooltipFormatString = '%.4P, %.4P';
  81          // prop: useAxesFormatters
  82          // Use the x and y axes formatters to format the text in the tooltip.
  83          this.useAxesFormatters = true;
  84          // prop: tooltipAxisGroups
  85          // Show position for the specified axes.
  86          // This is an array like [['xaxis', 'yaxis'], ['xaxis', 'y2axis']]
  87          // Default is to compute automatically for all visible axes.
  88          this.tooltipAxisGroups = [];
  89          // prop: zoom
  90          // Enable plot zooming.
  91          this.zoom = false;
  92          // zoomProxy and zoomTarget properties are not directly set by user.  
  93          // They Will be set through call to zoomProxy method.
  94          this.zoomProxy = false;
  95          this.zoomTarget = false;
  96          // prop: looseZoom
  97          // Will expand zoom range to provide more rounded tick values.
  98          // Works only with linear, log and date axes.
  99          this.looseZoom = true;
 100          // prop: clickReset
 101          // Will reset plot zoom if single click on plot without drag.
 102          this.clickReset = false;
 103          // prop: dblClickReset
 104          // Will reset plot zoom if double click on plot without drag.
 105          this.dblClickReset = true;
 106          // prop: showVerticalLine
 107          // draw a vertical line across the plot which follows the cursor.
 108          // When the line is near a data point, a special legend and/or tooltip can
 109          // be updated with the data values.
 110          this.showVerticalLine = false;
 111          // prop: showHorizontalLine
 112          // draw a horizontal line across the plot which follows the cursor.
 113          this.showHorizontalLine = false;
 114          // prop: constrainZoomTo
 115          // 'none', 'x' or 'y'
 116          this.constrainZoomTo = 'none';
 117          // // prop: autoscaleConstraint
 118          // // when a constrained axis is specified, true will
 119          // // auatoscale the adjacent axis.
 120          // this.autoscaleConstraint = true;
 121          this.shapeRenderer = new $.jqplot.ShapeRenderer();
 122          this._zoom = {start:[], end:[], started: false, zooming:false, isZoomed:false, axes:{start:{}, end:{}}, gridpos:{}, datapos:{}};
 123          this._tooltipElem;
 124          this.zoomCanvas;
 125          this.cursorCanvas;
 126          // prop: intersectionThreshold
 127          // pixel distance from data point or marker to consider cursor lines intersecting with point.
 128          // If data point markers are not shown, this should be >= 1 or will often miss point intersections.
 129          this.intersectionThreshold = 2;
 130          // prop: showCursorLegend
 131          // Replace the plot legend with an enhanced legend displaying intersection information.
 132          this.showCursorLegend = false;
 133          // prop: cursorLegendFormatString
 134          // Format string used in the cursor legend.  If showTooltipDataPosition is true,
 135          // this will also be the default format string used by tooltipFormatString.
 136          this.cursorLegendFormatString = $.jqplot.Cursor.cursorLegendFormatString;
 137          // whether the cursor is over the grid or not.
 138          this._oldHandlers = {onselectstart: null, ondrag: null, onmousedown: null};
 139          // prop: constrainOutsideZoom
 140          // True to limit actual zoom area to edges of grid, even when zooming
 141          // outside of plot area.  That is, can't zoom out by mousing outside plot.
 142          this.constrainOutsideZoom = true;
 143          // prop: showTooltipOutsideZoom
 144          // True will keep updating the tooltip when zooming of the grid.
 145          this.showTooltipOutsideZoom = false;
 146          // true if mouse is over grid, false if not.
 147          this.onGrid = false;
 148          $.extend(true, this, options);
 149      };
 150      
 151      $.jqplot.Cursor.cursorLegendFormatString = '%s x:%s, y:%s';
 152      
 153      // called with scope of plot
 154      $.jqplot.Cursor.init = function (target, data, opts){
 155          // add a cursor attribute to the plot
 156          var options = opts || {};
 157          this.plugins.cursor = new $.jqplot.Cursor(options.cursor);
 158          var c = this.plugins.cursor;
 159  
 160          if (c.show) {
 161              $.jqplot.eventListenerHooks.push(['jqplotMouseEnter', handleMouseEnter]);
 162              $.jqplot.eventListenerHooks.push(['jqplotMouseLeave', handleMouseLeave]);
 163              $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMouseMove]);
 164              
 165              if (c.showCursorLegend) {              
 166                  opts.legend = opts.legend || {};
 167                  opts.legend.renderer =  $.jqplot.CursorLegendRenderer;
 168                  opts.legend.formatString = this.plugins.cursor.cursorLegendFormatString;
 169                  opts.legend.show = true;
 170              }
 171              
 172              if (c.zoom) {
 173                  $.jqplot.eventListenerHooks.push(['jqplotMouseDown', handleMouseDown]);
 174                  
 175                  if (c.clickReset) {
 176                      $.jqplot.eventListenerHooks.push(['jqplotClick', handleClick]);
 177                  }
 178                  
 179                  if (c.dblClickReset) {
 180                      $.jqplot.eventListenerHooks.push(['jqplotDblClick', handleDblClick]);
 181                  }             
 182              }
 183      
 184              this.resetZoom = function() {
 185                  var axes = this.axes;
 186                  if (!c.zoomProxy) {
 187                      for (var ax in axes) {
 188                          axes[ax].reset();
 189                          axes[ax]._ticks = [];
 190                          // fake out tick creation algorithm to make sure original auto
 191                          // computed format string is used if _overrideFormatString is true
 192                          if (c._zoom.axes[ax] !== undefined) {
 193                              axes[ax]._autoFormatString = c._zoom.axes[ax].tickFormatString;
 194                          }
 195                      }
 196                      this.redraw();
 197                  }
 198                  else {
 199                      var ctx = this.plugins.cursor.zoomCanvas._ctx;
 200                      ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
 201                      ctx = null;
 202                  }
 203                  this.plugins.cursor._zoom.isZoomed = false;
 204                  this.target.trigger('jqplotResetZoom', [this, this.plugins.cursor]);
 205              };
 206              
 207  
 208              if (c.showTooltipDataPosition) {
 209                  c.showTooltipUnitPosition = false;
 210                  c.showTooltipGridPosition = false;
 211                  if (options.cursor.tooltipFormatString == undefined) {
 212                      c.tooltipFormatString = $.jqplot.Cursor.cursorLegendFormatString;
 213                  }
 214              }
 215          }
 216      };
 217      
 218      // called with context of plot
 219      $.jqplot.Cursor.postDraw = function() {
 220          var c = this.plugins.cursor;
 221          
 222          // Memory Leaks patch
 223          if (c.zoomCanvas) {
 224              c.zoomCanvas.resetCanvas();
 225              c.zoomCanvas = null;
 226          }
 227          
 228          if (c.cursorCanvas) {
 229              c.cursorCanvas.resetCanvas();
 230              c.cursorCanvas = null;
 231          }
 232          
 233          if (c._tooltipElem) {
 234              c._tooltipElem.emptyForce();
 235              c._tooltipElem = null;
 236          }
 237  
 238          
 239          if (c.zoom) {
 240              c.zoomCanvas = new $.jqplot.GenericCanvas();
 241              this.eventCanvas._elem.before(c.zoomCanvas.createElement(this._gridPadding, 'jqplot-zoom-canvas', this._plotDimensions, this));
 242              c.zoomCanvas.setContext();
 243          }
 244  
 245          var elem = document.createElement('div');
 246          c._tooltipElem = $(elem);
 247          elem = null;
 248          c._tooltipElem.addClass('jqplot-cursor-tooltip');
 249          c._tooltipElem.css({position:'absolute', display:'none'});
 250          
 251          
 252          if (c.zoomCanvas) {
 253              c.zoomCanvas._elem.before(c._tooltipElem);
 254          }
 255  
 256          else {
 257              this.eventCanvas._elem.before(c._tooltipElem);
 258          }
 259  
 260          if (c.showVerticalLine || c.showHorizontalLine) {
 261              c.cursorCanvas = new $.jqplot.GenericCanvas();
 262              this.eventCanvas._elem.before(c.cursorCanvas.createElement(this._gridPadding, 'jqplot-cursor-canvas', this._plotDimensions, this));
 263              c.cursorCanvas.setContext();
 264          }
 265  
 266          // if we are showing the positions in unit coordinates, and no axes groups
 267          // were specified, create a default set.
 268          if (c.showTooltipUnitPosition){
 269              if (c.tooltipAxisGroups.length === 0) {
 270                  var series = this.series;
 271                  var s;
 272                  var temp = [];
 273                  for (var i=0; i<series.length; i++) {
 274                      s = series[i];
 275                      var ax = s.xaxis+','+s.yaxis;
 276                      if ($.inArray(ax, temp) == -1) {
 277                          temp.push(ax);
 278                      }
 279                  }
 280                  for (var i=0; i<temp.length; i++) {
 281                      c.tooltipAxisGroups.push(temp[i].split(','));
 282                  }
 283              }
 284          }
 285      };
 286      
 287      // Group: methods
 288      //
 289      // method: $.jqplot.Cursor.zoomProxy
 290      // links targetPlot to controllerPlot so that plot zooming of
 291      // targetPlot will be controlled by zooming on the controllerPlot.
 292      // controllerPlot will not actually zoom, but acts as an
 293      // overview plot.  Note, the zoom options must be set to true for
 294      // zoomProxy to work.
 295      $.jqplot.Cursor.zoomProxy = function(targetPlot, controllerPlot) {
 296          var tc = targetPlot.plugins.cursor;
 297          var cc = controllerPlot.plugins.cursor;
 298          tc.zoomTarget = true;
 299          tc.zoom = true;
 300          tc.style = 'auto';
 301          tc.dblClickReset = false;
 302          cc.zoom = true;
 303          cc.zoomProxy = true;
 304                
 305          controllerPlot.target.bind('jqplotZoom', plotZoom);
 306          controllerPlot.target.bind('jqplotResetZoom', plotReset);
 307  
 308          function plotZoom(ev, gridpos, datapos, plot, cursor) {
 309              tc.doZoom(gridpos, datapos, targetPlot, cursor);
 310          } 
 311  
 312          function plotReset(ev, plot, cursor) {
 313              targetPlot.resetZoom();
 314          }
 315      };
 316      
 317      $.jqplot.Cursor.prototype.resetZoom = function(plot, cursor) {
 318          var axes = plot.axes;
 319          var cax = cursor._zoom.axes;
 320          if (!plot.plugins.cursor.zoomProxy && cursor._zoom.isZoomed) {
 321              for (var ax in axes) {
 322                  // axes[ax]._ticks = [];
 323                  // axes[ax].min = cax[ax].min;
 324                  // axes[ax].max = cax[ax].max;
 325                  // axes[ax].numberTicks = cax[ax].numberTicks; 
 326                  // axes[ax].tickInterval = cax[ax].tickInterval;
 327                  // // for date axes
 328                  // axes[ax].daTickInterval = cax[ax].daTickInterval;
 329                  axes[ax].reset();
 330                  axes[ax]._ticks = [];
 331                  // fake out tick creation algorithm to make sure original auto
 332                  // computed format string is used if _overrideFormatString is true
 333                  axes[ax]._autoFormatString = cax[ax].tickFormatString;
 334              }
 335              plot.redraw();
 336              cursor._zoom.isZoomed = false;
 337          }
 338          else {
 339              var ctx = cursor.zoomCanvas._ctx;
 340              ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
 341              ctx = null;
 342          }
 343          plot.target.trigger('jqplotResetZoom', [plot, cursor]);
 344      };
 345      
 346      $.jqplot.Cursor.resetZoom = function(plot) {
 347          plot.resetZoom();
 348      };
 349      
 350      $.jqplot.Cursor.prototype.doZoom = function (gridpos, datapos, plot, cursor) {
 351          var c = cursor;
 352          var axes = plot.axes;
 353          var zaxes = c._zoom.axes;
 354          var start = zaxes.start;
 355          var end = zaxes.end;
 356          var min, max, dp, span,
 357              newmin, newmax, curax, _numberTicks, ret;
 358          var ctx = plot.plugins.cursor.zoomCanvas._ctx;
 359          // don't zoom if zoom area is too small (in pixels)
 360          if ((c.constrainZoomTo == 'none' && Math.abs(gridpos.x - c._zoom.start[0]) > 6 && Math.abs(gridpos.y - c._zoom.start[1]) > 6) || (c.constrainZoomTo == 'x' && Math.abs(gridpos.x - c._zoom.start[0]) > 6) ||  (c.constrainZoomTo == 'y' && Math.abs(gridpos.y - c._zoom.start[1]) > 6)) {
 361              if (!plot.plugins.cursor.zoomProxy) {
 362                  for (var ax in datapos) {
 363                      // make a copy of the original axes to revert back.
 364                      if (c._zoom.axes[ax] == undefined) {
 365                          c._zoom.axes[ax] = {};
 366                          c._zoom.axes[ax].numberTicks = axes[ax].numberTicks;
 367                          c._zoom.axes[ax].tickInterval = axes[ax].tickInterval;
 368                          // for date axes...
 369                          c._zoom.axes[ax].daTickInterval = axes[ax].daTickInterval;
 370                          c._zoom.axes[ax].min = axes[ax].min;
 371                          c._zoom.axes[ax].max = axes[ax].max;
 372                          c._zoom.axes[ax].tickFormatString = (axes[ax].tickOptions != null) ? axes[ax].tickOptions.formatString :  '';
 373                      }
 374  
 375  
 376                      if ((c.constrainZoomTo == 'none') || (c.constrainZoomTo == 'x' && ax.charAt(0) == 'x') || (c.constrainZoomTo == 'y' && ax.charAt(0) == 'y')) {   
 377                          dp = datapos[ax];
 378                          if (dp != null) {           
 379                              if (dp > start[ax]) { 
 380                                  newmin = start[ax];
 381                                  newmax = dp;
 382                              }
 383                              else {
 384                                  span = start[ax] - dp;
 385                                  newmin = dp;
 386                                  newmax = start[ax];
 387                              }
 388  
 389                              curax = axes[ax];
 390  
 391                              _numberTicks = null;
 392  
 393                              // if aligning this axis, use number of ticks from previous axis.
 394                              // Do I need to reset somehow if alignTicks is changed and then graph is replotted??
 395                              if (curax.alignTicks) {
 396                                  if (curax.name === 'x2axis' && plot.axes.xaxis.show) {
 397                                      _numberTicks = plot.axes.xaxis.numberTicks;
 398                                  }
 399                                  else if (curax.name.charAt(0) === 'y' && curax.name !== 'yaxis' && curax.name !== 'yMidAxis' && plot.axes.yaxis.show) {
 400                                      _numberTicks = plot.axes.yaxis.numberTicks;
 401                                  }
 402                              }
 403                              
 404                              if (this.looseZoom && (axes[ax].renderer.constructor === $.jqplot.LinearAxisRenderer || axes[ax].renderer.constructor === $.jqplot.LogAxisRenderer )) { //} || axes[ax].renderer.constructor === $.jqplot.DateAxisRenderer)) {
 405  
 406                                  ret = $.jqplot.LinearTickGenerator(newmin, newmax, curax._scalefact, _numberTicks);
 407  
 408                                  // if new minimum is less than "true" minimum of axis display, adjust it
 409                                  if (axes[ax].tickInset && ret[0] < axes[ax].min + axes[ax].tickInset * axes[ax].tickInterval) {
 410                                      ret[0] += ret[4];
 411                                      ret[2] -= 1;
 412                                  }
 413  
 414                                  // if new maximum is greater than "true" max of axis display, adjust it
 415                                  if (axes[ax].tickInset && ret[1] > axes[ax].max - axes[ax].tickInset * axes[ax].tickInterval) {
 416                                      ret[1] -= ret[4];
 417                                      ret[2] -= 1;
 418                                  }
 419  
 420                                  // for log axes, don't fall below current minimum, this will look bad and can't have 0 in range anyway.
 421                                  if (axes[ax].renderer.constructor === $.jqplot.LogAxisRenderer && ret[0] < axes[ax].min) {
 422                                      // remove a tick and shift min up
 423                                      ret[0] += ret[4];
 424                                      ret[2] -= 1;
 425                                  }
 426  
 427                                  axes[ax].min = ret[0];
 428                                  axes[ax].max = ret[1];
 429                                  axes[ax]._autoFormatString = ret[3];
 430                                  axes[ax].numberTicks = ret[2];
 431                                  axes[ax].tickInterval = ret[4];
 432                                  // for date axes...
 433                                  axes[ax].daTickInterval = [ret[4]/1000, 'seconds'];
 434                              }
 435                              else {
 436                                  axes[ax].min = newmin;
 437                                  axes[ax].max = newmax;
 438                                  axes[ax].tickInterval = null;
 439                                  axes[ax].numberTicks = null;
 440                                  // for date axes...
 441                                  axes[ax].daTickInterval = null;
 442                              }
 443  
 444                              axes[ax]._ticks = [];
 445                          }
 446                      }
 447                              
 448                      // if ((c.constrainZoomTo == 'x' && ax.charAt(0) == 'y' && c.autoscaleConstraint) || (c.constrainZoomTo == 'y' && ax.charAt(0) == 'x' && c.autoscaleConstraint)) {
 449                      //     dp = datapos[ax];
 450                      //     if (dp != null) {
 451                      //         axes[ax].max == null;
 452                      //         axes[ax].min = null;
 453                      //     }
 454                      // }
 455                  }
 456                  ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
 457                  plot.redraw();
 458                  c._zoom.isZoomed = true;
 459                  ctx = null;
 460              }
 461              plot.target.trigger('jqplotZoom', [gridpos, datapos, plot, cursor]);
 462          }
 463      };
 464      
 465      $.jqplot.preInitHooks.push($.jqplot.Cursor.init);
 466      $.jqplot.postDrawHooks.push($.jqplot.Cursor.postDraw);
 467      
 468      function updateTooltip(gridpos, datapos, plot) {
 469          var c = plot.plugins.cursor;
 470          var s = '';
 471          var addbr = false;
 472          if (c.showTooltipGridPosition) {
 473              s = gridpos.x+', '+gridpos.y;
 474              addbr = true;
 475          }
 476          if (c.showTooltipUnitPosition) {
 477              var g;
 478              for (var i=0; i<c.tooltipAxisGroups.length; i++) {
 479                  g = c.tooltipAxisGroups[i];
 480                  if (addbr) {
 481                      s += '<br />';
 482                  }
 483                  if (c.useAxesFormatters) {
 484                      for (var j=0; j<g.length; j++) {
 485                          if (j) {
 486                              s += ', ';
 487                          }
 488                          var af = plot.axes[g[j]]._ticks[0].formatter;
 489                          var afstr = plot.axes[g[j]]._ticks[0].formatString;
 490                          s += af(afstr, datapos[g[j]]);
 491                      }
 492                  }
 493                  else {
 494                      s += $.jqplot.sprintf(c.tooltipFormatString, datapos[g[0]], datapos[g[1]]);
 495                  }
 496                  addbr = true;
 497              }
 498          }
 499          
 500          if (c.showTooltipDataPosition) {
 501              var series = plot.series; 
 502              var ret = getIntersectingPoints(plot, gridpos.x, gridpos.y);
 503              var addbr = false;
 504          
 505              for (var i = 0; i< series.length; i++) {
 506                  if (series[i].show) {
 507                      var idx = series[i].index;
 508                      var label = series[i].label.toString();
 509                      var cellid = $.inArray(idx, ret.indices);
 510                      var sx = undefined;
 511                      var sy = undefined;
 512                      if (cellid != -1) {
 513                          var data = ret.data[cellid].data;
 514                          if (c.useAxesFormatters) {
 515                              var xf = series[i]._xaxis._ticks[0].formatter;
 516                              var yf = series[i]._yaxis._ticks[0].formatter;
 517                              var xfstr = series[i]._xaxis._ticks[0].formatString;
 518                              var yfstr = series[i]._yaxis._ticks[0].formatString;
 519                              sx = xf(xfstr, data[0]);
 520                              sy = yf(yfstr, data[1]);
 521                          }
 522                          else {
 523                              sx = data[0];
 524                              sy = data[1];
 525                          }
 526                          if (addbr) {
 527                              s += '<br />';
 528                          }
 529                          s += $.jqplot.sprintf(c.tooltipFormatString, label, sx, sy);
 530                          addbr = true;
 531                      }
 532                  }
 533              }
 534              
 535          }
 536          c._tooltipElem.html(s);
 537      }
 538      
 539      function moveLine(gridpos, plot) {
 540          var c = plot.plugins.cursor;
 541          var ctx = c.cursorCanvas._ctx;
 542          ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
 543          if (c.showVerticalLine) {
 544              c.shapeRenderer.draw(ctx, [[gridpos.x, 0], [gridpos.x, ctx.canvas.height]]);
 545          }
 546          if (c.showHorizontalLine) {
 547              c.shapeRenderer.draw(ctx, [[0, gridpos.y], [ctx.canvas.width, gridpos.y]]);
 548          }
 549          var ret = getIntersectingPoints(plot, gridpos.x, gridpos.y);
 550          if (c.showCursorLegend) {
 551              var cells = $(plot.targetId + ' td.jqplot-cursor-legend-label');
 552              for (var i=0; i<cells.length; i++) {
 553                  var idx = $(cells[i]).data('seriesIndex');
 554                  var series = plot.series[idx];
 555                  var label = series.label.toString();
 556                  var cellid = $.inArray(idx, ret.indices);
 557                  var sx = undefined;
 558                  var sy = undefined;
 559                  if (cellid != -1) {
 560                      var data = ret.data[cellid].data;
 561                      if (c.useAxesFormatters) {
 562                          var xf = series._xaxis._ticks[0].formatter;
 563                          var yf = series._yaxis._ticks[0].formatter;
 564                          var xfstr = series._xaxis._ticks[0].formatString;
 565                          var yfstr = series._yaxis._ticks[0].formatString;
 566                          sx = xf(xfstr, data[0]);
 567                          sy = yf(yfstr, data[1]);
 568                      }
 569                      else {
 570                          sx = data[0];
 571                          sy = data[1];
 572                      }
 573                  }
 574                  if (plot.legend.escapeHtml) {
 575                      $(cells[i]).text($.jqplot.sprintf(c.cursorLegendFormatString, label, sx, sy));
 576                  }
 577                  else {
 578                      $(cells[i]).html($.jqplot.sprintf(c.cursorLegendFormatString, label, sx, sy));
 579                  }
 580              }        
 581          }
 582          ctx = null;
 583      }
 584          
 585      function getIntersectingPoints(plot, x, y) {
 586          var ret = {indices:[], data:[]};
 587          var s, i, d0, d, j, r, p;
 588          var threshold;
 589          var c = plot.plugins.cursor;
 590          for (var i=0; i<plot.series.length; i++) {
 591              s = plot.series[i];
 592              r = s.renderer;
 593              if (s.show) {
 594                  threshold = c.intersectionThreshold;
 595                  if (s.showMarker) {
 596                      threshold += s.markerRenderer.size/2;
 597                  }
 598                  for (var j=0; j<s.gridData.length; j++) {
 599                      p = s.gridData[j];
 600                      // check vertical line
 601                      if (c.showVerticalLine) {
 602                          if (Math.abs(x-p[0]) <= threshold) {
 603                              ret.indices.push(i);
 604                              ret.data.push({seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]});
 605                          }
 606                      }
 607                  } 
 608              }
 609          }
 610          return ret;
 611      }
 612      
 613      function moveTooltip(gridpos, plot) {
 614          var c = plot.plugins.cursor;  
 615          var elem = c._tooltipElem;
 616          switch (c.tooltipLocation) {
 617              case 'nw':
 618                  var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;
 619                  var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);
 620                  break;
 621              case 'n':
 622                  var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2;
 623                  var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);
 624                  break;
 625              case 'ne':
 626                  var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
 627                  var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);
 628                  break;
 629              case 'e':
 630                  var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
 631                  var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2;
 632                  break;
 633              case 'se':
 634                  var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
 635                  var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
 636                  break;
 637              case 's':
 638                  var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2;
 639                  var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
 640                  break;
 641              case 'sw':
 642                  var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;
 643                  var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
 644                  break;
 645              case 'w':
 646                  var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;
 647                  var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2;
 648                  break;
 649              default:
 650                  var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
 651                  var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
 652                  break;
 653          }
 654              
 655          elem.css('left', x);
 656          elem.css('top', y);
 657          elem = null;
 658      }
 659      
 660      function positionTooltip(plot) { 
 661          // fake a grid for positioning
 662          var grid = plot._gridPadding; 
 663          var c = plot.plugins.cursor;
 664          var elem = c._tooltipElem;  
 665          switch (c.tooltipLocation) {
 666              case 'nw':
 667                  var a = grid.left + c.tooltipOffset;
 668                  var b = grid.top + c.tooltipOffset;
 669                  elem.css('left', a);
 670                  elem.css('top', b);
 671                  break;
 672              case 'n':
 673                  var a = (grid.left + (plot._plotDimensions.width - grid.right))/2 - elem.outerWidth(true)/2;
 674                  var b = grid.top + c.tooltipOffset;
 675                  elem.css('left', a);
 676                  elem.css('top', b);
 677                  break;
 678              case 'ne':
 679                  var a = grid.right + c.tooltipOffset;
 680                  var b = grid.top + c.tooltipOffset;
 681                  elem.css({right:a, top:b});
 682                  break;
 683              case 'e':
 684                  var a = grid.right + c.tooltipOffset;
 685                  var b = (grid.top + (plot._plotDimensions.height - grid.bottom))/2 - elem.outerHeight(true)/2;
 686                  elem.css({right:a, top:b});
 687                  break;
 688              case 'se':
 689                  var a = grid.right + c.tooltipOffset;
 690                  var b = grid.bottom + c.tooltipOffset;
 691                  elem.css({right:a, bottom:b});
 692                  break;
 693              case 's':
 694                  var a = (grid.left + (plot._plotDimensions.width - grid.right))/2 - elem.outerWidth(true)/2;
 695                  var b = grid.bottom + c.tooltipOffset;
 696                  elem.css({left:a, bottom:b});
 697                  break;
 698              case 'sw':
 699                  var a = grid.left + c.tooltipOffset;
 700                  var b = grid.bottom + c.tooltipOffset;
 701                  elem.css({left:a, bottom:b});
 702                  break;
 703              case 'w':
 704                  var a = grid.left + c.tooltipOffset;
 705                  var b = (grid.top + (plot._plotDimensions.height - grid.bottom))/2 - elem.outerHeight(true)/2;
 706                  elem.css({left:a, top:b});
 707                  break;
 708              default:  // same as 'se'
 709                  var a = grid.right - c.tooltipOffset;
 710                  var b = grid.bottom + c.tooltipOffset;
 711                  elem.css({right:a, bottom:b});
 712                  break;
 713          }
 714          elem = null;
 715      }
 716      
 717      function handleClick (ev, gridpos, datapos, neighbor, plot) {
 718          ev.preventDefault();
 719          ev.stopImmediatePropagation();
 720          var c = plot.plugins.cursor;
 721          if (c.clickReset) {
 722              c.resetZoom(plot, c);
 723          }
 724          var sel = window.getSelection;
 725          if (document.selection && document.selection.empty)
 726          {
 727              document.selection.empty();
 728          }
 729          else if (sel && !sel().isCollapsed) {
 730              sel().collapse();
 731          }
 732          return false;
 733      }
 734      
 735      function handleDblClick (ev, gridpos, datapos, neighbor, plot) {
 736          ev.preventDefault();
 737          ev.stopImmediatePropagation();
 738          var c = plot.plugins.cursor;
 739          if (c.dblClickReset) {
 740              c.resetZoom(plot, c);
 741          }
 742          var sel = window.getSelection;
 743          if (document.selection && document.selection.empty)
 744          {
 745              document.selection.empty();
 746          }
 747          else if (sel && !sel().isCollapsed) {
 748              sel().collapse();
 749          }
 750          return false;
 751      }
 752      
 753      function handleMouseLeave(ev, gridpos, datapos, neighbor, plot) {
 754          var c = plot.plugins.cursor;
 755          c.onGrid = false;
 756          if (c.show) {
 757              $(ev.target).css('cursor', c.previousCursor);
 758              if (c.showTooltip && !(c._zoom.zooming && c.showTooltipOutsideZoom && !c.constrainOutsideZoom)) {
 759                  c._tooltipElem.empty();
 760                  c._tooltipElem.hide();
 761              }
 762              if (c.zoom) {
 763                  c._zoom.gridpos = gridpos;
 764                  c._zoom.datapos = datapos;
 765              }
 766              if (c.showVerticalLine || c.showHorizontalLine) {
 767                  var ctx = c.cursorCanvas._ctx;
 768                  ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
 769                  ctx = null;
 770              }
 771              if (c.showCursorLegend) {
 772                  var cells = $(plot.targetId + ' td.jqplot-cursor-legend-label');
 773                  for (var i=0; i<cells.length; i++) {
 774                      var idx = $(cells[i]).data('seriesIndex');
 775                      var series = plot.series[idx];
 776                      var label = series.label.toString();
 777                      if (plot.legend.escapeHtml) {
 778                          $(cells[i]).text($.jqplot.sprintf(c.cursorLegendFormatString, label, undefined, undefined));
 779                      }
 780                      else {
 781                          $(cells[i]).html($.jqplot.sprintf(c.cursorLegendFormatString, label, undefined, undefined));
 782                      }
 783                  
 784                  }        
 785              }
 786          }
 787      }
 788      
 789      function handleMouseEnter(ev, gridpos, datapos, neighbor, plot) {
 790          var c = plot.plugins.cursor;
 791          c.onGrid = true;
 792          if (c.show) {
 793              c.previousCursor = ev.target.style.cursor;
 794              ev.target.style.cursor = c.style;
 795              if (c.showTooltip) {
 796                  updateTooltip(gridpos, datapos, plot);
 797                  if (c.followMouse) {
 798                      moveTooltip(gridpos, plot);
 799                  }
 800                  else {
 801                      positionTooltip(plot);
 802                  }
 803                  c._tooltipElem.show();
 804              }
 805              if (c.showVerticalLine || c.showHorizontalLine) {
 806                  moveLine(gridpos, plot);
 807              }
 808          }
 809  
 810      }    
 811      
 812      function handleMouseMove(ev, gridpos, datapos, neighbor, plot) {
 813          var c = plot.plugins.cursor;
 814          if (c.show) {
 815              if (c.showTooltip) {
 816                  updateTooltip(gridpos, datapos, plot);
 817                  if (c.followMouse) {
 818                      moveTooltip(gridpos, plot);
 819                  }
 820              }
 821              if (c.showVerticalLine || c.showHorizontalLine) {
 822                  moveLine(gridpos, plot);
 823              }
 824          }
 825      }
 826              
 827      function getEventPosition(ev) {
 828          var plot = ev.data.plot;
 829          var go = plot.eventCanvas._elem.offset();
 830          var gridPos = {x:ev.pageX - go.left, y:ev.pageY - go.top};
 831          //////
 832          // TO DO: handle yMidAxis
 833          //////
 834          var dataPos = {xaxis:null, yaxis:null, x2axis:null, y2axis:null, y3axis:null, y4axis:null, y5axis:null, y6axis:null, y7axis:null, y8axis:null, y9axis:null, yMidAxis:null};
 835          var an = ['xaxis', 'yaxis', 'x2axis', 'y2axis', 'y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis', 'yMidAxis'];
 836          var ax = plot.axes;
 837          var n, axis;
 838          for (n=11; n>0; n--) {
 839              axis = an[n-1];
 840              if (ax[axis].show) {
 841                  dataPos[axis] = ax[axis].series_p2u(gridPos[axis.charAt(0)]);
 842              }
 843          }
 844  
 845          return {offsets:go, gridPos:gridPos, dataPos:dataPos};
 846      }    
 847      
 848      function handleZoomMove(ev) {
 849          var plot = ev.data.plot;
 850          var c = plot.plugins.cursor;
 851          // don't do anything if not on grid.
 852          if (c.show && c.zoom && c._zoom.started && !c.zoomTarget) {
 853              ev.preventDefault();
 854              var ctx = c.zoomCanvas._ctx;
 855              var positions = getEventPosition(ev);
 856              var gridpos = positions.gridPos;
 857              var datapos = positions.dataPos;
 858              c._zoom.gridpos = gridpos;
 859              c._zoom.datapos = datapos;
 860              c._zoom.zooming = true;
 861              var xpos = gridpos.x;
 862              var ypos = gridpos.y;
 863              var height = ctx.canvas.height;
 864              var width = ctx.canvas.width;
 865              if (c.showTooltip && !c.onGrid && c.showTooltipOutsideZoom) {
 866                  updateTooltip(gridpos, datapos, plot);
 867                  if (c.followMouse) {
 868                      moveTooltip(gridpos, plot);
 869                  }
 870              }
 871              if (c.constrainZoomTo == 'x') {
 872                  c._zoom.end = [xpos, height];
 873              }
 874              else if (c.constrainZoomTo == 'y') {
 875                  c._zoom.end = [width, ypos];
 876              }
 877              else {
 878                  c._zoom.end = [xpos, ypos];
 879              }
 880              var sel = window.getSelection;
 881              if (document.selection && document.selection.empty)
 882              {
 883                  document.selection.empty();
 884              }
 885              else if (sel && !sel().isCollapsed) {
 886                  sel().collapse();
 887              }
 888              drawZoomBox.call(c);
 889              ctx = null;
 890          }
 891      }
 892      
 893      function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
 894          var c = plot.plugins.cursor;
 895          if(plot.plugins.mobile){
 896              $(document).one('vmouseup.jqplot_cursor', {plot:plot}, handleMouseUp);
 897          } else {
 898              $(document).one('mouseup.jqplot_cursor', {plot:plot}, handleMouseUp);
 899          }
 900          var axes = plot.axes;
 901          if (document.onselectstart != undefined) {
 902              c._oldHandlers.onselectstart = document.onselectstart;
 903              document.onselectstart = function () { return false; };
 904          }
 905          if (document.ondrag != undefined) {
 906              c._oldHandlers.ondrag = document.ondrag;
 907              document.ondrag = function () { return false; };
 908          }
 909          if (document.onmousedown != undefined) {
 910              c._oldHandlers.onmousedown = document.onmousedown;
 911              document.onmousedown = function () { return false; };
 912          }
 913          if (c.zoom) {
 914              if (!c.zoomProxy) {
 915                  var ctx = c.zoomCanvas._ctx;
 916                  ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
 917                  ctx = null;
 918              }
 919              if (c.constrainZoomTo == 'x') {
 920                  c._zoom.start = [gridpos.x, 0];
 921              }
 922              else if (c.constrainZoomTo == 'y') {
 923                  c._zoom.start = [0, gridpos.y];
 924              }
 925              else {
 926                  c._zoom.start = [gridpos.x, gridpos.y];
 927              }
 928              c._zoom.started = true;
 929              for (var ax in datapos) {
 930                  // get zoom starting position.
 931                  c._zoom.axes.start[ax] = datapos[ax];
 932              }  
 933             if(plot.plugins.mobile){
 934                  $(document).bind('vmousemove.jqplotCursor', {plot:plot}, handleZoomMove);              
 935              } else {
 936                  $(document).bind('mousemove.jqplotCursor', {plot:plot}, handleZoomMove);              
 937              }
 938  
 939          }
 940      }
 941      
 942      function handleMouseUp(ev) {
 943          var plot = ev.data.plot;
 944          var c = plot.plugins.cursor;
 945          if (c.zoom && c._zoom.zooming && !c.zoomTarget) {
 946              var xpos = c._zoom.gridpos.x;
 947              var ypos = c._zoom.gridpos.y;
 948              var datapos = c._zoom.datapos;
 949              var height = c.zoomCanvas._ctx.canvas.height;
 950              var width = c.zoomCanvas._ctx.canvas.width;
 951              var axes = plot.axes;
 952              
 953              if (c.constrainOutsideZoom && !c.onGrid) {
 954                  if (xpos < 0) { xpos = 0; }
 955                  else if (xpos > width) { xpos = width; }
 956                  if (ypos < 0) { ypos = 0; }
 957                  else if (ypos > height) { ypos = height; }
 958                  
 959                  for (var axis in datapos) {
 960                      if (datapos[axis]) {
 961                          if (axis.charAt(0) == 'x') {
 962                              datapos[axis] = axes[axis].series_p2u(xpos);
 963                          }
 964                          else {
 965                              datapos[axis] = axes[axis].series_p2u(ypos);
 966                          }
 967                      }
 968                  }
 969              }
 970              
 971              if (c.constrainZoomTo == 'x') {
 972                  ypos = height;
 973              }
 974              else if (c.constrainZoomTo == 'y') {
 975                  xpos = width;
 976              }
 977              c._zoom.end = [xpos, ypos];
 978              c._zoom.gridpos = {x:xpos, y:ypos};
 979              
 980              c.doZoom(c._zoom.gridpos, datapos, plot, c);
 981          }
 982          c._zoom.started = false;
 983          c._zoom.zooming = false;
 984          
 985          $(document).unbind('mousemove.jqplotCursor', handleZoomMove);
 986          
 987          if (document.onselectstart != undefined && c._oldHandlers.onselectstart != null){
 988              document.onselectstart = c._oldHandlers.onselectstart;
 989              c._oldHandlers.onselectstart = null;
 990          }
 991          if (document.ondrag != undefined && c._oldHandlers.ondrag != null){
 992              document.ondrag = c._oldHandlers.ondrag;
 993              c._oldHandlers.ondrag = null;
 994          }
 995          if (document.onmousedown != undefined && c._oldHandlers.onmousedown != null){
 996              document.onmousedown = c._oldHandlers.onmousedown;
 997              c._oldHandlers.onmousedown = null;
 998          }
 999  
1000      }
1001      
1002      function drawZoomBox() {
1003          var start = this._zoom.start;
1004          var end = this._zoom.end;
1005          var ctx = this.zoomCanvas._ctx;
1006          var l, t, h, w;
1007          if (end[0] > start[0]) {
1008              l = start[0];
1009              w = end[0] - start[0];
1010          }
1011          else {
1012              l = end[0];
1013              w = start[0] - end[0];
1014          }
1015          if (end[1] > start[1]) {
1016              t = start[1];
1017              h = end[1] - start[1];
1018          }
1019          else {
1020              t = end[1];
1021              h = start[1] - end[1];
1022          }
1023          ctx.fillStyle = 'rgba(0,0,0,0.2)';
1024          ctx.strokeStyle = '#999999';
1025          ctx.lineWidth = 1.0;
1026          ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
1027          ctx.fillRect(0,0,ctx.canvas.width, ctx.canvas.height);
1028          ctx.clearRect(l, t, w, h);
1029          // IE won't show transparent fill rect, so stroke a rect also.
1030          ctx.strokeRect(l,t,w,h);
1031          ctx = null;
1032      }
1033      
1034      $.jqplot.CursorLegendRenderer = function(options) {
1035          $.jqplot.TableLegendRenderer.call(this, options);
1036          this.formatString = '%s';
1037      };
1038      
1039      $.jqplot.CursorLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();
1040      $.jqplot.CursorLegendRenderer.prototype.constructor = $.jqplot.CursorLegendRenderer;
1041      
1042      // called in context of a Legend
1043      $.jqplot.CursorLegendRenderer.prototype.draw = function() {
1044          if (this._elem) {
1045              this._elem.emptyForce();
1046              this._elem = null;
1047          }
1048          if (this.show) {
1049              var series = this._series, s;
1050              // make a table.  one line label per row.
1051              var elem = document.createElement('div');
1052              this._elem = $(elem);
1053              elem = null;
1054              this._elem.addClass('jqplot-legend jqplot-cursor-legend');
1055              this._elem.css('position', 'absolute');
1056          
1057              var pad = false;
1058              for (var i = 0; i< series.length; i++) {
1059                  s = series[i];
1060                  if (s.show && s.showLabel) {
1061                      var lt = $.jqplot.sprintf(this.formatString, s.label.toString());
1062                      if (lt) {
1063                          var color = s.color;
1064                          if (s._stack && !s.fill) {
1065                              color = '';
1066                          }
1067                          addrow.call(this, lt, color, pad, i);
1068                          pad = true;
1069                      }
1070                      // let plugins add more rows to legend.  Used by trend line plugin.
1071                      for (var j=0; j<$.jqplot.addLegendRowHooks.length; j++) {
1072                          var item = $.jqplot.addLegendRowHooks[j].call(this, s);
1073                          if (item) {
1074                              addrow.call(this, item.label, item.color, pad);
1075                              pad = true;
1076                          } 
1077                      }
1078                  }
1079              }
1080              series = s = null;
1081              delete series;
1082              delete s;
1083          }
1084          
1085          function addrow(label, color, pad, idx) {
1086              var rs = (pad) ? this.rowSpacing : '0';
1087              var tr = $('<tr class="jqplot-legend jqplot-cursor-legend"></tr>').appendTo(this._elem);
1088              tr.data('seriesIndex', idx);
1089              $('<td class="jqplot-legend jqplot-cursor-legend-swatch" style="padding-top:'+rs+';">'+
1090                  '<div style="border:1px solid #cccccc;padding:0.2em;">'+
1091                  '<div class="jqplot-cursor-legend-swatch" style="background-color:'+color+';"></div>'+
1092                  '</div></td>').appendTo(tr);
1093              var td = $('<td class="jqplot-legend jqplot-cursor-legend-label" style="vertical-align:middle;padding-top:'+rs+';"></td>');
1094              td.appendTo(tr);
1095              td.data('seriesIndex', idx);
1096              if (this.escapeHtml) {
1097                  td.text(label);
1098              }
1099              else {
1100                  td.html(label);
1101              }
1102              tr = null;
1103              td = null;
1104          }
1105          return this._elem;
1106      };
1107      
1108  })(jQuery);


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1