jquery.flot.extents.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Copyright 2012, Serge V. Izmaylov
  3. * Released under GPL Version 2 license.
  4. */
  5. (function ($) {
  6. var options = {
  7. series: {
  8. extents: {
  9. show: false,
  10. lineWidth: 1,
  11. barHeight: 17,
  12. color: "rgba(192, 192, 192, 1.0)",
  13. showConnections: true,
  14. connectionColor: "rgba(0, 192, 128, 0.8)",
  15. fill: true,
  16. fillColor: "rgba(64, 192, 255, 0.5)",
  17. showLabels: true,
  18. rowHeight: 20,
  19. rows: 7,
  20. barVAlign: "top",
  21. labelHAlign: "left"
  22. }
  23. }
  24. };
  25. function processRawData(plot, series, data, datapoints) {
  26. if (!series.extents || !series.extents.show)
  27. return;
  28. // Fool Flot with fake datapoints
  29. datapoints.format = [ // Fake format
  30. { x: true, number: true, required: true },
  31. { y: true, number: true, required: true },
  32. ];
  33. datapoints.points = []; // Empty data
  34. datapoints.pointsize = 2; // Fake size
  35. // Check if we have extents data
  36. if (series.extentdata == null)
  37. return;
  38. // Process our real data
  39. var row = 0;
  40. for (i = 0; i < series.extentdata.length; i++) {
  41. // Skip bad extents
  42. if ((series.extentdata[i].start == null) || (series.extentdata[i].end == null))
  43. continue;
  44. if (series.extentdata[i].end < series.extentdata[i].start) {
  45. var t = series.extentdata[i].end;
  46. series.extentdata[i].end = series.extentdata[i].start;
  47. series.extentdata[i].start = t;
  48. }
  49. if ((series.extentdata[i].labelHAlign != "left") && (series.extentdata[i].labelHAlign != "right"))
  50. series.extentdata[i].labelHAlign = series.extents.labelHAlign;
  51. if (series.extentdata[i].row == null) {
  52. series.extentdata[i].row = row;
  53. row = (row+1) % series.extents.rows;
  54. } else {
  55. row = (series.extentdata[i].row+1) % series.extents.rows;
  56. }
  57. if (series.extentdata[i].color == null)
  58. series.extentdata[i].color = series.extents.color;
  59. if (series.extentdata[i].fillColor == null)
  60. series.extentdata[i].fillColor = series.extents.fillColor;
  61. }
  62. };
  63. function drawSingleExtent(ctx, width, height, xfrom, xto, series, extent) {
  64. if (xfrom < 0) xfrom = 0;
  65. if (xto > width) xto = width;
  66. var bw = xto-xfrom;
  67. var yfrom;
  68. if (series.extents.barVAlign == "top")
  69. yfrom = 4 + series.extents.rowHeight*extent.row;
  70. else
  71. yfrom = height - 4 - series.extents.rowHeight*(extent.row) - series.extents.barHeight;
  72. if (series.extents.fill) {
  73. ctx.fillStyle = extent.fillColor;
  74. ctx.fillRect(xfrom, yfrom, bw, series.extents.barHeight);
  75. }
  76. ctx.strokeStyle = extent.color;
  77. ctx.strokeRect(xfrom, yfrom, bw, series.extents.barHeight);
  78. }
  79. function drawSingleConnection(ctx, width, height, xfrom, xto, rfrom, rto, series) {
  80. if (xfrom < 0) xfrom = 0;
  81. if (xto > width) xto = width;
  82. var yfrom, yto;
  83. if (series.extents.barVAlign == "top") {
  84. yfrom = 4 + Math.round(series.extents.rowHeight*rfrom) + Math.round(series.extents.barHeight*0.5);
  85. yto = 4 + Math.round(series.extents.rowHeight*rto) + Math.round(series.extents.barHeight*0.5);
  86. } else {
  87. yfrom = height - 4 - Math.round(series.extents.rowHeight*rfrom) - Math.round(series.extents.barHeight*0.5);
  88. yto = height - 4 - Math.round(series.extents.rowHeight*rto) - Math.round(series.extents.barHeight*0.5);
  89. }
  90. ctx.beginPath();
  91. ctx.moveTo(xfrom, yfrom);
  92. ctx.lineTo(xfrom+10, yfrom);
  93. ctx.lineTo(xto-10, yto);
  94. ctx.lineTo(xto, yto);
  95. ctx.lineTo(xto-6, yto-3);
  96. ctx.lineTo(xto-6, yto+3);
  97. ctx.lineTo(xto, yto);
  98. ctx.stroke();
  99. }
  100. function addExtentLabel(placeholder, plotOffset, width, xfrom, xto, series, extent) {
  101. var styles = [];
  102. if (series.extents.barVAlign == "top")
  103. styles.push("top:"+Math.round((plotOffset.top+series.extents.rowHeight*extent.row+4))+"px");
  104. else
  105. styles.push("bottom:"+Math.round((plotOffset.bottom+series.extents.rowHeight*extent.row+4))+"px");
  106. if (extent.labelHAlign == "left")
  107. styles.push("left:"+Math.round((plotOffset.left+xfrom+3))+"px");
  108. else
  109. styles.push("right:"+Math.round((plotOffset.right+(width-xto)+3))+"px");
  110. styles.push("");
  111. placeholder.append('<div '+((extent.id !=null)?('id="'+extent.id+'" '):'')+'class="extentLabel" style="font-size:smaller;position:absolute;'+(styles.join(';'))+'">'+extent.label+'</div>');
  112. }
  113. function drawSeries(plot, ctx, series) {
  114. if (!series.extents || !series.extents.show || !series.extentdata)
  115. return;
  116. var placeholder = plot.getPlaceholder();
  117. placeholder.find(".extentLabel").remove();
  118. ctx.save();
  119. var plotOffset = plot.getPlotOffset();
  120. var axes = plot.getAxes();
  121. var yf = axes.yaxis.p2c(axes.yaxis.min);
  122. var yt = axes.yaxis.p2c(axes.yaxis.max);
  123. var ytop = (yf>yt)?yt:yf;
  124. var ybot = (yf>yt)?yf:yt;
  125. var width = plot.width();
  126. var height = plot.height();
  127. ctx.translate(plotOffset.left, plotOffset.top);
  128. ctx.lineJoin = "round";
  129. for (var i = 0; i < series.extentdata.length; i++) {
  130. var xfrom, xto;
  131. if ((series.extentdata[i].start == null) || (series.extentdata[i].end == null))
  132. continue;
  133. if ((series.extentdata[i].start < axes.xaxis.max) && (series.extentdata[i].end > axes.xaxis.min)) {
  134. xfrom = axes.xaxis.p2c((series.extentdata[i].start<axes.xaxis.min)?axes.xaxis.min:series.extentdata[i].start);
  135. xto = axes.xaxis.p2c((series.extentdata[i].end>axes.xaxis.max)?axes.xaxis.max:series.extentdata[i].end);
  136. drawSingleExtent(ctx, width, height, xfrom, xto, series, series.extentdata[i]);
  137. if (series.extents.showConnections && (series.extentdata[i].start > axes.xaxis.min) && (series.extentdata[i].start < axes.xaxis.max))
  138. if ((series.extentdata[i].depends != null) && (series.extentdata[i].depends.length != null) && (series.extentdata[i].depends.length > 0))
  139. for (var j=0; j<series.extentdata[i].depends.length; j++) {
  140. var k = series.extentdata[i].depends[j];
  141. if ((k < 0) || (k >= series.extentdata.length))
  142. continue;
  143. if ((series.extentdata[k].start == null) || (series.extentdata[k].end == null))
  144. continue;
  145. var cxto = xfrom;
  146. var cxfrom = series.extentdata[k].end;
  147. if (cxfrom < axes.xaxis.min) cxfrom = axes.xaxis.min;
  148. if (cxfrom > axes.xaxis.max) cxfrom = axes.xaxis.max;
  149. cxfrom = axes.xaxis.p2c(cxfrom);
  150. ctx.strokeStyle = series.extents.connectionColor;
  151. drawSingleConnection(ctx, width, height, cxfrom, cxto, series.extentdata[k].row, series.extentdata[i].row, series);
  152. }
  153. if (series.extents.showLabels && (series.extentdata[i].label != null))
  154. addExtentLabel(placeholder, plotOffset, width, xfrom, xto, series, series.extentdata[i]);
  155. }
  156. }
  157. ctx.restore();
  158. };
  159. function init(plot) {
  160. plot.hooks.processRawData.push(processRawData);
  161. plot.hooks.drawSeries.push(drawSeries);
  162. };
  163. $.plot.plugins.push({
  164. init: init,
  165. name: "extents",
  166. options: options,
  167. version: "0.3"
  168. });
  169. })(jQuery);