Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

709 righe
30 KiB

  1. /**
  2. * jqPlot
  3. * Pure JavaScript plotting plugin using jQuery
  4. *
  5. * Version: 1.0.0b2_r792
  6. *
  7. * Copyright (c) 2009-2011 Chris Leonello
  8. * jqPlot is currently available for use in all personal or commercial projects
  9. * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL
  10. * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can
  11. * choose the license that best suits your project and use it accordingly.
  12. *
  13. * Although not required, the author would appreciate an email letting him
  14. * know of any substantial use of jqPlot. You can reach the author at:
  15. * chris at jqplot dot com or see http://www.jqplot.com/info.php .
  16. *
  17. * If you are feeling kind and generous, consider supporting the project by
  18. * making a donation at: http://www.jqplot.com/donate.php .
  19. *
  20. * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
  21. *
  22. * version 2007.04.27
  23. * author Ash Searle
  24. * http://hexmen.com/blog/2007/03/printf-sprintf/
  25. * http://hexmen.com/js/sprintf.js
  26. * The author (Ash Searle) has placed this code in the public domain:
  27. * "This code is unrestricted: you are free to use it however you like."
  28. *
  29. */
  30. (function($) {
  31. // Class: $.jqplot.BarRenderer
  32. // A plugin renderer for jqPlot to draw a bar plot.
  33. // Draws series as a line.
  34. $.jqplot.BarRenderer = function(){
  35. $.jqplot.LineRenderer.call(this);
  36. };
  37. $.jqplot.BarRenderer.prototype = new $.jqplot.LineRenderer();
  38. $.jqplot.BarRenderer.prototype.constructor = $.jqplot.BarRenderer;
  39. // called with scope of series.
  40. $.jqplot.BarRenderer.prototype.init = function(options, plot) {
  41. // Group: Properties
  42. //
  43. // prop: barPadding
  44. // Number of pixels between adjacent bars at the same axis value.
  45. this.barPadding = 8;
  46. // prop: barMargin
  47. // Number of pixels between groups of bars at adjacent axis values.
  48. this.barMargin = 10;
  49. // prop: barDirection
  50. // 'vertical' = up and down bars, 'horizontal' = side to side bars
  51. this.barDirection = 'vertical';
  52. // prop: barWidth
  53. // Width of the bar in pixels (auto by devaul). null = calculated automatically.
  54. this.barWidth = null;
  55. // prop: shadowOffset
  56. // offset of the shadow from the slice and offset of
  57. // each succesive stroke of the shadow from the last.
  58. this.shadowOffset = 2;
  59. // prop: shadowDepth
  60. // number of strokes to apply to the shadow,
  61. // each stroke offset shadowOffset from the last.
  62. this.shadowDepth = 5;
  63. // prop: shadowAlpha
  64. // transparency of the shadow (0 = transparent, 1 = opaque)
  65. this.shadowAlpha = 0.08;
  66. // prop: waterfall
  67. // true to enable waterfall plot.
  68. this.waterfall = false;
  69. // prop: groups
  70. // group bars into this many groups
  71. this.groups = 1;
  72. // prop: varyBarColor
  73. // true to color each bar of a series separately rather than
  74. // have every bar of a given series the same color.
  75. // If used for non-stacked multiple series bar plots, user should
  76. // specify a separate 'seriesColors' array for each series.
  77. // Otherwise, each series will set their bars to the same color array.
  78. // This option has no Effect for stacked bar charts and is disabled.
  79. this.varyBarColor = false;
  80. // prop: highlightMouseOver
  81. // True to highlight slice when moused over.
  82. // This must be false to enable highlightMouseDown to highlight when clicking on a slice.
  83. this.highlightMouseOver = true;
  84. // prop: highlightMouseDown
  85. // True to highlight when a mouse button is pressed over a slice.
  86. // This will be disabled if highlightMouseOver is true.
  87. this.highlightMouseDown = false;
  88. // prop: highlightColors
  89. // an array of colors to use when highlighting a bar.
  90. this.highlightColors = [];
  91. this._type = 'bar';
  92. // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver
  93. if (options.highlightMouseDown && options.highlightMouseOver == null) {
  94. options.highlightMouseOver = false;
  95. }
  96. $.extend(true, this, options);
  97. // fill is still needed to properly draw the legend.
  98. // bars have to be filled.
  99. this.fill = true;
  100. if (this.waterfall) {
  101. this.fillToZero = false;
  102. this.disableStack = true;
  103. }
  104. if (this.barDirection == 'vertical' ) {
  105. this._primaryAxis = '_xaxis';
  106. this._stackAxis = 'y';
  107. this.fillAxis = 'y';
  108. }
  109. else {
  110. this._primaryAxis = '_yaxis';
  111. this._stackAxis = 'x';
  112. this.fillAxis = 'x';
  113. }
  114. // index of the currenty highlighted point, if any
  115. this._highlightedPoint = null;
  116. // total number of values for all bar series, total number of bar series, and position of this series
  117. this._plotSeriesInfo = null;
  118. // Array of actual data colors used for each data point.
  119. this._dataColors = [];
  120. this._barPoints = [];
  121. // set the shape renderer options
  122. var opts = {lineJoin:'miter', lineCap:'round', fill:true, isarc:false, strokeStyle:this.color, fillStyle:this.color, closePath:this.fill};
  123. this.renderer.shapeRenderer.init(opts);
  124. // set the shadow renderer options
  125. var sopts = {lineJoin:'miter', lineCap:'round', fill:true, isarc:false, angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, depth:this.shadowDepth, closePath:this.fill};
  126. this.renderer.shadowRenderer.init(sopts);
  127. plot.postInitHooks.addOnce(postInit);
  128. plot.postDrawHooks.addOnce(postPlotDraw);
  129. plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove);
  130. plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown);
  131. plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp);
  132. plot.eventListenerHooks.addOnce('jqplotClick', handleClick);
  133. plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick);
  134. };
  135. // called with scope of series
  136. function barPreInit(target, data, seriesDefaults, options) {
  137. if (this.rendererOptions.barDirection == 'horizontal') {
  138. this._stackAxis = 'x';
  139. this._primaryAxis = '_yaxis';
  140. }
  141. if (this.rendererOptions.waterfall == true) {
  142. this._data = $.extend(true, [], this.data);
  143. var sum = 0;
  144. var pos = (!this.rendererOptions.barDirection || this.rendererOptions.barDirection == 'vertical') ? 1 : 0;
  145. for(var i=0; i<this.data.length; i++) {
  146. sum += this.data[i][pos];
  147. if (i>0) {
  148. this.data[i][pos] += this.data[i-1][pos];
  149. }
  150. }
  151. this.data[this.data.length] = (pos == 1) ? [this.data.length+1, sum] : [sum, this.data.length+1];
  152. this._data[this._data.length] = (pos == 1) ? [this._data.length+1, sum] : [sum, this._data.length+1];
  153. }
  154. if (this.rendererOptions.groups > 1) {
  155. this.breakOnNull = true;
  156. var l = this.data.length;
  157. var skip = parseInt(l/this.rendererOptions.groups, 10);
  158. var count = 0;
  159. for (var i=skip; i<l; i+=skip) {
  160. this.data.splice(i+count, 0, [null, null]);
  161. count++;
  162. }
  163. for (i=0; i<this.data.length; i++) {
  164. if (this._primaryAxis == '_xaxis') {
  165. this.data[i][0] = i+1;
  166. }
  167. else {
  168. this.data[i][1] = i+1;
  169. }
  170. }
  171. }
  172. }
  173. $.jqplot.preSeriesInitHooks.push(barPreInit);
  174. // needs to be called with scope of series, not renderer.
  175. $.jqplot.BarRenderer.prototype.calcSeriesNumbers = function() {
  176. var nvals = 0;
  177. var nseries = 0;
  178. var paxis = this[this._primaryAxis];
  179. var s, series, pos;
  180. // loop through all series on this axis
  181. for (var i=0; i < paxis._series.length; i++) {
  182. series = paxis._series[i];
  183. if (series === this) {
  184. pos = i;
  185. }
  186. // is the series rendered as a bar?
  187. if (series.renderer.constructor == $.jqplot.BarRenderer) {
  188. // gridData may not be computed yet, use data length insted
  189. nvals += series.data.length;
  190. nseries += 1;
  191. }
  192. }
  193. // return total number of values for all bar series, total number of bar series, and position of this series
  194. return [nvals, nseries, pos];
  195. };
  196. $.jqplot.BarRenderer.prototype.setBarWidth = function() {
  197. // need to know how many data values we have on the approprate axis and figure it out.
  198. var i;
  199. var nvals = 0;
  200. var nseries = 0;
  201. var paxis = this[this._primaryAxis];
  202. var s, series, pos;
  203. var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this);
  204. nvals = temp[0];
  205. nseries = temp[1];
  206. var nticks = paxis.numberTicks;
  207. var nbins = (nticks-1)/2;
  208. // so, now we have total number of axis values.
  209. if (paxis.name == 'xaxis' || paxis.name == 'x2axis') {
  210. if (this._stack) {
  211. this.barWidth = (paxis._offsets.max - paxis._offsets.min) / nvals * nseries - this.barMargin;
  212. }
  213. else {
  214. this.barWidth = ((paxis._offsets.max - paxis._offsets.min)/nbins - this.barPadding * (nseries-1) - this.barMargin*2)/nseries;
  215. // this.barWidth = (paxis._offsets.max - paxis._offsets.min) / nvals - this.barPadding - this.barMargin/nseries;
  216. }
  217. }
  218. else {
  219. if (this._stack) {
  220. this.barWidth = (paxis._offsets.min - paxis._offsets.max) / nvals * nseries - this.barMargin;
  221. }
  222. else {
  223. this.barWidth = ((paxis._offsets.min - paxis._offsets.max)/nbins - this.barPadding * (nseries-1) - this.barMargin*2)/nseries;
  224. // this.barWidth = (paxis._offsets.min - paxis._offsets.max) / nvals - this.barPadding - this.barMargin/nseries;
  225. }
  226. }
  227. return [nvals, nseries];
  228. };
  229. function computeHighlightColors (colors) {
  230. var ret = [];
  231. for (var i=0; i<colors.length; i++){
  232. var rgba = $.jqplot.getColorComponents(colors[i]);
  233. var newrgb = [rgba[0], rgba[1], rgba[2]];
  234. var sum = newrgb[0] + newrgb[1] + newrgb[2];
  235. for (var j=0; j<3; j++) {
  236. // when darkening, lowest color component can be is 60.
  237. newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]);
  238. newrgb[j] = parseInt(newrgb[j], 10);
  239. }
  240. ret.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')');
  241. }
  242. return ret;
  243. }
  244. $.jqplot.BarRenderer.prototype.draw = function(ctx, gridData, options) {
  245. var i;
  246. // Ughhh, have to make a copy of options b/c it may be modified later.
  247. var opts = $.extend({}, options);
  248. var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;
  249. var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;
  250. var fill = (opts.fill != undefined) ? opts.fill : this.fill;
  251. var xaxis = this.xaxis;
  252. var yaxis = this.yaxis;
  253. var xp = this._xaxis.series_u2p;
  254. var yp = this._yaxis.series_u2p;
  255. var pointx, pointy;
  256. // clear out data colors.
  257. this._dataColors = [];
  258. this._barPoints = [];
  259. if (this.barWidth == null) {
  260. this.renderer.setBarWidth.call(this);
  261. }
  262. var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this);
  263. var nvals = temp[0];
  264. var nseries = temp[1];
  265. var pos = temp[2];
  266. var points = [];
  267. if (this._stack) {
  268. this._barNudge = 0;
  269. }
  270. else {
  271. this._barNudge = (-Math.abs(nseries/2 - 0.5) + pos) * (this.barWidth + this.barPadding);
  272. }
  273. if (showLine) {
  274. var negativeColors = new $.jqplot.ColorGenerator(this.negativeSeriesColors);
  275. var positiveColors = new $.jqplot.ColorGenerator(this.seriesColors);
  276. var negativeColor = negativeColors.get(this.index);
  277. if (! this.useNegativeColors) {
  278. negativeColor = opts.fillStyle;
  279. }
  280. var positiveColor = opts.fillStyle;
  281. var base;
  282. var xstart;
  283. var ystart;
  284. if (this.barDirection == 'vertical') {
  285. for (var i=0; i<gridData.length; i++) {
  286. if (this.data[i][1] == null) {
  287. continue;
  288. }
  289. points = [];
  290. base = gridData[i][0] + this._barNudge;
  291. ystart;
  292. // stacked
  293. if (this._stack && this._prevGridData.length) {
  294. ystart = this._prevGridData[i][1];
  295. }
  296. // not stacked and first series in stack
  297. else {
  298. if (this.fillToZero) {
  299. ystart = this._yaxis.series_u2p(0);
  300. }
  301. else if (this.waterfall && i > 0 && i < this.gridData.length-1) {
  302. ystart = this.gridData[i-1][1];
  303. }
  304. else if (this.waterfall && i == 0 && i < this.gridData.length-1) {
  305. if (this._yaxis.min <= 0 && this._yaxis.max >= 0) {
  306. ystart = this._yaxis.series_u2p(0);
  307. }
  308. else if (this._yaxis.min > 0) {
  309. ystart = ctx.canvas.height;
  310. }
  311. else {
  312. ystart = 0;
  313. }
  314. }
  315. else if (this.waterfall && i == this.gridData.length - 1) {
  316. if (this._yaxis.min <= 0 && this._yaxis.max >= 0) {
  317. ystart = this._yaxis.series_u2p(0);
  318. }
  319. else if (this._yaxis.min > 0) {
  320. ystart = ctx.canvas.height;
  321. }
  322. else {
  323. ystart = 0;
  324. }
  325. }
  326. else {
  327. ystart = ctx.canvas.height;
  328. }
  329. }
  330. if ((this.fillToZero && this._plotData[i][1] < 0) || (this.waterfall && this._data[i][1] < 0)) {
  331. if (this.varyBarColor && !this._stack) {
  332. if (this.useNegativeColors) {
  333. opts.fillStyle = negativeColors.next();
  334. }
  335. else {
  336. opts.fillStyle = positiveColors.next();
  337. }
  338. }
  339. else {
  340. opts.fillStyle = negativeColor;
  341. }
  342. }
  343. else {
  344. if (this.varyBarColor && !this._stack) {
  345. opts.fillStyle = positiveColors.next();
  346. }
  347. else {
  348. opts.fillStyle = positiveColor;
  349. }
  350. }
  351. if (!this.fillToZero || this._plotData[i][1] >= 0) {
  352. points.push([base-this.barWidth/2, ystart]);
  353. points.push([base-this.barWidth/2, gridData[i][1]]);
  354. points.push([base+this.barWidth/2, gridData[i][1]]);
  355. points.push([base+this.barWidth/2, ystart]);
  356. }
  357. // for negative bars make sure points are always ordered clockwise
  358. else {
  359. points.push([base-this.barWidth/2, gridData[i][1]]);
  360. points.push([base-this.barWidth/2, ystart]);
  361. points.push([base+this.barWidth/2, ystart]);
  362. points.push([base+this.barWidth/2, gridData[i][1]]);
  363. }
  364. this._barPoints.push(points);
  365. // now draw the shadows if not stacked.
  366. // for stacked plots, they are predrawn by drawShadow
  367. if (shadow && !this._stack) {
  368. var sopts = $.extend(true, {}, opts);
  369. // need to get rid of fillStyle on shadow.
  370. delete sopts.fillStyle;
  371. this.renderer.shadowRenderer.draw(ctx, points, sopts);
  372. }
  373. var clr = opts.fillStyle || this.color;
  374. this._dataColors.push(clr);
  375. this.renderer.shapeRenderer.draw(ctx, points, opts);
  376. }
  377. }
  378. else if (this.barDirection == 'horizontal'){
  379. for (var i=0; i<gridData.length; i++) {
  380. if (this.data[i][0] == null) {
  381. continue;
  382. }
  383. points = [];
  384. base = gridData[i][1] - this._barNudge;
  385. xstart;
  386. if (this._stack && this._prevGridData.length) {
  387. xstart = this._prevGridData[i][0];
  388. }
  389. // not stacked and first series in stack
  390. else {
  391. if (this.fillToZero) {
  392. xstart = this._xaxis.series_u2p(0);
  393. }
  394. else if (this.waterfall && i > 0 && i < this.gridData.length-1) {
  395. xstart = this.gridData[i-1][1];
  396. }
  397. else if (this.waterfall && i == 0 && i < this.gridData.length-1) {
  398. if (this._xaxis.min <= 0 && this._xaxis.max >= 0) {
  399. xstart = this._xaxis.series_u2p(0);
  400. }
  401. else if (this._xaxis.min > 0) {
  402. xstart = 0;
  403. }
  404. else {
  405. xstart = ctx.canvas.width;
  406. }
  407. }
  408. else if (this.waterfall && i == this.gridData.length - 1) {
  409. if (this._xaxis.min <= 0 && this._xaxis.max >= 0) {
  410. xstart = this._xaxis.series_u2p(0);
  411. }
  412. else if (this._xaxis.min > 0) {
  413. xstart = 0;
  414. }
  415. else {
  416. xstart = ctx.canvas.width;
  417. }
  418. }
  419. else {
  420. xstart = 0;
  421. }
  422. }
  423. if ((this.fillToZero && this._plotData[i][1] < 0) || (this.waterfall && this._data[i][1] < 0)) {
  424. if (this.varyBarColor && !this._stack) {
  425. if (this.useNegativeColors) {
  426. opts.fillStyle = negativeColors.next();
  427. }
  428. else {
  429. opts.fillStyle = positiveColors.next();
  430. }
  431. }
  432. }
  433. else {
  434. if (this.varyBarColor && !this._stack) {
  435. opts.fillStyle = positiveColors.next();
  436. }
  437. else {
  438. opts.fillStyle = positiveColor;
  439. }
  440. }
  441. points.push([xstart, base+this.barWidth/2]);
  442. points.push([xstart, base-this.barWidth/2]);
  443. points.push([gridData[i][0], base-this.barWidth/2]);
  444. points.push([gridData[i][0], base+this.barWidth/2]);
  445. this._barPoints.push(points);
  446. // now draw the shadows if not stacked.
  447. // for stacked plots, they are predrawn by drawShadow
  448. if (shadow && !this._stack) {
  449. var sopts = $.extend(true, {}, opts);
  450. delete sopts.fillStyle;
  451. this.renderer.shadowRenderer.draw(ctx, points, sopts);
  452. }
  453. var clr = opts.fillStyle || this.color;
  454. this._dataColors.push(clr);
  455. this.renderer.shapeRenderer.draw(ctx, points, opts);
  456. }
  457. }
  458. }
  459. if (this.highlightColors.length == 0) {
  460. this.highlightColors = computeHighlightColors(this._dataColors);
  461. }
  462. else if (typeof(this.highlightColors) == 'string') {
  463. var temp = this.highlightColors;
  464. this.highlightColors = [];
  465. for (var i=0; i<this._dataColors.length; i++) {
  466. this.highlightColors.push(temp);
  467. }
  468. }
  469. };
  470. // for stacked plots, shadows will be pre drawn by drawShadow.
  471. $.jqplot.BarRenderer.prototype.drawShadow = function(ctx, gridData, options) {
  472. var i;
  473. var opts = (options != undefined) ? options : {};
  474. var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;
  475. var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;
  476. var fill = (opts.fill != undefined) ? opts.fill : this.fill;
  477. var xaxis = this.xaxis;
  478. var yaxis = this.yaxis;
  479. var xp = this._xaxis.series_u2p;
  480. var yp = this._yaxis.series_u2p;
  481. var pointx, points, pointy, nvals, nseries, pos;
  482. if (this._stack && this.shadow) {
  483. if (this.barWidth == null) {
  484. this.renderer.setBarWidth.call(this);
  485. }
  486. var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this);
  487. nvals = temp[0];
  488. nseries = temp[1];
  489. pos = temp[2];
  490. if (this._stack) {
  491. this._barNudge = 0;
  492. }
  493. else {
  494. this._barNudge = (-Math.abs(nseries/2 - 0.5) + pos) * (this.barWidth + this.barPadding);
  495. }
  496. if (showLine) {
  497. if (this.barDirection == 'vertical') {
  498. for (var i=0; i<gridData.length; i++) {
  499. if (this.data[i][1] == null) {
  500. continue;
  501. }
  502. points = [];
  503. var base = gridData[i][0] + this._barNudge;
  504. var ystart;
  505. if (this._stack && this._prevGridData.length) {
  506. ystart = this._prevGridData[i][1];
  507. }
  508. else {
  509. if (this.fillToZero) {
  510. ystart = this._yaxis.series_u2p(0);
  511. }
  512. else {
  513. ystart = ctx.canvas.height;
  514. }
  515. }
  516. points.push([base-this.barWidth/2, ystart]);
  517. points.push([base-this.barWidth/2, gridData[i][1]]);
  518. points.push([base+this.barWidth/2, gridData[i][1]]);
  519. points.push([base+this.barWidth/2, ystart]);
  520. this.renderer.shadowRenderer.draw(ctx, points, opts);
  521. }
  522. }
  523. else if (this.barDirection == 'horizontal'){
  524. for (var i=0; i<gridData.length; i++) {
  525. if (this.data[i][0] == null) {
  526. continue;
  527. }
  528. points = [];
  529. var base = gridData[i][1] - this._barNudge;
  530. var xstart;
  531. if (this._stack && this._prevGridData.length) {
  532. xstart = this._prevGridData[i][0];
  533. }
  534. else {
  535. xstart = 0;
  536. }
  537. points.push([xstart, base+this.barWidth/2]);
  538. points.push([gridData[i][0], base+this.barWidth/2]);
  539. points.push([gridData[i][0], base-this.barWidth/2]);
  540. points.push([xstart, base-this.barWidth/2]);
  541. this.renderer.shadowRenderer.draw(ctx, points, opts);
  542. }
  543. }
  544. }
  545. }
  546. };
  547. function postInit(target, data, options) {
  548. for (var i=0; i<this.series.length; i++) {
  549. if (this.series[i].renderer.constructor == $.jqplot.BarRenderer) {
  550. // don't allow mouseover and mousedown at same time.
  551. if (this.series[i].highlightMouseOver) {
  552. this.series[i].highlightMouseDown = false;
  553. }
  554. }
  555. }
  556. this.target.bind('mouseout', {plot:this}, function (ev) { unhighlight(ev.data.plot); });
  557. }
  558. // called within context of plot
  559. // create a canvas which we can draw on.
  560. // insert it before the eventCanvas, so eventCanvas will still capture events.
  561. function postPlotDraw() {
  562. // Memory Leaks patch
  563. if (this.plugins.barRenderer && this.plugins.barRenderer.highlightCanvas) {
  564. this.plugins.barRenderer.highlightCanvas.resetCanvas();
  565. this.plugins.barRenderer.highlightCanvas = null;
  566. }
  567. this.plugins.barRenderer = {highlightedSeriesIndex:null};
  568. this.plugins.barRenderer.highlightCanvas = new $.jqplot.GenericCanvas();
  569. this.eventCanvas._elem.before(this.plugins.barRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-barRenderer-highlight-canvas', this._plotDimensions, this));
  570. this.plugins.barRenderer.highlightCanvas.setContext();
  571. }
  572. function highlight (plot, sidx, pidx, points) {
  573. var s = plot.series[sidx];
  574. var canvas = plot.plugins.barRenderer.highlightCanvas;
  575. canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height);
  576. s._highlightedPoint = pidx;
  577. plot.plugins.barRenderer.highlightedSeriesIndex = sidx;
  578. var opts = {fillStyle: s.highlightColors[pidx]};
  579. s.renderer.shapeRenderer.draw(canvas._ctx, points, opts);
  580. canvas = null;
  581. }
  582. function unhighlight (plot) {
  583. var canvas = plot.plugins.barRenderer.highlightCanvas;
  584. canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);
  585. for (var i=0; i<plot.series.length; i++) {
  586. plot.series[i]._highlightedPoint = null;
  587. }
  588. plot.plugins.barRenderer.highlightedSeriesIndex = null;
  589. plot.target.trigger('jqplotDataUnhighlight');
  590. canvas = null;
  591. }
  592. function handleMove(ev, gridpos, datapos, neighbor, plot) {
  593. if (neighbor) {
  594. var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
  595. var evt1 = jQuery.Event('jqplotDataMouseOver');
  596. evt1.pageX = ev.pageX;
  597. evt1.pageY = ev.pageY;
  598. plot.target.trigger(evt1, ins);
  599. if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.barRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
  600. var evt = jQuery.Event('jqplotDataHighlight');
  601. evt.pageX = ev.pageX;
  602. evt.pageY = ev.pageY;
  603. plot.target.trigger(evt, ins);
  604. highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points);
  605. }
  606. }
  607. else if (neighbor == null) {
  608. unhighlight (plot);
  609. }
  610. }
  611. function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
  612. if (neighbor) {
  613. var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
  614. if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.barRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
  615. var evt = jQuery.Event('jqplotDataHighlight');
  616. evt.pageX = ev.pageX;
  617. evt.pageY = ev.pageY;
  618. plot.target.trigger(evt, ins);
  619. highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points);
  620. }
  621. }
  622. else if (neighbor == null) {
  623. unhighlight (plot);
  624. }
  625. }
  626. function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {
  627. var idx = plot.plugins.barRenderer.highlightedSeriesIndex;
  628. if (idx != null && plot.series[idx].highlightMouseDown) {
  629. unhighlight(plot);
  630. }
  631. }
  632. function handleClick(ev, gridpos, datapos, neighbor, plot) {
  633. if (neighbor) {
  634. var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
  635. var evt = jQuery.Event('jqplotDataClick');
  636. evt.pageX = ev.pageX;
  637. evt.pageY = ev.pageY;
  638. plot.target.trigger(evt, ins);
  639. }
  640. }
  641. function handleRightClick(ev, gridpos, datapos, neighbor, plot) {
  642. if (neighbor) {
  643. var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
  644. var idx = plot.plugins.barRenderer.highlightedSeriesIndex;
  645. if (idx != null && plot.series[idx].highlightMouseDown) {
  646. unhighlight(plot);
  647. }
  648. var evt = jQuery.Event('jqplotDataRightClick');
  649. evt.pageX = ev.pageX;
  650. evt.pageY = ev.pageY;
  651. plot.target.trigger(evt, ins);
  652. }
  653. }
  654. })(jQuery);