text: /* ========================================================================
   * Chart.js: Chart.line.js [Version: 1.0.2]
   * http://chartjs.org/
   * 
   * ZUI: The file has been changed in ZUI. It will not keep update with the
   * official version in the future.
   * http://zui.sexy
   * ========================================================================
   * Copyright 2015 Nick Downie, Released under the MIT license
   * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
   * ======================================================================== */
  
  
  /// ----- ZUI change begin -----
  /// Add jquery object to namespace
  
  /// (function(){ // Old code
  (function($) {
  
      /// ----- ZUI change end -----
      "use strict";
  
      /// ----- ZUI change begin -----
      /// Change root to zui shared object
      /// 
      ///   var root = this, // old code
      var root = $ && $.zui ? $.zui : this,
          /// ----- ZUI change end -----
          Chart = root.Chart,
          helpers = Chart.helpers;
  
      var defaultConfig = {
  
          ///Boolean - Whether grid lines are shown across the chart
          scaleShowGridLines: true,
  
          //String - Colour of the grid lines
          scaleGridLineColor: "rgba(0,0,0,.05)",
  
          //Number - Width of the grid lines
          scaleGridLineWidth: 1,
  
          //Boolean - Whether to show horizontal lines (except X axis)
          scaleShowHorizontalLines: true,
  
          /// ZUI change end
          //Boolean - Whether to show beyond lines
          scaleShowBeyondLine: true,
          /// ZUI change end
          /// 
          //Boolean - Whether to show vertical lines (except Y axis)
          scaleShowVerticalLines: true,
  
          //Boolean - Whether the line is curved between points
          bezierCurve: true,
  
          //Number - Tension of the bezier curve between points
          bezierCurveTension: 0.4,
  
          //Boolean - Whether to show a dot for each point
          pointDot: true,
  
          //Number - Radius of each point dot in pixels
          pointDotRadius: 4,
  
          //Number - Pixel width of point dot stroke
          pointDotStrokeWidth: 1,
  
          //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
          pointHitDetectionRadius: 20,
  
          //Boolean - Whether to show a stroke for datasets
          datasetStroke: true,
  
          //Number - Pixel width of dataset stroke
          datasetStrokeWidth: 2,
  
          //Boolean - Whether to fill the dataset with a colour
          datasetFill: true,
  
          //String - A legend template
          legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
  
      };
  
  
      Chart.Type.extend({
          name: "Line",
          defaults: defaultConfig,
  
          initialize: function(data) {
              //Declare the extension of the default point, to cater for the options passed in to the constructor
              this.PointClass = Chart.Point.extend({
                  strokeWidth: this.options.pointDotStrokeWidth,
                  radius: this.options.pointDotRadius,
                  display: this.options.pointDot,
                  hitDetectionRadius: this.options.pointHitDetectionRadius,
                  ctx: this.chart.ctx,
                  inRange: function(mouseX) {
                      return(Math.pow(mouseX - this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius, 2));
                  }
              });
  
              this.datasets = [];
  
              //Set up tooltip events on the chart
              if(this.options.showTooltips) {
                  helpers.bindEvents(this, this.options.tooltipEvents, function(evt) {
                      var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
                      this.eachPoints(function(point) {
                          point.restore(['fillColor', 'strokeColor']);
                      });
                      helpers.each(activePoints, function(activePoint) {
                          activePoint.fillColor = activePoint.highlightFill;
                          activePoint.strokeColor = activePoint.highlightStroke;
                      });
                      this.showTooltip(activePoints);
                  });
              }
  
              //Iterate through each of the datasets, and build this into a property of the chart
              helpers.each(data.datasets, function(dataset) {
                  /// ----- ZUI change begin -----
                  // add color theme
                  if($.zui && $.zui.Color && $.zui.Color.get) {
                      var accentColor = $.zui.Color.get(dataset.color);
                      var accentColorValue = accentColor.toCssStr();
  
                      if(!dataset.fillColor) dataset.fillColor = accentColor.clone().fade(20).toCssStr();
                      if(!dataset.strokeColor) dataset.strokeColor = accentColorValue;
                      if(!dataset.pointColor) dataset.pointColor = accentColorValue;
                      if(!dataset.pointStrokeColor) dataset.pointStrokeColor = '#fff';
                      if(!dataset.pointHighlightFill) dataset.pointHighlightFill = '#fff';
                      if(!dataset.pointHighlightStroke) dataset.pointHighlightStroke = accentColorValue;
                  }
                  /// ----- ZUI change begin -----
  
                  var datasetObject = {
                      label: dataset.label || null,
                      fillColor: dataset.fillColor,
                      strokeColor: dataset.strokeColor,
                      pointColor: dataset.pointColor,
                      pointStrokeColor: dataset.pointStrokeColor,
                      /// ZUI change begin
                      showTooltips: dataset.showTooltips !== false,
                      /// ZUI change end
                      points: []
                  };
  
                  this.datasets.push(datasetObject);
  
  
                  helpers.each(dataset.data, function(dataPoint, index) {
                      //Add a new point for each piece of data, passing any required data to draw.
                      datasetObject.points.push(new this.PointClass({
                          value: dataPoint,
                          label: data.labels[index],
                          datasetLabel: dataset.label,
                          strokeColor: dataset.pointStrokeColor,
                          fillColor: dataset.pointColor,
                          highlightFill: dataset.pointHighlightFill || dataset.pointColor,
                          highlightStroke: dataset.pointHighlightStroke || dataset.pointStrokeColor
                      }));
                  }, this);
  
                  this.buildScale(data.labels);
  
  
                  this.eachPoints(function(point, index) {
                      helpers.extend(point, {
                          x: this.scale.calculateX(index),
                          y: this.scale.endPoint
                      });
                      point.save();
                  }, this);
  
              }, this);
  
  
              this.render();
          },
          update: function() {
              this.scale.update();
              // Reset any highlight colours before updating.
              helpers.each(this.activeElements, function(activeElement) {
                  activeElement.restore(['fillColor', 'strokeColor']);
              });
              this.eachPoints(function(point) {
                  point.save();
              });
              this.render();
          },
          eachPoints: function(callback) {
              helpers.each(this.datasets, function(dataset) {
                  helpers.each(dataset.points, callback, this);
              }, this);
          },
          getPointsAtEvent: function(e) {
              var pointsArray = [],
                  eventPosition = helpers.getRelativePosition(e);
              helpers.each(this.datasets, function(dataset) {
                  helpers.each(dataset.points, function(point) {
                      if(point.inRange(eventPosition.x, eventPosition.y)) pointsArray.push(point);
                  });
              }, this);
              return pointsArray;
          },
          buildScale: function(labels) {
              var self = this;
  
              var dataTotal = function() {
                  var values = [];
                  self.eachPoints(function(point) {
                      values.push(point.value);
                  });
  
                  return values;
              };
  
              var scaleOptions = {
                  templateString: this.options.scaleLabel,
                  height: this.chart.height,
                  width: this.chart.width,
                  ctx: this.chart.ctx,
                  textColor: this.options.scaleFontColor,
                  fontSize: this.options.scaleFontSize,
                  fontStyle: this.options.scaleFontStyle,
                  fontFamily: this.options.scaleFontFamily,
                  valuesCount: labels.length,
                  beginAtZero: this.options.scaleBeginAtZero,
                  integersOnly: this.options.scaleIntegersOnly,
                  calculateYRange: function(currentHeight) {
                      var updatedRanges = helpers.calculateScaleRange(
                          dataTotal(),
                          currentHeight,
                          this.fontSize,
                          this.beginAtZero,
                          this.integersOnly
                      );
                      helpers.extend(this, updatedRanges);
                  },
                  xLabels: labels,
                  font: helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
                  lineWidth: this.options.scaleLineWidth,
                  lineColor: this.options.scaleLineColor,
                  showHorizontalLines: this.options.scaleShowHorizontalLines,
                  showVerticalLines: this.options.scaleShowVerticalLines,
                  /// ZUI change begin
                  showBeyondLine: this.options.scaleShowBeyondLine,
                  /// ZUI change end
                  gridLineWidth: (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
                  gridLineColor: (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
                  padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,
                  showLabels: this.options.scaleShowLabels,
                  display: this.options.showScale
              };
  
              if(this.options.scaleOverride) {
                  helpers.extend(scaleOptions, {
                      calculateYRange: helpers.noop,
                      steps: this.options.scaleSteps,
                      stepValue: this.options.scaleStepWidth,
                      min: this.options.scaleStartValue,
                      max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
                  });
              }
  
  
              this.scale = new Chart.Scale(scaleOptions);
          },
          addData: function(valuesArray, label) {
              //Map the values array for each of the datasets
  
              helpers.each(valuesArray, function(value, datasetIndex) {
                  //Add a new point for each piece of data, passing any required data to draw.
                  this.datasets[datasetIndex].points.push(new this.PointClass({
                      value: value,
                      label: label,
                      x: this.scale.calculateX(this.scale.valuesCount + 1),
                      y: this.scale.endPoint,
                      strokeColor: this.datasets[datasetIndex].pointStrokeColor,
                      fillColor: this.datasets[datasetIndex].pointColor
                  }));
              }, this);
  
              this.scale.addXLabel(label);
              //Then re-render the chart.
              this.update();
          },
          removeData: function() {
              this.scale.removeXLabel();
              //Then re-render the chart.
              helpers.each(this.datasets, function(dataset) {
                  dataset.points.shift();
              }, this);
              this.update();
          },
          reflow: function() {
              var newScaleProps = helpers.extend({
                  height: this.chart.height,
                  width: this.chart.width
              });
              this.scale.update(newScaleProps);
          },
          draw: function(ease) {
              var easingDecimal = ease || 1;
              this.clear();
  
              var ctx = this.chart.ctx;
  
              // Some helper methods for getting the next/prev points
              var hasValue = function(item) {
                      return item.value !== null;
                  },
                  nextPoint = function(point, collection, index) {
                      return helpers.findNextWhere(collection, hasValue, index) || point;
                  },
                  previousPoint = function(point, collection, index) {
                      return helpers.findPreviousWhere(collection, hasValue, index) || point;
                  };
  
              this.scale.draw(easingDecimal);
  
  
              helpers.each(this.datasets, function(dataset) {
                  var pointsWithValues = helpers.where(dataset.points, hasValue);
  
                  //Transition each point first so that the line and point drawing isn't out of sync
                  //We can use this extra loop to calculate the control points of this dataset also in this loop
  
                  helpers.each(dataset.points, function(point, index) {
                      if(point.hasValue()) {
                          point.transition({
                              y: this.scale.calculateY(point.value),
                              x: this.scale.calculateX(index)
                          }, easingDecimal);
                      }
                  }, this);
  
  
                  // Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point
                  // This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed
                  if(this.options.bezierCurve) {
                      helpers.each(pointsWithValues, function(point, index) {
                          var tension = (index > 0 && index < pointsWithValues.length - 1) ? this.options.bezierCurveTension : 0;
                          point.controlPoints = helpers.splineCurve(
                              previousPoint(point, pointsWithValues, index),
                              point,
                              nextPoint(point, pointsWithValues, index),
                              tension
                          );
  
                          // Prevent the bezier going outside of the bounds of the graph
  
                          // Cap puter bezier handles to the upper/lower scale bounds
                          if(point.controlPoints.outer.y > this.scale.endPoint) {
                              point.controlPoints.outer.y = this.scale.endPoint;
                          } else if(point.controlPoints.outer.y < this.scale.startPoint) {
                              point.controlPoints.outer.y = this.scale.startPoint;
                          }
  
                          // Cap inner bezier handles to the upper/lower scale bounds
                          if(point.controlPoints.inner.y > this.scale.endPoint) {
                              point.controlPoints.inner.y = this.scale.endPoint;
                          } else if(point.controlPoints.inner.y < this.scale.startPoint) {
                              point.controlPoints.inner.y = this.scale.startPoint;
                          }
                      }, this);
                  }
  
  
                  //Draw the line between all the points
                  ctx.lineWidth = this.options.datasetStrokeWidth;
                  ctx.strokeStyle = dataset.strokeColor;
                  ctx.beginPath();
  
                  helpers.each(pointsWithValues, function(point, index) {
                      if(index === 0) {
                          ctx.moveTo(point.x, point.y);
                      } else {
                          if(this.options.bezierCurve) {
                              var previous = previousPoint(point, pointsWithValues, index);
  
                              ctx.bezierCurveTo(
                                  previous.controlPoints.outer.x,
                                  previous.controlPoints.outer.y,
                                  point.controlPoints.inner.x,
                                  point.controlPoints.inner.y,
                                  point.x,
                                  point.y
                              );
                          } else {
                              ctx.lineTo(point.x, point.y);
                          }
                      }
                  }, this);
  
                  ctx.stroke();
  
                  if(this.options.datasetFill && pointsWithValues.length > 0) {
                      //Round off the line by going to the base of the chart, back to the start, then fill.
                      ctx.lineTo(pointsWithValues[pointsWithValues.length - 1].x, this.scale.endPoint);
                      ctx.lineTo(pointsWithValues[0].x, this.scale.endPoint);
                      ctx.fillStyle = dataset.fillColor;
                      ctx.closePath();
                      ctx.fill();
                  }
  
                  //Now draw the points over the line
                  //A little inefficient double looping, but better than the line
                  //lagging behind the point positions
                  helpers.each(pointsWithValues, function(point) {
                      point.draw();
                  });
              }, this);
          }
      });
  
      /// ----- ZUI change begin -----
      /// Use jquery object to create Chart object
      $.fn.lineChart = function(data, options) {
          var lineCharts = [];
          this.each(function() {
              var $this = $(this);
              lineCharts.push(new Chart(this.getContext("2d")).Line(data, $.extend($this.data(), options)));
          });
          return lineCharts.length === 1 ? lineCharts[0] : lineCharts;
      }
  
      /// ----- ZUI change end -----
  
      /// ----- ZUI change begin -----
      /// Add jquery object to namespace
  
      /// }).call(this); // Old code
  }).call(this, jQuery);
  
  /// ----- ZUI change end -----
  
  