{"version":3,"sources":["webpack:///pipelines_times.e46dc9aeaebdd9a38964.bundle.js","webpack:///(webpack)/buildin/amd-options.js","webpack:////opt/gitlab/embedded/service/gitlab-rails/vendor/assets/javascripts/Chart.js","webpack:///./pipelines/pipelines_times.js"],"names":["webpackJsonp","../../../node_modules/webpack/buildin/amd-options.js","module","exports","__webpack_amd_options__","call","../../../vendor/assets/javascripts/Chart.js","__webpack_require__","__WEBPACK_AMD_DEFINE_RESULT__","root","this","previous","Chart","context","canvas","ctx","computeDimension","element","dimension","document","defaultView","getComputedStyle","getPropertyValue","width","height","aspectRatio","helpers","retinaScale","defaults","global","animation","animationSteps","animationEasing","showScale","scaleOverride","scaleSteps","scaleStepWidth","scaleStartValue","scaleLineColor","scaleLineWidth","scaleShowLabels","scaleLabel","scaleIntegersOnly","scaleBeginAtZero","scaleFontFamily","scaleFontSize","scaleFontStyle","scaleFontColor","responsive","maintainAspectRatio","showTooltips","customTooltips","tooltipEvents","tooltipFillColor","tooltipFontFamily","tooltipFontSize","tooltipFontStyle","tooltipFontColor","tooltipTitleFontFamily","tooltipTitleFontSize","tooltipTitleFontStyle","tooltipTitleFontColor","tooltipYPadding","tooltipXPadding","tooltipCaretSize","tooltipCornerRadius","tooltipXOffset","tooltipTemplate","multiTooltipTemplate","multiTooltipKeyBackground","onAnimationProgress","onAnimationComplete","types","each","loopable","callback","self","additionalArgs","Array","prototype","slice","arguments","length","i","apply","concat","item","clone","obj","objClone","value","key","hasOwnProperty","extend","base","extensionObject","merge","master","args","unshift","indexOf","arrayToSearch","inherits","where","collection","filterCallback","filtered","push","findNextWhere","startIndex","currentItem","findPreviousWhere","extensions","parent","ChartElement","constructor","Surrogate","__super__","noop","uid","id","warn","str","window","console","amd","isNumber","n","isNaN","parseFloat","isFinite","max","array","Math","min","getDecimalPlaces","cap","valueToCap","maxValue","minValue","num","toString","split","toRadians","radians","degrees","PI","aliasPixel","getAngleFromPoint","centrePoint","anglePoint","distanceFromXCenter","x","distanceFromYCenter","y","radialDistanceFromCenter","sqrt","angle","atan2","distance","pixelWidth","calculateOrderOfMagnitude","splineCurve","FirstPoint","MiddlePoint","AfterPoint","t","d01","pow","d12","fa","fb","inner","outer","val","floor","log","LN10","template","calculateScaleRange","valuesArray","drawingSize","textSize","startFromZero","integersOnly","maxSteps","skipFitting","valueRange","abs","rangeOrderOfMagnitude","graphMax","ceil","graphMin","graphRange","stepValue","numberOfSteps","round","steps","templateString","valuesObject","Function","cache","data","fn","test","replace","join","easingEffects","generateLabels","labelsArray","labelTemplateString","index","linear","easeInQuad","easeOutQuad","easeInOutQuad","easeInCubic","easeOutCubic","easeInOutCubic","easeInQuart","easeOutQuart","easeInOutQuart","easeInQuint","easeOutQuint","easeInOutQuint","easeInSine","cos","easeOutSine","sin","easeInOutSine","easeInExpo","easeOutExpo","easeInOutExpo","easeInCirc","easeOutCirc","easeInOutCirc","easeInElastic","s","p","a","asin","easeOutElastic","easeInOutElastic","easeInBack","easeOutBack","easeInOutBack","easeInBounce","easeOutBounce","easeInOutBounce","requestAnimFrame","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","setTimeout","cancelAnimFrame","cancelAnimationFrame","webkitCancelAnimationFrame","mozCancelAnimationFrame","oCancelAnimationFrame","msCancelAnimationFrame","clearTimeout","addEvent","animationLoop","totalSteps","easingString","onProgress","onComplete","chartInstance","currentStep","easingFunction","animationFrame","stepDecimal","easeDecimal","getRelativePosition","evt","mouseX","mouseY","e","originalEvent","currentTarget","srcElement","boundingRect","getBoundingClientRect","touches","clientX","left","clientY","top","node","eventType","method","addEventListener","attachEvent","removeEvent","handler","removeEventListener","detachEvent","unbindEvents","bindEvents","arrayOfEvents","events","eventName","chart","getMaximumWidth","domNode","parentNode","clientWidth","getMaximumHeight","clientHeight","getMaximumSize","devicePixelRatio","style","scale","clear","clearRect","fontString","pixelSize","fontStyle","fontFamily","longestText","font","arrayOfStrings","longest","string","textWidth","measureText","drawRoundedRectangle","radius","beginPath","moveTo","lineTo","quadraticCurveTo","closePath","instances","Type","options","resize","initialize","stop","newWidth","newHeight","reflow","render","draw","generateLegend","legendTemplate","destroy","removeProperty","removeAttribute","showTooltip","ChartElements","forceRedraw","activeElements","Elements","changed","datasets","dataArray","dataIndex","points","bars","segments","tooltipLabels","tooltipColors","medianPosition","dataCollection","xMax","yMax","xMin","yMin","xPositions","yPositions","dataset","hasValue","fill","_saved","fillColor","stroke","strokeColor","MultiTooltip","xPadding","yPadding","xOffset","textColor","fontSize","titleTextColor","titleFontFamily","titleFontStyle","titleFontSize","cornerRadius","labels","legendColors","legendColorBackground","title","label","custom","Element","tooltipPosition","Tooltip","caretHeight","text","toBase64Image","toDataURL","ChartType","name","chartName","baseDefaults","config","configuration","save","restore","props","update","newProps","transition","ease","Point","display","inRange","chartX","chartY","hitDetectionRange","hitDetectionRadius","arc","strokeStyle","lineWidth","strokeWidth","fillStyle","Arc","pointRelativePosition","betweenAngles","startAngle","endAngle","withinRadius","innerRadius","outerRadius","centreAngle","rangeFromCentre","animationPercent","lineJoin","showStroke","Rectangle","halfWidth","leftX","rightX","halfStroke","xAlign","yAlign","caretPadding","tooltipWidth","tooltipRectHeight","tooltipHeight","tooltipX","tooltipY","textAlign","textBaseline","fillText","titleFont","titleWidth","labelWidth","longestTextWidth","halfHeight","getLineHeight","baseLineHeight","afterTitleIndex","fillRect","Scale","fit","buildYLabels","yLabels","stepDecimalPlaces","toFixed","yLabelWidth","showLabels","addXLabel","xLabels","valuesCount","removeXLabel","shift","startPoint","endPoint","padding","cachedYLabelWidth","cachedHeight","calculateYRange","calculateXLabelRotation","firstRotated","firstWidth","lastWidth","xScalePaddingRight","xScalePaddingLeft","xLabelRotation","cosRotation","originalLabelWidth","xLabelWidth","xGridWidth","calculateX","drawingArea","calculateY","scalingFactor","innerWidth","valueWidth","valueOffset","offsetGridLines","yLabelGap","xStart","labelString","yLabelCenter","linePositionY","drawHorizontalLine","showHorizontalLines","gridLineWidth","gridLineColor","lineColor","xPos","linePos","isRotated","drawVerticalLine","showVerticalLines","translate","rotate","RadialScale","size","backdropPaddingY","calculateCenterOffset","lineArc","setScaleSize","getCircumference","pointPosition","halfTextWidth","furthestRightIndex","furthestRightAngle","furthestLeftIndex","furthestLeftAngle","xProtrusionLeft","xProtrusionRight","radiusReductionRight","radiusReductionLeft","largestPossibleRadius","pointLabelFontSize","furthestRight","furthestLeft","pointLabelFontStyle","pointLabelFontFamily","getPointPosition","getIndexAngle","setCenterPoint","leftMovement","rightMovement","maxRight","maxLeft","xCenter","yCenter","distanceFromCenter","thisAngle","yCenterOffset","yHeight","showLabelBackdrop","backdropColor","backdropPaddingX","fontColor","angleLineWidth","angleLineColor","outerPosition","pointLabelPosition","pointLabelFontColor","labelsCount","halfLabelsCount","quarterLabelsCount","upperHalf","exactQuarter","timeout","instance","undefined","noConflict","defaultConfig","scaleShowGridLines","scaleGridLineColor","scaleGridLineWidth","scaleShowHorizontalLines","scaleShowVerticalLines","barShowStroke","barStrokeWidth","barValueSpacing","barDatasetSpacing","ScaleClass","calculateBarX","datasetCount","datasetIndex","barIndex","xWidth","calculateBaseWidth","xAbsolute","barWidth","calculateBarWidth","activeBars","type","getBarsAtEvent","eachBars","bar","activeBar","highlightFill","highlightStroke","BarClass","datasetObject","dataPoint","datasetLabel","buildScale","activeElement","barsArray","eventPosition","datasetIterator","dataTotal","values","scaleOptions","beginAtZero","currentHeight","updatedRanges","addData","removeData","newScaleProps","easingDecimal","segmentShowStroke","segmentStrokeColor","segmentStrokeWidth","percentageInnerCutout","animateRotate","animateScale","SegmentArc","activeSegments","getSegmentsAtEvent","segment","activeSegment","highlightColor","calculateTotal","datapoint","segmentsArray","location","atIndex","silent","splice","color","highlight","circumference","calculateCircumference","total","indexToDelete","animDecimal","Doughnut","bezierCurve","bezierCurveTension","pointDot","pointDotRadius","pointDotStrokeWidth","pointHitDetectionRadius","datasetStroke","datasetStrokeWidth","datasetFill","PointClass","activePoints","getPointsAtEvent","eachPoints","point","activePoint","pointColor","pointStrokeColor","pointHighlightFill","pointHighlightStroke","pointsArray","nextPoint","previousPoint","pointsWithValues","tension","controlPoints","bezierCurveTo","scaleShowLabelBackdrop","scaleBackdropColor","scaleBackdropPaddingY","scaleBackdropPaddingX","scaleShowLine","updateScaleRange","datapoints","scaleSizes","angleShowLineOut","activePointsCollection","mousePosition","fromCenter","anglePerIndex","pointIndex","totalDataArray","./pipelines/pipelines_times.js","__webpack_exports__","Object","defineProperty","$","__WEBPACK_IMPORTED_MODULE_0_vendor_Chart__","__WEBPACK_IMPORTED_MODULE_0_vendor_Chart___default","chartData","JSON","parse","getElementById","innerHTML","get","getContext","scaleOverlay","Bar"],"mappings":"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","file":"pipelines_times.e46dc9aeaebdd9a38964.bundle.js","sourcesContent":["webpackJsonp([\"pipelines_times\"],{\n\n/***/ \"../../../node_modules/webpack/buildin/amd-options.js\":\n/***/ (function(module, exports) {\n\n/* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {/* globals __webpack_amd_options__ */\r\nmodule.exports = __webpack_amd_options__;\r\n\n/* WEBPACK VAR INJECTION */}.call(exports, {}))\n\n/***/ }),\n\n/***/ \"../../../vendor/assets/javascripts/Chart.js\":\n/***/ (function(module, exports, __webpack_require__) {\n\nvar __WEBPACK_AMD_DEFINE_RESULT__;/*!\n * Chart.js\n * http://chartjs.org/\n * Version: 1.0.2\n *\n * Copyright 2015 Nick Downie\n * Released under the MIT license\n * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md\n */\n\n\n(function(){\n\n\t\"use strict\";\n\n\t//Declare root variable - window in the browser, global on the server\n\tvar root = this,\n\t\tprevious = root.Chart;\n\n\t//Occupy the global variable of Chart, and create a simple base class\n\tvar Chart = function(context){\n\t\tvar chart = this;\n\t\tthis.canvas = context.canvas;\n\n\t\tthis.ctx = context;\n\n\t\t//Variables global to the chart\n\t\tvar computeDimension = function(element,dimension)\n\t\t{\n\t\t\tif (element['offset'+dimension])\n\t\t\t{\n\t\t\t\treturn element['offset'+dimension];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn document.defaultView.getComputedStyle(element).getPropertyValue(dimension);\n\t\t\t}\n\t\t}\n\n\t\tvar width = this.width = computeDimension(context.canvas,'Width');\n\t\tvar height = this.height = computeDimension(context.canvas,'Height');\n\n\t\t// Firefox requires this to work correctly\n\t\tcontext.canvas.width = width;\n\t\tcontext.canvas.height = height;\n\n\t\tvar width = this.width = context.canvas.width;\n\t\tvar height = this.height = context.canvas.height;\n\t\tthis.aspectRatio = this.width / this.height;\n\t\t//High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.\n\t\thelpers.retinaScale(this);\n\n\t\treturn this;\n\t};\n\t//Globally expose the defaults to allow for user updating/changing\n\tChart.defaults = {\n\t\tglobal: {\n\t\t\t// Boolean - Whether to animate the chart\n\t\t\tanimation: true,\n\n\t\t\t// Number - Number of animation steps\n\t\t\tanimationSteps: 60,\n\n\t\t\t// String - Animation easing effect\n\t\t\tanimationEasing: \"easeOutQuart\",\n\n\t\t\t// Boolean - If we should show the scale at all\n\t\t\tshowScale: true,\n\n\t\t\t// Boolean - If we want to override with a hard coded scale\n\t\t\tscaleOverride: false,\n\n\t\t\t// ** Required if scaleOverride is true **\n\t\t\t// Number - The number of steps in a hard coded scale\n\t\t\tscaleSteps: null,\n\t\t\t// Number - The value jump in the hard coded scale\n\t\t\tscaleStepWidth: null,\n\t\t\t// Number - The scale starting value\n\t\t\tscaleStartValue: null,\n\n\t\t\t// String - Colour of the scale line\n\t\t\tscaleLineColor: \"rgba(0,0,0,.1)\",\n\n\t\t\t// Number - Pixel width of the scale line\n\t\t\tscaleLineWidth: 1,\n\n\t\t\t// Boolean - Whether to show labels on the scale\n\t\t\tscaleShowLabels: true,\n\n\t\t\t// Interpolated JS string - can access value\n\t\t\tscaleLabel: \"<%=value%>\",\n\n\t\t\t// Boolean - Whether the scale should stick to integers, and not show any floats even if drawing space is there\n\t\t\tscaleIntegersOnly: true,\n\n\t\t\t// Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value\n\t\t\tscaleBeginAtZero: false,\n\n\t\t\t// String - Scale label font declaration for the scale label\n\t\t\tscaleFontFamily: \"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif\",\n\n\t\t\t// Number - Scale label font size in pixels\n\t\t\tscaleFontSize: 12,\n\n\t\t\t// String - Scale label font weight style\n\t\t\tscaleFontStyle: \"normal\",\n\n\t\t\t// String - Scale label font colour\n\t\t\tscaleFontColor: \"#666\",\n\n\t\t\t// Boolean - whether or not the chart should be responsive and resize when the browser does.\n\t\t\tresponsive: false,\n\n\t\t\t// Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container\n\t\t\tmaintainAspectRatio: true,\n\n\t\t\t// Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove\n\t\t\tshowTooltips: true,\n\n\t\t\t// Boolean - Determines whether to draw built-in tooltip or call custom tooltip function\n\t\t\tcustomTooltips: false,\n\n\t\t\t// Array - Array of string names to attach tooltip events\n\t\t\ttooltipEvents: [\"mousemove\", \"touchstart\", \"touchmove\", \"mouseout\"],\n\n\t\t\t// String - Tooltip background colour\n\t\t\ttooltipFillColor: \"rgba(0,0,0,0.8)\",\n\n\t\t\t// String - Tooltip label font declaration for the scale label\n\t\t\ttooltipFontFamily: \"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif\",\n\n\t\t\t// Number - Tooltip label font size in pixels\n\t\t\ttooltipFontSize: 14,\n\n\t\t\t// String - Tooltip font weight style\n\t\t\ttooltipFontStyle: \"normal\",\n\n\t\t\t// String - Tooltip label font colour\n\t\t\ttooltipFontColor: \"#fff\",\n\n\t\t\t// String - Tooltip title font declaration for the scale label\n\t\t\ttooltipTitleFontFamily: \"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif\",\n\n\t\t\t// Number - Tooltip title font size in pixels\n\t\t\ttooltipTitleFontSize: 14,\n\n\t\t\t// String - Tooltip title font weight style\n\t\t\ttooltipTitleFontStyle: \"bold\",\n\n\t\t\t// String - Tooltip title font colour\n\t\t\ttooltipTitleFontColor: \"#fff\",\n\n\t\t\t// Number - pixel width of padding around tooltip text\n\t\t\ttooltipYPadding: 6,\n\n\t\t\t// Number - pixel width of padding around tooltip text\n\t\t\ttooltipXPadding: 6,\n\n\t\t\t// Number - Size of the caret on the tooltip\n\t\t\ttooltipCaretSize: 8,\n\n\t\t\t// Number - Pixel radius of the tooltip border\n\t\t\ttooltipCornerRadius: 6,\n\n\t\t\t// Number - Pixel offset from point x to tooltip edge\n\t\t\ttooltipXOffset: 10,\n\n\t\t\t// String - Template string for single tooltips\n\t\t\ttooltipTemplate: \"<%if (label){%><%=label%>: <%}%><%= value %>\",\n\n\t\t\t// String - Template string for single tooltips\n\t\t\tmultiTooltipTemplate: \"<%= value %>\",\n\n\t\t\t// String - Colour behind the legend colour block\n\t\t\tmultiTooltipKeyBackground: '#fff',\n\n\t\t\t// Function - Will fire on animation progression.\n\t\t\tonAnimationProgress: function(){},\n\n\t\t\t// Function - Will fire on animation completion.\n\t\t\tonAnimationComplete: function(){}\n\n\t\t}\n\t};\n\n\t//Create a dictionary of chart types, to allow for extension of existing types\n\tChart.types = {};\n\n\t//Global Chart helpers object for utility methods and classes\n\tvar helpers = Chart.helpers = {};\n\n\t\t//-- Basic js utility methods\n\tvar each = helpers.each = function(loopable,callback,self){\n\t\t\tvar additionalArgs = Array.prototype.slice.call(arguments, 3);\n\t\t\t// Check to see if null or undefined firstly.\n\t\t\tif (loopable){\n\t\t\t\tif (loopable.length === +loopable.length){\n\t\t\t\t\tvar i;\n\t\t\t\t\tfor (i=0; i= 0; i--) {\n\t\t\t\tvar currentItem = arrayToSearch[i];\n\t\t\t\tif (filterCallback(currentItem)){\n\t\t\t\t\treturn currentItem;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tinherits = helpers.inherits = function(extensions){\n\t\t\t//Basic javascript inheritance based on the model created in Backbone.js\n\t\t\tvar parent = this;\n\t\t\tvar ChartElement = (extensions && extensions.hasOwnProperty(\"constructor\")) ? extensions.constructor : function(){ return parent.apply(this, arguments); };\n\n\t\t\tvar Surrogate = function(){ this.constructor = ChartElement;};\n\t\t\tSurrogate.prototype = parent.prototype;\n\t\t\tChartElement.prototype = new Surrogate();\n\n\t\t\tChartElement.extend = inherits;\n\n\t\t\tif (extensions) extend(ChartElement.prototype, extensions);\n\n\t\t\tChartElement.__super__ = parent.prototype;\n\n\t\t\treturn ChartElement;\n\t\t},\n\t\tnoop = helpers.noop = function(){},\n\t\tuid = helpers.uid = (function(){\n\t\t\tvar id=0;\n\t\t\treturn function(){\n\t\t\t\treturn \"chart-\" + id++;\n\t\t\t};\n\t\t})(),\n\t\twarn = helpers.warn = function(str){\n\t\t\t//Method for warning of errors\n\t\t\tif (window.console && typeof window.console.warn == \"function\") console.warn(str);\n\t\t},\n\t\tamd = helpers.amd = (\"function\" == 'function' && __webpack_require__(\"../../../node_modules/webpack/buildin/amd-options.js\")),\n\t\t//-- Math methods\n\t\tisNumber = helpers.isNumber = function(n){\n\t\t\treturn !isNaN(parseFloat(n)) && isFinite(n);\n\t\t},\n\t\tmax = helpers.max = function(array){\n\t\t\treturn Math.max.apply( Math, array );\n\t\t},\n\t\tmin = helpers.min = function(array){\n\t\t\treturn Math.min.apply( Math, array );\n\t\t},\n\t\tcap = helpers.cap = function(valueToCap,maxValue,minValue){\n\t\t\tif(isNumber(maxValue)) {\n\t\t\t\tif( valueToCap > maxValue ) {\n\t\t\t\t\treturn maxValue;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(isNumber(minValue)){\n\t\t\t\tif ( valueToCap < minValue ){\n\t\t\t\t\treturn minValue;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn valueToCap;\n\t\t},\n\t\tgetDecimalPlaces = helpers.getDecimalPlaces = function(num){\n\t\t\tif (num%1!==0 && isNumber(num)){\n\t\t\t\treturn num.toString().split(\".\")[1].length;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t},\n\t\ttoRadians = helpers.radians = function(degrees){\n\t\t\treturn degrees * (Math.PI/180);\n\t\t},\n\t\t// Gets the angle from vertical upright to the point about a centre.\n\t\tgetAngleFromPoint = helpers.getAngleFromPoint = function(centrePoint, anglePoint){\n\t\t\tvar distanceFromXCenter = anglePoint.x - centrePoint.x,\n\t\t\t\tdistanceFromYCenter = anglePoint.y - centrePoint.y,\n\t\t\t\tradialDistanceFromCenter = Math.sqrt( distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);\n\n\n\t\t\tvar angle = Math.PI * 2 + Math.atan2(distanceFromYCenter, distanceFromXCenter);\n\n\t\t\t//If the segment is in the top left quadrant, we need to add another rotation to the angle\n\t\t\tif (distanceFromXCenter < 0 && distanceFromYCenter < 0){\n\t\t\t\tangle += Math.PI*2;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tangle: angle,\n\t\t\t\tdistance: radialDistanceFromCenter\n\t\t\t};\n\t\t},\n\t\taliasPixel = helpers.aliasPixel = function(pixelWidth){\n\t\t\treturn (pixelWidth % 2 === 0) ? 0 : 0.5;\n\t\t},\n\t\tsplineCurve = helpers.splineCurve = function(FirstPoint,MiddlePoint,AfterPoint,t){\n\t\t\t//Props to Rob Spencer at scaled innovation for his post on splining between points\n\t\t\t//http://scaledinnovation.com/analytics/splines/aboutSplines.html\n\t\t\tvar d01=Math.sqrt(Math.pow(MiddlePoint.x-FirstPoint.x,2)+Math.pow(MiddlePoint.y-FirstPoint.y,2)),\n\t\t\t\td12=Math.sqrt(Math.pow(AfterPoint.x-MiddlePoint.x,2)+Math.pow(AfterPoint.y-MiddlePoint.y,2)),\n\t\t\t\tfa=t*d01/(d01+d12),// scaling factor for triangle Ta\n\t\t\t\tfb=t*d12/(d01+d12);\n\t\t\treturn {\n\t\t\t\tinner : {\n\t\t\t\t\tx : MiddlePoint.x-fa*(AfterPoint.x-FirstPoint.x),\n\t\t\t\t\ty : MiddlePoint.y-fa*(AfterPoint.y-FirstPoint.y)\n\t\t\t\t},\n\t\t\t\touter : {\n\t\t\t\t\tx: MiddlePoint.x+fb*(AfterPoint.x-FirstPoint.x),\n\t\t\t\t\ty : MiddlePoint.y+fb*(AfterPoint.y-FirstPoint.y)\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\tcalculateOrderOfMagnitude = helpers.calculateOrderOfMagnitude = function(val){\n\t\t\treturn Math.floor(Math.log(val) / Math.LN10);\n\t\t},\n\t\tcalculateScaleRange = helpers.calculateScaleRange = function(valuesArray, drawingSize, textSize, startFromZero, integersOnly){\n\n\t\t\t//Set a minimum step of two - a point at the top of the graph, and a point at the base\n\t\t\tvar minSteps = 2,\n\t\t\t\tmaxSteps = Math.floor(drawingSize/(textSize * 1.5)),\n\t\t\t\tskipFitting = (minSteps >= maxSteps);\n\n\t\t\tvar maxValue = max(valuesArray),\n\t\t\t\tminValue = min(valuesArray);\n\n\t\t\t// We need some degree of seperation here to calculate the scales if all the values are the same\n\t\t\t// Adding/minusing 0.5 will give us a range of 1.\n\t\t\tif (maxValue === minValue){\n\t\t\t\tmaxValue += 0.5;\n\t\t\t\t// So we don't end up with a graph with a negative start value if we've said always start from zero\n\t\t\t\tif (minValue >= 0.5 && !startFromZero){\n\t\t\t\t\tminValue -= 0.5;\n\t\t\t\t}\n\t\t\t\telse{\n\t\t\t\t\t// Make up a whole number above the values\n\t\t\t\t\tmaxValue += 0.5;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar\tvalueRange = Math.abs(maxValue - minValue),\n\t\t\t\trangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange),\n\t\t\t\tgraphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),\n\t\t\t\tgraphMin = (startFromZero) ? 0 : Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),\n\t\t\t\tgraphRange = graphMax - graphMin,\n\t\t\t\tstepValue = Math.pow(10, rangeOrderOfMagnitude),\n\t\t\t\tnumberOfSteps = Math.round(graphRange / stepValue);\n\n\t\t\t//If we have more space on the graph we'll use it to give more definition to the data\n\t\t\twhile((numberOfSteps > maxSteps || (numberOfSteps * 2) < maxSteps) && !skipFitting) {\n\t\t\t\tif(numberOfSteps > maxSteps){\n\t\t\t\t\tstepValue *=2;\n\t\t\t\t\tnumberOfSteps = Math.round(graphRange/stepValue);\n\t\t\t\t\t// Don't ever deal with a decimal number of steps - cancel fitting and just use the minimum number of steps.\n\t\t\t\t\tif (numberOfSteps % 1 !== 0){\n\t\t\t\t\t\tskipFitting = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t//We can fit in double the amount of scale points on the scale\n\t\t\t\telse{\n\t\t\t\t\t//If user has declared ints only, and the step value isn't a decimal\n\t\t\t\t\tif (integersOnly && rangeOrderOfMagnitude >= 0){\n\t\t\t\t\t\t//If the user has said integers only, we need to check that making the scale more granular wouldn't make it a float\n\t\t\t\t\t\tif(stepValue/2 % 1 === 0){\n\t\t\t\t\t\t\tstepValue /=2;\n\t\t\t\t\t\t\tnumberOfSteps = Math.round(graphRange/stepValue);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//If it would make it a float break out of the loop\n\t\t\t\t\t\telse{\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//If the scale doesn't have to be an int, make the scale more granular anyway.\n\t\t\t\t\telse{\n\t\t\t\t\t\tstepValue /=2;\n\t\t\t\t\t\tnumberOfSteps = Math.round(graphRange/stepValue);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (skipFitting){\n\t\t\t\tnumberOfSteps = minSteps;\n\t\t\t\tstepValue = graphRange / numberOfSteps;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tsteps : numberOfSteps,\n\t\t\t\tstepValue : stepValue,\n\t\t\t\tmin : graphMin,\n\t\t\t\tmax\t: graphMin + (numberOfSteps * stepValue)\n\t\t\t};\n\n\t\t},\n\t\t/* jshint ignore:start */\n\t\t// Blows up jshint errors based on the new Function constructor\n\t\t//Templating methods\n\t\t//Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/\n\t\ttemplate = helpers.template = function(templateString, valuesObject){\n\n\t\t\t// If templateString is function rather than string-template - call the function for valuesObject\n\n\t\t\tif(templateString instanceof Function){\n\t\t\t \treturn templateString(valuesObject);\n\t\t \t}\n\n\t\t\tvar cache = {};\n\t\t\tfunction tmpl(str, data){\n\t\t\t\t// Figure out if we're getting a template, or if we need to\n\t\t\t\t// load the template - and be sure to cache the result.\n\t\t\t\tvar fn = !/\\W/.test(str) ?\n\t\t\t\tcache[str] = cache[str] :\n\n\t\t\t\t// Generate a reusable function that will serve as a template\n\t\t\t\t// generator (and which will be cached).\n\t\t\t\tnew Function(\"obj\",\n\t\t\t\t\t\"var p=[],print=function(){p.push.apply(p,arguments);};\" +\n\n\t\t\t\t\t// Introduce the data as local variables using with(){}\n\t\t\t\t\t\"with(obj){p.push('\" +\n\n\t\t\t\t\t// Convert the template into pure JavaScript\n\t\t\t\t\tstr\n\t\t\t\t\t\t.replace(/[\\r\\t\\n]/g, \" \")\n\t\t\t\t\t\t.split(\"<%\").join(\"\\t\")\n\t\t\t\t\t\t.replace(/((^|%>)[^\\t]*)'/g, \"$1\\r\")\n\t\t\t\t\t\t.replace(/\\t=(.*?)%>/g, \"',$1,'\")\n\t\t\t\t\t\t.split(\"\\t\").join(\"');\")\n\t\t\t\t\t\t.split(\"%>\").join(\"p.push('\")\n\t\t\t\t\t\t.split(\"\\r\").join(\"\\\\'\") +\n\t\t\t\t\t\"');}return p.join('');\"\n\t\t\t\t);\n\n\t\t\t\t// Provide some basic currying to the user\n\t\t\t\treturn data ? fn( data ) : fn;\n\t\t\t}\n\t\t\treturn tmpl(templateString,valuesObject);\n\t\t},\n\t\t/* jshint ignore:end */\n\t\tgenerateLabels = helpers.generateLabels = function(templateString,numberOfSteps,graphMin,stepValue){\n\t\t\tvar labelsArray = new Array(numberOfSteps);\n\t\t\tif (labelTemplateString){\n\t\t\t\teach(labelsArray,function(val,index){\n\t\t\t\t\tlabelsArray[index] = template(templateString,{value: (graphMin + (stepValue*(index+1)))});\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn labelsArray;\n\t\t},\n\t\t//--Animation methods\n\t\t//Easing functions adapted from Robert Penner's easing equations\n\t\t//http://www.robertpenner.com/easing/\n\t\teasingEffects = helpers.easingEffects = {\n\t\t\tlinear: function (t) {\n\t\t\t\treturn t;\n\t\t\t},\n\t\t\teaseInQuad: function (t) {\n\t\t\t\treturn t * t;\n\t\t\t},\n\t\t\teaseOutQuad: function (t) {\n\t\t\t\treturn -1 * t * (t - 2);\n\t\t\t},\n\t\t\teaseInOutQuad: function (t) {\n\t\t\t\tif ((t /= 1 / 2) < 1) return 1 / 2 * t * t;\n\t\t\t\treturn -1 / 2 * ((--t) * (t - 2) - 1);\n\t\t\t},\n\t\t\teaseInCubic: function (t) {\n\t\t\t\treturn t * t * t;\n\t\t\t},\n\t\t\teaseOutCubic: function (t) {\n\t\t\t\treturn 1 * ((t = t / 1 - 1) * t * t + 1);\n\t\t\t},\n\t\t\teaseInOutCubic: function (t) {\n\t\t\t\tif ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t;\n\t\t\t\treturn 1 / 2 * ((t -= 2) * t * t + 2);\n\t\t\t},\n\t\t\teaseInQuart: function (t) {\n\t\t\t\treturn t * t * t * t;\n\t\t\t},\n\t\t\teaseOutQuart: function (t) {\n\t\t\t\treturn -1 * ((t = t / 1 - 1) * t * t * t - 1);\n\t\t\t},\n\t\t\teaseInOutQuart: function (t) {\n\t\t\t\tif ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t;\n\t\t\t\treturn -1 / 2 * ((t -= 2) * t * t * t - 2);\n\t\t\t},\n\t\t\teaseInQuint: function (t) {\n\t\t\t\treturn 1 * (t /= 1) * t * t * t * t;\n\t\t\t},\n\t\t\teaseOutQuint: function (t) {\n\t\t\t\treturn 1 * ((t = t / 1 - 1) * t * t * t * t + 1);\n\t\t\t},\n\t\t\teaseInOutQuint: function (t) {\n\t\t\t\tif ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t * t;\n\t\t\t\treturn 1 / 2 * ((t -= 2) * t * t * t * t + 2);\n\t\t\t},\n\t\t\teaseInSine: function (t) {\n\t\t\t\treturn -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1;\n\t\t\t},\n\t\t\teaseOutSine: function (t) {\n\t\t\t\treturn 1 * Math.sin(t / 1 * (Math.PI / 2));\n\t\t\t},\n\t\t\teaseInOutSine: function (t) {\n\t\t\t\treturn -1 / 2 * (Math.cos(Math.PI * t / 1) - 1);\n\t\t\t},\n\t\t\teaseInExpo: function (t) {\n\t\t\t\treturn (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1));\n\t\t\t},\n\t\t\teaseOutExpo: function (t) {\n\t\t\t\treturn (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1);\n\t\t\t},\n\t\t\teaseInOutExpo: function (t) {\n\t\t\t\tif (t === 0) return 0;\n\t\t\t\tif (t === 1) return 1;\n\t\t\t\tif ((t /= 1 / 2) < 1) return 1 / 2 * Math.pow(2, 10 * (t - 1));\n\t\t\t\treturn 1 / 2 * (-Math.pow(2, -10 * --t) + 2);\n\t\t\t},\n\t\t\teaseInCirc: function (t) {\n\t\t\t\tif (t >= 1) return t;\n\t\t\t\treturn -1 * (Math.sqrt(1 - (t /= 1) * t) - 1);\n\t\t\t},\n\t\t\teaseOutCirc: function (t) {\n\t\t\t\treturn 1 * Math.sqrt(1 - (t = t / 1 - 1) * t);\n\t\t\t},\n\t\t\teaseInOutCirc: function (t) {\n\t\t\t\tif ((t /= 1 / 2) < 1) return -1 / 2 * (Math.sqrt(1 - t * t) - 1);\n\t\t\t\treturn 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);\n\t\t\t},\n\t\t\teaseInElastic: function (t) {\n\t\t\t\tvar s = 1.70158;\n\t\t\t\tvar p = 0;\n\t\t\t\tvar a = 1;\n\t\t\t\tif (t === 0) return 0;\n\t\t\t\tif ((t /= 1) == 1) return 1;\n\t\t\t\tif (!p) p = 1 * 0.3;\n\t\t\t\tif (a < Math.abs(1)) {\n\t\t\t\t\ta = 1;\n\t\t\t\t\ts = p / 4;\n\t\t\t\t} else s = p / (2 * Math.PI) * Math.asin(1 / a);\n\t\t\t\treturn -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));\n\t\t\t},\n\t\t\teaseOutElastic: function (t) {\n\t\t\t\tvar s = 1.70158;\n\t\t\t\tvar p = 0;\n\t\t\t\tvar a = 1;\n\t\t\t\tif (t === 0) return 0;\n\t\t\t\tif ((t /= 1) == 1) return 1;\n\t\t\t\tif (!p) p = 1 * 0.3;\n\t\t\t\tif (a < Math.abs(1)) {\n\t\t\t\t\ta = 1;\n\t\t\t\t\ts = p / 4;\n\t\t\t\t} else s = p / (2 * Math.PI) * Math.asin(1 / a);\n\t\t\t\treturn a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;\n\t\t\t},\n\t\t\teaseInOutElastic: function (t) {\n\t\t\t\tvar s = 1.70158;\n\t\t\t\tvar p = 0;\n\t\t\t\tvar a = 1;\n\t\t\t\tif (t === 0) return 0;\n\t\t\t\tif ((t /= 1 / 2) == 2) return 1;\n\t\t\t\tif (!p) p = 1 * (0.3 * 1.5);\n\t\t\t\tif (a < Math.abs(1)) {\n\t\t\t\t\ta = 1;\n\t\t\t\t\ts = p / 4;\n\t\t\t\t} else s = p / (2 * Math.PI) * Math.asin(1 / a);\n\t\t\t\tif (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));\n\t\t\t\treturn a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1;\n\t\t\t},\n\t\t\teaseInBack: function (t) {\n\t\t\t\tvar s = 1.70158;\n\t\t\t\treturn 1 * (t /= 1) * t * ((s + 1) * t - s);\n\t\t\t},\n\t\t\teaseOutBack: function (t) {\n\t\t\t\tvar s = 1.70158;\n\t\t\t\treturn 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1);\n\t\t\t},\n\t\t\teaseInOutBack: function (t) {\n\t\t\t\tvar s = 1.70158;\n\t\t\t\tif ((t /= 1 / 2) < 1) return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s));\n\t\t\t\treturn 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);\n\t\t\t},\n\t\t\teaseInBounce: function (t) {\n\t\t\t\treturn 1 - easingEffects.easeOutBounce(1 - t);\n\t\t\t},\n\t\t\teaseOutBounce: function (t) {\n\t\t\t\tif ((t /= 1) < (1 / 2.75)) {\n\t\t\t\t\treturn 1 * (7.5625 * t * t);\n\t\t\t\t} else if (t < (2 / 2.75)) {\n\t\t\t\t\treturn 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75);\n\t\t\t\t} else if (t < (2.5 / 2.75)) {\n\t\t\t\t\treturn 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375);\n\t\t\t\t} else {\n\t\t\t\t\treturn 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375);\n\t\t\t\t}\n\t\t\t},\n\t\t\teaseInOutBounce: function (t) {\n\t\t\t\tif (t < 1 / 2) return easingEffects.easeInBounce(t * 2) * 0.5;\n\t\t\t\treturn easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5;\n\t\t\t}\n\t\t},\n\t\t//Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/\n\t\trequestAnimFrame = helpers.requestAnimFrame = (function(){\n\t\t\treturn window.requestAnimationFrame ||\n\t\t\t\twindow.webkitRequestAnimationFrame ||\n\t\t\t\twindow.mozRequestAnimationFrame ||\n\t\t\t\twindow.oRequestAnimationFrame ||\n\t\t\t\twindow.msRequestAnimationFrame ||\n\t\t\t\tfunction(callback) {\n\t\t\t\t\treturn window.setTimeout(callback, 1000 / 60);\n\t\t\t\t};\n\t\t})(),\n\t\tcancelAnimFrame = helpers.cancelAnimFrame = (function(){\n\t\t\treturn window.cancelAnimationFrame ||\n\t\t\t\twindow.webkitCancelAnimationFrame ||\n\t\t\t\twindow.mozCancelAnimationFrame ||\n\t\t\t\twindow.oCancelAnimationFrame ||\n\t\t\t\twindow.msCancelAnimationFrame ||\n\t\t\t\tfunction(callback) {\n\t\t\t\t\treturn window.clearTimeout(callback, 1000 / 60);\n\t\t\t\t};\n\t\t})(),\n\t\tanimationLoop = helpers.animationLoop = function(callback,totalSteps,easingString,onProgress,onComplete,chartInstance){\n\n\t\t\tvar currentStep = 0,\n\t\t\t\teasingFunction = easingEffects[easingString] || easingEffects.linear;\n\n\t\t\tvar animationFrame = function(){\n\t\t\t\tcurrentStep++;\n\t\t\t\tvar stepDecimal = currentStep/totalSteps;\n\t\t\t\tvar easeDecimal = easingFunction(stepDecimal);\n\n\t\t\t\tcallback.call(chartInstance,easeDecimal,stepDecimal, currentStep);\n\t\t\t\tonProgress.call(chartInstance,easeDecimal,stepDecimal);\n\t\t\t\tif (currentStep < totalSteps){\n\t\t\t\t\tchartInstance.animationFrame = requestAnimFrame(animationFrame);\n\t\t\t\t} else{\n\t\t\t\t\tonComplete.apply(chartInstance);\n\t\t\t\t}\n\t\t\t};\n\t\t\trequestAnimFrame(animationFrame);\n\t\t},\n\t\t//-- DOM methods\n\t\tgetRelativePosition = helpers.getRelativePosition = function(evt){\n\t\t\tvar mouseX, mouseY;\n\t\t\tvar e = evt.originalEvent || evt,\n\t\t\t\tcanvas = evt.currentTarget || evt.srcElement,\n\t\t\t\tboundingRect = canvas.getBoundingClientRect();\n\n\t\t\tif (e.touches){\n\t\t\t\tmouseX = e.touches[0].clientX - boundingRect.left;\n\t\t\t\tmouseY = e.touches[0].clientY - boundingRect.top;\n\n\t\t\t}\n\t\t\telse{\n\t\t\t\tmouseX = e.clientX - boundingRect.left;\n\t\t\t\tmouseY = e.clientY - boundingRect.top;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tx : mouseX,\n\t\t\t\ty : mouseY\n\t\t\t};\n\n\t\t},\n\t\taddEvent = helpers.addEvent = function(node,eventType,method){\n\t\t\tif (node.addEventListener){\n\t\t\t\tnode.addEventListener(eventType,method);\n\t\t\t} else if (node.attachEvent){\n\t\t\t\tnode.attachEvent(\"on\"+eventType, method);\n\t\t\t} else {\n\t\t\t\tnode[\"on\"+eventType] = method;\n\t\t\t}\n\t\t},\n\t\tremoveEvent = helpers.removeEvent = function(node, eventType, handler){\n\t\t\tif (node.removeEventListener){\n\t\t\t\tnode.removeEventListener(eventType, handler, false);\n\t\t\t} else if (node.detachEvent){\n\t\t\t\tnode.detachEvent(\"on\"+eventType,handler);\n\t\t\t} else{\n\t\t\t\tnode[\"on\" + eventType] = noop;\n\t\t\t}\n\t\t},\n\t\tbindEvents = helpers.bindEvents = function(chartInstance, arrayOfEvents, handler){\n\t\t\t// Create the events object if it's not already present\n\t\t\tif (!chartInstance.events) chartInstance.events = {};\n\n\t\t\teach(arrayOfEvents,function(eventName){\n\t\t\t\tchartInstance.events[eventName] = function(){\n\t\t\t\t\thandler.apply(chartInstance, arguments);\n\t\t\t\t};\n\t\t\t\taddEvent(chartInstance.chart.canvas,eventName,chartInstance.events[eventName]);\n\t\t\t});\n\t\t},\n\t\tunbindEvents = helpers.unbindEvents = function (chartInstance, arrayOfEvents) {\n\t\t\teach(arrayOfEvents, function(handler,eventName){\n\t\t\t\tremoveEvent(chartInstance.chart.canvas, eventName, handler);\n\t\t\t});\n\t\t},\n\t\tgetMaximumWidth = helpers.getMaximumWidth = function(domNode){\n\t\t\tvar container = domNode.parentNode;\n\t\t\t// TODO = check cross browser stuff with this.\n\t\t\treturn container.clientWidth;\n\t\t},\n\t\tgetMaximumHeight = helpers.getMaximumHeight = function(domNode){\n\t\t\tvar container = domNode.parentNode;\n\t\t\t// TODO = check cross browser stuff with this.\n\t\t\treturn container.clientHeight;\n\t\t},\n\t\tgetMaximumSize = helpers.getMaximumSize = helpers.getMaximumWidth, // legacy support\n\t\tretinaScale = helpers.retinaScale = function(chart){\n\t\t\tvar ctx = chart.ctx,\n\t\t\t\twidth = chart.canvas.width,\n\t\t\t\theight = chart.canvas.height;\n\n\t\t\tif (window.devicePixelRatio) {\n\t\t\t\tctx.canvas.style.width = width + \"px\";\n\t\t\t\tctx.canvas.style.height = height + \"px\";\n\t\t\t\tctx.canvas.height = height * window.devicePixelRatio;\n\t\t\t\tctx.canvas.width = width * window.devicePixelRatio;\n\t\t\t\tctx.scale(window.devicePixelRatio, window.devicePixelRatio);\n\t\t\t}\n\t\t},\n\t\t//-- Canvas methods\n\t\tclear = helpers.clear = function(chart){\n\t\t\tchart.ctx.clearRect(0,0,chart.width,chart.height);\n\t\t},\n\t\tfontString = helpers.fontString = function(pixelSize,fontStyle,fontFamily){\n\t\t\treturn fontStyle + \" \" + pixelSize+\"px \" + fontFamily;\n\t\t},\n\t\tlongestText = helpers.longestText = function(ctx,font,arrayOfStrings){\n\t\t\tctx.font = font;\n\t\t\tvar longest = 0;\n\t\t\teach(arrayOfStrings,function(string){\n\t\t\t\tvar textWidth = ctx.measureText(string).width;\n\t\t\t\tlongest = (textWidth > longest) ? textWidth : longest;\n\t\t\t});\n\t\t\treturn longest;\n\t\t},\n\t\tdrawRoundedRectangle = helpers.drawRoundedRectangle = function(ctx,x,y,width,height,radius){\n\t\t\tctx.beginPath();\n\t\t\tctx.moveTo(x + radius, y);\n\t\t\tctx.lineTo(x + width - radius, y);\n\t\t\tctx.quadraticCurveTo(x + width, y, x + width, y + radius);\n\t\t\tctx.lineTo(x + width, y + height - radius);\n\t\t\tctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\n\t\t\tctx.lineTo(x + radius, y + height);\n\t\t\tctx.quadraticCurveTo(x, y + height, x, y + height - radius);\n\t\t\tctx.lineTo(x, y + radius);\n\t\t\tctx.quadraticCurveTo(x, y, x + radius, y);\n\t\t\tctx.closePath();\n\t\t};\n\n\n\t//Store a reference to each instance - allowing us to globally resize chart instances on window resize.\n\t//Destroy method on the chart will remove the instance of the chart from this reference.\n\tChart.instances = {};\n\n\tChart.Type = function(data,options,chart){\n\t\tthis.options = options;\n\t\tthis.chart = chart;\n\t\tthis.id = uid();\n\t\t//Add the chart instance to the global namespace\n\t\tChart.instances[this.id] = this;\n\n\t\t// Initialize is always called when a chart type is created\n\t\t// By default it is a no op, but it should be extended\n\t\tif (options.responsive){\n\t\t\tthis.resize();\n\t\t}\n\t\tthis.initialize.call(this,data);\n\t};\n\n\t//Core methods that'll be a part of every chart type\n\textend(Chart.Type.prototype,{\n\t\tinitialize : function(){return this;},\n\t\tclear : function(){\n\t\t\tclear(this.chart);\n\t\t\treturn this;\n\t\t},\n\t\tstop : function(){\n\t\t\t// Stops any current animation loop occuring\n\t\t\tcancelAnimFrame(this.animationFrame);\n\t\t\treturn this;\n\t\t},\n\t\tresize : function(callback){\n\t\t\tthis.stop();\n\t\t\tvar canvas = this.chart.canvas,\n\t\t\t\tnewWidth = getMaximumWidth(this.chart.canvas),\n\t\t\t\tnewHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : getMaximumHeight(this.chart.canvas);\n\n\t\t\tcanvas.width = this.chart.width = newWidth;\n\t\t\tcanvas.height = this.chart.height = newHeight;\n\n\t\t\tretinaScale(this.chart);\n\n\t\t\tif (typeof callback === \"function\"){\n\t\t\t\tcallback.apply(this, Array.prototype.slice.call(arguments, 1));\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\t\treflow : noop,\n\t\trender : function(reflow){\n\t\t\tif (reflow){\n\t\t\t\tthis.reflow();\n\t\t\t}\n\t\t\tif (this.options.animation && !reflow){\n\t\t\t\thelpers.animationLoop(\n\t\t\t\t\tthis.draw,\n\t\t\t\t\tthis.options.animationSteps,\n\t\t\t\t\tthis.options.animationEasing,\n\t\t\t\t\tthis.options.onAnimationProgress,\n\t\t\t\t\tthis.options.onAnimationComplete,\n\t\t\t\t\tthis\n\t\t\t\t);\n\t\t\t}\n\t\t\telse{\n\t\t\t\tthis.draw();\n\t\t\t\tthis.options.onAnimationComplete.call(this);\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\t\tgenerateLegend : function(){\n\t\t\treturn template(this.options.legendTemplate,this);\n\t\t},\n\t\tdestroy : function(){\n\t\t\tthis.clear();\n\t\t\tunbindEvents(this, this.events);\n\t\t\tvar canvas = this.chart.canvas;\n\n\t\t\t// Reset canvas height/width attributes starts a fresh with the canvas context\n\t\t\tcanvas.width = this.chart.width;\n\t\t\tcanvas.height = this.chart.height;\n\n\t\t\t// < IE9 doesn't support removeProperty\n\t\t\tif (canvas.style.removeProperty) {\n\t\t\t\tcanvas.style.removeProperty('width');\n\t\t\t\tcanvas.style.removeProperty('height');\n\t\t\t} else {\n\t\t\t\tcanvas.style.removeAttribute('width');\n\t\t\t\tcanvas.style.removeAttribute('height');\n\t\t\t}\n\n\t\t\tdelete Chart.instances[this.id];\n\t\t},\n\t\tshowTooltip : function(ChartElements, forceRedraw){\n\t\t\t// Only redraw the chart if we've actually changed what we're hovering on.\n\t\t\tif (typeof this.activeElements === 'undefined') this.activeElements = [];\n\n\t\t\tvar isChanged = (function(Elements){\n\t\t\t\tvar changed = false;\n\n\t\t\t\tif (Elements.length !== this.activeElements.length){\n\t\t\t\t\tchanged = true;\n\t\t\t\t\treturn changed;\n\t\t\t\t}\n\n\t\t\t\teach(Elements, function(element, index){\n\t\t\t\t\tif (element !== this.activeElements[index]){\n\t\t\t\t\t\tchanged = true;\n\t\t\t\t\t}\n\t\t\t\t}, this);\n\t\t\t\treturn changed;\n\t\t\t}).call(this, ChartElements);\n\n\t\t\tif (!isChanged && !forceRedraw){\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse{\n\t\t\t\tthis.activeElements = ChartElements;\n\t\t\t}\n\t\t\tthis.draw();\n\t\t\tif(this.options.customTooltips){\n\t\t\t\tthis.options.customTooltips(false);\n\t\t\t}\n\t\t\tif (ChartElements.length > 0){\n\t\t\t\t// If we have multiple datasets, show a MultiTooltip for all of the data points at that index\n\t\t\t\tif (this.datasets && this.datasets.length > 1) {\n\t\t\t\t\tvar dataArray,\n\t\t\t\t\t\tdataIndex;\n\n\t\t\t\t\tfor (var i = this.datasets.length - 1; i >= 0; i--) {\n\t\t\t\t\t\tdataArray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments;\n\t\t\t\t\t\tdataIndex = indexOf(dataArray, ChartElements[0]);\n\t\t\t\t\t\tif (dataIndex !== -1){\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tvar tooltipLabels = [],\n\t\t\t\t\t\ttooltipColors = [],\n\t\t\t\t\t\tmedianPosition = (function(index) {\n\n\t\t\t\t\t\t\t// Get all the points at that particular index\n\t\t\t\t\t\t\tvar Elements = [],\n\t\t\t\t\t\t\t\tdataCollection,\n\t\t\t\t\t\t\t\txPositions = [],\n\t\t\t\t\t\t\t\tyPositions = [],\n\t\t\t\t\t\t\t\txMax,\n\t\t\t\t\t\t\t\tyMax,\n\t\t\t\t\t\t\t\txMin,\n\t\t\t\t\t\t\t\tyMin;\n\t\t\t\t\t\t\thelpers.each(this.datasets, function(dataset){\n\t\t\t\t\t\t\t\tdataCollection = dataset.points || dataset.bars || dataset.segments;\n\t\t\t\t\t\t\t\tif (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){\n\t\t\t\t\t\t\t\t\tElements.push(dataCollection[dataIndex]);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\thelpers.each(Elements, function(element) {\n\t\t\t\t\t\t\t\txPositions.push(element.x);\n\t\t\t\t\t\t\t\tyPositions.push(element.y);\n\n\n\t\t\t\t\t\t\t\t//Include any colour information about the element\n\t\t\t\t\t\t\t\ttooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element));\n\t\t\t\t\t\t\t\ttooltipColors.push({\n\t\t\t\t\t\t\t\t\tfill: element._saved.fillColor || element.fillColor,\n\t\t\t\t\t\t\t\t\tstroke: element._saved.strokeColor || element.strokeColor\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t}, this);\n\n\t\t\t\t\t\t\tyMin = min(yPositions);\n\t\t\t\t\t\t\tyMax = max(yPositions);\n\n\t\t\t\t\t\t\txMin = min(xPositions);\n\t\t\t\t\t\t\txMax = max(xPositions);\n\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tx: (xMin > this.chart.width/2) ? xMin : xMax,\n\t\t\t\t\t\t\t\ty: (yMin + yMax)/2\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}).call(this, dataIndex);\n\n\t\t\t\t\tnew Chart.MultiTooltip({\n\t\t\t\t\t\tx: medianPosition.x,\n\t\t\t\t\t\ty: medianPosition.y,\n\t\t\t\t\t\txPadding: this.options.tooltipXPadding,\n\t\t\t\t\t\tyPadding: this.options.tooltipYPadding,\n\t\t\t\t\t\txOffset: this.options.tooltipXOffset,\n\t\t\t\t\t\tfillColor: this.options.tooltipFillColor,\n\t\t\t\t\t\ttextColor: this.options.tooltipFontColor,\n\t\t\t\t\t\tfontFamily: this.options.tooltipFontFamily,\n\t\t\t\t\t\tfontStyle: this.options.tooltipFontStyle,\n\t\t\t\t\t\tfontSize: this.options.tooltipFontSize,\n\t\t\t\t\t\ttitleTextColor: this.options.tooltipTitleFontColor,\n\t\t\t\t\t\ttitleFontFamily: this.options.tooltipTitleFontFamily,\n\t\t\t\t\t\ttitleFontStyle: this.options.tooltipTitleFontStyle,\n\t\t\t\t\t\ttitleFontSize: this.options.tooltipTitleFontSize,\n\t\t\t\t\t\tcornerRadius: this.options.tooltipCornerRadius,\n\t\t\t\t\t\tlabels: tooltipLabels,\n\t\t\t\t\t\tlegendColors: tooltipColors,\n\t\t\t\t\t\tlegendColorBackground : this.options.multiTooltipKeyBackground,\n\t\t\t\t\t\ttitle: ChartElements[0].label,\n\t\t\t\t\t\tchart: this.chart,\n\t\t\t\t\t\tctx: this.chart.ctx,\n\t\t\t\t\t\tcustom: this.options.customTooltips\n\t\t\t\t\t}).draw();\n\n\t\t\t\t} else {\n\t\t\t\t\teach(ChartElements, function(Element) {\n\t\t\t\t\t\tvar tooltipPosition = Element.tooltipPosition();\n\t\t\t\t\t\tnew Chart.Tooltip({\n\t\t\t\t\t\t\tx: Math.round(tooltipPosition.x),\n\t\t\t\t\t\t\ty: Math.round(tooltipPosition.y),\n\t\t\t\t\t\t\txPadding: this.options.tooltipXPadding,\n\t\t\t\t\t\t\tyPadding: this.options.tooltipYPadding,\n\t\t\t\t\t\t\tfillColor: this.options.tooltipFillColor,\n\t\t\t\t\t\t\ttextColor: this.options.tooltipFontColor,\n\t\t\t\t\t\t\tfontFamily: this.options.tooltipFontFamily,\n\t\t\t\t\t\t\tfontStyle: this.options.tooltipFontStyle,\n\t\t\t\t\t\t\tfontSize: this.options.tooltipFontSize,\n\t\t\t\t\t\t\tcaretHeight: this.options.tooltipCaretSize,\n\t\t\t\t\t\t\tcornerRadius: this.options.tooltipCornerRadius,\n\t\t\t\t\t\t\ttext: template(this.options.tooltipTemplate, Element),\n\t\t\t\t\t\t\tchart: this.chart,\n\t\t\t\t\t\t\tcustom: this.options.customTooltips\n\t\t\t\t\t\t}).draw();\n\t\t\t\t\t}, this);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\t\ttoBase64Image : function(){\n\t\t\treturn this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);\n\t\t}\n\t});\n\n\tChart.Type.extend = function(extensions){\n\n\t\tvar parent = this;\n\n\t\tvar ChartType = function(){\n\t\t\treturn parent.apply(this,arguments);\n\t\t};\n\n\t\t//Copy the prototype object of the this class\n\t\tChartType.prototype = clone(parent.prototype);\n\t\t//Now overwrite some of the properties in the base class with the new extensions\n\t\textend(ChartType.prototype, extensions);\n\n\t\tChartType.extend = Chart.Type.extend;\n\n\t\tif (extensions.name || parent.prototype.name){\n\n\t\t\tvar chartName = extensions.name || parent.prototype.name;\n\t\t\t//Assign any potential default values of the new chart type\n\n\t\t\t//If none are defined, we'll use a clone of the chart type this is being extended from.\n\t\t\t//I.e. if we extend a line chart, we'll use the defaults from the line chart if our new chart\n\t\t\t//doesn't define some defaults of their own.\n\n\t\t\tvar baseDefaults = (Chart.defaults[parent.prototype.name]) ? clone(Chart.defaults[parent.prototype.name]) : {};\n\n\t\t\tChart.defaults[chartName] = extend(baseDefaults,extensions.defaults);\n\n\t\t\tChart.types[chartName] = ChartType;\n\n\t\t\t//Register this new chart type in the Chart prototype\n\t\t\tChart.prototype[chartName] = function(data,options){\n\t\t\t\tvar config = merge(Chart.defaults.global, Chart.defaults[chartName], options || {});\n\t\t\t\treturn new ChartType(data,config,this);\n\t\t\t};\n\t\t} else{\n\t\t\twarn(\"Name not provided for this chart, so it hasn't been registered\");\n\t\t}\n\t\treturn parent;\n\t};\n\n\tChart.Element = function(configuration){\n\t\textend(this,configuration);\n\t\tthis.initialize.apply(this,arguments);\n\t\tthis.save();\n\t};\n\textend(Chart.Element.prototype,{\n\t\tinitialize : function(){},\n\t\trestore : function(props){\n\t\t\tif (!props){\n\t\t\t\textend(this,this._saved);\n\t\t\t} else {\n\t\t\t\teach(props,function(key){\n\t\t\t\t\tthis[key] = this._saved[key];\n\t\t\t\t},this);\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\t\tsave : function(){\n\t\t\tthis._saved = clone(this);\n\t\t\tdelete this._saved._saved;\n\t\t\treturn this;\n\t\t},\n\t\tupdate : function(newProps){\n\t\t\teach(newProps,function(value,key){\n\t\t\t\tthis._saved[key] = this[key];\n\t\t\t\tthis[key] = value;\n\t\t\t},this);\n\t\t\treturn this;\n\t\t},\n\t\ttransition : function(props,ease){\n\t\t\teach(props,function(value,key){\n\t\t\t\tthis[key] = ((value - this._saved[key]) * ease) + this._saved[key];\n\t\t\t},this);\n\t\t\treturn this;\n\t\t},\n\t\ttooltipPosition : function(){\n\t\t\treturn {\n\t\t\t\tx : this.x,\n\t\t\t\ty : this.y\n\t\t\t};\n\t\t},\n\t\thasValue: function(){\n\t\t\treturn isNumber(this.value);\n\t\t}\n\t});\n\n\tChart.Element.extend = inherits;\n\n\n\tChart.Point = Chart.Element.extend({\n\t\tdisplay: true,\n\t\tinRange: function(chartX,chartY){\n\t\t\tvar hitDetectionRange = this.hitDetectionRadius + this.radius;\n\t\t\treturn ((Math.pow(chartX-this.x, 2)+Math.pow(chartY-this.y, 2)) < Math.pow(hitDetectionRange,2));\n\t\t},\n\t\tdraw : function(){\n\t\t\tif (this.display){\n\t\t\t\tvar ctx = this.ctx;\n\t\t\t\tctx.beginPath();\n\n\t\t\t\tctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);\n\t\t\t\tctx.closePath();\n\n\t\t\t\tctx.strokeStyle = this.strokeColor;\n\t\t\t\tctx.lineWidth = this.strokeWidth;\n\n\t\t\t\tctx.fillStyle = this.fillColor;\n\n\t\t\t\tctx.fill();\n\t\t\t\tctx.stroke();\n\t\t\t}\n\n\n\t\t\t//Quick debug for bezier curve splining\n\t\t\t//Highlights control points and the line between them.\n\t\t\t//Handy for dev - stripped in the min version.\n\n\t\t\t// ctx.save();\n\t\t\t// ctx.fillStyle = \"black\";\n\t\t\t// ctx.strokeStyle = \"black\"\n\t\t\t// ctx.beginPath();\n\t\t\t// ctx.arc(this.controlPoints.inner.x,this.controlPoints.inner.y, 2, 0, Math.PI*2);\n\t\t\t// ctx.fill();\n\n\t\t\t// ctx.beginPath();\n\t\t\t// ctx.arc(this.controlPoints.outer.x,this.controlPoints.outer.y, 2, 0, Math.PI*2);\n\t\t\t// ctx.fill();\n\n\t\t\t// ctx.moveTo(this.controlPoints.inner.x,this.controlPoints.inner.y);\n\t\t\t// ctx.lineTo(this.x, this.y);\n\t\t\t// ctx.lineTo(this.controlPoints.outer.x,this.controlPoints.outer.y);\n\t\t\t// ctx.stroke();\n\n\t\t\t// ctx.restore();\n\n\n\n\t\t}\n\t});\n\n\tChart.Arc = Chart.Element.extend({\n\t\tinRange : function(chartX,chartY){\n\n\t\t\tvar pointRelativePosition = helpers.getAngleFromPoint(this, {\n\t\t\t\tx: chartX,\n\t\t\t\ty: chartY\n\t\t\t});\n\n\t\t\t//Check if within the range of the open/close angle\n\t\t\tvar betweenAngles = (pointRelativePosition.angle >= this.startAngle && pointRelativePosition.angle <= this.endAngle),\n\t\t\t\twithinRadius = (pointRelativePosition.distance >= this.innerRadius && pointRelativePosition.distance <= this.outerRadius);\n\n\t\t\treturn (betweenAngles && withinRadius);\n\t\t\t//Ensure within the outside of the arc centre, but inside arc outer\n\t\t},\n\t\ttooltipPosition : function(){\n\t\t\tvar centreAngle = this.startAngle + ((this.endAngle - this.startAngle) / 2),\n\t\t\t\trangeFromCentre = (this.outerRadius - this.innerRadius) / 2 + this.innerRadius;\n\t\t\treturn {\n\t\t\t\tx : this.x + (Math.cos(centreAngle) * rangeFromCentre),\n\t\t\t\ty : this.y + (Math.sin(centreAngle) * rangeFromCentre)\n\t\t\t};\n\t\t},\n\t\tdraw : function(animationPercent){\n\n\t\t\tvar easingDecimal = animationPercent || 1;\n\n\t\t\tvar ctx = this.ctx;\n\n\t\t\tctx.beginPath();\n\n\t\t\tctx.arc(this.x, this.y, this.outerRadius, this.startAngle, this.endAngle);\n\n\t\t\tctx.arc(this.x, this.y, this.innerRadius, this.endAngle, this.startAngle, true);\n\n\t\t\tctx.closePath();\n\t\t\tctx.strokeStyle = this.strokeColor;\n\t\t\tctx.lineWidth = this.strokeWidth;\n\n\t\t\tctx.fillStyle = this.fillColor;\n\n\t\t\tctx.fill();\n\t\t\tctx.lineJoin = 'bevel';\n\n\t\t\tif (this.showStroke){\n\t\t\t\tctx.stroke();\n\t\t\t}\n\t\t}\n\t});\n\n\tChart.Rectangle = Chart.Element.extend({\n\t\tdraw : function(){\n\t\t\tvar ctx = this.ctx,\n\t\t\t\thalfWidth = this.width/2,\n\t\t\t\tleftX = this.x - halfWidth,\n\t\t\t\trightX = this.x + halfWidth,\n\t\t\t\ttop = this.base - (this.base - this.y),\n\t\t\t\thalfStroke = this.strokeWidth / 2;\n\n\t\t\t// Canvas doesn't allow us to stroke inside the width so we can\n\t\t\t// adjust the sizes to fit if we're setting a stroke on the line\n\t\t\tif (this.showStroke){\n\t\t\t\tleftX += halfStroke;\n\t\t\t\trightX -= halfStroke;\n\t\t\t\ttop += halfStroke;\n\t\t\t}\n\n\t\t\tctx.beginPath();\n\n\t\t\tctx.fillStyle = this.fillColor;\n\t\t\tctx.strokeStyle = this.strokeColor;\n\t\t\tctx.lineWidth = this.strokeWidth;\n\n\t\t\t// It'd be nice to keep this class totally generic to any rectangle\n\t\t\t// and simply specify which border to miss out.\n\t\t\tctx.moveTo(leftX, this.base);\n\t\t\tctx.lineTo(leftX, top);\n\t\t\tctx.lineTo(rightX, top);\n\t\t\tctx.lineTo(rightX, this.base);\n\t\t\tctx.fill();\n\t\t\tif (this.showStroke){\n\t\t\t\tctx.stroke();\n\t\t\t}\n\t\t},\n\t\theight : function(){\n\t\t\treturn this.base - this.y;\n\t\t},\n\t\tinRange : function(chartX,chartY){\n\t\t\treturn (chartX >= this.x - this.width/2 && chartX <= this.x + this.width/2) && (chartY >= this.y && chartY <= this.base);\n\t\t}\n\t});\n\n\tChart.Tooltip = Chart.Element.extend({\n\t\tdraw : function(){\n\n\t\t\tvar ctx = this.chart.ctx;\n\n\t\t\tctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);\n\n\t\t\tthis.xAlign = \"center\";\n\t\t\tthis.yAlign = \"above\";\n\n\t\t\t//Distance between the actual element.y position and the start of the tooltip caret\n\t\t\tvar caretPadding = this.caretPadding = 2;\n\n\t\t\tvar tooltipWidth = ctx.measureText(this.text).width + 2*this.xPadding,\n\t\t\t\ttooltipRectHeight = this.fontSize + 2*this.yPadding,\n\t\t\t\ttooltipHeight = tooltipRectHeight + this.caretHeight + caretPadding;\n\n\t\t\tif (this.x + tooltipWidth/2 >this.chart.width){\n\t\t\t\tthis.xAlign = \"left\";\n\t\t\t} else if (this.x - tooltipWidth/2 < 0){\n\t\t\t\tthis.xAlign = \"right\";\n\t\t\t}\n\n\t\t\tif (this.y - tooltipHeight < 0){\n\t\t\t\tthis.yAlign = \"below\";\n\t\t\t}\n\n\n\t\t\tvar tooltipX = this.x - tooltipWidth/2,\n\t\t\t\ttooltipY = this.y - tooltipHeight;\n\n\t\t\tctx.fillStyle = this.fillColor;\n\n\t\t\t// Custom Tooltips\n\t\t\tif(this.custom){\n\t\t\t\tthis.custom(this);\n\t\t\t}\n\t\t\telse{\n\t\t\t\tswitch(this.yAlign)\n\t\t\t\t{\n\t\t\t\tcase \"above\":\n\t\t\t\t\t//Draw a caret above the x/y\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(this.x,this.y - caretPadding);\n\t\t\t\t\tctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight));\n\t\t\t\t\tctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight));\n\t\t\t\t\tctx.closePath();\n\t\t\t\t\tctx.fill();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"below\":\n\t\t\t\t\ttooltipY = this.y + caretPadding + this.caretHeight;\n\t\t\t\t\t//Draw a caret below the x/y\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(this.x, this.y + caretPadding);\n\t\t\t\t\tctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight);\n\t\t\t\t\tctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight);\n\t\t\t\t\tctx.closePath();\n\t\t\t\t\tctx.fill();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tswitch(this.xAlign)\n\t\t\t\t{\n\t\t\t\tcase \"left\":\n\t\t\t\t\ttooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"right\":\n\t\t\t\t\ttooltipX = this.x - (this.cornerRadius + this.caretHeight);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdrawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius);\n\n\t\t\t\tctx.fill();\n\n\t\t\t\tctx.fillStyle = this.textColor;\n\t\t\t\tctx.textAlign = \"center\";\n\t\t\t\tctx.textBaseline = \"middle\";\n\t\t\t\tctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2);\n\t\t\t}\n\t\t}\n\t});\n\n\tChart.MultiTooltip = Chart.Element.extend({\n\t\tinitialize : function(){\n\t\t\tthis.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);\n\n\t\t\tthis.titleFont = fontString(this.titleFontSize,this.titleFontStyle,this.titleFontFamily);\n\n\t\t\tthis.height = (this.labels.length * this.fontSize) + ((this.labels.length-1) * (this.fontSize/2)) + (this.yPadding*2) + this.titleFontSize *1.5;\n\n\t\t\tthis.ctx.font = this.titleFont;\n\n\t\t\tvar titleWidth = this.ctx.measureText(this.title).width,\n\t\t\t\t//Label has a legend square as well so account for this.\n\t\t\t\tlabelWidth = longestText(this.ctx,this.font,this.labels) + this.fontSize + 3,\n\t\t\t\tlongestTextWidth = max([labelWidth,titleWidth]);\n\n\t\t\tthis.width = longestTextWidth + (this.xPadding*2);\n\n\n\t\t\tvar halfHeight = this.height/2;\n\n\t\t\t//Check to ensure the height will fit on the canvas\n\t\t\tif (this.y - halfHeight < 0 ){\n\t\t\t\tthis.y = halfHeight;\n\t\t\t} else if (this.y + halfHeight > this.chart.height){\n\t\t\t\tthis.y = this.chart.height - halfHeight;\n\t\t\t}\n\n\t\t\t//Decide whether to align left or right based on position on canvas\n\t\t\tif (this.x > this.chart.width/2){\n\t\t\t\tthis.x -= this.xOffset + this.width;\n\t\t\t} else {\n\t\t\t\tthis.x += this.xOffset;\n\t\t\t}\n\n\n\t\t},\n\t\tgetLineHeight : function(index){\n\t\t\tvar baseLineHeight = this.y - (this.height/2) + this.yPadding,\n\t\t\t\tafterTitleIndex = index-1;\n\n\t\t\t//If the index is zero, we're getting the title\n\t\t\tif (index === 0){\n\t\t\t\treturn baseLineHeight + this.titleFontSize/2;\n\t\t\t} else{\n\t\t\t\treturn baseLineHeight + ((this.fontSize*1.5*afterTitleIndex) + this.fontSize/2) + this.titleFontSize * 1.5;\n\t\t\t}\n\n\t\t},\n\t\tdraw : function(){\n\t\t\t// Custom Tooltips\n\t\t\tif(this.custom){\n\t\t\t\tthis.custom(this);\n\t\t\t}\n\t\t\telse{\n\t\t\t\tdrawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius);\n\t\t\t\tvar ctx = this.ctx;\n\t\t\t\tctx.fillStyle = this.fillColor;\n\t\t\t\tctx.fill();\n\t\t\t\tctx.closePath();\n\n\t\t\t\tctx.textAlign = \"left\";\n\t\t\t\tctx.textBaseline = \"middle\";\n\t\t\t\tctx.fillStyle = this.titleTextColor;\n\t\t\t\tctx.font = this.titleFont;\n\n\t\t\t\tctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0));\n\n\t\t\t\tctx.font = this.font;\n\t\t\t\thelpers.each(this.labels,function(label,index){\n\t\t\t\t\tctx.fillStyle = this.textColor;\n\t\t\t\t\tctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1));\n\n\t\t\t\t\t//A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas)\n\t\t\t\t\t//ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);\n\t\t\t\t\t//Instead we'll make a white filled block to put the legendColour palette over.\n\n\t\t\t\t\tctx.fillStyle = this.legendColorBackground;\n\t\t\t\t\tctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);\n\n\t\t\t\t\tctx.fillStyle = this.legendColors[index].fill;\n\t\t\t\t\tctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);\n\n\n\t\t\t\t},this);\n\t\t\t}\n\t\t}\n\t});\n\n\tChart.Scale = Chart.Element.extend({\n\t\tinitialize : function(){\n\t\t\tthis.fit();\n\t\t},\n\t\tbuildYLabels : function(){\n\t\t\tthis.yLabels = [];\n\n\t\t\tvar stepDecimalPlaces = getDecimalPlaces(this.stepValue);\n\n\t\t\tfor (var i=0; i<=this.steps; i++){\n\t\t\t\tthis.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));\n\t\t\t}\n\t\t\tthis.yLabelWidth = (this.display && this.showLabels) ? longestText(this.ctx,this.font,this.yLabels) : 0;\n\t\t},\n\t\taddXLabel : function(label){\n\t\t\tthis.xLabels.push(label);\n\t\t\tthis.valuesCount++;\n\t\t\tthis.fit();\n\t\t},\n\t\tremoveXLabel : function(){\n\t\t\tthis.xLabels.shift();\n\t\t\tthis.valuesCount--;\n\t\t\tthis.fit();\n\t\t},\n\t\t// Fitting loop to rotate x Labels and figure out what fits there, and also calculate how many Y steps to use\n\t\tfit: function(){\n\t\t\t// First we need the width of the yLabels, assuming the xLabels aren't rotated\n\n\t\t\t// To do that we need the base line at the top and base of the chart, assuming there is no x label rotation\n\t\t\tthis.startPoint = (this.display) ? this.fontSize : 0;\n\t\t\tthis.endPoint = (this.display) ? this.height - (this.fontSize * 1.5) - 5 : this.height; // -5 to pad labels\n\n\t\t\t// Apply padding settings to the start and end point.\n\t\t\tthis.startPoint += this.padding;\n\t\t\tthis.endPoint -= this.padding;\n\n\t\t\t// Cache the starting height, so can determine if we need to recalculate the scale yAxis\n\t\t\tvar cachedHeight = this.endPoint - this.startPoint,\n\t\t\t\tcachedYLabelWidth;\n\n\t\t\t// Build the current yLabels so we have an idea of what size they'll be to start\n\t\t\t/*\n\t\t\t *\tThis sets what is returned from calculateScaleRange as static properties of this class:\n\t\t\t *\n\t\t\t\tthis.steps;\n\t\t\t\tthis.stepValue;\n\t\t\t\tthis.min;\n\t\t\t\tthis.max;\n\t\t\t *\n\t\t\t */\n\t\t\tthis.calculateYRange(cachedHeight);\n\n\t\t\t// With these properties set we can now build the array of yLabels\n\t\t\t// and also the width of the largest yLabel\n\t\t\tthis.buildYLabels();\n\n\t\t\tthis.calculateXLabelRotation();\n\n\t\t\twhile((cachedHeight > this.endPoint - this.startPoint)){\n\t\t\t\tcachedHeight = this.endPoint - this.startPoint;\n\t\t\t\tcachedYLabelWidth = this.yLabelWidth;\n\n\t\t\t\tthis.calculateYRange(cachedHeight);\n\t\t\t\tthis.buildYLabels();\n\n\t\t\t\t// Only go through the xLabel loop again if the yLabel width has changed\n\t\t\t\tif (cachedYLabelWidth < this.yLabelWidth){\n\t\t\t\t\tthis.calculateXLabelRotation();\n\t\t\t\t}\n\t\t\t}\n\n\t\t},\n\t\tcalculateXLabelRotation : function(){\n\t\t\t//Get the width of each grid by calculating the difference\n\t\t\t//between x offsets between 0 and 1.\n\n\t\t\tthis.ctx.font = this.font;\n\n\t\t\tvar firstWidth = this.ctx.measureText(this.xLabels[0]).width,\n\t\t\t\tlastWidth = this.ctx.measureText(this.xLabels[this.xLabels.length - 1]).width,\n\t\t\t\tfirstRotated,\n\t\t\t\tlastRotated;\n\n\n\t\t\tthis.xScalePaddingRight = lastWidth/2 + 3;\n\t\t\tthis.xScalePaddingLeft = (firstWidth/2 > this.yLabelWidth + 10) ? firstWidth/2 : this.yLabelWidth + 10;\n\n\t\t\tthis.xLabelRotation = 0;\n\t\t\tif (this.display){\n\t\t\t\tvar originalLabelWidth = longestText(this.ctx,this.font,this.xLabels),\n\t\t\t\t\tcosRotation,\n\t\t\t\t\tfirstRotatedWidth;\n\t\t\t\tthis.xLabelWidth = originalLabelWidth;\n\t\t\t\t//Allow 3 pixels x2 padding either side for label readability\n\t\t\t\tvar xGridWidth = Math.floor(this.calculateX(1) - this.calculateX(0)) - 6;\n\n\t\t\t\t//Max label rotate should be 90 - also act as a loop counter\n\t\t\t\twhile ((this.xLabelWidth > xGridWidth && this.xLabelRotation === 0) || (this.xLabelWidth > xGridWidth && this.xLabelRotation <= 90 && this.xLabelRotation > 0)){\n\t\t\t\t\tcosRotation = Math.cos(toRadians(this.xLabelRotation));\n\n\t\t\t\t\tfirstRotated = cosRotation * firstWidth;\n\t\t\t\t\tlastRotated = cosRotation * lastWidth;\n\n\t\t\t\t\t// We're right aligning the text now.\n\t\t\t\t\tif (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8){\n\t\t\t\t\t\tthis.xScalePaddingLeft = firstRotated + this.fontSize / 2;\n\t\t\t\t\t}\n\t\t\t\t\tthis.xScalePaddingRight = this.fontSize/2;\n\n\n\t\t\t\t\tthis.xLabelRotation++;\n\t\t\t\t\tthis.xLabelWidth = cosRotation * originalLabelWidth;\n\n\t\t\t\t}\n\t\t\t\tif (this.xLabelRotation > 0){\n\t\t\t\t\tthis.endPoint -= Math.sin(toRadians(this.xLabelRotation))*originalLabelWidth + 3;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse{\n\t\t\t\tthis.xLabelWidth = 0;\n\t\t\t\tthis.xScalePaddingRight = this.padding;\n\t\t\t\tthis.xScalePaddingLeft = this.padding;\n\t\t\t}\n\n\t\t},\n\t\t// Needs to be overidden in each Chart type\n\t\t// Otherwise we need to pass all the data into the scale class\n\t\tcalculateYRange: noop,\n\t\tdrawingArea: function(){\n\t\t\treturn this.startPoint - this.endPoint;\n\t\t},\n\t\tcalculateY : function(value){\n\t\t\tvar scalingFactor = this.drawingArea() / (this.min - this.max);\n\t\t\treturn this.endPoint - (scalingFactor * (value - this.min));\n\t\t},\n\t\tcalculateX : function(index){\n\t\t\tvar isRotated = (this.xLabelRotation > 0),\n\t\t\t\t// innerWidth = (this.offsetGridLines) ? this.width - offsetLeft - this.padding : this.width - (offsetLeft + halfLabelWidth * 2) - this.padding,\n\t\t\t\tinnerWidth = this.width - (this.xScalePaddingLeft + this.xScalePaddingRight),\n\t\t\t\tvalueWidth = innerWidth/Math.max((this.valuesCount - ((this.offsetGridLines) ? 0 : 1)), 1),\n\t\t\t\tvalueOffset = (valueWidth * index) + this.xScalePaddingLeft;\n\n\t\t\tif (this.offsetGridLines){\n\t\t\t\tvalueOffset += (valueWidth/2);\n\t\t\t}\n\n\t\t\treturn Math.round(valueOffset);\n\t\t},\n\t\tupdate : function(newProps){\n\t\t\thelpers.extend(this, newProps);\n\t\t\tthis.fit();\n\t\t},\n\t\tdraw : function(){\n\t\t\tvar ctx = this.ctx,\n\t\t\t\tyLabelGap = (this.endPoint - this.startPoint) / this.steps,\n\t\t\t\txStart = Math.round(this.xScalePaddingLeft);\n\t\t\tif (this.display){\n\t\t\t\tctx.fillStyle = this.textColor;\n\t\t\t\tctx.font = this.font;\n\t\t\t\teach(this.yLabels,function(labelString,index){\n\t\t\t\t\tvar yLabelCenter = this.endPoint - (yLabelGap * index),\n\t\t\t\t\t\tlinePositionY = Math.round(yLabelCenter),\n\t\t\t\t\t\tdrawHorizontalLine = this.showHorizontalLines;\n\n\t\t\t\t\tctx.textAlign = \"right\";\n\t\t\t\t\tctx.textBaseline = \"middle\";\n\t\t\t\t\tif (this.showLabels){\n\t\t\t\t\t\tctx.fillText(labelString,xStart - 10,yLabelCenter);\n\t\t\t\t\t}\n\n\t\t\t\t\t// This is X axis, so draw it\n\t\t\t\t\tif (index === 0 && !drawHorizontalLine){\n\t\t\t\t\t\tdrawHorizontalLine = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (drawHorizontalLine){\n\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t}\n\n\t\t\t\t\tif (index > 0){\n\t\t\t\t\t\t// This is a grid line in the centre, so drop that\n\t\t\t\t\t\tctx.lineWidth = this.gridLineWidth;\n\t\t\t\t\t\tctx.strokeStyle = this.gridLineColor;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// This is the first line on the scale\n\t\t\t\t\t\tctx.lineWidth = this.lineWidth;\n\t\t\t\t\t\tctx.strokeStyle = this.lineColor;\n\t\t\t\t\t}\n\n\t\t\t\t\tlinePositionY += helpers.aliasPixel(ctx.lineWidth);\n\n\t\t\t\t\tif(drawHorizontalLine){\n\t\t\t\t\t\tctx.moveTo(xStart, linePositionY);\n\t\t\t\t\t\tctx.lineTo(this.width, linePositionY);\n\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t\tctx.closePath();\n\t\t\t\t\t}\n\n\t\t\t\t\tctx.lineWidth = this.lineWidth;\n\t\t\t\t\tctx.strokeStyle = this.lineColor;\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(xStart - 5, linePositionY);\n\t\t\t\t\tctx.lineTo(xStart, linePositionY);\n\t\t\t\t\tctx.stroke();\n\t\t\t\t\tctx.closePath();\n\n\t\t\t\t},this);\n\n\t\t\t\teach(this.xLabels,function(label,index){\n\t\t\t\t\tvar xPos = this.calculateX(index) + aliasPixel(this.lineWidth),\n\t\t\t\t\t\t// Check to see if line/bar here and decide where to place the line\n\t\t\t\t\t\tlinePos = this.calculateX(index - (this.offsetGridLines ? 0.5 : 0)) + aliasPixel(this.lineWidth),\n\t\t\t\t\t\tisRotated = (this.xLabelRotation > 0),\n\t\t\t\t\t\tdrawVerticalLine = this.showVerticalLines;\n\n\t\t\t\t\t// This is Y axis, so draw it\n\t\t\t\t\tif (index === 0 && !drawVerticalLine){\n\t\t\t\t\t\tdrawVerticalLine = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (drawVerticalLine){\n\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t}\n\n\t\t\t\t\tif (index > 0){\n\t\t\t\t\t\t// This is a grid line in the centre, so drop that\n\t\t\t\t\t\tctx.lineWidth = this.gridLineWidth;\n\t\t\t\t\t\tctx.strokeStyle = this.gridLineColor;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// This is the first line on the scale\n\t\t\t\t\t\tctx.lineWidth = this.lineWidth;\n\t\t\t\t\t\tctx.strokeStyle = this.lineColor;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (drawVerticalLine){\n\t\t\t\t\t\tctx.moveTo(linePos,this.endPoint);\n\t\t\t\t\t\tctx.lineTo(linePos,this.startPoint - 3);\n\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t\tctx.closePath();\n\t\t\t\t\t}\n\n\n\t\t\t\t\tctx.lineWidth = this.lineWidth;\n\t\t\t\t\tctx.strokeStyle = this.lineColor;\n\n\n\t\t\t\t\t// Small lines at the bottom of the base grid line\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(linePos,this.endPoint);\n\t\t\t\t\tctx.lineTo(linePos,this.endPoint + 5);\n\t\t\t\t\tctx.stroke();\n\t\t\t\t\tctx.closePath();\n\n\t\t\t\t\tctx.save();\n\t\t\t\t\tctx.translate(xPos,(isRotated) ? this.endPoint + 12 : this.endPoint + 8);\n\t\t\t\t\tctx.rotate(toRadians(this.xLabelRotation)*-1);\n\t\t\t\t\tctx.font = this.font;\n\t\t\t\t\tctx.textAlign = (isRotated) ? \"right\" : \"center\";\n\t\t\t\t\tctx.textBaseline = (isRotated) ? \"middle\" : \"top\";\n\t\t\t\t\tctx.fillText(label, 0, 0);\n\t\t\t\t\tctx.restore();\n\t\t\t\t},this);\n\n\t\t\t}\n\t\t}\n\n\t});\n\n\tChart.RadialScale = Chart.Element.extend({\n\t\tinitialize: function(){\n\t\t\tthis.size = min([this.height, this.width]);\n\t\t\tthis.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);\n\t\t},\n\t\tcalculateCenterOffset: function(value){\n\t\t\t// Take into account half font size + the yPadding of the top value\n\t\t\tvar scalingFactor = this.drawingArea / (this.max - this.min);\n\n\t\t\treturn (value - this.min) * scalingFactor;\n\t\t},\n\t\tupdate : function(){\n\t\t\tif (!this.lineArc){\n\t\t\t\tthis.setScaleSize();\n\t\t\t} else {\n\t\t\t\tthis.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);\n\t\t\t}\n\t\t\tthis.buildYLabels();\n\t\t},\n\t\tbuildYLabels: function(){\n\t\t\tthis.yLabels = [];\n\n\t\t\tvar stepDecimalPlaces = getDecimalPlaces(this.stepValue);\n\n\t\t\tfor (var i=0; i<=this.steps; i++){\n\t\t\t\tthis.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));\n\t\t\t}\n\t\t},\n\t\tgetCircumference : function(){\n\t\t\treturn ((Math.PI*2) / this.valuesCount);\n\t\t},\n\t\tsetScaleSize: function(){\n\t\t\t/*\n\t\t\t * Right, this is really confusing and there is a lot of maths going on here\n\t\t\t * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9\n\t\t\t *\n\t\t\t * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif\n\t\t\t *\n\t\t\t * Solution:\n\t\t\t *\n\t\t\t * We assume the radius of the polygon is half the size of the canvas at first\n\t\t\t * at each index we check if the text overlaps.\n\t\t\t *\n\t\t\t * Where it does, we store that angle and that index.\n\t\t\t *\n\t\t\t * After finding the largest index and angle we calculate how much we need to remove\n\t\t\t * from the shape radius to move the point inwards by that x.\n\t\t\t *\n\t\t\t * We average the left and right distances to get the maximum shape radius that can fit in the box\n\t\t\t * along with labels.\n\t\t\t *\n\t\t\t * Once we have that, we can find the centre point for the chart, by taking the x text protrusion\n\t\t\t * on each side, removing that from the size, halving it and adding the left x protrusion width.\n\t\t\t *\n\t\t\t * This will mean we have a shape fitted to the canvas, as large as it can be with the labels\n\t\t\t * and position it in the most space efficient manner\n\t\t\t *\n\t\t\t * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif\n\t\t\t */\n\n\n\t\t\t// Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.\n\t\t\t// Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points\n\t\t\tvar largestPossibleRadius = min([(this.height/2 - this.pointLabelFontSize - 5), this.width/2]),\n\t\t\t\tpointPosition,\n\t\t\t\ti,\n\t\t\t\ttextWidth,\n\t\t\t\thalfTextWidth,\n\t\t\t\tfurthestRight = this.width,\n\t\t\t\tfurthestRightIndex,\n\t\t\t\tfurthestRightAngle,\n\t\t\t\tfurthestLeft = 0,\n\t\t\t\tfurthestLeftIndex,\n\t\t\t\tfurthestLeftAngle,\n\t\t\t\txProtrusionLeft,\n\t\t\t\txProtrusionRight,\n\t\t\t\tradiusReductionRight,\n\t\t\t\tradiusReductionLeft,\n\t\t\t\tmaxWidthRadius;\n\t\t\tthis.ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);\n\t\t\tfor (i=0;i furthestRight) {\n\t\t\t\t\t\tfurthestRight = pointPosition.x + halfTextWidth;\n\t\t\t\t\t\tfurthestRightIndex = i;\n\t\t\t\t\t}\n\t\t\t\t\tif (pointPosition.x - halfTextWidth < furthestLeft) {\n\t\t\t\t\t\tfurthestLeft = pointPosition.x - halfTextWidth;\n\t\t\t\t\t\tfurthestLeftIndex = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (i < this.valuesCount/2) {\n\t\t\t\t\t// Less than half the values means we'll left align the text\n\t\t\t\t\tif (pointPosition.x + textWidth > furthestRight) {\n\t\t\t\t\t\tfurthestRight = pointPosition.x + textWidth;\n\t\t\t\t\t\tfurthestRightIndex = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (i > this.valuesCount/2){\n\t\t\t\t\t// More than half the values means we'll right align the text\n\t\t\t\t\tif (pointPosition.x - textWidth < furthestLeft) {\n\t\t\t\t\t\tfurthestLeft = pointPosition.x - textWidth;\n\t\t\t\t\t\tfurthestLeftIndex = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\txProtrusionLeft = furthestLeft;\n\n\t\t\txProtrusionRight = Math.ceil(furthestRight - this.width);\n\n\t\t\tfurthestRightAngle = this.getIndexAngle(furthestRightIndex);\n\n\t\t\tfurthestLeftAngle = this.getIndexAngle(furthestLeftIndex);\n\n\t\t\tradiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI/2);\n\n\t\t\tradiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI/2);\n\n\t\t\t// Ensure we actually need to reduce the size of the chart\n\t\t\tradiusReductionRight = (isNumber(radiusReductionRight)) ? radiusReductionRight : 0;\n\t\t\tradiusReductionLeft = (isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0;\n\n\t\t\tthis.drawingArea = largestPossibleRadius - (radiusReductionLeft + radiusReductionRight)/2;\n\n\t\t\t//this.drawingArea = min([maxWidthRadius, (this.height - (2 * (this.pointLabelFontSize + 5)))/2])\n\t\t\tthis.setCenterPoint(radiusReductionLeft, radiusReductionRight);\n\n\t\t},\n\t\tsetCenterPoint: function(leftMovement, rightMovement){\n\n\t\t\tvar maxRight = this.width - rightMovement - this.drawingArea,\n\t\t\t\tmaxLeft = leftMovement + this.drawingArea;\n\n\t\t\tthis.xCenter = (maxLeft + maxRight)/2;\n\t\t\t// Always vertically in the centre as the text height doesn't change\n\t\t\tthis.yCenter = (this.height/2);\n\t\t},\n\n\t\tgetIndexAngle : function(index){\n\t\t\tvar angleMultiplier = (Math.PI * 2) / this.valuesCount;\n\t\t\t// Start from the top instead of right, so remove a quarter of the circle\n\n\t\t\treturn index * angleMultiplier - (Math.PI/2);\n\t\t},\n\t\tgetPointPosition : function(index, distanceFromCenter){\n\t\t\tvar thisAngle = this.getIndexAngle(index);\n\t\t\treturn {\n\t\t\t\tx : (Math.cos(thisAngle) * distanceFromCenter) + this.xCenter,\n\t\t\t\ty : (Math.sin(thisAngle) * distanceFromCenter) + this.yCenter\n\t\t\t};\n\t\t},\n\t\tdraw: function(){\n\t\t\tif (this.display){\n\t\t\t\tvar ctx = this.ctx;\n\t\t\t\teach(this.yLabels, function(label, index){\n\t\t\t\t\t// Don't draw a centre value\n\t\t\t\t\tif (index > 0){\n\t\t\t\t\t\tvar yCenterOffset = index * (this.drawingArea/this.steps),\n\t\t\t\t\t\t\tyHeight = this.yCenter - yCenterOffset,\n\t\t\t\t\t\t\tpointPosition;\n\n\t\t\t\t\t\t// Draw circular lines around the scale\n\t\t\t\t\t\tif (this.lineWidth > 0){\n\t\t\t\t\t\t\tctx.strokeStyle = this.lineColor;\n\t\t\t\t\t\t\tctx.lineWidth = this.lineWidth;\n\n\t\t\t\t\t\t\tif(this.lineArc){\n\t\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\t\t\tctx.arc(this.xCenter, this.yCenter, yCenterOffset, 0, Math.PI*2);\n\t\t\t\t\t\t\t\tctx.closePath();\n\t\t\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t\t\t} else{\n\t\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\t\t\tfor (var i=0;i= 0; i--) {\n\t\t\t\t\t\tif (this.angleLineWidth > 0){\n\t\t\t\t\t\t\tvar outerPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max));\n\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\t\tctx.moveTo(this.xCenter, this.yCenter);\n\t\t\t\t\t\t\tctx.lineTo(outerPosition.x, outerPosition.y);\n\t\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t\t\tctx.closePath();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Extra 3px out for some label spacing\n\t\t\t\t\t\tvar pointLabelPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max) + 5);\n\t\t\t\t\t\tctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);\n\t\t\t\t\t\tctx.fillStyle = this.pointLabelFontColor;\n\n\t\t\t\t\t\tvar labelsCount = this.labels.length,\n\t\t\t\t\t\t\thalfLabelsCount = this.labels.length/2,\n\t\t\t\t\t\t\tquarterLabelsCount = halfLabelsCount/2,\n\t\t\t\t\t\t\tupperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),\n\t\t\t\t\t\t\texactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);\n\t\t\t\t\t\tif (i === 0){\n\t\t\t\t\t\t\tctx.textAlign = 'center';\n\t\t\t\t\t\t} else if(i === halfLabelsCount){\n\t\t\t\t\t\t\tctx.textAlign = 'center';\n\t\t\t\t\t\t} else if (i < halfLabelsCount){\n\t\t\t\t\t\t\tctx.textAlign = 'left';\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tctx.textAlign = 'right';\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Set the correct text baseline based on outer positioning\n\t\t\t\t\t\tif (exactQuarter){\n\t\t\t\t\t\t\tctx.textBaseline = 'middle';\n\t\t\t\t\t\t} else if (upperHalf){\n\t\t\t\t\t\t\tctx.textBaseline = 'bottom';\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tctx.textBaseline = 'top';\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tctx.fillText(this.labels[i], pointLabelPosition.x, pointLabelPosition.y);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\t// Attach global event to resize each chart instance when the browser resizes\n\thelpers.addEvent(window, \"resize\", (function(){\n\t\t// Basic debounce of resize function so it doesn't hurt performance when resizing browser.\n\t\tvar timeout;\n\t\treturn function(){\n\t\t\tclearTimeout(timeout);\n\t\t\ttimeout = setTimeout(function(){\n\t\t\t\teach(Chart.instances,function(instance){\n\t\t\t\t\t// If the responsive flag is set in the chart instance config\n\t\t\t\t\t// Cascade the resize event down to the chart.\n\t\t\t\t\tif (instance.options.responsive){\n\t\t\t\t\t\tinstance.resize(instance.render, true);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}, 50);\n\t\t};\n\t})());\n\n\n\tif (amd) {\n\t\t!(__WEBPACK_AMD_DEFINE_RESULT__ = function(){\n\t\t\treturn Chart;\n\t\t}.call(exports, __webpack_require__, exports, module),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t} else if (typeof module === 'object' && module.exports) {\n\t\tmodule.exports = Chart;\n\t}\n\n\troot.Chart = Chart;\n\n\tChart.noConflict = function(){\n\t\troot.Chart = previous;\n\t\treturn Chart;\n\t};\n\n}).call(this);\n\n(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\thelpers = Chart.helpers;\n\n\n\tvar defaultConfig = {\n\t\t//Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value\n\t\tscaleBeginAtZero : true,\n\n\t\t//Boolean - Whether grid lines are shown across the chart\n\t\tscaleShowGridLines : true,\n\n\t\t//String - Colour of the grid lines\n\t\tscaleGridLineColor : \"rgba(0,0,0,.05)\",\n\n\t\t//Number - Width of the grid lines\n\t\tscaleGridLineWidth : 1,\n\n\t\t//Boolean - Whether to show horizontal lines (except X axis)\n\t\tscaleShowHorizontalLines: true,\n\n\t\t//Boolean - Whether to show vertical lines (except Y axis)\n\t\tscaleShowVerticalLines: true,\n\n\t\t//Boolean - If there is a stroke on each bar\n\t\tbarShowStroke : true,\n\n\t\t//Number - Pixel width of the bar stroke\n\t\tbarStrokeWidth : 2,\n\n\t\t//Number - Spacing between each of the X value sets\n\t\tbarValueSpacing : 5,\n\n\t\t//Number - Spacing between data sets within X values\n\t\tbarDatasetSpacing : 1,\n\n\t\t//String - A legend template\n\t\tlegendTemplate : \"
    -legend\\\"><% for (var i=0; i
  • \\\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
\"\n\n\t};\n\n\n\tChart.Type.extend({\n\t\tname: \"Bar\",\n\t\tdefaults : defaultConfig,\n\t\tinitialize: function(data){\n\n\t\t\t//Expose options as a scope variable here so we can access it in the ScaleClass\n\t\t\tvar options = this.options;\n\n\t\t\tthis.ScaleClass = Chart.Scale.extend({\n\t\t\t\toffsetGridLines : true,\n\t\t\t\tcalculateBarX : function(datasetCount, datasetIndex, barIndex){\n\t\t\t\t\t//Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar\n\t\t\t\t\tvar xWidth = this.calculateBaseWidth(),\n\t\t\t\t\t\txAbsolute = this.calculateX(barIndex) - (xWidth/2),\n\t\t\t\t\t\tbarWidth = this.calculateBarWidth(datasetCount);\n\n\t\t\t\t\treturn xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2;\n\t\t\t\t},\n\t\t\t\tcalculateBaseWidth : function(){\n\t\t\t\t\treturn (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing);\n\t\t\t\t},\n\t\t\t\tcalculateBarWidth : function(datasetCount){\n\t\t\t\t\t//The padding between datasets is to the right of each bar, providing that there are more than 1 dataset\n\t\t\t\t\tvar baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing);\n\n\t\t\t\t\treturn (baseWidth / datasetCount);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.datasets = [];\n\n\t\t\t//Set up tooltip events on the chart\n\t\t\tif (this.options.showTooltips){\n\t\t\t\thelpers.bindEvents(this, this.options.tooltipEvents, function(evt){\n\t\t\t\t\tvar activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];\n\n\t\t\t\t\tthis.eachBars(function(bar){\n\t\t\t\t\t\tbar.restore(['fillColor', 'strokeColor']);\n\t\t\t\t\t});\n\t\t\t\t\thelpers.each(activeBars, function(activeBar){\n\t\t\t\t\t\tactiveBar.fillColor = activeBar.highlightFill;\n\t\t\t\t\t\tactiveBar.strokeColor = activeBar.highlightStroke;\n\t\t\t\t\t});\n\t\t\t\t\tthis.showTooltip(activeBars);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t//Declare the extension of the default point, to cater for the options passed in to the constructor\n\t\t\tthis.BarClass = Chart.Rectangle.extend({\n\t\t\t\tstrokeWidth : this.options.barStrokeWidth,\n\t\t\t\tshowStroke : this.options.barShowStroke,\n\t\t\t\tctx : this.chart.ctx\n\t\t\t});\n\n\t\t\t//Iterate through each of the datasets, and build this into a property of the chart\n\t\t\thelpers.each(data.datasets,function(dataset,datasetIndex){\n\n\t\t\t\tvar datasetObject = {\n\t\t\t\t\tlabel : dataset.label || null,\n\t\t\t\t\tfillColor : dataset.fillColor,\n\t\t\t\t\tstrokeColor : dataset.strokeColor,\n\t\t\t\t\tbars : []\n\t\t\t\t};\n\n\t\t\t\tthis.datasets.push(datasetObject);\n\n\t\t\t\thelpers.each(dataset.data,function(dataPoint,index){\n\t\t\t\t\t//Add a new point for each piece of data, passing any required data to draw.\n\t\t\t\t\tdatasetObject.bars.push(new this.BarClass({\n\t\t\t\t\t\tvalue : dataPoint,\n\t\t\t\t\t\tlabel : data.labels[index],\n\t\t\t\t\t\tdatasetLabel: dataset.label,\n\t\t\t\t\t\tstrokeColor : dataset.strokeColor,\n\t\t\t\t\t\tfillColor : dataset.fillColor,\n\t\t\t\t\t\thighlightFill : dataset.highlightFill || dataset.fillColor,\n\t\t\t\t\t\thighlightStroke : dataset.highlightStroke || dataset.strokeColor\n\t\t\t\t\t}));\n\t\t\t\t},this);\n\n\t\t\t},this);\n\n\t\t\tthis.buildScale(data.labels);\n\n\t\t\tthis.BarClass.prototype.base = this.scale.endPoint;\n\n\t\t\tthis.eachBars(function(bar, index, datasetIndex){\n\t\t\t\thelpers.extend(bar, {\n\t\t\t\t\twidth : this.scale.calculateBarWidth(this.datasets.length),\n\t\t\t\t\tx: this.scale.calculateBarX(this.datasets.length, datasetIndex, index),\n\t\t\t\t\ty: this.scale.endPoint\n\t\t\t\t});\n\t\t\t\tbar.save();\n\t\t\t}, this);\n\n\t\t\tthis.render();\n\t\t},\n\t\tupdate : function(){\n\t\t\tthis.scale.update();\n\t\t\t// Reset any highlight colours before updating.\n\t\t\thelpers.each(this.activeElements, function(activeElement){\n\t\t\t\tactiveElement.restore(['fillColor', 'strokeColor']);\n\t\t\t});\n\n\t\t\tthis.eachBars(function(bar){\n\t\t\t\tbar.save();\n\t\t\t});\n\t\t\tthis.render();\n\t\t},\n\t\teachBars : function(callback){\n\t\t\thelpers.each(this.datasets,function(dataset, datasetIndex){\n\t\t\t\thelpers.each(dataset.bars, callback, this, datasetIndex);\n\t\t\t},this);\n\t\t},\n\t\tgetBarsAtEvent : function(e){\n\t\t\tvar barsArray = [],\n\t\t\t\teventPosition = helpers.getRelativePosition(e),\n\t\t\t\tdatasetIterator = function(dataset){\n\t\t\t\t\tbarsArray.push(dataset.bars[barIndex]);\n\t\t\t\t},\n\t\t\t\tbarIndex;\n\n\t\t\tfor (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) {\n\t\t\t\tfor (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) {\n\t\t\t\t\tif (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){\n\t\t\t\t\t\thelpers.each(this.datasets, datasetIterator);\n\t\t\t\t\t\treturn barsArray;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn barsArray;\n\t\t},\n\t\tbuildScale : function(labels){\n\t\t\tvar self = this;\n\n\t\t\tvar dataTotal = function(){\n\t\t\t\tvar values = [];\n\t\t\t\tself.eachBars(function(bar){\n\t\t\t\t\tvalues.push(bar.value);\n\t\t\t\t});\n\t\t\t\treturn values;\n\t\t\t};\n\n\t\t\tvar scaleOptions = {\n\t\t\t\ttemplateString : this.options.scaleLabel,\n\t\t\t\theight : this.chart.height,\n\t\t\t\twidth : this.chart.width,\n\t\t\t\tctx : this.chart.ctx,\n\t\t\t\ttextColor : this.options.scaleFontColor,\n\t\t\t\tfontSize : this.options.scaleFontSize,\n\t\t\t\tfontStyle : this.options.scaleFontStyle,\n\t\t\t\tfontFamily : this.options.scaleFontFamily,\n\t\t\t\tvaluesCount : labels.length,\n\t\t\t\tbeginAtZero : this.options.scaleBeginAtZero,\n\t\t\t\tintegersOnly : this.options.scaleIntegersOnly,\n\t\t\t\tcalculateYRange: function(currentHeight){\n\t\t\t\t\tvar updatedRanges = helpers.calculateScaleRange(\n\t\t\t\t\t\tdataTotal(),\n\t\t\t\t\t\tcurrentHeight,\n\t\t\t\t\t\tthis.fontSize,\n\t\t\t\t\t\tthis.beginAtZero,\n\t\t\t\t\t\tthis.integersOnly\n\t\t\t\t\t);\n\t\t\t\t\thelpers.extend(this, updatedRanges);\n\t\t\t\t},\n\t\t\t\txLabels : labels,\n\t\t\t\tfont : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),\n\t\t\t\tlineWidth : this.options.scaleLineWidth,\n\t\t\t\tlineColor : this.options.scaleLineColor,\n\t\t\t\tshowHorizontalLines : this.options.scaleShowHorizontalLines,\n\t\t\t\tshowVerticalLines : this.options.scaleShowVerticalLines,\n\t\t\t\tgridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,\n\t\t\t\tgridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : \"rgba(0,0,0,0)\",\n\t\t\t\tpadding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0,\n\t\t\t\tshowLabels : this.options.scaleShowLabels,\n\t\t\t\tdisplay : this.options.showScale\n\t\t\t};\n\n\t\t\tif (this.options.scaleOverride){\n\t\t\t\thelpers.extend(scaleOptions, {\n\t\t\t\t\tcalculateYRange: helpers.noop,\n\t\t\t\t\tsteps: this.options.scaleSteps,\n\t\t\t\t\tstepValue: this.options.scaleStepWidth,\n\t\t\t\t\tmin: this.options.scaleStartValue,\n\t\t\t\t\tmax: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.scale = new this.ScaleClass(scaleOptions);\n\t\t},\n\t\taddData : function(valuesArray,label){\n\t\t\t//Map the values array for each of the datasets\n\t\t\thelpers.each(valuesArray,function(value,datasetIndex){\n\t\t\t\t//Add a new point for each piece of data, passing any required data to draw.\n\t\t\t\tthis.datasets[datasetIndex].bars.push(new this.BarClass({\n\t\t\t\t\tvalue : value,\n\t\t\t\t\tlabel : label,\n\t\t\t\t\tx: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1),\n\t\t\t\t\ty: this.scale.endPoint,\n\t\t\t\t\twidth : this.scale.calculateBarWidth(this.datasets.length),\n\t\t\t\t\tbase : this.scale.endPoint,\n\t\t\t\t\tstrokeColor : this.datasets[datasetIndex].strokeColor,\n\t\t\t\t\tfillColor : this.datasets[datasetIndex].fillColor\n\t\t\t\t}));\n\t\t\t},this);\n\n\t\t\tthis.scale.addXLabel(label);\n\t\t\t//Then re-render the chart.\n\t\t\tthis.update();\n\t\t},\n\t\tremoveData : function(){\n\t\t\tthis.scale.removeXLabel();\n\t\t\t//Then re-render the chart.\n\t\t\thelpers.each(this.datasets,function(dataset){\n\t\t\t\tdataset.bars.shift();\n\t\t\t},this);\n\t\t\tthis.update();\n\t\t},\n\t\treflow : function(){\n\t\t\thelpers.extend(this.BarClass.prototype,{\n\t\t\t\ty: this.scale.endPoint,\n\t\t\t\tbase : this.scale.endPoint\n\t\t\t});\n\t\t\tvar newScaleProps = helpers.extend({\n\t\t\t\theight : this.chart.height,\n\t\t\t\twidth : this.chart.width\n\t\t\t});\n\t\t\tthis.scale.update(newScaleProps);\n\t\t},\n\t\tdraw : function(ease){\n\t\t\tvar easingDecimal = ease || 1;\n\t\t\tthis.clear();\n\n\t\t\tvar ctx = this.chart.ctx;\n\n\t\t\tthis.scale.draw(easingDecimal);\n\n\t\t\t//Draw all the bars for each dataset\n\t\t\thelpers.each(this.datasets,function(dataset,datasetIndex){\n\t\t\t\thelpers.each(dataset.bars,function(bar,index){\n\t\t\t\t\tif (bar.hasValue()){\n\t\t\t\t\t\tbar.base = this.scale.endPoint;\n\t\t\t\t\t\t//Transition then draw\n\t\t\t\t\t\tbar.transition({\n\t\t\t\t\t\t\tx : this.scale.calculateBarX(this.datasets.length, datasetIndex, index),\n\t\t\t\t\t\t\ty : this.scale.calculateY(bar.value),\n\t\t\t\t\t\t\twidth : this.scale.calculateBarWidth(this.datasets.length)\n\t\t\t\t\t\t}, easingDecimal).draw();\n\t\t\t\t\t}\n\t\t\t\t},this);\n\n\t\t\t},this);\n\t\t}\n\t});\n\n\n}).call(this);\n\n(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\t//Cache a local reference to Chart.helpers\n\t\thelpers = Chart.helpers;\n\n\tvar defaultConfig = {\n\t\t//Boolean - Whether we should show a stroke on each segment\n\t\tsegmentShowStroke : true,\n\n\t\t//String - The colour of each segment stroke\n\t\tsegmentStrokeColor : \"#fff\",\n\n\t\t//Number - The width of each segment stroke\n\t\tsegmentStrokeWidth : 2,\n\n\t\t//The percentage of the chart that we cut out of the middle.\n\t\tpercentageInnerCutout : 50,\n\n\t\t//Number - Amount of animation steps\n\t\tanimationSteps : 100,\n\n\t\t//String - Animation easing effect\n\t\tanimationEasing : \"easeOutBounce\",\n\n\t\t//Boolean - Whether we animate the rotation of the Doughnut\n\t\tanimateRotate : true,\n\n\t\t//Boolean - Whether we animate scaling the Doughnut from the centre\n\t\tanimateScale : false,\n\n\t\t//String - A legend template\n\t\tlegendTemplate : \"
    -legend\\\"><% for (var i=0; i
  • \\\"><%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>
\"\n\n\t};\n\n\n\tChart.Type.extend({\n\t\t//Passing in a name registers this chart in the Chart namespace\n\t\tname: \"Doughnut\",\n\t\t//Providing a defaults will also register the deafults in the chart namespace\n\t\tdefaults : defaultConfig,\n\t\t//Initialize is fired when the chart is initialized - Data is passed in as a parameter\n\t\t//Config is automatically merged by the core of Chart.js, and is available at this.options\n\t\tinitialize: function(data){\n\n\t\t\t//Declare segments as a static property to prevent inheriting across the Chart type prototype\n\t\t\tthis.segments = [];\n\t\t\tthis.outerRadius = (helpers.min([this.chart.width,this.chart.height]) -\tthis.options.segmentStrokeWidth/2)/2;\n\n\t\t\tthis.SegmentArc = Chart.Arc.extend({\n\t\t\t\tctx : this.chart.ctx,\n\t\t\t\tx : this.chart.width/2,\n\t\t\t\ty : this.chart.height/2\n\t\t\t});\n\n\t\t\t//Set up tooltip events on the chart\n\t\t\tif (this.options.showTooltips){\n\t\t\t\thelpers.bindEvents(this, this.options.tooltipEvents, function(evt){\n\t\t\t\t\tvar activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];\n\n\t\t\t\t\thelpers.each(this.segments,function(segment){\n\t\t\t\t\t\tsegment.restore([\"fillColor\"]);\n\t\t\t\t\t});\n\t\t\t\t\thelpers.each(activeSegments,function(activeSegment){\n\t\t\t\t\t\tactiveSegment.fillColor = activeSegment.highlightColor;\n\t\t\t\t\t});\n\t\t\t\t\tthis.showTooltip(activeSegments);\n\t\t\t\t});\n\t\t\t}\n\t\t\tthis.calculateTotal(data);\n\n\t\t\thelpers.each(data,function(datapoint, index){\n\t\t\t\tthis.addData(datapoint, index, true);\n\t\t\t},this);\n\n\t\t\tthis.render();\n\t\t},\n\t\tgetSegmentsAtEvent : function(e){\n\t\t\tvar segmentsArray = [];\n\n\t\t\tvar location = helpers.getRelativePosition(e);\n\n\t\t\thelpers.each(this.segments,function(segment){\n\t\t\t\tif (segment.inRange(location.x,location.y)) segmentsArray.push(segment);\n\t\t\t},this);\n\t\t\treturn segmentsArray;\n\t\t},\n\t\taddData : function(segment, atIndex, silent){\n\t\t\tvar index = atIndex || this.segments.length;\n\t\t\tthis.segments.splice(index, 0, new this.SegmentArc({\n\t\t\t\tvalue : segment.value,\n\t\t\t\touterRadius : (this.options.animateScale) ? 0 : this.outerRadius,\n\t\t\t\tinnerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout,\n\t\t\t\tfillColor : segment.color,\n\t\t\t\thighlightColor : segment.highlight || segment.color,\n\t\t\t\tshowStroke : this.options.segmentShowStroke,\n\t\t\t\tstrokeWidth : this.options.segmentStrokeWidth,\n\t\t\t\tstrokeColor : this.options.segmentStrokeColor,\n\t\t\t\tstartAngle : Math.PI * 1.5,\n\t\t\t\tcircumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),\n\t\t\t\tlabel : segment.label\n\t\t\t}));\n\t\t\tif (!silent){\n\t\t\t\tthis.reflow();\n\t\t\t\tthis.update();\n\t\t\t}\n\t\t},\n\t\tcalculateCircumference : function(value){\n\t\t\treturn (Math.PI*2)*(Math.abs(value) / this.total);\n\t\t},\n\t\tcalculateTotal : function(data){\n\t\t\tthis.total = 0;\n\t\t\thelpers.each(data,function(segment){\n\t\t\t\tthis.total += Math.abs(segment.value);\n\t\t\t},this);\n\t\t},\n\t\tupdate : function(){\n\t\t\tthis.calculateTotal(this.segments);\n\n\t\t\t// Reset any highlight colours before updating.\n\t\t\thelpers.each(this.activeElements, function(activeElement){\n\t\t\t\tactiveElement.restore(['fillColor']);\n\t\t\t});\n\n\t\t\thelpers.each(this.segments,function(segment){\n\t\t\t\tsegment.save();\n\t\t\t});\n\t\t\tthis.render();\n\t\t},\n\n\t\tremoveData: function(atIndex){\n\t\t\tvar indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;\n\t\t\tthis.segments.splice(indexToDelete, 1);\n\t\t\tthis.reflow();\n\t\t\tthis.update();\n\t\t},\n\n\t\treflow : function(){\n\t\t\thelpers.extend(this.SegmentArc.prototype,{\n\t\t\t\tx : this.chart.width/2,\n\t\t\t\ty : this.chart.height/2\n\t\t\t});\n\t\t\tthis.outerRadius = (helpers.min([this.chart.width,this.chart.height]) -\tthis.options.segmentStrokeWidth/2)/2;\n\t\t\thelpers.each(this.segments, function(segment){\n\t\t\t\tsegment.update({\n\t\t\t\t\touterRadius : this.outerRadius,\n\t\t\t\t\tinnerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout\n\t\t\t\t});\n\t\t\t}, this);\n\t\t},\n\t\tdraw : function(easeDecimal){\n\t\t\tvar animDecimal = (easeDecimal) ? easeDecimal : 1;\n\t\t\tthis.clear();\n\t\t\thelpers.each(this.segments,function(segment,index){\n\t\t\t\tsegment.transition({\n\t\t\t\t\tcircumference : this.calculateCircumference(segment.value),\n\t\t\t\t\touterRadius : this.outerRadius,\n\t\t\t\t\tinnerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout\n\t\t\t\t},animDecimal);\n\n\t\t\t\tsegment.endAngle = segment.startAngle + segment.circumference;\n\n\t\t\t\tsegment.draw();\n\t\t\t\tif (index === 0){\n\t\t\t\t\tsegment.startAngle = Math.PI * 1.5;\n\t\t\t\t}\n\t\t\t\t//Check to see if it's the last segment, if not get the next and update the start angle\n\t\t\t\tif (index < this.segments.length-1){\n\t\t\t\t\tthis.segments[index+1].startAngle = segment.endAngle;\n\t\t\t\t}\n\t\t\t},this);\n\n\t\t}\n\t});\n\n\tChart.types.Doughnut.extend({\n\t\tname : \"Pie\",\n\t\tdefaults : helpers.merge(defaultConfig,{percentageInnerCutout : 0})\n\t});\n\n}).call(this);\n(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\thelpers = Chart.helpers;\n\n\tvar defaultConfig = {\n\n\t\t///Boolean - Whether grid lines are shown across the chart\n\t\tscaleShowGridLines : true,\n\n\t\t//String - Colour of the grid lines\n\t\tscaleGridLineColor : \"rgba(0,0,0,.05)\",\n\n\t\t//Number - Width of the grid lines\n\t\tscaleGridLineWidth : 1,\n\n\t\t//Boolean - Whether to show horizontal lines (except X axis)\n\t\tscaleShowHorizontalLines: true,\n\n\t\t//Boolean - Whether to show vertical lines (except Y axis)\n\t\tscaleShowVerticalLines: true,\n\n\t\t//Boolean - Whether the line is curved between points\n\t\tbezierCurve : true,\n\n\t\t//Number - Tension of the bezier curve between points\n\t\tbezierCurveTension : 0.4,\n\n\t\t//Boolean - Whether to show a dot for each point\n\t\tpointDot : true,\n\n\t\t//Number - Radius of each point dot in pixels\n\t\tpointDotRadius : 4,\n\n\t\t//Number - Pixel width of point dot stroke\n\t\tpointDotStrokeWidth : 1,\n\n\t\t//Number - amount extra to add to the radius to cater for hit detection outside the drawn point\n\t\tpointHitDetectionRadius : 20,\n\n\t\t//Boolean - Whether to show a stroke for datasets\n\t\tdatasetStroke : true,\n\n\t\t//Number - Pixel width of dataset stroke\n\t\tdatasetStrokeWidth : 2,\n\n\t\t//Boolean - Whether to fill the dataset with a colour\n\t\tdatasetFill : true,\n\n\t\t//String - A legend template\n\t\tlegendTemplate : \"
    -legend\\\"><% for (var i=0; i
  • \\\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
\"\n\n\t};\n\n\n\tChart.Type.extend({\n\t\tname: \"Line\",\n\t\tdefaults : defaultConfig,\n\t\tinitialize: function(data){\n\t\t\t//Declare the extension of the default point, to cater for the options passed in to the constructor\n\t\t\tthis.PointClass = Chart.Point.extend({\n\t\t\t\tstrokeWidth : this.options.pointDotStrokeWidth,\n\t\t\t\tradius : this.options.pointDotRadius,\n\t\t\t\tdisplay: this.options.pointDot,\n\t\t\t\thitDetectionRadius : this.options.pointHitDetectionRadius,\n\t\t\t\tctx : this.chart.ctx,\n\t\t\t\tinRange : function(mouseX){\n\t\t\t\t\treturn (Math.pow(mouseX-this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius,2));\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.datasets = [];\n\n\t\t\t//Set up tooltip events on the chart\n\t\t\tif (this.options.showTooltips){\n\t\t\t\thelpers.bindEvents(this, this.options.tooltipEvents, function(evt){\n\t\t\t\t\tvar activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];\n\t\t\t\t\tthis.eachPoints(function(point){\n\t\t\t\t\t\tpoint.restore(['fillColor', 'strokeColor']);\n\t\t\t\t\t});\n\t\t\t\t\thelpers.each(activePoints, function(activePoint){\n\t\t\t\t\t\tactivePoint.fillColor = activePoint.highlightFill;\n\t\t\t\t\t\tactivePoint.strokeColor = activePoint.highlightStroke;\n\t\t\t\t\t});\n\t\t\t\t\tthis.showTooltip(activePoints);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t//Iterate through each of the datasets, and build this into a property of the chart\n\t\t\thelpers.each(data.datasets,function(dataset){\n\n\t\t\t\tvar datasetObject = {\n\t\t\t\t\tlabel : dataset.label || null,\n\t\t\t\t\tfillColor : dataset.fillColor,\n\t\t\t\t\tstrokeColor : dataset.strokeColor,\n\t\t\t\t\tpointColor : dataset.pointColor,\n\t\t\t\t\tpointStrokeColor : dataset.pointStrokeColor,\n\t\t\t\t\tpoints : []\n\t\t\t\t};\n\n\t\t\t\tthis.datasets.push(datasetObject);\n\n\n\t\t\t\thelpers.each(dataset.data,function(dataPoint,index){\n\t\t\t\t\t//Add a new point for each piece of data, passing any required data to draw.\n\t\t\t\t\tdatasetObject.points.push(new this.PointClass({\n\t\t\t\t\t\tvalue : dataPoint,\n\t\t\t\t\t\tlabel : data.labels[index],\n\t\t\t\t\t\tdatasetLabel: dataset.label,\n\t\t\t\t\t\tstrokeColor : dataset.pointStrokeColor,\n\t\t\t\t\t\tfillColor : dataset.pointColor,\n\t\t\t\t\t\thighlightFill : dataset.pointHighlightFill || dataset.pointColor,\n\t\t\t\t\t\thighlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor\n\t\t\t\t\t}));\n\t\t\t\t},this);\n\n\t\t\t\tthis.buildScale(data.labels);\n\n\n\t\t\t\tthis.eachPoints(function(point, index){\n\t\t\t\t\thelpers.extend(point, {\n\t\t\t\t\t\tx: this.scale.calculateX(index),\n\t\t\t\t\t\ty: this.scale.endPoint\n\t\t\t\t\t});\n\t\t\t\t\tpoint.save();\n\t\t\t\t}, this);\n\n\t\t\t},this);\n\n\n\t\t\tthis.render();\n\t\t},\n\t\tupdate : function(){\n\t\t\tthis.scale.update();\n\t\t\t// Reset any highlight colours before updating.\n\t\t\thelpers.each(this.activeElements, function(activeElement){\n\t\t\t\tactiveElement.restore(['fillColor', 'strokeColor']);\n\t\t\t});\n\t\t\tthis.eachPoints(function(point){\n\t\t\t\tpoint.save();\n\t\t\t});\n\t\t\tthis.render();\n\t\t},\n\t\teachPoints : function(callback){\n\t\t\thelpers.each(this.datasets,function(dataset){\n\t\t\t\thelpers.each(dataset.points,callback,this);\n\t\t\t},this);\n\t\t},\n\t\tgetPointsAtEvent : function(e){\n\t\t\tvar pointsArray = [],\n\t\t\t\teventPosition = helpers.getRelativePosition(e);\n\t\t\thelpers.each(this.datasets,function(dataset){\n\t\t\t\thelpers.each(dataset.points,function(point){\n\t\t\t\t\tif (point.inRange(eventPosition.x,eventPosition.y)) pointsArray.push(point);\n\t\t\t\t});\n\t\t\t},this);\n\t\t\treturn pointsArray;\n\t\t},\n\t\tbuildScale : function(labels){\n\t\t\tvar self = this;\n\n\t\t\tvar dataTotal = function(){\n\t\t\t\tvar values = [];\n\t\t\t\tself.eachPoints(function(point){\n\t\t\t\t\tvalues.push(point.value);\n\t\t\t\t});\n\n\t\t\t\treturn values;\n\t\t\t};\n\n\t\t\tvar scaleOptions = {\n\t\t\t\ttemplateString : this.options.scaleLabel,\n\t\t\t\theight : this.chart.height,\n\t\t\t\twidth : this.chart.width,\n\t\t\t\tctx : this.chart.ctx,\n\t\t\t\ttextColor : this.options.scaleFontColor,\n\t\t\t\tfontSize : this.options.scaleFontSize,\n\t\t\t\tfontStyle : this.options.scaleFontStyle,\n\t\t\t\tfontFamily : this.options.scaleFontFamily,\n\t\t\t\tvaluesCount : labels.length,\n\t\t\t\tbeginAtZero : this.options.scaleBeginAtZero,\n\t\t\t\tintegersOnly : this.options.scaleIntegersOnly,\n\t\t\t\tcalculateYRange : function(currentHeight){\n\t\t\t\t\tvar updatedRanges = helpers.calculateScaleRange(\n\t\t\t\t\t\tdataTotal(),\n\t\t\t\t\t\tcurrentHeight,\n\t\t\t\t\t\tthis.fontSize,\n\t\t\t\t\t\tthis.beginAtZero,\n\t\t\t\t\t\tthis.integersOnly\n\t\t\t\t\t);\n\t\t\t\t\thelpers.extend(this, updatedRanges);\n\t\t\t\t},\n\t\t\t\txLabels : labels,\n\t\t\t\tfont : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),\n\t\t\t\tlineWidth : this.options.scaleLineWidth,\n\t\t\t\tlineColor : this.options.scaleLineColor,\n\t\t\t\tshowHorizontalLines : this.options.scaleShowHorizontalLines,\n\t\t\t\tshowVerticalLines : this.options.scaleShowVerticalLines,\n\t\t\t\tgridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,\n\t\t\t\tgridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : \"rgba(0,0,0,0)\",\n\t\t\t\tpadding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,\n\t\t\t\tshowLabels : this.options.scaleShowLabels,\n\t\t\t\tdisplay : this.options.showScale\n\t\t\t};\n\n\t\t\tif (this.options.scaleOverride){\n\t\t\t\thelpers.extend(scaleOptions, {\n\t\t\t\t\tcalculateYRange: helpers.noop,\n\t\t\t\t\tsteps: this.options.scaleSteps,\n\t\t\t\t\tstepValue: this.options.scaleStepWidth,\n\t\t\t\t\tmin: this.options.scaleStartValue,\n\t\t\t\t\tmax: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)\n\t\t\t\t});\n\t\t\t}\n\n\n\t\t\tthis.scale = new Chart.Scale(scaleOptions);\n\t\t},\n\t\taddData : function(valuesArray,label){\n\t\t\t//Map the values array for each of the datasets\n\n\t\t\thelpers.each(valuesArray,function(value,datasetIndex){\n\t\t\t\t//Add a new point for each piece of data, passing any required data to draw.\n\t\t\t\tthis.datasets[datasetIndex].points.push(new this.PointClass({\n\t\t\t\t\tvalue : value,\n\t\t\t\t\tlabel : label,\n\t\t\t\t\tx: this.scale.calculateX(this.scale.valuesCount+1),\n\t\t\t\t\ty: this.scale.endPoint,\n\t\t\t\t\tstrokeColor : this.datasets[datasetIndex].pointStrokeColor,\n\t\t\t\t\tfillColor : this.datasets[datasetIndex].pointColor\n\t\t\t\t}));\n\t\t\t},this);\n\n\t\t\tthis.scale.addXLabel(label);\n\t\t\t//Then re-render the chart.\n\t\t\tthis.update();\n\t\t},\n\t\tremoveData : function(){\n\t\t\tthis.scale.removeXLabel();\n\t\t\t//Then re-render the chart.\n\t\t\thelpers.each(this.datasets,function(dataset){\n\t\t\t\tdataset.points.shift();\n\t\t\t},this);\n\t\t\tthis.update();\n\t\t},\n\t\treflow : function(){\n\t\t\tvar newScaleProps = helpers.extend({\n\t\t\t\theight : this.chart.height,\n\t\t\t\twidth : this.chart.width\n\t\t\t});\n\t\t\tthis.scale.update(newScaleProps);\n\t\t},\n\t\tdraw : function(ease){\n\t\t\tvar easingDecimal = ease || 1;\n\t\t\tthis.clear();\n\n\t\t\tvar ctx = this.chart.ctx;\n\n\t\t\t// Some helper methods for getting the next/prev points\n\t\t\tvar hasValue = function(item){\n\t\t\t\treturn item.value !== null;\n\t\t\t},\n\t\t\tnextPoint = function(point, collection, index){\n\t\t\t\treturn helpers.findNextWhere(collection, hasValue, index) || point;\n\t\t\t},\n\t\t\tpreviousPoint = function(point, collection, index){\n\t\t\t\treturn helpers.findPreviousWhere(collection, hasValue, index) || point;\n\t\t\t};\n\n\t\t\tthis.scale.draw(easingDecimal);\n\n\n\t\t\thelpers.each(this.datasets,function(dataset){\n\t\t\t\tvar pointsWithValues = helpers.where(dataset.points, hasValue);\n\n\t\t\t\t//Transition each point first so that the line and point drawing isn't out of sync\n\t\t\t\t//We can use this extra loop to calculate the control points of this dataset also in this loop\n\n\t\t\t\thelpers.each(dataset.points, function(point, index){\n\t\t\t\t\tif (point.hasValue()){\n\t\t\t\t\t\tpoint.transition({\n\t\t\t\t\t\t\ty : this.scale.calculateY(point.value),\n\t\t\t\t\t\t\tx : this.scale.calculateX(index)\n\t\t\t\t\t\t}, easingDecimal);\n\t\t\t\t\t}\n\t\t\t\t},this);\n\n\n\t\t\t\t// Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point\n\t\t\t\t// This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed\n\t\t\t\tif (this.options.bezierCurve){\n\t\t\t\t\thelpers.each(pointsWithValues, function(point, index){\n\t\t\t\t\t\tvar tension = (index > 0 && index < pointsWithValues.length - 1) ? this.options.bezierCurveTension : 0;\n\t\t\t\t\t\tpoint.controlPoints = helpers.splineCurve(\n\t\t\t\t\t\t\tpreviousPoint(point, pointsWithValues, index),\n\t\t\t\t\t\t\tpoint,\n\t\t\t\t\t\t\tnextPoint(point, pointsWithValues, index),\n\t\t\t\t\t\t\ttension\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// Prevent the bezier going outside of the bounds of the graph\n\n\t\t\t\t\t\t// Cap puter bezier handles to the upper/lower scale bounds\n\t\t\t\t\t\tif (point.controlPoints.outer.y > this.scale.endPoint){\n\t\t\t\t\t\t\tpoint.controlPoints.outer.y = this.scale.endPoint;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (point.controlPoints.outer.y < this.scale.startPoint){\n\t\t\t\t\t\t\tpoint.controlPoints.outer.y = this.scale.startPoint;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Cap inner bezier handles to the upper/lower scale bounds\n\t\t\t\t\t\tif (point.controlPoints.inner.y > this.scale.endPoint){\n\t\t\t\t\t\t\tpoint.controlPoints.inner.y = this.scale.endPoint;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (point.controlPoints.inner.y < this.scale.startPoint){\n\t\t\t\t\t\t\tpoint.controlPoints.inner.y = this.scale.startPoint;\n\t\t\t\t\t\t}\n\t\t\t\t\t},this);\n\t\t\t\t}\n\n\n\t\t\t\t//Draw the line between all the points\n\t\t\t\tctx.lineWidth = this.options.datasetStrokeWidth;\n\t\t\t\tctx.strokeStyle = dataset.strokeColor;\n\t\t\t\tctx.beginPath();\n\n\t\t\t\thelpers.each(pointsWithValues, function(point, index){\n\t\t\t\t\tif (index === 0){\n\t\t\t\t\t\tctx.moveTo(point.x, point.y);\n\t\t\t\t\t}\n\t\t\t\t\telse{\n\t\t\t\t\t\tif(this.options.bezierCurve){\n\t\t\t\t\t\t\tvar previous = previousPoint(point, pointsWithValues, index);\n\n\t\t\t\t\t\t\tctx.bezierCurveTo(\n\t\t\t\t\t\t\t\tprevious.controlPoints.outer.x,\n\t\t\t\t\t\t\t\tprevious.controlPoints.outer.y,\n\t\t\t\t\t\t\t\tpoint.controlPoints.inner.x,\n\t\t\t\t\t\t\t\tpoint.controlPoints.inner.y,\n\t\t\t\t\t\t\t\tpoint.x,\n\t\t\t\t\t\t\t\tpoint.y\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse{\n\t\t\t\t\t\t\tctx.lineTo(point.x,point.y);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}, this);\n\n\t\t\t\tctx.stroke();\n\n\t\t\t\tif (this.options.datasetFill && pointsWithValues.length > 0){\n\t\t\t\t\t//Round off the line by going to the base of the chart, back to the start, then fill.\n\t\t\t\t\tctx.lineTo(pointsWithValues[pointsWithValues.length - 1].x, this.scale.endPoint);\n\t\t\t\t\tctx.lineTo(pointsWithValues[0].x, this.scale.endPoint);\n\t\t\t\t\tctx.fillStyle = dataset.fillColor;\n\t\t\t\t\tctx.closePath();\n\t\t\t\t\tctx.fill();\n\t\t\t\t}\n\n\t\t\t\t//Now draw the points over the line\n\t\t\t\t//A little inefficient double looping, but better than the line\n\t\t\t\t//lagging behind the point positions\n\t\t\t\thelpers.each(pointsWithValues,function(point){\n\t\t\t\t\tpoint.draw();\n\t\t\t\t});\n\t\t\t},this);\n\t\t}\n\t});\n\n\n}).call(this);\n\n(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\t//Cache a local reference to Chart.helpers\n\t\thelpers = Chart.helpers;\n\n\tvar defaultConfig = {\n\t\t//Boolean - Show a backdrop to the scale label\n\t\tscaleShowLabelBackdrop : true,\n\n\t\t//String - The colour of the label backdrop\n\t\tscaleBackdropColor : \"rgba(255,255,255,0.75)\",\n\n\t\t// Boolean - Whether the scale should begin at zero\n\t\tscaleBeginAtZero : true,\n\n\t\t//Number - The backdrop padding above & below the label in pixels\n\t\tscaleBackdropPaddingY : 2,\n\n\t\t//Number - The backdrop padding to the side of the label in pixels\n\t\tscaleBackdropPaddingX : 2,\n\n\t\t//Boolean - Show line for each value in the scale\n\t\tscaleShowLine : true,\n\n\t\t//Boolean - Stroke a line around each segment in the chart\n\t\tsegmentShowStroke : true,\n\n\t\t//String - The colour of the stroke on each segement.\n\t\tsegmentStrokeColor : \"#fff\",\n\n\t\t//Number - The width of the stroke value in pixels\n\t\tsegmentStrokeWidth : 2,\n\n\t\t//Number - Amount of animation steps\n\t\tanimationSteps : 100,\n\n\t\t//String - Animation easing effect.\n\t\tanimationEasing : \"easeOutBounce\",\n\n\t\t//Boolean - Whether to animate the rotation of the chart\n\t\tanimateRotate : true,\n\n\t\t//Boolean - Whether to animate scaling the chart from the centre\n\t\tanimateScale : false,\n\n\t\t//String - A legend template\n\t\tlegendTemplate : \"
    -legend\\\"><% for (var i=0; i
  • \\\"><%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>
\"\n\t};\n\n\n\tChart.Type.extend({\n\t\t//Passing in a name registers this chart in the Chart namespace\n\t\tname: \"PolarArea\",\n\t\t//Providing a defaults will also register the deafults in the chart namespace\n\t\tdefaults : defaultConfig,\n\t\t//Initialize is fired when the chart is initialized - Data is passed in as a parameter\n\t\t//Config is automatically merged by the core of Chart.js, and is available at this.options\n\t\tinitialize: function(data){\n\t\t\tthis.segments = [];\n\t\t\t//Declare segment class as a chart instance specific class, so it can share props for this instance\n\t\t\tthis.SegmentArc = Chart.Arc.extend({\n\t\t\t\tshowStroke : this.options.segmentShowStroke,\n\t\t\t\tstrokeWidth : this.options.segmentStrokeWidth,\n\t\t\t\tstrokeColor : this.options.segmentStrokeColor,\n\t\t\t\tctx : this.chart.ctx,\n\t\t\t\tinnerRadius : 0,\n\t\t\t\tx : this.chart.width/2,\n\t\t\t\ty : this.chart.height/2\n\t\t\t});\n\t\t\tthis.scale = new Chart.RadialScale({\n\t\t\t\tdisplay: this.options.showScale,\n\t\t\t\tfontStyle: this.options.scaleFontStyle,\n\t\t\t\tfontSize: this.options.scaleFontSize,\n\t\t\t\tfontFamily: this.options.scaleFontFamily,\n\t\t\t\tfontColor: this.options.scaleFontColor,\n\t\t\t\tshowLabels: this.options.scaleShowLabels,\n\t\t\t\tshowLabelBackdrop: this.options.scaleShowLabelBackdrop,\n\t\t\t\tbackdropColor: this.options.scaleBackdropColor,\n\t\t\t\tbackdropPaddingY : this.options.scaleBackdropPaddingY,\n\t\t\t\tbackdropPaddingX: this.options.scaleBackdropPaddingX,\n\t\t\t\tlineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,\n\t\t\t\tlineColor: this.options.scaleLineColor,\n\t\t\t\tlineArc: true,\n\t\t\t\twidth: this.chart.width,\n\t\t\t\theight: this.chart.height,\n\t\t\t\txCenter: this.chart.width/2,\n\t\t\t\tyCenter: this.chart.height/2,\n\t\t\t\tctx : this.chart.ctx,\n\t\t\t\ttemplateString: this.options.scaleLabel,\n\t\t\t\tvaluesCount: data.length\n\t\t\t});\n\n\t\t\tthis.updateScaleRange(data);\n\n\t\t\tthis.scale.update();\n\n\t\t\thelpers.each(data,function(segment,index){\n\t\t\t\tthis.addData(segment,index,true);\n\t\t\t},this);\n\n\t\t\t//Set up tooltip events on the chart\n\t\t\tif (this.options.showTooltips){\n\t\t\t\thelpers.bindEvents(this, this.options.tooltipEvents, function(evt){\n\t\t\t\t\tvar activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];\n\t\t\t\t\thelpers.each(this.segments,function(segment){\n\t\t\t\t\t\tsegment.restore([\"fillColor\"]);\n\t\t\t\t\t});\n\t\t\t\t\thelpers.each(activeSegments,function(activeSegment){\n\t\t\t\t\t\tactiveSegment.fillColor = activeSegment.highlightColor;\n\t\t\t\t\t});\n\t\t\t\t\tthis.showTooltip(activeSegments);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.render();\n\t\t},\n\t\tgetSegmentsAtEvent : function(e){\n\t\t\tvar segmentsArray = [];\n\n\t\t\tvar location = helpers.getRelativePosition(e);\n\n\t\t\thelpers.each(this.segments,function(segment){\n\t\t\t\tif (segment.inRange(location.x,location.y)) segmentsArray.push(segment);\n\t\t\t},this);\n\t\t\treturn segmentsArray;\n\t\t},\n\t\taddData : function(segment, atIndex, silent){\n\t\t\tvar index = atIndex || this.segments.length;\n\n\t\t\tthis.segments.splice(index, 0, new this.SegmentArc({\n\t\t\t\tfillColor: segment.color,\n\t\t\t\thighlightColor: segment.highlight || segment.color,\n\t\t\t\tlabel: segment.label,\n\t\t\t\tvalue: segment.value,\n\t\t\t\touterRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value),\n\t\t\t\tcircumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(),\n\t\t\t\tstartAngle: Math.PI * 1.5\n\t\t\t}));\n\t\t\tif (!silent){\n\t\t\t\tthis.reflow();\n\t\t\t\tthis.update();\n\t\t\t}\n\t\t},\n\t\tremoveData: function(atIndex){\n\t\t\tvar indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;\n\t\t\tthis.segments.splice(indexToDelete, 1);\n\t\t\tthis.reflow();\n\t\t\tthis.update();\n\t\t},\n\t\tcalculateTotal: function(data){\n\t\t\tthis.total = 0;\n\t\t\thelpers.each(data,function(segment){\n\t\t\t\tthis.total += segment.value;\n\t\t\t},this);\n\t\t\tthis.scale.valuesCount = this.segments.length;\n\t\t},\n\t\tupdateScaleRange: function(datapoints){\n\t\t\tvar valuesArray = [];\n\t\t\thelpers.each(datapoints,function(segment){\n\t\t\t\tvaluesArray.push(segment.value);\n\t\t\t});\n\n\t\t\tvar scaleSizes = (this.options.scaleOverride) ?\n\t\t\t\t{\n\t\t\t\t\tsteps: this.options.scaleSteps,\n\t\t\t\t\tstepValue: this.options.scaleStepWidth,\n\t\t\t\t\tmin: this.options.scaleStartValue,\n\t\t\t\t\tmax: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)\n\t\t\t\t} :\n\t\t\t\thelpers.calculateScaleRange(\n\t\t\t\t\tvaluesArray,\n\t\t\t\t\thelpers.min([this.chart.width, this.chart.height])/2,\n\t\t\t\t\tthis.options.scaleFontSize,\n\t\t\t\t\tthis.options.scaleBeginAtZero,\n\t\t\t\t\tthis.options.scaleIntegersOnly\n\t\t\t\t);\n\n\t\t\thelpers.extend(\n\t\t\t\tthis.scale,\n\t\t\t\tscaleSizes,\n\t\t\t\t{\n\t\t\t\t\tsize: helpers.min([this.chart.width, this.chart.height]),\n\t\t\t\t\txCenter: this.chart.width/2,\n\t\t\t\t\tyCenter: this.chart.height/2\n\t\t\t\t}\n\t\t\t);\n\n\t\t},\n\t\tupdate : function(){\n\t\t\tthis.calculateTotal(this.segments);\n\n\t\t\thelpers.each(this.segments,function(segment){\n\t\t\t\tsegment.save();\n\t\t\t});\n\t\t\t\n\t\t\tthis.reflow();\n\t\t\tthis.render();\n\t\t},\n\t\treflow : function(){\n\t\t\thelpers.extend(this.SegmentArc.prototype,{\n\t\t\t\tx : this.chart.width/2,\n\t\t\t\ty : this.chart.height/2\n\t\t\t});\n\t\t\tthis.updateScaleRange(this.segments);\n\t\t\tthis.scale.update();\n\n\t\t\thelpers.extend(this.scale,{\n\t\t\t\txCenter: this.chart.width/2,\n\t\t\t\tyCenter: this.chart.height/2\n\t\t\t});\n\n\t\t\thelpers.each(this.segments, function(segment){\n\t\t\t\tsegment.update({\n\t\t\t\t\touterRadius : this.scale.calculateCenterOffset(segment.value)\n\t\t\t\t});\n\t\t\t}, this);\n\n\t\t},\n\t\tdraw : function(ease){\n\t\t\tvar easingDecimal = ease || 1;\n\t\t\t//Clear & draw the canvas\n\t\t\tthis.clear();\n\t\t\thelpers.each(this.segments,function(segment, index){\n\t\t\t\tsegment.transition({\n\t\t\t\t\tcircumference : this.scale.getCircumference(),\n\t\t\t\t\touterRadius : this.scale.calculateCenterOffset(segment.value)\n\t\t\t\t},easingDecimal);\n\n\t\t\t\tsegment.endAngle = segment.startAngle + segment.circumference;\n\n\t\t\t\t// If we've removed the first segment we need to set the first one to\n\t\t\t\t// start at the top.\n\t\t\t\tif (index === 0){\n\t\t\t\t\tsegment.startAngle = Math.PI * 1.5;\n\t\t\t\t}\n\n\t\t\t\t//Check to see if it's the last segment, if not get the next and update the start angle\n\t\t\t\tif (index < this.segments.length - 1){\n\t\t\t\t\tthis.segments[index+1].startAngle = segment.endAngle;\n\t\t\t\t}\n\t\t\t\tsegment.draw();\n\t\t\t}, this);\n\t\t\tthis.scale.draw();\n\t\t}\n\t});\n\n}).call(this);\n(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\thelpers = Chart.helpers;\n\n\n\n\tChart.Type.extend({\n\t\tname: \"Radar\",\n\t\tdefaults:{\n\t\t\t//Boolean - Whether to show lines for each scale point\n\t\t\tscaleShowLine : true,\n\n\t\t\t//Boolean - Whether we show the angle lines out of the radar\n\t\t\tangleShowLineOut : true,\n\n\t\t\t//Boolean - Whether to show labels on the scale\n\t\t\tscaleShowLabels : false,\n\n\t\t\t// Boolean - Whether the scale should begin at zero\n\t\t\tscaleBeginAtZero : true,\n\n\t\t\t//String - Colour of the angle line\n\t\t\tangleLineColor : \"rgba(0,0,0,.1)\",\n\n\t\t\t//Number - Pixel width of the angle line\n\t\t\tangleLineWidth : 1,\n\n\t\t\t//String - Point label font declaration\n\t\t\tpointLabelFontFamily : \"'Arial'\",\n\n\t\t\t//String - Point label font weight\n\t\t\tpointLabelFontStyle : \"normal\",\n\n\t\t\t//Number - Point label font size in pixels\n\t\t\tpointLabelFontSize : 10,\n\n\t\t\t//String - Point label font colour\n\t\t\tpointLabelFontColor : \"#666\",\n\n\t\t\t//Boolean - Whether to show a dot for each point\n\t\t\tpointDot : true,\n\n\t\t\t//Number - Radius of each point dot in pixels\n\t\t\tpointDotRadius : 3,\n\n\t\t\t//Number - Pixel width of point dot stroke\n\t\t\tpointDotStrokeWidth : 1,\n\n\t\t\t//Number - amount extra to add to the radius to cater for hit detection outside the drawn point\n\t\t\tpointHitDetectionRadius : 20,\n\n\t\t\t//Boolean - Whether to show a stroke for datasets\n\t\t\tdatasetStroke : true,\n\n\t\t\t//Number - Pixel width of dataset stroke\n\t\t\tdatasetStrokeWidth : 2,\n\n\t\t\t//Boolean - Whether to fill the dataset with a colour\n\t\t\tdatasetFill : true,\n\n\t\t\t//String - A legend template\n\t\t\tlegendTemplate : \"
    -legend\\\"><% for (var i=0; i
  • \\\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
\"\n\n\t\t},\n\n\t\tinitialize: function(data){\n\t\t\tthis.PointClass = Chart.Point.extend({\n\t\t\t\tstrokeWidth : this.options.pointDotStrokeWidth,\n\t\t\t\tradius : this.options.pointDotRadius,\n\t\t\t\tdisplay: this.options.pointDot,\n\t\t\t\thitDetectionRadius : this.options.pointHitDetectionRadius,\n\t\t\t\tctx : this.chart.ctx\n\t\t\t});\n\n\t\t\tthis.datasets = [];\n\n\t\t\tthis.buildScale(data);\n\n\t\t\t//Set up tooltip events on the chart\n\t\t\tif (this.options.showTooltips){\n\t\t\t\thelpers.bindEvents(this, this.options.tooltipEvents, function(evt){\n\t\t\t\t\tvar activePointsCollection = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];\n\n\t\t\t\t\tthis.eachPoints(function(point){\n\t\t\t\t\t\tpoint.restore(['fillColor', 'strokeColor']);\n\t\t\t\t\t});\n\t\t\t\t\thelpers.each(activePointsCollection, function(activePoint){\n\t\t\t\t\t\tactivePoint.fillColor = activePoint.highlightFill;\n\t\t\t\t\t\tactivePoint.strokeColor = activePoint.highlightStroke;\n\t\t\t\t\t});\n\n\t\t\t\t\tthis.showTooltip(activePointsCollection);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t//Iterate through each of the datasets, and build this into a property of the chart\n\t\t\thelpers.each(data.datasets,function(dataset){\n\n\t\t\t\tvar datasetObject = {\n\t\t\t\t\tlabel: dataset.label || null,\n\t\t\t\t\tfillColor : dataset.fillColor,\n\t\t\t\t\tstrokeColor : dataset.strokeColor,\n\t\t\t\t\tpointColor : dataset.pointColor,\n\t\t\t\t\tpointStrokeColor : dataset.pointStrokeColor,\n\t\t\t\t\tpoints : []\n\t\t\t\t};\n\n\t\t\t\tthis.datasets.push(datasetObject);\n\n\t\t\t\thelpers.each(dataset.data,function(dataPoint,index){\n\t\t\t\t\t//Add a new point for each piece of data, passing any required data to draw.\n\t\t\t\t\tvar pointPosition;\n\t\t\t\t\tif (!this.scale.animation){\n\t\t\t\t\t\tpointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint));\n\t\t\t\t\t}\n\t\t\t\t\tdatasetObject.points.push(new this.PointClass({\n\t\t\t\t\t\tvalue : dataPoint,\n\t\t\t\t\t\tlabel : data.labels[index],\n\t\t\t\t\t\tdatasetLabel: dataset.label,\n\t\t\t\t\t\tx: (this.options.animation) ? this.scale.xCenter : pointPosition.x,\n\t\t\t\t\t\ty: (this.options.animation) ? this.scale.yCenter : pointPosition.y,\n\t\t\t\t\t\tstrokeColor : dataset.pointStrokeColor,\n\t\t\t\t\t\tfillColor : dataset.pointColor,\n\t\t\t\t\t\thighlightFill : dataset.pointHighlightFill || dataset.pointColor,\n\t\t\t\t\t\thighlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor\n\t\t\t\t\t}));\n\t\t\t\t},this);\n\n\t\t\t},this);\n\n\t\t\tthis.render();\n\t\t},\n\t\teachPoints : function(callback){\n\t\t\thelpers.each(this.datasets,function(dataset){\n\t\t\t\thelpers.each(dataset.points,callback,this);\n\t\t\t},this);\n\t\t},\n\n\t\tgetPointsAtEvent : function(evt){\n\t\t\tvar mousePosition = helpers.getRelativePosition(evt),\n\t\t\t\tfromCenter = helpers.getAngleFromPoint({\n\t\t\t\t\tx: this.scale.xCenter,\n\t\t\t\t\ty: this.scale.yCenter\n\t\t\t\t}, mousePosition);\n\n\t\t\tvar anglePerIndex = (Math.PI * 2) /this.scale.valuesCount,\n\t\t\t\tpointIndex = Math.round((fromCenter.angle - Math.PI * 1.5) / anglePerIndex),\n\t\t\t\tactivePointsCollection = [];\n\n\t\t\t// If we're at the top, make the pointIndex 0 to get the first of the array.\n\t\t\tif (pointIndex >= this.scale.valuesCount || pointIndex < 0){\n\t\t\t\tpointIndex = 0;\n\t\t\t}\n\n\t\t\tif (fromCenter.distance <= this.scale.drawingArea){\n\t\t\t\thelpers.each(this.datasets, function(dataset){\n\t\t\t\t\tactivePointsCollection.push(dataset.points[pointIndex]);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn activePointsCollection;\n\t\t},\n\n\t\tbuildScale : function(data){\n\t\t\tthis.scale = new Chart.RadialScale({\n\t\t\t\tdisplay: this.options.showScale,\n\t\t\t\tfontStyle: this.options.scaleFontStyle,\n\t\t\t\tfontSize: this.options.scaleFontSize,\n\t\t\t\tfontFamily: this.options.scaleFontFamily,\n\t\t\t\tfontColor: this.options.scaleFontColor,\n\t\t\t\tshowLabels: this.options.scaleShowLabels,\n\t\t\t\tshowLabelBackdrop: this.options.scaleShowLabelBackdrop,\n\t\t\t\tbackdropColor: this.options.scaleBackdropColor,\n\t\t\t\tbackdropPaddingY : this.options.scaleBackdropPaddingY,\n\t\t\t\tbackdropPaddingX: this.options.scaleBackdropPaddingX,\n\t\t\t\tlineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,\n\t\t\t\tlineColor: this.options.scaleLineColor,\n\t\t\t\tangleLineColor : this.options.angleLineColor,\n\t\t\t\tangleLineWidth : (this.options.angleShowLineOut) ? this.options.angleLineWidth : 0,\n\t\t\t\t// Point labels at the edge of each line\n\t\t\t\tpointLabelFontColor : this.options.pointLabelFontColor,\n\t\t\t\tpointLabelFontSize : this.options.pointLabelFontSize,\n\t\t\t\tpointLabelFontFamily : this.options.pointLabelFontFamily,\n\t\t\t\tpointLabelFontStyle : this.options.pointLabelFontStyle,\n\t\t\t\theight : this.chart.height,\n\t\t\t\twidth: this.chart.width,\n\t\t\t\txCenter: this.chart.width/2,\n\t\t\t\tyCenter: this.chart.height/2,\n\t\t\t\tctx : this.chart.ctx,\n\t\t\t\ttemplateString: this.options.scaleLabel,\n\t\t\t\tlabels: data.labels,\n\t\t\t\tvaluesCount: data.datasets[0].data.length\n\t\t\t});\n\n\t\t\tthis.scale.setScaleSize();\n\t\t\tthis.updateScaleRange(data.datasets);\n\t\t\tthis.scale.buildYLabels();\n\t\t},\n\t\tupdateScaleRange: function(datasets){\n\t\t\tvar valuesArray = (function(){\n\t\t\t\tvar totalDataArray = [];\n\t\t\t\thelpers.each(datasets,function(dataset){\n\t\t\t\t\tif (dataset.data){\n\t\t\t\t\t\ttotalDataArray = totalDataArray.concat(dataset.data);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\thelpers.each(dataset.points, function(point){\n\t\t\t\t\t\t\ttotalDataArray.push(point.value);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn totalDataArray;\n\t\t\t})();\n\n\n\t\t\tvar scaleSizes = (this.options.scaleOverride) ?\n\t\t\t\t{\n\t\t\t\t\tsteps: this.options.scaleSteps,\n\t\t\t\t\tstepValue: this.options.scaleStepWidth,\n\t\t\t\t\tmin: this.options.scaleStartValue,\n\t\t\t\t\tmax: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)\n\t\t\t\t} :\n\t\t\t\thelpers.calculateScaleRange(\n\t\t\t\t\tvaluesArray,\n\t\t\t\t\thelpers.min([this.chart.width, this.chart.height])/2,\n\t\t\t\t\tthis.options.scaleFontSize,\n\t\t\t\t\tthis.options.scaleBeginAtZero,\n\t\t\t\t\tthis.options.scaleIntegersOnly\n\t\t\t\t);\n\n\t\t\thelpers.extend(\n\t\t\t\tthis.scale,\n\t\t\t\tscaleSizes\n\t\t\t);\n\n\t\t},\n\t\taddData : function(valuesArray,label){\n\t\t\t//Map the values array for each of the datasets\n\t\t\tthis.scale.valuesCount++;\n\t\t\thelpers.each(valuesArray,function(value,datasetIndex){\n\t\t\t\tvar pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value));\n\t\t\t\tthis.datasets[datasetIndex].points.push(new this.PointClass({\n\t\t\t\t\tvalue : value,\n\t\t\t\t\tlabel : label,\n\t\t\t\t\tx: pointPosition.x,\n\t\t\t\t\ty: pointPosition.y,\n\t\t\t\t\tstrokeColor : this.datasets[datasetIndex].pointStrokeColor,\n\t\t\t\t\tfillColor : this.datasets[datasetIndex].pointColor\n\t\t\t\t}));\n\t\t\t},this);\n\n\t\t\tthis.scale.labels.push(label);\n\n\t\t\tthis.reflow();\n\n\t\t\tthis.update();\n\t\t},\n\t\tremoveData : function(){\n\t\t\tthis.scale.valuesCount--;\n\t\t\tthis.scale.labels.shift();\n\t\t\thelpers.each(this.datasets,function(dataset){\n\t\t\t\tdataset.points.shift();\n\t\t\t},this);\n\t\t\tthis.reflow();\n\t\t\tthis.update();\n\t\t},\n\t\tupdate : function(){\n\t\t\tthis.eachPoints(function(point){\n\t\t\t\tpoint.save();\n\t\t\t});\n\t\t\tthis.reflow();\n\t\t\tthis.render();\n\t\t},\n\t\treflow: function(){\n\t\t\thelpers.extend(this.scale, {\n\t\t\t\twidth : this.chart.width,\n\t\t\t\theight: this.chart.height,\n\t\t\t\tsize : helpers.min([this.chart.width, this.chart.height]),\n\t\t\t\txCenter: this.chart.width/2,\n\t\t\t\tyCenter: this.chart.height/2\n\t\t\t});\n\t\t\tthis.updateScaleRange(this.datasets);\n\t\t\tthis.scale.setScaleSize();\n\t\t\tthis.scale.buildYLabels();\n\t\t},\n\t\tdraw : function(ease){\n\t\t\tvar easeDecimal = ease || 1,\n\t\t\t\tctx = this.chart.ctx;\n\t\t\tthis.clear();\n\t\t\tthis.scale.draw();\n\n\t\t\thelpers.each(this.datasets,function(dataset){\n\n\t\t\t\t//Transition each point first so that the line and point drawing isn't out of sync\n\t\t\t\thelpers.each(dataset.points,function(point,index){\n\t\t\t\t\tif (point.hasValue()){\n\t\t\t\t\t\tpoint.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal);\n\t\t\t\t\t}\n\t\t\t\t},this);\n\n\n\n\t\t\t\t//Draw the line between all the points\n\t\t\t\tctx.lineWidth = this.options.datasetStrokeWidth;\n\t\t\t\tctx.strokeStyle = dataset.strokeColor;\n\t\t\t\tctx.beginPath();\n\t\t\t\thelpers.each(dataset.points,function(point,index){\n\t\t\t\t\tif (index === 0){\n\t\t\t\t\t\tctx.moveTo(point.x,point.y);\n\t\t\t\t\t}\n\t\t\t\t\telse{\n\t\t\t\t\t\tctx.lineTo(point.x,point.y);\n\t\t\t\t\t}\n\t\t\t\t},this);\n\t\t\t\tctx.closePath();\n\t\t\t\tctx.stroke();\n\n\t\t\t\tctx.fillStyle = dataset.fillColor;\n\t\t\t\tctx.fill();\n\n\t\t\t\t//Now draw the points over the line\n\t\t\t\t//A little inefficient double looping, but better than the line\n\t\t\t\t//lagging behind the point positions\n\t\t\t\thelpers.each(dataset.points,function(point){\n\t\t\t\t\tif (point.hasValue()){\n\t\t\t\t\t\tpoint.draw();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t},this);\n\n\t\t}\n\n\t});\n\n\n\n\n\n}).call(this);\n\n/***/ }),\n\n/***/ \"./pipelines/pipelines_times.js\":\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* WEBPACK VAR INJECTION */(function($) {/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_vendor_Chart__ = __webpack_require__(\"../../../vendor/assets/javascripts/Chart.js\");\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_vendor_Chart___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_vendor_Chart__);\n\n\ndocument.addEventListener('DOMContentLoaded', function () {\n var chartData = JSON.parse(document.getElementById('pipelinesTimesChartsData').innerHTML);\n var data = {\n labels: chartData.labels,\n datasets: [{\n fillColor: 'rgba(220,220,220,0.5)',\n strokeColor: 'rgba(220,220,220,1)',\n barStrokeWidth: 1,\n barValueSpacing: 1,\n barDatasetSpacing: 1,\n data: chartData.values\n }]\n };\n var ctx = $('#build_timesChart').get(0).getContext('2d');\n var options = {\n scaleOverlay: true,\n responsive: true,\n maintainAspectRatio: false\n };\n if (window.innerWidth < 768) {\n // Scale fonts if window width lower than 768px (iPad portrait)\n options.scaleFontSize = 8;\n }\n new __WEBPACK_IMPORTED_MODULE_0_vendor_Chart___default.a(ctx).Bar(data, options);\n});\n/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(\"../../../node_modules/jquery/dist/jquery.js\")))\n\n/***/ })\n\n},[\"./pipelines/pipelines_times.js\"]);\n\n\n// WEBPACK FOOTER //\n// pipelines_times.e46dc9aeaebdd9a38964.bundle.js","/* globals __webpack_amd_options__ */\r\nmodule.exports = __webpack_amd_options__;\r\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// (webpack)/buildin/amd-options.js\n// module id = ../../../node_modules/webpack/buildin/amd-options.js\n// module chunks = graphs graphs_charts pipelines_charts pipelines_times","/*!\n * Chart.js\n * http://chartjs.org/\n * Version: 1.0.2\n *\n * Copyright 2015 Nick Downie\n * Released under the MIT license\n * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md\n */\n\n\n(function(){\n\n\t\"use strict\";\n\n\t//Declare root variable - window in the browser, global on the server\n\tvar root = this,\n\t\tprevious = root.Chart;\n\n\t//Occupy the global variable of Chart, and create a simple base class\n\tvar Chart = function(context){\n\t\tvar chart = this;\n\t\tthis.canvas = context.canvas;\n\n\t\tthis.ctx = context;\n\n\t\t//Variables global to the chart\n\t\tvar computeDimension = function(element,dimension)\n\t\t{\n\t\t\tif (element['offset'+dimension])\n\t\t\t{\n\t\t\t\treturn element['offset'+dimension];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn document.defaultView.getComputedStyle(element).getPropertyValue(dimension);\n\t\t\t}\n\t\t}\n\n\t\tvar width = this.width = computeDimension(context.canvas,'Width');\n\t\tvar height = this.height = computeDimension(context.canvas,'Height');\n\n\t\t// Firefox requires this to work correctly\n\t\tcontext.canvas.width = width;\n\t\tcontext.canvas.height = height;\n\n\t\tvar width = this.width = context.canvas.width;\n\t\tvar height = this.height = context.canvas.height;\n\t\tthis.aspectRatio = this.width / this.height;\n\t\t//High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.\n\t\thelpers.retinaScale(this);\n\n\t\treturn this;\n\t};\n\t//Globally expose the defaults to allow for user updating/changing\n\tChart.defaults = {\n\t\tglobal: {\n\t\t\t// Boolean - Whether to animate the chart\n\t\t\tanimation: true,\n\n\t\t\t// Number - Number of animation steps\n\t\t\tanimationSteps: 60,\n\n\t\t\t// String - Animation easing effect\n\t\t\tanimationEasing: \"easeOutQuart\",\n\n\t\t\t// Boolean - If we should show the scale at all\n\t\t\tshowScale: true,\n\n\t\t\t// Boolean - If we want to override with a hard coded scale\n\t\t\tscaleOverride: false,\n\n\t\t\t// ** Required if scaleOverride is true **\n\t\t\t// Number - The number of steps in a hard coded scale\n\t\t\tscaleSteps: null,\n\t\t\t// Number - The value jump in the hard coded scale\n\t\t\tscaleStepWidth: null,\n\t\t\t// Number - The scale starting value\n\t\t\tscaleStartValue: null,\n\n\t\t\t// String - Colour of the scale line\n\t\t\tscaleLineColor: \"rgba(0,0,0,.1)\",\n\n\t\t\t// Number - Pixel width of the scale line\n\t\t\tscaleLineWidth: 1,\n\n\t\t\t// Boolean - Whether to show labels on the scale\n\t\t\tscaleShowLabels: true,\n\n\t\t\t// Interpolated JS string - can access value\n\t\t\tscaleLabel: \"<%=value%>\",\n\n\t\t\t// Boolean - Whether the scale should stick to integers, and not show any floats even if drawing space is there\n\t\t\tscaleIntegersOnly: true,\n\n\t\t\t// Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value\n\t\t\tscaleBeginAtZero: false,\n\n\t\t\t// String - Scale label font declaration for the scale label\n\t\t\tscaleFontFamily: \"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif\",\n\n\t\t\t// Number - Scale label font size in pixels\n\t\t\tscaleFontSize: 12,\n\n\t\t\t// String - Scale label font weight style\n\t\t\tscaleFontStyle: \"normal\",\n\n\t\t\t// String - Scale label font colour\n\t\t\tscaleFontColor: \"#666\",\n\n\t\t\t// Boolean - whether or not the chart should be responsive and resize when the browser does.\n\t\t\tresponsive: false,\n\n\t\t\t// Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container\n\t\t\tmaintainAspectRatio: true,\n\n\t\t\t// Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove\n\t\t\tshowTooltips: true,\n\n\t\t\t// Boolean - Determines whether to draw built-in tooltip or call custom tooltip function\n\t\t\tcustomTooltips: false,\n\n\t\t\t// Array - Array of string names to attach tooltip events\n\t\t\ttooltipEvents: [\"mousemove\", \"touchstart\", \"touchmove\", \"mouseout\"],\n\n\t\t\t// String - Tooltip background colour\n\t\t\ttooltipFillColor: \"rgba(0,0,0,0.8)\",\n\n\t\t\t// String - Tooltip label font declaration for the scale label\n\t\t\ttooltipFontFamily: \"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif\",\n\n\t\t\t// Number - Tooltip label font size in pixels\n\t\t\ttooltipFontSize: 14,\n\n\t\t\t// String - Tooltip font weight style\n\t\t\ttooltipFontStyle: \"normal\",\n\n\t\t\t// String - Tooltip label font colour\n\t\t\ttooltipFontColor: \"#fff\",\n\n\t\t\t// String - Tooltip title font declaration for the scale label\n\t\t\ttooltipTitleFontFamily: \"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif\",\n\n\t\t\t// Number - Tooltip title font size in pixels\n\t\t\ttooltipTitleFontSize: 14,\n\n\t\t\t// String - Tooltip title font weight style\n\t\t\ttooltipTitleFontStyle: \"bold\",\n\n\t\t\t// String - Tooltip title font colour\n\t\t\ttooltipTitleFontColor: \"#fff\",\n\n\t\t\t// Number - pixel width of padding around tooltip text\n\t\t\ttooltipYPadding: 6,\n\n\t\t\t// Number - pixel width of padding around tooltip text\n\t\t\ttooltipXPadding: 6,\n\n\t\t\t// Number - Size of the caret on the tooltip\n\t\t\ttooltipCaretSize: 8,\n\n\t\t\t// Number - Pixel radius of the tooltip border\n\t\t\ttooltipCornerRadius: 6,\n\n\t\t\t// Number - Pixel offset from point x to tooltip edge\n\t\t\ttooltipXOffset: 10,\n\n\t\t\t// String - Template string for single tooltips\n\t\t\ttooltipTemplate: \"<%if (label){%><%=label%>: <%}%><%= value %>\",\n\n\t\t\t// String - Template string for single tooltips\n\t\t\tmultiTooltipTemplate: \"<%= value %>\",\n\n\t\t\t// String - Colour behind the legend colour block\n\t\t\tmultiTooltipKeyBackground: '#fff',\n\n\t\t\t// Function - Will fire on animation progression.\n\t\t\tonAnimationProgress: function(){},\n\n\t\t\t// Function - Will fire on animation completion.\n\t\t\tonAnimationComplete: function(){}\n\n\t\t}\n\t};\n\n\t//Create a dictionary of chart types, to allow for extension of existing types\n\tChart.types = {};\n\n\t//Global Chart helpers object for utility methods and classes\n\tvar helpers = Chart.helpers = {};\n\n\t\t//-- Basic js utility methods\n\tvar each = helpers.each = function(loopable,callback,self){\n\t\t\tvar additionalArgs = Array.prototype.slice.call(arguments, 3);\n\t\t\t// Check to see if null or undefined firstly.\n\t\t\tif (loopable){\n\t\t\t\tif (loopable.length === +loopable.length){\n\t\t\t\t\tvar i;\n\t\t\t\t\tfor (i=0; i= 0; i--) {\n\t\t\t\tvar currentItem = arrayToSearch[i];\n\t\t\t\tif (filterCallback(currentItem)){\n\t\t\t\t\treturn currentItem;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tinherits = helpers.inherits = function(extensions){\n\t\t\t//Basic javascript inheritance based on the model created in Backbone.js\n\t\t\tvar parent = this;\n\t\t\tvar ChartElement = (extensions && extensions.hasOwnProperty(\"constructor\")) ? extensions.constructor : function(){ return parent.apply(this, arguments); };\n\n\t\t\tvar Surrogate = function(){ this.constructor = ChartElement;};\n\t\t\tSurrogate.prototype = parent.prototype;\n\t\t\tChartElement.prototype = new Surrogate();\n\n\t\t\tChartElement.extend = inherits;\n\n\t\t\tif (extensions) extend(ChartElement.prototype, extensions);\n\n\t\t\tChartElement.__super__ = parent.prototype;\n\n\t\t\treturn ChartElement;\n\t\t},\n\t\tnoop = helpers.noop = function(){},\n\t\tuid = helpers.uid = (function(){\n\t\t\tvar id=0;\n\t\t\treturn function(){\n\t\t\t\treturn \"chart-\" + id++;\n\t\t\t};\n\t\t})(),\n\t\twarn = helpers.warn = function(str){\n\t\t\t//Method for warning of errors\n\t\t\tif (window.console && typeof window.console.warn == \"function\") console.warn(str);\n\t\t},\n\t\tamd = helpers.amd = (typeof define == 'function' && define.amd),\n\t\t//-- Math methods\n\t\tisNumber = helpers.isNumber = function(n){\n\t\t\treturn !isNaN(parseFloat(n)) && isFinite(n);\n\t\t},\n\t\tmax = helpers.max = function(array){\n\t\t\treturn Math.max.apply( Math, array );\n\t\t},\n\t\tmin = helpers.min = function(array){\n\t\t\treturn Math.min.apply( Math, array );\n\t\t},\n\t\tcap = helpers.cap = function(valueToCap,maxValue,minValue){\n\t\t\tif(isNumber(maxValue)) {\n\t\t\t\tif( valueToCap > maxValue ) {\n\t\t\t\t\treturn maxValue;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(isNumber(minValue)){\n\t\t\t\tif ( valueToCap < minValue ){\n\t\t\t\t\treturn minValue;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn valueToCap;\n\t\t},\n\t\tgetDecimalPlaces = helpers.getDecimalPlaces = function(num){\n\t\t\tif (num%1!==0 && isNumber(num)){\n\t\t\t\treturn num.toString().split(\".\")[1].length;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t},\n\t\ttoRadians = helpers.radians = function(degrees){\n\t\t\treturn degrees * (Math.PI/180);\n\t\t},\n\t\t// Gets the angle from vertical upright to the point about a centre.\n\t\tgetAngleFromPoint = helpers.getAngleFromPoint = function(centrePoint, anglePoint){\n\t\t\tvar distanceFromXCenter = anglePoint.x - centrePoint.x,\n\t\t\t\tdistanceFromYCenter = anglePoint.y - centrePoint.y,\n\t\t\t\tradialDistanceFromCenter = Math.sqrt( distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);\n\n\n\t\t\tvar angle = Math.PI * 2 + Math.atan2(distanceFromYCenter, distanceFromXCenter);\n\n\t\t\t//If the segment is in the top left quadrant, we need to add another rotation to the angle\n\t\t\tif (distanceFromXCenter < 0 && distanceFromYCenter < 0){\n\t\t\t\tangle += Math.PI*2;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tangle: angle,\n\t\t\t\tdistance: radialDistanceFromCenter\n\t\t\t};\n\t\t},\n\t\taliasPixel = helpers.aliasPixel = function(pixelWidth){\n\t\t\treturn (pixelWidth % 2 === 0) ? 0 : 0.5;\n\t\t},\n\t\tsplineCurve = helpers.splineCurve = function(FirstPoint,MiddlePoint,AfterPoint,t){\n\t\t\t//Props to Rob Spencer at scaled innovation for his post on splining between points\n\t\t\t//http://scaledinnovation.com/analytics/splines/aboutSplines.html\n\t\t\tvar d01=Math.sqrt(Math.pow(MiddlePoint.x-FirstPoint.x,2)+Math.pow(MiddlePoint.y-FirstPoint.y,2)),\n\t\t\t\td12=Math.sqrt(Math.pow(AfterPoint.x-MiddlePoint.x,2)+Math.pow(AfterPoint.y-MiddlePoint.y,2)),\n\t\t\t\tfa=t*d01/(d01+d12),// scaling factor for triangle Ta\n\t\t\t\tfb=t*d12/(d01+d12);\n\t\t\treturn {\n\t\t\t\tinner : {\n\t\t\t\t\tx : MiddlePoint.x-fa*(AfterPoint.x-FirstPoint.x),\n\t\t\t\t\ty : MiddlePoint.y-fa*(AfterPoint.y-FirstPoint.y)\n\t\t\t\t},\n\t\t\t\touter : {\n\t\t\t\t\tx: MiddlePoint.x+fb*(AfterPoint.x-FirstPoint.x),\n\t\t\t\t\ty : MiddlePoint.y+fb*(AfterPoint.y-FirstPoint.y)\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\tcalculateOrderOfMagnitude = helpers.calculateOrderOfMagnitude = function(val){\n\t\t\treturn Math.floor(Math.log(val) / Math.LN10);\n\t\t},\n\t\tcalculateScaleRange = helpers.calculateScaleRange = function(valuesArray, drawingSize, textSize, startFromZero, integersOnly){\n\n\t\t\t//Set a minimum step of two - a point at the top of the graph, and a point at the base\n\t\t\tvar minSteps = 2,\n\t\t\t\tmaxSteps = Math.floor(drawingSize/(textSize * 1.5)),\n\t\t\t\tskipFitting = (minSteps >= maxSteps);\n\n\t\t\tvar maxValue = max(valuesArray),\n\t\t\t\tminValue = min(valuesArray);\n\n\t\t\t// We need some degree of seperation here to calculate the scales if all the values are the same\n\t\t\t// Adding/minusing 0.5 will give us a range of 1.\n\t\t\tif (maxValue === minValue){\n\t\t\t\tmaxValue += 0.5;\n\t\t\t\t// So we don't end up with a graph with a negative start value if we've said always start from zero\n\t\t\t\tif (minValue >= 0.5 && !startFromZero){\n\t\t\t\t\tminValue -= 0.5;\n\t\t\t\t}\n\t\t\t\telse{\n\t\t\t\t\t// Make up a whole number above the values\n\t\t\t\t\tmaxValue += 0.5;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar\tvalueRange = Math.abs(maxValue - minValue),\n\t\t\t\trangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange),\n\t\t\t\tgraphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),\n\t\t\t\tgraphMin = (startFromZero) ? 0 : Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),\n\t\t\t\tgraphRange = graphMax - graphMin,\n\t\t\t\tstepValue = Math.pow(10, rangeOrderOfMagnitude),\n\t\t\t\tnumberOfSteps = Math.round(graphRange / stepValue);\n\n\t\t\t//If we have more space on the graph we'll use it to give more definition to the data\n\t\t\twhile((numberOfSteps > maxSteps || (numberOfSteps * 2) < maxSteps) && !skipFitting) {\n\t\t\t\tif(numberOfSteps > maxSteps){\n\t\t\t\t\tstepValue *=2;\n\t\t\t\t\tnumberOfSteps = Math.round(graphRange/stepValue);\n\t\t\t\t\t// Don't ever deal with a decimal number of steps - cancel fitting and just use the minimum number of steps.\n\t\t\t\t\tif (numberOfSteps % 1 !== 0){\n\t\t\t\t\t\tskipFitting = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t//We can fit in double the amount of scale points on the scale\n\t\t\t\telse{\n\t\t\t\t\t//If user has declared ints only, and the step value isn't a decimal\n\t\t\t\t\tif (integersOnly && rangeOrderOfMagnitude >= 0){\n\t\t\t\t\t\t//If the user has said integers only, we need to check that making the scale more granular wouldn't make it a float\n\t\t\t\t\t\tif(stepValue/2 % 1 === 0){\n\t\t\t\t\t\t\tstepValue /=2;\n\t\t\t\t\t\t\tnumberOfSteps = Math.round(graphRange/stepValue);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//If it would make it a float break out of the loop\n\t\t\t\t\t\telse{\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t//If the scale doesn't have to be an int, make the scale more granular anyway.\n\t\t\t\t\telse{\n\t\t\t\t\t\tstepValue /=2;\n\t\t\t\t\t\tnumberOfSteps = Math.round(graphRange/stepValue);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (skipFitting){\n\t\t\t\tnumberOfSteps = minSteps;\n\t\t\t\tstepValue = graphRange / numberOfSteps;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tsteps : numberOfSteps,\n\t\t\t\tstepValue : stepValue,\n\t\t\t\tmin : graphMin,\n\t\t\t\tmax\t: graphMin + (numberOfSteps * stepValue)\n\t\t\t};\n\n\t\t},\n\t\t/* jshint ignore:start */\n\t\t// Blows up jshint errors based on the new Function constructor\n\t\t//Templating methods\n\t\t//Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/\n\t\ttemplate = helpers.template = function(templateString, valuesObject){\n\n\t\t\t// If templateString is function rather than string-template - call the function for valuesObject\n\n\t\t\tif(templateString instanceof Function){\n\t\t\t \treturn templateString(valuesObject);\n\t\t \t}\n\n\t\t\tvar cache = {};\n\t\t\tfunction tmpl(str, data){\n\t\t\t\t// Figure out if we're getting a template, or if we need to\n\t\t\t\t// load the template - and be sure to cache the result.\n\t\t\t\tvar fn = !/\\W/.test(str) ?\n\t\t\t\tcache[str] = cache[str] :\n\n\t\t\t\t// Generate a reusable function that will serve as a template\n\t\t\t\t// generator (and which will be cached).\n\t\t\t\tnew Function(\"obj\",\n\t\t\t\t\t\"var p=[],print=function(){p.push.apply(p,arguments);};\" +\n\n\t\t\t\t\t// Introduce the data as local variables using with(){}\n\t\t\t\t\t\"with(obj){p.push('\" +\n\n\t\t\t\t\t// Convert the template into pure JavaScript\n\t\t\t\t\tstr\n\t\t\t\t\t\t.replace(/[\\r\\t\\n]/g, \" \")\n\t\t\t\t\t\t.split(\"<%\").join(\"\\t\")\n\t\t\t\t\t\t.replace(/((^|%>)[^\\t]*)'/g, \"$1\\r\")\n\t\t\t\t\t\t.replace(/\\t=(.*?)%>/g, \"',$1,'\")\n\t\t\t\t\t\t.split(\"\\t\").join(\"');\")\n\t\t\t\t\t\t.split(\"%>\").join(\"p.push('\")\n\t\t\t\t\t\t.split(\"\\r\").join(\"\\\\'\") +\n\t\t\t\t\t\"');}return p.join('');\"\n\t\t\t\t);\n\n\t\t\t\t// Provide some basic currying to the user\n\t\t\t\treturn data ? fn( data ) : fn;\n\t\t\t}\n\t\t\treturn tmpl(templateString,valuesObject);\n\t\t},\n\t\t/* jshint ignore:end */\n\t\tgenerateLabels = helpers.generateLabels = function(templateString,numberOfSteps,graphMin,stepValue){\n\t\t\tvar labelsArray = new Array(numberOfSteps);\n\t\t\tif (labelTemplateString){\n\t\t\t\teach(labelsArray,function(val,index){\n\t\t\t\t\tlabelsArray[index] = template(templateString,{value: (graphMin + (stepValue*(index+1)))});\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn labelsArray;\n\t\t},\n\t\t//--Animation methods\n\t\t//Easing functions adapted from Robert Penner's easing equations\n\t\t//http://www.robertpenner.com/easing/\n\t\teasingEffects = helpers.easingEffects = {\n\t\t\tlinear: function (t) {\n\t\t\t\treturn t;\n\t\t\t},\n\t\t\teaseInQuad: function (t) {\n\t\t\t\treturn t * t;\n\t\t\t},\n\t\t\teaseOutQuad: function (t) {\n\t\t\t\treturn -1 * t * (t - 2);\n\t\t\t},\n\t\t\teaseInOutQuad: function (t) {\n\t\t\t\tif ((t /= 1 / 2) < 1) return 1 / 2 * t * t;\n\t\t\t\treturn -1 / 2 * ((--t) * (t - 2) - 1);\n\t\t\t},\n\t\t\teaseInCubic: function (t) {\n\t\t\t\treturn t * t * t;\n\t\t\t},\n\t\t\teaseOutCubic: function (t) {\n\t\t\t\treturn 1 * ((t = t / 1 - 1) * t * t + 1);\n\t\t\t},\n\t\t\teaseInOutCubic: function (t) {\n\t\t\t\tif ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t;\n\t\t\t\treturn 1 / 2 * ((t -= 2) * t * t + 2);\n\t\t\t},\n\t\t\teaseInQuart: function (t) {\n\t\t\t\treturn t * t * t * t;\n\t\t\t},\n\t\t\teaseOutQuart: function (t) {\n\t\t\t\treturn -1 * ((t = t / 1 - 1) * t * t * t - 1);\n\t\t\t},\n\t\t\teaseInOutQuart: function (t) {\n\t\t\t\tif ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t;\n\t\t\t\treturn -1 / 2 * ((t -= 2) * t * t * t - 2);\n\t\t\t},\n\t\t\teaseInQuint: function (t) {\n\t\t\t\treturn 1 * (t /= 1) * t * t * t * t;\n\t\t\t},\n\t\t\teaseOutQuint: function (t) {\n\t\t\t\treturn 1 * ((t = t / 1 - 1) * t * t * t * t + 1);\n\t\t\t},\n\t\t\teaseInOutQuint: function (t) {\n\t\t\t\tif ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t * t;\n\t\t\t\treturn 1 / 2 * ((t -= 2) * t * t * t * t + 2);\n\t\t\t},\n\t\t\teaseInSine: function (t) {\n\t\t\t\treturn -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1;\n\t\t\t},\n\t\t\teaseOutSine: function (t) {\n\t\t\t\treturn 1 * Math.sin(t / 1 * (Math.PI / 2));\n\t\t\t},\n\t\t\teaseInOutSine: function (t) {\n\t\t\t\treturn -1 / 2 * (Math.cos(Math.PI * t / 1) - 1);\n\t\t\t},\n\t\t\teaseInExpo: function (t) {\n\t\t\t\treturn (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1));\n\t\t\t},\n\t\t\teaseOutExpo: function (t) {\n\t\t\t\treturn (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1);\n\t\t\t},\n\t\t\teaseInOutExpo: function (t) {\n\t\t\t\tif (t === 0) return 0;\n\t\t\t\tif (t === 1) return 1;\n\t\t\t\tif ((t /= 1 / 2) < 1) return 1 / 2 * Math.pow(2, 10 * (t - 1));\n\t\t\t\treturn 1 / 2 * (-Math.pow(2, -10 * --t) + 2);\n\t\t\t},\n\t\t\teaseInCirc: function (t) {\n\t\t\t\tif (t >= 1) return t;\n\t\t\t\treturn -1 * (Math.sqrt(1 - (t /= 1) * t) - 1);\n\t\t\t},\n\t\t\teaseOutCirc: function (t) {\n\t\t\t\treturn 1 * Math.sqrt(1 - (t = t / 1 - 1) * t);\n\t\t\t},\n\t\t\teaseInOutCirc: function (t) {\n\t\t\t\tif ((t /= 1 / 2) < 1) return -1 / 2 * (Math.sqrt(1 - t * t) - 1);\n\t\t\t\treturn 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);\n\t\t\t},\n\t\t\teaseInElastic: function (t) {\n\t\t\t\tvar s = 1.70158;\n\t\t\t\tvar p = 0;\n\t\t\t\tvar a = 1;\n\t\t\t\tif (t === 0) return 0;\n\t\t\t\tif ((t /= 1) == 1) return 1;\n\t\t\t\tif (!p) p = 1 * 0.3;\n\t\t\t\tif (a < Math.abs(1)) {\n\t\t\t\t\ta = 1;\n\t\t\t\t\ts = p / 4;\n\t\t\t\t} else s = p / (2 * Math.PI) * Math.asin(1 / a);\n\t\t\t\treturn -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));\n\t\t\t},\n\t\t\teaseOutElastic: function (t) {\n\t\t\t\tvar s = 1.70158;\n\t\t\t\tvar p = 0;\n\t\t\t\tvar a = 1;\n\t\t\t\tif (t === 0) return 0;\n\t\t\t\tif ((t /= 1) == 1) return 1;\n\t\t\t\tif (!p) p = 1 * 0.3;\n\t\t\t\tif (a < Math.abs(1)) {\n\t\t\t\t\ta = 1;\n\t\t\t\t\ts = p / 4;\n\t\t\t\t} else s = p / (2 * Math.PI) * Math.asin(1 / a);\n\t\t\t\treturn a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;\n\t\t\t},\n\t\t\teaseInOutElastic: function (t) {\n\t\t\t\tvar s = 1.70158;\n\t\t\t\tvar p = 0;\n\t\t\t\tvar a = 1;\n\t\t\t\tif (t === 0) return 0;\n\t\t\t\tif ((t /= 1 / 2) == 2) return 1;\n\t\t\t\tif (!p) p = 1 * (0.3 * 1.5);\n\t\t\t\tif (a < Math.abs(1)) {\n\t\t\t\t\ta = 1;\n\t\t\t\t\ts = p / 4;\n\t\t\t\t} else s = p / (2 * Math.PI) * Math.asin(1 / a);\n\t\t\t\tif (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));\n\t\t\t\treturn a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1;\n\t\t\t},\n\t\t\teaseInBack: function (t) {\n\t\t\t\tvar s = 1.70158;\n\t\t\t\treturn 1 * (t /= 1) * t * ((s + 1) * t - s);\n\t\t\t},\n\t\t\teaseOutBack: function (t) {\n\t\t\t\tvar s = 1.70158;\n\t\t\t\treturn 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1);\n\t\t\t},\n\t\t\teaseInOutBack: function (t) {\n\t\t\t\tvar s = 1.70158;\n\t\t\t\tif ((t /= 1 / 2) < 1) return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s));\n\t\t\t\treturn 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);\n\t\t\t},\n\t\t\teaseInBounce: function (t) {\n\t\t\t\treturn 1 - easingEffects.easeOutBounce(1 - t);\n\t\t\t},\n\t\t\teaseOutBounce: function (t) {\n\t\t\t\tif ((t /= 1) < (1 / 2.75)) {\n\t\t\t\t\treturn 1 * (7.5625 * t * t);\n\t\t\t\t} else if (t < (2 / 2.75)) {\n\t\t\t\t\treturn 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75);\n\t\t\t\t} else if (t < (2.5 / 2.75)) {\n\t\t\t\t\treturn 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375);\n\t\t\t\t} else {\n\t\t\t\t\treturn 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375);\n\t\t\t\t}\n\t\t\t},\n\t\t\teaseInOutBounce: function (t) {\n\t\t\t\tif (t < 1 / 2) return easingEffects.easeInBounce(t * 2) * 0.5;\n\t\t\t\treturn easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5;\n\t\t\t}\n\t\t},\n\t\t//Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/\n\t\trequestAnimFrame = helpers.requestAnimFrame = (function(){\n\t\t\treturn window.requestAnimationFrame ||\n\t\t\t\twindow.webkitRequestAnimationFrame ||\n\t\t\t\twindow.mozRequestAnimationFrame ||\n\t\t\t\twindow.oRequestAnimationFrame ||\n\t\t\t\twindow.msRequestAnimationFrame ||\n\t\t\t\tfunction(callback) {\n\t\t\t\t\treturn window.setTimeout(callback, 1000 / 60);\n\t\t\t\t};\n\t\t})(),\n\t\tcancelAnimFrame = helpers.cancelAnimFrame = (function(){\n\t\t\treturn window.cancelAnimationFrame ||\n\t\t\t\twindow.webkitCancelAnimationFrame ||\n\t\t\t\twindow.mozCancelAnimationFrame ||\n\t\t\t\twindow.oCancelAnimationFrame ||\n\t\t\t\twindow.msCancelAnimationFrame ||\n\t\t\t\tfunction(callback) {\n\t\t\t\t\treturn window.clearTimeout(callback, 1000 / 60);\n\t\t\t\t};\n\t\t})(),\n\t\tanimationLoop = helpers.animationLoop = function(callback,totalSteps,easingString,onProgress,onComplete,chartInstance){\n\n\t\t\tvar currentStep = 0,\n\t\t\t\teasingFunction = easingEffects[easingString] || easingEffects.linear;\n\n\t\t\tvar animationFrame = function(){\n\t\t\t\tcurrentStep++;\n\t\t\t\tvar stepDecimal = currentStep/totalSteps;\n\t\t\t\tvar easeDecimal = easingFunction(stepDecimal);\n\n\t\t\t\tcallback.call(chartInstance,easeDecimal,stepDecimal, currentStep);\n\t\t\t\tonProgress.call(chartInstance,easeDecimal,stepDecimal);\n\t\t\t\tif (currentStep < totalSteps){\n\t\t\t\t\tchartInstance.animationFrame = requestAnimFrame(animationFrame);\n\t\t\t\t} else{\n\t\t\t\t\tonComplete.apply(chartInstance);\n\t\t\t\t}\n\t\t\t};\n\t\t\trequestAnimFrame(animationFrame);\n\t\t},\n\t\t//-- DOM methods\n\t\tgetRelativePosition = helpers.getRelativePosition = function(evt){\n\t\t\tvar mouseX, mouseY;\n\t\t\tvar e = evt.originalEvent || evt,\n\t\t\t\tcanvas = evt.currentTarget || evt.srcElement,\n\t\t\t\tboundingRect = canvas.getBoundingClientRect();\n\n\t\t\tif (e.touches){\n\t\t\t\tmouseX = e.touches[0].clientX - boundingRect.left;\n\t\t\t\tmouseY = e.touches[0].clientY - boundingRect.top;\n\n\t\t\t}\n\t\t\telse{\n\t\t\t\tmouseX = e.clientX - boundingRect.left;\n\t\t\t\tmouseY = e.clientY - boundingRect.top;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tx : mouseX,\n\t\t\t\ty : mouseY\n\t\t\t};\n\n\t\t},\n\t\taddEvent = helpers.addEvent = function(node,eventType,method){\n\t\t\tif (node.addEventListener){\n\t\t\t\tnode.addEventListener(eventType,method);\n\t\t\t} else if (node.attachEvent){\n\t\t\t\tnode.attachEvent(\"on\"+eventType, method);\n\t\t\t} else {\n\t\t\t\tnode[\"on\"+eventType] = method;\n\t\t\t}\n\t\t},\n\t\tremoveEvent = helpers.removeEvent = function(node, eventType, handler){\n\t\t\tif (node.removeEventListener){\n\t\t\t\tnode.removeEventListener(eventType, handler, false);\n\t\t\t} else if (node.detachEvent){\n\t\t\t\tnode.detachEvent(\"on\"+eventType,handler);\n\t\t\t} else{\n\t\t\t\tnode[\"on\" + eventType] = noop;\n\t\t\t}\n\t\t},\n\t\tbindEvents = helpers.bindEvents = function(chartInstance, arrayOfEvents, handler){\n\t\t\t// Create the events object if it's not already present\n\t\t\tif (!chartInstance.events) chartInstance.events = {};\n\n\t\t\teach(arrayOfEvents,function(eventName){\n\t\t\t\tchartInstance.events[eventName] = function(){\n\t\t\t\t\thandler.apply(chartInstance, arguments);\n\t\t\t\t};\n\t\t\t\taddEvent(chartInstance.chart.canvas,eventName,chartInstance.events[eventName]);\n\t\t\t});\n\t\t},\n\t\tunbindEvents = helpers.unbindEvents = function (chartInstance, arrayOfEvents) {\n\t\t\teach(arrayOfEvents, function(handler,eventName){\n\t\t\t\tremoveEvent(chartInstance.chart.canvas, eventName, handler);\n\t\t\t});\n\t\t},\n\t\tgetMaximumWidth = helpers.getMaximumWidth = function(domNode){\n\t\t\tvar container = domNode.parentNode;\n\t\t\t// TODO = check cross browser stuff with this.\n\t\t\treturn container.clientWidth;\n\t\t},\n\t\tgetMaximumHeight = helpers.getMaximumHeight = function(domNode){\n\t\t\tvar container = domNode.parentNode;\n\t\t\t// TODO = check cross browser stuff with this.\n\t\t\treturn container.clientHeight;\n\t\t},\n\t\tgetMaximumSize = helpers.getMaximumSize = helpers.getMaximumWidth, // legacy support\n\t\tretinaScale = helpers.retinaScale = function(chart){\n\t\t\tvar ctx = chart.ctx,\n\t\t\t\twidth = chart.canvas.width,\n\t\t\t\theight = chart.canvas.height;\n\n\t\t\tif (window.devicePixelRatio) {\n\t\t\t\tctx.canvas.style.width = width + \"px\";\n\t\t\t\tctx.canvas.style.height = height + \"px\";\n\t\t\t\tctx.canvas.height = height * window.devicePixelRatio;\n\t\t\t\tctx.canvas.width = width * window.devicePixelRatio;\n\t\t\t\tctx.scale(window.devicePixelRatio, window.devicePixelRatio);\n\t\t\t}\n\t\t},\n\t\t//-- Canvas methods\n\t\tclear = helpers.clear = function(chart){\n\t\t\tchart.ctx.clearRect(0,0,chart.width,chart.height);\n\t\t},\n\t\tfontString = helpers.fontString = function(pixelSize,fontStyle,fontFamily){\n\t\t\treturn fontStyle + \" \" + pixelSize+\"px \" + fontFamily;\n\t\t},\n\t\tlongestText = helpers.longestText = function(ctx,font,arrayOfStrings){\n\t\t\tctx.font = font;\n\t\t\tvar longest = 0;\n\t\t\teach(arrayOfStrings,function(string){\n\t\t\t\tvar textWidth = ctx.measureText(string).width;\n\t\t\t\tlongest = (textWidth > longest) ? textWidth : longest;\n\t\t\t});\n\t\t\treturn longest;\n\t\t},\n\t\tdrawRoundedRectangle = helpers.drawRoundedRectangle = function(ctx,x,y,width,height,radius){\n\t\t\tctx.beginPath();\n\t\t\tctx.moveTo(x + radius, y);\n\t\t\tctx.lineTo(x + width - radius, y);\n\t\t\tctx.quadraticCurveTo(x + width, y, x + width, y + radius);\n\t\t\tctx.lineTo(x + width, y + height - radius);\n\t\t\tctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\n\t\t\tctx.lineTo(x + radius, y + height);\n\t\t\tctx.quadraticCurveTo(x, y + height, x, y + height - radius);\n\t\t\tctx.lineTo(x, y + radius);\n\t\t\tctx.quadraticCurveTo(x, y, x + radius, y);\n\t\t\tctx.closePath();\n\t\t};\n\n\n\t//Store a reference to each instance - allowing us to globally resize chart instances on window resize.\n\t//Destroy method on the chart will remove the instance of the chart from this reference.\n\tChart.instances = {};\n\n\tChart.Type = function(data,options,chart){\n\t\tthis.options = options;\n\t\tthis.chart = chart;\n\t\tthis.id = uid();\n\t\t//Add the chart instance to the global namespace\n\t\tChart.instances[this.id] = this;\n\n\t\t// Initialize is always called when a chart type is created\n\t\t// By default it is a no op, but it should be extended\n\t\tif (options.responsive){\n\t\t\tthis.resize();\n\t\t}\n\t\tthis.initialize.call(this,data);\n\t};\n\n\t//Core methods that'll be a part of every chart type\n\textend(Chart.Type.prototype,{\n\t\tinitialize : function(){return this;},\n\t\tclear : function(){\n\t\t\tclear(this.chart);\n\t\t\treturn this;\n\t\t},\n\t\tstop : function(){\n\t\t\t// Stops any current animation loop occuring\n\t\t\tcancelAnimFrame(this.animationFrame);\n\t\t\treturn this;\n\t\t},\n\t\tresize : function(callback){\n\t\t\tthis.stop();\n\t\t\tvar canvas = this.chart.canvas,\n\t\t\t\tnewWidth = getMaximumWidth(this.chart.canvas),\n\t\t\t\tnewHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : getMaximumHeight(this.chart.canvas);\n\n\t\t\tcanvas.width = this.chart.width = newWidth;\n\t\t\tcanvas.height = this.chart.height = newHeight;\n\n\t\t\tretinaScale(this.chart);\n\n\t\t\tif (typeof callback === \"function\"){\n\t\t\t\tcallback.apply(this, Array.prototype.slice.call(arguments, 1));\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\t\treflow : noop,\n\t\trender : function(reflow){\n\t\t\tif (reflow){\n\t\t\t\tthis.reflow();\n\t\t\t}\n\t\t\tif (this.options.animation && !reflow){\n\t\t\t\thelpers.animationLoop(\n\t\t\t\t\tthis.draw,\n\t\t\t\t\tthis.options.animationSteps,\n\t\t\t\t\tthis.options.animationEasing,\n\t\t\t\t\tthis.options.onAnimationProgress,\n\t\t\t\t\tthis.options.onAnimationComplete,\n\t\t\t\t\tthis\n\t\t\t\t);\n\t\t\t}\n\t\t\telse{\n\t\t\t\tthis.draw();\n\t\t\t\tthis.options.onAnimationComplete.call(this);\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\t\tgenerateLegend : function(){\n\t\t\treturn template(this.options.legendTemplate,this);\n\t\t},\n\t\tdestroy : function(){\n\t\t\tthis.clear();\n\t\t\tunbindEvents(this, this.events);\n\t\t\tvar canvas = this.chart.canvas;\n\n\t\t\t// Reset canvas height/width attributes starts a fresh with the canvas context\n\t\t\tcanvas.width = this.chart.width;\n\t\t\tcanvas.height = this.chart.height;\n\n\t\t\t// < IE9 doesn't support removeProperty\n\t\t\tif (canvas.style.removeProperty) {\n\t\t\t\tcanvas.style.removeProperty('width');\n\t\t\t\tcanvas.style.removeProperty('height');\n\t\t\t} else {\n\t\t\t\tcanvas.style.removeAttribute('width');\n\t\t\t\tcanvas.style.removeAttribute('height');\n\t\t\t}\n\n\t\t\tdelete Chart.instances[this.id];\n\t\t},\n\t\tshowTooltip : function(ChartElements, forceRedraw){\n\t\t\t// Only redraw the chart if we've actually changed what we're hovering on.\n\t\t\tif (typeof this.activeElements === 'undefined') this.activeElements = [];\n\n\t\t\tvar isChanged = (function(Elements){\n\t\t\t\tvar changed = false;\n\n\t\t\t\tif (Elements.length !== this.activeElements.length){\n\t\t\t\t\tchanged = true;\n\t\t\t\t\treturn changed;\n\t\t\t\t}\n\n\t\t\t\teach(Elements, function(element, index){\n\t\t\t\t\tif (element !== this.activeElements[index]){\n\t\t\t\t\t\tchanged = true;\n\t\t\t\t\t}\n\t\t\t\t}, this);\n\t\t\t\treturn changed;\n\t\t\t}).call(this, ChartElements);\n\n\t\t\tif (!isChanged && !forceRedraw){\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse{\n\t\t\t\tthis.activeElements = ChartElements;\n\t\t\t}\n\t\t\tthis.draw();\n\t\t\tif(this.options.customTooltips){\n\t\t\t\tthis.options.customTooltips(false);\n\t\t\t}\n\t\t\tif (ChartElements.length > 0){\n\t\t\t\t// If we have multiple datasets, show a MultiTooltip for all of the data points at that index\n\t\t\t\tif (this.datasets && this.datasets.length > 1) {\n\t\t\t\t\tvar dataArray,\n\t\t\t\t\t\tdataIndex;\n\n\t\t\t\t\tfor (var i = this.datasets.length - 1; i >= 0; i--) {\n\t\t\t\t\t\tdataArray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments;\n\t\t\t\t\t\tdataIndex = indexOf(dataArray, ChartElements[0]);\n\t\t\t\t\t\tif (dataIndex !== -1){\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tvar tooltipLabels = [],\n\t\t\t\t\t\ttooltipColors = [],\n\t\t\t\t\t\tmedianPosition = (function(index) {\n\n\t\t\t\t\t\t\t// Get all the points at that particular index\n\t\t\t\t\t\t\tvar Elements = [],\n\t\t\t\t\t\t\t\tdataCollection,\n\t\t\t\t\t\t\t\txPositions = [],\n\t\t\t\t\t\t\t\tyPositions = [],\n\t\t\t\t\t\t\t\txMax,\n\t\t\t\t\t\t\t\tyMax,\n\t\t\t\t\t\t\t\txMin,\n\t\t\t\t\t\t\t\tyMin;\n\t\t\t\t\t\t\thelpers.each(this.datasets, function(dataset){\n\t\t\t\t\t\t\t\tdataCollection = dataset.points || dataset.bars || dataset.segments;\n\t\t\t\t\t\t\t\tif (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){\n\t\t\t\t\t\t\t\t\tElements.push(dataCollection[dataIndex]);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\thelpers.each(Elements, function(element) {\n\t\t\t\t\t\t\t\txPositions.push(element.x);\n\t\t\t\t\t\t\t\tyPositions.push(element.y);\n\n\n\t\t\t\t\t\t\t\t//Include any colour information about the element\n\t\t\t\t\t\t\t\ttooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element));\n\t\t\t\t\t\t\t\ttooltipColors.push({\n\t\t\t\t\t\t\t\t\tfill: element._saved.fillColor || element.fillColor,\n\t\t\t\t\t\t\t\t\tstroke: element._saved.strokeColor || element.strokeColor\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t}, this);\n\n\t\t\t\t\t\t\tyMin = min(yPositions);\n\t\t\t\t\t\t\tyMax = max(yPositions);\n\n\t\t\t\t\t\t\txMin = min(xPositions);\n\t\t\t\t\t\t\txMax = max(xPositions);\n\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tx: (xMin > this.chart.width/2) ? xMin : xMax,\n\t\t\t\t\t\t\t\ty: (yMin + yMax)/2\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}).call(this, dataIndex);\n\n\t\t\t\t\tnew Chart.MultiTooltip({\n\t\t\t\t\t\tx: medianPosition.x,\n\t\t\t\t\t\ty: medianPosition.y,\n\t\t\t\t\t\txPadding: this.options.tooltipXPadding,\n\t\t\t\t\t\tyPadding: this.options.tooltipYPadding,\n\t\t\t\t\t\txOffset: this.options.tooltipXOffset,\n\t\t\t\t\t\tfillColor: this.options.tooltipFillColor,\n\t\t\t\t\t\ttextColor: this.options.tooltipFontColor,\n\t\t\t\t\t\tfontFamily: this.options.tooltipFontFamily,\n\t\t\t\t\t\tfontStyle: this.options.tooltipFontStyle,\n\t\t\t\t\t\tfontSize: this.options.tooltipFontSize,\n\t\t\t\t\t\ttitleTextColor: this.options.tooltipTitleFontColor,\n\t\t\t\t\t\ttitleFontFamily: this.options.tooltipTitleFontFamily,\n\t\t\t\t\t\ttitleFontStyle: this.options.tooltipTitleFontStyle,\n\t\t\t\t\t\ttitleFontSize: this.options.tooltipTitleFontSize,\n\t\t\t\t\t\tcornerRadius: this.options.tooltipCornerRadius,\n\t\t\t\t\t\tlabels: tooltipLabels,\n\t\t\t\t\t\tlegendColors: tooltipColors,\n\t\t\t\t\t\tlegendColorBackground : this.options.multiTooltipKeyBackground,\n\t\t\t\t\t\ttitle: ChartElements[0].label,\n\t\t\t\t\t\tchart: this.chart,\n\t\t\t\t\t\tctx: this.chart.ctx,\n\t\t\t\t\t\tcustom: this.options.customTooltips\n\t\t\t\t\t}).draw();\n\n\t\t\t\t} else {\n\t\t\t\t\teach(ChartElements, function(Element) {\n\t\t\t\t\t\tvar tooltipPosition = Element.tooltipPosition();\n\t\t\t\t\t\tnew Chart.Tooltip({\n\t\t\t\t\t\t\tx: Math.round(tooltipPosition.x),\n\t\t\t\t\t\t\ty: Math.round(tooltipPosition.y),\n\t\t\t\t\t\t\txPadding: this.options.tooltipXPadding,\n\t\t\t\t\t\t\tyPadding: this.options.tooltipYPadding,\n\t\t\t\t\t\t\tfillColor: this.options.tooltipFillColor,\n\t\t\t\t\t\t\ttextColor: this.options.tooltipFontColor,\n\t\t\t\t\t\t\tfontFamily: this.options.tooltipFontFamily,\n\t\t\t\t\t\t\tfontStyle: this.options.tooltipFontStyle,\n\t\t\t\t\t\t\tfontSize: this.options.tooltipFontSize,\n\t\t\t\t\t\t\tcaretHeight: this.options.tooltipCaretSize,\n\t\t\t\t\t\t\tcornerRadius: this.options.tooltipCornerRadius,\n\t\t\t\t\t\t\ttext: template(this.options.tooltipTemplate, Element),\n\t\t\t\t\t\t\tchart: this.chart,\n\t\t\t\t\t\t\tcustom: this.options.customTooltips\n\t\t\t\t\t\t}).draw();\n\t\t\t\t\t}, this);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\t\ttoBase64Image : function(){\n\t\t\treturn this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);\n\t\t}\n\t});\n\n\tChart.Type.extend = function(extensions){\n\n\t\tvar parent = this;\n\n\t\tvar ChartType = function(){\n\t\t\treturn parent.apply(this,arguments);\n\t\t};\n\n\t\t//Copy the prototype object of the this class\n\t\tChartType.prototype = clone(parent.prototype);\n\t\t//Now overwrite some of the properties in the base class with the new extensions\n\t\textend(ChartType.prototype, extensions);\n\n\t\tChartType.extend = Chart.Type.extend;\n\n\t\tif (extensions.name || parent.prototype.name){\n\n\t\t\tvar chartName = extensions.name || parent.prototype.name;\n\t\t\t//Assign any potential default values of the new chart type\n\n\t\t\t//If none are defined, we'll use a clone of the chart type this is being extended from.\n\t\t\t//I.e. if we extend a line chart, we'll use the defaults from the line chart if our new chart\n\t\t\t//doesn't define some defaults of their own.\n\n\t\t\tvar baseDefaults = (Chart.defaults[parent.prototype.name]) ? clone(Chart.defaults[parent.prototype.name]) : {};\n\n\t\t\tChart.defaults[chartName] = extend(baseDefaults,extensions.defaults);\n\n\t\t\tChart.types[chartName] = ChartType;\n\n\t\t\t//Register this new chart type in the Chart prototype\n\t\t\tChart.prototype[chartName] = function(data,options){\n\t\t\t\tvar config = merge(Chart.defaults.global, Chart.defaults[chartName], options || {});\n\t\t\t\treturn new ChartType(data,config,this);\n\t\t\t};\n\t\t} else{\n\t\t\twarn(\"Name not provided for this chart, so it hasn't been registered\");\n\t\t}\n\t\treturn parent;\n\t};\n\n\tChart.Element = function(configuration){\n\t\textend(this,configuration);\n\t\tthis.initialize.apply(this,arguments);\n\t\tthis.save();\n\t};\n\textend(Chart.Element.prototype,{\n\t\tinitialize : function(){},\n\t\trestore : function(props){\n\t\t\tif (!props){\n\t\t\t\textend(this,this._saved);\n\t\t\t} else {\n\t\t\t\teach(props,function(key){\n\t\t\t\t\tthis[key] = this._saved[key];\n\t\t\t\t},this);\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\t\tsave : function(){\n\t\t\tthis._saved = clone(this);\n\t\t\tdelete this._saved._saved;\n\t\t\treturn this;\n\t\t},\n\t\tupdate : function(newProps){\n\t\t\teach(newProps,function(value,key){\n\t\t\t\tthis._saved[key] = this[key];\n\t\t\t\tthis[key] = value;\n\t\t\t},this);\n\t\t\treturn this;\n\t\t},\n\t\ttransition : function(props,ease){\n\t\t\teach(props,function(value,key){\n\t\t\t\tthis[key] = ((value - this._saved[key]) * ease) + this._saved[key];\n\t\t\t},this);\n\t\t\treturn this;\n\t\t},\n\t\ttooltipPosition : function(){\n\t\t\treturn {\n\t\t\t\tx : this.x,\n\t\t\t\ty : this.y\n\t\t\t};\n\t\t},\n\t\thasValue: function(){\n\t\t\treturn isNumber(this.value);\n\t\t}\n\t});\n\n\tChart.Element.extend = inherits;\n\n\n\tChart.Point = Chart.Element.extend({\n\t\tdisplay: true,\n\t\tinRange: function(chartX,chartY){\n\t\t\tvar hitDetectionRange = this.hitDetectionRadius + this.radius;\n\t\t\treturn ((Math.pow(chartX-this.x, 2)+Math.pow(chartY-this.y, 2)) < Math.pow(hitDetectionRange,2));\n\t\t},\n\t\tdraw : function(){\n\t\t\tif (this.display){\n\t\t\t\tvar ctx = this.ctx;\n\t\t\t\tctx.beginPath();\n\n\t\t\t\tctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);\n\t\t\t\tctx.closePath();\n\n\t\t\t\tctx.strokeStyle = this.strokeColor;\n\t\t\t\tctx.lineWidth = this.strokeWidth;\n\n\t\t\t\tctx.fillStyle = this.fillColor;\n\n\t\t\t\tctx.fill();\n\t\t\t\tctx.stroke();\n\t\t\t}\n\n\n\t\t\t//Quick debug for bezier curve splining\n\t\t\t//Highlights control points and the line between them.\n\t\t\t//Handy for dev - stripped in the min version.\n\n\t\t\t// ctx.save();\n\t\t\t// ctx.fillStyle = \"black\";\n\t\t\t// ctx.strokeStyle = \"black\"\n\t\t\t// ctx.beginPath();\n\t\t\t// ctx.arc(this.controlPoints.inner.x,this.controlPoints.inner.y, 2, 0, Math.PI*2);\n\t\t\t// ctx.fill();\n\n\t\t\t// ctx.beginPath();\n\t\t\t// ctx.arc(this.controlPoints.outer.x,this.controlPoints.outer.y, 2, 0, Math.PI*2);\n\t\t\t// ctx.fill();\n\n\t\t\t// ctx.moveTo(this.controlPoints.inner.x,this.controlPoints.inner.y);\n\t\t\t// ctx.lineTo(this.x, this.y);\n\t\t\t// ctx.lineTo(this.controlPoints.outer.x,this.controlPoints.outer.y);\n\t\t\t// ctx.stroke();\n\n\t\t\t// ctx.restore();\n\n\n\n\t\t}\n\t});\n\n\tChart.Arc = Chart.Element.extend({\n\t\tinRange : function(chartX,chartY){\n\n\t\t\tvar pointRelativePosition = helpers.getAngleFromPoint(this, {\n\t\t\t\tx: chartX,\n\t\t\t\ty: chartY\n\t\t\t});\n\n\t\t\t//Check if within the range of the open/close angle\n\t\t\tvar betweenAngles = (pointRelativePosition.angle >= this.startAngle && pointRelativePosition.angle <= this.endAngle),\n\t\t\t\twithinRadius = (pointRelativePosition.distance >= this.innerRadius && pointRelativePosition.distance <= this.outerRadius);\n\n\t\t\treturn (betweenAngles && withinRadius);\n\t\t\t//Ensure within the outside of the arc centre, but inside arc outer\n\t\t},\n\t\ttooltipPosition : function(){\n\t\t\tvar centreAngle = this.startAngle + ((this.endAngle - this.startAngle) / 2),\n\t\t\t\trangeFromCentre = (this.outerRadius - this.innerRadius) / 2 + this.innerRadius;\n\t\t\treturn {\n\t\t\t\tx : this.x + (Math.cos(centreAngle) * rangeFromCentre),\n\t\t\t\ty : this.y + (Math.sin(centreAngle) * rangeFromCentre)\n\t\t\t};\n\t\t},\n\t\tdraw : function(animationPercent){\n\n\t\t\tvar easingDecimal = animationPercent || 1;\n\n\t\t\tvar ctx = this.ctx;\n\n\t\t\tctx.beginPath();\n\n\t\t\tctx.arc(this.x, this.y, this.outerRadius, this.startAngle, this.endAngle);\n\n\t\t\tctx.arc(this.x, this.y, this.innerRadius, this.endAngle, this.startAngle, true);\n\n\t\t\tctx.closePath();\n\t\t\tctx.strokeStyle = this.strokeColor;\n\t\t\tctx.lineWidth = this.strokeWidth;\n\n\t\t\tctx.fillStyle = this.fillColor;\n\n\t\t\tctx.fill();\n\t\t\tctx.lineJoin = 'bevel';\n\n\t\t\tif (this.showStroke){\n\t\t\t\tctx.stroke();\n\t\t\t}\n\t\t}\n\t});\n\n\tChart.Rectangle = Chart.Element.extend({\n\t\tdraw : function(){\n\t\t\tvar ctx = this.ctx,\n\t\t\t\thalfWidth = this.width/2,\n\t\t\t\tleftX = this.x - halfWidth,\n\t\t\t\trightX = this.x + halfWidth,\n\t\t\t\ttop = this.base - (this.base - this.y),\n\t\t\t\thalfStroke = this.strokeWidth / 2;\n\n\t\t\t// Canvas doesn't allow us to stroke inside the width so we can\n\t\t\t// adjust the sizes to fit if we're setting a stroke on the line\n\t\t\tif (this.showStroke){\n\t\t\t\tleftX += halfStroke;\n\t\t\t\trightX -= halfStroke;\n\t\t\t\ttop += halfStroke;\n\t\t\t}\n\n\t\t\tctx.beginPath();\n\n\t\t\tctx.fillStyle = this.fillColor;\n\t\t\tctx.strokeStyle = this.strokeColor;\n\t\t\tctx.lineWidth = this.strokeWidth;\n\n\t\t\t// It'd be nice to keep this class totally generic to any rectangle\n\t\t\t// and simply specify which border to miss out.\n\t\t\tctx.moveTo(leftX, this.base);\n\t\t\tctx.lineTo(leftX, top);\n\t\t\tctx.lineTo(rightX, top);\n\t\t\tctx.lineTo(rightX, this.base);\n\t\t\tctx.fill();\n\t\t\tif (this.showStroke){\n\t\t\t\tctx.stroke();\n\t\t\t}\n\t\t},\n\t\theight : function(){\n\t\t\treturn this.base - this.y;\n\t\t},\n\t\tinRange : function(chartX,chartY){\n\t\t\treturn (chartX >= this.x - this.width/2 && chartX <= this.x + this.width/2) && (chartY >= this.y && chartY <= this.base);\n\t\t}\n\t});\n\n\tChart.Tooltip = Chart.Element.extend({\n\t\tdraw : function(){\n\n\t\t\tvar ctx = this.chart.ctx;\n\n\t\t\tctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);\n\n\t\t\tthis.xAlign = \"center\";\n\t\t\tthis.yAlign = \"above\";\n\n\t\t\t//Distance between the actual element.y position and the start of the tooltip caret\n\t\t\tvar caretPadding = this.caretPadding = 2;\n\n\t\t\tvar tooltipWidth = ctx.measureText(this.text).width + 2*this.xPadding,\n\t\t\t\ttooltipRectHeight = this.fontSize + 2*this.yPadding,\n\t\t\t\ttooltipHeight = tooltipRectHeight + this.caretHeight + caretPadding;\n\n\t\t\tif (this.x + tooltipWidth/2 >this.chart.width){\n\t\t\t\tthis.xAlign = \"left\";\n\t\t\t} else if (this.x - tooltipWidth/2 < 0){\n\t\t\t\tthis.xAlign = \"right\";\n\t\t\t}\n\n\t\t\tif (this.y - tooltipHeight < 0){\n\t\t\t\tthis.yAlign = \"below\";\n\t\t\t}\n\n\n\t\t\tvar tooltipX = this.x - tooltipWidth/2,\n\t\t\t\ttooltipY = this.y - tooltipHeight;\n\n\t\t\tctx.fillStyle = this.fillColor;\n\n\t\t\t// Custom Tooltips\n\t\t\tif(this.custom){\n\t\t\t\tthis.custom(this);\n\t\t\t}\n\t\t\telse{\n\t\t\t\tswitch(this.yAlign)\n\t\t\t\t{\n\t\t\t\tcase \"above\":\n\t\t\t\t\t//Draw a caret above the x/y\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(this.x,this.y - caretPadding);\n\t\t\t\t\tctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight));\n\t\t\t\t\tctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight));\n\t\t\t\t\tctx.closePath();\n\t\t\t\t\tctx.fill();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"below\":\n\t\t\t\t\ttooltipY = this.y + caretPadding + this.caretHeight;\n\t\t\t\t\t//Draw a caret below the x/y\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(this.x, this.y + caretPadding);\n\t\t\t\t\tctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight);\n\t\t\t\t\tctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight);\n\t\t\t\t\tctx.closePath();\n\t\t\t\t\tctx.fill();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tswitch(this.xAlign)\n\t\t\t\t{\n\t\t\t\tcase \"left\":\n\t\t\t\t\ttooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"right\":\n\t\t\t\t\ttooltipX = this.x - (this.cornerRadius + this.caretHeight);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdrawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius);\n\n\t\t\t\tctx.fill();\n\n\t\t\t\tctx.fillStyle = this.textColor;\n\t\t\t\tctx.textAlign = \"center\";\n\t\t\t\tctx.textBaseline = \"middle\";\n\t\t\t\tctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2);\n\t\t\t}\n\t\t}\n\t});\n\n\tChart.MultiTooltip = Chart.Element.extend({\n\t\tinitialize : function(){\n\t\t\tthis.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);\n\n\t\t\tthis.titleFont = fontString(this.titleFontSize,this.titleFontStyle,this.titleFontFamily);\n\n\t\t\tthis.height = (this.labels.length * this.fontSize) + ((this.labels.length-1) * (this.fontSize/2)) + (this.yPadding*2) + this.titleFontSize *1.5;\n\n\t\t\tthis.ctx.font = this.titleFont;\n\n\t\t\tvar titleWidth = this.ctx.measureText(this.title).width,\n\t\t\t\t//Label has a legend square as well so account for this.\n\t\t\t\tlabelWidth = longestText(this.ctx,this.font,this.labels) + this.fontSize + 3,\n\t\t\t\tlongestTextWidth = max([labelWidth,titleWidth]);\n\n\t\t\tthis.width = longestTextWidth + (this.xPadding*2);\n\n\n\t\t\tvar halfHeight = this.height/2;\n\n\t\t\t//Check to ensure the height will fit on the canvas\n\t\t\tif (this.y - halfHeight < 0 ){\n\t\t\t\tthis.y = halfHeight;\n\t\t\t} else if (this.y + halfHeight > this.chart.height){\n\t\t\t\tthis.y = this.chart.height - halfHeight;\n\t\t\t}\n\n\t\t\t//Decide whether to align left or right based on position on canvas\n\t\t\tif (this.x > this.chart.width/2){\n\t\t\t\tthis.x -= this.xOffset + this.width;\n\t\t\t} else {\n\t\t\t\tthis.x += this.xOffset;\n\t\t\t}\n\n\n\t\t},\n\t\tgetLineHeight : function(index){\n\t\t\tvar baseLineHeight = this.y - (this.height/2) + this.yPadding,\n\t\t\t\tafterTitleIndex = index-1;\n\n\t\t\t//If the index is zero, we're getting the title\n\t\t\tif (index === 0){\n\t\t\t\treturn baseLineHeight + this.titleFontSize/2;\n\t\t\t} else{\n\t\t\t\treturn baseLineHeight + ((this.fontSize*1.5*afterTitleIndex) + this.fontSize/2) + this.titleFontSize * 1.5;\n\t\t\t}\n\n\t\t},\n\t\tdraw : function(){\n\t\t\t// Custom Tooltips\n\t\t\tif(this.custom){\n\t\t\t\tthis.custom(this);\n\t\t\t}\n\t\t\telse{\n\t\t\t\tdrawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius);\n\t\t\t\tvar ctx = this.ctx;\n\t\t\t\tctx.fillStyle = this.fillColor;\n\t\t\t\tctx.fill();\n\t\t\t\tctx.closePath();\n\n\t\t\t\tctx.textAlign = \"left\";\n\t\t\t\tctx.textBaseline = \"middle\";\n\t\t\t\tctx.fillStyle = this.titleTextColor;\n\t\t\t\tctx.font = this.titleFont;\n\n\t\t\t\tctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0));\n\n\t\t\t\tctx.font = this.font;\n\t\t\t\thelpers.each(this.labels,function(label,index){\n\t\t\t\t\tctx.fillStyle = this.textColor;\n\t\t\t\t\tctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1));\n\n\t\t\t\t\t//A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas)\n\t\t\t\t\t//ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);\n\t\t\t\t\t//Instead we'll make a white filled block to put the legendColour palette over.\n\n\t\t\t\t\tctx.fillStyle = this.legendColorBackground;\n\t\t\t\t\tctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);\n\n\t\t\t\t\tctx.fillStyle = this.legendColors[index].fill;\n\t\t\t\t\tctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);\n\n\n\t\t\t\t},this);\n\t\t\t}\n\t\t}\n\t});\n\n\tChart.Scale = Chart.Element.extend({\n\t\tinitialize : function(){\n\t\t\tthis.fit();\n\t\t},\n\t\tbuildYLabels : function(){\n\t\t\tthis.yLabels = [];\n\n\t\t\tvar stepDecimalPlaces = getDecimalPlaces(this.stepValue);\n\n\t\t\tfor (var i=0; i<=this.steps; i++){\n\t\t\t\tthis.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));\n\t\t\t}\n\t\t\tthis.yLabelWidth = (this.display && this.showLabels) ? longestText(this.ctx,this.font,this.yLabels) : 0;\n\t\t},\n\t\taddXLabel : function(label){\n\t\t\tthis.xLabels.push(label);\n\t\t\tthis.valuesCount++;\n\t\t\tthis.fit();\n\t\t},\n\t\tremoveXLabel : function(){\n\t\t\tthis.xLabels.shift();\n\t\t\tthis.valuesCount--;\n\t\t\tthis.fit();\n\t\t},\n\t\t// Fitting loop to rotate x Labels and figure out what fits there, and also calculate how many Y steps to use\n\t\tfit: function(){\n\t\t\t// First we need the width of the yLabels, assuming the xLabels aren't rotated\n\n\t\t\t// To do that we need the base line at the top and base of the chart, assuming there is no x label rotation\n\t\t\tthis.startPoint = (this.display) ? this.fontSize : 0;\n\t\t\tthis.endPoint = (this.display) ? this.height - (this.fontSize * 1.5) - 5 : this.height; // -5 to pad labels\n\n\t\t\t// Apply padding settings to the start and end point.\n\t\t\tthis.startPoint += this.padding;\n\t\t\tthis.endPoint -= this.padding;\n\n\t\t\t// Cache the starting height, so can determine if we need to recalculate the scale yAxis\n\t\t\tvar cachedHeight = this.endPoint - this.startPoint,\n\t\t\t\tcachedYLabelWidth;\n\n\t\t\t// Build the current yLabels so we have an idea of what size they'll be to start\n\t\t\t/*\n\t\t\t *\tThis sets what is returned from calculateScaleRange as static properties of this class:\n\t\t\t *\n\t\t\t\tthis.steps;\n\t\t\t\tthis.stepValue;\n\t\t\t\tthis.min;\n\t\t\t\tthis.max;\n\t\t\t *\n\t\t\t */\n\t\t\tthis.calculateYRange(cachedHeight);\n\n\t\t\t// With these properties set we can now build the array of yLabels\n\t\t\t// and also the width of the largest yLabel\n\t\t\tthis.buildYLabels();\n\n\t\t\tthis.calculateXLabelRotation();\n\n\t\t\twhile((cachedHeight > this.endPoint - this.startPoint)){\n\t\t\t\tcachedHeight = this.endPoint - this.startPoint;\n\t\t\t\tcachedYLabelWidth = this.yLabelWidth;\n\n\t\t\t\tthis.calculateYRange(cachedHeight);\n\t\t\t\tthis.buildYLabels();\n\n\t\t\t\t// Only go through the xLabel loop again if the yLabel width has changed\n\t\t\t\tif (cachedYLabelWidth < this.yLabelWidth){\n\t\t\t\t\tthis.calculateXLabelRotation();\n\t\t\t\t}\n\t\t\t}\n\n\t\t},\n\t\tcalculateXLabelRotation : function(){\n\t\t\t//Get the width of each grid by calculating the difference\n\t\t\t//between x offsets between 0 and 1.\n\n\t\t\tthis.ctx.font = this.font;\n\n\t\t\tvar firstWidth = this.ctx.measureText(this.xLabels[0]).width,\n\t\t\t\tlastWidth = this.ctx.measureText(this.xLabels[this.xLabels.length - 1]).width,\n\t\t\t\tfirstRotated,\n\t\t\t\tlastRotated;\n\n\n\t\t\tthis.xScalePaddingRight = lastWidth/2 + 3;\n\t\t\tthis.xScalePaddingLeft = (firstWidth/2 > this.yLabelWidth + 10) ? firstWidth/2 : this.yLabelWidth + 10;\n\n\t\t\tthis.xLabelRotation = 0;\n\t\t\tif (this.display){\n\t\t\t\tvar originalLabelWidth = longestText(this.ctx,this.font,this.xLabels),\n\t\t\t\t\tcosRotation,\n\t\t\t\t\tfirstRotatedWidth;\n\t\t\t\tthis.xLabelWidth = originalLabelWidth;\n\t\t\t\t//Allow 3 pixels x2 padding either side for label readability\n\t\t\t\tvar xGridWidth = Math.floor(this.calculateX(1) - this.calculateX(0)) - 6;\n\n\t\t\t\t//Max label rotate should be 90 - also act as a loop counter\n\t\t\t\twhile ((this.xLabelWidth > xGridWidth && this.xLabelRotation === 0) || (this.xLabelWidth > xGridWidth && this.xLabelRotation <= 90 && this.xLabelRotation > 0)){\n\t\t\t\t\tcosRotation = Math.cos(toRadians(this.xLabelRotation));\n\n\t\t\t\t\tfirstRotated = cosRotation * firstWidth;\n\t\t\t\t\tlastRotated = cosRotation * lastWidth;\n\n\t\t\t\t\t// We're right aligning the text now.\n\t\t\t\t\tif (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8){\n\t\t\t\t\t\tthis.xScalePaddingLeft = firstRotated + this.fontSize / 2;\n\t\t\t\t\t}\n\t\t\t\t\tthis.xScalePaddingRight = this.fontSize/2;\n\n\n\t\t\t\t\tthis.xLabelRotation++;\n\t\t\t\t\tthis.xLabelWidth = cosRotation * originalLabelWidth;\n\n\t\t\t\t}\n\t\t\t\tif (this.xLabelRotation > 0){\n\t\t\t\t\tthis.endPoint -= Math.sin(toRadians(this.xLabelRotation))*originalLabelWidth + 3;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse{\n\t\t\t\tthis.xLabelWidth = 0;\n\t\t\t\tthis.xScalePaddingRight = this.padding;\n\t\t\t\tthis.xScalePaddingLeft = this.padding;\n\t\t\t}\n\n\t\t},\n\t\t// Needs to be overidden in each Chart type\n\t\t// Otherwise we need to pass all the data into the scale class\n\t\tcalculateYRange: noop,\n\t\tdrawingArea: function(){\n\t\t\treturn this.startPoint - this.endPoint;\n\t\t},\n\t\tcalculateY : function(value){\n\t\t\tvar scalingFactor = this.drawingArea() / (this.min - this.max);\n\t\t\treturn this.endPoint - (scalingFactor * (value - this.min));\n\t\t},\n\t\tcalculateX : function(index){\n\t\t\tvar isRotated = (this.xLabelRotation > 0),\n\t\t\t\t// innerWidth = (this.offsetGridLines) ? this.width - offsetLeft - this.padding : this.width - (offsetLeft + halfLabelWidth * 2) - this.padding,\n\t\t\t\tinnerWidth = this.width - (this.xScalePaddingLeft + this.xScalePaddingRight),\n\t\t\t\tvalueWidth = innerWidth/Math.max((this.valuesCount - ((this.offsetGridLines) ? 0 : 1)), 1),\n\t\t\t\tvalueOffset = (valueWidth * index) + this.xScalePaddingLeft;\n\n\t\t\tif (this.offsetGridLines){\n\t\t\t\tvalueOffset += (valueWidth/2);\n\t\t\t}\n\n\t\t\treturn Math.round(valueOffset);\n\t\t},\n\t\tupdate : function(newProps){\n\t\t\thelpers.extend(this, newProps);\n\t\t\tthis.fit();\n\t\t},\n\t\tdraw : function(){\n\t\t\tvar ctx = this.ctx,\n\t\t\t\tyLabelGap = (this.endPoint - this.startPoint) / this.steps,\n\t\t\t\txStart = Math.round(this.xScalePaddingLeft);\n\t\t\tif (this.display){\n\t\t\t\tctx.fillStyle = this.textColor;\n\t\t\t\tctx.font = this.font;\n\t\t\t\teach(this.yLabels,function(labelString,index){\n\t\t\t\t\tvar yLabelCenter = this.endPoint - (yLabelGap * index),\n\t\t\t\t\t\tlinePositionY = Math.round(yLabelCenter),\n\t\t\t\t\t\tdrawHorizontalLine = this.showHorizontalLines;\n\n\t\t\t\t\tctx.textAlign = \"right\";\n\t\t\t\t\tctx.textBaseline = \"middle\";\n\t\t\t\t\tif (this.showLabels){\n\t\t\t\t\t\tctx.fillText(labelString,xStart - 10,yLabelCenter);\n\t\t\t\t\t}\n\n\t\t\t\t\t// This is X axis, so draw it\n\t\t\t\t\tif (index === 0 && !drawHorizontalLine){\n\t\t\t\t\t\tdrawHorizontalLine = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (drawHorizontalLine){\n\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t}\n\n\t\t\t\t\tif (index > 0){\n\t\t\t\t\t\t// This is a grid line in the centre, so drop that\n\t\t\t\t\t\tctx.lineWidth = this.gridLineWidth;\n\t\t\t\t\t\tctx.strokeStyle = this.gridLineColor;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// This is the first line on the scale\n\t\t\t\t\t\tctx.lineWidth = this.lineWidth;\n\t\t\t\t\t\tctx.strokeStyle = this.lineColor;\n\t\t\t\t\t}\n\n\t\t\t\t\tlinePositionY += helpers.aliasPixel(ctx.lineWidth);\n\n\t\t\t\t\tif(drawHorizontalLine){\n\t\t\t\t\t\tctx.moveTo(xStart, linePositionY);\n\t\t\t\t\t\tctx.lineTo(this.width, linePositionY);\n\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t\tctx.closePath();\n\t\t\t\t\t}\n\n\t\t\t\t\tctx.lineWidth = this.lineWidth;\n\t\t\t\t\tctx.strokeStyle = this.lineColor;\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(xStart - 5, linePositionY);\n\t\t\t\t\tctx.lineTo(xStart, linePositionY);\n\t\t\t\t\tctx.stroke();\n\t\t\t\t\tctx.closePath();\n\n\t\t\t\t},this);\n\n\t\t\t\teach(this.xLabels,function(label,index){\n\t\t\t\t\tvar xPos = this.calculateX(index) + aliasPixel(this.lineWidth),\n\t\t\t\t\t\t// Check to see if line/bar here and decide where to place the line\n\t\t\t\t\t\tlinePos = this.calculateX(index - (this.offsetGridLines ? 0.5 : 0)) + aliasPixel(this.lineWidth),\n\t\t\t\t\t\tisRotated = (this.xLabelRotation > 0),\n\t\t\t\t\t\tdrawVerticalLine = this.showVerticalLines;\n\n\t\t\t\t\t// This is Y axis, so draw it\n\t\t\t\t\tif (index === 0 && !drawVerticalLine){\n\t\t\t\t\t\tdrawVerticalLine = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (drawVerticalLine){\n\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t}\n\n\t\t\t\t\tif (index > 0){\n\t\t\t\t\t\t// This is a grid line in the centre, so drop that\n\t\t\t\t\t\tctx.lineWidth = this.gridLineWidth;\n\t\t\t\t\t\tctx.strokeStyle = this.gridLineColor;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// This is the first line on the scale\n\t\t\t\t\t\tctx.lineWidth = this.lineWidth;\n\t\t\t\t\t\tctx.strokeStyle = this.lineColor;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (drawVerticalLine){\n\t\t\t\t\t\tctx.moveTo(linePos,this.endPoint);\n\t\t\t\t\t\tctx.lineTo(linePos,this.startPoint - 3);\n\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t\tctx.closePath();\n\t\t\t\t\t}\n\n\n\t\t\t\t\tctx.lineWidth = this.lineWidth;\n\t\t\t\t\tctx.strokeStyle = this.lineColor;\n\n\n\t\t\t\t\t// Small lines at the bottom of the base grid line\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(linePos,this.endPoint);\n\t\t\t\t\tctx.lineTo(linePos,this.endPoint + 5);\n\t\t\t\t\tctx.stroke();\n\t\t\t\t\tctx.closePath();\n\n\t\t\t\t\tctx.save();\n\t\t\t\t\tctx.translate(xPos,(isRotated) ? this.endPoint + 12 : this.endPoint + 8);\n\t\t\t\t\tctx.rotate(toRadians(this.xLabelRotation)*-1);\n\t\t\t\t\tctx.font = this.font;\n\t\t\t\t\tctx.textAlign = (isRotated) ? \"right\" : \"center\";\n\t\t\t\t\tctx.textBaseline = (isRotated) ? \"middle\" : \"top\";\n\t\t\t\t\tctx.fillText(label, 0, 0);\n\t\t\t\t\tctx.restore();\n\t\t\t\t},this);\n\n\t\t\t}\n\t\t}\n\n\t});\n\n\tChart.RadialScale = Chart.Element.extend({\n\t\tinitialize: function(){\n\t\t\tthis.size = min([this.height, this.width]);\n\t\t\tthis.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);\n\t\t},\n\t\tcalculateCenterOffset: function(value){\n\t\t\t// Take into account half font size + the yPadding of the top value\n\t\t\tvar scalingFactor = this.drawingArea / (this.max - this.min);\n\n\t\t\treturn (value - this.min) * scalingFactor;\n\t\t},\n\t\tupdate : function(){\n\t\t\tif (!this.lineArc){\n\t\t\t\tthis.setScaleSize();\n\t\t\t} else {\n\t\t\t\tthis.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);\n\t\t\t}\n\t\t\tthis.buildYLabels();\n\t\t},\n\t\tbuildYLabels: function(){\n\t\t\tthis.yLabels = [];\n\n\t\t\tvar stepDecimalPlaces = getDecimalPlaces(this.stepValue);\n\n\t\t\tfor (var i=0; i<=this.steps; i++){\n\t\t\t\tthis.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));\n\t\t\t}\n\t\t},\n\t\tgetCircumference : function(){\n\t\t\treturn ((Math.PI*2) / this.valuesCount);\n\t\t},\n\t\tsetScaleSize: function(){\n\t\t\t/*\n\t\t\t * Right, this is really confusing and there is a lot of maths going on here\n\t\t\t * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9\n\t\t\t *\n\t\t\t * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif\n\t\t\t *\n\t\t\t * Solution:\n\t\t\t *\n\t\t\t * We assume the radius of the polygon is half the size of the canvas at first\n\t\t\t * at each index we check if the text overlaps.\n\t\t\t *\n\t\t\t * Where it does, we store that angle and that index.\n\t\t\t *\n\t\t\t * After finding the largest index and angle we calculate how much we need to remove\n\t\t\t * from the shape radius to move the point inwards by that x.\n\t\t\t *\n\t\t\t * We average the left and right distances to get the maximum shape radius that can fit in the box\n\t\t\t * along with labels.\n\t\t\t *\n\t\t\t * Once we have that, we can find the centre point for the chart, by taking the x text protrusion\n\t\t\t * on each side, removing that from the size, halving it and adding the left x protrusion width.\n\t\t\t *\n\t\t\t * This will mean we have a shape fitted to the canvas, as large as it can be with the labels\n\t\t\t * and position it in the most space efficient manner\n\t\t\t *\n\t\t\t * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif\n\t\t\t */\n\n\n\t\t\t// Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.\n\t\t\t// Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points\n\t\t\tvar largestPossibleRadius = min([(this.height/2 - this.pointLabelFontSize - 5), this.width/2]),\n\t\t\t\tpointPosition,\n\t\t\t\ti,\n\t\t\t\ttextWidth,\n\t\t\t\thalfTextWidth,\n\t\t\t\tfurthestRight = this.width,\n\t\t\t\tfurthestRightIndex,\n\t\t\t\tfurthestRightAngle,\n\t\t\t\tfurthestLeft = 0,\n\t\t\t\tfurthestLeftIndex,\n\t\t\t\tfurthestLeftAngle,\n\t\t\t\txProtrusionLeft,\n\t\t\t\txProtrusionRight,\n\t\t\t\tradiusReductionRight,\n\t\t\t\tradiusReductionLeft,\n\t\t\t\tmaxWidthRadius;\n\t\t\tthis.ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);\n\t\t\tfor (i=0;i furthestRight) {\n\t\t\t\t\t\tfurthestRight = pointPosition.x + halfTextWidth;\n\t\t\t\t\t\tfurthestRightIndex = i;\n\t\t\t\t\t}\n\t\t\t\t\tif (pointPosition.x - halfTextWidth < furthestLeft) {\n\t\t\t\t\t\tfurthestLeft = pointPosition.x - halfTextWidth;\n\t\t\t\t\t\tfurthestLeftIndex = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (i < this.valuesCount/2) {\n\t\t\t\t\t// Less than half the values means we'll left align the text\n\t\t\t\t\tif (pointPosition.x + textWidth > furthestRight) {\n\t\t\t\t\t\tfurthestRight = pointPosition.x + textWidth;\n\t\t\t\t\t\tfurthestRightIndex = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (i > this.valuesCount/2){\n\t\t\t\t\t// More than half the values means we'll right align the text\n\t\t\t\t\tif (pointPosition.x - textWidth < furthestLeft) {\n\t\t\t\t\t\tfurthestLeft = pointPosition.x - textWidth;\n\t\t\t\t\t\tfurthestLeftIndex = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\txProtrusionLeft = furthestLeft;\n\n\t\t\txProtrusionRight = Math.ceil(furthestRight - this.width);\n\n\t\t\tfurthestRightAngle = this.getIndexAngle(furthestRightIndex);\n\n\t\t\tfurthestLeftAngle = this.getIndexAngle(furthestLeftIndex);\n\n\t\t\tradiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI/2);\n\n\t\t\tradiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI/2);\n\n\t\t\t// Ensure we actually need to reduce the size of the chart\n\t\t\tradiusReductionRight = (isNumber(radiusReductionRight)) ? radiusReductionRight : 0;\n\t\t\tradiusReductionLeft = (isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0;\n\n\t\t\tthis.drawingArea = largestPossibleRadius - (radiusReductionLeft + radiusReductionRight)/2;\n\n\t\t\t//this.drawingArea = min([maxWidthRadius, (this.height - (2 * (this.pointLabelFontSize + 5)))/2])\n\t\t\tthis.setCenterPoint(radiusReductionLeft, radiusReductionRight);\n\n\t\t},\n\t\tsetCenterPoint: function(leftMovement, rightMovement){\n\n\t\t\tvar maxRight = this.width - rightMovement - this.drawingArea,\n\t\t\t\tmaxLeft = leftMovement + this.drawingArea;\n\n\t\t\tthis.xCenter = (maxLeft + maxRight)/2;\n\t\t\t// Always vertically in the centre as the text height doesn't change\n\t\t\tthis.yCenter = (this.height/2);\n\t\t},\n\n\t\tgetIndexAngle : function(index){\n\t\t\tvar angleMultiplier = (Math.PI * 2) / this.valuesCount;\n\t\t\t// Start from the top instead of right, so remove a quarter of the circle\n\n\t\t\treturn index * angleMultiplier - (Math.PI/2);\n\t\t},\n\t\tgetPointPosition : function(index, distanceFromCenter){\n\t\t\tvar thisAngle = this.getIndexAngle(index);\n\t\t\treturn {\n\t\t\t\tx : (Math.cos(thisAngle) * distanceFromCenter) + this.xCenter,\n\t\t\t\ty : (Math.sin(thisAngle) * distanceFromCenter) + this.yCenter\n\t\t\t};\n\t\t},\n\t\tdraw: function(){\n\t\t\tif (this.display){\n\t\t\t\tvar ctx = this.ctx;\n\t\t\t\teach(this.yLabels, function(label, index){\n\t\t\t\t\t// Don't draw a centre value\n\t\t\t\t\tif (index > 0){\n\t\t\t\t\t\tvar yCenterOffset = index * (this.drawingArea/this.steps),\n\t\t\t\t\t\t\tyHeight = this.yCenter - yCenterOffset,\n\t\t\t\t\t\t\tpointPosition;\n\n\t\t\t\t\t\t// Draw circular lines around the scale\n\t\t\t\t\t\tif (this.lineWidth > 0){\n\t\t\t\t\t\t\tctx.strokeStyle = this.lineColor;\n\t\t\t\t\t\t\tctx.lineWidth = this.lineWidth;\n\n\t\t\t\t\t\t\tif(this.lineArc){\n\t\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\t\t\tctx.arc(this.xCenter, this.yCenter, yCenterOffset, 0, Math.PI*2);\n\t\t\t\t\t\t\t\tctx.closePath();\n\t\t\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t\t\t} else{\n\t\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\t\t\tfor (var i=0;i= 0; i--) {\n\t\t\t\t\t\tif (this.angleLineWidth > 0){\n\t\t\t\t\t\t\tvar outerPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max));\n\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\t\tctx.moveTo(this.xCenter, this.yCenter);\n\t\t\t\t\t\t\tctx.lineTo(outerPosition.x, outerPosition.y);\n\t\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t\t\tctx.closePath();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Extra 3px out for some label spacing\n\t\t\t\t\t\tvar pointLabelPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max) + 5);\n\t\t\t\t\t\tctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);\n\t\t\t\t\t\tctx.fillStyle = this.pointLabelFontColor;\n\n\t\t\t\t\t\tvar labelsCount = this.labels.length,\n\t\t\t\t\t\t\thalfLabelsCount = this.labels.length/2,\n\t\t\t\t\t\t\tquarterLabelsCount = halfLabelsCount/2,\n\t\t\t\t\t\t\tupperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),\n\t\t\t\t\t\t\texactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);\n\t\t\t\t\t\tif (i === 0){\n\t\t\t\t\t\t\tctx.textAlign = 'center';\n\t\t\t\t\t\t} else if(i === halfLabelsCount){\n\t\t\t\t\t\t\tctx.textAlign = 'center';\n\t\t\t\t\t\t} else if (i < halfLabelsCount){\n\t\t\t\t\t\t\tctx.textAlign = 'left';\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tctx.textAlign = 'right';\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Set the correct text baseline based on outer positioning\n\t\t\t\t\t\tif (exactQuarter){\n\t\t\t\t\t\t\tctx.textBaseline = 'middle';\n\t\t\t\t\t\t} else if (upperHalf){\n\t\t\t\t\t\t\tctx.textBaseline = 'bottom';\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tctx.textBaseline = 'top';\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tctx.fillText(this.labels[i], pointLabelPosition.x, pointLabelPosition.y);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\t// Attach global event to resize each chart instance when the browser resizes\n\thelpers.addEvent(window, \"resize\", (function(){\n\t\t// Basic debounce of resize function so it doesn't hurt performance when resizing browser.\n\t\tvar timeout;\n\t\treturn function(){\n\t\t\tclearTimeout(timeout);\n\t\t\ttimeout = setTimeout(function(){\n\t\t\t\teach(Chart.instances,function(instance){\n\t\t\t\t\t// If the responsive flag is set in the chart instance config\n\t\t\t\t\t// Cascade the resize event down to the chart.\n\t\t\t\t\tif (instance.options.responsive){\n\t\t\t\t\t\tinstance.resize(instance.render, true);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}, 50);\n\t\t};\n\t})());\n\n\n\tif (amd) {\n\t\tdefine(function(){\n\t\t\treturn Chart;\n\t\t});\n\t} else if (typeof module === 'object' && module.exports) {\n\t\tmodule.exports = Chart;\n\t}\n\n\troot.Chart = Chart;\n\n\tChart.noConflict = function(){\n\t\troot.Chart = previous;\n\t\treturn Chart;\n\t};\n\n}).call(this);\n\n(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\thelpers = Chart.helpers;\n\n\n\tvar defaultConfig = {\n\t\t//Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value\n\t\tscaleBeginAtZero : true,\n\n\t\t//Boolean - Whether grid lines are shown across the chart\n\t\tscaleShowGridLines : true,\n\n\t\t//String - Colour of the grid lines\n\t\tscaleGridLineColor : \"rgba(0,0,0,.05)\",\n\n\t\t//Number - Width of the grid lines\n\t\tscaleGridLineWidth : 1,\n\n\t\t//Boolean - Whether to show horizontal lines (except X axis)\n\t\tscaleShowHorizontalLines: true,\n\n\t\t//Boolean - Whether to show vertical lines (except Y axis)\n\t\tscaleShowVerticalLines: true,\n\n\t\t//Boolean - If there is a stroke on each bar\n\t\tbarShowStroke : true,\n\n\t\t//Number - Pixel width of the bar stroke\n\t\tbarStrokeWidth : 2,\n\n\t\t//Number - Spacing between each of the X value sets\n\t\tbarValueSpacing : 5,\n\n\t\t//Number - Spacing between data sets within X values\n\t\tbarDatasetSpacing : 1,\n\n\t\t//String - A legend template\n\t\tlegendTemplate : \"
    -legend\\\"><% for (var i=0; i
  • \\\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
\"\n\n\t};\n\n\n\tChart.Type.extend({\n\t\tname: \"Bar\",\n\t\tdefaults : defaultConfig,\n\t\tinitialize: function(data){\n\n\t\t\t//Expose options as a scope variable here so we can access it in the ScaleClass\n\t\t\tvar options = this.options;\n\n\t\t\tthis.ScaleClass = Chart.Scale.extend({\n\t\t\t\toffsetGridLines : true,\n\t\t\t\tcalculateBarX : function(datasetCount, datasetIndex, barIndex){\n\t\t\t\t\t//Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar\n\t\t\t\t\tvar xWidth = this.calculateBaseWidth(),\n\t\t\t\t\t\txAbsolute = this.calculateX(barIndex) - (xWidth/2),\n\t\t\t\t\t\tbarWidth = this.calculateBarWidth(datasetCount);\n\n\t\t\t\t\treturn xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2;\n\t\t\t\t},\n\t\t\t\tcalculateBaseWidth : function(){\n\t\t\t\t\treturn (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing);\n\t\t\t\t},\n\t\t\t\tcalculateBarWidth : function(datasetCount){\n\t\t\t\t\t//The padding between datasets is to the right of each bar, providing that there are more than 1 dataset\n\t\t\t\t\tvar baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing);\n\n\t\t\t\t\treturn (baseWidth / datasetCount);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.datasets = [];\n\n\t\t\t//Set up tooltip events on the chart\n\t\t\tif (this.options.showTooltips){\n\t\t\t\thelpers.bindEvents(this, this.options.tooltipEvents, function(evt){\n\t\t\t\t\tvar activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];\n\n\t\t\t\t\tthis.eachBars(function(bar){\n\t\t\t\t\t\tbar.restore(['fillColor', 'strokeColor']);\n\t\t\t\t\t});\n\t\t\t\t\thelpers.each(activeBars, function(activeBar){\n\t\t\t\t\t\tactiveBar.fillColor = activeBar.highlightFill;\n\t\t\t\t\t\tactiveBar.strokeColor = activeBar.highlightStroke;\n\t\t\t\t\t});\n\t\t\t\t\tthis.showTooltip(activeBars);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t//Declare the extension of the default point, to cater for the options passed in to the constructor\n\t\t\tthis.BarClass = Chart.Rectangle.extend({\n\t\t\t\tstrokeWidth : this.options.barStrokeWidth,\n\t\t\t\tshowStroke : this.options.barShowStroke,\n\t\t\t\tctx : this.chart.ctx\n\t\t\t});\n\n\t\t\t//Iterate through each of the datasets, and build this into a property of the chart\n\t\t\thelpers.each(data.datasets,function(dataset,datasetIndex){\n\n\t\t\t\tvar datasetObject = {\n\t\t\t\t\tlabel : dataset.label || null,\n\t\t\t\t\tfillColor : dataset.fillColor,\n\t\t\t\t\tstrokeColor : dataset.strokeColor,\n\t\t\t\t\tbars : []\n\t\t\t\t};\n\n\t\t\t\tthis.datasets.push(datasetObject);\n\n\t\t\t\thelpers.each(dataset.data,function(dataPoint,index){\n\t\t\t\t\t//Add a new point for each piece of data, passing any required data to draw.\n\t\t\t\t\tdatasetObject.bars.push(new this.BarClass({\n\t\t\t\t\t\tvalue : dataPoint,\n\t\t\t\t\t\tlabel : data.labels[index],\n\t\t\t\t\t\tdatasetLabel: dataset.label,\n\t\t\t\t\t\tstrokeColor : dataset.strokeColor,\n\t\t\t\t\t\tfillColor : dataset.fillColor,\n\t\t\t\t\t\thighlightFill : dataset.highlightFill || dataset.fillColor,\n\t\t\t\t\t\thighlightStroke : dataset.highlightStroke || dataset.strokeColor\n\t\t\t\t\t}));\n\t\t\t\t},this);\n\n\t\t\t},this);\n\n\t\t\tthis.buildScale(data.labels);\n\n\t\t\tthis.BarClass.prototype.base = this.scale.endPoint;\n\n\t\t\tthis.eachBars(function(bar, index, datasetIndex){\n\t\t\t\thelpers.extend(bar, {\n\t\t\t\t\twidth : this.scale.calculateBarWidth(this.datasets.length),\n\t\t\t\t\tx: this.scale.calculateBarX(this.datasets.length, datasetIndex, index),\n\t\t\t\t\ty: this.scale.endPoint\n\t\t\t\t});\n\t\t\t\tbar.save();\n\t\t\t}, this);\n\n\t\t\tthis.render();\n\t\t},\n\t\tupdate : function(){\n\t\t\tthis.scale.update();\n\t\t\t// Reset any highlight colours before updating.\n\t\t\thelpers.each(this.activeElements, function(activeElement){\n\t\t\t\tactiveElement.restore(['fillColor', 'strokeColor']);\n\t\t\t});\n\n\t\t\tthis.eachBars(function(bar){\n\t\t\t\tbar.save();\n\t\t\t});\n\t\t\tthis.render();\n\t\t},\n\t\teachBars : function(callback){\n\t\t\thelpers.each(this.datasets,function(dataset, datasetIndex){\n\t\t\t\thelpers.each(dataset.bars, callback, this, datasetIndex);\n\t\t\t},this);\n\t\t},\n\t\tgetBarsAtEvent : function(e){\n\t\t\tvar barsArray = [],\n\t\t\t\teventPosition = helpers.getRelativePosition(e),\n\t\t\t\tdatasetIterator = function(dataset){\n\t\t\t\t\tbarsArray.push(dataset.bars[barIndex]);\n\t\t\t\t},\n\t\t\t\tbarIndex;\n\n\t\t\tfor (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) {\n\t\t\t\tfor (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) {\n\t\t\t\t\tif (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){\n\t\t\t\t\t\thelpers.each(this.datasets, datasetIterator);\n\t\t\t\t\t\treturn barsArray;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn barsArray;\n\t\t},\n\t\tbuildScale : function(labels){\n\t\t\tvar self = this;\n\n\t\t\tvar dataTotal = function(){\n\t\t\t\tvar values = [];\n\t\t\t\tself.eachBars(function(bar){\n\t\t\t\t\tvalues.push(bar.value);\n\t\t\t\t});\n\t\t\t\treturn values;\n\t\t\t};\n\n\t\t\tvar scaleOptions = {\n\t\t\t\ttemplateString : this.options.scaleLabel,\n\t\t\t\theight : this.chart.height,\n\t\t\t\twidth : this.chart.width,\n\t\t\t\tctx : this.chart.ctx,\n\t\t\t\ttextColor : this.options.scaleFontColor,\n\t\t\t\tfontSize : this.options.scaleFontSize,\n\t\t\t\tfontStyle : this.options.scaleFontStyle,\n\t\t\t\tfontFamily : this.options.scaleFontFamily,\n\t\t\t\tvaluesCount : labels.length,\n\t\t\t\tbeginAtZero : this.options.scaleBeginAtZero,\n\t\t\t\tintegersOnly : this.options.scaleIntegersOnly,\n\t\t\t\tcalculateYRange: function(currentHeight){\n\t\t\t\t\tvar updatedRanges = helpers.calculateScaleRange(\n\t\t\t\t\t\tdataTotal(),\n\t\t\t\t\t\tcurrentHeight,\n\t\t\t\t\t\tthis.fontSize,\n\t\t\t\t\t\tthis.beginAtZero,\n\t\t\t\t\t\tthis.integersOnly\n\t\t\t\t\t);\n\t\t\t\t\thelpers.extend(this, updatedRanges);\n\t\t\t\t},\n\t\t\t\txLabels : labels,\n\t\t\t\tfont : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),\n\t\t\t\tlineWidth : this.options.scaleLineWidth,\n\t\t\t\tlineColor : this.options.scaleLineColor,\n\t\t\t\tshowHorizontalLines : this.options.scaleShowHorizontalLines,\n\t\t\t\tshowVerticalLines : this.options.scaleShowVerticalLines,\n\t\t\t\tgridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,\n\t\t\t\tgridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : \"rgba(0,0,0,0)\",\n\t\t\t\tpadding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0,\n\t\t\t\tshowLabels : this.options.scaleShowLabels,\n\t\t\t\tdisplay : this.options.showScale\n\t\t\t};\n\n\t\t\tif (this.options.scaleOverride){\n\t\t\t\thelpers.extend(scaleOptions, {\n\t\t\t\t\tcalculateYRange: helpers.noop,\n\t\t\t\t\tsteps: this.options.scaleSteps,\n\t\t\t\t\tstepValue: this.options.scaleStepWidth,\n\t\t\t\t\tmin: this.options.scaleStartValue,\n\t\t\t\t\tmax: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.scale = new this.ScaleClass(scaleOptions);\n\t\t},\n\t\taddData : function(valuesArray,label){\n\t\t\t//Map the values array for each of the datasets\n\t\t\thelpers.each(valuesArray,function(value,datasetIndex){\n\t\t\t\t//Add a new point for each piece of data, passing any required data to draw.\n\t\t\t\tthis.datasets[datasetIndex].bars.push(new this.BarClass({\n\t\t\t\t\tvalue : value,\n\t\t\t\t\tlabel : label,\n\t\t\t\t\tx: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1),\n\t\t\t\t\ty: this.scale.endPoint,\n\t\t\t\t\twidth : this.scale.calculateBarWidth(this.datasets.length),\n\t\t\t\t\tbase : this.scale.endPoint,\n\t\t\t\t\tstrokeColor : this.datasets[datasetIndex].strokeColor,\n\t\t\t\t\tfillColor : this.datasets[datasetIndex].fillColor\n\t\t\t\t}));\n\t\t\t},this);\n\n\t\t\tthis.scale.addXLabel(label);\n\t\t\t//Then re-render the chart.\n\t\t\tthis.update();\n\t\t},\n\t\tremoveData : function(){\n\t\t\tthis.scale.removeXLabel();\n\t\t\t//Then re-render the chart.\n\t\t\thelpers.each(this.datasets,function(dataset){\n\t\t\t\tdataset.bars.shift();\n\t\t\t},this);\n\t\t\tthis.update();\n\t\t},\n\t\treflow : function(){\n\t\t\thelpers.extend(this.BarClass.prototype,{\n\t\t\t\ty: this.scale.endPoint,\n\t\t\t\tbase : this.scale.endPoint\n\t\t\t});\n\t\t\tvar newScaleProps = helpers.extend({\n\t\t\t\theight : this.chart.height,\n\t\t\t\twidth : this.chart.width\n\t\t\t});\n\t\t\tthis.scale.update(newScaleProps);\n\t\t},\n\t\tdraw : function(ease){\n\t\t\tvar easingDecimal = ease || 1;\n\t\t\tthis.clear();\n\n\t\t\tvar ctx = this.chart.ctx;\n\n\t\t\tthis.scale.draw(easingDecimal);\n\n\t\t\t//Draw all the bars for each dataset\n\t\t\thelpers.each(this.datasets,function(dataset,datasetIndex){\n\t\t\t\thelpers.each(dataset.bars,function(bar,index){\n\t\t\t\t\tif (bar.hasValue()){\n\t\t\t\t\t\tbar.base = this.scale.endPoint;\n\t\t\t\t\t\t//Transition then draw\n\t\t\t\t\t\tbar.transition({\n\t\t\t\t\t\t\tx : this.scale.calculateBarX(this.datasets.length, datasetIndex, index),\n\t\t\t\t\t\t\ty : this.scale.calculateY(bar.value),\n\t\t\t\t\t\t\twidth : this.scale.calculateBarWidth(this.datasets.length)\n\t\t\t\t\t\t}, easingDecimal).draw();\n\t\t\t\t\t}\n\t\t\t\t},this);\n\n\t\t\t},this);\n\t\t}\n\t});\n\n\n}).call(this);\n\n(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\t//Cache a local reference to Chart.helpers\n\t\thelpers = Chart.helpers;\n\n\tvar defaultConfig = {\n\t\t//Boolean - Whether we should show a stroke on each segment\n\t\tsegmentShowStroke : true,\n\n\t\t//String - The colour of each segment stroke\n\t\tsegmentStrokeColor : \"#fff\",\n\n\t\t//Number - The width of each segment stroke\n\t\tsegmentStrokeWidth : 2,\n\n\t\t//The percentage of the chart that we cut out of the middle.\n\t\tpercentageInnerCutout : 50,\n\n\t\t//Number - Amount of animation steps\n\t\tanimationSteps : 100,\n\n\t\t//String - Animation easing effect\n\t\tanimationEasing : \"easeOutBounce\",\n\n\t\t//Boolean - Whether we animate the rotation of the Doughnut\n\t\tanimateRotate : true,\n\n\t\t//Boolean - Whether we animate scaling the Doughnut from the centre\n\t\tanimateScale : false,\n\n\t\t//String - A legend template\n\t\tlegendTemplate : \"
    -legend\\\"><% for (var i=0; i
  • \\\"><%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>
\"\n\n\t};\n\n\n\tChart.Type.extend({\n\t\t//Passing in a name registers this chart in the Chart namespace\n\t\tname: \"Doughnut\",\n\t\t//Providing a defaults will also register the deafults in the chart namespace\n\t\tdefaults : defaultConfig,\n\t\t//Initialize is fired when the chart is initialized - Data is passed in as a parameter\n\t\t//Config is automatically merged by the core of Chart.js, and is available at this.options\n\t\tinitialize: function(data){\n\n\t\t\t//Declare segments as a static property to prevent inheriting across the Chart type prototype\n\t\t\tthis.segments = [];\n\t\t\tthis.outerRadius = (helpers.min([this.chart.width,this.chart.height]) -\tthis.options.segmentStrokeWidth/2)/2;\n\n\t\t\tthis.SegmentArc = Chart.Arc.extend({\n\t\t\t\tctx : this.chart.ctx,\n\t\t\t\tx : this.chart.width/2,\n\t\t\t\ty : this.chart.height/2\n\t\t\t});\n\n\t\t\t//Set up tooltip events on the chart\n\t\t\tif (this.options.showTooltips){\n\t\t\t\thelpers.bindEvents(this, this.options.tooltipEvents, function(evt){\n\t\t\t\t\tvar activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];\n\n\t\t\t\t\thelpers.each(this.segments,function(segment){\n\t\t\t\t\t\tsegment.restore([\"fillColor\"]);\n\t\t\t\t\t});\n\t\t\t\t\thelpers.each(activeSegments,function(activeSegment){\n\t\t\t\t\t\tactiveSegment.fillColor = activeSegment.highlightColor;\n\t\t\t\t\t});\n\t\t\t\t\tthis.showTooltip(activeSegments);\n\t\t\t\t});\n\t\t\t}\n\t\t\tthis.calculateTotal(data);\n\n\t\t\thelpers.each(data,function(datapoint, index){\n\t\t\t\tthis.addData(datapoint, index, true);\n\t\t\t},this);\n\n\t\t\tthis.render();\n\t\t},\n\t\tgetSegmentsAtEvent : function(e){\n\t\t\tvar segmentsArray = [];\n\n\t\t\tvar location = helpers.getRelativePosition(e);\n\n\t\t\thelpers.each(this.segments,function(segment){\n\t\t\t\tif (segment.inRange(location.x,location.y)) segmentsArray.push(segment);\n\t\t\t},this);\n\t\t\treturn segmentsArray;\n\t\t},\n\t\taddData : function(segment, atIndex, silent){\n\t\t\tvar index = atIndex || this.segments.length;\n\t\t\tthis.segments.splice(index, 0, new this.SegmentArc({\n\t\t\t\tvalue : segment.value,\n\t\t\t\touterRadius : (this.options.animateScale) ? 0 : this.outerRadius,\n\t\t\t\tinnerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout,\n\t\t\t\tfillColor : segment.color,\n\t\t\t\thighlightColor : segment.highlight || segment.color,\n\t\t\t\tshowStroke : this.options.segmentShowStroke,\n\t\t\t\tstrokeWidth : this.options.segmentStrokeWidth,\n\t\t\t\tstrokeColor : this.options.segmentStrokeColor,\n\t\t\t\tstartAngle : Math.PI * 1.5,\n\t\t\t\tcircumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),\n\t\t\t\tlabel : segment.label\n\t\t\t}));\n\t\t\tif (!silent){\n\t\t\t\tthis.reflow();\n\t\t\t\tthis.update();\n\t\t\t}\n\t\t},\n\t\tcalculateCircumference : function(value){\n\t\t\treturn (Math.PI*2)*(Math.abs(value) / this.total);\n\t\t},\n\t\tcalculateTotal : function(data){\n\t\t\tthis.total = 0;\n\t\t\thelpers.each(data,function(segment){\n\t\t\t\tthis.total += Math.abs(segment.value);\n\t\t\t},this);\n\t\t},\n\t\tupdate : function(){\n\t\t\tthis.calculateTotal(this.segments);\n\n\t\t\t// Reset any highlight colours before updating.\n\t\t\thelpers.each(this.activeElements, function(activeElement){\n\t\t\t\tactiveElement.restore(['fillColor']);\n\t\t\t});\n\n\t\t\thelpers.each(this.segments,function(segment){\n\t\t\t\tsegment.save();\n\t\t\t});\n\t\t\tthis.render();\n\t\t},\n\n\t\tremoveData: function(atIndex){\n\t\t\tvar indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;\n\t\t\tthis.segments.splice(indexToDelete, 1);\n\t\t\tthis.reflow();\n\t\t\tthis.update();\n\t\t},\n\n\t\treflow : function(){\n\t\t\thelpers.extend(this.SegmentArc.prototype,{\n\t\t\t\tx : this.chart.width/2,\n\t\t\t\ty : this.chart.height/2\n\t\t\t});\n\t\t\tthis.outerRadius = (helpers.min([this.chart.width,this.chart.height]) -\tthis.options.segmentStrokeWidth/2)/2;\n\t\t\thelpers.each(this.segments, function(segment){\n\t\t\t\tsegment.update({\n\t\t\t\t\touterRadius : this.outerRadius,\n\t\t\t\t\tinnerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout\n\t\t\t\t});\n\t\t\t}, this);\n\t\t},\n\t\tdraw : function(easeDecimal){\n\t\t\tvar animDecimal = (easeDecimal) ? easeDecimal : 1;\n\t\t\tthis.clear();\n\t\t\thelpers.each(this.segments,function(segment,index){\n\t\t\t\tsegment.transition({\n\t\t\t\t\tcircumference : this.calculateCircumference(segment.value),\n\t\t\t\t\touterRadius : this.outerRadius,\n\t\t\t\t\tinnerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout\n\t\t\t\t},animDecimal);\n\n\t\t\t\tsegment.endAngle = segment.startAngle + segment.circumference;\n\n\t\t\t\tsegment.draw();\n\t\t\t\tif (index === 0){\n\t\t\t\t\tsegment.startAngle = Math.PI * 1.5;\n\t\t\t\t}\n\t\t\t\t//Check to see if it's the last segment, if not get the next and update the start angle\n\t\t\t\tif (index < this.segments.length-1){\n\t\t\t\t\tthis.segments[index+1].startAngle = segment.endAngle;\n\t\t\t\t}\n\t\t\t},this);\n\n\t\t}\n\t});\n\n\tChart.types.Doughnut.extend({\n\t\tname : \"Pie\",\n\t\tdefaults : helpers.merge(defaultConfig,{percentageInnerCutout : 0})\n\t});\n\n}).call(this);\n(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\thelpers = Chart.helpers;\n\n\tvar defaultConfig = {\n\n\t\t///Boolean - Whether grid lines are shown across the chart\n\t\tscaleShowGridLines : true,\n\n\t\t//String - Colour of the grid lines\n\t\tscaleGridLineColor : \"rgba(0,0,0,.05)\",\n\n\t\t//Number - Width of the grid lines\n\t\tscaleGridLineWidth : 1,\n\n\t\t//Boolean - Whether to show horizontal lines (except X axis)\n\t\tscaleShowHorizontalLines: true,\n\n\t\t//Boolean - Whether to show vertical lines (except Y axis)\n\t\tscaleShowVerticalLines: true,\n\n\t\t//Boolean - Whether the line is curved between points\n\t\tbezierCurve : true,\n\n\t\t//Number - Tension of the bezier curve between points\n\t\tbezierCurveTension : 0.4,\n\n\t\t//Boolean - Whether to show a dot for each point\n\t\tpointDot : true,\n\n\t\t//Number - Radius of each point dot in pixels\n\t\tpointDotRadius : 4,\n\n\t\t//Number - Pixel width of point dot stroke\n\t\tpointDotStrokeWidth : 1,\n\n\t\t//Number - amount extra to add to the radius to cater for hit detection outside the drawn point\n\t\tpointHitDetectionRadius : 20,\n\n\t\t//Boolean - Whether to show a stroke for datasets\n\t\tdatasetStroke : true,\n\n\t\t//Number - Pixel width of dataset stroke\n\t\tdatasetStrokeWidth : 2,\n\n\t\t//Boolean - Whether to fill the dataset with a colour\n\t\tdatasetFill : true,\n\n\t\t//String - A legend template\n\t\tlegendTemplate : \"
    -legend\\\"><% for (var i=0; i
  • \\\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
\"\n\n\t};\n\n\n\tChart.Type.extend({\n\t\tname: \"Line\",\n\t\tdefaults : defaultConfig,\n\t\tinitialize: function(data){\n\t\t\t//Declare the extension of the default point, to cater for the options passed in to the constructor\n\t\t\tthis.PointClass = Chart.Point.extend({\n\t\t\t\tstrokeWidth : this.options.pointDotStrokeWidth,\n\t\t\t\tradius : this.options.pointDotRadius,\n\t\t\t\tdisplay: this.options.pointDot,\n\t\t\t\thitDetectionRadius : this.options.pointHitDetectionRadius,\n\t\t\t\tctx : this.chart.ctx,\n\t\t\t\tinRange : function(mouseX){\n\t\t\t\t\treturn (Math.pow(mouseX-this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius,2));\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.datasets = [];\n\n\t\t\t//Set up tooltip events on the chart\n\t\t\tif (this.options.showTooltips){\n\t\t\t\thelpers.bindEvents(this, this.options.tooltipEvents, function(evt){\n\t\t\t\t\tvar activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];\n\t\t\t\t\tthis.eachPoints(function(point){\n\t\t\t\t\t\tpoint.restore(['fillColor', 'strokeColor']);\n\t\t\t\t\t});\n\t\t\t\t\thelpers.each(activePoints, function(activePoint){\n\t\t\t\t\t\tactivePoint.fillColor = activePoint.highlightFill;\n\t\t\t\t\t\tactivePoint.strokeColor = activePoint.highlightStroke;\n\t\t\t\t\t});\n\t\t\t\t\tthis.showTooltip(activePoints);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t//Iterate through each of the datasets, and build this into a property of the chart\n\t\t\thelpers.each(data.datasets,function(dataset){\n\n\t\t\t\tvar datasetObject = {\n\t\t\t\t\tlabel : dataset.label || null,\n\t\t\t\t\tfillColor : dataset.fillColor,\n\t\t\t\t\tstrokeColor : dataset.strokeColor,\n\t\t\t\t\tpointColor : dataset.pointColor,\n\t\t\t\t\tpointStrokeColor : dataset.pointStrokeColor,\n\t\t\t\t\tpoints : []\n\t\t\t\t};\n\n\t\t\t\tthis.datasets.push(datasetObject);\n\n\n\t\t\t\thelpers.each(dataset.data,function(dataPoint,index){\n\t\t\t\t\t//Add a new point for each piece of data, passing any required data to draw.\n\t\t\t\t\tdatasetObject.points.push(new this.PointClass({\n\t\t\t\t\t\tvalue : dataPoint,\n\t\t\t\t\t\tlabel : data.labels[index],\n\t\t\t\t\t\tdatasetLabel: dataset.label,\n\t\t\t\t\t\tstrokeColor : dataset.pointStrokeColor,\n\t\t\t\t\t\tfillColor : dataset.pointColor,\n\t\t\t\t\t\thighlightFill : dataset.pointHighlightFill || dataset.pointColor,\n\t\t\t\t\t\thighlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor\n\t\t\t\t\t}));\n\t\t\t\t},this);\n\n\t\t\t\tthis.buildScale(data.labels);\n\n\n\t\t\t\tthis.eachPoints(function(point, index){\n\t\t\t\t\thelpers.extend(point, {\n\t\t\t\t\t\tx: this.scale.calculateX(index),\n\t\t\t\t\t\ty: this.scale.endPoint\n\t\t\t\t\t});\n\t\t\t\t\tpoint.save();\n\t\t\t\t}, this);\n\n\t\t\t},this);\n\n\n\t\t\tthis.render();\n\t\t},\n\t\tupdate : function(){\n\t\t\tthis.scale.update();\n\t\t\t// Reset any highlight colours before updating.\n\t\t\thelpers.each(this.activeElements, function(activeElement){\n\t\t\t\tactiveElement.restore(['fillColor', 'strokeColor']);\n\t\t\t});\n\t\t\tthis.eachPoints(function(point){\n\t\t\t\tpoint.save();\n\t\t\t});\n\t\t\tthis.render();\n\t\t},\n\t\teachPoints : function(callback){\n\t\t\thelpers.each(this.datasets,function(dataset){\n\t\t\t\thelpers.each(dataset.points,callback,this);\n\t\t\t},this);\n\t\t},\n\t\tgetPointsAtEvent : function(e){\n\t\t\tvar pointsArray = [],\n\t\t\t\teventPosition = helpers.getRelativePosition(e);\n\t\t\thelpers.each(this.datasets,function(dataset){\n\t\t\t\thelpers.each(dataset.points,function(point){\n\t\t\t\t\tif (point.inRange(eventPosition.x,eventPosition.y)) pointsArray.push(point);\n\t\t\t\t});\n\t\t\t},this);\n\t\t\treturn pointsArray;\n\t\t},\n\t\tbuildScale : function(labels){\n\t\t\tvar self = this;\n\n\t\t\tvar dataTotal = function(){\n\t\t\t\tvar values = [];\n\t\t\t\tself.eachPoints(function(point){\n\t\t\t\t\tvalues.push(point.value);\n\t\t\t\t});\n\n\t\t\t\treturn values;\n\t\t\t};\n\n\t\t\tvar scaleOptions = {\n\t\t\t\ttemplateString : this.options.scaleLabel,\n\t\t\t\theight : this.chart.height,\n\t\t\t\twidth : this.chart.width,\n\t\t\t\tctx : this.chart.ctx,\n\t\t\t\ttextColor : this.options.scaleFontColor,\n\t\t\t\tfontSize : this.options.scaleFontSize,\n\t\t\t\tfontStyle : this.options.scaleFontStyle,\n\t\t\t\tfontFamily : this.options.scaleFontFamily,\n\t\t\t\tvaluesCount : labels.length,\n\t\t\t\tbeginAtZero : this.options.scaleBeginAtZero,\n\t\t\t\tintegersOnly : this.options.scaleIntegersOnly,\n\t\t\t\tcalculateYRange : function(currentHeight){\n\t\t\t\t\tvar updatedRanges = helpers.calculateScaleRange(\n\t\t\t\t\t\tdataTotal(),\n\t\t\t\t\t\tcurrentHeight,\n\t\t\t\t\t\tthis.fontSize,\n\t\t\t\t\t\tthis.beginAtZero,\n\t\t\t\t\t\tthis.integersOnly\n\t\t\t\t\t);\n\t\t\t\t\thelpers.extend(this, updatedRanges);\n\t\t\t\t},\n\t\t\t\txLabels : labels,\n\t\t\t\tfont : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),\n\t\t\t\tlineWidth : this.options.scaleLineWidth,\n\t\t\t\tlineColor : this.options.scaleLineColor,\n\t\t\t\tshowHorizontalLines : this.options.scaleShowHorizontalLines,\n\t\t\t\tshowVerticalLines : this.options.scaleShowVerticalLines,\n\t\t\t\tgridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,\n\t\t\t\tgridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : \"rgba(0,0,0,0)\",\n\t\t\t\tpadding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,\n\t\t\t\tshowLabels : this.options.scaleShowLabels,\n\t\t\t\tdisplay : this.options.showScale\n\t\t\t};\n\n\t\t\tif (this.options.scaleOverride){\n\t\t\t\thelpers.extend(scaleOptions, {\n\t\t\t\t\tcalculateYRange: helpers.noop,\n\t\t\t\t\tsteps: this.options.scaleSteps,\n\t\t\t\t\tstepValue: this.options.scaleStepWidth,\n\t\t\t\t\tmin: this.options.scaleStartValue,\n\t\t\t\t\tmax: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)\n\t\t\t\t});\n\t\t\t}\n\n\n\t\t\tthis.scale = new Chart.Scale(scaleOptions);\n\t\t},\n\t\taddData : function(valuesArray,label){\n\t\t\t//Map the values array for each of the datasets\n\n\t\t\thelpers.each(valuesArray,function(value,datasetIndex){\n\t\t\t\t//Add a new point for each piece of data, passing any required data to draw.\n\t\t\t\tthis.datasets[datasetIndex].points.push(new this.PointClass({\n\t\t\t\t\tvalue : value,\n\t\t\t\t\tlabel : label,\n\t\t\t\t\tx: this.scale.calculateX(this.scale.valuesCount+1),\n\t\t\t\t\ty: this.scale.endPoint,\n\t\t\t\t\tstrokeColor : this.datasets[datasetIndex].pointStrokeColor,\n\t\t\t\t\tfillColor : this.datasets[datasetIndex].pointColor\n\t\t\t\t}));\n\t\t\t},this);\n\n\t\t\tthis.scale.addXLabel(label);\n\t\t\t//Then re-render the chart.\n\t\t\tthis.update();\n\t\t},\n\t\tremoveData : function(){\n\t\t\tthis.scale.removeXLabel();\n\t\t\t//Then re-render the chart.\n\t\t\thelpers.each(this.datasets,function(dataset){\n\t\t\t\tdataset.points.shift();\n\t\t\t},this);\n\t\t\tthis.update();\n\t\t},\n\t\treflow : function(){\n\t\t\tvar newScaleProps = helpers.extend({\n\t\t\t\theight : this.chart.height,\n\t\t\t\twidth : this.chart.width\n\t\t\t});\n\t\t\tthis.scale.update(newScaleProps);\n\t\t},\n\t\tdraw : function(ease){\n\t\t\tvar easingDecimal = ease || 1;\n\t\t\tthis.clear();\n\n\t\t\tvar ctx = this.chart.ctx;\n\n\t\t\t// Some helper methods for getting the next/prev points\n\t\t\tvar hasValue = function(item){\n\t\t\t\treturn item.value !== null;\n\t\t\t},\n\t\t\tnextPoint = function(point, collection, index){\n\t\t\t\treturn helpers.findNextWhere(collection, hasValue, index) || point;\n\t\t\t},\n\t\t\tpreviousPoint = function(point, collection, index){\n\t\t\t\treturn helpers.findPreviousWhere(collection, hasValue, index) || point;\n\t\t\t};\n\n\t\t\tthis.scale.draw(easingDecimal);\n\n\n\t\t\thelpers.each(this.datasets,function(dataset){\n\t\t\t\tvar pointsWithValues = helpers.where(dataset.points, hasValue);\n\n\t\t\t\t//Transition each point first so that the line and point drawing isn't out of sync\n\t\t\t\t//We can use this extra loop to calculate the control points of this dataset also in this loop\n\n\t\t\t\thelpers.each(dataset.points, function(point, index){\n\t\t\t\t\tif (point.hasValue()){\n\t\t\t\t\t\tpoint.transition({\n\t\t\t\t\t\t\ty : this.scale.calculateY(point.value),\n\t\t\t\t\t\t\tx : this.scale.calculateX(index)\n\t\t\t\t\t\t}, easingDecimal);\n\t\t\t\t\t}\n\t\t\t\t},this);\n\n\n\t\t\t\t// Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point\n\t\t\t\t// This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed\n\t\t\t\tif (this.options.bezierCurve){\n\t\t\t\t\thelpers.each(pointsWithValues, function(point, index){\n\t\t\t\t\t\tvar tension = (index > 0 && index < pointsWithValues.length - 1) ? this.options.bezierCurveTension : 0;\n\t\t\t\t\t\tpoint.controlPoints = helpers.splineCurve(\n\t\t\t\t\t\t\tpreviousPoint(point, pointsWithValues, index),\n\t\t\t\t\t\t\tpoint,\n\t\t\t\t\t\t\tnextPoint(point, pointsWithValues, index),\n\t\t\t\t\t\t\ttension\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// Prevent the bezier going outside of the bounds of the graph\n\n\t\t\t\t\t\t// Cap puter bezier handles to the upper/lower scale bounds\n\t\t\t\t\t\tif (point.controlPoints.outer.y > this.scale.endPoint){\n\t\t\t\t\t\t\tpoint.controlPoints.outer.y = this.scale.endPoint;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (point.controlPoints.outer.y < this.scale.startPoint){\n\t\t\t\t\t\t\tpoint.controlPoints.outer.y = this.scale.startPoint;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Cap inner bezier handles to the upper/lower scale bounds\n\t\t\t\t\t\tif (point.controlPoints.inner.y > this.scale.endPoint){\n\t\t\t\t\t\t\tpoint.controlPoints.inner.y = this.scale.endPoint;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (point.controlPoints.inner.y < this.scale.startPoint){\n\t\t\t\t\t\t\tpoint.controlPoints.inner.y = this.scale.startPoint;\n\t\t\t\t\t\t}\n\t\t\t\t\t},this);\n\t\t\t\t}\n\n\n\t\t\t\t//Draw the line between all the points\n\t\t\t\tctx.lineWidth = this.options.datasetStrokeWidth;\n\t\t\t\tctx.strokeStyle = dataset.strokeColor;\n\t\t\t\tctx.beginPath();\n\n\t\t\t\thelpers.each(pointsWithValues, function(point, index){\n\t\t\t\t\tif (index === 0){\n\t\t\t\t\t\tctx.moveTo(point.x, point.y);\n\t\t\t\t\t}\n\t\t\t\t\telse{\n\t\t\t\t\t\tif(this.options.bezierCurve){\n\t\t\t\t\t\t\tvar previous = previousPoint(point, pointsWithValues, index);\n\n\t\t\t\t\t\t\tctx.bezierCurveTo(\n\t\t\t\t\t\t\t\tprevious.controlPoints.outer.x,\n\t\t\t\t\t\t\t\tprevious.controlPoints.outer.y,\n\t\t\t\t\t\t\t\tpoint.controlPoints.inner.x,\n\t\t\t\t\t\t\t\tpoint.controlPoints.inner.y,\n\t\t\t\t\t\t\t\tpoint.x,\n\t\t\t\t\t\t\t\tpoint.y\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse{\n\t\t\t\t\t\t\tctx.lineTo(point.x,point.y);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}, this);\n\n\t\t\t\tctx.stroke();\n\n\t\t\t\tif (this.options.datasetFill && pointsWithValues.length > 0){\n\t\t\t\t\t//Round off the line by going to the base of the chart, back to the start, then fill.\n\t\t\t\t\tctx.lineTo(pointsWithValues[pointsWithValues.length - 1].x, this.scale.endPoint);\n\t\t\t\t\tctx.lineTo(pointsWithValues[0].x, this.scale.endPoint);\n\t\t\t\t\tctx.fillStyle = dataset.fillColor;\n\t\t\t\t\tctx.closePath();\n\t\t\t\t\tctx.fill();\n\t\t\t\t}\n\n\t\t\t\t//Now draw the points over the line\n\t\t\t\t//A little inefficient double looping, but better than the line\n\t\t\t\t//lagging behind the point positions\n\t\t\t\thelpers.each(pointsWithValues,function(point){\n\t\t\t\t\tpoint.draw();\n\t\t\t\t});\n\t\t\t},this);\n\t\t}\n\t});\n\n\n}).call(this);\n\n(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\t//Cache a local reference to Chart.helpers\n\t\thelpers = Chart.helpers;\n\n\tvar defaultConfig = {\n\t\t//Boolean - Show a backdrop to the scale label\n\t\tscaleShowLabelBackdrop : true,\n\n\t\t//String - The colour of the label backdrop\n\t\tscaleBackdropColor : \"rgba(255,255,255,0.75)\",\n\n\t\t// Boolean - Whether the scale should begin at zero\n\t\tscaleBeginAtZero : true,\n\n\t\t//Number - The backdrop padding above & below the label in pixels\n\t\tscaleBackdropPaddingY : 2,\n\n\t\t//Number - The backdrop padding to the side of the label in pixels\n\t\tscaleBackdropPaddingX : 2,\n\n\t\t//Boolean - Show line for each value in the scale\n\t\tscaleShowLine : true,\n\n\t\t//Boolean - Stroke a line around each segment in the chart\n\t\tsegmentShowStroke : true,\n\n\t\t//String - The colour of the stroke on each segement.\n\t\tsegmentStrokeColor : \"#fff\",\n\n\t\t//Number - The width of the stroke value in pixels\n\t\tsegmentStrokeWidth : 2,\n\n\t\t//Number - Amount of animation steps\n\t\tanimationSteps : 100,\n\n\t\t//String - Animation easing effect.\n\t\tanimationEasing : \"easeOutBounce\",\n\n\t\t//Boolean - Whether to animate the rotation of the chart\n\t\tanimateRotate : true,\n\n\t\t//Boolean - Whether to animate scaling the chart from the centre\n\t\tanimateScale : false,\n\n\t\t//String - A legend template\n\t\tlegendTemplate : \"
    -legend\\\"><% for (var i=0; i
  • \\\"><%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>
\"\n\t};\n\n\n\tChart.Type.extend({\n\t\t//Passing in a name registers this chart in the Chart namespace\n\t\tname: \"PolarArea\",\n\t\t//Providing a defaults will also register the deafults in the chart namespace\n\t\tdefaults : defaultConfig,\n\t\t//Initialize is fired when the chart is initialized - Data is passed in as a parameter\n\t\t//Config is automatically merged by the core of Chart.js, and is available at this.options\n\t\tinitialize: function(data){\n\t\t\tthis.segments = [];\n\t\t\t//Declare segment class as a chart instance specific class, so it can share props for this instance\n\t\t\tthis.SegmentArc = Chart.Arc.extend({\n\t\t\t\tshowStroke : this.options.segmentShowStroke,\n\t\t\t\tstrokeWidth : this.options.segmentStrokeWidth,\n\t\t\t\tstrokeColor : this.options.segmentStrokeColor,\n\t\t\t\tctx : this.chart.ctx,\n\t\t\t\tinnerRadius : 0,\n\t\t\t\tx : this.chart.width/2,\n\t\t\t\ty : this.chart.height/2\n\t\t\t});\n\t\t\tthis.scale = new Chart.RadialScale({\n\t\t\t\tdisplay: this.options.showScale,\n\t\t\t\tfontStyle: this.options.scaleFontStyle,\n\t\t\t\tfontSize: this.options.scaleFontSize,\n\t\t\t\tfontFamily: this.options.scaleFontFamily,\n\t\t\t\tfontColor: this.options.scaleFontColor,\n\t\t\t\tshowLabels: this.options.scaleShowLabels,\n\t\t\t\tshowLabelBackdrop: this.options.scaleShowLabelBackdrop,\n\t\t\t\tbackdropColor: this.options.scaleBackdropColor,\n\t\t\t\tbackdropPaddingY : this.options.scaleBackdropPaddingY,\n\t\t\t\tbackdropPaddingX: this.options.scaleBackdropPaddingX,\n\t\t\t\tlineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,\n\t\t\t\tlineColor: this.options.scaleLineColor,\n\t\t\t\tlineArc: true,\n\t\t\t\twidth: this.chart.width,\n\t\t\t\theight: this.chart.height,\n\t\t\t\txCenter: this.chart.width/2,\n\t\t\t\tyCenter: this.chart.height/2,\n\t\t\t\tctx : this.chart.ctx,\n\t\t\t\ttemplateString: this.options.scaleLabel,\n\t\t\t\tvaluesCount: data.length\n\t\t\t});\n\n\t\t\tthis.updateScaleRange(data);\n\n\t\t\tthis.scale.update();\n\n\t\t\thelpers.each(data,function(segment,index){\n\t\t\t\tthis.addData(segment,index,true);\n\t\t\t},this);\n\n\t\t\t//Set up tooltip events on the chart\n\t\t\tif (this.options.showTooltips){\n\t\t\t\thelpers.bindEvents(this, this.options.tooltipEvents, function(evt){\n\t\t\t\t\tvar activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];\n\t\t\t\t\thelpers.each(this.segments,function(segment){\n\t\t\t\t\t\tsegment.restore([\"fillColor\"]);\n\t\t\t\t\t});\n\t\t\t\t\thelpers.each(activeSegments,function(activeSegment){\n\t\t\t\t\t\tactiveSegment.fillColor = activeSegment.highlightColor;\n\t\t\t\t\t});\n\t\t\t\t\tthis.showTooltip(activeSegments);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.render();\n\t\t},\n\t\tgetSegmentsAtEvent : function(e){\n\t\t\tvar segmentsArray = [];\n\n\t\t\tvar location = helpers.getRelativePosition(e);\n\n\t\t\thelpers.each(this.segments,function(segment){\n\t\t\t\tif (segment.inRange(location.x,location.y)) segmentsArray.push(segment);\n\t\t\t},this);\n\t\t\treturn segmentsArray;\n\t\t},\n\t\taddData : function(segment, atIndex, silent){\n\t\t\tvar index = atIndex || this.segments.length;\n\n\t\t\tthis.segments.splice(index, 0, new this.SegmentArc({\n\t\t\t\tfillColor: segment.color,\n\t\t\t\thighlightColor: segment.highlight || segment.color,\n\t\t\t\tlabel: segment.label,\n\t\t\t\tvalue: segment.value,\n\t\t\t\touterRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value),\n\t\t\t\tcircumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(),\n\t\t\t\tstartAngle: Math.PI * 1.5\n\t\t\t}));\n\t\t\tif (!silent){\n\t\t\t\tthis.reflow();\n\t\t\t\tthis.update();\n\t\t\t}\n\t\t},\n\t\tremoveData: function(atIndex){\n\t\t\tvar indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;\n\t\t\tthis.segments.splice(indexToDelete, 1);\n\t\t\tthis.reflow();\n\t\t\tthis.update();\n\t\t},\n\t\tcalculateTotal: function(data){\n\t\t\tthis.total = 0;\n\t\t\thelpers.each(data,function(segment){\n\t\t\t\tthis.total += segment.value;\n\t\t\t},this);\n\t\t\tthis.scale.valuesCount = this.segments.length;\n\t\t},\n\t\tupdateScaleRange: function(datapoints){\n\t\t\tvar valuesArray = [];\n\t\t\thelpers.each(datapoints,function(segment){\n\t\t\t\tvaluesArray.push(segment.value);\n\t\t\t});\n\n\t\t\tvar scaleSizes = (this.options.scaleOverride) ?\n\t\t\t\t{\n\t\t\t\t\tsteps: this.options.scaleSteps,\n\t\t\t\t\tstepValue: this.options.scaleStepWidth,\n\t\t\t\t\tmin: this.options.scaleStartValue,\n\t\t\t\t\tmax: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)\n\t\t\t\t} :\n\t\t\t\thelpers.calculateScaleRange(\n\t\t\t\t\tvaluesArray,\n\t\t\t\t\thelpers.min([this.chart.width, this.chart.height])/2,\n\t\t\t\t\tthis.options.scaleFontSize,\n\t\t\t\t\tthis.options.scaleBeginAtZero,\n\t\t\t\t\tthis.options.scaleIntegersOnly\n\t\t\t\t);\n\n\t\t\thelpers.extend(\n\t\t\t\tthis.scale,\n\t\t\t\tscaleSizes,\n\t\t\t\t{\n\t\t\t\t\tsize: helpers.min([this.chart.width, this.chart.height]),\n\t\t\t\t\txCenter: this.chart.width/2,\n\t\t\t\t\tyCenter: this.chart.height/2\n\t\t\t\t}\n\t\t\t);\n\n\t\t},\n\t\tupdate : function(){\n\t\t\tthis.calculateTotal(this.segments);\n\n\t\t\thelpers.each(this.segments,function(segment){\n\t\t\t\tsegment.save();\n\t\t\t});\n\t\t\t\n\t\t\tthis.reflow();\n\t\t\tthis.render();\n\t\t},\n\t\treflow : function(){\n\t\t\thelpers.extend(this.SegmentArc.prototype,{\n\t\t\t\tx : this.chart.width/2,\n\t\t\t\ty : this.chart.height/2\n\t\t\t});\n\t\t\tthis.updateScaleRange(this.segments);\n\t\t\tthis.scale.update();\n\n\t\t\thelpers.extend(this.scale,{\n\t\t\t\txCenter: this.chart.width/2,\n\t\t\t\tyCenter: this.chart.height/2\n\t\t\t});\n\n\t\t\thelpers.each(this.segments, function(segment){\n\t\t\t\tsegment.update({\n\t\t\t\t\touterRadius : this.scale.calculateCenterOffset(segment.value)\n\t\t\t\t});\n\t\t\t}, this);\n\n\t\t},\n\t\tdraw : function(ease){\n\t\t\tvar easingDecimal = ease || 1;\n\t\t\t//Clear & draw the canvas\n\t\t\tthis.clear();\n\t\t\thelpers.each(this.segments,function(segment, index){\n\t\t\t\tsegment.transition({\n\t\t\t\t\tcircumference : this.scale.getCircumference(),\n\t\t\t\t\touterRadius : this.scale.calculateCenterOffset(segment.value)\n\t\t\t\t},easingDecimal);\n\n\t\t\t\tsegment.endAngle = segment.startAngle + segment.circumference;\n\n\t\t\t\t// If we've removed the first segment we need to set the first one to\n\t\t\t\t// start at the top.\n\t\t\t\tif (index === 0){\n\t\t\t\t\tsegment.startAngle = Math.PI * 1.5;\n\t\t\t\t}\n\n\t\t\t\t//Check to see if it's the last segment, if not get the next and update the start angle\n\t\t\t\tif (index < this.segments.length - 1){\n\t\t\t\t\tthis.segments[index+1].startAngle = segment.endAngle;\n\t\t\t\t}\n\t\t\t\tsegment.draw();\n\t\t\t}, this);\n\t\t\tthis.scale.draw();\n\t\t}\n\t});\n\n}).call(this);\n(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\thelpers = Chart.helpers;\n\n\n\n\tChart.Type.extend({\n\t\tname: \"Radar\",\n\t\tdefaults:{\n\t\t\t//Boolean - Whether to show lines for each scale point\n\t\t\tscaleShowLine : true,\n\n\t\t\t//Boolean - Whether we show the angle lines out of the radar\n\t\t\tangleShowLineOut : true,\n\n\t\t\t//Boolean - Whether to show labels on the scale\n\t\t\tscaleShowLabels : false,\n\n\t\t\t// Boolean - Whether the scale should begin at zero\n\t\t\tscaleBeginAtZero : true,\n\n\t\t\t//String - Colour of the angle line\n\t\t\tangleLineColor : \"rgba(0,0,0,.1)\",\n\n\t\t\t//Number - Pixel width of the angle line\n\t\t\tangleLineWidth : 1,\n\n\t\t\t//String - Point label font declaration\n\t\t\tpointLabelFontFamily : \"'Arial'\",\n\n\t\t\t//String - Point label font weight\n\t\t\tpointLabelFontStyle : \"normal\",\n\n\t\t\t//Number - Point label font size in pixels\n\t\t\tpointLabelFontSize : 10,\n\n\t\t\t//String - Point label font colour\n\t\t\tpointLabelFontColor : \"#666\",\n\n\t\t\t//Boolean - Whether to show a dot for each point\n\t\t\tpointDot : true,\n\n\t\t\t//Number - Radius of each point dot in pixels\n\t\t\tpointDotRadius : 3,\n\n\t\t\t//Number - Pixel width of point dot stroke\n\t\t\tpointDotStrokeWidth : 1,\n\n\t\t\t//Number - amount extra to add to the radius to cater for hit detection outside the drawn point\n\t\t\tpointHitDetectionRadius : 20,\n\n\t\t\t//Boolean - Whether to show a stroke for datasets\n\t\t\tdatasetStroke : true,\n\n\t\t\t//Number - Pixel width of dataset stroke\n\t\t\tdatasetStrokeWidth : 2,\n\n\t\t\t//Boolean - Whether to fill the dataset with a colour\n\t\t\tdatasetFill : true,\n\n\t\t\t//String - A legend template\n\t\t\tlegendTemplate : \"
    -legend\\\"><% for (var i=0; i
  • \\\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
\"\n\n\t\t},\n\n\t\tinitialize: function(data){\n\t\t\tthis.PointClass = Chart.Point.extend({\n\t\t\t\tstrokeWidth : this.options.pointDotStrokeWidth,\n\t\t\t\tradius : this.options.pointDotRadius,\n\t\t\t\tdisplay: this.options.pointDot,\n\t\t\t\thitDetectionRadius : this.options.pointHitDetectionRadius,\n\t\t\t\tctx : this.chart.ctx\n\t\t\t});\n\n\t\t\tthis.datasets = [];\n\n\t\t\tthis.buildScale(data);\n\n\t\t\t//Set up tooltip events on the chart\n\t\t\tif (this.options.showTooltips){\n\t\t\t\thelpers.bindEvents(this, this.options.tooltipEvents, function(evt){\n\t\t\t\t\tvar activePointsCollection = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];\n\n\t\t\t\t\tthis.eachPoints(function(point){\n\t\t\t\t\t\tpoint.restore(['fillColor', 'strokeColor']);\n\t\t\t\t\t});\n\t\t\t\t\thelpers.each(activePointsCollection, function(activePoint){\n\t\t\t\t\t\tactivePoint.fillColor = activePoint.highlightFill;\n\t\t\t\t\t\tactivePoint.strokeColor = activePoint.highlightStroke;\n\t\t\t\t\t});\n\n\t\t\t\t\tthis.showTooltip(activePointsCollection);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t//Iterate through each of the datasets, and build this into a property of the chart\n\t\t\thelpers.each(data.datasets,function(dataset){\n\n\t\t\t\tvar datasetObject = {\n\t\t\t\t\tlabel: dataset.label || null,\n\t\t\t\t\tfillColor : dataset.fillColor,\n\t\t\t\t\tstrokeColor : dataset.strokeColor,\n\t\t\t\t\tpointColor : dataset.pointColor,\n\t\t\t\t\tpointStrokeColor : dataset.pointStrokeColor,\n\t\t\t\t\tpoints : []\n\t\t\t\t};\n\n\t\t\t\tthis.datasets.push(datasetObject);\n\n\t\t\t\thelpers.each(dataset.data,function(dataPoint,index){\n\t\t\t\t\t//Add a new point for each piece of data, passing any required data to draw.\n\t\t\t\t\tvar pointPosition;\n\t\t\t\t\tif (!this.scale.animation){\n\t\t\t\t\t\tpointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint));\n\t\t\t\t\t}\n\t\t\t\t\tdatasetObject.points.push(new this.PointClass({\n\t\t\t\t\t\tvalue : dataPoint,\n\t\t\t\t\t\tlabel : data.labels[index],\n\t\t\t\t\t\tdatasetLabel: dataset.label,\n\t\t\t\t\t\tx: (this.options.animation) ? this.scale.xCenter : pointPosition.x,\n\t\t\t\t\t\ty: (this.options.animation) ? this.scale.yCenter : pointPosition.y,\n\t\t\t\t\t\tstrokeColor : dataset.pointStrokeColor,\n\t\t\t\t\t\tfillColor : dataset.pointColor,\n\t\t\t\t\t\thighlightFill : dataset.pointHighlightFill || dataset.pointColor,\n\t\t\t\t\t\thighlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor\n\t\t\t\t\t}));\n\t\t\t\t},this);\n\n\t\t\t},this);\n\n\t\t\tthis.render();\n\t\t},\n\t\teachPoints : function(callback){\n\t\t\thelpers.each(this.datasets,function(dataset){\n\t\t\t\thelpers.each(dataset.points,callback,this);\n\t\t\t},this);\n\t\t},\n\n\t\tgetPointsAtEvent : function(evt){\n\t\t\tvar mousePosition = helpers.getRelativePosition(evt),\n\t\t\t\tfromCenter = helpers.getAngleFromPoint({\n\t\t\t\t\tx: this.scale.xCenter,\n\t\t\t\t\ty: this.scale.yCenter\n\t\t\t\t}, mousePosition);\n\n\t\t\tvar anglePerIndex = (Math.PI * 2) /this.scale.valuesCount,\n\t\t\t\tpointIndex = Math.round((fromCenter.angle - Math.PI * 1.5) / anglePerIndex),\n\t\t\t\tactivePointsCollection = [];\n\n\t\t\t// If we're at the top, make the pointIndex 0 to get the first of the array.\n\t\t\tif (pointIndex >= this.scale.valuesCount || pointIndex < 0){\n\t\t\t\tpointIndex = 0;\n\t\t\t}\n\n\t\t\tif (fromCenter.distance <= this.scale.drawingArea){\n\t\t\t\thelpers.each(this.datasets, function(dataset){\n\t\t\t\t\tactivePointsCollection.push(dataset.points[pointIndex]);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn activePointsCollection;\n\t\t},\n\n\t\tbuildScale : function(data){\n\t\t\tthis.scale = new Chart.RadialScale({\n\t\t\t\tdisplay: this.options.showScale,\n\t\t\t\tfontStyle: this.options.scaleFontStyle,\n\t\t\t\tfontSize: this.options.scaleFontSize,\n\t\t\t\tfontFamily: this.options.scaleFontFamily,\n\t\t\t\tfontColor: this.options.scaleFontColor,\n\t\t\t\tshowLabels: this.options.scaleShowLabels,\n\t\t\t\tshowLabelBackdrop: this.options.scaleShowLabelBackdrop,\n\t\t\t\tbackdropColor: this.options.scaleBackdropColor,\n\t\t\t\tbackdropPaddingY : this.options.scaleBackdropPaddingY,\n\t\t\t\tbackdropPaddingX: this.options.scaleBackdropPaddingX,\n\t\t\t\tlineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,\n\t\t\t\tlineColor: this.options.scaleLineColor,\n\t\t\t\tangleLineColor : this.options.angleLineColor,\n\t\t\t\tangleLineWidth : (this.options.angleShowLineOut) ? this.options.angleLineWidth : 0,\n\t\t\t\t// Point labels at the edge of each line\n\t\t\t\tpointLabelFontColor : this.options.pointLabelFontColor,\n\t\t\t\tpointLabelFontSize : this.options.pointLabelFontSize,\n\t\t\t\tpointLabelFontFamily : this.options.pointLabelFontFamily,\n\t\t\t\tpointLabelFontStyle : this.options.pointLabelFontStyle,\n\t\t\t\theight : this.chart.height,\n\t\t\t\twidth: this.chart.width,\n\t\t\t\txCenter: this.chart.width/2,\n\t\t\t\tyCenter: this.chart.height/2,\n\t\t\t\tctx : this.chart.ctx,\n\t\t\t\ttemplateString: this.options.scaleLabel,\n\t\t\t\tlabels: data.labels,\n\t\t\t\tvaluesCount: data.datasets[0].data.length\n\t\t\t});\n\n\t\t\tthis.scale.setScaleSize();\n\t\t\tthis.updateScaleRange(data.datasets);\n\t\t\tthis.scale.buildYLabels();\n\t\t},\n\t\tupdateScaleRange: function(datasets){\n\t\t\tvar valuesArray = (function(){\n\t\t\t\tvar totalDataArray = [];\n\t\t\t\thelpers.each(datasets,function(dataset){\n\t\t\t\t\tif (dataset.data){\n\t\t\t\t\t\ttotalDataArray = totalDataArray.concat(dataset.data);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\thelpers.each(dataset.points, function(point){\n\t\t\t\t\t\t\ttotalDataArray.push(point.value);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn totalDataArray;\n\t\t\t})();\n\n\n\t\t\tvar scaleSizes = (this.options.scaleOverride) ?\n\t\t\t\t{\n\t\t\t\t\tsteps: this.options.scaleSteps,\n\t\t\t\t\tstepValue: this.options.scaleStepWidth,\n\t\t\t\t\tmin: this.options.scaleStartValue,\n\t\t\t\t\tmax: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)\n\t\t\t\t} :\n\t\t\t\thelpers.calculateScaleRange(\n\t\t\t\t\tvaluesArray,\n\t\t\t\t\thelpers.min([this.chart.width, this.chart.height])/2,\n\t\t\t\t\tthis.options.scaleFontSize,\n\t\t\t\t\tthis.options.scaleBeginAtZero,\n\t\t\t\t\tthis.options.scaleIntegersOnly\n\t\t\t\t);\n\n\t\t\thelpers.extend(\n\t\t\t\tthis.scale,\n\t\t\t\tscaleSizes\n\t\t\t);\n\n\t\t},\n\t\taddData : function(valuesArray,label){\n\t\t\t//Map the values array for each of the datasets\n\t\t\tthis.scale.valuesCount++;\n\t\t\thelpers.each(valuesArray,function(value,datasetIndex){\n\t\t\t\tvar pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value));\n\t\t\t\tthis.datasets[datasetIndex].points.push(new this.PointClass({\n\t\t\t\t\tvalue : value,\n\t\t\t\t\tlabel : label,\n\t\t\t\t\tx: pointPosition.x,\n\t\t\t\t\ty: pointPosition.y,\n\t\t\t\t\tstrokeColor : this.datasets[datasetIndex].pointStrokeColor,\n\t\t\t\t\tfillColor : this.datasets[datasetIndex].pointColor\n\t\t\t\t}));\n\t\t\t},this);\n\n\t\t\tthis.scale.labels.push(label);\n\n\t\t\tthis.reflow();\n\n\t\t\tthis.update();\n\t\t},\n\t\tremoveData : function(){\n\t\t\tthis.scale.valuesCount--;\n\t\t\tthis.scale.labels.shift();\n\t\t\thelpers.each(this.datasets,function(dataset){\n\t\t\t\tdataset.points.shift();\n\t\t\t},this);\n\t\t\tthis.reflow();\n\t\t\tthis.update();\n\t\t},\n\t\tupdate : function(){\n\t\t\tthis.eachPoints(function(point){\n\t\t\t\tpoint.save();\n\t\t\t});\n\t\t\tthis.reflow();\n\t\t\tthis.render();\n\t\t},\n\t\treflow: function(){\n\t\t\thelpers.extend(this.scale, {\n\t\t\t\twidth : this.chart.width,\n\t\t\t\theight: this.chart.height,\n\t\t\t\tsize : helpers.min([this.chart.width, this.chart.height]),\n\t\t\t\txCenter: this.chart.width/2,\n\t\t\t\tyCenter: this.chart.height/2\n\t\t\t});\n\t\t\tthis.updateScaleRange(this.datasets);\n\t\t\tthis.scale.setScaleSize();\n\t\t\tthis.scale.buildYLabels();\n\t\t},\n\t\tdraw : function(ease){\n\t\t\tvar easeDecimal = ease || 1,\n\t\t\t\tctx = this.chart.ctx;\n\t\t\tthis.clear();\n\t\t\tthis.scale.draw();\n\n\t\t\thelpers.each(this.datasets,function(dataset){\n\n\t\t\t\t//Transition each point first so that the line and point drawing isn't out of sync\n\t\t\t\thelpers.each(dataset.points,function(point,index){\n\t\t\t\t\tif (point.hasValue()){\n\t\t\t\t\t\tpoint.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal);\n\t\t\t\t\t}\n\t\t\t\t},this);\n\n\n\n\t\t\t\t//Draw the line between all the points\n\t\t\t\tctx.lineWidth = this.options.datasetStrokeWidth;\n\t\t\t\tctx.strokeStyle = dataset.strokeColor;\n\t\t\t\tctx.beginPath();\n\t\t\t\thelpers.each(dataset.points,function(point,index){\n\t\t\t\t\tif (index === 0){\n\t\t\t\t\t\tctx.moveTo(point.x,point.y);\n\t\t\t\t\t}\n\t\t\t\t\telse{\n\t\t\t\t\t\tctx.lineTo(point.x,point.y);\n\t\t\t\t\t}\n\t\t\t\t},this);\n\t\t\t\tctx.closePath();\n\t\t\t\tctx.stroke();\n\n\t\t\t\tctx.fillStyle = dataset.fillColor;\n\t\t\t\tctx.fill();\n\n\t\t\t\t//Now draw the points over the line\n\t\t\t\t//A little inefficient double looping, but better than the line\n\t\t\t\t//lagging behind the point positions\n\t\t\t\thelpers.each(dataset.points,function(point){\n\t\t\t\t\tif (point.hasValue()){\n\t\t\t\t\t\tpoint.draw();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t},this);\n\n\t\t}\n\n\t});\n\n\n\n\n\n}).call(this);\n\n\n//////////////////\n// WEBPACK FOOTER\n// /opt/gitlab/embedded/service/gitlab-rails/vendor/assets/javascripts/Chart.js\n// module id = ../../../vendor/assets/javascripts/Chart.js\n// module chunks = graphs graphs_charts pipelines_charts pipelines_times","import Chart from 'vendor/Chart';\n\ndocument.addEventListener('DOMContentLoaded', () => {\n const chartData = JSON.parse(document.getElementById('pipelinesTimesChartsData').innerHTML);\n const data = {\n labels: chartData.labels,\n datasets: [{\n fillColor: 'rgba(220,220,220,0.5)',\n strokeColor: 'rgba(220,220,220,1)',\n barStrokeWidth: 1,\n barValueSpacing: 1,\n barDatasetSpacing: 1,\n data: chartData.values,\n }],\n };\n const ctx = $('#build_timesChart').get(0).getContext('2d');\n const options = {\n scaleOverlay: true,\n responsive: true,\n maintainAspectRatio: false,\n };\n if (window.innerWidth < 768) {\n // Scale fonts if window width lower than 768px (iPad portrait)\n options.scaleFontSize = 8;\n }\n new Chart(ctx).Bar(data, options);\n});\n\n\n\n// WEBPACK FOOTER //\n// ./pipelines/pipelines_times.js"],"sourceRoot":""}