html5 boiler plate
[scannr.git] / js / flotr2 / js / types / gantt.js
blob:a/js/flotr2/js/types/gantt.js -> blob:b/js/flotr2/js/types/gantt.js
--- a/js/flotr2/js/types/gantt.js
+++ b/js/flotr2/js/types/gantt.js
@@ -1,1 +1,230 @@
-
+/** Gantt
+ * Base on data in form [s,y,d] where:
+ * y - executor or simply y value
+ * s - task start value
+ * d - task duration
+ * **/
+Flotr.addType('gantt', {
+  options: {
+    show: false,           // => setting to true will show gantt, false will hide
+    lineWidth: 2,          // => in pixels
+    barWidth: 1,           // => in units of the x axis
+    fill: true,            // => true to fill the area from the line to the x axis, false for (transparent) no fill
+    fillColor: null,       // => fill color
+    fillOpacity: 0.4,      // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill
+    centered: true         // => center the bars to their x axis value
+  },
+  /**
+   * Draws gantt series in the canvas element.
+   * @param {Object} series - Series with options.gantt.show = true.
+   */
+  draw: function(series) {
+    var ctx = this.ctx,
+      bw = series.gantt.barWidth,
+      lw = Math.min(series.gantt.lineWidth, bw);
+    
+    ctx.save();
+    ctx.translate(this.plotOffset.left, this.plotOffset.top);
+    ctx.lineJoin = 'miter';
+
+    /**
+     * @todo linewidth not interpreted the right way.
+     */
+    ctx.lineWidth = lw;
+    ctx.strokeStyle = series.color;
+    
+    ctx.save();
+    this.gantt.plotShadows(series, bw, 0, series.gantt.fill);
+    ctx.restore();
+    
+    if(series.gantt.fill){
+      var color = series.gantt.fillColor || series.color;
+      ctx.fillStyle = this.processColor(color, {opacity: series.gantt.fillOpacity});
+    }
+    
+    this.gantt.plot(series, bw, 0, series.gantt.fill);
+    ctx.restore();
+  },
+  plot: function(series, barWidth, offset, fill){
+    var data = series.data;
+    if(data.length < 1) return;
+    
+    var xa = series.xaxis,
+        ya = series.yaxis,
+        ctx = this.ctx, i;
+
+    for(i = 0; i < data.length; i++){
+      var y = data[i][0],
+          s = data[i][1],
+          d = data[i][2],
+          drawLeft = true, drawTop = true, drawRight = true;
+      
+      if (s === null || d === null) continue;
+
+      var left = s, 
+          right = s + d,
+          bottom = y - (series.gantt.centered ? barWidth/2 : 0), 
+          top = y + barWidth - (series.gantt.centered ? barWidth/2 : 0);
+      
+      if(right < xa.min || left > xa.max || top < ya.min || bottom > ya.max)
+        continue;
+
+      if(left < xa.min){
+        left = xa.min;
+        drawLeft = false;
+      }
+
+      if(right > xa.max){
+        right = xa.max;
+        if (xa.lastSerie != series)
+          drawTop = false;
+      }
+
+      if(bottom < ya.min)
+        bottom = ya.min;
+
+      if(top > ya.max){
+        top = ya.max;
+        if (ya.lastSerie != series)
+          drawTop = false;
+      }
+      
+      /**
+       * Fill the bar.
+       */
+      if(fill){
+        ctx.beginPath();
+        ctx.moveTo(xa.d2p(left), ya.d2p(bottom) + offset);
+        ctx.lineTo(xa.d2p(left), ya.d2p(top) + offset);
+        ctx.lineTo(xa.d2p(right), ya.d2p(top) + offset);
+        ctx.lineTo(xa.d2p(right), ya.d2p(bottom) + offset);
+        ctx.fill();
+        ctx.closePath();
+      }
+
+      /**
+       * Draw bar outline/border.
+       */
+      if(series.gantt.lineWidth && (drawLeft || drawRight || drawTop)){
+        ctx.beginPath();
+        ctx.moveTo(xa.d2p(left), ya.d2p(bottom) + offset);
+        
+        ctx[drawLeft ?'lineTo':'moveTo'](xa.d2p(left), ya.d2p(top) + offset);
+        ctx[drawTop  ?'lineTo':'moveTo'](xa.d2p(right), ya.d2p(top) + offset);
+        ctx[drawRight?'lineTo':'moveTo'](xa.d2p(right), ya.d2p(bottom) + offset);
+                 
+        ctx.stroke();
+        ctx.closePath();
+      }
+    }
+  },
+  plotShadows: function(series, barWidth, offset){
+    var data = series.data;
+    if(data.length < 1) return;
+    
+    var i, y, s, d,
+        xa = series.xaxis,
+        ya = series.yaxis,
+        ctx = this.ctx,
+        sw = this.options.shadowSize;
+    
+    for(i = 0; i < data.length; i++){
+      y = data[i][0];
+      s = data[i][1];
+      d = data[i][2];
+        
+      if (s === null || d === null) continue;
+            
+      var left = s, 
+          right = s + d,
+          bottom = y - (series.gantt.centered ? barWidth/2 : 0), 
+          top = y + barWidth - (series.gantt.centered ? barWidth/2 : 0);
+ 
+      if(right < xa.min || left > xa.max || top < ya.min || bottom > ya.max)
+        continue;
+      
+      if(left < xa.min)   left = xa.min;
+      if(right > xa.max)  right = xa.max;
+      if(bottom < ya.min) bottom = ya.min;
+      if(top > ya.max)    top = ya.max;
+      
+      var width =  xa.d2p(right)-xa.d2p(left)-((xa.d2p(right)+sw <= this.plotWidth) ? 0 : sw);
+      var height = ya.d2p(bottom)-ya.d2p(top)-((ya.d2p(bottom)+sw <= this.plotHeight) ? 0 : sw );
+      
+      ctx.fillStyle = 'rgba(0,0,0,0.05)';
+      ctx.fillRect(Math.min(xa.d2p(left)+sw, this.plotWidth), Math.min(ya.d2p(top)+sw, this.plotHeight), width, height);
+    }
+  },
+  extendXRange: function(axis) {
+    if(axis.options.max === null){
+      var newmin = axis.min,
+          newmax = axis.max,
+          i, j, x, s, g,
+          stackedSumsPos = {},
+          stackedSumsNeg = {},
+          lastSerie = null;
+
+      for(i = 0; i < this.series.length; ++i){
+        s = this.series[i];
+        g = s.gantt;
+        
+        if(g.show && s.xaxis == axis) {
+            for (j = 0; j < s.data.length; j++) {
+              if (g.show) {
+                y = s.data[j][0]+'';
+                stackedSumsPos[y] = Math.max((stackedSumsPos[y] || 0), s.data[j][1]+s.data[j][2]);
+                lastSerie = s;
+              }
+            }
+            for (j in stackedSumsPos) {
+              newmax = Math.max(stackedSumsPos[j], newmax);
+            }
+        }
+      }
+      axis.lastSerie = lastSerie;
+      axis.max = newmax;
+      axis.min = newmin;
+    }
+  },
+  extendYRange: function(axis){
+    if(axis.options.max === null){
+      var newmax = Number.MIN_VALUE,
+          newmin = Number.MAX_VALUE,
+          i, j, s, g,
+          stackedSumsPos = {},
+          stackedSumsNeg = {},
+          lastSerie = null;
+                  
+      for(i = 0; i < this.series.length; ++i){
+        s = this.series[i];
+        g = s.gantt;
+        
+        if (g.show && !s.hide && s.yaxis == axis) {
+          var datamax = Number.MIN_VALUE, datamin = Number.MAX_VALUE;
+          for(j=0; j < s.data.length; j++){
+            datamax = Math.max(datamax,s.data[j][0]);
+            datamin = Math.min(datamin,s.data[j][0]);
+          }
+            
+          if (g.centered) {
+            newmax = Math.max(datamax + 0.5, newmax);
+            newmin = Math.min(datamin - 0.5, newmin);
+          }
+        else {
+          newmax = Math.max(datamax + 1, newmax);
+            newmin = Math.min(datamin, newmin);
+          }
+          // For normal horizontal bars
+          if (g.barWidth + datamax > newmax){
+            newmax = axis.max + g.barWidth;
+          }
+        }
+      }
+      axis.lastSerie = lastSerie;
+      axis.max = newmax;
+      axis.min = newmin;
+      axis.tickSize = Flotr.getTickSize(axis.options.noTicks, newmin, newmax, axis.options.tickDecimals);
+    }
+  }
+});
+