Replaced Chart.js with flotr
Project: http://git-wip-us.apache.org/repos/asf/incubator-blur/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-blur/commit/70fced06 Tree: http://git-wip-us.apache.org/repos/asf/incubator-blur/tree/70fced06 Diff: http://git-wip-us.apache.org/repos/asf/incubator-blur/diff/70fced06 Branch: refs/heads/blur-console-v2 Commit: 70fced066dc599a3c6196ab01fdd7085a638cacc Parents: 79df6ba Author: Chris Rohr <[email protected]> Authored: Mon Oct 14 12:16:29 2013 -0400 Committer: Chris Rohr <[email protected]> Committed: Mon Oct 14 12:16:29 2013 -0400 ---------------------------------------------------------------------- .../org/apache/blur/console/util/NodeUtil.java | 7 +- .../org/apache/blur/console/webapp/index.html | 3 +- .../org/apache/blur/console/webapp/js/Chart.js | 1426 ---- .../org/apache/blur/console/webapp/js/app.js | 32 +- .../apache/blur/console/webapp/js/directives.js | 140 + .../apache/blur/console/webapp/js/factories.js | 22 + .../org/apache/blur/console/webapp/js/flotr2.js | 7209 ++++++++++++++++++ .../console/webapp/partials/dashboard.tpl.html | 13 +- 8 files changed, 7386 insertions(+), 1466 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/70fced06/contrib/blur-console/src/main/java/org/apache/blur/console/util/NodeUtil.java ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/java/org/apache/blur/console/util/NodeUtil.java b/contrib/blur-console/src/main/java/org/apache/blur/console/util/NodeUtil.java index aa16bef..6c6d0cc 100644 --- a/contrib/blur-console/src/main/java/org/apache/blur/console/util/NodeUtil.java +++ b/contrib/blur-console/src/main/java/org/apache/blur/console/util/NodeUtil.java @@ -25,6 +25,7 @@ import java.net.Socket; import java.net.URI; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; @@ -67,11 +68,13 @@ public class NodeUtil { JSONArray chartData = new JSONArray(); JSONObject online = new JSONObject(); - online.put("value", onlineControllers.size()); + online.put("data", new JSONArray(Arrays.asList(new int[]{0,onlineControllers.size()}))); + online.put("label", "Online"); online.put("color", "#7DC77D"); JSONObject offline = new JSONObject(); - offline.put("value", offlineControllers.size()); + offline.put("data", new JSONArray(Arrays.asList(new int[]{0,offlineControllers.size()}))); + offline.put("label", "Offline"); offline.put("color", "#FF1919"); chartData.put(online); http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/70fced06/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/index.html ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/index.html b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/index.html index 1e23bf0..b3f6c43 100644 --- a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/index.html +++ b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/index.html @@ -57,9 +57,10 @@ Licensed to the Apache Software Foundation (ASF) under one <script type="text/javascript" src="js/angular.js"></script> <script type="text/javascript" src="js/ui-bootstrap-tpls-0.6.0.js"></script> - <script type="text/javascript" src="js/Chart.js"></script> + <script type="text/javascript" src="js/factories.js"></script> <script type="text/javascript" src="js/app.js"></script> + <script type="text/javascript" src="js/directives.js"></script> <script type="text/javascript" src="js/dashboard.js"></script> </body> </html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/70fced06/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/Chart.js ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/Chart.js b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/Chart.js deleted file mode 100644 index ffbe16f..0000000 --- a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/Chart.js +++ /dev/null @@ -1,1426 +0,0 @@ -/*! - * Chart.js - * http://chartjs.org/ - * - * Copyright 2013 Nick Downie - * Released under the MIT license - * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md - */ - -//Define the global Chart Variable as a class. -window.Chart = function(context){ - - var chart = this; - - - //Easing functions adapted from Robert Penner's easing equations - //http://www.robertpenner.com/easing/ - - var animationOptions = { - linear : function (t){ - return t; - }, - easeInQuad: function (t) { - return t*t; - }, - easeOutQuad: function (t) { - return -1 *t*(t-2); - }, - easeInOutQuad: function (t) { - if ((t/=1/2) < 1) return 1/2*t*t; - return -1/2 * ((--t)*(t-2) - 1); - }, - easeInCubic: function (t) { - return t*t*t; - }, - easeOutCubic: function (t) { - return 1*((t=t/1-1)*t*t + 1); - }, - easeInOutCubic: function (t) { - if ((t/=1/2) < 1) return 1/2*t*t*t; - return 1/2*((t-=2)*t*t + 2); - }, - easeInQuart: function (t) { - return t*t*t*t; - }, - easeOutQuart: function (t) { - return -1 * ((t=t/1-1)*t*t*t - 1); - }, - easeInOutQuart: function (t) { - if ((t/=1/2) < 1) return 1/2*t*t*t*t; - return -1/2 * ((t-=2)*t*t*t - 2); - }, - easeInQuint: function (t) { - return 1*(t/=1)*t*t*t*t; - }, - easeOutQuint: function (t) { - return 1*((t=t/1-1)*t*t*t*t + 1); - }, - easeInOutQuint: function (t) { - if ((t/=1/2) < 1) return 1/2*t*t*t*t*t; - return 1/2*((t-=2)*t*t*t*t + 2); - }, - easeInSine: function (t) { - return -1 * Math.cos(t/1 * (Math.PI/2)) + 1; - }, - easeOutSine: function (t) { - return 1 * Math.sin(t/1 * (Math.PI/2)); - }, - easeInOutSine: function (t) { - return -1/2 * (Math.cos(Math.PI*t/1) - 1); - }, - easeInExpo: function (t) { - return (t==0) ? 1 : 1 * Math.pow(2, 10 * (t/1 - 1)); - }, - easeOutExpo: function (t) { - return (t==1) ? 1 : 1 * (-Math.pow(2, -10 * t/1) + 1); - }, - easeInOutExpo: function (t) { - if (t==0) return 0; - if (t==1) return 1; - if ((t/=1/2) < 1) return 1/2 * Math.pow(2, 10 * (t - 1)); - return 1/2 * (-Math.pow(2, -10 * --t) + 2); - }, - easeInCirc: function (t) { - if (t>=1) return t; - return -1 * (Math.sqrt(1 - (t/=1)*t) - 1); - }, - easeOutCirc: function (t) { - return 1 * Math.sqrt(1 - (t=t/1-1)*t); - }, - easeInOutCirc: function (t) { - if ((t/=1/2) < 1) return -1/2 * (Math.sqrt(1 - t*t) - 1); - return 1/2 * (Math.sqrt(1 - (t-=2)*t) + 1); - }, - easeInElastic: function (t) { - var s=1.70158;var p=0;var a=1; - if (t==0) return 0; if ((t/=1)==1) return 1; if (!p) p=1*.3; - if (a < Math.abs(1)) { a=1; var s=p/4; } - else var s = p/(2*Math.PI) * Math.asin (1/a); - return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*1-s)*(2*Math.PI)/p )); - }, - easeOutElastic: function (t) { - var s=1.70158;var p=0;var a=1; - if (t==0) return 0; if ((t/=1)==1) return 1; if (!p) p=1*.3; - if (a < Math.abs(1)) { a=1; var s=p/4; } - else var s = p/(2*Math.PI) * Math.asin (1/a); - return a*Math.pow(2,-10*t) * Math.sin( (t*1-s)*(2*Math.PI)/p ) + 1; - }, - easeInOutElastic: function (t) { - var s=1.70158;var p=0;var a=1; - if (t==0) return 0; if ((t/=1/2)==2) return 1; if (!p) p=1*(.3*1.5); - if (a < Math.abs(1)) { a=1; var s=p/4; } - else var s = p/(2*Math.PI) * Math.asin (1/a); - if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*1-s)*(2*Math.PI)/p )); - return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*1-s)*(2*Math.PI)/p )*.5 + 1; - }, - easeInBack: function (t) { - var s = 1.70158; - return 1*(t/=1)*t*((s+1)*t - s); - }, - easeOutBack: function (t) { - var s = 1.70158; - return 1*((t=t/1-1)*t*((s+1)*t + s) + 1); - }, - easeInOutBack: function (t) { - var s = 1.70158; - if ((t/=1/2) < 1) return 1/2*(t*t*(((s*=(1.525))+1)*t - s)); - return 1/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2); - }, - easeInBounce: function (t) { - return 1 - animationOptions.easeOutBounce (1-t); - }, - easeOutBounce: function (t) { - if ((t/=1) < (1/2.75)) { - return 1*(7.5625*t*t); - } else if (t < (2/2.75)) { - return 1*(7.5625*(t-=(1.5/2.75))*t + .75); - } else if (t < (2.5/2.75)) { - return 1*(7.5625*(t-=(2.25/2.75))*t + .9375); - } else { - return 1*(7.5625*(t-=(2.625/2.75))*t + .984375); - } - }, - easeInOutBounce: function (t) { - if (t < 1/2) return animationOptions.easeInBounce (t*2) * .5; - return animationOptions.easeOutBounce (t*2-1) * .5 + 1*.5; - } - }; - - //Variables global to the chart - var width = context.canvas.width; - var height = context.canvas.height; - - - //High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale. - if (window.devicePixelRatio) { - context.canvas.style.width = width + "px"; - context.canvas.style.height = height + "px"; - context.canvas.height = height * window.devicePixelRatio; - context.canvas.width = width * window.devicePixelRatio; - context.scale(window.devicePixelRatio, window.devicePixelRatio); - } - - this.PolarArea = function(data,options){ - - chart.PolarArea.defaults = { - scaleOverlay : true, - scaleOverride : false, - scaleSteps : null, - scaleStepWidth : null, - scaleStartValue : null, - scaleShowLine : true, - scaleLineColor : "rgba(0,0,0,.1)", - scaleLineWidth : 1, - scaleShowLabels : true, - scaleLabel : "<%=value%>", - scaleFontFamily : "'Arial'", - scaleFontSize : 12, - scaleFontStyle : "normal", - scaleFontColor : "#666", - scaleShowLabelBackdrop : true, - scaleBackdropColor : "rgba(255,255,255,0.75)", - scaleBackdropPaddingY : 2, - scaleBackdropPaddingX : 2, - segmentShowStroke : true, - segmentStrokeColor : "#fff", - segmentStrokeWidth : 2, - animation : true, - animationSteps : 100, - animationEasing : "easeOutBounce", - animateRotate : true, - animateScale : false, - onAnimationComplete : null - }; - - var config = (options)? mergeChartConfig(chart.PolarArea.defaults,options) : chart.PolarArea.defaults; - - return new PolarArea(data,config,context); - }; - - this.Radar = function(data,options){ - - chart.Radar.defaults = { - scaleOverlay : false, - scaleOverride : false, - scaleSteps : null, - scaleStepWidth : null, - scaleStartValue : null, - scaleShowLine : true, - scaleLineColor : "rgba(0,0,0,.1)", - scaleLineWidth : 1, - scaleShowLabels : false, - scaleLabel : "<%=value%>", - scaleFontFamily : "'Arial'", - scaleFontSize : 12, - scaleFontStyle : "normal", - scaleFontColor : "#666", - scaleShowLabelBackdrop : true, - scaleBackdropColor : "rgba(255,255,255,0.75)", - scaleBackdropPaddingY : 2, - scaleBackdropPaddingX : 2, - angleShowLineOut : true, - angleLineColor : "rgba(0,0,0,.1)", - angleLineWidth : 1, - pointLabelFontFamily : "'Arial'", - pointLabelFontStyle : "normal", - pointLabelFontSize : 12, - pointLabelFontColor : "#666", - pointDot : true, - pointDotRadius : 3, - pointDotStrokeWidth : 1, - datasetStroke : true, - datasetStrokeWidth : 2, - datasetFill : true, - animation : true, - animationSteps : 60, - animationEasing : "easeOutQuart", - onAnimationComplete : null - }; - - var config = (options)? mergeChartConfig(chart.Radar.defaults,options) : chart.Radar.defaults; - - return new Radar(data,config,context); - }; - - this.Pie = function(data,options){ - chart.Pie.defaults = { - segmentShowStroke : true, - segmentStrokeColor : "#fff", - segmentStrokeWidth : 2, - animation : true, - animationSteps : 100, - animationEasing : "easeOutBounce", - animateRotate : true, - animateScale : false, - onAnimationComplete : null - }; - - var config = (options)? mergeChartConfig(chart.Pie.defaults,options) : chart.Pie.defaults; - - return new Pie(data,config,context); - }; - - this.Doughnut = function(data,options){ - - chart.Doughnut.defaults = { - segmentShowStroke : true, - segmentStrokeColor : "#fff", - segmentStrokeWidth : 2, - percentageInnerCutout : 50, - animation : true, - animationSteps : 100, - animationEasing : "easeOutBounce", - animateRotate : true, - animateScale : false, - onAnimationComplete : null - }; - - var config = (options)? mergeChartConfig(chart.Doughnut.defaults,options) : chart.Doughnut.defaults; - - return new Doughnut(data,config,context); - - }; - - this.Line = function(data,options){ - - chart.Line.defaults = { - scaleOverlay : false, - scaleOverride : false, - scaleSteps : null, - scaleStepWidth : null, - scaleStartValue : null, - scaleLineColor : "rgba(0,0,0,.1)", - scaleLineWidth : 1, - scaleShowLabels : true, - scaleLabel : "<%=value%>", - scaleFontFamily : "'Arial'", - scaleFontSize : 12, - scaleFontStyle : "normal", - scaleFontColor : "#666", - scaleShowGridLines : true, - scaleGridLineColor : "rgba(0,0,0,.05)", - scaleGridLineWidth : 1, - bezierCurve : true, - pointDot : true, - pointDotRadius : 4, - pointDotStrokeWidth : 2, - datasetStroke : true, - datasetStrokeWidth : 2, - datasetFill : true, - animation : true, - animationSteps : 60, - animationEasing : "easeOutQuart", - onAnimationComplete : null - }; - var config = (options) ? mergeChartConfig(chart.Line.defaults,options) : chart.Line.defaults; - - return new Line(data,config,context); - } - - this.Bar = function(data,options){ - chart.Bar.defaults = { - scaleOverlay : false, - scaleOverride : false, - scaleSteps : null, - scaleStepWidth : null, - scaleStartValue : null, - scaleLineColor : "rgba(0,0,0,.1)", - scaleLineWidth : 1, - scaleShowLabels : true, - scaleLabel : "<%=value%>", - scaleFontFamily : "'Arial'", - scaleFontSize : 12, - scaleFontStyle : "normal", - scaleFontColor : "#666", - scaleShowGridLines : true, - scaleGridLineColor : "rgba(0,0,0,.05)", - scaleGridLineWidth : 1, - barShowStroke : true, - barStrokeWidth : 2, - barValueSpacing : 5, - barDatasetSpacing : 1, - animation : true, - animationSteps : 60, - animationEasing : "easeOutQuart", - onAnimationComplete : null - }; - var config = (options) ? mergeChartConfig(chart.Bar.defaults,options) : chart.Bar.defaults; - - return new Bar(data,config,context); - } - - var clear = function(c){ - c.clearRect(0, 0, width, height); - }; - - var PolarArea = function(data,config,ctx){ - var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString; - - - calculateDrawingSizes(); - - valueBounds = getValueBounds(); - - labelTemplateString = (config.scaleShowLabels)? config.scaleLabel : null; - - //Check and set the scale - if (!config.scaleOverride){ - - calculatedScale = calculateScale(scaleHeight,valueBounds.maxSteps,valueBounds.minSteps,valueBounds.maxValue,valueBounds.minValue,labelTemplateString); - } - else { - calculatedScale = { - steps : config.scaleSteps, - stepValue : config.scaleStepWidth, - graphMin : config.scaleStartValue, - labels : [] - } - populateLabels(labelTemplateString, calculatedScale.labels,calculatedScale.steps,config.scaleStartValue,config.scaleStepWidth); - } - - scaleHop = maxSize/(calculatedScale.steps); - - //Wrap in an animation loop wrapper - animationLoop(config,drawScale,drawAllSegments,ctx); - - function calculateDrawingSizes(){ - maxSize = (Min([width,height])/2); - //Remove whatever is larger - the font size or line width. - - maxSize -= Max([config.scaleFontSize*0.5,config.scaleLineWidth*0.5]); - - labelHeight = config.scaleFontSize*2; - //If we're drawing the backdrop - add the Y padding to the label height and remove from drawing region. - if (config.scaleShowLabelBackdrop){ - labelHeight += (2 * config.scaleBackdropPaddingY); - maxSize -= config.scaleBackdropPaddingY*1.5; - } - - scaleHeight = maxSize; - //If the label height is less than 5, set it to 5 so we don't have lines on top of each other. - labelHeight = Default(labelHeight,5); - } - function drawScale(){ - for (var i=0; i<calculatedScale.steps; i++){ - //If the line object is there - if (config.scaleShowLine){ - ctx.beginPath(); - ctx.arc(width/2, height/2, scaleHop * (i + 1), 0, (Math.PI * 2), true); - ctx.strokeStyle = config.scaleLineColor; - ctx.lineWidth = config.scaleLineWidth; - ctx.stroke(); - } - - if (config.scaleShowLabels){ - ctx.textAlign = "center"; - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily; - var label = calculatedScale.labels[i]; - //If the backdrop object is within the font object - if (config.scaleShowLabelBackdrop){ - var textWidth = ctx.measureText(label).width; - ctx.fillStyle = config.scaleBackdropColor; - ctx.beginPath(); - ctx.rect( - Math.round(width/2 - textWidth/2 - config.scaleBackdropPaddingX), //X - Math.round(height/2 - (scaleHop * (i + 1)) - config.scaleFontSize*0.5 - config.scaleBackdropPaddingY),//Y - Math.round(textWidth + (config.scaleBackdropPaddingX*2)), //Width - Math.round(config.scaleFontSize + (config.scaleBackdropPaddingY*2)) //Height - ); - ctx.fill(); - } - ctx.textBaseline = "middle"; - ctx.fillStyle = config.scaleFontColor; - ctx.fillText(label,width/2,height/2 - (scaleHop * (i + 1))); - } - } - } - function drawAllSegments(animationDecimal){ - var startAngle = -Math.PI/2, - angleStep = (Math.PI*2)/data.length, - scaleAnimation = 1, - rotateAnimation = 1; - if (config.animation) { - if (config.animateScale) { - scaleAnimation = animationDecimal; - } - if (config.animateRotate){ - rotateAnimation = animationDecimal; - } - } - - for (var i=0; i<data.length; i++){ - - ctx.beginPath(); - ctx.arc(width/2,height/2,scaleAnimation * calculateOffset(data[i].value,calculatedScale,scaleHop),startAngle, startAngle + rotateAnimation*angleStep, false); - ctx.lineTo(width/2,height/2); - ctx.closePath(); - ctx.fillStyle = data[i].color; - ctx.fill(); - - if(config.segmentShowStroke){ - ctx.strokeStyle = config.segmentStrokeColor; - ctx.lineWidth = config.segmentStrokeWidth; - ctx.stroke(); - } - startAngle += rotateAnimation*angleStep; - } - } - function getValueBounds() { - var upperValue = Number.MIN_VALUE; - var lowerValue = Number.MAX_VALUE; - for (var i=0; i<data.length; i++){ - if (data[i].value > upperValue) {upperValue = data[i].value;} - if (data[i].value < lowerValue) {lowerValue = data[i].value;} - }; - - var maxSteps = Math.floor((scaleHeight / (labelHeight*0.66))); - var minSteps = Math.floor((scaleHeight / labelHeight*0.5)); - - return { - maxValue : upperValue, - minValue : lowerValue, - maxSteps : maxSteps, - minSteps : minSteps - }; - - - } - } - - var Radar = function (data,config,ctx) { - var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString; - - //If no labels are defined set to an empty array, so referencing length for looping doesn't blow up. - if (!data.labels) data.labels = []; - - calculateDrawingSizes(); - - var valueBounds = getValueBounds(); - - labelTemplateString = (config.scaleShowLabels)? config.scaleLabel : null; - - //Check and set the scale - if (!config.scaleOverride){ - - calculatedScale = calculateScale(scaleHeight,valueBounds.maxSteps,valueBounds.minSteps,valueBounds.maxValue,valueBounds.minValue,labelTemplateString); - } - else { - calculatedScale = { - steps : config.scaleSteps, - stepValue : config.scaleStepWidth, - graphMin : config.scaleStartValue, - labels : [] - } - populateLabels(labelTemplateString, calculatedScale.labels,calculatedScale.steps,config.scaleStartValue,config.scaleStepWidth); - } - - scaleHop = maxSize/(calculatedScale.steps); - - animationLoop(config,drawScale,drawAllDataPoints,ctx); - - //Radar specific functions. - function drawAllDataPoints(animationDecimal){ - var rotationDegree = (2*Math.PI)/data.datasets[0].data.length; - - ctx.save(); - //translate to the centre of the canvas. - ctx.translate(width/2,height/2); - - //We accept multiple data sets for radar charts, so show loop through each set - for (var i=0; i<data.datasets.length; i++){ - ctx.beginPath(); - - ctx.moveTo(0,animationDecimal*(-1*calculateOffset(data.datasets[i].data[0],calculatedScale,scaleHop))); - for (var j=1; j<data.datasets[i].data.length; j++){ - ctx.rotate(rotationDegree); - ctx.lineTo(0,animationDecimal*(-1*calculateOffset(data.datasets[i].data[j],calculatedScale,scaleHop))); - - } - ctx.closePath(); - - - ctx.fillStyle = data.datasets[i].fillColor; - ctx.strokeStyle = data.datasets[i].strokeColor; - ctx.lineWidth = config.datasetStrokeWidth; - ctx.fill(); - ctx.stroke(); - - - if (config.pointDot){ - ctx.fillStyle = data.datasets[i].pointColor; - ctx.strokeStyle = data.datasets[i].pointStrokeColor; - ctx.lineWidth = config.pointDotStrokeWidth; - for (var k=0; k<data.datasets[i].data.length; k++){ - ctx.rotate(rotationDegree); - ctx.beginPath(); - ctx.arc(0,animationDecimal*(-1*calculateOffset(data.datasets[i].data[k],calculatedScale,scaleHop)),config.pointDotRadius,2*Math.PI,false); - ctx.fill(); - ctx.stroke(); - } - - } - ctx.rotate(rotationDegree); - - } - ctx.restore(); - - - } - function drawScale(){ - var rotationDegree = (2*Math.PI)/data.datasets[0].data.length; - ctx.save(); - ctx.translate(width / 2, height / 2); - - if (config.angleShowLineOut){ - ctx.strokeStyle = config.angleLineColor; - ctx.lineWidth = config.angleLineWidth; - for (var h=0; h<data.datasets[0].data.length; h++){ - - ctx.rotate(rotationDegree); - ctx.beginPath(); - ctx.moveTo(0,0); - ctx.lineTo(0,-maxSize); - ctx.stroke(); - } - } - - for (var i=0; i<calculatedScale.steps; i++){ - ctx.beginPath(); - - if(config.scaleShowLine){ - ctx.strokeStyle = config.scaleLineColor; - ctx.lineWidth = config.scaleLineWidth; - ctx.moveTo(0,-scaleHop * (i+1)); - for (var j=0; j<data.datasets[0].data.length; j++){ - ctx.rotate(rotationDegree); - ctx.lineTo(0,-scaleHop * (i+1)); - } - ctx.closePath(); - ctx.stroke(); - - } - - if (config.scaleShowLabels){ - ctx.textAlign = 'center'; - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize+"px " + config.scaleFontFamily; - ctx.textBaseline = "middle"; - - if (config.scaleShowLabelBackdrop){ - var textWidth = ctx.measureText(calculatedScale.labels[i]).width; - ctx.fillStyle = config.scaleBackdropColor; - ctx.beginPath(); - ctx.rect( - Math.round(- textWidth/2 - config.scaleBackdropPaddingX), //X - Math.round((-scaleHop * (i + 1)) - config.scaleFontSize*0.5 - config.scaleBackdropPaddingY),//Y - Math.round(textWidth + (config.scaleBackdropPaddingX*2)), //Width - Math.round(config.scaleFontSize + (config.scaleBackdropPaddingY*2)) //Height - ); - ctx.fill(); - } - ctx.fillStyle = config.scaleFontColor; - ctx.fillText(calculatedScale.labels[i],0,-scaleHop*(i+1)); - } - - } - for (var k=0; k<data.labels.length; k++){ - ctx.font = config.pointLabelFontStyle + " " + config.pointLabelFontSize+"px " + config.pointLabelFontFamily; - ctx.fillStyle = config.pointLabelFontColor; - var opposite = Math.sin(rotationDegree*k) * (maxSize + config.pointLabelFontSize); - var adjacent = Math.cos(rotationDegree*k) * (maxSize + config.pointLabelFontSize); - - if(rotationDegree*k == Math.PI || rotationDegree*k == 0){ - ctx.textAlign = "center"; - } - else if(rotationDegree*k > Math.PI){ - ctx.textAlign = "right"; - } - else{ - ctx.textAlign = "left"; - } - - ctx.textBaseline = "middle"; - - ctx.fillText(data.labels[k],opposite,-adjacent); - - } - ctx.restore(); - }; - function calculateDrawingSizes(){ - maxSize = (Min([width,height])/2); - - labelHeight = config.scaleFontSize*2; - - var labelLength = 0; - for (var i=0; i<data.labels.length; i++){ - ctx.font = config.pointLabelFontStyle + " " + config.pointLabelFontSize+"px " + config.pointLabelFontFamily; - var textMeasurement = ctx.measureText(data.labels[i]).width; - if(textMeasurement>labelLength) labelLength = textMeasurement; - } - - //Figure out whats the largest - the height of the text or the width of what's there, and minus it from the maximum usable size. - maxSize -= Max([labelLength,((config.pointLabelFontSize/2)*1.5)]); - - maxSize -= config.pointLabelFontSize; - maxSize = CapValue(maxSize, null, 0); - scaleHeight = maxSize; - //If the label height is less than 5, set it to 5 so we don't have lines on top of each other. - labelHeight = Default(labelHeight,5); - }; - function getValueBounds() { - var upperValue = Number.MIN_VALUE; - var lowerValue = Number.MAX_VALUE; - - for (var i=0; i<data.datasets.length; i++){ - for (var j=0; j<data.datasets[i].data.length; j++){ - if (data.datasets[i].data[j] > upperValue){upperValue = data.datasets[i].data[j]} - if (data.datasets[i].data[j] < lowerValue){lowerValue = data.datasets[i].data[j]} - } - } - - var maxSteps = Math.floor((scaleHeight / (labelHeight*0.66))); - var minSteps = Math.floor((scaleHeight / labelHeight*0.5)); - - return { - maxValue : upperValue, - minValue : lowerValue, - maxSteps : maxSteps, - minSteps : minSteps - }; - - - } - } - - var Pie = function(data,config,ctx){ - var segmentTotal = 0; - - //In case we have a canvas that is not a square. Minus 5 pixels as padding round the edge. - var pieRadius = Min([height/2,width/2]) - 5; - - for (var i=0; i<data.length; i++){ - segmentTotal += data[i].value; - } - - - animationLoop(config,null,drawPieSegments,ctx); - - function drawPieSegments (animationDecimal){ - var cumulativeAngle = -Math.PI/2, - scaleAnimation = 1, - rotateAnimation = 1; - if (config.animation) { - if (config.animateScale) { - scaleAnimation = animationDecimal; - } - if (config.animateRotate){ - rotateAnimation = animationDecimal; - } - } - for (var i=0; i<data.length; i++){ - var segmentAngle = rotateAnimation * ((data[i].value/segmentTotal) * (Math.PI*2)); - ctx.beginPath(); - ctx.arc(width/2,height/2,scaleAnimation * pieRadius,cumulativeAngle,cumulativeAngle + segmentAngle); - ctx.lineTo(width/2,height/2); - ctx.closePath(); - ctx.fillStyle = data[i].color; - ctx.fill(); - - if(config.segmentShowStroke){ - ctx.lineWidth = config.segmentStrokeWidth; - ctx.strokeStyle = config.segmentStrokeColor; - ctx.stroke(); - } - cumulativeAngle += segmentAngle; - } - } - } - - var Doughnut = function(data,config,ctx){ - var segmentTotal = 0; - - //In case we have a canvas that is not a square. Minus 5 pixels as padding round the edge. - var doughnutRadius = Min([height/2,width/2]) - 5; - - var cutoutRadius = doughnutRadius * (config.percentageInnerCutout/100); - - for (var i=0; i<data.length; i++){ - segmentTotal += data[i].value; - } - - - animationLoop(config,null,drawPieSegments,ctx); - - - function drawPieSegments (animationDecimal){ - var cumulativeAngle = -Math.PI/2, - scaleAnimation = 1, - rotateAnimation = 1; - if (config.animation) { - if (config.animateScale) { - scaleAnimation = animationDecimal; - } - if (config.animateRotate){ - rotateAnimation = animationDecimal; - } - } - for (var i=0; i<data.length; i++){ - var segmentAngle = rotateAnimation * ((data[i].value/segmentTotal) * (Math.PI*2)); - ctx.beginPath(); - ctx.arc(width/2,height/2,scaleAnimation * doughnutRadius,cumulativeAngle,cumulativeAngle + segmentAngle,false); - ctx.arc(width/2,height/2,scaleAnimation * cutoutRadius,cumulativeAngle + segmentAngle,cumulativeAngle,true); - ctx.closePath(); - ctx.fillStyle = data[i].color; - ctx.fill(); - - if(config.segmentShowStroke){ - ctx.lineWidth = config.segmentStrokeWidth; - ctx.strokeStyle = config.segmentStrokeColor; - ctx.stroke(); - } - cumulativeAngle += segmentAngle; - } - } - - - - } - - var Line = function(data,config,ctx){ - var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, valueHop,widestXLabel, xAxisLength,yAxisPosX,xAxisPosY, rotateLabels = 0; - - calculateDrawingSizes(); - - valueBounds = getValueBounds(); - //Check and set the scale - labelTemplateString = (config.scaleShowLabels)? config.scaleLabel : ""; - if (!config.scaleOverride){ - - calculatedScale = calculateScale(scaleHeight,valueBounds.maxSteps,valueBounds.minSteps,valueBounds.maxValue,valueBounds.minValue,labelTemplateString); - } - else { - calculatedScale = { - steps : config.scaleSteps, - stepValue : config.scaleStepWidth, - graphMin : config.scaleStartValue, - labels : [] - } - populateLabels(labelTemplateString, calculatedScale.labels,calculatedScale.steps,config.scaleStartValue,config.scaleStepWidth); - } - - scaleHop = Math.floor(scaleHeight/calculatedScale.steps); - calculateXAxisSize(); - animationLoop(config,drawScale,drawLines,ctx); - - function drawLines(animPc){ - for (var i=0; i<data.datasets.length; i++){ - ctx.strokeStyle = data.datasets[i].strokeColor; - ctx.lineWidth = config.datasetStrokeWidth; - ctx.beginPath(); - ctx.moveTo(yAxisPosX, xAxisPosY - animPc*(calculateOffset(data.datasets[i].data[0],calculatedScale,scaleHop))) - - for (var j=1; j<data.datasets[i].data.length; j++){ - if (config.bezierCurve){ - ctx.bezierCurveTo(xPos(j-0.5),yPos(i,j-1),xPos(j-0.5),yPos(i,j),xPos(j),yPos(i,j)); - } - else{ - ctx.lineTo(xPos(j),yPos(i,j)); - } - } - ctx.stroke(); - if (config.datasetFill){ - ctx.lineTo(yAxisPosX + (valueHop*(data.datasets[i].data.length-1)),xAxisPosY); - ctx.lineTo(yAxisPosX,xAxisPosY); - ctx.closePath(); - ctx.fillStyle = data.datasets[i].fillColor; - ctx.fill(); - } - else{ - ctx.closePath(); - } - if(config.pointDot){ - ctx.fillStyle = data.datasets[i].pointColor; - ctx.strokeStyle = data.datasets[i].pointStrokeColor; - ctx.lineWidth = config.pointDotStrokeWidth; - for (var k=0; k<data.datasets[i].data.length; k++){ - ctx.beginPath(); - ctx.arc(yAxisPosX + (valueHop *k),xAxisPosY - animPc*(calculateOffset(data.datasets[i].data[k],calculatedScale,scaleHop)),config.pointDotRadius,0,Math.PI*2,true); - ctx.fill(); - ctx.stroke(); - } - } - } - - function yPos(dataSet,iteration){ - return xAxisPosY - animPc*(calculateOffset(data.datasets[dataSet].data[iteration],calculatedScale,scaleHop)); - } - function xPos(iteration){ - return yAxisPosX + (valueHop * iteration); - } - } - function drawScale(){ - //X axis line - ctx.lineWidth = config.scaleLineWidth; - ctx.strokeStyle = config.scaleLineColor; - ctx.beginPath(); - ctx.moveTo(width-widestXLabel/2+5,xAxisPosY); - ctx.lineTo(width-(widestXLabel/2)-xAxisLength-5,xAxisPosY); - ctx.stroke(); - - - if (rotateLabels > 0){ - ctx.save(); - ctx.textAlign = "right"; - } - else{ - ctx.textAlign = "center"; - } - ctx.fillStyle = config.scaleFontColor; - for (var i=0; i<data.labels.length; i++){ - ctx.save(); - if (rotateLabels > 0){ - ctx.translate(yAxisPosX + i*valueHop,xAxisPosY + config.scaleFontSize); - ctx.rotate(-(rotateLabels * (Math.PI/180))); - ctx.fillText(data.labels[i], 0,0); - ctx.restore(); - } - - else{ - ctx.fillText(data.labels[i], yAxisPosX + i*valueHop,xAxisPosY + config.scaleFontSize+3); - } - - ctx.beginPath(); - ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY+3); - - //Check i isnt 0, so we dont go over the Y axis twice. - if(config.scaleShowGridLines && i>0){ - ctx.lineWidth = config.scaleGridLineWidth; - ctx.strokeStyle = config.scaleGridLineColor; - ctx.lineTo(yAxisPosX + i * valueHop, 5); - } - else{ - ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY+3); - } - ctx.stroke(); - } - - //Y axis - ctx.lineWidth = config.scaleLineWidth; - ctx.strokeStyle = config.scaleLineColor; - ctx.beginPath(); - ctx.moveTo(yAxisPosX,xAxisPosY+5); - ctx.lineTo(yAxisPosX,5); - ctx.stroke(); - - ctx.textAlign = "right"; - ctx.textBaseline = "middle"; - for (var j=0; j<calculatedScale.steps; j++){ - ctx.beginPath(); - ctx.moveTo(yAxisPosX-3,xAxisPosY - ((j+1) * scaleHop)); - if (config.scaleShowGridLines){ - ctx.lineWidth = config.scaleGridLineWidth; - ctx.strokeStyle = config.scaleGridLineColor; - ctx.lineTo(yAxisPosX + xAxisLength + 5,xAxisPosY - ((j+1) * scaleHop)); - } - else{ - ctx.lineTo(yAxisPosX-0.5,xAxisPosY - ((j+1) * scaleHop)); - } - - ctx.stroke(); - - if (config.scaleShowLabels){ - ctx.fillText(calculatedScale.labels[j],yAxisPosX-8,xAxisPosY - ((j+1) * scaleHop)); - } - } - - - } - function calculateXAxisSize(){ - var longestText = 1; - //if we are showing the labels - if (config.scaleShowLabels){ - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize+"px " + config.scaleFontFamily; - for (var i=0; i<calculatedScale.labels.length; i++){ - var measuredText = ctx.measureText(calculatedScale.labels[i]).width; - longestText = (measuredText > longestText)? measuredText : longestText; - } - //Add a little extra padding from the y axis - longestText +=10; - } - xAxisLength = width - longestText - widestXLabel; - valueHop = Math.floor(xAxisLength/(data.labels.length-1)); - - yAxisPosX = width-widestXLabel/2-xAxisLength; - xAxisPosY = scaleHeight + config.scaleFontSize/2; - } - function calculateDrawingSizes(){ - maxSize = height; - - //Need to check the X axis first - measure the length of each text metric, and figure out if we need to rotate by 45 degrees. - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize+"px " + config.scaleFontFamily; - widestXLabel = 1; - for (var i=0; i<data.labels.length; i++){ - var textLength = ctx.measureText(data.labels[i]).width; - //If the text length is longer - make that equal to longest text! - widestXLabel = (textLength > widestXLabel)? textLength : widestXLabel; - } - if (width/data.labels.length < widestXLabel){ - rotateLabels = 45; - if (width/data.labels.length < Math.cos(rotateLabels) * widestXLabel){ - rotateLabels = 90; - maxSize -= widestXLabel; - } - else{ - maxSize -= Math.sin(rotateLabels) * widestXLabel; - } - } - else{ - maxSize -= config.scaleFontSize; - } - - //Add a little padding between the x line and the text - maxSize -= 5; - - - labelHeight = config.scaleFontSize; - - maxSize -= labelHeight; - //Set 5 pixels greater than the font size to allow for a little padding from the X axis. - - scaleHeight = maxSize; - - //Then get the area above we can safely draw on. - - } - function getValueBounds() { - var upperValue = Number.MIN_VALUE; - var lowerValue = Number.MAX_VALUE; - for (var i=0; i<data.datasets.length; i++){ - for (var j=0; j<data.datasets[i].data.length; j++){ - if ( data.datasets[i].data[j] > upperValue) { upperValue = data.datasets[i].data[j] }; - if ( data.datasets[i].data[j] < lowerValue) { lowerValue = data.datasets[i].data[j] }; - } - }; - - var maxSteps = Math.floor((scaleHeight / (labelHeight*0.66))); - var minSteps = Math.floor((scaleHeight / labelHeight*0.5)); - - return { - maxValue : upperValue, - minValue : lowerValue, - maxSteps : maxSteps, - minSteps : minSteps - }; - - - } - - - } - - var Bar = function(data,config,ctx){ - var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, valueHop,widestXLabel, xAxisLength,yAxisPosX,xAxisPosY,barWidth, rotateLabels = 0; - - calculateDrawingSizes(); - - valueBounds = getValueBounds(); - //Check and set the scale - labelTemplateString = (config.scaleShowLabels)? config.scaleLabel : ""; - if (!config.scaleOverride){ - - calculatedScale = calculateScale(scaleHeight,valueBounds.maxSteps,valueBounds.minSteps,valueBounds.maxValue,valueBounds.minValue,labelTemplateString); - } - else { - calculatedScale = { - steps : config.scaleSteps, - stepValue : config.scaleStepWidth, - graphMin : config.scaleStartValue, - labels : [] - } - populateLabels(labelTemplateString, calculatedScale.labels,calculatedScale.steps,config.scaleStartValue,config.scaleStepWidth); - } - - scaleHop = Math.floor(scaleHeight/calculatedScale.steps); - calculateXAxisSize(); - animationLoop(config,drawScale,drawBars,ctx); - - function drawBars(animPc){ - ctx.lineWidth = config.barStrokeWidth; - for (var i=0; i<data.datasets.length; i++){ - ctx.fillStyle = data.datasets[i].fillColor; - ctx.strokeStyle = data.datasets[i].strokeColor; - for (var j=0; j<data.datasets[i].data.length; j++){ - var barOffset = yAxisPosX + config.barValueSpacing + valueHop*j + barWidth*i + config.barDatasetSpacing*i + config.barStrokeWidth*i; - - ctx.beginPath(); - ctx.moveTo(barOffset, xAxisPosY); - ctx.lineTo(barOffset, xAxisPosY - animPc*calculateOffset(data.datasets[i].data[j],calculatedScale,scaleHop)+(config.barStrokeWidth/2)); - ctx.lineTo(barOffset + barWidth, xAxisPosY - animPc*calculateOffset(data.datasets[i].data[j],calculatedScale,scaleHop)+(config.barStrokeWidth/2)); - ctx.lineTo(barOffset + barWidth, xAxisPosY); - if(config.barShowStroke){ - ctx.stroke(); - } - ctx.closePath(); - ctx.fill(); - } - } - - } - function drawScale(){ - //X axis line - ctx.lineWidth = config.scaleLineWidth; - ctx.strokeStyle = config.scaleLineColor; - ctx.beginPath(); - ctx.moveTo(width-widestXLabel/2+5,xAxisPosY); - ctx.lineTo(width-(widestXLabel/2)-xAxisLength-5,xAxisPosY); - ctx.stroke(); - - - if (rotateLabels > 0){ - ctx.save(); - ctx.textAlign = "right"; - } - else{ - ctx.textAlign = "center"; - } - ctx.fillStyle = config.scaleFontColor; - for (var i=0; i<data.labels.length; i++){ - ctx.save(); - if (rotateLabels > 0){ - ctx.translate(yAxisPosX + i*valueHop,xAxisPosY + config.scaleFontSize); - ctx.rotate(-(rotateLabels * (Math.PI/180))); - ctx.fillText(data.labels[i], 0,0); - ctx.restore(); - } - - else{ - ctx.fillText(data.labels[i], yAxisPosX + i*valueHop + valueHop/2,xAxisPosY + config.scaleFontSize+3); - } - - ctx.beginPath(); - ctx.moveTo(yAxisPosX + (i+1) * valueHop, xAxisPosY+3); - - //Check i isnt 0, so we dont go over the Y axis twice. - ctx.lineWidth = config.scaleGridLineWidth; - ctx.strokeStyle = config.scaleGridLineColor; - ctx.lineTo(yAxisPosX + (i+1) * valueHop, 5); - ctx.stroke(); - } - - //Y axis - ctx.lineWidth = config.scaleLineWidth; - ctx.strokeStyle = config.scaleLineColor; - ctx.beginPath(); - ctx.moveTo(yAxisPosX,xAxisPosY+5); - ctx.lineTo(yAxisPosX,5); - ctx.stroke(); - - ctx.textAlign = "right"; - ctx.textBaseline = "middle"; - for (var j=0; j<calculatedScale.steps; j++){ - ctx.beginPath(); - ctx.moveTo(yAxisPosX-3,xAxisPosY - ((j+1) * scaleHop)); - if (config.scaleShowGridLines){ - ctx.lineWidth = config.scaleGridLineWidth; - ctx.strokeStyle = config.scaleGridLineColor; - ctx.lineTo(yAxisPosX + xAxisLength + 5,xAxisPosY - ((j+1) * scaleHop)); - } - else{ - ctx.lineTo(yAxisPosX-0.5,xAxisPosY - ((j+1) * scaleHop)); - } - - ctx.stroke(); - if (config.scaleShowLabels){ - ctx.fillText(calculatedScale.labels[j],yAxisPosX-8,xAxisPosY - ((j+1) * scaleHop)); - } - } - - - } - function calculateXAxisSize(){ - var longestText = 1; - //if we are showing the labels - if (config.scaleShowLabels){ - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize+"px " + config.scaleFontFamily; - for (var i=0; i<calculatedScale.labels.length; i++){ - var measuredText = ctx.measureText(calculatedScale.labels[i]).width; - longestText = (measuredText > longestText)? measuredText : longestText; - } - //Add a little extra padding from the y axis - longestText +=10; - } - xAxisLength = width - longestText - widestXLabel; - valueHop = Math.floor(xAxisLength/(data.labels.length)); - - barWidth = (valueHop - config.scaleGridLineWidth*2 - (config.barValueSpacing*2) - (config.barDatasetSpacing*data.datasets.length-1) - ((config.barStrokeWidth/2)*data.datasets.length-1))/data.datasets.length; - - yAxisPosX = width-widestXLabel/2-xAxisLength; - xAxisPosY = scaleHeight + config.scaleFontSize/2; - } - function calculateDrawingSizes(){ - maxSize = height; - - //Need to check the X axis first - measure the length of each text metric, and figure out if we need to rotate by 45 degrees. - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize+"px " + config.scaleFontFamily; - widestXLabel = 1; - for (var i=0; i<data.labels.length; i++){ - var textLength = ctx.measureText(data.labels[i]).width; - //If the text length is longer - make that equal to longest text! - widestXLabel = (textLength > widestXLabel)? textLength : widestXLabel; - } - if (width/data.labels.length < widestXLabel){ - rotateLabels = 45; - if (width/data.labels.length < Math.cos(rotateLabels) * widestXLabel){ - rotateLabels = 90; - maxSize -= widestXLabel; - } - else{ - maxSize -= Math.sin(rotateLabels) * widestXLabel; - } - } - else{ - maxSize -= config.scaleFontSize; - } - - //Add a little padding between the x line and the text - maxSize -= 5; - - - labelHeight = config.scaleFontSize; - - maxSize -= labelHeight; - //Set 5 pixels greater than the font size to allow for a little padding from the X axis. - - scaleHeight = maxSize; - - //Then get the area above we can safely draw on. - - } - function getValueBounds() { - var upperValue = Number.MIN_VALUE; - var lowerValue = Number.MAX_VALUE; - for (var i=0; i<data.datasets.length; i++){ - for (var j=0; j<data.datasets[i].data.length; j++){ - if ( data.datasets[i].data[j] > upperValue) { upperValue = data.datasets[i].data[j] }; - if ( data.datasets[i].data[j] < lowerValue) { lowerValue = data.datasets[i].data[j] }; - } - }; - - var maxSteps = Math.floor((scaleHeight / (labelHeight*0.66))); - var minSteps = Math.floor((scaleHeight / labelHeight*0.5)); - - return { - maxValue : upperValue, - minValue : lowerValue, - maxSteps : maxSteps, - minSteps : minSteps - }; - - - } - } - - function calculateOffset(val,calculatedScale,scaleHop){ - var outerValue = calculatedScale.steps * calculatedScale.stepValue; - var adjustedValue = val - calculatedScale.graphMin; - var scalingFactor = CapValue(adjustedValue/outerValue,1,0); - return (scaleHop*calculatedScale.steps) * scalingFactor; - } - - function animationLoop(config,drawScale,drawData,ctx){ - var animFrameAmount = (config.animation)? 1/CapValue(config.animationSteps,Number.MAX_VALUE,1) : 1, - easingFunction = animationOptions[config.animationEasing], - percentAnimComplete =(config.animation)? 0 : 1; - - - - if (typeof drawScale !== "function") drawScale = function(){}; - - requestAnimFrame(animLoop); - - function animateFrame(){ - var easeAdjustedAnimationPercent =(config.animation)? CapValue(easingFunction(percentAnimComplete),null,0) : 1; - clear(ctx); - if(config.scaleOverlay){ - drawData(easeAdjustedAnimationPercent); - drawScale(); - } else { - drawScale(); - drawData(easeAdjustedAnimationPercent); - } - } - function animLoop(){ - //We need to check if the animation is incomplete (less than 1), or complete (1). - percentAnimComplete += animFrameAmount; - animateFrame(); - //Stop the loop continuing forever - if (percentAnimComplete <= 1){ - requestAnimFrame(animLoop); - } - else{ - if (typeof config.onAnimationComplete == "function") config.onAnimationComplete(); - } - - } - - } - - //Declare global functions to be called within this namespace here. - - - // shim layer with setTimeout fallback - var requestAnimFrame = (function(){ - return window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.oRequestAnimationFrame || - window.msRequestAnimationFrame || - function(callback) { - window.setTimeout(callback, 1000 / 60); - }; - })(); - - function calculateScale(drawingHeight,maxSteps,minSteps,maxValue,minValue,labelTemplateString){ - var graphMin,graphMax,graphRange,stepValue,numberOfSteps,valueRange,rangeOrderOfMagnitude,decimalNum; - - valueRange = maxValue - minValue; - - rangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange); - - graphMin = Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude); - - graphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude); - - graphRange = graphMax - graphMin; - - stepValue = Math.pow(10, rangeOrderOfMagnitude); - - numberOfSteps = Math.round(graphRange / stepValue); - - //Compare number of steps to the max and min for that size graph, and add in half steps if need be. - while(numberOfSteps < minSteps || numberOfSteps > maxSteps) { - if (numberOfSteps < minSteps){ - stepValue /= 2; - numberOfSteps = Math.round(graphRange/stepValue); - } - else{ - stepValue *=2; - numberOfSteps = Math.round(graphRange/stepValue); - } - }; - - var labels = []; - populateLabels(labelTemplateString, labels, numberOfSteps, graphMin, stepValue); - - return { - steps : numberOfSteps, - stepValue : stepValue, - graphMin : graphMin, - labels : labels - - } - - function calculateOrderOfMagnitude(val){ - return Math.floor(Math.log(val) / Math.LN10); - } - - - } - - //Populate an array of all the labels by interpolating the string. - function populateLabels(labelTemplateString, labels, numberOfSteps, graphMin, stepValue) { - if (labelTemplateString) { - //Fix floating point errors by setting to fixed the on the same decimal as the stepValue. - for (var i = 1; i < numberOfSteps + 1; i++) { - labels.push(tmpl(labelTemplateString, {value: (graphMin + (stepValue * i)).toFixed(getDecimalPlaces(stepValue))})); - } - } - } - - //Max value from array - function Max( array ){ - return Math.max.apply( Math, array ); - }; - //Min value from array - function Min( array ){ - return Math.min.apply( Math, array ); - }; - //Default if undefined - function Default(userDeclared,valueIfFalse){ - if(!userDeclared){ - return valueIfFalse; - } else { - return userDeclared; - } - }; - //Is a number function - function isNumber(n) { - return !isNaN(parseFloat(n)) && isFinite(n); - } - //Apply cap a value at a high or low number - function CapValue(valueToCap, maxValue, minValue){ - if(isNumber(maxValue)) { - if( valueToCap > maxValue ) { - return maxValue; - } - } - if(isNumber(minValue)){ - if ( valueToCap < minValue ){ - return minValue; - } - } - return valueToCap; - } - function getDecimalPlaces (num){ - var numberOfDecimalPlaces; - if (num%1!=0){ - return num.toString().split(".")[1].length - } - else{ - return 0; - } - - } - - function mergeChartConfig(defaults,userDefined){ - var returnObj = {}; - for (var attrname in defaults) { returnObj[attrname] = defaults[attrname]; } - for (var attrname in userDefined) { returnObj[attrname] = userDefined[attrname]; } - return returnObj; - } - - //Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/ - var cache = {}; - - function tmpl(str, data){ - // Figure out if we're getting a template, or if we need to - // load the template - and be sure to cache the result. - var fn = !/\W/.test(str) ? - cache[str] = cache[str] || - tmpl(document.getElementById(str).innerHTML) : - - // Generate a reusable function that will serve as a template - // generator (and which will be cached). - new Function("obj", - "var p=[],print=function(){p.push.apply(p,arguments);};" + - - // Introduce the data as local variables using with(){} - "with(obj){p.push('" + - - // Convert the template into pure JavaScript - str - .replace(/[\r\t\n]/g, " ") - .split("<%").join("\t") - .replace(/((^|%>)[^\t]*)'/g, "$1\r") - .replace(/\t=(.*?)%>/g, "',$1,'") - .split("\t").join("');") - .split("%>").join("p.push('") - .split("\r").join("\\'") - + "');}return p.join('');"); - - // Provide some basic currying to the user - return data ? fn( data ) : fn; - }; -} - - http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/70fced06/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/app.js ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/app.js b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/app.js index 13bf46b..1a51a66 100644 --- a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/app.js +++ b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/app.js @@ -15,34 +15,4 @@ * limitations under the License. */ -var blurApp = angular.module('blurApp', ['ui.bootstrap']) - -blurApp.chart = function (type) { - return { - restrict: "A", - scope: { - data: "=", - options: "=", - id: "@" - }, - link: function ($scope, $elem) { - var ctx = $elem[0].getContext("2d"); - var chart = new Chart(ctx); - - $scope.$watch("data", function (newVal, oldVal) { - // if data not defined, exit - if (!newVal) return; - - chart[type]($scope.data, $scope.options); - }, true); - } - } -} - -/* Aliases for various chart types */ -blurApp.directive("linechart", function () { return blurApp.chart("Line"); }); -blurApp.directive("barchart", function () { return blurApp.chart("Bar"); }); -blurApp.directive("radarchart", function () { return blurApp.chart("Radar"); }); -blurApp.directive("polarchart", function () { return blurApp.chart("PolarArea"); }); -blurApp.directive("piechart", function () { return blurApp.chart("Pie"); }); -blurApp.directive("doughnutchart", function () { return blurApp.chart("Doughnut"); }); \ No newline at end of file +var blurApp = angular.module('blurApp', ['ui.bootstrap', 'flotr']); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/70fced06/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/directives.js ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/directives.js b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/directives.js new file mode 100644 index 0000000..3ed1a87 --- /dev/null +++ b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/directives.js @@ -0,0 +1,140 @@ +blurApp.directive('piechart', ['flotrService', '$window', function(flotrService, $window){ + return { + restrict: 'EA', + scope: { + chartdata: '=' + }, + link: function(scope, element, attrs) { + flotrService.flotr().then(function(Flotr) { + window.onresize = function() { + scope.$apply(); + }; + + scope.$watch(function() { + return angular.element($window)[0].innerWidth; + }, function() { + scope.render(scope.chartdata); + }); + + scope.$watch('chartdata', function(newVals, oldVals) { + return scope.render(newVals); + }, true); + + scope.render = function(data) { + element.children().remove(); + if (!data) return; + + var width = element.parent()[0].clientWidth - 10, + height = width; + + element.css('height', height); + element.css('width', width); + + Flotr.draw(element[0], data, { + HtmlText: false, + grid: { + verticalLines: false, + horizontalLines: false + }, + xaxis: { showLabels: false }, + yaxis: { showLabels: false }, + pie: { + show: true + }, + legend: { + show: false + } + }); + } + }); + } + }; +}]); + +// blurApp.directive('doughnutchart', ['d3Service', '$window', function(d3Service, $window) { +// return { +// restrict: 'EA', +// scope: { +// chartdata: '=' +// }, +// link: function (scope, element, attrs) { +// d3Service.d3().then(function(d3) { +// var margin = parseInt(attrs.margin) || 20, +// ringHeight = parseInt(attrs.ringHeight) || 300, +// ringRadius = parseInt(attrs.ringRadius) || 5; + +// var svg = d3.select(element[0]).append("svg:svg"); + +// window.onresize = function() { +// scope.$apply(); +// }; + +// scope.$watch(function() { +// return angular.element($window)[0].innerWidth; +// }, function() { +// scope.render(scope.chartdata); +// }); + +// scope.$watch('data', function(newVals, oldVals) { +// return scope.render(newVals); +// }, true); + +// scope.render = function(data) { +// svg.selectAll('*').remove(); + +// if (!data) return; + +// var w = 400, +// h = 400, +// r = Math.min(w, h) / 2, +// labelr = r + 30, +// color = d3.scale.category20, +// donut = d3.layout.pie(), +// arc = d3.svg.arc().innerRadius(r * .6).outerRadius(r); + +// var vis = svg.data([data]) +// .attr('width', w + 150) +// .attr('height', h); + +// var arcs = vis.selectAll('g.arc') +// .data(donut.value(function(d){ return d.val })) +// .enter().append('svg:g') +// .attr('class', 'arc') +// .attr('transform', 'translate(' + (r + 30) + ',' + r + ')'); + +// arcs.append('svg:path') +// .attr('fill', function(d, i){ return color(i); }) +// .attr('d', arc); + +// arcs.append('svg:text') +// .attr('transform', function(d){ +// var c = arc.centroid(d), +// x = c[0], +// y = c[1], +// h = Math.sqrt(x*x + y*y); +// return "translate(" + (x/h * labelr) + ',' + (y/h * labelr) + ")"; +// }) +// .attr('dy', '.35em') +// .attr('text-anchor', function(d){ +// return (d.endAngle + d.startAngle)/2 > Math.PI ? "end" : "start"; +// }) +// .text(function(d, i){ return d.value.toFixed(2); }); + +// // var width = d3.select(element[0]).node().offsetWidth - margin, +// // height = ringHeight, +// // color = d3.scale.category20(); + +// // var pie = d3.layout.pie().sort(null); +// // var arc = d3.svg.arc().innerRadius(ringRadius - 100).outerRadius(ringRadius - 50); + +// // svg.attr('width', width); +// // svg.attr('height', height); +// // svg.append('g'); +// // svg.attr('transform', 'translate(' + width / 2 + ',' + height /2 + ')'); + +// // var path = svg.selectAll('path').data(pie(scope.chartdata)).enter().append('path').attr('fill', function(d, i) { return color(i); }).attr('d', arc); +// } +// }); +// } +// } +// }]); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/70fced06/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/factories.js ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/factories.js b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/factories.js new file mode 100644 index 0000000..9aa764a --- /dev/null +++ b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/factories.js @@ -0,0 +1,22 @@ +angular.module('flotr', []).factory('flotrService', ['$document', '$q', '$rootScope', function($document, $q, $rootScope) { + var d = $q.defer(); + function onScriptLoad() { + $rootScope.$apply(function() { d.resolve(window.Flotr); }); + } + + var scriptTag = $document[0].createElement('script'); + scriptTag.type = 'text/javascript'; + scriptTag.async = true; + scriptTag.src = 'js/flotr2.js'; + scriptTag.onreadystatechage = function () { + if (this.readyState == 'complete') onScriptLoad(); + } + scriptTag.onload = onScriptLoad; + + var s = $document[0].getElementsByTagName('body')[0]; + s.appendChild(scriptTag); + + return { + flotr: function() { return d.promise; } + }; +}]) \ No newline at end of file
