html5 boiler plate
[scannr.git] / js / flotr2 / js / types / markers.js
blob:a/js/flotr2/js/types/markers.js -> blob:b/js/flotr2/js/types/markers.js
--- a/js/flotr2/js/types/markers.js
+++ b/js/flotr2/js/types/markers.js
@@ -1,1 +1,141 @@
+/** Markers **/
+/**
+ * Formats the marker labels.
+ * @param {Object} obj - Marker value Object {x:..,y:..}
+ * @return {String} Formatted marker string
+ */
+(function () {
 
+Flotr.defaultMarkerFormatter = function(obj){
+  return (Math.round(obj.y*100)/100)+'';
+};
+
+Flotr.addType('markers', {
+  options: {
+    show: false,           // => setting to true will show markers, false will hide
+    lineWidth: 1,          // => line width of the rectangle around the marker
+    color: '#000000',      // => text color
+    fill: false,           // => fill or not the marekers' rectangles
+    fillColor: "#FFFFFF",  // => fill color
+    fillOpacity: 0.4,      // => fill opacity
+    stroke: false,         // => draw the rectangle around the markers
+    position: 'ct',        // => the markers position (vertical align: b, m, t, horizontal align: l, c, r)
+    verticalMargin: 0,     // => the margin between the point and the text.
+    labelFormatter: Flotr.defaultMarkerFormatter,
+    fontSize: Flotr.defaultOptions.fontSize,
+    stacked: false,        // => true if markers should be stacked
+    stackingType: 'b',     // => define staching behavior, (b- bars like, a - area like) (see Issue 125 for details)
+    horizontal: false      // => true if markers should be horizontal (For now only in a case on horizontal stacked bars, stacks should be calculated horizontaly)
+  },
+
+  // TODO test stacked markers.
+  stack : {
+      positive : [],
+      negative : [],
+      values : []
+  },
+
+  draw : function (options) {
+
+    var
+      data            = options.data,
+      context         = options.context,
+      stack           = options.stacked ? options.stack : false,
+      stackType       = options.stackingType,
+      stackOffsetNeg,
+      stackOffsetPos,
+      stackOffset,
+      i, x, y, label;
+
+    context.save();
+    context.lineJoin = 'round';
+    context.lineWidth = options.lineWidth;
+    context.strokeStyle = 'rgba(0,0,0,0.5)';
+    context.fillStyle = options.fillStyle;
+
+    function stackPos (a, b) {
+      stackOffsetPos = stack.negative[a] || 0;
+      stackOffsetNeg = stack.positive[a] || 0;
+      if (b > 0) {
+        stack.positive[a] = stackOffsetPos + b;
+        return stackOffsetPos + b;
+      } else {
+        stack.negative[a] = stackOffsetNeg + b;
+        return stackOffsetNeg + b;
+      }
+    }
+
+    for (i = 0; i < data.length; ++i) {
+    
+      x = data[i][0];
+      y = data[i][1];
+        
+      if (stack) {
+        if (stackType == 'b') {
+          if (options.horizontal) y = stackPos(y, x);
+          else x = stackPos(x, y);
+        } else if (stackType == 'a') {
+          stackOffset = stack.values[x] || 0;
+          stack.values[x] = stackOffset + y;
+          y = stackOffset + y;
+        }
+      }
+
+      label = options.labelFormatter({x: x, y: y, index: i, data : data});
+      this.plot(options.xScale(x), options.yScale(y), label, options);
+    }
+    context.restore();
+  },
+  plot: function(x, y, label, options) {
+    var context = options.context;
+    if (isImage(label) && !label.complete) {
+      throw 'Marker image not loaded.';
+    } else {
+      this._plot(x, y, label, options);
+    }
+  },
+
+  _plot: function(x, y, label, options) {
+    var context = options.context,
+        margin = 2,
+        left = x,
+        top = y,
+        dim;
+
+    if (isImage(label))
+      dim = {height : label.height, width: label.width};
+    else
+      dim = options.text.canvas(label);
+
+    dim.width = Math.floor(dim.width+margin*2);
+    dim.height = Math.floor(dim.height+margin*2);
+
+         if (options.position.indexOf('c') != -1) left -= dim.width/2 + margin;
+    else if (options.position.indexOf('l') != -1) left -= dim.width;
+    
+         if (options.position.indexOf('m') != -1) top -= dim.height/2 + margin;
+    else if (options.position.indexOf('t') != -1) top -= dim.height + options.verticalMargin;
+    else top += options.verticalMargin;
+    
+    left = Math.floor(left)+0.5;
+    top = Math.floor(top)+0.5;
+    
+    if(options.fill)
+      context.fillRect(left, top, dim.width, dim.height);
+      
+    if(options.stroke)
+      context.strokeRect(left, top, dim.width, dim.height);
+    
+    if (isImage(label))
+      context.drawImage(label, left+margin, top+margin);
+    else
+      Flotr.drawText(context, label, left+margin, top+margin, {textBaseline: 'top', textAlign: 'left', size: options.fontSize, color: options.color});
+  }
+});
+
+function isImage (i) {
+  return typeof i === 'object' && i.constructor && (Image ? true : i.constructor === Image);
+}
+
+})();
+