| Index: bower_components/chartnewjs/ChartNew.js
|
| diff --git a/bower_components/chartnewjs/ChartNew.js b/bower_components/chartnewjs/ChartNew.js
|
| deleted file mode 100644
|
| index 6c756e6e647a101f9c0dc5e811a893ab9bb795c0..0000000000000000000000000000000000000000
|
| --- a/bower_components/chartnewjs/ChartNew.js
|
| +++ /dev/null
|
| @@ -1,6491 +0,0 @@
|
| -/*
|
| - * ChartNew.js
|
| - *
|
| - * Vancoppenolle Francois - January 2014
|
| - * francois.vancoppenolle@favomo.be
|
| - *
|
| - * Source location : http:\\www.favomo.be\graphjs
|
| - * GitHub community : https://github.com/FVANCOP/ChartNew.js
|
| - *
|
| - * This file is an adaptation of the chart.js source developped by Nick Downie (2013)
|
| - * https://github.com/nnnick/Chart.js
|
| - *
|
| - * new charts
|
| - *
|
| - * horizontalBar
|
| - * horizontalStackedBar
|
| - *
|
| - * Added items :
|
| - *
|
| - * Title
|
| - * Subtitle
|
| - * X Axis Label
|
| - * Y Axis Label
|
| - * Unit Label
|
| - * Y Axis on the right and/or the left
|
| - * Annotates
|
| - * canvas Border
|
| - * Legend
|
| - * Footnote
|
| - * crossText
|
| - * graphMin / graphMax
|
| - * logarithmic y-axis (for line and bar)
|
| - * rotateLabels
|
| - * and lot of others...
|
| - *
|
| - */
|
| -// non standard functions;
|
| -if (typeof String.prototype.trim !== 'function') {
|
| - String.prototype.trim = function() {
|
| - return this.replace(/^\s+|\s+$/g, '');
|
| - }
|
| -};
|
| -if (!Array.prototype.indexOf) {
|
| - Array.prototype.indexOf = function(searchElement /*, fromIndex */ ) {
|
| - "use strict";
|
| - if (this == null) {
|
| - throw new TypeError();
|
| - }
|
| - var t = Object(this);
|
| - var len = t.length >>> 0;
|
| - if (len === 0) {
|
| - return -1;
|
| - }
|
| - var n = 0;
|
| - if (arguments.length > 0) {
|
| - n = Number(arguments[1]);
|
| - if (n != n) { // shortcut for verifying if it's NaN
|
| - n = 0;
|
| - } else if (n != 0 && n != Infinity && n != -Infinity) {
|
| - n = (n > 0 || -1) * Math.floor(Math.abs(n));
|
| - }
|
| - }
|
| - if (n >= len) {
|
| - return -1;
|
| - }
|
| - var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
|
| - for (; k < len; k++) {
|
| - if (k in t && t[k] === searchElement) {
|
| - return k;
|
| - }
|
| - }
|
| - return -1;
|
| - }
|
| -};
|
| -var charJSPersonalDefaultOptions = {}
|
| -var charJSPersonalDefaultOptionsLine = {}
|
| -var charJSPersonalDefaultOptionsRadar = {}
|
| -var charJSPersonalDefaultOptionsPolarArea = {}
|
| -var charJSPersonalDefaultOptionsPie = {}
|
| -var charJSPersonalDefaultOptionsDoughnut = {}
|
| -var charJSPersonalDefaultOptionsBar = {}
|
| -var charJSPersonalDefaultOptionsStackedBar = {}
|
| -var charJSPersonalDefaultOptionsHorizontalBar = {}
|
| -var charJSPersonalDefaultOptionsHorizontalStackedBar = {}
|
| - ///////// FUNCTIONS THAN CAN BE USED IN THE TEMPLATES ///////////////////////////////////////////
|
| -
|
| -function roundToWithThousands(config, num, place) {
|
| - var newval = 1 * unFormat(config, num);
|
| - if (typeof(newval) == "number" && place != "none") {
|
| - if (place <= 0) {
|
| - var roundVal = -place;
|
| - newval = +(Math.round(newval + "e+" + roundVal) + "e-" + roundVal);
|
| - } else {
|
| - var roundVal = place;
|
| - var divval = "1e+" + roundVal;
|
| - newval = +(Math.round(newval / divval)) * divval;
|
| - }
|
| - }
|
| - newval = fmtChartJS(config, newval, "none");
|
| - return (newval);
|
| -};
|
| -
|
| -function unFormat(config, num) {
|
| - if ((config.decimalSeparator != "." || config.thousandSeparator != "") && typeof(num) == "string") {
|
| - var v1 = "" + num;
|
| - if (config.thousandSeparator != "") {
|
| - while (v1.indexOf(config.thousandSeparator) >= 0) v1 = "" + v1.replace(config.thousandSeparator, "");
|
| - }
|
| - if (config.decimalSeparator != ".") v1 = "" + v1.replace(config.decimalSeparator, ".")
|
| - // v1=fmtChartJS(config,1*roundToWithThousands(1*v1,place),"none")
|
| - return 1 * v1;
|
| - } else {
|
| - return num;
|
| - }
|
| -};
|
| -///////// ANNOTATE PART OF THE SCRIPT ///////////////////////////////////////////
|
| -/********************************************************************************
|
| -Copyright (C) 1999 Thomas Brattli
|
| -This script is made by and copyrighted to Thomas Brattli
|
| -Visit for more great scripts. This may be used freely as long as this msg is intact!
|
| -I will also appriciate any links you could give me.
|
| -Distributed by Hypergurl
|
| -********************************************************************************/
|
| -var cachebis = {};
|
| -
|
| -function fmtChartJSPerso(config, value, fmt) {
|
| - switch (fmt) {
|
| - case "SampleJS_Format":
|
| - if (typeof(value) == "number") return_value = "My Format : " + value.toString() + " $";
|
| - else return_value = value + "XX";
|
| - break;
|
| - case "Change_Month":
|
| - if (typeof(value) == "string") return_value = value.toString() + " 2014";
|
| - else return_value = value.toString() + "YY";
|
| - break;
|
| - default:
|
| - return_value = value;
|
| - break;
|
| - }
|
| - return (return_value);
|
| -};
|
| -
|
| -function fmtChartJS(config, value, fmt) {
|
| - var return_value;
|
| - if (fmt == "notformatted") {
|
| - return_value = value;
|
| - } else if (fmt == "none" && typeof(value) == "number") {
|
| - if (config.roundNumber != "none") {
|
| - if (config.roundNumber <= 0) {
|
| - var roundVal = -config.roundNumber;
|
| - value = +(Math.round(value + "e+" + roundVal) + "e-" + roundVal);
|
| - } else {
|
| - var roundVal = config.roundNumber;
|
| - var divval = "1e+" + roundVal;
|
| - value = +(Math.round(value / divval)) * divval;
|
| - }
|
| - }
|
| - if (config.decimalSeparator != "." || config.thousandSeparator != "") {
|
| - return_value = value.toString().replace(/\./g, config.decimalSeparator);
|
| - if (config.thousandSeparator != "") {
|
| - var part1 = return_value;
|
| - var part2 = "";
|
| - var posdec = part1.indexOf(config.decimalSeparator);
|
| - if (posdec >= 0) {
|
| - part2 = part1.substring(posdec + 1, part1.length);
|
| - part2 = part2.split('').reverse().join(''); // reverse string
|
| - part1 = part1.substring(0, posdec);
|
| - }
|
| - part1 = part1.toString().replace(/\B(?=(\d{3})+(?!\d))/g, config.thousandSeparator);
|
| - // part2=part2.toString().replace(/\B(?=(\d{3})+(?!\d))/g, config.thousandSeparator);
|
| - part2 = part2.split('').reverse().join(''); // reverse string
|
| - return_value = part1
|
| - if (part2 != "") return_value = return_value + config.decimalSeparator + part2;
|
| - }
|
| - } else return_value = value;
|
| - } else if (fmt != "none" && fmt != "notformatted") {
|
| - return_value = fmtChartJSPerso(config, value, fmt);
|
| - } else {
|
| - return_value = value;
|
| - }
|
| - return (return_value);
|
| -};
|
| -
|
| -function addParameters2Function(data, fctName, fctList) {
|
| - var mathFunctions = {
|
| - mean: {
|
| - data: data.data,
|
| - datasetNr: data.v11
|
| - },
|
| - varianz: {
|
| - data: data.data,
|
| - datasetNr: data.v11
|
| - },
|
| - stddev: {
|
| - data: data.data,
|
| - datasetNr: data.v11
|
| - },
|
| - cv: {
|
| - data: data.data,
|
| - datasetNr: data.v11
|
| - },
|
| - median: {
|
| - data: data.data,
|
| - datasetNr: data.v11
|
| - }
|
| - };
|
| - // difference to current value (v3)
|
| - dif = false;
|
| - if (fctName.substr(-3) == "Dif") {
|
| - fctName = fctName.substr(0, fctName.length - 3);
|
| - dif = true;
|
| - }
|
| - if (typeof eval(fctName) == "function") {
|
| - var parameter = eval(fctList + "." + fctName);
|
| - if (dif) {
|
| - // difference between v3 (current value) and math function
|
| - return data.v3 - window[fctName](parameter);
|
| - }
|
| - return window[fctName](parameter);
|
| - }
|
| - return;
|
| - }
|
| - //Is a number function
|
| -
|
| -function isNumber(n) {
|
| - return !isNaN(parseFloat(n)) && isFinite(n);
|
| -};
|
| -
|
| -function tmplbis(str, data) {
|
| - var mathFunctionList = ["mean", "varianz", "stddev", "cv", "median"];
|
| - var regexMath = new RegExp('<%=((?:(?:.*?)\\W)??)((?:' + mathFunctionList.join('|') + ')(?:Dif)?)\\(([0-9]*?)\\)(.*?)%>', 'g');
|
| - while (regexMath.test(str)) {
|
| - str = str.replace(regexMath, function($0, $1, $2, $3, $4) {
|
| - if ($3) {
|
| - var rndFac = $3;
|
| - } else {
|
| - var rndFac = 2;
|
| - }
|
| - var value = addParameters2Function(data, $2, "mathFunctions");
|
| - if (isNumber(value)) {
|
| - return '<%=' + $1 + '' + Math.round(Math.pow(10, rndFac) * value) / Math.pow(10, rndFac) + '' + $4 + '%>';
|
| - }
|
| - return '<%= %>';
|
| - });
|
| - }
|
| - // Figure out if we're getting a template, or if we need to
|
| - // load the template - and be sure to cache the result.
|
| - // first check if it's can be an id
|
| - var fn = /^[A-Za-z][-A-Za-z0-9_:.]*$/.test(str) ? cachebis[str] = cachebis[str] ||
|
| - tmplbis(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\n]/g, "\\n")
|
| - .replace(/[\t]/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;
|
| -};
|
| -/**
|
| - * ctx.prototype
|
| - * fillText option for canvas Multiline Support
|
| - * @param text string \n for newline
|
| - * @param x x position
|
| - * @param y y position
|
| - * @param yLevel = "bottom" => last line has this y-Pos [default], = "middle" => the middle line has this y-Pos)
|
| - * @param lineHeight lineHeight
|
| - */
|
| -CanvasRenderingContext2D.prototype.fillTextMultiLine = function(text, x, y, yLevel, lineHeight) {
|
| - var lines = ("" + text).split("\n");
|
| - // if its one line => in the middle
|
| - // two lines one above the mid one below etc.
|
| - if (yLevel == "middle") {
|
| - y -= ((lines.length - 1) / 2) * lineHeight;
|
| - } else if (yLevel == "bottom") { // default
|
| - y -= (lines.length - 1) * lineHeight;
|
| - }
|
| - for (var i = 0; i < lines.length; i++) {
|
| - this.fillText(lines[i], x, y);
|
| - y += lineHeight;
|
| - }
|
| -}
|
| -CanvasRenderingContext2D.prototype.measureTextMultiLine = function(text, lineHeight) {
|
| - var textWidth = 0;
|
| - var lg;
|
| - var lines = ("" + text).split("\n");
|
| - var textHeight = lines.length * lineHeight;
|
| - // if its one line => in the middle
|
| - // two lines one above the mid one below etc.
|
| - for (var i = 0; i < lines.length; i++) {
|
| - lg = this.measureText(lines[i]).width;
|
| - if (lg > textWidth) textWidth = lg;
|
| - }
|
| - return {
|
| - textWidth: textWidth,
|
| - textHeight: textHeight
|
| - };
|
| -}
|
| -cursorDivCreated = false;
|
| -
|
| -function createCursorDiv() {
|
| - if (cursorDivCreated == false) {
|
| - var div = document.createElement('divCursor');
|
| - div.id = 'divCursor';
|
| - div.style.position = 'absolute';
|
| - document.body.appendChild(div);
|
| - cursorDivCreated = true;
|
| - }
|
| -};
|
| -
|
| -initChartJsResize = false;
|
| -var jsGraphResize = new Array();
|
| -
|
| -function addResponsiveChart(id,ctx,data,config) {
|
| - initChartResize();
|
| - var newSize=resizeGraph(ctx,config);
|
| -
|
| - if(typeof ctx.prevWidth != "undefined") {
|
| - resizeCtx(ctx,newSize.newWidth,newSize.newHeight);
|
| - ctx.prevWidth=newSize.newWidth;
|
| - }
|
| - ctx.prevWidth=newSize.newWidth;
|
| - ctx.prevHeight=newSize.newHeight;
|
| - jsGraphResize[jsGraphResize.length]= [id,ctx.tpchart,ctx,data,config];
|
| -};
|
| -
|
| -function initChartResize() {
|
| - if(initChartJsResize==false) {
|
| - window.addEventListener("resize", chartJsResize);
|
| - }
|
| -};
|
| -
|
| -function getMaximumWidth(domNode){
|
| - var container = domNode.parentNode;
|
| - // TODO = check cross browser stuff with this.
|
| - return container.clientWidth;
|
| -};
|
| -
|
| -function getMaximumHeight(domNode){
|
| - var container = domNode.parentNode;
|
| - // TODO = check cross browser stuff with this.
|
| - return container.clientHeight;
|
| -};
|
| -
|
| -
|
| -function resizeCtx(ctx,newWidth,newHeight)
|
| -{
|
| - if (window.devicePixelRatio) { // Retina devine
|
| -
|
| - ctx.canvas.style.width = newWidth/window.devicePixelRatio + "px";
|
| - ctx.canvas.style.height = newHeight/window.devicePixelRatio + "px";
|
| - ctx.canvas.height = newHeight/window.devicePixelRatio * window.devicePixelRatio;
|
| - ctx.canvas.width = newWidth/window.devicePixelRatio * window.devicePixelRatio;
|
| - ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
|
| - } else {
|
| - ctx.canvas.height = newHeight ;
|
| - ctx.canvas.width = newWidth;
|
| - }
|
| -}
|
| -
|
| -function resizeGraph(ctx,config) {
|
| - if(typeof config.maintainAspectRatio == "undefined")config.maintainAspectRatio=true;
|
| - var canvas = ctx.canvas;
|
| - if(typeof ctx.aspectRatio == "undefined") {
|
| - ctx.aspectRatio = canvas.width / canvas.height;
|
| - }
|
| - var newWidth = getMaximumWidth(canvas);
|
| - var newHeight = config.maintainAspectRatio ? newWidth / ctx.aspectRatio : getMaximumHeight(canvas);
|
| - return { newWidth : parseInt(newWidth), newHeight : parseInt(newHeight)};
|
| -};
|
| -
|
| -
|
| -
|
| -function chartJsResize() {
|
| - for (var i=0;i<jsGraphResize.length;i++) {
|
| - if(typeof jsGraphResize[i][2].firstPass != "undefined") {
|
| - if(jsGraphResize[i][2].firstPass == 5)jsGraphResize[i][2].firstPass=6;
|
| - }
|
| - subUpdateChart(jsGraphResize[i][2],jsGraphResize[i][3],jsGraphResize[i][4]);
|
| - }
|
| -};
|
| -
|
| -function testRedraw(ctx,data,config) {
|
| - if (ctx.firstPass==2 || ctx.firstPass==4 || ctx.firstPass==9) {
|
| - ctx.firstPass=6;
|
| - subUpdateChart(ctx,data,config) ;
|
| - return true;
|
| - } else {
|
| - ctx.firstPass=5;
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -function updateChart(ctx,data,config,animation,runanimationcompletefunction) {
|
| - if (ctx.firstPass==5)
|
| - {
|
| - ctx.runanimationcompletefunction=runanimationcompletefunction;
|
| - if(animation)ctx.firstPass=0;
|
| - else if (config.responsive) ctx.firstPass=7;
|
| - else ctx.firstPass=7;
|
| - subUpdateChart(ctx,data,config) ;
|
| -
|
| - }
|
| -}
|
| -
|
| -function subUpdateChart(ctx,data,config) {
|
| - // ctx.firstPass==undefined => graph never drawn
|
| - // ctx.firstPass==0 => graph is drawn but need to be redrawn with animation
|
| - // ctx.firstPass==1 => graph is drawn with animation
|
| - // ctx.firstPass==2 => graph is in animation but at the end the graph need perhaps to be redrawn;
|
| - // ctx.firstPass==3 => graph currently drawing without animation;
|
| - // ctx.firstPass==4 => graph currently drawing without animationb but at the end, the graph need perhaps to be redrawn;
|
| - // ctx.firstPass==5 => graph is displayed ;
|
| - // ctx.firstPass==6 => graph is displayed but need to be redraw without animation (because of a resize);
|
| - // ctx.firstPass==7 => graph is displayed but need to be redraw without responsivity;
|
| -
|
| -
|
| - if(!dynamicFunction(data, config, ctx)) { return; }
|
| -
|
| - if(typeof ctx.firstPass == "undefined") {
|
| - ctx.firstPass=1;
|
| - var newSize=resizeGraph(ctx,config);
|
| - if(config.responsive) {
|
| - resizeCtx(ctx,newSize.newWidth,newSize.newHeight);
|
| - ctx.prevWidth=newSize.newWidth;
|
| - ctx.prevHeight=newSize.newHeight;
|
| - } else {
|
| - ctx.prevWidth=0;
|
| - ctx.prevHeight=0;
|
| - }
|
| - ctx.runanimationcompletefunction=true;
|
| - redrawGraph(ctx,data,config);
|
| - } else if(ctx.firstPass == 0) {
|
| - ctx.firstPass=1;
|
| - var newSize=resizeGraph(ctx,config);
|
| - if(config.responsive) {
|
| - resizeCtx(ctx,newSize.newWidth,newSize.newHeight);
|
| - ctx.prevWidth=newSize.newWidth;
|
| - ctx.prevHeight=newSize.newHeight;
|
| - } else {
|
| - ctx.prevWidth=0;
|
| - ctx.prevHeight=0;
|
| - }
|
| - redrawGraph(ctx,data,config);
|
| - } else if(ctx.firstPass==1 || ctx.firstPass==2) {
|
| - ctx.firstPass=2;
|
| - } else if (ctx.firstPass==3 || ctx.firstPass==4) {
|
| - ctx.firstPass=4;
|
| - } else if(ctx.firstPass==5) {
|
| - ctx.firstPass=1;
|
| - redrawGraph(ctx,data,config);
|
| - } else if(ctx.firstPass==6) {
|
| - var newSize=resizeGraph(ctx,config);
|
| - if (newSize.newWidth!=ctx.prevWidth || newSize.newHeight != ctx.prevHeight) {
|
| - ctx.firstPass=3;
|
| - ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
| - if(config.responsive) {
|
| - resizeCtx(ctx,newSize.newWidth,newSize.newHeight);
|
| - ctx.prevWidth=newSize.newWidth;
|
| - ctx.prevHeight=newSize.newHeight;
|
| - } else {
|
| - ctx.prevWidth=0;
|
| - ctx.prevHeight=0;
|
| - }
|
| - redrawGraph(ctx,data,config);
|
| - } else ctx.firstPass=5;
|
| - } else if(ctx.firstPass==7) {
|
| - var newSize=resizeGraph(ctx,config);
|
| - ctx.firstPass=3;
|
| - ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
| - if(config.responsive) {
|
| - resizeCtx(ctx,newSize.newWidth,newSize.newHeight);
|
| - ctx.prevWidth=newSize.newWidth;
|
| - ctx.prevHeight=newSize.newHeight;
|
| - } else {
|
| - ctx.prevWidth=0;
|
| - ctx.prevHeight=0;
|
| - }
|
| - redrawGraph(ctx,data,config);
|
| - }
|
| -};
|
| -
|
| -function redrawGraph(ctx,data,config) {
|
| - var myGraph = new Chart(ctx);
|
| - switch (ctx.tpchart) {
|
| - case "Bar":
|
| - myGraph.Bar(data,config);
|
| - break;
|
| - case "Pie":
|
| - myGraph.Pie(data,config);
|
| - break;
|
| - case "Doughnut":
|
| - myGraph.Doughnut(data,config);
|
| - break;
|
| - case "Radar":
|
| - myGraph.Radar(data,config);
|
| - break;
|
| - case "PolarArea":
|
| - myGraph.PolarArea(data,config);
|
| - break;
|
| - case "HorizontalBar":
|
| - myGraph.HorizontalBar(data,config);
|
| - break;
|
| - case "StackedBar":
|
| - myGraph.StackedBar(data,config);
|
| - break;
|
| - case "HorizontalStackedBar":
|
| - myGraph.HorizontalStackedBar(data,config);
|
| - break;
|
| - case "Line":
|
| - myGraph.Line(data,config);
|
| - break;
|
| - }
|
| -
|
| -
|
| -
|
| -}
|
| -
|
| -
|
| -//Default browsercheck, added to all scripts!
|
| -function checkBrowser() {
|
| - this.ver = navigator.appVersion
|
| - this.dom = document.getElementById ? 1 : 0
|
| - this.ie5 = (this.ver.indexOf("MSIE 5") > -1 && this.dom) ? 1 : 0;
|
| - this.ie4 = (document.all && !this.dom) ? 1 : 0;
|
| - this.ns5 = (this.dom && parseInt(this.ver) >= 5) ? 1 : 0;
|
| - this.ns4 = (document.layers && !this.dom) ? 1 : 0;
|
| - this.bw = (this.ie5 || this.ie4 || this.ns4 || this.ns5)
|
| - return this
|
| -};
|
| -bw = new checkBrowser();
|
| -//Set these variables:
|
| -fromLeft = 10; // How much from the left of the cursor should the div be?
|
| -fromTop = 10; // How much from the top of the cursor should the div be?
|
| -/********************************************************************
|
| -Initilizes the objects
|
| -*********************************************************************/
|
| -function cursorInit() {
|
| - scrolled = bw.ns4 || bw.ns5 ? "window.pageYOffset" : "document.body.scrollTop"
|
| - if (bw.ns4) document.captureEvents(Event.MOUSEMOVE)
|
| -};
|
| -/********************************************************************
|
| -Contructs the cursorobjects
|
| -*********************************************************************/
|
| -function makeCursorObj(obj, nest) {
|
| - createCursorDiv();
|
| - nest = (!nest) ? '' : 'document.' + nest + '.'
|
| - this.css = bw.dom ? document.getElementById(obj).style : bw.ie4 ? document.all[obj].style : bw.ns4 ? eval(nest + "document.layers." + obj) : 0;
|
| - this.moveIt = b_moveIt;
|
| - cursorInit();
|
| - return this
|
| -};
|
| -
|
| -function b_moveIt(x, y) {
|
| - this.x = x;
|
| - this.y = y;
|
| - this.css.left = this.x + "px";
|
| - this.css.top = this.y + "px";
|
| -};
|
| -
|
| -function isIE() {
|
| - var myNav = navigator.userAgent.toLowerCase();
|
| - return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false;
|
| -};
|
| -
|
| -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;
|
| -};
|
| -
|
| -function sleep(ms) {
|
| - var dt = new Date();
|
| - dt.setTime(dt.getTime() + ms);
|
| - while (new Date().getTime() < dt.getTime()) {};
|
| -};
|
| -
|
| -function saveCanvas(ctx, data, config) {
|
| - cvSave = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
|
| - var saveCanvasConfig = {
|
| - savePng: false,
|
| - annotateDisplay: false,
|
| - animation: false,
|
| - dynamicDisplay: false
|
| - };
|
| - var savePngConfig = mergeChartConfig(config, saveCanvasConfig);
|
| - savePngConfig.clearRect = false;
|
| - /* And ink them */
|
| -
|
| - redrawGraph(ctx,data,savePngConfig);
|
| - if (config.savePngOutput == "NewWindow") {
|
| - var image = ctx.canvas.toDataURL();
|
| - ctx.putImageData(cvSave, 0, 0);
|
| - window.open(image, '_blank');
|
| - }
|
| - if (config.savePngOutput == "CurrentWindow") {
|
| - var image = ctx.canvas.toDataURL();
|
| - ctx.putImageData(cvSave, 0, 0);
|
| - window.location.href = image;
|
| - }
|
| - if (config.savePngOutput == "Save") {
|
| - // document.location.href= ctx.canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
|
| - // ctx.putImageData(cvSave,0,0);
|
| - var image = ctx.canvas.toDataURL();
|
| - var downloadLink = document.createElement("a");
|
| - downloadLink.href = image;
|
| - downloadLink.download = config.savePngName + ".png";
|
| - document.body.appendChild(downloadLink);
|
| - downloadLink.click();
|
| - document.body.removeChild(downloadLink);
|
| - }
|
| -};
|
| -//if (isIE() < 9 && isIE() != false) {
|
| -if (typeof String.prototype.trim !== 'function') {
|
| - String.prototype.trim = function() {
|
| - return this.replace(/^\s+|\s+$/g, '');
|
| - }
|
| -};
|
| -//};
|
| -var dynamicDisplay = new Array();
|
| -var dynamicDisplayList = new Array();
|
| -
|
| -function dynamicFunction(data, config, ctx) {
|
| -
|
| - if (config.dynamicDisplay) {
|
| - if (ctx.canvas.id == "") {
|
| - var cvdate = new Date();
|
| - var cvmillsec = cvdate.getTime();
|
| - ctx.canvas.id = "Canvas_" + cvmillsec;
|
| - }
|
| - if (typeof(dynamicDisplay[ctx.canvas.id]) == "undefined") {
|
| - dynamicDisplayList[dynamicDisplayList["length"]] = ctx.canvas.id;
|
| - dynamicDisplay[ctx.canvas.id] = [ctx, false, false, data, config, ctx.canvas];
|
| - dynamicDisplay[ctx.canvas.id][1] = isScrolledIntoView(ctx.canvas);
|
| - window.onscroll = scrollFunction;
|
| - } else if (dynamicDisplay[ctx.canvas.id][2] == false) {
|
| - dynamicDisplay[ctx.canvas.id][1] = isScrolledIntoView(ctx.canvas);
|
| - }
|
| -// if (dynamicDisplay[ctx.canvas.id][1] == false || dynamicDisplay[ctx.canvas.id][2] == true) {
|
| - if (dynamicDisplay[ctx.canvas.id][1] == false && dynamicDisplay[ctx.canvas.id][2] == false) {
|
| - return false;
|
| - }
|
| - dynamicDisplay[ctx.canvas.id][2] = true;
|
| - }
|
| - return true;
|
| -};
|
| -
|
| -function isScrolledIntoView(element) {
|
| - var xPosition = 0;
|
| - var yPosition = 0;
|
| - elem = element;
|
| - while (elem) {
|
| - xPosition += (elem.offsetLeft - elem.scrollLeft + elem.clientLeft);
|
| - yPosition += (elem.offsetTop - elem.scrollTop + elem.clientTop);
|
| - elem = elem.offsetParent;
|
| - }
|
| - if (xPosition + element.width / 2 >= window.pageXOffset &&
|
| - xPosition + element.width / 2 <= window.pageXOffset + window.innerWidth &&
|
| - yPosition + element.height / 2 >= window.pageYOffset &&
|
| - yPosition + element.height / 2 <= window.pageYOffset + window.innerHeight
|
| - ) return (true);
|
| - else return false;
|
| -};
|
| -
|
| -function scrollFunction() {
|
| - for (var i = 0; i < dynamicDisplayList["length"]; i++) {
|
| - if (isScrolledIntoView(dynamicDisplay[dynamicDisplayList[i]][5]) && dynamicDisplay[dynamicDisplayList[i]][2] == false) {
|
| - dynamicDisplay[dynamicDisplayList[i]][1] = true;
|
| - redrawGraph(dynamicDisplay[dynamicDisplayList[i]][0],dynamicDisplay[dynamicDisplayList[i]][3], dynamicDisplay[dynamicDisplayList[i]][4]);
|
| - }
|
| - }
|
| -};
|
| -
|
| -var jsGraphAnnotate = new Array();
|
| -
|
| -function clearAnnotate(ctxid) {
|
| - jsGraphAnnotate[ctxid] = [];
|
| -};
|
| -
|
| -function getMousePos(canvas, evt) {
|
| - var rect = canvas.getBoundingClientRect();
|
| - return {
|
| - x: evt.clientX - rect.left,
|
| - y: evt.clientY - rect.top
|
| - };
|
| -};
|
| -
|
| -function doMouseAction(config, ctx, event, data, action, funct) {
|
| -
|
| - var onData = false;
|
| - if (action == "annotate") {
|
| - var annotateDIV = document.getElementById('divCursor');
|
| - var show = false;
|
| - annotateDIV.className = (config.annotateClassName) ? config.annotateClassName : '';
|
| - annotateDIV.style.border = (config.annotateClassName) ? '' : config.annotateBorder;
|
| - annotateDIV.style.padding = (config.annotateClassName) ? '' : config.annotatePadding;
|
| - annotateDIV.style.borderRadius = (config.annotateClassName) ? '' : config.annotateBorderRadius;
|
| - annotateDIV.style.backgroundColor = (config.annotateClassName) ? '' : config.annotateBackgroundColor;
|
| - annotateDIV.style.color = (config.annotateClassName) ? '' : config.annotateFontColor;
|
| - annotateDIV.style.fontFamily = (config.annotateClassName) ? '' : config.annotateFontFamily;
|
| - annotateDIV.style.fontSize = (config.annotateClassName) ? '' : config.annotateFontSize + "pt";
|
| - annotateDIV.style.fontStyle = (config.annotateClassName) ? '' : config.annotateFontStyle;
|
| - }
|
| - if (action=="annotate") {
|
| - show=false;
|
| - annotateDIV.style.display = show ? '' : 'none';
|
| - }
|
| - canvas_pos = getMousePos(ctx.canvas, event);
|
| - for (i = 0; i < jsGraphAnnotate[ctx.ChartNewId]["length"]; i++) {
|
| - if (jsGraphAnnotate[ctx.ChartNewId][i][0] == "ARC") {
|
| - distance = Math.sqrt((canvas_pos.x - jsGraphAnnotate[ctx.ChartNewId][i][1]) * (canvas_pos.x - jsGraphAnnotate[ctx.ChartNewId][i][1]) + (canvas_pos.y - jsGraphAnnotate[ctx.ChartNewId][i][2]) * (canvas_pos.y - jsGraphAnnotate[ctx.ChartNewId][i][2]));
|
| - if (distance > jsGraphAnnotate[ctx.ChartNewId][i][3] && distance < jsGraphAnnotate[ctx.ChartNewId][i][4]) {
|
| - angle = Math.acos((canvas_pos.x - jsGraphAnnotate[ctx.ChartNewId][i][1]) / distance);
|
| - if (canvas_pos.y < jsGraphAnnotate[ctx.ChartNewId][i][2]) angle = -angle;
|
| - while (angle < 0) {
|
| - angle += 2 * Math.PI;
|
| - }
|
| - while (angle > 2 * Math.PI) {
|
| - angle -= 2 * Math.PI;
|
| - }
|
| - if (angle < config.startAngle * (Math.PI / 360)) angle += 2 * Math.PI;
|
| - if ((angle > jsGraphAnnotate[ctx.ChartNewId][i][5] && angle < jsGraphAnnotate[ctx.ChartNewId][i][6]) || (angle > jsGraphAnnotate[ctx.ChartNewId][i][5] - 2 * Math.PI && angle < jsGraphAnnotate[ctx.ChartNewId][i][6] - 2 * Math.PI) || (angle > jsGraphAnnotate[ctx.ChartNewId][i][5] + 2 * Math.PI && angle < jsGraphAnnotate[ctx.ChartNewId][i][6] + 2 * Math.PI)) {
|
| - v1 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][7], config.fmtV1); // V1=Label
|
| - v2 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][8], config.fmtV2); // V2=Data Value
|
| - v3 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][9], config.fmtV3); // V3=Cumulated Value
|
| - v4 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][10], config.fmtV4); // V4=Total Data Value
|
| - v5 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][11], config.fmtV5); // V5=Angle
|
| - v6 = fmtChartJS(config, 100 * jsGraphAnnotate[ctx.ChartNewId][i][8] / jsGraphAnnotate[ctx.ChartNewId][i][10], config.fmtV6); // v6=Percentage;
|
| - v6 = roundToWithThousands(config, v6, config.roundPct);
|
| - v7 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][1], config.fmtV7); // v7=midPointX of arc;
|
| - v8 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][2], config.fmtV8); // v8=midPointY of arc;
|
| - v9 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][3], config.fmtV9); // v9=radius Minimum;
|
| - v10 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][4], config.fmtV10); // v10=radius Maximum;
|
| - v11 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][5], config.fmtV11); // v11=start angle;
|
| - v12 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][6], config.fmtV12); // v12=stop angle;
|
| - v13 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][12], config.fmtV13); // v13=position in Data;
|
| - graphPosX = canvas_pos.x;
|
| - graphPosY = canvas_pos.y;
|
| - onData = true;
|
| - if (action == "annotate") {
|
| - dispString = tmplbis(config.annotateLabel, {
|
| - config: config,
|
| - v1: v1,
|
| - v2: v2,
|
| - v3: v3,
|
| - v4: v4,
|
| - v5: v5,
|
| - v6: v6,
|
| - v7: v7,
|
| - v8: v8,
|
| - v9: v9,
|
| - v10: v10,
|
| - v11: v11,
|
| - v12: v12,
|
| - v13: v13,
|
| - graphPosX: graphPosX,
|
| - graphPosY: graphPosY
|
| - });
|
| - annotateDIV.innerHTML = dispString;
|
| - show = true;
|
| - } else {
|
| - funct(event, ctx, config, data, {
|
| - v1: v1,
|
| - v2: v2,
|
| - v3: v3,
|
| - v4: v4,
|
| - v5: v5,
|
| - v6: v6,
|
| - v7: v7,
|
| - v8: v8,
|
| - v9: v9,
|
| - v10: v10,
|
| - v11: v11,
|
| - v12: v12,
|
| - v13: v13,
|
| - graphPosX: graphPosX,
|
| - graphPosY: graphPosY
|
| - });
|
| - }
|
| - if (action == "annotate") {
|
| - x = bw.ns4 || bw.ns5 ? event.pageX : event.x;
|
| - y = bw.ns4 || bw.ns5 ? event.pageY : event.y;
|
| - if (bw.ie4 || bw.ie5) y = y + eval(scrolled);
|
| - oCursor.moveIt(x + fromLeft, y + fromTop);
|
| - }
|
| - }
|
| - }
|
| - } else if (jsGraphAnnotate[ctx.ChartNewId][i][0] == "RECT") {
|
| - if (canvas_pos.x > jsGraphAnnotate[ctx.ChartNewId][i][1] && canvas_pos.x < jsGraphAnnotate[ctx.ChartNewId][i][3] && canvas_pos.y < jsGraphAnnotate[ctx.ChartNewId][i][2] && canvas_pos.y > jsGraphAnnotate[ctx.ChartNewId][i][4]) {
|
| - v1 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][5], config.fmtV1); // V1=Label1
|
| - v2 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][6], config.fmtV2); // V2=Label2
|
| - v3 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][7], config.fmtV3); // V3=Data Value
|
| - v4 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][8], config.fmtV4); // V4=Cumulated Value
|
| - v5 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][9], config.fmtV5); // V5=Total Data Value
|
| - v6 = fmtChartJS(config, 100 * jsGraphAnnotate[ctx.ChartNewId][i][7] / jsGraphAnnotate[ctx.ChartNewId][i][9], config.fmtV6); // v6=Percentage;
|
| - v6 = roundToWithThousands(config, v6, config.roundPct);
|
| - v7 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][1], config.fmtV7); // v7=top X of rectangle;
|
| - v8 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][2], config.fmtV8); // v8=top Y of rectangle;
|
| - v9 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][3], config.fmtV9); // v9=bottom X of rectangle;
|
| - v10 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][4], config.fmtV10); // v10=bottom Y of rectangle;
|
| - v11 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][10], config.fmtV11); // v11=position in Dataset;
|
| - v12 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][11], config.fmtV12); // v12=position in Dataset[v11].Data;
|
| - graphPosX = canvas_pos.x;
|
| - graphPosY = canvas_pos.y;
|
| - onData = true;
|
| - if (action == "annotate") {
|
| - dispString = tmplbis(config.annotateLabel, {
|
| - config: config,
|
| - v1: v1,
|
| - v2: v2,
|
| - v3: v3,
|
| - v4: v4,
|
| - v5: v5,
|
| - v6: v6,
|
| - v7: v7,
|
| - v8: v8,
|
| - v9: v9,
|
| - v10: v10,
|
| - v11: v11,
|
| - v12: v12,
|
| - graphPosX: graphPosX,
|
| - graphPosY: graphPosY,
|
| - data: data
|
| - });
|
| - annotateDIV.innerHTML = dispString;
|
| - show = true;
|
| - } else {
|
| - funct(event, ctx, config, data, {
|
| - v1: v1,
|
| - v2: v2,
|
| - v3: v3,
|
| - v4: v4,
|
| - v5: v5,
|
| - v6: v6,
|
| - v7: v7,
|
| - v8: v8,
|
| - v9: v9,
|
| - v10: v10,
|
| - v11: v11,
|
| - v12: v12,
|
| - graphPosX: graphPosX,
|
| - graphPosY: graphPosY
|
| - });
|
| - }
|
| - if (action == "annotate") {
|
| - x = bw.ns4 || bw.ns5 ? event.pageX : event.x;
|
| - y = bw.ns4 || bw.ns5 ? event.pageY : event.y;
|
| - if (bw.ie4 || bw.ie5) y = y + eval(scrolled);
|
| - oCursor.moveIt(x + fromLeft, y + fromTop);
|
| - }
|
| - }
|
| - } else if (jsGraphAnnotate[ctx.ChartNewId][i][0] == "POINT") {
|
| - distance = Math.sqrt((canvas_pos.x - jsGraphAnnotate[ctx.ChartNewId][i][1]) * (canvas_pos.x - jsGraphAnnotate[ctx.ChartNewId][i][1]) + (canvas_pos.y - jsGraphAnnotate[ctx.ChartNewId][i][2]) * (canvas_pos.y - jsGraphAnnotate[ctx.ChartNewId][i][2]));
|
| - if (distance < 10) {
|
| - v1 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][3], config.fmtV1); // V1=Label1
|
| - v2 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][4], config.fmtV2); // V2=Label2
|
| - v3 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][5], config.fmtV3); // V3=Data Value
|
| - v4 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][6], config.fmtV4); // V4=Difference with Previous line
|
| - v5 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][7], config.fmtV5); // V5=Difference with next line;
|
| - v6 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][8], config.fmtV6); // V6=max;
|
| - v7 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][9], config.fmtV7); // V7=Total;
|
| - v8 = fmtChartJS(config, 100 * jsGraphAnnotate[ctx.ChartNewId][i][5] / jsGraphAnnotate[ctx.ChartNewId][i][9], config.fmtV8); // v8=percentage;
|
| - v8 = roundToWithThousands(config, v8, config.roundPct);
|
| - v9 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][1], config.fmtV9); // v9=pos X of point;
|
| - v10 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][2], config.fmtV10); // v10=pos Y of point;
|
| - v11 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][10], config.fmtV11); // v11=position in Dataset;
|
| - v12 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][11], config.fmtV12); // v12=position in Dataset[v11].Data;
|
| - graphPosX = canvas_pos.x;
|
| - graphPosY = canvas_pos.y;
|
| - onData = true;
|
| - if (action == "annotate") {
|
| - dispString = tmplbis(config.annotateLabel, {
|
| - config: config,
|
| - v1: v1,
|
| - v2: v2,
|
| - v3: v3,
|
| - v4: v4,
|
| - v5: v5,
|
| - v6: v6,
|
| - v7: v7,
|
| - v8: v8,
|
| - v9: v9,
|
| - v10: v10,
|
| - v11: v11,
|
| - v12: v12,
|
| - graphPosX: graphPosX,
|
| - graphPosY: graphPosY,
|
| - data: data
|
| - });
|
| - annotateDIV.innerHTML = dispString;
|
| - show = true;
|
| - } else {
|
| - funct(event, ctx, config, data, {
|
| - v1: v1,
|
| - v2: v2,
|
| - v3: v3,
|
| - v4: v4,
|
| - v5: v5,
|
| - v6: v6,
|
| - v7: v7,
|
| - v8: v8,
|
| - v9: v9,
|
| - v10: v10,
|
| - v11: v11,
|
| - v12: v12,
|
| - graphPosX: graphPosX,
|
| - graphPosY: graphPosY
|
| - });
|
| - }
|
| - if (action == "annotate") {
|
| - x = bw.ns4 || bw.ns5 ? event.pageX : event.x;
|
| - y = bw.ns4 || bw.ns5 ? event.pageY : event.y;
|
| - if (bw.ie4 || bw.ie5) y = y + eval(scrolled);
|
| - oCursor.moveIt(x + fromLeft, y + fromTop);
|
| - }
|
| - }
|
| - }
|
| - if (action == "annotate") {
|
| - annotateDIV.style.display = show ? '' : 'none';
|
| - }
|
| - }
|
| - if (onData == false && action != "annotate") {
|
| - funct(event, ctx, config, data, null);
|
| - }
|
| -};
|
| -///////// GRAPHICAL PART OF THE SCRIPT ///////////////////////////////////////////
|
| -//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 = {
|
| - inGraphDataShow: false,
|
| - inGraphDataPaddingRadius: 5,
|
| - inGraphDataPaddingAngle: 0,
|
| - inGraphDataTmpl: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>",
|
| - inGraphDataAlign: "off-center", // "right", "center", "left", "off-center" or "to-center"
|
| - inGraphDataVAlign: "off-center", // "bottom", "center", "top", "off-center" or "to-center"
|
| - inGraphDataRotate: 0, // rotateAngle value (0->360) , "inRadiusAxis" or "inRadiusAxisRotateLabels"
|
| - inGraphDataFontFamily: "'Arial'",
|
| - inGraphDataFontSize: 12,
|
| - inGraphDataFontStyle: "normal",
|
| - inGraphDataFontColor: "#666",
|
| - inGraphDataRadiusPosition: 3,
|
| - inGraphDataAnglePosition: 2,
|
| - scaleOverlay: true,
|
| - scaleOverride: false,
|
| - scaleOverride2: false,
|
| - scaleSteps: null,
|
| - scaleStepWidth: null,
|
| - scaleStartValue: null,
|
| - scaleShowLine: true,
|
| - scaleLineColor: "rgba(0,0,0,.1)",
|
| - scaleLineWidth: 1,
|
| - scaleShowLabels: true,
|
| - scaleShowLabels2: 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,
|
| - annotateLabel: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>",
|
| - startAngle: 90
|
| - };
|
| - chart.PolarArea.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.PolarArea.defaults);
|
| - chart.PolarArea.defaults = mergeChartConfig(chart.PolarArea.defaults, charJSPersonalDefaultOptions);
|
| - chart.PolarArea.defaults = mergeChartConfig(chart.PolarArea.defaults, charJSPersonalDefaultOptionsPolarArea);
|
| - 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 = {
|
| - inGraphDataShow: false,
|
| - inGraphDataPaddingRadius: 5,
|
| - inGraphDataTmpl: "<%=v3%>",
|
| - inGraphDataAlign: "off-center", // "right", "center", "left", "off-center" or "to-center"
|
| - inGraphDataVAlign: "off-center", // "right", "center", "left", "off-center" or "to-center"
|
| - inGraphDataRotate: 0, // rotateAngle value (0->360) , "inRadiusAxis" or "inRadiusAxisRotateLabels"
|
| - inGraphDataFontFamily: "'Arial'",
|
| - inGraphDataFontSize: 12,
|
| - inGraphDataFontStyle: "normal",
|
| - inGraphDataFontColor: "#666",
|
| - inGraphDataRadiusPosition: 3,
|
| - yAxisMinimumInterval: "none",
|
| - scaleOverlay: false,
|
| - scaleOverride: false,
|
| - scaleOverride2: false,
|
| - scaleSteps: null,
|
| - scaleStepWidth: null,
|
| - scaleStartValue: null,
|
| - scaleShowLine: true,
|
| - scaleLineColor: "rgba(0,0,0,.1)",
|
| - scaleLineWidth: 1,
|
| - scaleShowLabels: false,
|
| - scaleShowLabels2: true,
|
| - 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,
|
| - datasetFill: true,
|
| - datasetStrokeWidth: 2,
|
| - animation: true,
|
| - animationSteps: 60,
|
| - animationEasing: "easeOutQuart",
|
| - onAnimationComplete: null,
|
| - annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3%>",
|
| - startAngle: 90,
|
| - graphMaximized: false // if true, the graph will not be centered in the middle of the canvas
|
| - };
|
| - // merge annotate defaults
|
| - chart.Radar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Radar.defaults);
|
| - chart.Radar.defaults = mergeChartConfig(chart.Radar.defaults, charJSPersonalDefaultOptions);
|
| - chart.Radar.defaults = mergeChartConfig(chart.Radar.defaults, charJSPersonalDefaultOptionsRadar);
|
| - 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 = {
|
| - inGraphDataShow: false,
|
| - inGraphDataPaddingRadius: 5,
|
| - inGraphDataPaddingAngle: 0,
|
| - inGraphDataTmpl: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>",
|
| - inGraphDataAlign: "off-center", // "right", "center", "left", "off-center" or "to-center"
|
| - inGraphDataVAlign: "off-center", // "bottom", "center", "top", "off-center" or "to-center"
|
| - inGraphDataRotate: 0, // rotateAngle value (0->360) , "inRadiusAxis" or "inRadiusAxisRotateLabels"
|
| - inGraphDataFontFamily: "'Arial'",
|
| - inGraphDataFontSize: 12,
|
| - inGraphDataFontStyle: "normal",
|
| - inGraphDataFontColor: "#666",
|
| - inGraphDataRadiusPosition: 3,
|
| - inGraphDataAnglePosition: 2,
|
| - inGraphDataMinimumAngle : 0,
|
| - segmentShowStroke: true,
|
| - segmentStrokeColor: "#fff",
|
| - segmentStrokeWidth: 2,
|
| - animation: true,
|
| - animationSteps: 100,
|
| - animationEasing: "easeOutBounce",
|
| - animateRotate: true,
|
| - animateScale: false,
|
| - onAnimationComplete: null,
|
| - annotateLabel: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>",
|
| - startAngle: 90,
|
| - radiusScale: 1
|
| - };
|
| - // merge annotate defaults
|
| - chart.Pie.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Pie.defaults);
|
| - chart.Pie.defaults = mergeChartConfig(chart.Pie.defaults, charJSPersonalDefaultOptions);
|
| - chart.Pie.defaults = mergeChartConfig(chart.Pie.defaults, charJSPersonalDefaultOptionsPie);
|
| - 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 = {
|
| - inGraphDataShow: false,
|
| - inGraphDataPaddingRadius: 5,
|
| - inGraphDataPaddingAngle: 0,
|
| - inGraphDataTmpl: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>",
|
| - inGraphDataAlign: "off-center", // "right", "center", "left", "off-center" or "to-center"
|
| - inGraphDataVAlign: "off-center", // "bottom", "middle", "top", "off-center" or "to-center"
|
| - inGraphDataRotate: 0, // rotateAngle value (0->360) , "inRadiusAxis" or "inRadiusAxisRotateLabels"
|
| - inGraphDataFontFamily: "'Arial'",
|
| - inGraphDataFontSize: 12,
|
| - inGraphDataFontStyle: "normal",
|
| - inGraphDataFontColor: "#666",
|
| - inGraphDataRadiusPosition: 3,
|
| - inGraphDataAnglePosition: 2,
|
| - inGraphDataMinimumAngle : 0,
|
| - segmentShowStroke: true,
|
| - segmentStrokeColor: "#fff",
|
| - segmentStrokeWidth: 2,
|
| - percentageInnerCutout: 50,
|
| - animation: true,
|
| - animationSteps: 100,
|
| - animationEasing: "easeOutBounce",
|
| - animateRotate: true,
|
| - animateScale: false,
|
| - onAnimationComplete: null,
|
| - annotateLabel: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>",
|
| - startAngle: 90,
|
| - radiusScale: 1
|
| - };
|
| - // merge annotate defaults
|
| - chart.Doughnut.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Doughnut.defaults);
|
| - chart.Doughnut.defaults = mergeChartConfig(chart.Doughnut.defaults, charJSPersonalDefaultOptions);
|
| - chart.Doughnut.defaults = mergeChartConfig(chart.Doughnut.defaults, charJSPersonalDefaultOptionsDoughnut);
|
| - 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 = {
|
| - inGraphDataShow: false,
|
| - inGraphDataPaddingX: 3,
|
| - inGraphDataPaddingY: 3,
|
| - inGraphDataTmpl: "<%=v3%>",
|
| - inGraphDataAlign: "left",
|
| - inGraphDataVAlign: "bottom",
|
| - inGraphDataRotate: 0,
|
| - inGraphDataFontFamily: "'Arial'",
|
| - inGraphDataFontSize: 12,
|
| - inGraphDataFontStyle: "normal",
|
| - inGraphDataFontColor: "#666",
|
| - drawXScaleLine: [{
|
| - position: "bottom"
|
| - }],
|
| - scaleOverlay: false,
|
| - scaleOverride: false,
|
| - scaleOverride2: false,
|
| - scaleSteps: null,
|
| - scaleStepWidth: null,
|
| - scaleStartValue: null,
|
| - scaleSteps2: null,
|
| - scaleStepWidth2: null,
|
| - scaleStartValue2: null,
|
| - scaleLabel2 : "<%=value%>",
|
| - scaleLineColor: "rgba(0,0,0,.1)",
|
| - scaleLineWidth: 1,
|
| - scaleShowLabels: true,
|
| - scaleShowLabels2: true,
|
| - scaleLabel: "<%=value%>",
|
| - scaleFontFamily: "'Arial'",
|
| - scaleFontSize: 12,
|
| - scaleFontStyle: "normal",
|
| - scaleFontColor: "#666",
|
| - scaleShowGridLines: true,
|
| - scaleXGridLinesStep: 1,
|
| - scaleYGridLinesStep: 1,
|
| - scaleGridLineColor: "rgba(0,0,0,.05)",
|
| - scaleGridLineWidth: 1,
|
| - showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels)
|
| - rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre;
|
| - // you can force an integer value between 0 and 180 degres
|
| - logarithmic: false, // can be 'fuzzy',true and false ('fuzzy' => if the gap between min and maximum is big it's using a logarithmic y-Axis scale
|
| - logarithmic2: false, // can be 'fuzzy',true and false ('fuzzy' => if the gap between min and maximum is big it's using a logarithmic y-Axis scale
|
| - scaleTickSizeLeft: 5,
|
| - scaleTickSizeRight: 5,
|
| - scaleTickSizeBottom: 5,
|
| - scaleTickSizeTop: 5,
|
| - bezierCurve: true,
|
| - pointDot: true,
|
| - pointDotRadius: 4,
|
| - pointDotStrokeWidth: 2,
|
| - datasetStrokeWidth: 2,
|
| - datasetFill: true,
|
| - animation: true,
|
| - animationSteps: 60,
|
| - animationEasing: "easeOutQuart",
|
| - extrapolateMissingData: true,
|
| - onAnimationComplete: null,
|
| - annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3%>"
|
| - };
|
| - // merge annotate defaults
|
| - chart.Line.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Line.defaults);
|
| - chart.Line.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.Line.defaults);
|
| - chart.Line.defaults = mergeChartConfig(chart.Line.defaults, charJSPersonalDefaultOptions);
|
| - chart.Line.defaults = mergeChartConfig(chart.Line.defaults, charJSPersonalDefaultOptionsLine);
|
| - var config = (options) ? mergeChartConfig(chart.Line.defaults, options) : chart.Line.defaults;
|
| - return new Line(data, config, context);
|
| - };
|
| - this.StackedBar = function(data, options) {
|
| - chart.StackedBar.defaults = {
|
| - inGraphDataShow: false,
|
| - inGraphDataPaddingX: 0,
|
| - inGraphDataPaddingY: -3,
|
| - inGraphDataTmpl: "<%=v3%>",
|
| - inGraphDataAlign: "center",
|
| - inGraphDataVAlign: "top",
|
| - inGraphDataRotate: 0,
|
| - inGraphDataFontFamily: "'Arial'",
|
| - inGraphDataFontSize: 12,
|
| - inGraphDataFontStyle: "normal",
|
| - inGraphDataFontColor: "#666",
|
| - inGraphDataXPosition: 2,
|
| - inGraphDataYPosition: 3,
|
| - scaleOverlay: false,
|
| - scaleOverride: false,
|
| - scaleOverride2: false,
|
| - scaleSteps: null,
|
| - scaleStepWidth: null,
|
| - scaleStartValue: null,
|
| - scaleLineColor: "rgba(0,0,0,.1)",
|
| - scaleLineWidth: 1,
|
| - scaleShowLabels: true,
|
| - scaleShowLabels2: true,
|
| - scaleLabel: "<%=value%>",
|
| - scaleFontFamily: "'Arial'",
|
| - scaleFontSize: 12,
|
| - scaleFontStyle: "normal",
|
| - scaleFontColor: "#666",
|
| - scaleShowGridLines: true,
|
| - scaleXGridLinesStep: 1,
|
| - scaleYGridLinesStep: 1,
|
| - scaleGridLineColor: "rgba(0,0,0,.05)",
|
| - scaleGridLineWidth: 1,
|
| - showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels)
|
| - rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre;
|
| - // you can force an integer value between 0 and 180 degres
|
| - scaleTickSizeLeft: 5,
|
| - scaleTickSizeRight: 5,
|
| - scaleTickSizeBottom: 5,
|
| - scaleTickSizeTop: 5,
|
| - barShowStroke: true,
|
| - barStrokeWidth: 2,
|
| - barValueSpacing: 5,
|
| - barDatasetSpacing: 1,
|
| - animation: true,
|
| - animationSteps: 60,
|
| - animationEasing: "easeOutQuart",
|
| - onAnimationComplete: null,
|
| - annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3 + ' (' + v6 + ' %)'%>"
|
| - };
|
| - // merge annotate defaults
|
| - chart.StackedBar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.StackedBar.defaults);
|
| - chart.StackedBar.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.StackedBar.defaults);
|
| - chart.StackedBar.defaults = mergeChartConfig(chart.StackedBar.defaults, charJSPersonalDefaultOptions);
|
| - chart.StackedBar.defaults = mergeChartConfig(chart.StackedBar.defaults, charJSPersonalDefaultOptionsStackedBar);
|
| - var config = (options) ? mergeChartConfig(chart.StackedBar.defaults, options) : chart.StackedBar.defaults;
|
| - return new StackedBar(data, config, context);
|
| - };
|
| - this.HorizontalStackedBar = function(data, options) {
|
| - chart.HorizontalStackedBar.defaults = {
|
| - inGraphDataShow: false,
|
| - inGraphDataPaddingX: -3,
|
| - inGraphDataPaddingY: 0,
|
| - inGraphDataTmpl: "<%=v3%>",
|
| - inGraphDataAlign: "right",
|
| - inGraphDataVAlign: "middle",
|
| - inGraphDataRotate: 0,
|
| - inGraphDataFontFamily: "'Arial'",
|
| - inGraphDataFontSize: 12,
|
| - inGraphDataFontStyle: "normal",
|
| - inGraphDataFontColor: "#666",
|
| - inGraphDataXPosition: 3,
|
| - inGraphDataYPosition: 2,
|
| - scaleOverlay: false,
|
| - scaleOverride: false,
|
| - scaleOverride2: false,
|
| - scaleSteps: null,
|
| - scaleStepWidth: null,
|
| - scaleStartValue: null,
|
| - scaleLineColor: "rgba(0,0,0,.1)",
|
| - scaleLineWidth: 1,
|
| - scaleShowLabels: true,
|
| - scaleShowLabels2: true,
|
| - scaleLabel: "<%=value%>",
|
| - scaleFontFamily: "'Arial'",
|
| - scaleFontSize: 12,
|
| - scaleFontStyle: "normal",
|
| - scaleFontColor: "#666",
|
| - scaleShowGridLines: true,
|
| - scaleXGridLinesStep: 1,
|
| - scaleYGridLinesStep: 1,
|
| - scaleGridLineColor: "rgba(0,0,0,.05)",
|
| - scaleGridLineWidth: 1,
|
| - scaleTickSizeLeft: 5,
|
| - scaleTickSizeRight: 5,
|
| - scaleTickSizeBottom: 5,
|
| - scaleTickSizeTop: 5,
|
| - showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels)
|
| - rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre;
|
| - barShowStroke: true,
|
| - barStrokeWidth: 2,
|
| - barValueSpacing: 5,
|
| - barDatasetSpacing: 1,
|
| - animation: true,
|
| - animationSteps: 60,
|
| - animationEasing: "easeOutQuart",
|
| - onAnimationComplete: null,
|
| - annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3 + ' (' + v6 + ' %)'%>",
|
| - reverseOrder: false
|
| - };
|
| - // merge annotate defaults
|
| - chart.HorizontalStackedBar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.HorizontalStackedBar.defaults);
|
| - chart.HorizontalStackedBar.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.HorizontalStackedBar.defaults);
|
| - chart.HorizontalStackedBar.defaults = mergeChartConfig(chart.HorizontalStackedBar.defaults, charJSPersonalDefaultOptions);
|
| - chart.HorizontalStackedBar.defaults = mergeChartConfig(chart.HorizontalStackedBar.defaults, charJSPersonalDefaultOptionsHorizontalStackedBar);
|
| - var config = (options) ? mergeChartConfig(chart.HorizontalStackedBar.defaults, options) : chart.HorizontalStackedBar.defaults;
|
| - return new HorizontalStackedBar(data, config, context);
|
| - };
|
| - this.Bar = function(data, options) {
|
| - chart.Bar.defaults = {
|
| - inGraphDataShow: false,
|
| - inGraphDataPaddingX: 0,
|
| - inGraphDataPaddingY: 3,
|
| - inGraphDataTmpl: "<%=v3%>",
|
| - inGraphDataAlign: "center",
|
| - inGraphDataVAlign: "bottom",
|
| - inGraphDataRotate: 0,
|
| - inGraphDataFontFamily: "'Arial'",
|
| - inGraphDataFontSize: 12,
|
| - inGraphDataFontStyle: "normal",
|
| - inGraphDataFontColor: "#666",
|
| - inGraphDataXPosition: 2,
|
| - inGraphDataYPosition: 3,
|
| - scaleOverlay: false,
|
| - scaleOverride: false,
|
| - scaleOverride2: false,
|
| - scaleSteps: null,
|
| - scaleStepWidth: null,
|
| - scaleStartValue: null,
|
| - scaleLineColor: "rgba(0,0,0,.1)",
|
| - scaleLineWidth: 1,
|
| - scaleShowLabels: true,
|
| - scaleShowLabels2: true,
|
| - scaleLabel: "<%=value%>",
|
| - scaleFontFamily: "'Arial'",
|
| - scaleFontSize: 12,
|
| - scaleFontStyle: "normal",
|
| - scaleFontColor: "#666",
|
| - scaleShowGridLines: true,
|
| - scaleXGridLinesStep: 1,
|
| - scaleYGridLinesStep: 1,
|
| - scaleGridLineColor: "rgba(0,0,0,.05)",
|
| - scaleGridLineWidth: 1,
|
| - showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels)
|
| - rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre;
|
| - // you can force an integer value between 0 and 180 degres
|
| - logarithmic: false, // can be 'fuzzy',true and false ('fuzzy' => if the gap between min and maximum is big it's using a logarithmic y-Axis scale
|
| - logarithmic2: false, // can be 'fuzzy',true and false ('fuzzy' => if the gap between min and maximum is big it's using a logarithmic y-Axis scale
|
| - scaleTickSizeLeft: 5,
|
| - scaleTickSizeRight: 5,
|
| - scaleTickSizeBottom: 5,
|
| - scaleTickSizeTop: 5,
|
| - barShowStroke: true,
|
| - barStrokeWidth: 2,
|
| - barValueSpacing: 5,
|
| - barDatasetSpacing: 1,
|
| - barBorderRadius: 0,
|
| - animation: true,
|
| - animationSteps: 60,
|
| - animationEasing: "easeOutQuart",
|
| - onAnimationComplete: null,
|
| - annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3 + ' (' + v6 + ' %)'%>"
|
| - };
|
| - // merge annotate defaults
|
| - chart.Bar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Bar.defaults);
|
| - chart.Bar.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.Bar.defaults);
|
| - chart.Bar.defaults = mergeChartConfig(chart.Bar.defaults, charJSPersonalDefaultOptions);
|
| - chart.Bar.defaults = mergeChartConfig(chart.Bar.defaults, charJSPersonalDefaultOptionsBar);
|
| - var config = (options) ? mergeChartConfig(chart.Bar.defaults, options) : chart.Bar.defaults;
|
| - return new Bar(data, config, context);
|
| - };
|
| - this.HorizontalBar = function(data, options) {
|
| - chart.HorizontalBar.defaults = {
|
| - inGraphDataShow: false,
|
| - inGraphDataPaddingX: 3,
|
| - inGraphDataPaddingY: 0,
|
| - inGraphDataTmpl: "<%=v3%>",
|
| - inGraphDataAlign: "left",
|
| - inGraphDataVAlign: "middle",
|
| - inGraphDataRotate: 0,
|
| - inGraphDataFontFamily: "'Arial'",
|
| - inGraphDataFontSize: 12,
|
| - inGraphDataFontStyle: "normal",
|
| - inGraphDataFontColor: "#666",
|
| - inGraphDataXPosition: 3,
|
| - inGraphDataYPosition: 2,
|
| - scaleOverlay: false,
|
| - scaleOverride: false,
|
| - scaleOverride2: false,
|
| - scaleSteps: null,
|
| - scaleStepWidth: null,
|
| - scaleStartValue: null,
|
| - scaleLineColor: "rgba(0,0,0,.1)",
|
| - scaleLineWidth: 1,
|
| - scaleShowLabels: true,
|
| - scaleShowLabels2: true,
|
| - scaleLabel: "<%=value%>",
|
| - scaleFontFamily: "'Arial'",
|
| - scaleFontSize: 12,
|
| - scaleFontStyle: "normal",
|
| - scaleFontColor: "#666",
|
| - scaleShowGridLines: true,
|
| - scaleXGridLinesStep: 1,
|
| - scaleYGridLinesStep: 1,
|
| - scaleGridLineColor: "rgba(0,0,0,.05)",
|
| - scaleGridLineWidth: 1,
|
| - scaleTickSizeLeft: 5,
|
| - scaleTickSizeRight: 5,
|
| - scaleTickSizeBottom: 5,
|
| - scaleTickSizeTop: 5,
|
| - showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels)
|
| - rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre;
|
| - barShowStroke: true,
|
| - barStrokeWidth: 2,
|
| - barValueSpacing: 5,
|
| - barDatasetSpacing: 1,
|
| - barBorderRadius: 0,
|
| - animation: true,
|
| - animationSteps: 60,
|
| - animationEasing: "easeOutQuart",
|
| - onAnimationComplete: null,
|
| - annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3 + ' (' + v6 + ' %)'%>",
|
| - reverseOrder: false
|
| - };
|
| - // merge annotate defaults
|
| - chart.HorizontalBar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.HorizontalBar.defaults);
|
| - chart.HorizontalBar.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.HorizontalBar.defaults);
|
| - chart.HorizontalBar.defaults = mergeChartConfig(chart.HorizontalBar.defaults, charJSPersonalDefaultOptions);
|
| - chart.HorizontalBar.defaults = mergeChartConfig(chart.HorizontalBar.defaults, charJSPersonalDefaultOptionsHorizontalBar);
|
| - var config = (options) ? mergeChartConfig(chart.HorizontalBar.defaults, options) : chart.HorizontalBar.defaults;
|
| - return new HorizontalBar(data, config, context);
|
| - };
|
| - chart.defaults = {};
|
| - chart.defaults.commonOptions = {
|
| - multiGraph: false,
|
| - clearRect: true, // do not change clearRect options; for internal use only
|
| - dynamicDisplay: false,
|
| - graphSpaceBefore: 5,
|
| - graphSpaceAfter: 5,
|
| - canvasBorders: false,
|
| - canvasBackgroundColor: "none",
|
| - canvasBordersWidth: 3,
|
| - canvasBordersColor: "black",
|
| - graphTitle: "",
|
| - graphTitleFontFamily: "'Arial'",
|
| - graphTitleFontSize: 24,
|
| - graphTitleFontStyle: "bold",
|
| - graphTitleFontColor: "#666",
|
| - graphTitleSpaceBefore: 5,
|
| - graphTitleSpaceAfter: 5,
|
| - graphSubTitle: "",
|
| - graphSubTitleFontFamily: "'Arial'",
|
| - graphSubTitleFontSize: 18,
|
| - graphSubTitleFontStyle: "normal",
|
| - graphSubTitleFontColor: "#666",
|
| - graphSubTitleSpaceBefore: 5,
|
| - graphSubTitleSpaceAfter: 5,
|
| - footNote: "",
|
| - footNoteFontFamily: "'Arial'",
|
| - footNoteFontSize: 8,
|
| - footNoteFontStyle: "bold",
|
| - footNoteFontColor: "#666",
|
| - footNoteSpaceBefore: 5,
|
| - footNoteSpaceAfter: 5,
|
| - legend : false,
|
| - showSingleLegend: false,
|
| - maxLegendCols : 999,
|
| - legendPosY :4,
|
| - legendPosX : -2,
|
| - legendFontFamily: "'Arial'",
|
| - legendFontSize: 12,
|
| - legendFontStyle: "normal",
|
| - legendFontColor: "#666",
|
| - legendBlockSize: 15,
|
| - legendBorders: true,
|
| - legendBordersWidth: 1,
|
| - legendBordersColors: "#666",
|
| - legendBordersSpaceBefore: 5,
|
| - legendBordersSpaceAfter: 5,
|
| - legendBordersSpaceLeft: 5,
|
| - legendBordersSpaceRight: 5,
|
| - legendSpaceBeforeText: 5,
|
| - legendSpaceAfterText: 5,
|
| - legendSpaceLeftText: 5,
|
| - legendSpaceRightText: 5,
|
| - legendSpaceBetweenTextVertical: 5,
|
| - legendSpaceBetweenTextHorizontal: 5,
|
| - legendSpaceBetweenBoxAndText: 5,
|
| - legendFillColor : "rgba(0,0,0,0)",
|
| - legendXPadding : 0,
|
| - legendYPadding : 0,
|
| - annotateDisplay: false,
|
| - savePng: false,
|
| - savePngOutput: "NewWindow", // Allowed values : "NewWindow", "CurrentWindow", "Save"
|
| - savePngFunction: "mousedown right",
|
| - savePngBackgroundColor: 'WHITE',
|
| - annotateFunction: "mousemove",
|
| - annotateFontFamily: "'Arial'",
|
| - annotateBorder: 'none',
|
| - annotateBorderRadius: '2px',
|
| - annotateBackgroundColor: 'rgba(0,0,0,0.8)',
|
| - annotateFontSize: 12,
|
| - annotateFontColor: 'white',
|
| - annotateFontStyle: "normal",
|
| - annotatePadding: "3px",
|
| - annotateClassName: "",
|
| - crossText: [""],
|
| - crossTextIter: ["all"],
|
| - crossTextOverlay: [true],
|
| - crossTextFontFamily: ["'Arial'"],
|
| - crossTextFontSize: [12],
|
| - crossTextFontStyle: ["normal"],
|
| - crossTextFontColor: ["rgba(220,220,220,1)"],
|
| - crossTextRelativePosX: [2],
|
| - crossTextRelativePosY: [2],
|
| - crossTextBaseline: ["middle"],
|
| - crossTextAlign: ["center"],
|
| - crossTextPosX: [0],
|
| - crossTextPosY: [0],
|
| - crossTextAngle: [0],
|
| - crossTextFunction: null,
|
| - crossImage: [undefined],
|
| - crossImageIter: ["all"],
|
| - crossImageOverlay: [true],
|
| - crossImageRelativePosX: [2],
|
| - crossImageRelativePosY: [2],
|
| - crossImageBaseline: ["middle"],
|
| - crossImageAlign: ["center"],
|
| - crossImagePosX: [0],
|
| - crossImagePosY: [0],
|
| - crossImageAngle: [0],
|
| - spaceTop: 0,
|
| - spaceBottom: 0,
|
| - spaceRight: 0,
|
| - spaceLeft: 0,
|
| - decimalSeparator: ".",
|
| - thousandSeparator: "",
|
| - roundNumber: "none",
|
| - roundPct: -1,
|
| - fmtV1: "none",
|
| - fmtV2: "none",
|
| - fmtV3: "none",
|
| - fmtV4: "none",
|
| - fmtV5: "none",
|
| - fmtV6: "none",
|
| - fmtV7: "none",
|
| - fmtV8: "none",
|
| - fmtV9: "none",
|
| - fmtV10: "none",
|
| - fmtV11: "none",
|
| - fmtV12: "none",
|
| - fmtV13: "none",
|
| - fmtXLabel: "none",
|
| - fmtYLabel: "none",
|
| - fmtYLabel2: "none",
|
| - fmtLegend: "none",
|
| - animationStartValue: 0,
|
| - animationStopValue: 1,
|
| - animationCount: 1,
|
| - animationPauseTime: 5,
|
| - animationBackward: false,
|
| - animationStartWithDataset: 1,
|
| - animationStartWithData: 1,
|
| - animationLeftToRight: false,
|
| - animationByDataset: false,
|
| - defaultStrokeColor: "rgba(220,220,220,1)",
|
| - defaultFillColor: "rgba(220,220,220,0.5)",
|
| - mouseDownRight: null,
|
| - mouseDownLeft: null,
|
| - mouseDownMiddle: null,
|
| - mouseMove: null,
|
| - mouseOut: null,
|
| - mouseWheel : null,
|
| - savePngName: "canvas",
|
| - responsive : false,
|
| - maintainAspectRatio: true
|
| - };
|
| - chart.defaults.xyAxisCommonOptions = {
|
| - yAxisMinimumInterval: "none",
|
| - yAxisMinimumInterval2: "none",
|
| - yScaleLabelsMinimumWidth: 0,
|
| - xScaleLabelsMinimumWidth: 0,
|
| - yAxisLeft: true,
|
| - yAxisRight: false,
|
| - xAxisBottom: true,
|
| - xAxisTop: false,
|
| - xAxisSpaceBetweenLabels: 5,
|
| - fullWidthGraph: false,
|
| - yAxisLabel: "",
|
| - yAxisLabel2: "",
|
| - yAxisFontFamily: "'Arial'",
|
| - yAxisFontSize: 16,
|
| - yAxisFontStyle: "normal",
|
| - yAxisFontColor: "#666",
|
| - yAxisLabelSpaceRight: 5,
|
| - yAxisLabelSpaceLeft: 5,
|
| - yAxisSpaceRight: 5,
|
| - yAxisSpaceLeft: 5,
|
| - xAxisLabel: "",
|
| - xAxisFontFamily: "'Arial'",
|
| - xAxisFontSize: 16,
|
| - xAxisFontStyle: "normal",
|
| - xAxisFontColor: "#666",
|
| - xAxisLabelSpaceBefore: 5,
|
| - xAxisLabelSpaceAfter: 5,
|
| - xAxisSpaceBefore: 5,
|
| - xAxisSpaceAfter: 5,
|
| - yAxisUnit: "",
|
| - yAxisUnit2: "",
|
| - yAxisUnitFontFamily: "'Arial'",
|
| - yAxisUnitFontSize: 8,
|
| - yAxisUnitFontStyle: "normal",
|
| - yAxisUnitFontColor: "#666",
|
| - yAxisUnitSpaceBefore: 5,
|
| - yAxisUnitSpaceAfter: 5
|
| - };
|
| - var clear = function(c) {
|
| - c.clearRect(0, 0, width, height);
|
| - };
|
| -
|
| - function setting_new_chart_vars(ctx) {
|
| -
|
| - if (typeof ctx.ChartNewId === typeof undefined) {
|
| - ctx.runanimationcompletefunction=true;
|
| - var cvdate = new Date();
|
| - var cvmillsec = cvdate.getTime();
|
| - ctx.ChartNewId = ctx.tpchart + '_' + cvmillsec;
|
| - ctx._eventListeners = {};
|
| - }
|
| - }
|
| -
|
| - var PolarArea = function(data, config, ctx) {
|
| - var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, msr, midPosX, midPosY;
|
| -
|
| - ctx.tpchart="PolarArea";
|
| - setting_new_chart_vars(ctx);
|
| - if (!dynamicFunction(data, config, ctx)) {
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } }
|
| - return;
|
| - }
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") {
|
| - if(!config.multiGraph) {
|
| - addResponsiveChart(ctx.ChartNewId,ctx,data,config);
|
| - subUpdateChart(ctx,data,config);
|
| - return;
|
| - } else { ctx.firstPass=1; }
|
| - }
|
| -
|
| - var realStartAngle = config.startAngle * (Math.PI / 180) + 2 * Math.PI;
|
| - while (config.startAngle < 0) {
|
| - config.startAngle += 360;
|
| - }
|
| - while (config.startAngle > 360) {
|
| - config.startAngle -= 360;
|
| - }
|
| - while (realStartAngle < 0) {
|
| - realStartAngle += 2 * Math.PI;
|
| - }
|
| - while (realStartAngle > 2 * Math.PI) {
|
| - realStartAngle -= 2 * Math.PI;
|
| - }
|
| - config.logarithmic = false;
|
| - config.logarithmic2 = false;
|
| - if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array();
|
| - else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId);
|
| - defMouse(ctx, data, config);
|
| - setRect(ctx, config);
|
| - valueBounds = getValueBounds();
|
| - //Check and set the scale
|
| - labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : "";
|
| - if (!config.scaleOverride) {
|
| - calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString);
|
| - msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, false, false, true, "PolarArea");
|
| - } else {
|
| - calculatedScale = {
|
| - steps: config.scaleSteps,
|
| - stepValue: config.scaleStepWidth,
|
| - graphMin: config.scaleStartValue,
|
| - graphMax: config.scaleStartValue + config.scaleSteps * config.scaleStepWidth,
|
| - labels: []
|
| - }
|
| - populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, config.scaleStartValue, calculatedScale.graphMax, config.scaleStepWidth);
|
| - msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, false, false, true, "PolarArea");
|
| - }
|
| - midPosX = msr.leftNotUsableSize + (msr.availableWidth / 2);
|
| - midPosY = msr.topNotUsableSize + (msr.availableHeight / 2);
|
| - scaleHop = Math.floor(((Min([msr.availableHeight, msr.availableWidth]) / 2) - 5) / calculatedScale.steps);
|
| - //Wrap in an animation loop wrapper
|
| - if(scaleHop > 0) {
|
| - animationLoop(config, drawScale, drawAllSegments, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, midPosX, midPosY, midPosX - ((Min([msr.availableHeight, msr.availableWidth]) / 2) - 5), midPosY + ((Min([msr.availableHeight, msr.availableWidth]) / 2) - 5), data);
|
| - } else {
|
| - testRedraw(ctx,data,config);
|
| - }
|
| -
|
| - function drawAllSegments(animationDecimal) {
|
| - var startAngle = -config.startAngle * (Math.PI / 180) + 2 * Math.PI,
|
| - cumvalue = 0,
|
| - angleStep = 0,
|
| - scaleAnimation = 1,
|
| - rotateAnimation = 1;
|
| - angleStep = 0;
|
| - for (var i = 0; i < data.length; i++)
|
| - if (!(typeof(data[i].value) == 'undefined')) angleStep++;
|
| - angleStep = (Math.PI * 2) / angleStep;
|
| - while (startAngle < 0) {
|
| - startAngle += 2 * Math.PI;
|
| - }
|
| - while (startAngle > 2 * Math.PI) {
|
| - startAngle -= 2 * Math.PI;
|
| - }
|
| - if (config.animation) {
|
| - if (config.animateScale) {
|
| - scaleAnimation = animationDecimal;
|
| - }
|
| - if (config.animateRotate) {
|
| - rotateAnimation = animationDecimal;
|
| - }
|
| - }
|
| - if (animationDecimal >= 1) {
|
| - totvalue = 0;
|
| - for (var i = 0; i < data.length; i++)
|
| - if (!(typeof(data[i].value) == 'undefined')) totvalue += 1 * data[i].value;
|
| - }
|
| - for (var i = 0; i < data.length; i++) {
|
| - correctedRotateAnimation = animationCorrection(rotateAnimation, data, config, i, -1, 0).mainVal;
|
| - if (!(typeof(data[i].value) == 'undefined')) {
|
| - ctx.beginPath();
|
| - ctx.arc(midPosX, midPosY, scaleAnimation * calculateOffset(config.logarithmic, 1 * data[i].value, calculatedScale, scaleHop), startAngle, startAngle + correctedRotateAnimation * angleStep, false);
|
| - ctx.lineTo(midPosX, midPosY);
|
| - ctx.closePath();
|
| - if (typeof data[i].color == "function") ctx.fillStyle = data[i].color("COLOR", data, config, i, -1, animationDecimal, data[i].value, "PolarArea", ctx, midPosX, midPosY, 0, scaleAnimation * calculateOffset(config.logarithmic, 1 * data[i].value, calculatedScale, scaleHop));
|
| - else ctx.fillStyle = data[i].color;
|
| - ctx.fill();
|
| - startAngle += angleStep;
|
| - if (config.segmentShowStroke) {
|
| - ctx.strokeStyle = config.segmentStrokeColor;
|
| - ctx.lineWidth = config.segmentStrokeWidth;
|
| - ctx.stroke();
|
| - }
|
| - }
|
| - }
|
| - if (animationDecimal >= 1) {
|
| - startAngle -= 2*Math.PI;
|
| - for (var i = 0; i < data.length; i++) {
|
| - if (!(typeof(data[i].value) == 'undefined')) {
|
| - cumvalue += 1 * data[i].value;
|
| - startAngle += angleStep;
|
| - if (typeof(data[i].title) == "string") lgtxt = data[i].title.trim();
|
| - else lgtxt = "";
|
| - jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["ARC", midPosX, midPosY, 0, calculateOffset(config.logarithmic, 1 * data[i].value, calculatedScale, scaleHop), startAngle - angleStep, startAngle, lgtxt, 1 * data[i].value, cumvalue, totvalue, angleStep, i];
|
| - if (config.inGraphDataShow) {
|
| - if (config.inGraphDataAnglePosition == 1) posAngle = realStartAngle + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - else if (config.inGraphDataAnglePosition == 2) posAngle = realStartAngle - angleStep / 2 + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - else if (config.inGraphDataAnglePosition == 3) posAngle = realStartAngle - angleStep + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - if (config.inGraphDataRadiusPosition == 1) labelRadius = 0 + config.inGraphDataPaddingRadius;
|
| - else if (config.inGraphDataRadiusPosition == 2) labelRadius = calculateOffset(config.logarithmic, 1 * data[i].value, calculatedScale, scaleHop) / 2 + config.inGraphDataPaddingRadius;
|
| - else if (config.inGraphDataRadiusPosition == 3) labelRadius = calculateOffset(config.logarithmic, 1 * data[i].value, calculatedScale, scaleHop) + config.inGraphDataPaddingRadius;
|
| - else if (config.inGraphDataRadiusPosition == 4) labelRadius = scaleHop * calculatedScale.steps + config.inGraphDataPaddingRadius;
|
| - ctx.save()
|
| - if (config.inGraphDataAlign == "off-center") {
|
| - if (config.inGraphDataRotate == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "left";
|
| - else ctx.textAlign = "right";
|
| - } else if (config.inGraphDataAlign == "to-center") {
|
| - if (config.inGraphDataRotate == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "right";
|
| - else ctx.textAlign = "left";
|
| - } else ctx.textAlign = config.inGraphDataAlign;
|
| - if (config.inGraphDataVAlign == "off-center") {
|
| - if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "top";
|
| - else ctx.textBaseline = "bottom";
|
| - } else if (config.inGraphDataVAlign == "to-center") {
|
| - if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "bottom";
|
| - else ctx.textBaseline = "top";
|
| - } else ctx.textBaseline = config.inGraphDataVAlign;
|
| - ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily;
|
| - ctx.fillStyle = config.inGraphDataFontColor;
|
| - var dispString = tmplbis(config.inGraphDataTmpl, {
|
| - config: config,
|
| - v1: fmtChartJS(config, lgtxt, config.fmtV1),
|
| - v2: fmtChartJS(config, 1 * data[i].value, config.fmtV2),
|
| - v3: fmtChartJS(config, cumvalue, config.fmtV3),
|
| - v4: fmtChartJS(config, totvalue, config.fmtV4),
|
| - v5: fmtChartJS(config, angleStep, config.fmtV5),
|
| - v6: roundToWithThousands(config, fmtChartJS(config, 100 * data[i].value / totvalue, config.fmtV6), config.roundPct),
|
| - v7: fmtChartJS(config, midPosX, config.fmtV7),
|
| - v8: fmtChartJS(config, midPosY, config.fmtV8),
|
| - v9: fmtChartJS(config, 0, config.fmtV9),
|
| - v10: fmtChartJS(config, calculateOffset(config.logarithmic, 1 * data[i].value, calculatedScale, scaleHop), config.fmtV10),
|
| - v11: fmtChartJS(config, startAngle - angleStep, config.fmtV11),
|
| - v12: fmtChartJS(config, angleStep, config.fmtV12),
|
| - v13: fmtChartJS(config, i, config.fmtV13),
|
| - data: data
|
| - });
|
| - ctx.translate(midPosX + labelRadius * Math.cos(posAngle), midPosY - labelRadius * Math.sin(posAngle));
|
| - if (config.inGraphDataRotate == "inRadiusAxis") ctx.rotate(2 * Math.PI - posAngle);
|
| - else if (config.inGraphDataRotate == "inRadiusAxisRotateLabels") {
|
| - if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI / 2 && (posAngle + 2 * Math.PI) % (2 * Math.PI) < 3 * Math.PI / 2) ctx.rotate(3 * Math.PI - posAngle);
|
| - else ctx.rotate(2 * Math.PI - posAngle);
|
| - } else ctx.rotate(config.inGraphDataRotate * (Math.PI / 180));
|
| - ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize);
|
| - ctx.restore();
|
| - }
|
| - realStartAngle -= angleStep;
|
| - }
|
| - }
|
| - }
|
| - if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"PolarArea");
|
| - };
|
| -
|
| - function drawScale() {
|
| - for (var i = 0; i < calculatedScale.steps; i++) {
|
| - //If the line object is there
|
| - if (config.scaleShowLine) {
|
| - ctx.beginPath();
|
| - ctx.arc(midPosX, midPosY, 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 + 1];
|
| - //If the backdrop object is within the font object
|
| - if (config.scaleShowLabelBackdrop) {
|
| - var textWidth = ctx.measureTextMultiLine(label, config.scaleFontSize).textWidth;
|
| - ctx.fillStyle = config.scaleBackdropColor;
|
| - ctx.beginPath();
|
| - ctx.rect(
|
| - Math.round(midPosX - textWidth / 2 - config.scaleBackdropPaddingX), //X
|
| - Math.round(midPosY - (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.fillTextMultiLine(label, midPosX, midPosY - (scaleHop * (i + 1)), ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - }
|
| - };
|
| -
|
| - function getValueBounds() {
|
| - var upperValue = Number.MIN_VALUE;
|
| - var lowerValue = Number.MAX_VALUE;
|
| - for (var i = 0; i < data.length; i++) {
|
| - if (1 * data[i].value > upperValue) {
|
| - upperValue = 1 * data[i].value;
|
| - }
|
| - if (1 * data[i].value < lowerValue) {
|
| - lowerValue = 1 * data[i].value;
|
| - }
|
| - };
|
| - if (Math.abs(upperValue - lowerValue) < 0.00000001) {
|
| - upperValue = Max([upperValue * 2, 1]);
|
| - lowerValue = 0;
|
| - }
|
| - if (!isNaN(config.graphMin)) lowerValue = config.graphMin;
|
| - if (!isNaN(config.graphMax)) upperValue = config.graphMax;
|
| - 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, msr, midPosX, midPosY;
|
| -
|
| - ctx.tpchart="Radar";
|
| - setting_new_chart_vars(ctx);
|
| - if (!dynamicFunction(data, config, ctx)) {
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } }
|
| - return;
|
| - }
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") {
|
| - if(!config.multiGraph) {
|
| - addResponsiveChart(ctx.ChartNewId,ctx,data,config);
|
| - subUpdateChart(ctx,data,config);
|
| - return;
|
| - } else { ctx.firstPass=1; }
|
| - }
|
| -
|
| - while (config.startAngle < 0) {
|
| - config.startAngle += 360;
|
| - }
|
| - while (config.startAngle > 360) {
|
| - config.startAngle -= 360;
|
| - }
|
| - config.logarithmic = false;
|
| - config.logarithmic2 = false;
|
| - if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array();
|
| - else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId);
|
| - defMouse(ctx, data, config);
|
| - //If no labels are defined set to an empty array, so referencing length for looping doesn't blow up.
|
| - if (!data.labels) data.labels = [];
|
| - setRect(ctx, config);
|
| - valueBounds = getValueBounds();
|
| - //Check and set the scale
|
| - labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : "";
|
| - if (!config.scaleOverride) {
|
| - calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString);
|
| - msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, false, true, config.datasetFill, "Radar");
|
| - } else {
|
| - calculatedScale = {
|
| - steps: config.scaleSteps,
|
| - stepValue: config.scaleStepWidth,
|
| - graphMin: config.scaleStartValue,
|
| - graphMax: config.scaleStartValue + config.scaleSteps * config.scaleStepWidth,
|
| - labels: []
|
| - }
|
| - populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, config.scaleStartValue, calculatedScale.graphMax, config.scaleStepWidth);
|
| - msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, false, true, config.datasetFill, "Radar");
|
| - }
|
| -
|
| -
|
| - calculateDrawingSizes();
|
| - midPosY = msr.topNotUsableSize + (msr.availableHeight / 2);
|
| - scaleHop = maxSize / (calculatedScale.steps);
|
| - //Wrap in an animation loop wrapper
|
| - animationLoop(config, drawScale, drawAllDataPoints, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, midPosX, midPosY, midPosX - maxSize, midPosY + maxSize, data);
|
| - //Radar specific functions.
|
| - function drawAllDataPoints(animationDecimal) {
|
| - var totvalue = new Array();
|
| - var maxvalue = new Array();
|
| - var lmaxvalue = new Array();
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - lmaxvalue[i] = -999999999;
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - totvalue[j] = 0;
|
| - maxvalue[j] = -999999999;
|
| - }
|
| - }
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
|
| - totvalue[j] += 1 * data.datasets[i].data[j];
|
| - maxvalue[j] = Max([maxvalue[j], 1 * data.datasets[i].data[j]]);
|
| - lmaxvalue[i] = Max([lmaxvalue[i], 1 * data.datasets[i].data[j]]);
|
| - }
|
| - }
|
| - }
|
| - var rotationDegree = (2 * Math.PI) / data.datasets[0].data.length;
|
| - ctx.save();
|
| - //We accept multiple data sets for radar charts, so show loop through each set
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - if (animationDecimal >= 1) {
|
| - if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim();
|
| - else lgtxt = "";
|
| - }
|
| - var fPt = -1;
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - var currentAnimPc = animationCorrection(animationDecimal, data, config, i, j, 1).animVal;
|
| - if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1;
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
|
| - if (fPt == -1) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(midPosX + currentAnimPc * (Math.cos(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop)), midPosY - currentAnimPc * (Math.sin(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop)));
|
| - fPt = j;
|
| - } else {
|
| - ctx.lineTo(midPosX + currentAnimPc * (Math.cos(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop)), midPosY - currentAnimPc * (Math.sin(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop)));
|
| - }
|
| - if (animationDecimal >= 1) {
|
| - if (i == 0) divprev = 0;
|
| - else divprev = data.datasets[i].data[j] - data.datasets[i - 1].data[j];
|
| - if (i == data.datasets.length - 1) divnext = 0;
|
| - else divnext = data.datasets[i + 1].data[j] - data.datasets[i].data[j];
|
| - if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim();
|
| - else lgtxt2 = "";
|
| - jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["POINT", midPosX + Math.cos(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop), midPosY - Math.sin(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop), lgtxt, lgtxt2, 1 * data.datasets[i].data[j], divprev, divnext, maxvalue[j], totvalue[j], i, j];
|
| - }
|
| - }
|
| - }
|
| - ctx.closePath();
|
| - if (config.datasetFill) {
|
| - if (typeof data.datasets[i].fillColor == "function") ctx.fillStyle = data.datasets[i].fillColor("FILLCOLOR", data, config, i, -1, currentAnimPc, -1, "Radar", ctx, midPosX, midPosY, 0, (config.animationLeftToRight ? 1 : currentAnimPc) * (calculateOffset(config.logarithmic, lmaxvalue[i], calculatedScale, scaleHop)));
|
| - else if (typeof data.datasets[i].fillColor == "string") ctx.fillStyle = data.datasets[i].fillColor;
|
| - else ctx.fillStyle = config.defaultFillColor;
|
| - } else ctx.fillStyle = "rgba(0,0,0,0)";
|
| - if (typeof data.datasets[i].strokeColor == "function") ctx.strokeStyle = data.datasets[i].strokeColor("STROKECOLOR", data, config, i, -1, currentAnimPc, -1, "Radar", ctx, midPosX, midPosY, 0, (config.animationLeftToRight ? 1 : currentAnimPc) * (calculateOffset(config.logarithmic, lmaxvalue[i], calculatedScale, scaleHop)));
|
| - else if (typeof data.datasets[i].strokeColor == "string") ctx.strokeStyle = data.datasets[i].strokeColor;
|
| - else ctx.strokeStyle = config.defaultStrokeColor;
|
| - ctx.lineWidth = config.datasetStrokeWidth;
|
| - ctx.fill();
|
| - ctx.stroke();
|
| - if (config.pointDot && (!config.animationLeftToRight || (config.animationLeftToRight && animationDecimal >= 1))) {
|
| - ctx.beginPath();
|
| - if (typeof data.datasets[i].pointColor == "function") ctx.fillStyle = data.datasets[i].pointColor("POINTCOLOR", data, config, i, -1, currentAnimPc, -1, "Radar", ctx, midPosX, midPosY, 0, (config.animationLeftToRight ? 1 : currentAnimPc) * (calculateOffset(config.logarithmic, lmaxvalue[i], calculatedScale, scaleHop)));
|
| - else ctx.fillStyle = data.datasets[i].pointColor;
|
| - if (typeof data.datasets[i].pointStrokeColor == "function") ctx.strokeStyle = data.datasets[i].pointStrokeColor("POINTSTROKECOLOR", data, config, i, -1, currentAnimPc, -1, "Radar", ctx, midPosX, midPosY, 0, (config.animationLeftToRight ? 1 : currentAnimPc) * (calculateOffset(config.logarithmic, lmaxvalue[i], calculatedScale, scaleHop)));
|
| - else ctx.strokeStyle = data.datasets[i].pointStrokeColor;
|
| - ctx.lineWidth = config.pointDotStrokeWidth;
|
| - for (var k = 0; k < data.datasets[i].data.length; k++) {
|
| - if (!(typeof(data.datasets[i].data[k]) == 'undefined')) {
|
| - ctx.beginPath();
|
| - ctx.arc(midPosX + currentAnimPc * (Math.cos(config.startAngle * Math.PI / 180 - k * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[k], calculatedScale, scaleHop)), midPosY - currentAnimPc * (Math.sin(config.startAngle * Math.PI / 180 - k * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[k], calculatedScale, scaleHop)), config.pointDotRadius, 2 * Math.PI, false);
|
| - ctx.fill();
|
| - ctx.stroke();
|
| - }
|
| - }
|
| - }
|
| - }
|
| - ctx.restore();
|
| - if (animationDecimal >= 1 && config.inGraphDataShow) {
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim();
|
| - else lgtxt = "";
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
|
| - if (i == 0) divprev = 0;
|
| - else divprev = data.datasets[i].data[j] - data.datasets[i - 1].data[j];
|
| - if (i == data.datasets.length - 1) divnext = 0;
|
| - else divnext = data.datasets[i + 1].data[j] - data.datasets[i].data[j];
|
| - if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim();
|
| - else lgtxt2 = "";
|
| - ctx.save();
|
| - ctx.textAlign = config.inGraphDataAlign;
|
| - ctx.textBaseline = config.inGraphDataVAlign;
|
| - if (config.inGraphDataAlign == "off-center") {
|
| - if (config.inGraphDataRotate == "inRadiusAxis" || (config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) <= Math.PI / 2) ctx.textAlign = "left";
|
| - else ctx.textAlign = "right";
|
| - } else if (config.inGraphDataAlign == "to-center") {
|
| - if (config.inGraphDataRotate == "inRadiusAxis" || (config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "right";
|
| - else ctx.textAlign = "left";
|
| - } else ctx.textAlign = config.inGraphDataAlign;
|
| - if (config.inGraphDataVAlign == "off-center") {
|
| - if ((config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "bottom";
|
| - else ctx.textBaseline = "top";
|
| - } else if (config.inGraphDataVAlign == "to-center") {
|
| - if ((config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "top";
|
| - else ctx.textBaseline = "bottom";
|
| - } else ctx.textBaseline = config.inGraphDataVAlign;
|
| - ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily;
|
| - ctx.fillStyle = config.inGraphDataFontColor;
|
| - var radiusPrt;
|
| - if (config.inGraphDataRadiusPosition == 1) radiusPrt = 0 + config.inGraphDataPaddingRadius;
|
| - else if (config.inGraphDataRadiusPosition == 2) radiusPrt = (calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop)) / 2 + config.inGraphDataPaddingRadius;
|
| - else if (config.inGraphDataRadiusPosition == 3) radiusPrt = (calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop)) + config.inGraphDataPaddingRadius;
|
| - ctx.translate(midPosX + Math.cos(config.startAngle * Math.PI / 180 - j * rotationDegree) * radiusPrt, midPosY - Math.sin(config.startAngle * Math.PI / 180 - j * rotationDegree) * radiusPrt);
|
| - if (config.inGraphDataRotate == "inRadiusAxis") ctx.rotate(j * rotationDegree);
|
| - else if (config.inGraphDataRotate == "inRadiusAxisRotateLabels") {
|
| - if ((j * rotationDegree + 2 * Math.PI) % (2 * Math.PI) > Math.PI / 2 && (j * rotationDegree + 2 * Math.PI) % (2 * Math.PI) < 3 * Math.PI / 2) ctx.rotate(3 * Math.PI + j * rotationDegree);
|
| - else ctx.rotate(2 * Math.PI + j * rotationDegree);
|
| - } else ctx.rotate(config.inGraphDataRotate * (Math.PI / 180));
|
| - var dispString = tmplbis(config.inGraphDataTmpl, {
|
| - config: config,
|
| - v1: fmtChartJS(config, lgtxt, config.fmtV1),
|
| - v2: fmtChartJS(config, lgtxt2, config.fmtV2),
|
| - v3: fmtChartJS(config, 1 * data.datasets[i].data[j], config.fmtV3),
|
| - v4: fmtChartJS(config, divprev, config.fmtV4),
|
| - v5: fmtChartJS(config, divnext, config.fmtV5),
|
| - v6: fmtChartJS(config, maxvalue[j], config.fmtV6),
|
| - v7: fmtChartJS(config, totvalue[j], config.fmtV7),
|
| - v8: roundToWithThousands(config, fmtChartJS(config, 100 * data.datasets[i].data[j] / totvalue[j], config.fmtV8), config.roundPct),
|
| - v9: fmtChartJS(config, midPosX + Math.cos(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop), config.fmtV9),
|
| - v10: fmtChartJS(config, midPosY - Math.sin(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop), config.fmtV10),
|
| - v11: fmtChartJS(config, i, config.fmtV11),
|
| - v12: fmtChartJS(config, j, config.fmtV12),
|
| - data: data
|
| - });
|
| - ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize);
|
| - ctx.restore();
|
| - }
|
| - }
|
| - }
|
| - }
|
| - if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Radar");
|
| - };
|
| -
|
| - function drawScale() {
|
| - var rotationDegree = (2 * Math.PI) / data.datasets[0].data.length;
|
| - ctx.save();
|
| - ctx.translate(midPosX, midPosY);
|
| - ctx.rotate((90 - config.startAngle) * Math.PI / 180);
|
| - 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();
|
| - }
|
| - }
|
| - ctx.rotate(-(90 - config.startAngle) * Math.PI / 180);
|
| - if (config.scaleShowLabels) {
|
| - for (var i = 0; i < calculatedScale.steps; i++) {
|
| - ctx.textAlign = 'center';
|
| - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
|
| - ctx.textBaseline = "middle";
|
| - if (config.scaleShowLabelBackdrop) {
|
| - var textWidth = ctx.measureTextMultiLine(calculatedScale.labels[i + 1], config.scaleFontSize).textWidth;
|
| - ctx.fillStyle = config.scaleBackdropColor;
|
| - ctx.beginPath();
|
| - ctx.rect(
|
| - Math.round(Math.cos(config.startAngle * Math.PI / 180) * (scaleHop * (i + 1)) - textWidth / 2 - config.scaleBackdropPaddingX), //X
|
| - Math.round((-Math.sin(config.startAngle * Math.PI / 180) * 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.fillTextMultiLine(calculatedScale.labels[i + 1], Math.cos(config.startAngle * Math.PI / 180) * (scaleHop * (i + 1)), -Math.sin(config.startAngle * Math.PI / 180) * scaleHop * (i + 1), ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - }
|
| - 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((90 - config.startAngle) * Math.PI / 180 + rotationDegree * k) * (maxSize + config.pointLabelFontSize);
|
| - var adjacent = Math.cos((90 - config.startAngle) * Math.PI / 180 + rotationDegree * k) * (maxSize + config.pointLabelFontSize);
|
| - var vangle = (90 - config.startAngle) * Math.PI / 180 + rotationDegree * k;
|
| - while (vangle < 0) vangle = vangle + 2 * Math.PI;
|
| - while (vangle > 2 * Math.PI) vangle = vangle - 2 * Math.PI;
|
| - if (vangle == Math.PI || vangle == 0) {
|
| - ctx.textAlign = "center";
|
| - } else if (vangle > Math.PI) {
|
| - ctx.textAlign = "right";
|
| - } else {
|
| - ctx.textAlign = "left";
|
| - }
|
| - ctx.textBaseline = "middle";
|
| - ctx.fillTextMultiLine(data.labels[k], opposite, -adjacent, ctx.textBaseline, config.pointLabelFontSize);
|
| - }
|
| - ctx.restore();
|
| - };
|
| -
|
| - function calculateDrawingSizes() {
|
| - var midX, mxlb, maxL, maxR, iter, nbiter, prevMaxSize, prevMidX;
|
| - var rotationDegree = (2 * Math.PI) / data.datasets[0].data.length;
|
| - var rotateAngle = config.startAngle * Math.PI / 180;
|
| - // Compute range for Mid Point of graph
|
| - ctx.font = config.pointLabelFontStyle + " " + config.pointLabelFontSize + "px " + config.pointLabelFontFamily;
|
| - if (!config.graphMaximized) {
|
| - maxR = msr.availableWidth / 2;
|
| - maxL = msr.availableWidth / 2;
|
| - nbiter = 1;
|
| - } else {
|
| - maxR = msr.availableWidth / 2;
|
| - maxL = msr.availableWidth / 2;
|
| - nbiter = 40;
|
| - for (var i = 0; i < data.labels.length; i++) {
|
| - var textMeasurement = ctx.measureTextMultiLine(data.labels[i], config.scaleFontSize).textWidth + ctx.measureTextMultiLine(data.labels[i], config.scaleFontSize).textHeight;
|
| - mxlb = (msr.availableWidth - textMeasurement) / (1 + Math.abs(Math.cos(rotateAngle)));
|
| - if ((rotateAngle < Math.PI / 2 && rotateAngle > -Math.PI / 2) || rotateAngle > 3 * Math.PI / 2) {
|
| - if (mxlb < maxR) maxR = mxlb;
|
| - } else if (Math.cos(rotateAngle) != 0) {
|
| - if (mxlb < maxL) maxL = mxlb;
|
| - }
|
| - rotateAngle -= rotationDegree;
|
| - }
|
| - }
|
| - // compute max Radius and midPoint in that range
|
| - prevMaxSize = 0;
|
| - prevMidX = 0;
|
| - midPosX = maxR + msr.rightNotUsableSize;
|
| - for (midX = maxR, iter = 0; iter < nbiter; ++iter, midX += (msr.availableWidth - maxL - maxR) / nbiter) {
|
| - maxSize = Max([midX, msr.availableWidth - midX]);
|
| - var rotateAngle = config.startAngle * Math.PI / 180;
|
| - mxlb = msr.available;
|
| - for (var i = 0; i < data.labels.length; i++) {
|
| - var textMeasurement = ctx.measureTextMultiLine(data.labels[i], config.scaleFontSize).textWidth + ctx.measureTextMultiLine(data.labels[i], config.scaleFontSize).textHeight;
|
| - if ((rotateAngle < Math.PI / 2 && rotateAngle > -Math.PI / 2) || rotateAngle > 3 * Math.PI / 2) {
|
| - mxlb = ((msr.availableWidth - midX) - textMeasurement) / Math.abs(Math.cos(rotateAngle));
|
| - } else if (Math.cos(rotateAngle != 0)) {
|
| - mxlb = (midX - textMeasurement) / Math.abs(Math.cos(rotateAngle));
|
| - }
|
| - if (mxlb < maxSize) maxSize = mxlb;
|
| - if (Math.sin(rotateAngle) * msr.availableHeight / 2 > msr.availableHeight / 2 - config.scaleFontSize * 2) {
|
| - mxlb = Math.sin(rotateAngle) * msr.availableHeight / 2 - 1.5 * config.scaleFontSize;
|
| - if (mxlb < maxSize) maxSize = mxlb;
|
| - }
|
| - rotateAngle -= rotationDegree;
|
| - }
|
| - if (maxSize > prevMaxSize) {
|
| - prevMaxSize = maxSize;
|
| - midPosX = midX + msr.rightNotUsableSize;
|
| - }
|
| - }
|
| - maxSize = prevMaxSize - config.scaleFontSize / 2;
|
| - //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 (1 * data.datasets[i].data[j] > upperValue) {
|
| - upperValue = 1 * data.datasets[i].data[j]
|
| - }
|
| - if (1 * data.datasets[i].data[j] < lowerValue) {
|
| - lowerValue = 1 * data.datasets[i].data[j]
|
| - }
|
| - }
|
| - }
|
| - if (Math.abs(upperValue - lowerValue) < 0.00000001) {
|
| - upperValue = Max([upperValue * 2, 1]);
|
| - lowerValue = 0;
|
| - }
|
| - if (!isNaN(config.graphMin)) lowerValue = config.graphMin;
|
| - if (!isNaN(config.graphMax)) upperValue = config.graphMax;
|
| - 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;
|
| - var msr, midPieX, midPieY, pieRadius;
|
| -
|
| - ctx.tpchart="Pie";
|
| - setting_new_chart_vars(ctx);
|
| - if (!dynamicFunction(data, config, ctx)) {
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } }
|
| - return;
|
| - }
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") {
|
| - if(!config.multiGraph) {
|
| - addResponsiveChart(ctx.ChartNewId,ctx,data,config);
|
| - subUpdateChart(ctx,data,config);
|
| - return;
|
| - } else { ctx.firstPass=1; }
|
| - }
|
| -
|
| - while (config.startAngle < 0) {
|
| - config.startAngle += 360;
|
| - }
|
| - while (config.startAngle > 360) {
|
| - config.startAngle -= 360;
|
| - }
|
| - config.logarithmic = false;
|
| - config.logarithmic2 = false;
|
| - if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array();
|
| - else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId);
|
| - defMouse(ctx, data, config);
|
| - //In case we have a canvas that is not a square. Minus 5 pixels as padding round the edge.
|
| - setRect(ctx, config);
|
| - msr = setMeasures(data, config, ctx, height, width, "none", null, true, false, false, false, true, "Pie");
|
| - // midPieX = msr.leftNotUsableSize + (msr.availableWidth / 2);
|
| - // midPieY = msr.topNotUsableSize + (msr.availableHeight / 2);
|
| - // pieRadius = Min([msr.availableHeight / 2, msr.availableWidth / 2]) - 5;
|
| - for (var i = 0; i < data.length; i++) {
|
| - if (!(typeof(data[i].value) == 'undefined')) segmentTotal += 1 * data[i].value;
|
| - }
|
| - calculateDrawingSize();
|
| - if(pieRadius > 0) {
|
| - animationLoop(config, null, drawPieSegments, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, midPieX, midPieY, midPieX - pieRadius, midPieY + pieRadius, data);
|
| - } else {
|
| - testRedraw(ctx,data,config);
|
| - }
|
| - function drawPieSegments(animationDecimal) {
|
| - var cumulativeAngle = -config.startAngle * (Math.PI / 180) + 2 * Math.PI,
|
| - cumvalue = 0,
|
| - scaleAnimation = 1,
|
| - rotateAnimation = 1;
|
| - var realCumulativeAngle = config.startAngle * (Math.PI / 180) + 2 * Math.PI;
|
| - while (cumulativeAngle < 0) {
|
| - cumulativeAngle += 2 * Math.PI;
|
| - }
|
| - while (cumulativeAngle > 2 * Math.PI) {
|
| - cumulativeAngle -= 2 * Math.PI;
|
| - }
|
| - while (realCumulativeAngle < 0) {
|
| - realCumulativeAngle += 2 * Math.PI;
|
| - }
|
| - while (realCumulativeAngle > 2 * Math.PI) {
|
| - realCumulativeAngle -= 2 * Math.PI;
|
| - }
|
| - if (config.animation) {
|
| - if (config.animateScale) {
|
| - scaleAnimation = animationDecimal;
|
| - }
|
| - if (config.animateRotate) {
|
| - rotateAnimation = animationDecimal;
|
| - }
|
| - }
|
| - if (animationDecimal >= 1) {
|
| - totvalue = 0;
|
| - for (var i = 0; i < data.length; i++)
|
| - if (!(typeof(data[i].value) == 'undefined')) totvalue += 1 * data[i].value;
|
| - }
|
| - for (var i = 0; i < data.length; i++) {
|
| - correctedRotateAnimation = animationCorrection(rotateAnimation, data, config, i, -1, 0).mainVal;
|
| - if (!(typeof(data[i].value) == 'undefined')) {
|
| - var segmentAngle = correctedRotateAnimation * ((1 * data[i].value / segmentTotal) * (Math.PI * 2));
|
| - if (segmentAngle >= Math.PI * 2) segmentAngle = Math.PI * 2 - 0.001; // bug on Android when segmentAngle is >= 2*PI;
|
| - ctx.beginPath();
|
| - ctx.arc(midPieX, midPieY, scaleAnimation * pieRadius, cumulativeAngle, cumulativeAngle + segmentAngle);
|
| - ctx.lineTo(midPieX, midPieY);
|
| - ctx.closePath();
|
| - if (typeof data[i].color == "function") ctx.fillStyle = data[i].color("COLOR", data, config, i, -1, animationDecimal, data[i].value, "Pie", ctx, midPieX, midPieY, 0, scaleAnimation * pieRadius);
|
| - else ctx.fillStyle = data[i].color;
|
| - ctx.fill();
|
| - cumulativeAngle += segmentAngle;
|
| - cumvalue += 1 * data[i].value;
|
| - if (config.segmentShowStroke) {
|
| - ctx.lineWidth = config.segmentStrokeWidth;
|
| - ctx.strokeStyle = config.segmentStrokeColor;
|
| - ctx.stroke();
|
| - }
|
| - }
|
| - }
|
| - if (animationDecimal >= 1) {
|
| - cumulativeAngle-=2*Math.PI;
|
| - for (var i = 0; i < data.length; i++) {
|
| - correctedRotateAnimation = animationCorrection(rotateAnimation, data, config, i, -1, 0).mainVal;
|
| - if (!(typeof(data[i].value) == 'undefined')) {
|
| - var segmentAngle = correctedRotateAnimation * ((1 * data[i].value / segmentTotal) * (Math.PI * 2));
|
| - if (segmentAngle >= Math.PI * 2) segmentAngle = Math.PI * 2 - 0.001; // bug on Android when segmentAngle is >= 2*PI;
|
| - cumulativeAngle += segmentAngle;
|
| - cumvalue += 1 * data[i].value;
|
| - if (typeof(data[i].title) == "string") lgtxt = data[i].title.trim();
|
| - else lgtxt = "";
|
| - jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["ARC", midPieX, midPieY, 0, pieRadius, cumulativeAngle - segmentAngle, cumulativeAngle, lgtxt, 1 * data[i].value, cumvalue, totvalue, segmentAngle, i];
|
| - if (config.inGraphDataShow && segmentAngle >= (Math.PI/180) * config.inGraphDataMinimumAngle) {
|
| - if (config.inGraphDataAnglePosition == 1) posAngle = realCumulativeAngle + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - else if (config.inGraphDataAnglePosition == 2) posAngle = realCumulativeAngle - segmentAngle / 2 + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - else if (config.inGraphDataAnglePosition == 3) posAngle = realCumulativeAngle - segmentAngle + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - if (config.inGraphDataRadiusPosition == 1) labelRadius = 0 + config.inGraphDataPaddingRadius;
|
| - else if (config.inGraphDataRadiusPosition == 2) labelRadius = pieRadius / 2 + config.inGraphDataPaddingRadius;
|
| - else if (config.inGraphDataRadiusPosition == 3) labelRadius = pieRadius + config.inGraphDataPaddingRadius;
|
| - ctx.save();
|
| - if (config.inGraphDataAlign == "off-center") {
|
| - if (config.inGraphDataRotate == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "left";
|
| - else ctx.textAlign = "right";
|
| - } else if (config.inGraphDataAlign == "to-center") {
|
| - if (config.inGraphDataRotate == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "right";
|
| - else ctx.textAlign = "left";
|
| - } else ctx.textAlign = config.inGraphDataAlign;
|
| - if (config.inGraphDataVAlign == "off-center") {
|
| - if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "top";
|
| - else ctx.textBaseline = "bottom";
|
| - } else if (config.inGraphDataVAlign == "to-center") {
|
| - if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "bottom";
|
| - else ctx.textBaseline = "top";
|
| - } else ctx.textBaseline = config.inGraphDataVAlign;
|
| - ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily;
|
| - ctx.fillStyle = config.inGraphDataFontColor;
|
| - var dispString = tmplbis(config.inGraphDataTmpl, {
|
| - config: config,
|
| - v1: fmtChartJS(config, lgtxt, config.fmtV1),
|
| - v2: fmtChartJS(config, 1 * data[i].value, config.fmtV2),
|
| - v3: fmtChartJS(config, cumvalue, config.fmtV3),
|
| - v4: fmtChartJS(config, totvalue, config.fmtV4),
|
| - v5: fmtChartJS(config, segmentAngle, config.fmtV5),
|
| - v6: roundToWithThousands(config, fmtChartJS(config, 100 * data[i].value / totvalue, config.fmtV6), config.roundPct),
|
| - v7: fmtChartJS(config, midPieX, config.fmtV7),
|
| - v8: fmtChartJS(config, midPieY, config.fmtV8),
|
| - v9: fmtChartJS(config, 0, config.fmtV9),
|
| - v10: fmtChartJS(config, pieRadius, config.fmtV10),
|
| - v11: fmtChartJS(config, cumulativeAngle - segmentAngle, config.fmtV11),
|
| - v12: fmtChartJS(config, cumulativeAngle, config.fmtV12),
|
| - v13: fmtChartJS(config, i, config.fmtV13),
|
| - data: data
|
| - });
|
| - ctx.translate(midPieX + labelRadius * Math.cos(posAngle), midPieY - labelRadius * Math.sin(posAngle));
|
| - if (config.inGraphDataRotate == "inRadiusAxis") ctx.rotate(2 * Math.PI - posAngle);
|
| - else if (config.inGraphDataRotate == "inRadiusAxisRotateLabels") {
|
| - if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI / 2 && (posAngle + 2 * Math.PI) % (2 * Math.PI) < 3 * Math.PI / 2) ctx.rotate(3 * Math.PI - posAngle);
|
| - else ctx.rotate(2 * Math.PI - posAngle);
|
| - } else ctx.rotate(config.inGraphDataRotate * (Math.PI / 180));
|
| - ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize);
|
| - ctx.restore();
|
| - }
|
| - realCumulativeAngle -= segmentAngle;
|
| - }
|
| - }
|
| -
|
| - }
|
| - if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Pie");
|
| - };
|
| -
|
| - function calculateDrawingSize() {
|
| - var lgtxt;
|
| - var cumulativeAngle = -config.startAngle * (Math.PI / 180) + 2 * Math.PI,
|
| - cumvalue = 0;
|
| - while (cumulativeAngle < 0) {
|
| - cumulativeAngle += 2 * Math.PI;
|
| - }
|
| - while (cumulativeAngle > 2 * Math.PI) {
|
| - cumulativeAngle -= 2 * Math.PI;
|
| - }
|
| - midPieX = msr.leftNotUsableSize + (msr.availableWidth / 2);
|
| - midPieY = msr.topNotUsableSize + (msr.availableHeight / 2);
|
| - pieRadius = Min([msr.availableHeight / 2, msr.availableWidth / 2]) - 5;
|
| - // Computerange Pie Radius
|
| - if (config.inGraphDataShow && config.inGraphDataRadiusPosition == 3 && config.inGraphDataAlign == "off-center" && config.inGraphDataRotate == 0) {
|
| - pieRadius = Min([msr.availableHeight / 2, msr.availableWidth / 2]) - config.inGraphDataFontSize - config.inGraphDataPaddingRadius - 5;
|
| - var realCumulativeAngle = config.startAngle * (Math.PI / 180) + 2 * Math.PI;
|
| - while (realCumulativeAngle < 0) {
|
| - realCumulativeAngle += 2 * Math.PI;
|
| - }
|
| - while (realCumulativeAngle > 2 * Math.PI) {
|
| - realCumulativeAngle -= 2 * Math.PI;
|
| - }
|
| - var totvalue = 0;
|
| - for (var i = 0; i < data.length; i++)
|
| - if (!(typeof(data[i].value) == 'undefined')) totvalue += 1 * data[i].value;
|
| - ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily;
|
| - var cumvalue = 0;
|
| - var posAngle;
|
| - for (var i = 0; i < data.length; i++) {
|
| - if (!(typeof(data[i].value) == 'undefined')) {
|
| - cumvalue += 1 * data[i].value;
|
| - var segmentAngle = (1 * data[i].value / segmentTotal) * (Math.PI * 2);
|
| - cumulativeAngle += segmentAngle;
|
| - if (config.inGraphDataAnglePosition == 1) posAngle = realCumulativeAngle + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - else if (config.inGraphDataAnglePosition == 2) posAngle = realCumulativeAngle - segmentAngle / 2 + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - else if (config.inGraphDataAnglePosition == 3) posAngle = realCumulativeAngle - segmentAngle + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - realCumulativeAngle -= segmentAngle;
|
| - if (typeof(data[i].title) == "string") lgtxt = data[i].title.trim();
|
| - else lgtxt = "";
|
| - var dispString = tmplbis(config.inGraphDataTmpl, {
|
| - config: config,
|
| - v1: fmtChartJS(config, lgtxt, config.fmtV1),
|
| - v2: fmtChartJS(config, 1 * data[i].value, config.fmtV2),
|
| - v3: fmtChartJS(config, cumvalue, config.fmtV3),
|
| - v4: fmtChartJS(config, totvalue, config.fmtV4),
|
| - v5: fmtChartJS(config, segmentAngle, config.fmtV5),
|
| - v6: roundToWithThousands(config, fmtChartJS(config, 100 * data[i].value / totvalue, config.fmtV6), config.roundPct),
|
| - v7: fmtChartJS(config, midPieX, config.fmtV7),
|
| - v8: fmtChartJS(config, midPieY, config.fmtV8),
|
| - v9: fmtChartJS(config, 0, config.fmtV9),
|
| - v10: fmtChartJS(config, pieRadius, config.fmtV10),
|
| - v11: fmtChartJS(config, cumulativeAngle - segmentAngle, config.fmtV11),
|
| - v12: fmtChartJS(config, cumulativeAngle, config.fmtV12),
|
| - v13: fmtChartJS(config, i, config.fmtV13),
|
| - data: data
|
| - });
|
| - var textMeasurement = ctx.measureText(dispString).width;
|
| - var MaxRadiusX = Math.abs((msr.availableWidth / 2 - textMeasurement) / Math.cos(posAngle)) - config.inGraphDataPaddingRadius - 5;
|
| - if (MaxRadiusX < pieRadius) pieRadius = MaxRadiusX;
|
| - }
|
| - }
|
| - }
|
| - pieRadius = pieRadius * config.radiusScale;
|
| - };
|
| - };
|
| - var Doughnut = function(data, config, ctx) {
|
| - var segmentTotal = 0;
|
| - var msr, midPieX, midPieY, doughnutRadius;
|
| -
|
| - ctx.tpchart="Doughnut";
|
| - setting_new_chart_vars(ctx);
|
| - if (!dynamicFunction(data, config, ctx)) {
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } }
|
| - return;
|
| - }
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") {
|
| - if(!config.multiGraph) {
|
| - addResponsiveChart(ctx.ChartNewId,ctx,data,config);
|
| - subUpdateChart(ctx,data,config);
|
| - return;
|
| - } else { ctx.firstPass=1; }
|
| - }
|
| -
|
| - var realCumulativeAngle = config.startAngle * (Math.PI / 180) + 2 * Math.PI;
|
| - while (config.startAngle < 0) {
|
| - config.startAngle += 360;
|
| - }
|
| - while (config.startAngle > 360) {
|
| - config.startAngle -= 360;
|
| - }
|
| - while (realCumulativeAngle < 0) {
|
| - realCumulativeAngle += 2 * Math.PI;
|
| - }
|
| - while (realCumulativeAngle > 2 * Math.PI) {
|
| - realCumulativeAngle -= 2 * Math.PI;
|
| - }
|
| - config.logarithmic = false;
|
| - config.logarithmic2 = false;
|
| - if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array();
|
| - else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId);
|
| - defMouse(ctx, data, config);
|
| - setRect(ctx, config);
|
| - msr = setMeasures(data, config, ctx, height, width, "none", null, true, false, false, false, true, "Doughnut");
|
| - calculateDrawingSize();
|
| - var cutoutRadius = doughnutRadius * (config.percentageInnerCutout / 100);
|
| - for (var i = 0; i < data.length; i++) {
|
| - if (!(typeof(data[i].value) == 'undefined')) segmentTotal += 1 * data[i].value;
|
| - }
|
| - if(doughnutRadius > 0) {
|
| - animationLoop(config, null, drawPieSegments, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, midPieX, midPieY, midPieX - doughnutRadius, midPieY + doughnutRadius, data);
|
| - } else {
|
| - testRedraw(ctx,data,config);
|
| - }
|
| -
|
| -
|
| - function drawPieSegments(animationDecimal) {
|
| - var cumulativeAngle = -config.startAngle * (Math.PI / 180) + 2 * Math.PI,
|
| - cumvalue = 0,
|
| - scaleAnimation = 1,
|
| - rotateAnimation = 1;
|
| - while (cumulativeAngle < 0) {
|
| - cumulativeAngle += 2 * Math.PI;
|
| - }
|
| - while (cumulativeAngle > 2 * Math.PI) {
|
| - cumulativeAngle -= 2 * Math.PI;
|
| - }
|
| - if (config.animation) {
|
| - if (config.animateScale) {
|
| - scaleAnimation = animationDecimal;
|
| - }
|
| - if (config.animateRotate) {
|
| - rotateAnimation = animationDecimal;
|
| - }
|
| - }
|
| - if (animationDecimal >= 1) {
|
| - totvalue = 0;
|
| - for (var i = 0; i < data.length; i++)
|
| - if (!(typeof(data[i].value) == 'undefined')) totvalue += 1 * data[i].value;
|
| - }
|
| - for (var i = 0; i < data.length; i++) {
|
| - correctedRotateAnimation = animationCorrection(rotateAnimation, data, config, i, -1, 0).mainVal;
|
| - if (!(typeof(data[i].value) == 'undefined')) {
|
| - var segmentAngle = correctedRotateAnimation * ((1 * data[i].value / segmentTotal) * (Math.PI * 2));
|
| - if (segmentAngle >= Math.PI * 2) segmentAngle = Math.PI * 2 - 0.001; // but on Android when segmentAngle is >= 2*PI;
|
| - ctx.beginPath();
|
| - ctx.arc(midPieX, midPieY, scaleAnimation * doughnutRadius, cumulativeAngle, cumulativeAngle + segmentAngle, false);
|
| - ctx.arc(midPieX, midPieY, scaleAnimation * cutoutRadius, cumulativeAngle + segmentAngle, cumulativeAngle, true);
|
| - ctx.closePath();
|
| - if (typeof data[i].color == "function") ctx.fillStyle = data[i].color("COLOR", data, config, i, -1, animationDecimal, data[i].value, "Doughnut", ctx, midPieX, midPieY, scaleAnimation * cutoutRadius, scaleAnimation * doughnutRadius);
|
| - else ctx.fillStyle = data[i].color;
|
| - ctx.fill();
|
| - cumulativeAngle += segmentAngle;
|
| - cumvalue += 1 * data[i].value;
|
| - if (config.segmentShowStroke) {
|
| - ctx.lineWidth = config.segmentStrokeWidth;
|
| - ctx.strokeStyle = config.segmentStrokeColor;
|
| - ctx.stroke();
|
| - }
|
| - }
|
| - }
|
| - if (animationDecimal >= 1) {
|
| - cumulativeAngle-=2*Math.PI;
|
| - for (var i = 0; i < data.length; i++) {
|
| - correctedRotateAnimation = animationCorrection(rotateAnimation, data, config, i, -1, 0).mainVal;
|
| - if (!(typeof(data[i].value) == 'undefined')) {
|
| - var segmentAngle = correctedRotateAnimation * ((1 * data[i].value / segmentTotal) * (Math.PI * 2));
|
| - if (segmentAngle >= Math.PI * 2) segmentAngle = Math.PI * 2 - 0.001; // but on Android when segmentAngle is >= 2*PI;
|
| - cumulativeAngle += segmentAngle;
|
| - cumvalue += 1 * data[i].value;
|
| - if (typeof(data[i].title) == "string") lgtxt = data[i].title.trim();
|
| - else lgtxt = "";
|
| - jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["ARC", midPieX, midPieY, cutoutRadius, doughnutRadius, cumulativeAngle - segmentAngle, cumulativeAngle, lgtxt, 1 * data[i].value, cumvalue, totvalue, segmentAngle, i];
|
| - if (config.inGraphDataShow && segmentAngle >= (Math.PI/180) * config.inGraphDataMinimumAngle) {
|
| - if (config.inGraphDataAnglePosition == 1) posAngle = realCumulativeAngle + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - else if (config.inGraphDataAnglePosition == 2) posAngle = realCumulativeAngle - segmentAngle / 2 + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - else if (config.inGraphDataAnglePosition == 3) posAngle = realCumulativeAngle - segmentAngle + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - if (config.inGraphDataRadiusPosition == 1) labelRadius = cutoutRadius + config.inGraphDataPaddingRadius;
|
| - else if (config.inGraphDataRadiusPosition == 2) labelRadius = cutoutRadius + (doughnutRadius - cutoutRadius) / 2 + config.inGraphDataPaddingRadius;
|
| - else if (config.inGraphDataRadiusPosition == 3) labelRadius = doughnutRadius + config.inGraphDataPaddingRadius;
|
| - ctx.save();
|
| - if (config.inGraphDataAlign == "off-center") {
|
| - if (config.inGraphDataRotate == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "left";
|
| - else ctx.textAlign = "right";
|
| - } else if (config.inGraphDataAlign == "to-center") {
|
| - if (config.inGraphDataRotate == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "right";
|
| - else ctx.textAlign = "left";
|
| - } else ctx.textAlign = config.inGraphDataAlign;
|
| - if (config.inGraphDataVAlign == "off-center") {
|
| - if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "top";
|
| - else ctx.textBaseline = "bottom";
|
| - } else if (config.inGraphDataVAlign == "to-center") {
|
| - if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "bottom";
|
| - else ctx.textBaseline = "top";
|
| - } else ctx.textBaseline = config.inGraphDataVAlign;
|
| - ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily;
|
| - ctx.fillStyle = config.inGraphDataFontColor;
|
| - var dispString = tmplbis(config.inGraphDataTmpl, {
|
| - config: config,
|
| - v1: fmtChartJS(config, lgtxt, config.fmtV1),
|
| - v2: fmtChartJS(config, 1 * data[i].value, config.fmtV2),
|
| - v3: fmtChartJS(config, cumvalue, config.fmtV3),
|
| - v4: fmtChartJS(config, totvalue, config.fmtV4),
|
| - v5: fmtChartJS(config, segmentAngle, config.fmtV5),
|
| - v6: roundToWithThousands(config, fmtChartJS(config, 100 * data[i].value / totvalue, config.fmtV6), config.roundPct),
|
| - v7: fmtChartJS(config, midPieX, config.fmtV7),
|
| - v8: fmtChartJS(config, midPieY, config.fmtV8),
|
| - v9: fmtChartJS(config, cutoutRadius, config.fmtV9),
|
| - v10: fmtChartJS(config, doughnutRadius, config.fmtV10),
|
| - v11: fmtChartJS(config, cumulativeAngle - segmentAngle, config.fmtV11),
|
| - v12: fmtChartJS(config, cumulativeAngle, config.fmtV12),
|
| - v13: fmtChartJS(config, i, config.fmtV13)
|
| - });
|
| - ctx.translate(midPieX + labelRadius * Math.cos(posAngle), midPieY - labelRadius * Math.sin(posAngle));
|
| - if (config.inGraphDataRotate == "inRadiusAxis") ctx.rotate(2 * Math.PI - posAngle);
|
| - else if (config.inGraphDataRotate == "inRadiusAxisRotateLabels") {
|
| - if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI / 2 && (posAngle + 2 * Math.PI) % (2 * Math.PI) < 3 * Math.PI / 2) ctx.rotate(3 * Math.PI - posAngle);
|
| - else ctx.rotate(2 * Math.PI - posAngle);
|
| - } else ctx.rotate(config.inGraphDataRotate * (Math.PI / 180));
|
| - ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize);
|
| - ctx.restore();
|
| - }
|
| - realCumulativeAngle -= segmentAngle;
|
| - }
|
| - }
|
| - }
|
| - if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Doughnut");
|
| - };
|
| -
|
| - function calculateDrawingSize() {
|
| - var lgtxt;
|
| - var cumulativeAngle = -config.startAngle * (Math.PI / 180) + 2 * Math.PI,
|
| - cumvalue = 0;
|
| - while (cumulativeAngle < 0) {
|
| - cumulativeAngle += 2 * Math.PI;
|
| - }
|
| - while (cumulativeAngle > 2 * Math.PI) {
|
| - cumulativeAngle -= 2 * Math.PI;
|
| - }
|
| - midPieX = msr.leftNotUsableSize + (msr.availableWidth / 2);
|
| - midPieY = msr.topNotUsableSize + (msr.availableHeight / 2);
|
| - doughnutRadius = Min([msr.availableHeight / 2, msr.availableWidth / 2]) - 5;
|
| - // Computerange Pie Radius
|
| - if (config.inGraphDataShow && config.inGraphDataRadiusPosition == 3 && config.inGraphDataAlign == "off-center" && config.inGraphDataRotate == 0) {
|
| - doughnutRadius = Min([msr.availableHeight / 2, msr.availableWidth / 2]) - config.inGraphDataFontSize - config.inGraphDataPaddingRadius - 5;
|
| - var realCumulativeAngle = config.startAngle * (Math.PI / 180) + 2 * Math.PI;
|
| - while (realCumulativeAngle < 0) {
|
| - realCumulativeAngle += 2 * Math.PI;
|
| - }
|
| - while (realCumulativeAngle > 2 * Math.PI) {
|
| - realCumulativeAngle -= 2 * Math.PI;
|
| - }
|
| - var totvalue = 0;
|
| - for (var i = 0; i < data.length; i++)
|
| - if (!(typeof(data[i].value) == 'undefined')) totvalue += 1 * data[i].value;
|
| - ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily;
|
| - var posAngle;
|
| - var cumulativeAngle = 0;
|
| - for (var i = 0; i < data.length; i++) {
|
| - if (!(typeof(data[i].value) == 'undefined')) {
|
| - cumvalue += 1 * data[i].value;
|
| - var segmentAngle = (1 * data[i].value / segmentTotal) * (Math.PI * 2);
|
| - cumulativeAngle += segmentAngle;
|
| - if (config.inGraphDataAnglePosition == 1) posAngle = realCumulativeAngle + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - else if (config.inGraphDataAnglePosition == 2) posAngle = realCumulativeAngle - segmentAngle / 2 + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - else if (config.inGraphDataAnglePosition == 3) posAngle = realCumulativeAngle - segmentAngle + config.inGraphDataPaddingAngle * (Math.PI / 180);
|
| - realCumulativeAngle -= segmentAngle;
|
| - if (typeof(data[i].title) == "string") lgtxt = data[i].title.trim();
|
| - else lgtxt = "";
|
| - var dispString = tmplbis(config.inGraphDataTmpl, {
|
| - config: config,
|
| - v1: fmtChartJS(config, lgtxt, config.fmtV1),
|
| - v2: fmtChartJS(config, 1 * data[i].value, config.fmtV2),
|
| - v3: fmtChartJS(config, cumvalue, config.fmtV3),
|
| - v4: fmtChartJS(config, totvalue, config.fmtV4),
|
| - v5: fmtChartJS(config, segmentAngle, config.fmtV5),
|
| - v6: roundToWithThousands(config, fmtChartJS(config, 100 * data[i].value / totvalue, config.fmtV6), config.roundPct),
|
| - v7: fmtChartJS(config, midPieX, config.fmtV7),
|
| - v8: fmtChartJS(config, midPieY, config.fmtV8),
|
| - v9: fmtChartJS(config, cutoutRadius, config.fmtV9),
|
| - v10: fmtChartJS(config, doughnutRadius, config.fmtV10),
|
| - v11: fmtChartJS(config, cumulativeAngle - segmentAngle, config.fmtV11),
|
| - v12: fmtChartJS(config, cumulativeAngle, config.fmtV12),
|
| - v13: fmtChartJS(config, i, config.fmtV13),
|
| - data: data
|
| - });
|
| - var textMeasurement = ctx.measureText(dispString).width;
|
| - var MaxRadiusX = Math.abs((msr.availableWidth / 2 - textMeasurement) / Math.cos(posAngle)) - config.inGraphDataPaddingRadius - 5;
|
| - if (MaxRadiusX < doughnutRadius) doughnutRadius = MaxRadiusX;
|
| - }
|
| - }
|
| - }
|
| - doughnutRadius = doughnutRadius * config.radiusScale;
|
| - };
|
| - };
|
| - var Line = function(data, config, ctx) {
|
| - var maxSize, scaleHop, scaleHop2, calculatedScale, calculatedScale2, labelHeight, scaleHeight, valueBounds, labelTemplateString, labelTemplateString2;
|
| - var valueHop, widestXLabel, xAxisLength, yAxisPosX, xAxisPosY, rotateLabels = 0,
|
| - msr;
|
| - var zeroY = 0;
|
| - var zeroY2 = 0;
|
| - var offsets = [];
|
| - ctx.tpchart="Line";
|
| - setting_new_chart_vars(ctx);
|
| - if (!dynamicFunction(data, config, ctx)) {
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } }
|
| - return;
|
| - }
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") {
|
| - if(!config.multiGraph) {
|
| - addResponsiveChart(ctx.ChartNewId,ctx,data,config);
|
| - subUpdateChart(ctx,data,config);
|
| - return;
|
| - } else { ctx.firstPass=1; }
|
| - }
|
| -
|
| - // adapt data when length is 1;
|
| - var mxlgt = 0;
|
| - for (var i = 0; i < data.datasets.length; i++) mxlgt = Max([mxlgt, data.datasets[i].data.length]);
|
| - if (mxlgt == 1) {
|
| - if (typeof(data.labels[0]) == "string") data.labels = ["", data.labels[0], ""];
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - if (typeof(data.datasets[i].data[0] != "undefined")) data.datasets[i].data = [undefined, data.datasets[i].data[0], undefined];
|
| - }
|
| - }
|
| -
|
| - if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array();
|
| - else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId);
|
| - defMouse(ctx, data, config);
|
| - setRect(ctx, config);
|
| - msr = setMeasures(data, config, ctx, height, width, "nihil", [""], false, false, true, true, config.datasetFill, "Line");
|
| - valueBounds = getValueBounds();
|
| - // true or fuzzy (error for negativ values (included 0))
|
| - if (config.logarithmic !== false) {
|
| - if (valueBounds.minValue <= 0) {
|
| - config.logarithmic = false;
|
| - }
|
| - }
|
| - if (config.logarithmic2 !== false) {
|
| - if (valueBounds.minValue2 <= 0) {
|
| - config.logarithmic2 = false;
|
| - }
|
| - }
|
| - // Check if logarithmic is meanigful
|
| - var OrderOfMagnitude = calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.maxValue) + 1)) - calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.minValue)));
|
| - if ((config.logarithmic == 'fuzzy' && OrderOfMagnitude < 4) || config.scaleOverride) {
|
| - config.logarithmic = false;
|
| - }
|
| - // Check if logarithmic is meanigful
|
| - var OrderOfMagnitude2 = calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.maxValue2) + 1)) - calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.minValue2)));
|
| - if ((config.logarithmic2 == 'fuzzy' && OrderOfMagnitude2 < 4) || config.scaleOverride2) {
|
| - config.logarithmic2 = false;
|
| - }
|
| - //Check and set the scale
|
| - labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : "";
|
| - labelTemplateString2 = (config.scaleShowLabels2) ? config.scaleLabel2 : "";
|
| - if (!config.scaleOverride) {
|
| - if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) {
|
| - calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString);
|
| - }
|
| - } else {
|
| - calculatedScale = {
|
| - steps: config.scaleSteps,
|
| - stepValue: config.scaleStepWidth,
|
| - graphMin: config.scaleStartValue,
|
| - graphMax: config.scaleStartValue + config.scaleSteps * config.scaleStepWidth,
|
| - labels: []
|
| - }
|
| - populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, config.scaleStartValue, calculatedScale.graphMax, config.scaleStepWidth);
|
| - }
|
| -
|
| - if (valueBounds.dbAxis) {
|
| - if (!config.scaleOverride2) {
|
| - if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) {
|
| - calculatedScale2 = calculateScale(2, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue2, valueBounds.minValue2, labelTemplateString);
|
| - }
|
| - } else {
|
| - calculatedScale2 = {
|
| - steps: config.scaleSteps2,
|
| - stepValue: config.scaleStepWidth2,
|
| - graphMin: config.scaleStartValue2,
|
| - graphMax: config.scaleStartValue2 + config.scaleSteps2 * config.scaleStepWidth2,
|
| - labels: []
|
| - }
|
| - populateLabels(2, config, labelTemplateString2, calculatedScale2.labels, calculatedScale2.steps, config.scaleStartValue2, calculatedScale2.graphMax, config.scaleStepWidth2);
|
| - }
|
| - } else {
|
| - calculatedScale2 = {
|
| - steps: 0,
|
| - stepValue: 0,
|
| - graphMin: 0,
|
| - graphMax: 0,
|
| - labels: null
|
| - }
|
| - }
|
| - if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) {
|
| - msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, calculatedScale2.labels, false, false, true, true, config.datasetFill, "Line");
|
| - var prevHeight=msr.availableHeight;
|
| - msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop;
|
| - msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight;
|
| - scaleHop = Math.floor(msr.availableHeight / calculatedScale.steps);
|
| - scaleHop2 = Math.floor(msr.availableHeight / calculatedScale2.steps);
|
| - valueHop = Math.floor(msr.availableWidth / (data.labels.length - 1));
|
| - if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / (data.labels.length - 1));
|
| - msr.clrwidth = msr.clrwidth - (msr.availableWidth - (data.labels.length - 1) * valueHop);
|
| - msr.availableWidth = (data.labels.length - 1) * valueHop;
|
| - msr.availableHeight = (calculatedScale.steps) * scaleHop;
|
| - msr.xLabelPos+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight));
|
| - msr.clrheight+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight));
|
| - yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft;
|
| - xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop;
|
| - drawLabels();
|
| - if (valueBounds.minValue < 0) {
|
| - zeroY = calculateOffset(config.logarithmic, 0, calculatedScale, scaleHop);
|
| - }
|
| - if (valueBounds.minValue2 < 0) {
|
| - zeroY2 = calculateOffset(config.logarithmic2, 0, calculatedScale2, scaleHop2);
|
| - }
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - offsets[i] = [];
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - if (data.datasets[i].axis == 2) {
|
| - offsets[i][j] = (calculateOffset(config.logarithmic2, data.datasets[i].data[j], calculatedScale2, scaleHop2) - zeroY2);
|
| - } else {
|
| - offsets[i][j] = (calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop) - zeroY);
|
| - }
|
| - }
|
| - }
|
| - animationLoop(config, drawScale, drawLines, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data);
|
| - } else {
|
| - testRedraw(ctx,data,config);
|
| - }
|
| -
|
| -
|
| - function drawLines(animPc) {
|
| - drawLinesDataset(1, animPc, data, config, ctx, offsets, {
|
| - xAxisPosY: xAxisPosY,
|
| - yAxisPosX: yAxisPosX,
|
| - valueHop: valueHop,
|
| - nbValueHop: data.labels.length - 1,
|
| - scaleHop: scaleHop,
|
| - zeroY: zeroY,
|
| - calculatedScale: calculatedScale,
|
| - logarithmic: config.logarithmic
|
| - });
|
| - drawLinesDataset(2, animPc, data, config, ctx, offsets, {
|
| - xAxisPosY: xAxisPosY,
|
| - yAxisPosX: yAxisPosX,
|
| - valueHop: valueHop,
|
| - nbValueHop: data.labels.length - 1,
|
| - scaleHop: scaleHop2,
|
| - zeroY: zeroY2,
|
| - calculatedScale: calculatedScale2,
|
| - logarithmic: config.logarithmic2
|
| - });
|
| -
|
| -
|
| - if (animPc >= 1) {
|
| - if (typeof drawMath == "function") {
|
| - drawMath(ctx, config, data, msr, {
|
| - xAxisPosY: xAxisPosY,
|
| - yAxisPosX: yAxisPosX,
|
| - valueHop: valueHop,
|
| - scaleHop: scaleHop,
|
| - zeroY: zeroY,
|
| - calculatedScale: calculatedScale,
|
| - calculateOffset: calculateOffset
|
| - });
|
| - }
|
| - }
|
| - if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Line");
|
| - };
|
| -
|
| - function drawScale() {
|
| - //X axis line
|
| - // if the xScale should be drawn
|
| - if (config.drawXScaleLine !== false) {
|
| - for (var s = 0; s < config.drawXScaleLine.length; s++) {
|
| - // get special lineWidth and lineColor for this xScaleLine
|
| - ctx.lineWidth = config.drawXScaleLine[s].lineWidth ? config.drawXScaleLine[s].lineWidth : config.scaleLineWidth;
|
| - ctx.strokeStyle = config.drawXScaleLine[s].lineColor ? config.drawXScaleLine[s].lineColor : config.scaleLineColor;
|
| - ctx.beginPath();
|
| - var yPosXScale;
|
| - switch (config.drawXScaleLine[s].position) {
|
| - case "bottom":
|
| - yPosXScale = xAxisPosY;
|
| - break;
|
| - case "top":
|
| - yPosXScale = xAxisPosY - msr.availableHeight - config.scaleTickSizeTop;
|
| - break;
|
| - case "0":
|
| - case 0:
|
| - // check if zero exists
|
| - if (zeroY != 0) {
|
| - yPosXScale = xAxisPosY - zeroY;
|
| - }
|
| - break;
|
| - }
|
| - // draw the scale line
|
| - ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, yPosXScale);
|
| - ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, yPosXScale);
|
| - ctx.stroke();
|
| - }
|
| - }
|
| - for (var i = 0; i < data.labels.length; i++) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom);
|
| - ctx.lineWidth = config.scaleGridLineWidth;
|
| - ctx.strokeStyle = config.scaleGridLineColor;
|
| - //Check i isnt 0, so we dont go over the Y axis twice.
|
| - if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) {
|
| - ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
|
| - } else {
|
| - ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY);
|
| - }
|
| - ctx.stroke();
|
| - }
|
| - //Y axis
|
| - ctx.lineWidth = config.scaleLineWidth;
|
| - ctx.strokeStyle = config.scaleLineColor;
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom);
|
| - ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
|
| - ctx.stroke();
|
| - for (var j = 0; j < calculatedScale.steps; j++) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop));
|
| - ctx.lineWidth = config.scaleGridLineWidth;
|
| - ctx.strokeStyle = config.scaleGridLineColor;
|
| - if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) {
|
| - ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY - ((j + 1) * scaleHop));
|
| - } else {
|
| - ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop));
|
| - }
|
| - ctx.stroke();
|
| - }
|
| - };
|
| -
|
| - function drawLabels() {
|
| - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
|
| - //X Labels
|
| - if (config.xAxisTop || config.xAxisBottom) {
|
| - ctx.textBaseline = "top";
|
| - if (msr.rotateLabels > 90) {
|
| - ctx.save();
|
| - ctx.textAlign = "left";
|
| - } else if (msr.rotateLabels > 0) {
|
| - ctx.save();
|
| - ctx.textAlign = "right";
|
| - } else {
|
| - ctx.textAlign = "center";
|
| - }
|
| - ctx.fillStyle = config.scaleFontColor;
|
| - if (config.xAxisBottom) {
|
| - for (var i = 0; i < data.labels.length; i++) {
|
| - ctx.save();
|
| - if (msr.rotateLabels > 0) {
|
| - ctx.translate(yAxisPosX + i * valueHop - msr.highestXLabel / 2, msr.xLabelPos);
|
| - ctx.rotate(-(msr.rotateLabels * (Math.PI / 180)));
|
| - ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), 0, 0, ctx.textBaseline, config.scaleFontSize);
|
| - } else {
|
| - ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), yAxisPosX + i * valueHop, msr.xLabelPos, ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - ctx.restore();
|
| - }
|
| - }
|
| - }
|
| - //Y Labels
|
| - ctx.textAlign = "right";
|
| - ctx.textBaseline = "middle";
|
| - for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale.steps; j++) {
|
| - if (config.scaleShowLabels) {
|
| - if (config.yAxisLeft) {
|
| - ctx.textAlign = "right";
|
| - ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - if (config.yAxisRight && !valueBounds.dbAxis) {
|
| - ctx.textAlign = "left";
|
| - ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - }
|
| - }
|
| - if (config.yAxisRight && valueBounds.dbAxis) {
|
| - for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale2.steps; j++) {
|
| - if (config.scaleShowLabels) {
|
| - ctx.textAlign = "left";
|
| - ctx.fillTextMultiLine(calculatedScale2.labels[j + 1], yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop2), ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - }
|
| - }
|
| - };
|
| -
|
| - function getValueBounds() {
|
| - var upperValue = Number.MIN_VALUE;
|
| - var lowerValue = Number.MAX_VALUE;
|
| - var upperValue2 = Number.MIN_VALUE;
|
| - var lowerValue2 = Number.MAX_VALUE;
|
| - var secondAxis = false;
|
| - var firstAxis = false;
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - var mathFctName = data.datasets[i].drawMathDeviation;
|
| - var mathValueHeight = 0;
|
| - if (typeof eval(mathFctName) == "function") {
|
| - var parameter = {
|
| - data: data,
|
| - datasetNr: i
|
| - };
|
| - mathValueHeight = window[mathFctName](parameter);
|
| - }
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - if (data.datasets[i].axis == 2) {
|
| - secondAxis = true;
|
| - if (1 * data.datasets[i].data[j] + mathValueHeight > upperValue2) {
|
| - upperValue2 = 1 * data.datasets[i].data[j] + mathValueHeight
|
| - };
|
| - if (1 * data.datasets[i].data[j] - mathValueHeight < lowerValue2) {
|
| - lowerValue2 = 1 * data.datasets[i].data[j] - mathValueHeight
|
| - };
|
| - } else {
|
| - firstAxis = true;
|
| - if (1 * data.datasets[i].data[j] + mathValueHeight > upperValue) {
|
| - upperValue = 1 * data.datasets[i].data[j] + mathValueHeight
|
| - };
|
| - if (1 * data.datasets[i].data[j] - mathValueHeight < lowerValue) {
|
| - lowerValue = 1 * data.datasets[i].data[j] - mathValueHeight
|
| - };
|
| - }
|
| - }
|
| - };
|
| - if (Math.abs(upperValue - lowerValue) < 0.00000001) {
|
| - upperValue = Max([upperValue * 2, 1]);
|
| - lowerValue = 0;
|
| - }
|
| - if (!isNaN(config.graphMin)) lowerValue = config.graphMin;
|
| - if (!isNaN(config.graphMax)) upperValue = config.graphMax;
|
| - if (secondAxis) {
|
| - if (Math.abs(upperValue2 - lowerValue2) < 0.00000001) {
|
| - upperValue2 = Max([upperValue2 * 2, 1]);
|
| - lowerValue2 = 0;
|
| - }
|
| - if (!isNaN(config.graphMin2)) lowerValue2 = config.graphMin2;
|
| - if (!isNaN(config.graphMax2)) upperValue2 = config.graphMax2;
|
| - }
|
| - if (!firstAxis && secondAxis) {
|
| - upperValue = upperValue2;
|
| - lowerValue = lowerValue2;
|
| - }
|
| - labelHeight = config.scaleFontSize;
|
| - scaleHeight = msr.availableHeight;
|
| - var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66)));
|
| - var minSteps = Math.floor((scaleHeight / labelHeight * 0.5));
|
| - return {
|
| - maxValue: upperValue,
|
| - minValue: lowerValue,
|
| - maxValue2: upperValue2,
|
| - minValue2: lowerValue2,
|
| - dbAxis: secondAxis,
|
| - maxSteps: maxSteps,
|
| - minSteps: minSteps
|
| - };
|
| - };
|
| - };
|
| - var StackedBar = function(data, config, ctx) {
|
| - var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, valueHop, widestXLabel, xAxisLength, yAxisPosX, xAxisPosY, barWidth, rotateLabels = 0,
|
| - msr;
|
| - ctx.tpchart="StackedBar";
|
| - setting_new_chart_vars(ctx);
|
| - if (!dynamicFunction(data, config, ctx)) {
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } }
|
| - return;
|
| - }
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") {
|
| - if(!config.multiGraph) {
|
| - addResponsiveChart(ctx.ChartNewId,ctx,data,config);
|
| - subUpdateChart(ctx,data,config);
|
| - return;
|
| - } else { ctx.firstPass=1; }
|
| - }
|
| -
|
| - config.logarithmic = false;
|
| - if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array();
|
| - else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId);
|
| - defMouse(ctx, data, config);
|
| - setRect(ctx, config);
|
| - msr = setMeasures(data, config, ctx, height, width, "nihil", [""], true, false, true, true, true, "StackedBar");
|
| - valueBounds = getValueBounds();
|
| -
|
| - if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) {
|
| - //Check and set the scale
|
| - labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : "";
|
| - if (!config.scaleOverride) {
|
| - calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString);
|
| - msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, true, true, true, "StackedBar");
|
| - } else {
|
| - calculatedScale = {
|
| - steps: config.scaleSteps,
|
| - stepValue: config.scaleStepWidth,
|
| - graphMin: config.scaleStartValue,
|
| - labels: []
|
| - }
|
| - for (var i = 0; i <= calculatedScale.steps; i++) {
|
| - if (labelTemplateString) {
|
| - calculatedScale.labels.push(tmpl(labelTemplateString, {
|
| - value: fmtChartJS(config, 1 * ((config.scaleStartValue + (config.scaleStepWidth * i)).toFixed(getDecimalPlaces(config.scaleStepWidth))), config.fmtYLabel)
|
| - }));
|
| - }
|
| - }
|
| - msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, true, true, true, "StackedBar");
|
| - }
|
| -
|
| - var prevHeight=msr.availableHeight;
|
| -
|
| - msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop;
|
| - msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight;
|
| - scaleHop = Math.floor(msr.availableHeight / calculatedScale.steps);
|
| - valueHop = Math.floor(msr.availableWidth / (data.labels.length));
|
| - if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / data.labels.length);
|
| - msr.clrwidth = msr.clrwidth - (msr.availableWidth - ((data.labels.length) * valueHop));
|
| - msr.availableWidth = (data.labels.length) * valueHop;
|
| - msr.availableHeight = (calculatedScale.steps) * scaleHop;
|
| - msr.xLabelPos+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight));
|
| - msr.clrheight+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight));
|
| -
|
| - yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft;
|
| - xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop;
|
| - barWidth = (valueHop - config.scaleGridLineWidth * 2 - (config.barValueSpacing * 2) - (config.barDatasetSpacing * data.datasets.length - 1) - (config.barStrokeWidth / 2) - 1);
|
| - if(barWidth>=0 && barWidth<=1)barWidth=1;
|
| - if(barWidth<0 && barWidth>=-1)barWidth=-1;
|
| -
|
| - drawLabels();
|
| - animationLoop(config, drawScale, drawBars, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data);
|
| - } else {
|
| - testRedraw(ctx,data,config);
|
| - }
|
| - function drawBars(animPc) {
|
| - ctx.lineWidth = config.barStrokeWidth;
|
| - var tempp = new Array(data.datasets.length);
|
| - var tempn = new Array(data.datasets.length);
|
| - var cumvalue = new Array();
|
| - var totvalue = new Array();
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - cumvalue[j] = 0;
|
| - totvalue[j] = 0;
|
| - }
|
| - }
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++)
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
|
| - totvalue[j] += 1 * data.datasets[i].data[j];
|
| - }
|
| - }
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - if (animPc >= 1) {
|
| - if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim();
|
| - else lgtxt = "";
|
| - }
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - var currentAnimPc = animationCorrection(animPc, data, config, i, j, 1).animVal;
|
| - if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1;
|
| - if (i == 0) {
|
| - tempp[j]=0;
|
| - tempn[j]=0;
|
| - zeroY= calculateOffset(config.logarithmic, 0 , calculatedScale, scaleHop);
|
| - }
|
| - var barOffset = yAxisPosX + config.barValueSpacing + valueHop * j;
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined') && 1*data.datasets[i].data[j] != 0 ) {
|
| - if (1*data.datasets[i].data[j]<0) {
|
| - var botval=tempp[j];
|
| - var topval=tempp[j]+1*data.datasets[i].data[j] ;
|
| - } else {
|
| - var botval=tempn[j];
|
| - var topval=tempn[j]+1*data.datasets[i].data[j] ;
|
| - }
|
| - if(config.animationByDataset) {
|
| - var botBar=xAxisPosY - calculateOffset(config.logarithmic, botval , calculatedScale, scaleHop);
|
| - var topBar=xAxisPosY - calculateOffset(config.logarithmic, topval , calculatedScale, scaleHop);
|
| - topBar=botBar+currentAnimPc*(topBar-botBar);
|
| - } else {
|
| - var botBar=xAxisPosY - calculateOffset(config.logarithmic, currentAnimPc* botval , calculatedScale, scaleHop);
|
| - var topBar=xAxisPosY - calculateOffset(config.logarithmic, currentAnimPc*topval , calculatedScale, scaleHop);
|
| -
|
| - }
|
| - ctx.fillStyle = config.defaultFillColor;
|
| - if (typeof data.datasets[i].fillColor == "function") ctx.fillStyle = data.datasets[i].fillColor("FILLCOLOR", data, config, i, j, currentAnimPc, 1 * data.datasets[i].data[j], "StackedBar", ctx, barOffset, botBar , barOffset + barWidth, topBar);
|
| - else if (typeof(data.datasets[i].fillColor) == "string") {
|
| - ctx.fillStyle = data.datasets[i].fillColor;
|
| - } else if (typeof(data.datasets[i].fillColor) == "object") {
|
| - if (typeof(data.datasets[i].fillColor[0]) == "string") {
|
| - ctx.fillStyle = data.datasets[i].fillColor[Min([data.datasets[i].fillColor.length - 1, j])];
|
| - }
|
| - }
|
| - ctx.strokeStyle = config.defaultStrokeColor;
|
| - if (typeof data.datasets[i].strokeColor == "function") ctx.strokeStyle = data.datasets[i].strokeColor("STROKECOLOR", data, config, i, j, currentAnimPc, 1 * data.datasets[i].data[j], "StackedBar", ctx, barOffset, botBar, barOffset + barwidth, topBar);
|
| - else if (typeof(data.datasets[i].strokeColor) == "string") {
|
| - ctx.strokeStyle = data.datasets[i].strokeColor;
|
| - } else if (typeof(data.datasets[i].strokeColor) == "object") {
|
| - if (typeof(data.datasets[i].strokeColor[0]) == "string") {
|
| - ctx.strokeStyle = data.datasets[i].strokeColor[Min([data.datasets[i].strokeColor.length - 1, j])];
|
| - }
|
| - }
|
| -
|
| - if(currentAnimPc !=0) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(barOffset, botBar);
|
| - ctx.lineTo(barOffset, topBar);
|
| - ctx.lineTo(barOffset + barWidth, topBar);
|
| - ctx.lineTo(barOffset + barWidth, botBar);
|
| - if (config.barShowStroke) ctx.stroke();
|
| - ctx.closePath();
|
| - ctx.fill();
|
| - cumvalue[j] += 1 * data.datasets[i].data[j];
|
| - if (animPc >= 1) {
|
| - if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim();
|
| - else lgtxt2 = "";
|
| -// jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", barOffset, xAxisPosY - yStart[j] + 1, barOffset + barWidth, barheight , lgtxt, lgtxt2, 1 * data.datasets[i].data[j], cumvalue[j], totvalue[j], i, j];
|
| - if (1*data.datasets[i].data[j]<0) {
|
| - jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", barOffset, topBar, barOffset + barWidth, botBar , lgtxt, lgtxt2, 1 * data.datasets[i].data[j], cumvalue[j], totvalue[j], i, j];
|
| - } else {
|
| - jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", barOffset, botBar, barOffset + barWidth, topBar , lgtxt, lgtxt2, 1 * data.datasets[i].data[j], cumvalue[j], totvalue[j], i, j];
|
| - }
|
| - }
|
| - }
|
| - if (1*data.datasets[i].data[j]<0) {
|
| - tempp[j]=tempp[j]+1*data.datasets[i].data[j] ;
|
| - } else {
|
| - tempn[j]=tempn[j]+1*data.datasets[i].data[j] ;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - if (animPc >= 1 && config.inGraphDataShow) {
|
| - var yPos = 0,
|
| - xPos = 0;
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - cumvalue[j] = 0;
|
| - }
|
| - }
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim();
|
| - else lgtxt = "";
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - if (i == 0) {
|
| - tempp[j]=0;
|
| - tempn[j]=0;
|
| - zeroY= calculateOffset(config.logarithmic, 0 , calculatedScale, scaleHop);
|
| - }
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
|
| - if (1*data.datasets[i].data[j]<0) {
|
| - var botval=tempp[j];
|
| - var topval=tempp[j]+1*data.datasets[i].data[j] ;
|
| - } else {
|
| - var botval=tempn[j];
|
| - var topval=tempn[j]+1*data.datasets[i].data[j] ;
|
| - }
|
| - var botBar=xAxisPosY - calculateOffset(config.logarithmic, botval , calculatedScale, scaleHop);
|
| - var topBar=xAxisPosY - calculateOffset(config.logarithmic, topval , calculatedScale, scaleHop);
|
| - ctx.save();
|
| - ctx.textAlign = config.inGraphDataAlign;
|
| - ctx.textBaseline = config.inGraphDataVAlign;
|
| - ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily;
|
| - ctx.fillStyle = config.inGraphDataFontColor;
|
| - if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim();
|
| - else lgtxt2 = "";
|
| - cumvalue[j] += 1 + data.datasets[i].data[j];
|
| - var dispString = tmplbis(config.inGraphDataTmpl, {
|
| - config: config,
|
| - v1: fmtChartJS(config, lgtxt, config.fmtV1),
|
| - v2: fmtChartJS(config, lgtxt2, config.fmtV2),
|
| - v3: fmtChartJS(config, 1 * data.datasets[i].data[j], config.fmtV3),
|
| - v4: fmtChartJS(config, cumvalue[j], config.fmtV4),
|
| - v5: fmtChartJS(config, totvalue[j], config.fmtV5),
|
| - v6: roundToWithThousands(config, fmtChartJS(config, 100 * data.datasets[i].data[j] / totvalue[j], config.fmtV6), config.roundPct),
|
| - v7: fmtChartJS(config, barOffset, config.fmtV7),
|
| - v8: fmtChartJS(config, xAxisPosY, config.fmtV8),
|
| - v9: fmtChartJS(config, barOffset + barWidth, config.fmtV9),
|
| - v10: fmtChartJS(config, xAxisPosY - calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop) + (config.barStrokeWidth / 2), config.fmtV10),
|
| - v11: fmtChartJS(config, i, config.fmtV11),
|
| - v12: fmtChartJS(config, j, config.fmtV12),
|
| - data: data
|
| - });
|
| - var barOffset = yAxisPosX + config.barValueSpacing + valueHop * j;
|
| - ctx.beginPath();
|
| - ctx.beginPath();
|
| - yPos = 0;
|
| - xPos = 0;
|
| - if (config.inGraphDataXPosition == 1) {
|
| - xPos = barOffset + config.inGraphDataPaddingX;
|
| - } else if (config.inGraphDataXPosition == 2) {
|
| - xPos = barOffset + barWidth / 2 + config.inGraphDataPaddingX;
|
| - } else if (config.inGraphDataXPosition == 3) {
|
| - xPos = barOffset + barWidth + config.inGraphDataPaddingX;
|
| - }
|
| - if (config.inGraphDataYPosition == 1) {
|
| - yPos = botBar - config.inGraphDataPaddingY;
|
| - } else if (config.inGraphDataYPosition == 2) {
|
| - yPos = topBar - (botbar-topbar)/2 - config.inGraphDataPaddingY;
|
| - } else if (config.inGraphDataYPosition == 3) {
|
| - yPos = topBar - config.inGraphDataPaddingY;
|
| - }
|
| - if(yPos>msr.topNotUsableSize) {
|
| - ctx.translate(xPos, yPos);
|
| - ctx.rotate(config.inGraphDataRotate * (Math.PI / 180));
|
| - ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize);
|
| - }
|
| - ctx.restore();
|
| - if (1*data.datasets[i].data[j]<0) {
|
| - tempp[j]=tempp[j]+1*data.datasets[i].data[j] ;
|
| - } else {
|
| - tempn[j]=tempn[j]+1*data.datasets[i].data[j] ;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| - if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"StackedBar");
|
| - };
|
| -
|
| - function drawScale() {
|
| - //X axis line
|
| - ctx.lineWidth = config.scaleLineWidth;
|
| - ctx.strokeStyle = config.scaleLineColor;
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY);
|
| - ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY);
|
| - ctx.stroke();
|
| - for (var i = 0; i < data.labels.length; i++) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom);
|
| - ctx.lineWidth = config.scaleGridLineWidth;
|
| - ctx.strokeStyle = config.scaleGridLineColor;
|
| - //Check i isnt 0, so we dont go over the Y axis twice.
|
| - if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) {
|
| - ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
|
| - } else {
|
| - ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY);
|
| - }
|
| - ctx.stroke();
|
| - }
|
| - //Y axis
|
| - ctx.lineWidth = config.scaleLineWidth;
|
| - ctx.strokeStyle = config.scaleLineColor;
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom);
|
| - ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
|
| - ctx.stroke();
|
| - for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale.steps; j++) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop));
|
| - ctx.lineWidth = config.scaleGridLineWidth;
|
| - ctx.strokeStyle = config.scaleGridLineColor;
|
| - if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) {
|
| - ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY - ((j + 1) * scaleHop));
|
| - } else {
|
| - ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop));
|
| - }
|
| - ctx.stroke();
|
| - }
|
| - };
|
| -
|
| - function drawLabels() {
|
| - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
|
| - //X axis labels
|
| - if (config.xAxisTop || config.xAxisBottom) {
|
| - ctx.textBaseline = "top";
|
| - if (msr.rotateLabels > 90) {
|
| - ctx.save();
|
| - ctx.textAlign = "left";
|
| - } else if (msr.rotateLabels > 0) {
|
| - ctx.save();
|
| - ctx.textAlign = "right";
|
| - } else {
|
| - ctx.textAlign = "center";
|
| - }
|
| - ctx.fillStyle = config.scaleFontColor;
|
| - if (config.xAxisBottom) {
|
| - for (var i = 0; i < data.labels.length; i++) {
|
| - ctx.save();
|
| - if (msr.rotateLabels > 0) {
|
| - ctx.translate(yAxisPosX + i * valueHop + (barWidth / 2) - msr.highestXLabel / 2, msr.xLabelPos);
|
| - ctx.rotate(-(msr.rotateLabels * (Math.PI / 180)));
|
| - ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), 0, 0, ctx.textBaseline, config.scaleFontSize);
|
| - } else {
|
| - ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), yAxisPosX + i * valueHop + (barWidth / 2), msr.xLabelPos, ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - ctx.restore();
|
| - }
|
| - }
|
| - }
|
| - //Y axis
|
| - ctx.textAlign = "right";
|
| - ctx.textBaseline = "middle";
|
| - for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale.steps; j++) {
|
| - if (config.scaleShowLabels) {
|
| - if (config.yAxisLeft) {
|
| - ctx.textAlign = "right";
|
| - ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - if (config.yAxisRight) {
|
| - ctx.textAlign = "left";
|
| - ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - }
|
| - }
|
| - };
|
| -
|
| - function getValueBounds() {
|
| - var upperValue = Number.MIN_VALUE;
|
| - var lowerValue = Number.MAX_VALUE;
|
| - var minvl = new Array(data.datasets.length);
|
| - var maxvl = new Array(data.datasets.length);
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - var k = i;
|
| - var tempp = 0;
|
| - var tempn = 0;
|
| - if (!(typeof(data.datasets[0].data[j]) == 'undefined')) {
|
| - if(1 * data.datasets[0].data[j] > 0) {
|
| - tempp += 1 * data.datasets[0].data[j];
|
| - if (tempp > upperValue) {
|
| - upperValue = tempp;
|
| - };
|
| - if (tempp < lowerValue) {
|
| - lowerValue = tempp;
|
| - };
|
| - } else {
|
| - tempn += 1 * data.datasets[0].data[j];
|
| - if (tempn > upperValue) {
|
| - upperValue = tempn;
|
| - };
|
| - if (tempn < lowerValue) {
|
| - lowerValue = tempn;
|
| - };
|
| - }
|
| - }
|
| - while (k > 0) { //get max of stacked data
|
| - if (!(typeof(data.datasets[k].data[j]) == 'undefined')) {
|
| - if(1 * data.datasets[k].data[j] > 0) {
|
| - tempp += 1 * data.datasets[k].data[j];
|
| - if (tempp > upperValue) {
|
| - upperValue = tempp;
|
| - };
|
| - if (tempp < lowerValue) {
|
| - lowerValue = tempp;
|
| - };
|
| - } else {
|
| - tempn += 1 * data.datasets[k].data[j];
|
| - if (tempn > upperValue) {
|
| - upperValue = tempn;
|
| - };
|
| - if (tempn < lowerValue) {
|
| - lowerValue = tempn;
|
| - };
|
| - }
|
| - }
|
| - k--;
|
| - }
|
| - }
|
| - };
|
| - // AJOUT CHANGEMENT
|
| -
|
| - if (!isNaN(config.graphMin)) lowerValue = config.graphMin;
|
| - if (!isNaN(config.graphMax)) upperValue = config.graphMax;
|
| - if (Math.abs(upperValue - lowerValue) < 0.00000001) {
|
| - upperValue = Max([upperValue * 2, 1]);
|
| - lowerValue = 0;
|
| - }
|
| - labelHeight = config.scaleFontSize;
|
| - scaleHeight = msr.availableHeight;
|
| - 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
|
| - };
|
| - };
|
| - };
|
| - /**
|
| - * Reverse the data structure for horizontal charts
|
| - * - reverse labels and every array inside datasets
|
| - * @param {object} data datasets and labels for the chart
|
| - * @return return the reversed data
|
| - */
|
| - function reverseData(data) {
|
| - data.labels = data.labels.reverse();
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var key in data.datasets[i]) {
|
| - if (Array.isArray(data.datasets[i][key])) {
|
| - data.datasets[i][key] = data.datasets[i][key].reverse();
|
| - }
|
| - }
|
| - }
|
| - return data;
|
| - }
|
| - var HorizontalStackedBar = function(data, config, ctx) {
|
| - var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, valueHop, widestXLabel, xAxisLength, yAxisPosX, xAxisPosY, barWidth, rotateLabels = 0,
|
| - msr;
|
| -
|
| - ctx.tpchart="HorizontalStackedBar";
|
| - setting_new_chart_vars(ctx);
|
| -
|
| - if (!dynamicFunction(data, config, ctx)) {
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } }
|
| - return;
|
| - }
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") {
|
| - if(!config.multiGraph) {
|
| - addResponsiveChart(ctx.ChartNewId,ctx,data,config);
|
| - subUpdateChart(ctx,data,config);
|
| - return;
|
| - } else { ctx.firstPass=1; }
|
| - }
|
| -
|
| - if (config.reverseOrder && typeof ctx.reversed == "undefined") {
|
| - ctx.reversed=true;
|
| - data = reverseData(data);
|
| - }
|
| -
|
| -
|
| - config.logarithmic = false;
|
| - if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array();
|
| - else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId);
|
| - defMouse(ctx, data, config);
|
| - setRect(ctx, config);
|
| - msr = setMeasures(data, config, ctx, height, width, "nihil", [""], true, true, true, true, true, "HorizontalStackedBar");
|
| - valueBounds = getValueBounds();
|
| -
|
| - if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) {
|
| - //Check and set the scale
|
| - labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : "";
|
| - if (!config.scaleOverride) {
|
| - calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString);
|
| - msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, true, true, true, true, "HorizontalStackedBar");
|
| - } else {
|
| - calculatedScale = {
|
| - steps: config.scaleSteps,
|
| - stepValue: config.scaleStepWidth,
|
| - graphMin: config.scaleStartValue,
|
| - labels: []
|
| - }
|
| - for (var i = 0; i <= calculatedScale.steps; i++) {
|
| - if (labelTemplateString) {
|
| - calculatedScale.labels.push(tmpl(labelTemplateString, {
|
| - value: fmtChartJS(config, 1 * ((config.scaleStartValue + (config.scaleStepWidth * i)).toFixed(getDecimalPlaces(config.scaleStepWidth))), config.fmtYLabel)
|
| - }));
|
| - }
|
| - }
|
| - msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, true, true, true, true, "HorizontalStackedBar");
|
| - }
|
| - msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop;
|
| - msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight;
|
| - scaleHop = Math.floor(msr.availableHeight / data.labels.length);
|
| - valueHop = Math.floor(msr.availableWidth / (calculatedScale.steps));
|
| - if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / (calculatedScale.steps));
|
| - msr.clrwidth = msr.clrwidth - (msr.availableWidth - (calculatedScale.steps * valueHop));
|
| - msr.availableWidth = (calculatedScale.steps) * valueHop;
|
| - msr.availableHeight = (data.labels.length) * scaleHop;
|
| - yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft;
|
| - xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop;
|
| - barWidth = (scaleHop - config.scaleGridLineWidth * 2 - (config.barValueSpacing * 2) - (config.barDatasetSpacing * data.datasets.length - 1) - (config.barStrokeWidth / 2) - 1);
|
| - if(barWidth>=0 && barWidth<=1)barWidth=1;
|
| - if(barWidth<0 && barWidth>=-1)barWidth=-1;
|
| - drawLabels();
|
| - animationLoop(config, drawScale, drawBars, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data);
|
| - } else {
|
| - testRedraw(ctx,data,config);
|
| - }
|
| - function HorizontalCalculateOffset(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 drawBars(animPc) {
|
| - ctx.lineWidth = config.barStrokeWidth;
|
| - var tempp = new Array(data.datasets.length);
|
| - var tempn = new Array(data.datasets.length);
|
| - var cumvalue = new Array();
|
| - var totvalue = new Array();
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - cumvalue[j] = 0;
|
| - totvalue[j] = 0;
|
| - }
|
| - }
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++)
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
|
| - totvalue[j] += 1 * data.datasets[i].data[j];
|
| - }
|
| - }
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - if (animPc >= 1) {
|
| - if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim();
|
| - else lgtxt = "";
|
| - }
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - var currentAnimPc = animationCorrection(animPc, data, config, i, j, 1).animVal;
|
| - if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1;
|
| - if (i == 0) {
|
| - tempp[j]=0;
|
| - tempn[j]=0;
|
| - zeroY= HorizontalCalculateOffset(0 , calculatedScale, scaleHop);
|
| - }
|
| - var barOffset = xAxisPosY + config.barValueSpacing - scaleHop * (j + 1);
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined') && 1*data.datasets[i].data[j] != 0 ) {
|
| - if (1*data.datasets[i].data[j]<0) {
|
| - var botval=tempp[j];
|
| - var topval=tempp[j]+1*data.datasets[i].data[j] ;
|
| - } else {
|
| - var botval=tempn[j];
|
| - var topval=tempn[j]+1*data.datasets[i].data[j] ;
|
| - }
|
| - if(config.animationByDataset) {
|
| - var botBar=yAxisPosX + HorizontalCalculateOffset(botval , calculatedScale, valueHop);
|
| - var topBar=yAxisPosX + HorizontalCalculateOffset(topval , calculatedScale, valueHop);
|
| - topBar=botBar+currentAnimPc*(topBar-botBar);
|
| - } else {
|
| - var botBar=yAxisPosX + HorizontalCalculateOffset( currentAnimPc* botval , calculatedScale, valueHop);
|
| - var topBar=yAxisPosX + HorizontalCalculateOffset( currentAnimPc*topval , calculatedScale, valueHop);
|
| -
|
| - }
|
| - ctx.fillStyle = config.defaultFillColor;
|
| - if (typeof data.datasets[i].fillColor == "function") ctx.fillStyle = data.datasets[i].fillColor("FILLCOLOR", data, config, i, j, currentAnimPc, 1 * data.datasets[i].data[j], "HorizontalStackedBar", ctx, botBar, barOffset, topBar, barOffset + barWidth);
|
| - else if (typeof(data.datasets[i].fillColor) == "string") {
|
| - ctx.fillStyle = data.datasets[i].fillColor;
|
| - } else if (typeof(data.datasets[i].fillColor) == "object") {
|
| - if (typeof(data.datasets[i].fillColor[0]) == "string") {
|
| - ctx.fillStyle = data.datasets[i].fillColor[Min([data.datasets[i].fillColor.length - 1, j])];
|
| - }
|
| - }
|
| - ctx.strokeStyle = config.defaultStrokeColor;
|
| - if (typeof data.datasets[i].strokeColor == "function") ctx.strokeStyle = data.datasets[i].strokeColor("STROKECOLOR", data, config, i, j, currentAnimPc, 1 * data.datasets[i].data[j], ctx, "HorizontalStackedBar", ctx, botBar, barOffset, topBar, barOffset + barWidth);
|
| - else if (typeof(data.datasets[i].strokeColor) == "string") {
|
| - ctx.strokeStyle = data.datasets[i].strokeColor;
|
| - } else if (typeof(data.datasets[i].strokeColor) == "object") {
|
| - if (typeof(data.datasets[i].strokeColor[0]) == "string") {
|
| - ctx.strokeStyle = data.datasets[i].strokeColor[Min([data.datasets[i].strokeColor.length - 1, j])];
|
| - }
|
| - }
|
| - if(currentAnimPc !=0) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(botBar, barOffset);
|
| - ctx.lineTo(topBar, barOffset);
|
| - ctx.lineTo(topBar, barOffset + barWidth);
|
| - ctx.lineTo(botBar, barOffset + barWidth);
|
| - ctx.lineTo(botBar, barOffset);
|
| - if (config.barShowStroke) ctx.stroke();
|
| - ctx.closePath();
|
| - ctx.fill();
|
| - cumvalue[j] += 1 * data.datasets[i].data[j];
|
| - if (animPc >= 1) {
|
| - if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim();
|
| - else lgtxt2 = "";
|
| - if (1*data.datasets[i].data[j]<0) {
|
| - jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", topBar, barOffset + barWidth, botBar, barOffset, lgtxt, lgtxt2, 1 * data.datasets[i].data[j], cumvalue[j], totvalue[j], i, j];
|
| - } else {
|
| - jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", botBar, barOffset + barWidth, topBar, barOffset, lgtxt, lgtxt2, 1 * data.datasets[i].data[j], cumvalue[j], totvalue[j], i, j];
|
| - }
|
| - }
|
| - }
|
| - if (1*data.datasets[i].data[j]<0) {
|
| - tempp[j]=tempp[j]+1*data.datasets[i].data[j] ;
|
| - } else {
|
| - tempn[j]=tempn[j]+1*data.datasets[i].data[j] ;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - if (animPc >= 1 && config.inGraphDataShow) {
|
| - var yPos = 0,
|
| - xPos = 0;
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - cumvalue[j] = 0;
|
| - }
|
| - }
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim();
|
| - else lgtxt = "";
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - if (i == 0) {
|
| - tempp[j]=0;
|
| - tempn[j]=0;
|
| - zeroY= HorizontalCalculateOffset(0 , calculatedScale, scaleHop);
|
| - }
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
|
| - if (1*data.datasets[i].data[j]<0) {
|
| - var botval=tempp[j];
|
| - var topval=tempp[j]+1*data.datasets[i].data[j] ;
|
| - } else {
|
| - var botval=tempn[j];
|
| - var topval=tempn[j]+1*data.datasets[i].data[j] ;
|
| - }
|
| - var botBar=yAxisPosX + HorizontalCalculateOffset(botval , calculatedScale, valueHop);
|
| - var topBar=yAxisPosX + HorizontalCalculateOffset(topval , calculatedScale, valueHop);
|
| - ctx.save();
|
| - ctx.textAlign = config.inGraphDataAlign;
|
| - ctx.textBaseline = config.inGraphDataVAlign;
|
| - ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily;
|
| - ctx.fillStyle = config.inGraphDataFontColor;
|
| - if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim();
|
| - else lgtxt2 = "";
|
| - var barOffset = xAxisPosY + config.barValueSpacing - scaleHop * (j + 1);
|
| - cumvalue[j] += data.datasets[i].data[j];
|
| - var dispString = tmplbis(config.inGraphDataTmpl, {
|
| - config: config,
|
| - v1: fmtChartJS(config, lgtxt, config.fmtV1),
|
| - v2: fmtChartJS(config, lgtxt2, config.fmtV2),
|
| - v3: fmtChartJS(config, 1 * data.datasets[i].data[j], config.fmtV3),
|
| - v4: fmtChartJS(config, cumvalue[j], config.fmtV4),
|
| - v5: fmtChartJS(config, totvalue[j], config.fmtV5),
|
| - v6: roundToWithThousands(config, fmtChartJS(config, 100 * data.datasets[i].data[j] / totvalue[j], config.fmtV6), config.roundPct),
|
| - v7: fmtChartJS(config, yAxisPosX, config.fmtV7),
|
| - v8: fmtChartJS(config, barOffset + barWidth, config.fmtV8),
|
| - v9: fmtChartJS(config, yAxisPosX + HorizontalCalculateOffset(data.datasets[i].data[j], calculatedScale, valueHop) + (config.barStrokeWidth / 2), config.fmtV9),
|
| - v10: fmtChartJS(config, barOffset, config.fmtV10),
|
| - v11: fmtChartJS(config, i, config.fmtV11),
|
| - v12: fmtChartJS(config, j, config.fmtV12),
|
| - data: data
|
| - });
|
| - ctx.beginPath();
|
| - yPos = 0;
|
| - xPos = 0;
|
| - if (config.inGraphDataXPosition == 1) {
|
| - xPos = botBar + config.inGraphDataPaddingX;
|
| - } else if (config.inGraphDataXPosition == 2) {
|
| - xPos = botBar + (topBar-botBar)/2 + config.inGraphDataPaddingX;
|
| - } else if (config.inGraphDataXPosition == 3) {
|
| - xPos = topBar + config.inGraphDataPaddingX;
|
| - }
|
| - if (config.inGraphDataYPosition == 1) {
|
| - yPos = barOffset + barWidth - config.inGraphDataPaddingY;
|
| - } else if (config.inGraphDataYPosition == 2) {
|
| - yPos = barOffset + barWidth / 2 - config.inGraphDataPaddingY;
|
| - } else if (config.inGraphDataYPosition == 3) {
|
| - yPos = barOffset - config.inGraphDataPaddingY;
|
| - }
|
| - if(xPos<=msr.availableWidth+msr.leftNotUsableSize) {
|
| - ctx.translate(xPos, yPos);
|
| - ctx.rotate(config.inGraphDataRotate * (Math.PI / 180));
|
| - ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize);
|
| - ctx.restore();
|
| - }
|
| - if (1*data.datasets[i].data[j]<0) {
|
| - tempp[j]=tempp[j]+1*data.datasets[i].data[j] ;
|
| - } else {
|
| - tempn[j]=tempn[j]+1*data.datasets[i].data[j] ;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| - if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"HorizontalStackedBar");
|
| - };
|
| -
|
| - function drawScale() {
|
| - //X axis line
|
| - ctx.lineWidth = config.scaleLineWidth;
|
| - ctx.strokeStyle = config.scaleLineColor;
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY);
|
| - ctx.lineTo(yAxisPosX + msr.availableWidth, xAxisPosY);
|
| - ctx.stroke();
|
| - for (var i = ((config.showYAxisMin) ? -1 : 0); i < calculatedScale.steps; i++) {
|
| - if (i >= 0) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom);
|
| - ctx.lineWidth = config.scaleGridLineWidth;
|
| - ctx.strokeStyle = config.scaleGridLineColor;
|
| - //Check i isnt 0, so we dont go over the Y axis twice.
|
| - if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) {
|
| - ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
|
| - } else {
|
| - ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY);
|
| - }
|
| - ctx.stroke();
|
| - }
|
| - }
|
| - //Y axis
|
| - ctx.lineWidth = config.scaleLineWidth;
|
| - ctx.strokeStyle = config.scaleLineColor;
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom);
|
| - ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
|
| - ctx.stroke();
|
| - for (var j = 0; j < data.labels.length; j++) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop));
|
| - ctx.lineWidth = config.scaleGridLineWidth;
|
| - ctx.strokeStyle = config.scaleGridLineColor;
|
| - if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) {
|
| - ctx.lineTo(yAxisPosX + msr.availableWidth, xAxisPosY - ((j + 1) * scaleHop));
|
| - } else {
|
| - ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop));
|
| - }
|
| - ctx.stroke();
|
| - }
|
| - };
|
| -
|
| - function drawLabels() {
|
| - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
|
| - //X axis line
|
| - if (config.scaleShowLabels && (config.xAxisTop || config.xAxisBottom)) {
|
| - ctx.textBaseline = "top";
|
| - if (msr.rotateLabels > 90) {
|
| - ctx.save();
|
| - ctx.textAlign = "left";
|
| - } else if (msr.rotateLabels > 0) {
|
| - ctx.save();
|
| - ctx.textAlign = "right";
|
| - } else {
|
| - ctx.textAlign = "center";
|
| - }
|
| - ctx.fillStyle = config.scaleFontColor;
|
| - if (config.xAxisBottom) {
|
| - for (var i = ((config.showYAxisMin) ? -1 : 0); i < calculatedScale.steps; i++) {
|
| - ctx.save();
|
| - if (msr.rotateLabels > 0) {
|
| - ctx.translate(yAxisPosX + (i + 1) * valueHop - msr.highestXLabel / 2, msr.xLabelPos);
|
| - ctx.rotate(-(msr.rotateLabels * (Math.PI / 180)));
|
| - ctx.fillTextMultiLine(calculatedScale.labels[i + 1], 0, 0, ctx.textBaseline, config.scaleFontSize);
|
| - } else {
|
| - ctx.fillTextMultiLine(calculatedScale.labels[i + 1], yAxisPosX + ((i + 1) * valueHop), msr.xLabelPos, ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - ctx.restore();
|
| - }
|
| - }
|
| - }
|
| - //Y axis
|
| - ctx.textAlign = "right";
|
| - ctx.textBaseline = "middle";
|
| - for (var j = 0; j < data.labels.length; j++) {
|
| - if (config.yAxisLeft) {
|
| - ctx.textAlign = "right";
|
| - ctx.fillTextMultiLine(fmtChartJS(config, data.labels[j], config.fmtXLabel), yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop) + barWidth / 2, ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - if (config.yAxisRight) {
|
| - ctx.textAlign = "left";
|
| - ctx.fillTextMultiLine(fmtChartJS(config, data.labels[j], config.fmtXLabel), yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop) + barWidth / 2, ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - }
|
| - };
|
| -
|
| - function getValueBounds() {
|
| - var upperValue = Number.MIN_VALUE;
|
| - var lowerValue = Number.MAX_VALUE;
|
| - var minvl = new Array(data.datasets.length);
|
| - var maxvl = new Array(data.datasets.length);
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - var k = i;
|
| - var tempp = 0;
|
| - var tempn = 0;
|
| - if (!(typeof(data.datasets[0].data[j]) == 'undefined')) {
|
| - if(1 * data.datasets[0].data[j] > 0) {
|
| - tempp += 1 * data.datasets[0].data[j];
|
| - if (tempp > upperValue) {
|
| - upperValue = tempp;
|
| - };
|
| - if (tempp < lowerValue) {
|
| - lowerValue = tempp;
|
| - };
|
| - } else {
|
| - tempn += 1 * data.datasets[0].data[j];
|
| - if (tempn > upperValue) {
|
| - upperValue = tempn;
|
| - };
|
| - if (tempn < lowerValue) {
|
| - lowerValue = tempn;
|
| - };
|
| - }
|
| - }
|
| - while (k > 0) { //get max of stacked data
|
| - if (!(typeof(data.datasets[k].data[j]) == 'undefined')) {
|
| - if(1 * data.datasets[k].data[j] > 0) {
|
| - tempp += 1 * data.datasets[k].data[j];
|
| - if (tempp > upperValue) {
|
| - upperValue = tempp;
|
| - };
|
| - if (tempp < lowerValue) {
|
| - lowerValue = tempp;
|
| - };
|
| - } else {
|
| - tempn += 1 * data.datasets[k].data[j];
|
| - if (tempn > upperValue) {
|
| - upperValue = tempn;
|
| - };
|
| - if (tempn < lowerValue) {
|
| - lowerValue = tempn;
|
| - };
|
| - }
|
| - }
|
| - k--;
|
| - }
|
| - }
|
| - };
|
| - // AJOUT CHANGEMENT
|
| -
|
| - if (!isNaN(config.graphMin)) lowerValue = config.graphMin;
|
| - if (!isNaN(config.graphMax)) upperValue = config.graphMax;
|
| - if (Math.abs(upperValue - lowerValue) < 0.00000001) {
|
| - upperValue = Max([upperValue * 2, 1]);
|
| - lowerValue = 0;
|
| - }
|
| - labelHeight = config.scaleFontSize;
|
| - scaleHeight = msr.availableHeight;
|
| - 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,
|
| - msr;
|
| - var offsets = [];
|
| -
|
| - ctx.tpchart="Bar";
|
| - setting_new_chart_vars(ctx);
|
| -
|
| - if (!dynamicFunction(data, config, ctx)) {
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } }
|
| - return;
|
| - }
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") {
|
| - if(!config.multiGraph) {
|
| - addResponsiveChart(ctx.ChartNewId,ctx,data,config);
|
| - subUpdateChart(ctx,data,config);
|
| - return;
|
| - } else { ctx.firstPass=1; }
|
| - }
|
| -
|
| - // for BarLineCharts
|
| - var nrOfBars = data.datasets.length;
|
| - var nrOfLines = 0;
|
| - var lineDatasets = [];
|
| - var barDatasets = [];
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - if (data.datasets[i].type == "Line") {
|
| - nrOfLines++;
|
| - lineDatasets.push(i);
|
| - } else {
|
| - barDatasets.push(i);
|
| - }
|
| - }
|
| - // change the order (at first all bars then the lines) (form of BubbleSort)
|
| - var bufferDataset, l = 0;
|
| - for (var i = data.datasets.length - 1; i >= 0; i--) {
|
| - if (lineDatasets.indexOf(i) >= 0) {
|
| - l++;
|
| - for (var b = i; b < data.datasets.length - l; b++) {
|
| - bufferDataset = data.datasets[b + 1];
|
| - data.datasets[b + 1] = data.datasets[b];
|
| - data.datasets[b] = bufferDataset;
|
| - }
|
| - }
|
| - }
|
| - nrOfBars -= nrOfLines;
|
| -
|
| - if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array();
|
| - else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId);
|
| - defMouse(ctx, data, config);
|
| - setRect(ctx, config);
|
| -
|
| - msr = setMeasures(data, config, ctx, height, width, "nihil", [""], true, false, true, true, true, "Bar");
|
| - valueBounds = getValueBounds();
|
| -
|
| - if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) {
|
| -
|
| - // true or fuzzy (error for negativ values (included 0))
|
| - if (config.logarithmic !== false) {
|
| - if (valueBounds.minValue <= 0) {
|
| - config.logarithmic = false;
|
| - }
|
| - }
|
| - // Check if logarithmic is meanigful
|
| - var OrderOfMagnitude = calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.maxValue) + 1)) - calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.minValue)));
|
| - if ((config.logarithmic == 'fuzzy' && OrderOfMagnitude < 4) || config.scaleOverride) {
|
| - config.logarithmic = false;
|
| - }
|
| - //Check and set the scale
|
| - labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : "";
|
| - if (!config.scaleOverride) {
|
| - calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString);
|
| - msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, true, true, true, "Bar");
|
| - } else {
|
| - calculatedScale = {
|
| - steps: config.scaleSteps,
|
| - stepValue: config.scaleStepWidth,
|
| - graphMin: config.scaleStartValue,
|
| - graphMax: config.scaleStartValue + config.scaleSteps * config.scaleStepWidth,
|
| - labels: []
|
| - }
|
| - populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, config.scaleStartValue, calculatedScale.graphMax, config.scaleStepWidth);
|
| - msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, true, true, true, "Bar");
|
| - }
|
| -
|
| - var prevHeight=msr.availableHeight;
|
| -
|
| -
|
| -
|
| - msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop;
|
| - msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight;
|
| - scaleHop = Math.floor(msr.availableHeight / calculatedScale.steps);
|
| - valueHop = Math.floor(msr.availableWidth / (data.labels.length));
|
| - if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / data.labels.length);
|
| - msr.clrwidth = msr.clrwidth - (msr.availableWidth - ((data.labels.length) * valueHop));
|
| - msr.availableWidth = (data.labels.length) * valueHop;
|
| - msr.availableHeight = (calculatedScale.steps) * scaleHop;
|
| - msr.xLabelPos+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight));
|
| - msr.clrheight+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight));
|
| -
|
| - yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft;
|
| - xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop;
|
| - barWidth = (valueHop - config.scaleGridLineWidth * 2 - (config.barValueSpacing * 2) - (config.barDatasetSpacing * nrOfBars - 1) - ((config.barStrokeWidth / 2) * nrOfBars - 1)) / nrOfBars;
|
| - if(barWidth>=0 && barWidth<=1)barWidth=1;
|
| - if(barWidth<0 && barWidth>=-1)barWidth=-1;
|
| - var zeroY = 0;
|
| - if (valueBounds.minValue < 0) {
|
| - var zeroY = calculateOffset(config.logarithmic, 0, calculatedScale, scaleHop);
|
| - }
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - offsets[i] = [];
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - offsets[i][j] = (calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop) - zeroY);
|
| - }
|
| - }
|
| - drawLabels();
|
| - animationLoop(config, drawScale, drawBars, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data);
|
| - } else {
|
| - testRedraw(ctx,data,config);
|
| - }
|
| - function drawBars(animPc) {
|
| - var t1, t2, t3;
|
| - var cumvalue = new Array();
|
| - var totvalue = new Array();
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - cumvalue[j] = 0;
|
| - totvalue[j] = 0;
|
| - }
|
| - }
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
|
| - totvalue[j] += 1 * data.datasets[i].data[j];
|
| - }
|
| - }
|
| - }
|
| - ctx.lineWidth = config.barStrokeWidth;
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - if (data.datasets[i].type == "Line") {
|
| - var lineData = {
|
| - datasets: [],
|
| - labels: data.labels
|
| - };
|
| - lineData.datasets.push(data.datasets[i]);
|
| - lineConfig = mergeChartConfig(config, {
|
| - datasetFill: data.datasets[i].fill
|
| - });
|
| - drawLinesDataset(1, animPc, lineData, lineConfig, ctx, offsets, {
|
| - xAxisPosY: xAxisPosY,
|
| - yAxisPosX: yAxisPosX + config.barValueSpacing +
|
| - (barWidth + config.barDatasetSpacing / 2 + config.barStrokeWidth) * nrOfBars / 2,
|
| - valueHop: valueHop,
|
| - scaleHop: scaleHop,
|
| - nbValueHop: data.labels.length,
|
| - zeroY: zeroY,
|
| - calculatedScale: calculatedScale,
|
| - logarithmic: config.logarithmic
|
| - });
|
| - continue; // next dataset
|
| - }
|
| - if (animPc >= 1) {
|
| - if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim();
|
| - else lgtxt = "";
|
| - }
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - var currentAnimPc = animationCorrection(animPc, data, config, i, j, 1).animVal;
|
| - if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1;
|
| - var barOffset = yAxisPosX + config.barValueSpacing + valueHop * j + barWidth * i + config.barDatasetSpacing * i + config.barStrokeWidth * i;
|
| - var barHeight = currentAnimPc * (calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, scaleHop) - zeroY) + (config.barStrokeWidth / 2);
|
| - ctx.fillStyle = config.defaultFillColor;
|
| - if (typeof data.datasets[i].fillColor == "function") {
|
| - ctx.fillStyle = data.datasets[i].fillColor("FILLCOLOR", data, config, i, j, currentAnimPc, 1 * data.datasets[i].data[j], "Bar", ctx, barOffset, xAxisPosY - zeroY , barOffset + barWidth, xAxisPosY - zeroY - barHeight);
|
| - } else if (typeof(data.datasets[i].fillColor) == "string") {
|
| - ctx.fillStyle = data.datasets[i].fillColor;
|
| - } else if (typeof(data.datasets[i].fillColor) == "object") {
|
| - if (typeof(data.datasets[i].fillColor[0]) == "string") {
|
| - ctx.fillStyle = data.datasets[i].fillColor[Min([data.datasets[i].fillColor.length - 1, j])];
|
| - }
|
| - }
|
| - ctx.strokeStyle = config.defaultStrokeColor;
|
| - if (typeof data.datasets[i].strokeColor == "function") {
|
| - ctx.strokeStyle = data.datasets[i].strokeColor("STROKECOLOR", data, config, i, j, CurrentAnimPc, 1 * data.datasets[i].data[j], "Bar", ctx, barOffset, xAxisPosY - zeroY - barHeight, barOffset + barWidth, xAxisPosY - zeroY);
|
| - } else if (typeof(data.datasets[i].strokeColor) == "string") {
|
| - ctx.strokeStyle = data.datasets[i].strokeColor;
|
| - } else if (typeof(data.datasets[i].strokeColor) == "object") {
|
| - if (typeof(data.datasets[i].strokeColor[0]) == "string") {
|
| - ctx.strokeStyle = data.datasets[i].strokeColor[Min([data.datasets[i].strokeColor.length - 1, j])];
|
| - }
|
| - }
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
|
| - roundRect(ctx, barOffset, xAxisPosY - zeroY, barWidth, barHeight, config.barShowStroke, config.barBorderRadius);
|
| - cumvalue[j] += 1 * data.datasets[i].data[j];
|
| - if (animPc >= 1) {
|
| - if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim();
|
| - else lgtxt2 = "";
|
| - t1 = xAxisPosY - zeroY;
|
| - t2 = xAxisPosY - calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, scaleHop) + (config.barStrokeWidth / 2);
|
| - if (t1 < t2) {
|
| - t3 = t1;
|
| - t1 = t2;
|
| - t2 = t3
|
| - }
|
| - jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", barOffset, t1, barOffset + barWidth, t2, lgtxt, lgtxt2,
|
| - 1 * data.datasets[i].data[j], cumvalue[j], totvalue[j], i, j
|
| - ];
|
| - }
|
| - }
|
| - }
|
| - }
|
| - if (animPc >= 1 && config.inGraphDataShow) {
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - cumvalue[j] = 0;
|
| - }
|
| - }
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim();
|
| - else lgtxt = "";
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - if (data.datasets[i].type == "Line") { // no inGraphDataShow for lines again (is inside drawLinesDataset)
|
| - continue;
|
| - }
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
|
| - if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim();
|
| - ctx.save();
|
| - ctx.textAlign = config.inGraphDataAlign;
|
| - ctx.textBaseline = config.inGraphDataVAlign;
|
| - ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily;
|
| - ctx.fillStyle = config.inGraphDataFontColor;
|
| - var barOffset = yAxisPosX + config.barValueSpacing + valueHop * j + barWidth * i + config.barDatasetSpacing * i + config.barStrokeWidth * i;
|
| - t1 = xAxisPosY - zeroY;
|
| - t2 = xAxisPosY - calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, scaleHop) + (config.barStrokeWidth / 2);
|
| - ctx.beginPath();
|
| - var yPos = 0,
|
| - xPos = 0;
|
| - if (config.inGraphDataXPosition == 1) {
|
| - xPos = barOffset + config.inGraphDataPaddingX;
|
| - } else if (config.inGraphDataXPosition == 2) {
|
| - xPos = barOffset + barWidth / 2 + config.inGraphDataPaddingX;
|
| - } else if (config.inGraphDataXPosition == 3) {
|
| - xPos = barOffset + barWidth + config.inGraphDataPaddingX;
|
| - }
|
| - if (config.inGraphDataYPosition == 1) {
|
| - yPos = xAxisPosY - zeroY - config.inGraphDataPaddingY;
|
| - } else if (config.inGraphDataYPosition == 2) {
|
| - yPos = xAxisPosY - (calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, scaleHop) +
|
| - (config.barStrokeWidth / 2)) / 2 - config.inGraphDataPaddingY;
|
| - } else if (config.inGraphDataYPosition == 3) {
|
| - yPos = xAxisPosY - calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, scaleHop) +
|
| - (config.barStrokeWidth / 2) - config.inGraphDataPaddingY;
|
| - }
|
| - ctx.translate(xPos, yPos);
|
| - cumvalue[j] += 1 * data.datasets[i].data[j];
|
| - var dispString = tmplbis(config.inGraphDataTmpl, {
|
| - config: config,
|
| - v1: fmtChartJS(config, lgtxt, config.fmtV1),
|
| - v2: fmtChartJS(config, lgtxt2, config.fmtV2),
|
| - v3: fmtChartJS(config, 1 * data.datasets[i].data[j], config.fmtV3),
|
| - v4: fmtChartJS(config, cumvalue[j], config.fmtV4),
|
| - v5: fmtChartJS(config, totvalue[j], config.fmtV5),
|
| - v6: roundToWithThousands(config, fmtChartJS(config,
|
| - 100 * data.datasets[i].data[j] / totvalue[j], config.fmtV6), config.roundPct),
|
| - v7: fmtChartJS(config, barOffset, config.fmtV7),
|
| - v8: fmtChartJS(config, t1, config.fmtV8),
|
| - v9: fmtChartJS(config, barOffset + barWidth, config.fmtV9),
|
| - v10: fmtChartJS(config, t2, config.fmtV10),
|
| - v11: fmtChartJS(config, i, config.fmtV11),
|
| - v12: fmtChartJS(config, j, config.fmtV12),
|
| - data: data
|
| - });
|
| - ctx.rotate(config.inGraphDataRotate * (Math.PI / 180));
|
| - ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize);
|
| - ctx.restore();
|
| - }
|
| - }
|
| - }
|
| - }
|
| - if (animPc >= 1) {
|
| - if (typeof drawMath == "function") {
|
| - drawMath(ctx, config, data, msr, {
|
| - xAxisPosY: xAxisPosY,
|
| - yAxisPosX: yAxisPosX,
|
| - valueHop: valueHop,
|
| - scaleHop: scaleHop,
|
| - zeroY: zeroY,
|
| - calculatedScale: calculatedScale,
|
| - calculateOffset: calculateOffset,
|
| - barWidth: barWidth
|
| - });
|
| - }
|
| - }
|
| - if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Bar");
|
| - };
|
| -
|
| - function roundRect(ctx, x, y, w, h, stroke, radius) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(x + radius, y);
|
| - ctx.lineTo(x + w - radius, y);
|
| - ctx.quadraticCurveTo(x + w, y, x + w, y);
|
| - ctx.lineTo(x + w, y - h + radius);
|
| - ctx.quadraticCurveTo(x + w, y - h, x + w - radius, y - h);
|
| - ctx.lineTo(x + radius, y - h);
|
| - ctx.quadraticCurveTo(x, y - h, x, y - h + radius);
|
| - ctx.lineTo(x, y);
|
| - ctx.quadraticCurveTo(x, y, x + radius, y);
|
| - if (stroke) ctx.stroke();
|
| - ctx.closePath();
|
| - ctx.fill();
|
| - };
|
| -
|
| - function drawScale() {
|
| - //X axis line
|
| - ctx.lineWidth = config.scaleLineWidth;
|
| - ctx.strokeStyle = config.scaleLineColor;
|
| - ctx.beginPath();
|
| -
|
| -
|
| - ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY);
|
| - ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY);
|
| - ctx.stroke();
|
| - for (var i = 0; i < data.labels.length; i++) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom);
|
| - ctx.lineWidth = config.scaleGridLineWidth;
|
| - ctx.strokeStyle = config.scaleGridLineColor;
|
| - //Check i isnt 0, so we dont go over the Y axis twice.
|
| - if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) {
|
| - ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
|
| - } else {
|
| - ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY);
|
| - }
|
| - ctx.stroke();
|
| - }
|
| - //Y axis
|
| - ctx.lineWidth = config.scaleLineWidth;
|
| - ctx.strokeStyle = config.scaleLineColor;
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom);
|
| - ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
|
| - ctx.stroke();
|
| - for (var j = 0; j < calculatedScale.steps; j++) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop));
|
| - ctx.lineWidth = config.scaleGridLineWidth;
|
| - ctx.strokeStyle = config.scaleGridLineColor;
|
| - if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) {
|
| - ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY - ((j + 1) * scaleHop));
|
| - } else {
|
| - ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop));
|
| - }
|
| - ctx.stroke();
|
| - }
|
| - };
|
| -
|
| - function drawLabels() {
|
| - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
|
| - //X axis line
|
| - if (config.xAxisTop || config.xAxisBottom) {
|
| - ctx.textBaseline = "top";
|
| - if (msr.rotateLabels > 90) {
|
| - ctx.save();
|
| - ctx.textAlign = "left";
|
| - } else if (msr.rotateLabels > 0) {
|
| - ctx.save();
|
| - ctx.textAlign = "right";
|
| - } else {
|
| - ctx.textAlign = "center";
|
| - }
|
| - ctx.fillStyle = config.scaleFontColor;
|
| - if (config.xAxisBottom) {
|
| - for (var i = 0; i < data.labels.length; i++) {
|
| - ctx.save();
|
| - if (msr.rotateLabels > 0) {
|
| -
|
| - ctx.translate(yAxisPosX + i * valueHop + (valueHop / 2) - msr.highestXLabel / 2, msr.xLabelPos);
|
| - ctx.rotate(-(msr.rotateLabels * (Math.PI / 180)));
|
| - ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), 0, 0, ctx.textBaseline, config.scaleFontSize);
|
| - } else {
|
| - ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), yAxisPosX + i * valueHop + (valueHop / 2), msr.xLabelPos, ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - ctx.restore();
|
| - }
|
| - }
|
| - }
|
| - //Y axis
|
| - ctx.textAlign = "right";
|
| - ctx.textBaseline = "middle";
|
| - for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale.steps; j++) {
|
| - if (config.scaleShowLabels) {
|
| - if (config.yAxisLeft) {
|
| - ctx.textAlign = "right";
|
| - ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - if (config.yAxisRight) {
|
| - ctx.textAlign = "left";
|
| - ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - }
|
| - }
|
| - };
|
| -
|
| - function getValueBounds() {
|
| - var upperValue = Number.MIN_VALUE;
|
| - var lowerValue = Number.MAX_VALUE;
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - var mathFctName = data.datasets[i].drawMathDeviation;
|
| - var mathValueHeight = 0;
|
| - if (typeof eval(mathFctName) == "function") {
|
| - var parameter = {
|
| - data: data,
|
| - datasetNr: i
|
| - };
|
| - mathValueHeight = window[mathFctName](parameter);
|
| - }
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - if (1 * data.datasets[i].data[j] + mathValueHeight > upperValue) {
|
| - upperValue = 1 * data.datasets[i].data[j] + mathValueHeight
|
| - };
|
| - if (1 * data.datasets[i].data[j] - mathValueHeight < lowerValue) {
|
| - lowerValue = 1 * data.datasets[i].data[j] - mathValueHeight
|
| - };
|
| - }
|
| - };
|
| - if (Math.abs(upperValue - lowerValue) < 0.00000001) {
|
| - upperValue = Max([upperValue * 2, 1]);
|
| - lowerValue = 0;
|
| - }
|
| - // AJOUT CHANGEMENT
|
| - if (!isNaN(config.graphMin)) lowerValue = config.graphMin;
|
| - if (!isNaN(config.graphMax)) upperValue = config.graphMax;
|
| - labelHeight = config.scaleFontSize;
|
| - scaleHeight = msr.availableHeight;
|
| - 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 HorizontalBar = function(data, config, ctx) {
|
| - var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, valueHop, widestXLabel, xAxisLength, yAxisPosX, xAxisPosY, barWidth, rotateLabels = 0,
|
| - msr;
|
| - ctx.tpchart="HorizontalBar";
|
| - setting_new_chart_vars(ctx);
|
| -
|
| - if (!dynamicFunction(data, config, ctx)) {
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } }
|
| - return;
|
| - }
|
| - if(config.responsive && typeof ctx.firstPass == "undefined") {
|
| - if(!config.multiGraph) {
|
| - addResponsiveChart(ctx.ChartNewId,ctx,data,config);
|
| - subUpdateChart(ctx,data,config);
|
| - return;
|
| - } else { ctx.firstPass=1; }
|
| - }
|
| -
|
| - if (config.reverseOrder && typeof ctx.reversed == "undefined") {
|
| - ctx.reversed=true;
|
| - data = reverseData(data);
|
| - }
|
| -
|
| - if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array();
|
| - else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId);
|
| -
|
| - defMouse(ctx, data, config);
|
| - setRect(ctx, config);
|
| -
|
| - msr = setMeasures(data, config, ctx, height, width, "nihil", [""], true, true, true, true, true, "StackedBar");
|
| - valueBounds = getValueBounds();
|
| -
|
| - if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) {
|
| - //Check and set the scale
|
| - labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : "";
|
| - if (!config.scaleOverride) {
|
| - calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString);
|
| - msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, true, true, true, true, "HorizontalBar");
|
| - } else {
|
| - calculatedScale = {
|
| - steps: config.scaleSteps,
|
| - stepValue: config.scaleStepWidth,
|
| - graphMin: config.scaleStartValue,
|
| - graphMax: config.scaleStartValue + config.scaleSteps * config.scaleStepWidth,
|
| - labels: []
|
| - }
|
| - populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, config.scaleStartValue, calculatedScale.graphMax, config.scaleStepWidth);
|
| - msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, true, true, true, true, "HorizontalBar");
|
| - }
|
| - msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop;
|
| - msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight;
|
| - scaleHop = Math.floor(msr.availableHeight / data.labels.length);
|
| - valueHop = Math.floor(msr.availableWidth / (calculatedScale.steps));
|
| - if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / calculatedScale.steps);
|
| - msr.clrwidth = msr.clrwidth - (msr.availableWidth - (calculatedScale.steps * valueHop));
|
| - msr.availableWidth = (calculatedScale.steps) * valueHop;
|
| - msr.availableHeight = (data.labels.length) * scaleHop;
|
| - yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft;
|
| - xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop;
|
| - barWidth = (scaleHop - config.scaleGridLineWidth * 2 - (config.barValueSpacing * 2) - (config.barDatasetSpacing * data.datasets.length - 1) - ((config.barStrokeWidth / 2) * data.datasets.length - 1)) / data.datasets.length;
|
| - if(barWidth>=0 && barWidth<=1)barWidth=1;
|
| - if(barWidth<0 && barWidth>=-1)barWidth=-1;
|
| - var zeroY = 0;
|
| - if (valueBounds.minValue < 0) {
|
| - var zeroY = calculateOffset(config.logarithmic, 0, calculatedScale, valueHop);
|
| - }
|
| - drawLabels();
|
| - animationLoop(config, drawScale, drawBars, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data);
|
| - } else {
|
| - testRedraw(ctx,data,config);
|
| - }
|
| -
|
| - function drawBars(animPc) {
|
| - var cumvalue = new Array();
|
| - var totvalue = new Array();
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - cumvalue[j] = 0;
|
| - totvalue[j] = 0;
|
| - }
|
| - }
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++)
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined')) totvalue[j] += 1 * data.datasets[i].data[j];
|
| - }
|
| - ctx.lineWidth = config.barStrokeWidth;
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - if (animPc >= 1) {
|
| - if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim();
|
| - else lgtxt = "";
|
| - }
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - var currentAnimPc = animationCorrection(animPc, data, config, i, j, 1).animVal;
|
| - if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1;
|
| - var barOffset = xAxisPosY + config.barValueSpacing - scaleHop * (j + 1) + barWidth * i + config.barDatasetSpacing * i + config.barStrokeWidth * i;
|
| - var barHeight = currentAnimPc * (calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, valueHop) - zeroY) + (config.barStrokeWidth / 2);
|
| - ctx.fillStyle = config.defaultFillColor;
|
| - if (typeof data.datasets[i].fillColor == "function") ctx.fillStyle = data.datasets[i].fillColor("FILLCOLOR", data, config, i, j, currentAnimPc, 1 * data.datasets[i].data[j], "HorizontalBar", ctx, yAxisPosX+zeroY, barOffset, yAxisPosX + zeroY + barHeight, barOffset + barWidth);
|
| - else if (typeof(data.datasets[i].fillColor) == "string") {
|
| - ctx.fillStyle = data.datasets[i].fillColor;
|
| - } else if (typeof(data.datasets[i].fillColor) == "object") {
|
| - if (typeof(data.datasets[i].fillColor[0]) == "string") {
|
| - ctx.fillStyle = data.datasets[i].fillColor[Min([data.datasets[i].fillColor.length - 1, j])];
|
| - }
|
| - }
|
| - ctx.strokeStyle = config.defaultStrokeColor;
|
| - if (typeof data.datasets[i].strokeColor == "function") ctx.strokeStyle = data.datasets[i].strokeColor("STROKECOLOR", data, config, i, j, currentAnimPc, 1 * data.datasets[i].data[j], "HorizontalBar", ctx, yAxisPosX, barOffset, yAxisPosX + barHeight, barOffset + barWidth);
|
| - else if (typeof(data.datasets[i].strokeColor) == "string") {
|
| - ctx.strokeStyle = data.datasets[i].strokeColor;
|
| - } else if (typeof(data.datasets[i].strokeColor) == "object") {
|
| - if (typeof(data.datasets[i].strokeColor[0]) == "string") {
|
| - ctx.strokeStyle = data.datasets[i].strokeColor[Min([data.datasets[i].strokeColor.length - 1, j])];
|
| - }
|
| - }
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
|
| - roundRect(ctx, barOffset, yAxisPosX+zeroY, barWidth, barHeight, config.barShowStroke, config.barBorderRadius, 0);
|
| - cumvalue[j] += 1 * data.datasets[i].data[j];
|
| - if (animPc >= 1) {
|
| - if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim();
|
| - else lgtxt2 = "";
|
| - t1 = yAxisPosX + zeroY;
|
| - t2 = yAxisPosX + calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, valueHop) + (config.barStrokeWidth / 2)
|
| - if (t1 > t2) {
|
| - t3 = t1;
|
| - t1 = t2;
|
| - t2 = t3
|
| - }
|
| - jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", t1, barOffset + barWidth, t2, barOffset, lgtxt, lgtxt2, 1 * data.datasets[i].data[j], cumvalue[j], totvalue[j], i, j];
|
| - }
|
| - }
|
| - }
|
| - }
|
| - if (animPc >= 1 && config.inGraphDataShow) {
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - cumvalue[j] = 0;
|
| - }
|
| - }
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim();
|
| - else lgtxt = "";
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
|
| - if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim();
|
| - ctx.save();
|
| - ctx.textAlign = config.inGraphDataAlign;
|
| - ctx.textBaseline = config.inGraphDataVAlign;
|
| - ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily;
|
| - ctx.fillStyle = config.inGraphDataFontColor;
|
| - var barOffset = xAxisPosY + config.barValueSpacing - scaleHop * (j + 1) + barWidth * i + config.barDatasetSpacing * i + config.barStrokeWidth * i;
|
| - t1 = yAxisPosX + zeroY;
|
| - t2 = yAxisPosX + calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, valueHop) + (config.barStrokeWidth / 2)
|
| - if (t1 > t2) {
|
| - t3 = t1;
|
| - t1 = t2;
|
| - t2 = t3
|
| - }
|
| - ctx.beginPath();
|
| - var yPos = 0,
|
| - xPos = 0;
|
| - if (config.inGraphDataYPosition == 1) {
|
| - yPos = barOffset - config.inGraphDataPaddingY + barWidth;
|
| - } else if (config.inGraphDataYPosition == 2) {
|
| - yPos = barOffset + barWidth / 2 - config.inGraphDataPaddingY;
|
| - } else if (config.inGraphDataYPosition == 3) {
|
| - yPos = barOffset - config.inGraphDataPaddingY;
|
| - }
|
| - if (config.inGraphDataXPosition == 1) {
|
| - xPos = yAxisPosX + zeroY + config.inGraphDataPaddingX;
|
| - } else if (config.inGraphDataXPosition == 2) {
|
| - xPos = yAxisPosX + (calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, valueHop) + (config.barStrokeWidth / 2)) / 2 + config.inGraphDataPaddingX;
|
| - } else if (config.inGraphDataXPosition == 3) {
|
| - xPos = yAxisPosX + calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, valueHop) + (config.barStrokeWidth / 2) + config.inGraphDataPaddingX;
|
| - }
|
| - ctx.translate(xPos, yPos);
|
| - cumvalue[j] += 1 * data.datasets[i].data[j];
|
| - var dispString = tmplbis(config.inGraphDataTmpl, {
|
| - config: config,
|
| - v1: fmtChartJS(config, lgtxt, config.fmtV1),
|
| - v2: fmtChartJS(config, lgtxt2, config.fmtV2),
|
| - v3: fmtChartJS(config, 1 * data.datasets[i].data[j], config.fmtV3),
|
| - v4: fmtChartJS(config, cumvalue[j], config.fmtV4),
|
| - v5: fmtChartJS(config, totvalue[j], config.fmtV5),
|
| - v6: roundToWithThousands(config, fmtChartJS(config, 100 * data.datasets[i].data[j] / totvalue[j], config.fmtV6), config.roundPct),
|
| - v7: fmtChartJS(config, t1, config.fmtV7),
|
| - v8: fmtChartJS(config, barOffset + barWidth, config.fmtV8),
|
| - v9: fmtChartJS(config, t2, config.fmtV9),
|
| - v10: fmtChartJS(config, barOffset, config.fmtV10),
|
| - v11: fmtChartJS(config, i, config.fmtV11),
|
| - v12: fmtChartJS(config, j, config.fmtV12),
|
| - data: data
|
| - });
|
| - ctx.rotate(config.inGraphDataRotate * (Math.PI / 180));
|
| - ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize);
|
| - ctx.restore();
|
| - }
|
| - }
|
| - }
|
| - }
|
| - if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"HorizontalBar");
|
| - };
|
| -
|
| - function roundRect(ctx, x, y, w, h, stroke, radius, zeroY) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(y + zeroY, x + radius);
|
| - ctx.lineTo(y + zeroY, x + w - radius);
|
| - ctx.quadraticCurveTo(y + zeroY, x + w, y + zeroY, x + w);
|
| - ctx.lineTo(y + h - radius, x + w);
|
| - ctx.quadraticCurveTo(y + h, x + w, y + h, x + w - radius);
|
| - ctx.lineTo(y + h, x + radius);
|
| - ctx.quadraticCurveTo(y + h, x, y + h - radius, x);
|
| - ctx.lineTo(y + zeroY, x);
|
| - ctx.quadraticCurveTo(y + zeroY, x, y + zeroY, x + radius);
|
| - if (stroke) ctx.stroke();
|
| - ctx.closePath();
|
| - ctx.fill();
|
| - };
|
| -
|
| - function drawScale() {
|
| - //X axis line
|
| - ctx.lineWidth = config.scaleLineWidth;
|
| - ctx.strokeStyle = config.scaleLineColor;
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY);
|
| - ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY);
|
| - ctx.stroke();
|
| - for (var i = ((config.showYAxisMin) ? -1 : 0); i < calculatedScale.steps; i++) {
|
| - if (i >= 0) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom);
|
| - ctx.lineWidth = config.scaleGridLineWidth;
|
| - ctx.strokeStyle = config.scaleGridLineColor;
|
| - //Check i isnt 0, so we dont go over the Y axis twice.
|
| - if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) {
|
| - ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
|
| - } else {
|
| - ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY);
|
| - }
|
| - ctx.stroke();
|
| - }
|
| - }
|
| - //Y axis
|
| - ctx.lineWidth = config.scaleLineWidth;
|
| - ctx.strokeStyle = config.scaleLineColor;
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom);
|
| - ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
|
| - ctx.stroke();
|
| - for (var j = 0; j < data.labels.length; j++) {
|
| - ctx.beginPath();
|
| - ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop));
|
| - ctx.lineWidth = config.scaleGridLineWidth;
|
| - ctx.strokeStyle = config.scaleGridLineColor;
|
| - if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) {
|
| - ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY - ((j + 1) * scaleHop));
|
| - } else {
|
| - ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop));
|
| - }
|
| - ctx.stroke();
|
| - }
|
| - };
|
| -
|
| - function drawLabels() {
|
| - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
|
| - //X axis line
|
| - if (config.scaleShowLabels && (config.xAxisTop || config.xAxisBottom)) {
|
| - ctx.textBaseline = "top";
|
| - if (msr.rotateLabels > 90) {
|
| - ctx.save();
|
| - ctx.textAlign = "left";
|
| - } else if (msr.rotateLabels > 0) {
|
| - ctx.save();
|
| - ctx.textAlign = "right";
|
| - } else {
|
| - ctx.textAlign = "center";
|
| - }
|
| - ctx.fillStyle = config.scaleFontColor;
|
| - if (config.xAxisBottom) {
|
| - for (var i = ((config.showYAxisMin) ? -1 : 0); i < calculatedScale.steps; i++) {
|
| - ctx.save();
|
| - if (msr.rotateLabels > 0) {
|
| - ctx.translate(yAxisPosX + (i + 1) * valueHop - msr.highestXLabel / 2, msr.xLabelPos);
|
| - ctx.rotate(-(msr.rotateLabels * (Math.PI / 180)));
|
| - ctx.fillTextMultiLine(calculatedScale.labels[i + 1], 0, 0, ctx.textBaseline, config.scaleFontSize);
|
| - } else {
|
| - ctx.fillTextMultiLine(calculatedScale.labels[i + 1], yAxisPosX + (i + 1) * valueHop, msr.xLabelPos, ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - ctx.restore();
|
| - }
|
| - }
|
| - }
|
| - //Y axis
|
| - ctx.textAlign = "right";
|
| - ctx.textBaseline = "middle";
|
| - for (var j = 0; j < data.labels.length; j++) {
|
| - if (config.yAxisLeft) {
|
| - ctx.textAlign = "right";
|
| - ctx.fillTextMultiLine(fmtChartJS(config, data.labels[j], config.fmtXLabel), yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - (j * scaleHop) - scaleHop / 2, ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - if (config.yAxisRight) {
|
| - ctx.textAlign = "left";
|
| - ctx.fillTextMultiLine(fmtChartJS(config, data.labels[j], config.fmtXLabel), yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - (j * scaleHop) - scaleHop / 2, ctx.textBaseline, config.scaleFontSize);
|
| - }
|
| - }
|
| - };
|
| -
|
| - 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 (1 * data.datasets[i].data[j] > upperValue) {
|
| - upperValue = 1 * data.datasets[i].data[j]
|
| - };
|
| - if (1 * data.datasets[i].data[j] < lowerValue) {
|
| - lowerValue = 1 * data.datasets[i].data[j]
|
| - };
|
| - }
|
| - };
|
| - if (Math.abs(upperValue - lowerValue) < 0.00000001) {
|
| - upperValue = Max([upperValue * 2, 1]);
|
| - lowerValue = 0;
|
| - }
|
| - // AJOUT CHANGEMENT
|
| - if (!isNaN(config.graphMin)) lowerValue = config.graphMin;
|
| - if (!isNaN(config.graphMax)) upperValue = config.graphMax;
|
| -
|
| - labelHeight = config.scaleFontSize;
|
| - scaleHeight = msr.availableHeight;
|
| -
|
| - 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(logarithmic, val, calculatedScale, scaleHop) {
|
| - if (!logarithmic) { // no logarithmic scale
|
| - var outerValue = calculatedScale.steps * calculatedScale.stepValue;
|
| - var adjustedValue = val - calculatedScale.graphMin;
|
| - var scalingFactor = CapValue(adjustedValue / outerValue, 1, 0);
|
| - return (scaleHop * calculatedScale.steps) * scalingFactor;
|
| - } else { // logarithmic scale
|
| - return CapValue(log10(val) * scaleHop - calculateOrderOfMagnitude(calculatedScale.graphMin) * scaleHop, undefined, 0);
|
| - }
|
| - };
|
| -
|
| - function animationLoop(config, drawScale, drawData, ctx, clrx, clry, clrwidth, clrheight, midPosX, midPosY, borderX, borderY, data) {
|
| - var cntiter = 0;
|
| - var animationCount = 1;
|
| - var multAnim = 1;
|
| - if (config.animationStartValue < 0 || config.animationStartValue > 1) config.animation.StartValue = 0;
|
| - if (config.animationStopValue < 0 || config.animationStopValue > 1) config.animation.StopValue = 1;
|
| - if (config.animationStopValue < config.animationStartValue) config.animationStopValue = config.animationStartValue;
|
| - if (isIE() < 9 && isIE() != false) config.animation = false;
|
| - var animFrameAmount = (config.animation) ? 1 / CapValue(config.animationSteps, Number.MAX_VALUE, 1) : 1,
|
| - easingFunction = animationOptions[config.animationEasing],
|
| - percentAnimComplete = (config.animation) ? 0 : 1;
|
| - if (config.animation && config.animationStartValue > 0 && config.animationStartValue <= 1) {
|
| - while (percentAnimComplete < config.animationStartValue) {
|
| - cntiter++;
|
| - percentAnimComplete += animFrameAmount;
|
| - }
|
| - }
|
| - var beginAnim = cntiter;
|
| - var beginAnimPct = percentAnimComplete;
|
| - if (typeof drawScale !== "function") drawScale = function() {};
|
| - if (config.clearRect) requestAnimFrame(animLoop);
|
| - else animLoop();
|
| -
|
| - function animateFrame() {
|
| - var easeAdjustedAnimationPercent = (config.animation) ? CapValue(easingFunction(percentAnimComplete), null, 0) : 1;
|
| - if (1 * cntiter >= 1 * CapValue(config.animationSteps, Number.MAX_VALUE, 1) || config.animation == false || ctx.firstPass==3 || ctx.firstPass==4 || ctx.firstPass==8 || ctx.firstPass==9) easeAdjustedAnimationPercent = 1;
|
| - else if (easeAdjustedAnimationPercent >= 1) easeAdjustedAnimationPercent = 0.9999;
|
| - if (config.animation && !(isIE() < 9 && isIE() != false) && config.clearRect) ctx.clearRect(clrx, clry, clrwidth, clrheight);
|
| - dispCrossImage(ctx, config, midPosX, midPosY, borderX, borderY, false, data, easeAdjustedAnimationPercent, cntiter);
|
| - dispCrossText(ctx, config, midPosX, midPosY, borderX, borderY, false, data, easeAdjustedAnimationPercent, cntiter);
|
| - if (config.scaleOverlay) {
|
| - drawData(easeAdjustedAnimationPercent);
|
| - drawScale();
|
| - } else {
|
| - drawScale();
|
| - drawData(easeAdjustedAnimationPercent);
|
| - }
|
| - dispCrossImage(ctx, config, midPosX, midPosY, borderX, borderY, true, data, easeAdjustedAnimationPercent, cntiter);
|
| - dispCrossText(ctx, config, midPosX, midPosY, borderX, borderY, true, data, easeAdjustedAnimationPercent, cntiter);
|
| - };
|
| -
|
| - function animLoop() {
|
| - //We need to check if the animation is incomplete (less than 1), or complete (1).
|
| - cntiter += multAnim;
|
| - percentAnimComplete += multAnim * animFrameAmount;
|
| - if (cntiter == config.animationSteps || config.animation == false || ctx.firstPass==3 || ctx.firstPass==4 || ctx.firstPass==8 || ctx.firstPass==9) percentAnimComplete = 1;
|
| - else if (percentAnimComplete >= 1) percentAnimComplete = 0.999;
|
| - animateFrame();
|
| - //Stop the loop continuing forever
|
| - if (multAnim == -1 && cntiter <= beginAnim) {
|
| - if (typeof config.onAnimationComplete == "function" && ctx.runanimationcompletefunction==true) config.onAnimationComplete(ctx, config, data, 0, animationCount + 1);
|
| - multAnim = 1;
|
| - requestAnimFrame(animLoop);
|
| - } else if (percentAnimComplete < config.animationStopValue) {
|
| - requestAnimFrame(animLoop);
|
| - } else {
|
| - if ((animationCount < config.animationCount || config.animationCount == 0) && (ctx.firstPass ==1 || ctx.firstPass!=2)) {
|
| - animationCount++;
|
| - if (config.animationBackward && multAnim == 1) {
|
| - percentAnimComplete -= animFrameAmount;
|
| - multAnim = -1;
|
| - } else {
|
| - multAnim = 1;
|
| - cntiter = beginAnim - 1;
|
| - percentAnimComplete = beginAnimPct - animFrameAmount;
|
| - }
|
| - window.setTimeout(animLoop, config.animationPauseTime*1000);
|
| - } else {
|
| - if(!testRedraw(ctx,data,config) ) {
|
| - if (typeof config.onAnimationComplete == "function" && ctx.runanimationcompletefunction==true) {
|
| - config.onAnimationComplete(ctx, config, data, 1, animationCount + 1);
|
| - ctx.runanimationcompletefunction=false;
|
| - }
|
| - }
|
| - }
|
| -
|
| - }
|
| - };
|
| - };
|
| - //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(axis, config, maxSteps, minSteps, maxValue, minValue, labelTemplateString) {
|
| - var graphMin, graphMax, graphRange, stepValue, numberOfSteps, valueRange, rangeOrderOfMagnitude, decimalNum;
|
| - var logarithmic, yAxisMinimumInterval;
|
| - if (axis == 2) {
|
| - logarithmic = config.logarithmic2;
|
| - yAxisMinimumInterval = config.yAxisMinimumInterval2;
|
| - } else {
|
| - logarithmic = config.logarithmic;
|
| - yAxisMinimumInterval = config.yAxisMinimumInterval;
|
| - }
|
| - if (!logarithmic) { // no logarithmic scale
|
| - 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);
|
| - if (typeof yAxisMinimumInterval == "number") {
|
| - graphMin = graphMin - (graphMin % yAxisMinimumInterval);
|
| - while (graphMin > minValue) graphMin = graphMin - yAxisMinimumInterval;
|
| - if (graphMax % yAxisMinimumInterval > 0.0000001 && graphMax % yAxisMinimumInterval < yAxisMinimumInterval - 0.0000001) {
|
| - graphMax = roundScale(config, (1 + Math.floor(graphMax / yAxisMinimumInterval)) * yAxisMinimumInterval);
|
| - }
|
| - while (graphMax < maxValue) graphMax = graphMax + yAxisMinimumInterval;
|
| - }
|
| - } else { // logarithmic scale
|
| - var minMag = calculateOrderOfMagnitude(minValue);
|
| - var maxMag = calculateOrderOfMagnitude(maxValue) + 1;
|
| - graphMin = Math.pow(10, minMag);
|
| - graphMax = Math.pow(10, maxMag);
|
| - rangeOrderOfMagnitude = maxMag - minMag;
|
| - }
|
| - graphRange = graphMax - graphMin;
|
| - stepValue = Math.pow(10, rangeOrderOfMagnitude);
|
| - numberOfSteps = Math.round(graphRange / stepValue);
|
| - if (!logarithmic) { // no logarithmic scale
|
| - //Compare number of steps to the max and min for that size graph, and add in half steps if need be.
|
| - var stopLoop = false;
|
| - while (!stopLoop && (numberOfSteps < minSteps || numberOfSteps > maxSteps)) {
|
| - if (numberOfSteps < minSteps) {
|
| - if (typeof yAxisMinimumInterval == "number") {
|
| - if (stepValue / 2 < yAxisMinimumInterval) stopLoop = true;
|
| - }
|
| - if (!stopLoop) {
|
| - stepValue /= 2;
|
| - numberOfSteps = Math.round(graphRange / stepValue);
|
| - }
|
| - } else {
|
| - stepValue *= 2;
|
| - numberOfSteps = Math.round(graphRange / stepValue);
|
| - }
|
| - }
|
| -
|
| - if (typeof yAxisMinimumInterval == "number") {
|
| - if (stepValue < yAxisMinimumInterval) {
|
| - stepValue = yAxisMinimumInterval;
|
| - numberOfSteps = Math.round(graphRange / stepValue);
|
| - }
|
| - if (stepValue % yAxisMinimumInterval > 0.0000001 && stepValue % yAxisMinimumInterval < yAxisMinimumInterval - 0.0000001) {
|
| - if ((2 * stepValue) % yAxisMinimumInterval < 0.0000001 || (2 * stepValue) % yAxisMinimumInterval > yAxisMinimumInterval - 0.0000001) {
|
| - stepValue = 2 * stepValue;
|
| - numberOfSteps = Math.round(graphRange / stepValue);
|
| - } else {
|
| - stepValue = roundScale(config, (1 + Math.floor(stepValue / yAxisMinimumInterval)) * yAxisMinimumInterval);
|
| - numberOfSteps = Math.round(graphRange / stepValue);
|
| - }
|
| - }
|
| - }
|
| - } else { // logarithmic scale
|
| - numberOfSteps = rangeOrderOfMagnitude; // so scale is 10,100,1000,...
|
| - }
|
| - var labels = [];
|
| - populateLabels(1, config, labelTemplateString, labels, numberOfSteps, graphMin, graphMax, stepValue);
|
| - return {
|
| - steps: numberOfSteps,
|
| - stepValue: stepValue,
|
| - graphMin: graphMin,
|
| - labels: labels,
|
| - maxValue: maxValue
|
| - }
|
| - };
|
| -
|
| - function calculateScaleOld(config, maxSteps, minSteps, maxValue, minValue, labelTemplateString) {
|
| - var graphMin, graphMax, graphRange, stepValue, numberOfSteps, valueRange, rangeOrderOfMagnitude, decimalNum;
|
| - if (!config.logarithmic) { // no logarithmic scale
|
| - 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);
|
| - if (typeof config.yAxisMinimumInterval == "number") {
|
| - graphMin = graphMin - (graphMin % config.yAxisMinimumInterval);
|
| - while (graphMin > minValue) graphMin = graphMin - config.yAxisMinimumInterval;
|
| - if (graphMax % config.yAxisMinimumInterval > 0.0000001 && graphMax % config.yAxisMinimumInterval < config.yAxisMinimumInterval - 0.0000001) {
|
| - graphMax = roundScale(config, (1 + Math.floor(graphMax / config.yAxisMinimumInterval)) * config.yAxisMinimumInterval);
|
| - }
|
| - while (graphMax < maxValue) graphMax = graphMax + config.yAxisMinimumInterval;
|
| - }
|
| - } else { // logarithmic scale
|
| - var minMag = calculateOrderOfMagnitude(minValue);
|
| - var maxMag = calculateOrderOfMagnitude(maxValue) + 1;
|
| - graphMin = Math.pow(10, minMag);
|
| - graphMax = Math.pow(10, maxMag);
|
| - rangeOrderOfMagnitude = maxMag - minMag;
|
| - }
|
| - graphRange = graphMax - graphMin;
|
| - stepValue = Math.pow(10, rangeOrderOfMagnitude);
|
| - numberOfSteps = Math.round(graphRange / stepValue);
|
| - if (!config.logarithmic) { // no logarithmic scale
|
| - //Compare number of steps to the max and min for that size graph, and add in half steps if need be.
|
| - var stopLoop = false;
|
| - while (!stopLoop && (numberOfSteps < minSteps || numberOfSteps > maxSteps)) {
|
| - if (numberOfSteps < minSteps) {
|
| - if (typeof config.yAxisMinimumInterval == "number") {
|
| - if (stepValue / 2 < config.yAxisMinimumInterval) stopLoop = true;
|
| - }
|
| - if (!stopLoop) {
|
| - stepValue /= 2;
|
| - numberOfSteps = Math.round(graphRange / stepValue);
|
| - }
|
| - } else {
|
| - stepValue *= 2;
|
| - numberOfSteps = Math.round(graphRange / stepValue);
|
| - }
|
| - }
|
| - if (typeof config.yAxisMinimumInterval == "number") {
|
| - if (stepValue < config.yAxisMinimumInterval) {
|
| - stepValue = config.yAxisMinimumInterval;
|
| - numberOfSteps = Math.round(graphRange / stepValue);
|
| - }
|
| - if (stepValue % config.yAxisMinimumInterval > 0.0000001 && stepValue % config.yAxisMinimumInterval < config.yAxisMinimumInterval - 0.0000001) {
|
| - if ((2 * stepValue) % config.yAxisMinimumInterval < 0.0000001 || (2 * stepValue) % config.yAxisMinimumInterval > config.yAxisMinimumInterval - 0.0000001) {
|
| - stepValue = 2 * stepValue;
|
| - numberOfSteps = Math.round(graphRange / stepValue);
|
| - } else {
|
| - stepValue = roundScale(config, (1 + Math.floor(stepValue / config.yAxisMinimumInterval)) * config.yAxisMinimumInterval);
|
| - numberOfSteps = Math.round(graphRange / stepValue);
|
| - }
|
| - }
|
| - }
|
| - } else { // logarithmic scale
|
| - numberOfSteps = rangeOrderOfMagnitude; // so scale is 10,100,1000,...
|
| - }
|
| - var labels = [];
|
| - populateLabels(1, config, labelTemplateString, labels, numberOfSteps, graphMin, graphMax, stepValue);
|
| - return {
|
| - steps: numberOfSteps,
|
| - stepValue: stepValue,
|
| - graphMin: graphMin,
|
| - labels: labels,
|
| - maxValue: maxValue
|
| - }
|
| - };
|
| -
|
| - function roundScale(config, value) {
|
| - var scldec = 0;
|
| - var sscl = "" + config.yAxisMinimumInterval;
|
| - if (sscl.indexOf(".") > 0) {
|
| - scldec = sscl.substr(sscl.indexOf(".")).length;
|
| - }
|
| - return (Math.round(value * Math.pow(10, scldec)) / Math.pow(10, scldec));
|
| - }
|
| -
|
| - function calculateOrderOfMagnitude(val) {
|
| - return Math.floor(Math.log(val) / Math.LN10);
|
| - };
|
| - //Populate an array of all the labels by interpolating the string.
|
| - function populateLabels(axis, config, labelTemplateString, labels, numberOfSteps, graphMin, graphMax, stepValue) {
|
| - var logarithmic;
|
| - if (axis == 2) {
|
| - logarithmic = config.logarithmic2;
|
| - fmtYLabel = config.fmtYLabel2;
|
| - } else {
|
| - logarithmic = config.logarithmic;
|
| - fmtYLabel = config.fmtYLabel;
|
| - }
|
| - if (labelTemplateString) {
|
| - //Fix floating point errors by setting to fixed the on the same decimal as the stepValue.
|
| - if (!logarithmic) { // no logarithmic scale
|
| - for (var i = 0; i < numberOfSteps + 1; i++) {
|
| - labels.push(tmpl(labelTemplateString, {
|
| - value: fmtChartJS(config, 1 * ((graphMin + (stepValue * i)).toFixed(getDecimalPlaces(stepValue))), fmtYLabel)
|
| - }));
|
| - }
|
| - } else { // logarithmic scale 10,100,1000,...
|
| - var value = graphMin;
|
| - for (var i = 0; i < numberOfSteps + 1; i++) {
|
| - labels.push(tmpl(labelTemplateString, {
|
| - value: fmtChartJS(config, 1 * value.toFixed(getDecimalPlaces(value)), fmtYLabel)
|
| - }));
|
| - value *= 10;
|
| - }
|
| - }
|
| - }
|
| - };
|
| - //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;
|
| - }
|
| - };
|
| - //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;
|
| - };
|
| -
|
| - function dispCrossText(ctx, config, posX, posY, borderX, borderY, overlay, data, animPC, cntiter) {
|
| - var i, disptxt, txtposx, txtposy, textAlign, textBaseline;
|
| - for (i = 0; i < config.crossText.length; i++) {
|
| - if (config.crossText[i] != "" && config.crossTextOverlay[Min([i, config.crossTextOverlay.length - 1])] == overlay && ((cntiter == 1 && config.crossTextIter[Min([i, config.crossTextIter.length - 1])] == "first") || config.crossTextIter[Min([i, config.crossTextIter.length - 1])] == cntiter || config.crossTextIter[Min([i, config.crossTextIter.length - 1])] == "all" || (animPC == 1 && config.crossTextIter[Min([i, config.crossTextIter.length - 1])] == "last"))) {
|
| - ctx.save();
|
| - ctx.beginPath();
|
| - ctx.font = config.crossTextFontStyle[Min([i, config.crossTextFontStyle.length - 1])] + " " + config.crossTextFontSize[Min([i, config.crossTextFontSize.length - 1])] + "px " + config.crossTextFontFamily[Min([i, config.crossTextFontFamily.length - 1])];
|
| - ctx.fillStyle = config.crossTextFontColor[Min([i, config.crossTextFontColor.length - 1])];
|
| - textAlign = config.crossTextAlign[Min([i, config.crossTextAlign.length - 1])];
|
| - textBaseline = config.crossTextBaseline[Min([i, config.crossTextBaseline.length - 1])];
|
| - txtposx = 1 * config.crossTextPosX[Min([i, config.crossTextPosX.length - 1])];
|
| - txtposy = 1 * config.crossTextPosY[Min([i, config.crossTextPosY.length - 1])];
|
| - switch (1 * config.crossTextRelativePosX[Min([i, config.crossTextRelativePosX.length - 1])]) {
|
| - case 0:
|
| - if (textAlign == "default") textAlign = "left";
|
| - break;
|
| - case 1:
|
| - txtposx += borderX;
|
| - if (textAlign == "default") textAlign = "right";
|
| - break;
|
| - case 2:
|
| - txtposx += posX;
|
| - if (textAlign == "default") textAlign = "center";
|
| - break;
|
| - case -2:
|
| - txtposx += context.canvas.width / 2;
|
| - if (textAlign == "default") textAlign = "center";
|
| - break;
|
| - case 3:
|
| - txtposx += txtposx + 2 * posX - borderX;
|
| - if (textAlign == "default") textAlign = "left";
|
| - break;
|
| - case 4:
|
| - // posX=width;
|
| - txtposx += context.canvas.width;
|
| - if (textAlign == "default") textAlign = "right";
|
| - break;
|
| - default:
|
| - txtposx += posX;
|
| - if (textAlign == "default") textAlign = "center";
|
| - break;
|
| - }
|
| - switch (1 * config.crossTextRelativePosY[Min([i, config.crossTextRelativePosY.length - 1])]) {
|
| - case 0:
|
| - if (textBaseline == "default") textBaseline = "top";
|
| - break;
|
| - case 3:
|
| - txtposy += borderY;
|
| - if (textBaseline == "default") textBaseline = "top";
|
| - break;
|
| - case 2:
|
| - txtposy += posY;
|
| - if (textBaseline == "default") textBaseline = "middle";
|
| - break;
|
| - case -2:
|
| - txtposy += context.canvas.height / 2;
|
| - if (textBaseline == "default") textBaseline = "middle";
|
| - break;
|
| - case 1:
|
| - txtposy += txtposy + 2 * posY - borderY;
|
| - if (textBaseline == "default") textBaseline = "bottom";
|
| - break;
|
| - case 4:
|
| - txtposy += context.canvas.height;
|
| - if (textBaseline == "default") textBaseline = "bottom";
|
| - break;
|
| - default:
|
| - txtposy += posY;
|
| - if (textBaseline == "default") textBaseline = "middle";
|
| - break;
|
| - }
|
| - ctx.textAlign = textAlign;
|
| - ctx.textBaseline = textBaseline;
|
| - ctx.translate(1 * txtposx, 1 * txtposy);
|
| - ctx.rotate(Math.PI * config.crossTextAngle[Min([i, config.crossTextAngle.length - 1])] / 180);
|
| - if (config.crossText[i].substring(0, 1) == "%") {
|
| - if (typeof config.crossTextFunction == "function") disptxt = config.crossTextFunction(i, config.crossText[i], ctx, config, posX, posY, borderX, borderY, overlay, data, animPC);
|
| - } else disptxt = config.crossText[i];
|
| - ctx.fillTextMultiLine(disptxt, 0, 0, ctx.textBaseline, config.crossTextFontSize[Min([i, config.crossTextFontSize.length - 1])]);
|
| - ctx.stroke();
|
| - ctx.restore();
|
| - }
|
| - }
|
| - };
|
| -
|
| - function dispCrossImage(ctx, config, posX, posY, borderX, borderY, overlay, data, animPC, cntiter) {
|
| - var i, disptxt, imageposx, imageposy, imageAlign, imageBaseline;
|
| - for (i = 0; i < config.crossImage.length; i++) {
|
| - if (typeof config.crossImage[i] != "undefined" && config.crossImageOverlay[Min([i, config.crossImageOverlay.length - 1])] == overlay && ((cntiter == -1 && config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == "background") || (cntiter == 1 && config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == "first") || config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == cntiter || (cntiter != -1 && config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == "all") || (animPC == 1 && config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == "last"))) {
|
| - ctx.save();
|
| - ctx.beginPath();
|
| - imageAlign = config.crossImageAlign[Min([i, config.crossImageAlign.length - 1])];
|
| - imageBaseline = config.crossImageBaseline[Min([i, config.crossImageBaseline.length - 1])];
|
| - imageposx = 1 * config.crossImagePosX[Min([i, config.crossImagePosX.length - 1])];
|
| - imageposy = 1 * config.crossImagePosY[Min([i, config.crossImagePosY.length - 1])];
|
| - switch (1 * config.crossImageRelativePosX[Min([i, config.crossImageRelativePosX.length - 1])]) {
|
| - case 0:
|
| - if (imageAlign == "default") imageAlign = "left";
|
| - break;
|
| - case 1:
|
| - imageposx += borderX;
|
| - if (imageAlign == "default") imageAlign = "right";
|
| - break;
|
| - case 2:
|
| - imageposx += posX;
|
| - if (imageAlign == "default") imageAlign = "center";
|
| - break;
|
| - case -2:
|
| - imageposx += context.canvas.width / 2;
|
| - if (imageAlign == "default") imageAlign = "center";
|
| - break;
|
| - case 3:
|
| - imageposx += imageposx + 2 * posX - borderX;
|
| - if (imageAlign == "default") imageAlign = "left";
|
| - break;
|
| - case 4:
|
| - // posX=width;
|
| - imageposx += context.canvas.width;
|
| - if (imageAlign == "default") imageAlign = "right";
|
| - break;
|
| - default:
|
| - imageposx += posX;
|
| - if (imageAlign == "default") imageAlign = "center";
|
| - break;
|
| - }
|
| - switch (1 * config.crossImageRelativePosY[Min([i, config.crossImageRelativePosY.length - 1])]) {
|
| - case 0:
|
| - if (imageBaseline == "default") imageBaseline = "top";
|
| - break;
|
| - case 3:
|
| - imageposy += borderY;
|
| - if (imageBaseline == "default") imageBaseline = "top";
|
| - break;
|
| - case 2:
|
| - imageposy += posY;
|
| - if (imageBaseline == "default") imageBaseline = "middle";
|
| - break;
|
| - case -2:
|
| - imageposy += context.canvas.height / 2;
|
| - if (imageBaseline == "default") imageBaseline = "middle";
|
| - break;
|
| - case 1:
|
| - imageposy += imageposy + 2 * posY - borderY;
|
| - if (imageBaseline == "default") imageBaseline = "bottom";
|
| - break;
|
| - case 4:
|
| - imageposy += context.canvas.height;
|
| - if (imageBaseline == "default") imageBaseline = "bottom";
|
| - break;
|
| - default:
|
| - imageposy += posY;
|
| - if (imageBaseline == "default") imageBaseline = "middle";
|
| - break;
|
| - }
|
| - var imageWidth = config.crossImage[i].width;
|
| - switch (imageAlign) {
|
| - case "left":
|
| - break;
|
| - case "right":
|
| - imageposx -= imageWidth;
|
| - break;
|
| - case "center":
|
| - imageposx -= (imageWidth / 2);
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| - var imageHeight = config.crossImage[i].height;
|
| - switch (imageBaseline) {
|
| - case "top":
|
| - break;
|
| - case "bottom":
|
| - imageposy -= imageHeight;
|
| - break;
|
| - case "middle":
|
| - imageposy -= (imageHeight / 2);
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| - ctx.translate(1 * imageposx, 1 * imageposy);
|
| - ctx.rotate(Math.PI * config.crossImageAngle[Min([i, config.crossImageAngle.length - 1])] / 180);
|
| - ctx.drawImage(config.crossImage[i], 0, 0);
|
| - // ctx.stroke();
|
| - ctx.restore();
|
| - }
|
| - }
|
| - };
|
| - //****************************************************************************************
|
| - function setMeasures(data, config, ctx, height, width, ylabels, ylabels2, reverseLegend, reverseAxis, drawAxis, drawLegendOnData, legendBox, typegraph) {
|
| - if (config.canvasBackgroundColor != "none") ctx.canvas.style.background = config.canvasBackgroundColor;
|
| - var borderWidth = 0;
|
| - var xAxisLabelPos = 0;
|
| - var graphTitleHeight = 0;
|
| - var graphTitlePosY = 0;
|
| - var graphSubTitleHeight = 0;
|
| - var graphSubTitlePosY = 0;
|
| - var footNoteHeight = 0;
|
| - var footNotePosY = 0;
|
| - var yAxisUnitHeight = 0;
|
| - var yAxisUnitPosY = 0;
|
| - var widestLegend = 0;
|
| - var nbeltLegend = 0;
|
| - var nbLegendLines = 0;
|
| - var nbLegendCols = 0;
|
| - var spaceLegendHeight = 0;
|
| - var xFirstLegendTextPos = 0;
|
| - var yFirstLegendTextPos = 0;
|
| - var xLegendBorderPos = 0;
|
| - var yLegendBorderPos = 0;
|
| - var yAxisLabelWidth = 0;
|
| - var yAxisLabelPosLeft = 0;
|
| - var yAxisLabelPosRight = 0;
|
| - var xAxisLabelHeight = 0;
|
| - var xLabelHeight = 0;
|
| - var widestXLabel = 1;
|
| - var highestXLabel = 1;
|
| - var widestYLabel = 0;
|
| - var highestYLabel = 1;
|
| - var widestYLabel2 = 0;
|
| - var highestYLabel2 = 1;
|
| - var leftNotUsableSize = 0;
|
| - var rightNotUsableSize = 0;
|
| - var rotateLabels = 0;
|
| - var xLabelPos = 0;
|
| - var legendBorderWidth = 0;
|
| - var legendBorderHeight = 0;
|
| -
|
| - ctx.widthAtSetMeasures=width;
|
| - ctx.heightAtSetMeasures=height;
|
| -
|
| - // Borders
|
| - if (config.canvasBorders) borderWidth = config.canvasBordersWidth;
|
| - // compute widest X label
|
| - if (drawAxis) {
|
| - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
|
| - for (var i = 0; i < data.labels.length; i++) {
|
| - var textMsr = ctx.measureTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), config.scaleFontSize);
|
| - //If the text length is longer - make that equal to longest text!
|
| - widestXLabel = (textMsr.textWidth > widestXLabel) ? textMsr.textWidth : widestXLabel;
|
| - highestXLabel = (textMsr.textHeight > highestXLabel) ? textMsr.textHeight : highestXLabel;
|
| - }
|
| - if (widestXLabel < config.xScaleLabelsMinimumWidth) {
|
| - widestXLabel = config.xScaleLabelsMinimumWidth;
|
| - }
|
| - }
|
| - // compute Y Label Width
|
| - if (drawAxis) {
|
| - widestYLabel = 1;
|
| - if (ylabels != null && ylabels != "nihil") {
|
| - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
|
| - for (var i = ylabels.length - 1; i >= 0; i--) {
|
| - if (typeof(ylabels[i]) == "string") {
|
| - if (ylabels[i].trim() != "") {
|
| - var textMsr = ctx.measureTextMultiLine(fmtChartJS(config, ylabels[i], config.fmtYLabel), config.scaleFontSize);
|
| - //If the text length is longer - make that equal to longest text!
|
| - widestYLabel = (textMsr.textWidth > widestYLabel) ? textMsr.textWidth : widestYLabel;
|
| - highestYLabel = (textMsr.textHeight > highestYLabel) ? textMsr.textHeight : highestYLabel;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - if (widestYLabel < config.yScaleLabelsMinimumWidth) {
|
| - widestYLabel = config.yScaleLabelsMinimumWidth;
|
| - }
|
| - widestYLabel2 = 1;
|
| - if (ylabels2 != null && config.yAxisRight) {
|
| - ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
|
| - for (var i = ylabels2.length - 1; i >= 0; i--) {
|
| - if (typeof(ylabels2[i]) == "string") {
|
| - if (ylabels2[i].trim() != "") {
|
| - var textMsr = ctx.measureTextMultiLine(fmtChartJS(config, ylabels2[i], config.fmtYLabel2), config.scaleFontSize);
|
| - //If the text length is longer - make that equal to longest text!
|
| - widestYLabel2 = (textMsr.textWidth > widestYLabel2) ? textMsr.textWidth : widestYLabel2;
|
| - highestYLabel2 = (textMsr.textHeight > highestYLabel2) ? textMsr.textHeight : highestYLabel2;
|
| - }
|
| - }
|
| - }
|
| - } else {
|
| - widestYLabel2 = widestYLabel;
|
| - }
|
| - if (widestYLabel2 < config.yScaleLabelsMinimumWidth) {
|
| - widestYLabel2 = config.yScaleLabelsMinimumWidth;
|
| - }
|
| - }
|
| - // yAxisLabel
|
| - leftNotUsableSize = borderWidth + config.spaceLeft
|
| - rightNotUsableSize = borderWidth + config.spaceRight;
|
| - if (drawAxis) {
|
| - if (typeof(config.yAxisLabel) != "undefined") {
|
| - if (config.yAxisLabel.trim() != "") {
|
| - yAxisLabelWidth = (config.yAxisFontSize + config.yAxisLabelSpaceLeft + config.yAxisLabelSpaceRight);
|
| - yAxisLabelPosLeft = borderWidth + config.spaceLeft + config.yAxisLabelSpaceLeft + config.yAxisFontSize;
|
| - yAxisLabelPosRight = width - borderWidth - config.spaceRight - config.yAxisLabelSpaceLeft - config.yAxisFontSize;
|
| - }
|
| - }
|
| - if (config.yAxisLeft) {
|
| - if (reverseAxis == false) leftNotUsableSize = borderWidth + config.spaceLeft + yAxisLabelWidth + widestYLabel + config.yAxisSpaceLeft + config.yAxisSpaceRight;
|
| - else leftNotUsableSize = borderWidth + config.spaceLeft + yAxisLabelWidth + widestXLabel + config.yAxisSpaceLeft + config.yAxisSpaceRight;
|
| - }
|
| - if (config.yAxisRight) {
|
| - if (reverseAxis == false) rightNotUsableSize = borderWidth + config.spaceRight + yAxisLabelWidth + widestYLabel2 + config.yAxisSpaceLeft + config.yAxisSpaceRight;
|
| - else rightNotUsableSize = borderWidth + config.spaceRight + yAxisLabelWidth + widestXLabel + config.yAxisSpaceLeft + config.yAxisSpaceRight;
|
| - }
|
| - }
|
| - availableWidth = width - leftNotUsableSize - rightNotUsableSize;
|
| - // Title
|
| - if (config.graphTitle.trim() != "") {
|
| - graphTitleHeight = (config.graphTitleFontSize + config.graphTitleSpaceBefore + config.graphTitleSpaceAfter);
|
| - graphTitlePosY = borderWidth + config.spaceTop + graphTitleHeight - config.graphTitleSpaceAfter;
|
| - }
|
| - // subTitle
|
| - if (config.graphSubTitle.trim() != "") {
|
| - graphSubTitleHeight = (config.graphSubTitleFontSize + config.graphSubTitleSpaceBefore + config.graphSubTitleSpaceAfter);
|
| - graphSubTitlePosY = borderWidth + config.spaceTop + graphTitleHeight + graphSubTitleHeight - config.graphSubTitleSpaceAfter;
|
| - }
|
| - // yAxisUnit
|
| - if (drawAxis) {
|
| - if (config.yAxisUnit.trim() != "") {
|
| - yAxisUnitHeight = (config.yAxisUnitFontSize + config.yAxisUnitSpaceBefore + config.yAxisUnitSpaceAfter);
|
| - yAxisUnitPosY = borderWidth + config.spaceTop + graphTitleHeight + graphSubTitleHeight + yAxisUnitHeight - config.yAxisUnitSpaceAfter;
|
| - }
|
| - }
|
| - topNotUsableSize = borderWidth + config.spaceTop + graphTitleHeight + graphSubTitleHeight + yAxisUnitHeight + config.graphSpaceBefore;
|
| - // footNote
|
| - if (typeof(config.footNote) != "undefined") {
|
| - if (config.footNote.trim() != "") {
|
| - footNoteHeight = (config.footNoteFontSize + config.footNoteSpaceBefore + config.footNoteSpaceAfter);
|
| - footNotePosY = height - config.spaceBottom - borderWidth - config.footNoteSpaceAfter;
|
| - }
|
| - }
|
| -
|
| - // xAxisLabel
|
| - if (drawAxis) {
|
| - if (typeof(config.xAxisLabel) != "undefined") {
|
| - if (config.xAxisLabel.trim() != "") {
|
| - xAxisLabelHeight = (config.xAxisFontSize + config.xAxisLabelSpaceBefore + config.xAxisLabelSpaceAfter);
|
| - xAxisLabelPos = height - borderWidth - config.spaceBottom - footNoteHeight - config.xAxisLabelSpaceAfter;
|
| - }
|
| - }
|
| - }
|
| -
|
| - bottomNotUsableHeightWithoutXLabels = borderWidth + config.spaceBottom + footNoteHeight + xAxisLabelHeight + config.graphSpaceAfter;
|
| -
|
| - // compute space for Legend
|
| - if (typeof(config.legend) != "undefined") {
|
| - if (config.legend == true) {
|
| - ctx.font = config.legendFontStyle + " " + config.legendFontSize + "px " + config.legendFontFamily;
|
| - if (drawLegendOnData) {
|
| - for (var i = data.datasets.length - 1; i >= 0; i--) {
|
| - if (typeof(data.datasets[i].title) == "string") {
|
| - if (data.datasets[i].title.trim() != "") {
|
| - nbeltLegend++;
|
| - var textLength = ctx.measureText(fmtChartJS(config, data.datasets[i].title, config.fmtLegend)).width;
|
| - //If the text length is longer - make that equal to longest text!
|
| - widestLegend = (textLength > widestLegend) ? textLength : widestLegend;
|
| - }
|
| - }
|
| - }
|
| - } else {
|
| - for (var i = data.length - 1; i >= 0; i--) {
|
| - if (typeof(data[i].title) == "string") {
|
| - if (data[i].title.trim() != "") {
|
| - nbeltLegend++;
|
| - var textLength = ctx.measureText(fmtChartJS(config, data[i].title, config.fmtLegend)).width;
|
| - //If the text length is longer - make that equal to longest text!
|
| - widestLegend = (textLength > widestLegend) ? textLength : widestLegend;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - if (nbeltLegend > 1 || (nbeltLegend == 1 && config.showSingleLegend)) {
|
| - widestLegend += config.legendBlockSize + config.legendSpaceBetweenBoxAndText;
|
| - if(config.legendPosY==1 || config.legendPosY==2 || config.legendPosY==3) {
|
| - availableLegendWidth = availableWidth- config.legendSpaceLeftText - config.legendSpaceRightText;
|
| - } else {
|
| - availableLegendWidth = width - config.spaceLeft - config.spaceRight - 2 * (borderWidth) - config.legendSpaceLeftText - config.legendSpaceRightText;
|
| - }
|
| - if (config.legendBorders == true) availableLegendWidth -= 2 * (config.legendBordersWidth) - config.legendBordersSpaceLeft - config.legendBordersSpaceRight;
|
| - maxLegendOnLine = Min([Math.floor((availableLegendWidth + config.legendSpaceBetweenTextHorizontal) / (widestLegend + config.legendSpaceBetweenTextHorizontal)),config.maxLegendCols]);
|
| - nbLegendLines = Math.ceil(nbeltLegend / maxLegendOnLine);
|
| - nbLegendCols = Math.ceil(nbeltLegend / nbLegendLines);
|
| -
|
| - var legendHeight = nbLegendLines * (config.legendFontSize + config.legendSpaceBetweenTextVertical) - config.legendSpaceBetweenTextVertical + config.legendSpaceBeforeText + config.legendSpaceAfterText;
|
| - if (config.legendBorders == true) {
|
| -// legendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
|
| - }
|
| -
|
| - switch (config.legendPosY) {
|
| - case 0:
|
| - xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
|
| - spaceLegendHeight = legendHeight;
|
| - if (config.legendBorders == true) {
|
| - yLegendBorderPos = topNotUsableSize + config.legendBordersSpaceBefore + (config.legendBordersWidth/2);
|
| - yFirstLegendTextPos = yLegendBorderPos + (config.legendBordersWidth/2) + config.legendSpaceBeforeText+config.legendFontSize;
|
| - spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
|
| - xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
|
| - legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
|
| - legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
|
| - } else {
|
| - yFirstLegendTextPos = topNotUsableSize + config.legendBordersSpaceBefore + (config.legendBordersWidth/2);
|
| - }
|
| - if(yAxisUnitHeight>0) {
|
| - yAxisUnitPosY+=spaceLegendHeight;
|
| - if(config.legendBorders==true)yLegendBorderPos-=yAxisUnitHeight;
|
| - yFirstLegendTextPos-=yAxisUnitHeight;
|
| - }
|
| - topNotUsableSize += spaceLegendHeight;
|
| - break;
|
| - case 1:
|
| - spaceLegendHeight = legendHeight;
|
| - xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
|
| - yFirstLegendTextPos = topNotUsableSize + config.legendSpaceBeforeText+config.legendFontSize;
|
| - if (config.legendBorders == true) {
|
| - yFirstLegendTextPos += config.legendBordersSpaceBefore+config.legendBordersWidth;
|
| - yLegendBorderPos = yFirstLegendTextPos - config.legendSpaceBeforeText - config.legendFontSize - (config.legendBordersWidth /2 );
|
| - spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
|
| - xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
|
| - legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
|
| - legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
|
| - }
|
| - break;
|
| - case 2:
|
| - spaceLegendHeight = legendHeight;
|
| - xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
|
| - yFirstLegendTextPos = topNotUsableSize + (height - topNotUsableSize - bottomNotUsableHeightWithoutXLabels - spaceLegendHeight) /2 + config.legendSpaceBeforeText+config.legendFontSize;
|
| - if (config.legendBorders == true) {
|
| - yFirstLegendTextPos += config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
|
| - yLegendBorderPos = yFirstLegendTextPos - config.legendSpaceBeforeText - config.legendFontSize - (config.legendBordersWidth /2 );
|
| - spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
|
| - xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
|
| - legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
|
| - legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
|
| - }
|
| - break;
|
| - case 3:
|
| - spaceLegendHeight = legendHeight;
|
| - xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
|
| - availableHeight = height - topNotUsableSize - bottomNotUsableHeightWithoutXLabels;
|
| - yFirstLegendTextPos = topNotUsableSize + availableHeight - spaceLegendHeight + config.legendSpaceBeforeText+config.legendFontSize;
|
| - if (config.legendBorders == true) {
|
| - yFirstLegendTextPos -= (config.legendBordersSpaceAfter+config.legendBordersWidth);
|
| - yLegendBorderPos = yFirstLegendTextPos - config.legendSpaceBeforeText - config.legendFontSize - (config.legendBordersWidth /2 );
|
| - spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
|
| - xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
|
| - legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
|
| - legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
|
| - }
|
| - break;
|
| - default:
|
| - spaceLegendHeight = legendHeight;
|
| - yFirstLegendTextPos = height - borderWidth - config.spaceBottom - footNoteHeight - spaceLegendHeight + config.legendSpaceBeforeText + config.legendFontSize;
|
| - xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
|
| - if (config.legendBorders == true) {
|
| - spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
|
| - yFirstLegendTextPos -= (config.legendBordersWidth + config.legendBordersSpaceAfter);
|
| - yLegendBorderPos = Math.floor(height - borderWidth - config.spaceBottom - footNoteHeight - spaceLegendHeight + (config.legendBordersWidth / 2) + config.legendBordersSpaceBefore);
|
| - xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
|
| - legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
|
| - legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
|
| - }
|
| - xAxisLabelPos -= spaceLegendHeight;
|
| -// xLabelPos -= spaceLegendHeight;
|
| - bottomNotUsableHeightWithoutXLabels +=spaceLegendHeight;
|
| - break;
|
| - }
|
| - var fullLegendWidth=config.legendSpaceRightText + nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) - config.legendSpaceBetweenTextHorizontal +config.legendSpaceLeftText;
|
| - if (config.legendBorders == true) {
|
| - fullLegendWidth+=2*config.legendBordersWidth+config.legendBordersSpaceLeft+config.legendBordersSpaceRight;
|
| - }
|
| -
|
| - switch (config.legendPosX) {
|
| - case 0:
|
| - xFirstLegendTextPos = config.spaceLeft + config.canvasBorders * config.canvasBordersWidth + config.legendSpaceLeftText;
|
| - if (config.legendBorders == true) {
|
| - xFirstLegendTextPos += config.legendBordersWidth+config.legendBordersSpaceLeft;
|
| - xLegendBorderPos = config.spaceLeft + config.canvasBorders * config.canvasBordersWidth + config.legendBordersSpaceLeft;
|
| - }
|
| - if(config.legendPosY>=1 && config.legendPosY <=3) {
|
| - leftNotUsableSize+=fullLegendWidth;
|
| - yAxisLabelPosLeft+=fullLegendWidth;
|
| - }
|
| - break;
|
| - case 1:
|
| - xFirstLegendTextPos = leftNotUsableSize + config.legendSpaceLeftText;
|
| - if (config.legendBorders == true) {
|
| - xLegendBorderPos = xFirstLegendTextPos;
|
| - xFirstLegendTextPos += config.legendBordersWidth+config.legendBordersSpaceLeft;
|
| - }
|
| - break;
|
| - case 2:
|
| - xFirstLegendTextPos = leftNotUsableSize + (width - rightNotUsableSize - leftNotUsableSize)/2 - (config.legendSpaceLeftText-config.legendSpaceRightText) - (nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) - config.legendSpaceBetweenTextHorizontal) / 2;
|
| - if (config.legendBorders == true) {
|
| - xFirstLegendTextPos -= (config.legendBordersWidth + config.legendBordersSpaceRight);
|
| - xLegendBorderPos = xFirstLegendTextPos - config.legendBordersWidth/2 - config.legendSpaceLeftText ;
|
| - }
|
| - break;
|
| - case 3:
|
| -
|
| - xFirstLegendTextPos = width - rightNotUsableSize - config.legendSpaceRightText - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal / 2;
|
| - if (config.legendBorders == true) {
|
| - xFirstLegendTextPos -= (config.legendBordersWidth + config.legendBordersSpaceRight);
|
| - xLegendBorderPos = xFirstLegendTextPos - config.legendBordersWidth/2 - config.legendSpaceLeftText ;
|
| - }
|
| - break;
|
| - case 4:
|
| - xFirstLegendTextPos = width - config.spaceRight - config.canvasBorders * config.canvasBordersWidth - config.legendSpaceRightText - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal / 2;
|
| - if (config.legendBorders == true) {
|
| - xFirstLegendTextPos -= (config.legendBordersWidth+config.legendBordersSpaceRight);
|
| - xLegendBorderPos = xFirstLegendTextPos - config.legendBordersSpaceLeft - config.legendBordersWidth/2;
|
| - }
|
| - if(config.legendPosY>=1 && config.legendPosY <=3) {
|
| - rightNotUsableSize+=fullLegendWidth;
|
| - yAxisLabelPosRight-=fullLegendWidth;
|
| - }
|
| - break;
|
| -
|
| - default:
|
| - break;
|
| - }
|
| - if(config.legendBorders==true) {
|
| - yLegendBorderPos+=config.legendYPadding;
|
| - xLegendBorderPos+=config.legendXPadding;
|
| -
|
| - }
|
| - yFirstLegendTextPos+=config.legendYPadding;
|
| - xFirstLegendTextPos+=config.legendXPadding;
|
| -
|
| - }
|
| - }
|
| - }
|
| - xLabelWidth = 0;
|
| - bottomNotUsableHeightWithXLabels = bottomNotUsableHeightWithoutXLabels;
|
| - if (drawAxis && (config.xAxisBottom || config.xAxisTop)) {
|
| - if (reverseAxis == false) {
|
| - var widestLabel = widestXLabel;
|
| - var highestLabel = highestXLabel;
|
| - nblab = data.labels.length;
|
| - } else {
|
| - var widestLabel = widestYLabel;
|
| - var highestLabel = highestYLabel;
|
| - nblab = ylabels.length;
|
| - }
|
| - if (config.rotateLabels == "smart") {
|
| - rotateLabels = 0;
|
| - if ((availableWidth + config.xAxisSpaceBetweenLabels) / nblab < (widestLabel + config.xAxisSpaceBetweenLabels)) {
|
| - rotateLabels = 45;
|
| - if (availableWidth / nblab < Math.abs(Math.cos(rotateLabels * Math.PI / 180) * widestLabel)) {
|
| - rotateLabels = 90;
|
| - }
|
| - }
|
| - } else {
|
| - rotateLabels = config.rotateLabels
|
| - if (rotateLabels < 0) rotateLabels = 0;
|
| - if (rotateLabels > 180) rotateLabels = 180;
|
| - }
|
| - if (rotateLabels > 90) rotateLabels += 180;
|
| - xLabelHeight = Math.abs(Math.sin(rotateLabels * Math.PI / 180) * widestLabel) + Math.abs(Math.sin((rotateLabels + 90) * Math.PI / 180) * highestLabel) + config.xAxisSpaceBefore + config.xAxisSpaceAfter;
|
| - xLabelPos = height - borderWidth - config.spaceBottom - footNoteHeight - xAxisLabelHeight - (xLabelHeight - config.xAxisSpaceBefore) - config.graphSpaceAfter;
|
| - xLabelWidth = Math.abs(Math.cos(rotateLabels * Math.PI / 180) * widestLabel) + Math.abs(Math.cos((rotateLabels + 90) * Math.PI / 180) * highestLabel);
|
| - leftNotUsableSize = Max([leftNotUsableSize, borderWidth + config.spaceLeft + xLabelWidth / 2]);
|
| - rightNotUsableSize = Max([rightNotUsableSize, borderWidth + config.spaceRight + xLabelWidth / 2]);
|
| - availableWidth = width - leftNotUsableSize - rightNotUsableSize;
|
| - if (config.legend && config.xAxisBottom && config.legendPosY==4) {
|
| - xLabelPos-=spaceLegendHeight;
|
| - }
|
| - bottomNotUsableHeightWithXLabels = bottomNotUsableHeightWithoutXLabels + xLabelHeight ;
|
| - } else {
|
| - availableWidth = width - leftNotUsableSize - rightNotUsableSize;
|
| - }
|
| -
|
| - availableHeight = height - topNotUsableSize - bottomNotUsableHeightWithXLabels;
|
| -
|
| - // ----------------------- DRAW EXTERNAL ELEMENTS -------------------------------------------------
|
| - dispCrossImage(ctx, config, width / 2, height / 2, width / 2, height / 2, false, data, -1, -1);
|
| - if (ylabels != "nihil") {
|
| - // Draw Borders
|
| - if (borderWidth > 0) {
|
| - ctx.save();
|
| - ctx.beginPath();
|
| - ctx.lineWidth = 2 * borderWidth;
|
| - ctx.strokeStyle = config.canvasBordersColor;
|
| - ctx.moveTo(0, 0);
|
| - ctx.lineTo(0, height);
|
| - ctx.lineTo(width, height);
|
| - ctx.lineTo(width, 0);
|
| - ctx.lineTo(0, 0);
|
| - ctx.stroke();
|
| - ctx.restore();
|
| - }
|
| - // Draw Graph Title
|
| - if (graphTitleHeight > 0) {
|
| - ctx.save();
|
| - ctx.beginPath();
|
| - ctx.font = config.graphTitleFontStyle + " " + config.graphTitleFontSize + "px " + config.graphTitleFontFamily;
|
| - ctx.fillStyle = config.graphTitleFontColor;
|
| - ctx.textAlign = "center";
|
| - ctx.textBaseline = "bottom";
|
| - ctx.translate(config.spaceLeft + (width - config.spaceLeft - config.spaceRight) / 2, graphTitlePosY);
|
| - ctx.fillText(config.graphTitle, 0, 0);
|
| - ctx.stroke();
|
| - ctx.restore();
|
| - }
|
| - // Draw Graph Sub-Title
|
| - if (graphSubTitleHeight > 0) {
|
| - ctx.save();
|
| - ctx.beginPath();
|
| - ctx.font = config.graphSubTitleFontStyle + " " + config.graphSubTitleFontSize + "px " + config.graphSubTitleFontFamily;
|
| - ctx.fillStyle = config.graphSubTitleFontColor;
|
| - ctx.textAlign = "center";
|
| - ctx.textBaseline = "bottom";
|
| - ctx.translate(config.spaceLeft + (width - config.spaceLeft - config.spaceRight) / 2, graphSubTitlePosY);
|
| - ctx.fillText(config.graphSubTitle, 0, 0);
|
| - ctx.stroke();
|
| - ctx.restore();
|
| - }
|
| - // Draw Y Axis Unit
|
| - if (yAxisUnitHeight > 0) {
|
| - if (config.yAxisLeft) {
|
| - ctx.save();
|
| - ctx.beginPath();
|
| - ctx.font = config.yAxisUnitFontStyle + " " + config.yAxisUnitFontSize + "px " + config.yAxisUnitFontFamily;
|
| - ctx.fillStyle = config.yAxisUnitFontColor;
|
| - ctx.textAlign = "center";
|
| - ctx.textBaseline = "bottom";
|
| - ctx.translate(leftNotUsableSize, yAxisUnitPosY);
|
| - ctx.fillText(config.yAxisUnit, 0, 0);
|
| - ctx.stroke();
|
| - ctx.restore();
|
| - }
|
| - if (config.yAxisRight) {
|
| - if (config.yAxisUnit2 == '') config.yAxisUnit2 = config.yAxisUnit;
|
| - ctx.save();
|
| - ctx.beginPath();
|
| - ctx.font = config.yAxisUnitFontStyle + " " + config.yAxisUnitFontSize + "px " + config.yAxisUnitFontFamily;
|
| - ctx.fillStyle = config.yAxisUnitFontColor;
|
| - ctx.textAlign = "center";
|
| - ctx.textBaseline = "bottom";
|
| - ctx.translate(width - rightNotUsableSize, yAxisUnitPosY);
|
| - ctx.fillText(config.yAxisUnit2, 0, 0);
|
| - ctx.stroke();
|
| - ctx.restore();
|
| - }
|
| - }
|
| - // Draw Y Axis Label
|
| - if (yAxisLabelWidth > 0) {
|
| - if (config.yAxisLeft) {
|
| - ctx.save();
|
| - ctx.beginPath();
|
| - ctx.font = config.yAxisFontStyle + " " + config.yAxisFontSize + "px " + config.yAxisFontFamily;
|
| - ctx.fillStyle = config.yAxisFontColor;
|
| - ctx.textAlign = "center";
|
| - ctx.textBaseline = "bottom";
|
| - ctx.translate(yAxisLabelPosLeft, topNotUsableSize + (availableHeight / 2));
|
| - ctx.rotate(-(90 * (Math.PI / 180)));
|
| - ctx.fillText(config.yAxisLabel, 0, 0);
|
| - ctx.stroke();
|
| - ctx.restore();
|
| - }
|
| - if (config.yAxisRight) {
|
| - if (config.yAxisLabel2 == '') config.yAxisLabel2 = config.yAxisLabel;
|
| - ctx.save();
|
| - ctx.beginPath();
|
| - ctx.font = config.yAxisFontStyle + " " + config.yAxisFontSize + "px " + config.yAxisFontFamily;
|
| - ctx.fillStyle = config.yAxisFontColor;
|
| - ctx.textAlign = "center";
|
| - ctx.textBaseline = "bottom";
|
| - ctx.translate(yAxisLabelPosRight, topNotUsableSize + (availableHeight / 2));
|
| - ctx.rotate(+(90 * (Math.PI / 180)));
|
| - ctx.fillText(config.yAxisLabel2, 0, 0);
|
| - ctx.stroke();
|
| - ctx.restore();
|
| - }
|
| - }
|
| - // Draw X Axis Label
|
| - if (xAxisLabelHeight > 0) {
|
| - if (config.xAxisBottom) {
|
| - ctx.save();
|
| - ctx.beginPath();
|
| - ctx.font = config.xAxisFontStyle + " " + config.xAxisFontSize + "px " + config.xAxisFontFamily;
|
| - ctx.fillStyle = config.xAxisFontColor;
|
| - ctx.textAlign = "center";
|
| - ctx.textBaseline = "bottom";
|
| - ctx.translate(leftNotUsableSize + (availableWidth / 2), xAxisLabelPos);
|
| - ctx.fillText(config.xAxisLabel, 0, 0);
|
| - ctx.stroke();
|
| - ctx.restore();
|
| - }
|
| - }
|
| - // Draw Legend
|
| -
|
| - if (nbeltLegend > 1 || (nbeltLegend == 1 && config.showSingleLegend)) {
|
| - var legendMsr={dispLegend : true, xLegendBorderPos : xLegendBorderPos,
|
| - yLegendBorderPos : yLegendBorderPos, legendBorderWidth : legendBorderWidth, legendBorderHeight : legendBorderHeight,
|
| - nbLegendCols: nbLegendCols, xFirstLegendTextPos : xFirstLegendTextPos , yFirstLegendTextPos : yFirstLegendTextPos,
|
| - drawLegendOnData : drawLegendOnData, reverseLegend : reverseLegend, legendBox : legendBox, widestLegend : widestLegend };
|
| - if(config.legendPosY==0 || config.legendPosY==4) {
|
| - drawLegend(legendMsr,data,config,ctx,typegraph);
|
| - var legendMsr={dispLegend : false};
|
| - }
|
| - } else {
|
| - var legendMsr={dispLegend : false };
|
| - }
|
| - // Draw FootNote
|
| - if (config.footNote.trim() != "") {
|
| - ctx.save();
|
| - ctx.font = config.footNoteFontStyle + " " + config.footNoteFontSize + "px " + config.footNoteFontFamily;
|
| - ctx.fillStyle = config.footNoteFontColor;
|
| - ctx.textAlign = "center";
|
| - ctx.textBaseline = "bottom";
|
| - ctx.translate(leftNotUsableSize + (availableWidth / 2), footNotePosY);
|
| - ctx.fillText(config.footNote, 0, 0);
|
| - ctx.stroke();
|
| - ctx.restore();
|
| - }
|
| - }
|
| - clrx = leftNotUsableSize;
|
| - clrwidth = availableWidth;
|
| - clry = topNotUsableSize;
|
| - clrheight = availableHeight;
|
| - return {
|
| - leftNotUsableSize: leftNotUsableSize,
|
| - rightNotUsableSize: rightNotUsableSize,
|
| - availableWidth: availableWidth,
|
| - topNotUsableSize: topNotUsableSize,
|
| - bottomNotUsableHeightWithoutXLabels: bottomNotUsableHeightWithoutXLabels,
|
| - bottomNotUsableHeightWithXLabels: bottomNotUsableHeightWithXLabels,
|
| - availableHeight: availableHeight,
|
| - widestXLabel: widestXLabel,
|
| - highestXLabel: highestXLabel,
|
| - widestYLabel: widestYLabel,
|
| - widestYLabel2: widestYLabel2,
|
| - highestYLabel: highestYLabel,
|
| - rotateLabels: rotateLabels,
|
| - xLabelPos: xLabelPos,
|
| - clrx: clrx,
|
| - clry: clry,
|
| - clrwidth: clrwidth,
|
| - clrheight: clrheight,
|
| - legendMsr : legendMsr
|
| - };
|
| - };
|
| - // Function for additionalLine (BarLine|Line)
|
| - function drawLinesDataset(axis, animPc, data, config, ctx, offsets, vars) {
|
| - var xAxisPosY = vars.xAxisPosY;
|
| - var yAxisPosX = vars.yAxisPosX;
|
| - var valueHop = vars.valueHop;
|
| - var nbValueHop = vars.nbValueHop;
|
| - var scaleHop = vars.scaleHop;
|
| - var zeroY = vars.zeroY;
|
| - var calculatedScale = vars.calculatedScale;
|
| - var logarithmic = vars.logarithmic;
|
| - var currentAnimPc = animationCorrection(animPc, data, config, 0, 0, 0);
|
| - var totvalue = new Array();
|
| - var maxvalue = new Array();
|
| - var lmaxvalue = new Array();
|
| - var lminvalue = new Array();
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - lmaxvalue[i] = -999999999;
|
| - lminvalue[i] = 999999999;
|
| - if ((axis == 2 && data.datasets[i].axis == 2) || (axis != 2 && data.datasets[i].axis != 2)) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - totvalue[j] = 0;
|
| - maxvalue[j] = -999999999;
|
| - }
|
| - }
|
| - }
|
| - currentAnimPc.mainVal = 1;
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - if ((axis == 2 && data.datasets[i].axis == 2) || (axis != 2 && data.datasets[i].axis != 2)) {
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - totvalue[j] += data.datasets[i].data[j];
|
| - maxvalue[j] = Max([maxvalue[j], data.datasets[i].data[j]]);
|
| - lmaxvalue[i] = Max([lmaxvalue[i], yPos(i, j)]);
|
| - lminvalue[i] = Min([lminvalue[i], yPos(i, j)]);
|
| - }
|
| - }
|
| - }
|
| - for (var i = 0; i < data.datasets.length; i++) {
|
| - if ((axis == 2 && data.datasets[i].axis == 2) || (axis != 2 && data.datasets[i].axis != 2)) {
|
| - var prevpt = -1;
|
| - var frstpt = -1;
|
| - if (typeof data.datasets[i].strokeColor == "function") {
|
| - ctx.strokeStyle = data.datasets[i].strokeColor("STROKECOLOR", data, config, i, -1, animPc, -1, "Line", ctx, yAxisPosX, lmaxvalue[i], yAxisPosX + valueHop * (data.datasets[i].data.length - 1), lmaxvalue[i] - ((config.animationLeftToRight) ? 1 : 1*currentAnimPc.mainVal) * (lmaxvalue[i] - lminvalue[i]));
|
| - } else if (typeof data.datasets[i].strokeColor == "string") {
|
| - ctx.strokeStyle = data.datasets[i].strokeColor;
|
| - } else ctx.strokeStyle = config.defaultStrokeColor;
|
| - ctx.lineWidth = config.datasetStrokeWidth;
|
| - ctx.beginPath();
|
| - var prevAnimPc;
|
| - var prevXpos;
|
| - prevAnimPc = 0;
|
| - prevnotempty = 0;
|
| - for (var j = 0; j < data.datasets[i].data.length; j++) {
|
| - var xposj = xPos(i, j, data);
|
| - currentAnimPc = animationCorrection(animPc, data, config, i, j, 0);
|
| - if (currentAnimPc.mainVal == 0 && prevAnimPc > 0) {
|
| - ctx.stroke();
|
| - ctx.strokeStyle = "rgba(0,0,0,0)";
|
| - // ctx.lineWidth =0.01;
|
| - ctx.lineTo(prevXpos, xAxisPosY - zeroY);
|
| - }
|
| - prevAnimPc = currentAnimPc.mainVal;
|
| - if (currentAnimPc.mainVal >= 1) {
|
| - if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim();
|
| - else lgtxt = "";
|
| - }
|
| - if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
|
| - prevXpos = xPos(i, j, data);
|
| - if (prevpt == -1) {
|
| - ctx.moveTo(xposj, yPos(i, j));
|
| - frstpt = j;
|
| - } else {
|
| - if (config.bezierCurve) {
|
| - ctx.bezierCurveTo(xPos(i, j - (j - prevpt) / 2, data), yPos(i, prevpt), xPos(i, j - (j - prevpt) / 2, data), yPos(i, j), xPos(i, j, data), yPos(i, j));
|
| - } else {
|
| - ctx.lineTo(xPos(i, j, data), yPos(i, j));
|
| - }
|
| - }
|
| - if ((typeof(data.datasets[i].data[j + 1]) !== 'undefined') || (true == config.extrapolateMissingData)) {
|
| - if (currentAnimPc.subVal > 0) {
|
| - // next not missing value
|
| - nxtnotmiss = -1;
|
| - for (t = j + 1; t < data.datasets[i].data["length"] && nxtnotmiss == -1; t++) {
|
| - if (!(typeof(data.datasets[i].data[t]) == 'undefined')) nxtnotmiss = t;
|
| - }
|
| - if (nxtnotmiss != -1) {
|
| - prevXpos = xPos(i, j + currentAnimPc.subVal, data);
|
| - if (config.bezierCurve) {
|
| - ctx.bezierCurveTo(xPos(i, j + currentAnimPc.subVal / 2, data), yPos(i, j), xPos(i, j + currentAnimPc.subVal / 2, data), yPos(i, nxtnotmiss), xPos(i, j + currentAnimPc.subVal, data), yPos(i, nxtnotmiss));
|
| - } else {
|
| - ctx.lineTo(xPos(i, j + currentAnimPc.subVal, data), yPos(i, j + 1));
|
| - }
|
| - }
|
| - }
|
| - prevpt = j;
|
| - if (animPc >= 1) {
|
| - if (i == 0) divprev = data.datasets[i].data[j];
|
| - else divprev = data.datasets[i].data[j] - data.datasets[i - 1].data[j];
|
| - if (i == data.datasets.length - 1) divnext = data.datasets[i].data[j];
|
| - else divnext = data.datasets[i].data[j] - data.datasets[i + 1].data[j];
|
| - lgtxt2 = "";
|
| - if (typeof data.datasets[i].xPos != "undefined") {
|
| - if (!(typeof data.datasets[i].xPos[j] == "undefined")) lgtxt2 = data.datasets[i].xPos[j];
|
| - }
|
| - if (lgtxt2 == "" && !(typeof(data.labels[j]) == "undefined")) lgtxt2 = data.labels[j];
|
| - if (typeof lgtxt2 == "string") lgtxt2 = lgtxt2.trim();
|
| - jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["POINT", xPos(i, j, data), yPos(i, j), lgtxt, lgtxt2, 1 * data.datasets[i].data[j], divprev, divnext, maxvalue[j], totvalue[j], i, j];
|
| - if (config.inGraphDataShow) {
|
| - ctx.save();
|
| - ctx.textAlign = config.inGraphDataAlign;
|
| - ctx.textBaseline = config.inGraphDataVAlign;
|
| - ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily;
|
| - ctx.fillStyle = config.inGraphDataFontColor;
|
| - var dotX = yAxisPosX + (valueHop * k),
|
| - dotY = xAxisPosY - currentAnimPc.mainVal * (calculateOffset(logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop)),
|
| - paddingTextX = config.inGraphDataPaddingX,
|
| - paddingTextY = config.inGraphDataPaddingY;
|
| - var dispString = tmplbis(config.inGraphDataTmpl, {
|
| - config: config,
|
| - v1: fmtChartJS(config, lgtxt, config.fmtV1),
|
| - v2: fmtChartJS(config, lgtxt2, config.fmtV2),
|
| - v3: fmtChartJS(config, 1 * data.datasets[i].data[j], config.fmtV3),
|
| - v4: fmtChartJS(config, divprev, config.fmtV4),
|
| - v5: fmtChartJS(config, divnext, config.fmtV5),
|
| - v6: fmtChartJS(config, maxvalue[j], config.fmtV6),
|
| - v7: fmtChartJS(config, totvalue[j], config.fmtV7),
|
| - v8: roundToWithThousands(config, fmtChartJS(config, 100 * data.datasets[i].data[j] / totvalue[j], config.fmtV8), config.roundPct),
|
| - v9: fmtChartJS(config, yAxisPosX + (valueHop * k), config.fmtV9),
|
| - v10: fmtChartJS(config, xAxisPosY - (calculateOffset(logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop)), config.fmtV10),
|
| - v11: fmtChartJS(config, i, config.fmtV11),
|
| - v12: fmtChartJS(config, j, config.fmtV12),
|
| - data: data
|
| - });
|
| - ctx.translate(xPos(i, j, data) + paddingTextX, yPos(i, j) - paddingTextY);
|
| - ctx.rotate(config.inGraphDataRotate * (Math.PI / 180));
|
| - ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize);
|
| - ctx.restore();
|
| - }
|
| - }
|
| - }
|
| - } else {
|
| - if (false == config.extrapolateMissingData) {
|
| - ctx.stroke();
|
| - if (config.datasetFill) {
|
| - ctx.lineTo(prevXpos, xAxisPosY - zeroY);
|
| - ctx.lineTo(xPos(i, frstpt, data), xAxisPosY - zeroY);
|
| - ctx.lineTo(xPos(i, frstpt, data), yPos(i, frstpt));
|
| - ctx.closePath();
|
| - if (typeof data.datasets[i].fillColor == "function") ctx.fillStyle = data.datasets[i].fillColor("FILLCOLOR", data, config, i, -1, currentAnimPc.mainVal, -1, "Line", ctx, yAxisPosX, lmaxvalue[i], yAxisPosX + valueHop * (data.datasets[i].data.length - 1), lmaxvalue[i] - ((config.animationLeftToRight) ? 1 : 1*currentAnimPc.mainVal) * (lmaxvalue[i] - lminvalue[i]));
|
| - else if (typeof data.datasets[i].fillColor == "string") ctx.fillStyle = data.datasets[i].fillColor;
|
| - else ctx.fillStyle = config.defaultFillColor;
|
| - ctx.fill();
|
| - }
|
| - ctx.beginPath();
|
| - prevpt = -1;
|
| - frstpt = -1;
|
| - prevAnimPc = 0;
|
| - prevnotempty = 0;
|
| - } else {
|
| - if (currentAnimPc.subVal > 0) {
|
| - nxtnotmiss = -1;
|
| - for (t = j + 1; t < data.datasets[i].data["length"] && nxtnotmiss == -1; t++) {
|
| - if (!(typeof(data.datasets[i].data[t]) == 'undefined')) nxtnotmiss = t;
|
| - }
|
| - if ((typeof(data.datasets[i].data[j]) !== 'undefined') || (true == config.extrapolateMissingData)) {
|
| - if (nxtnotmiss != -1) {
|
| - prevXpos = xPos(i, j + currentAnimPc.subVal, data);
|
| - if (config.bezierCurve) {
|
| - ctx.bezierCurveTo(xPos(i, prevpt + (j + currentAnimPc.subVal - prevpt) / 2, data), yPos(i, prevpt), xPos(i, prevpt + (j + currentAnimPc.subVal - prevpt) / 2, data), yPos(i, nxtnotmiss), xPos(i, j + currentAnimPc.subVal, data), yPos(i, nxtnotmiss));
|
| - } else {
|
| - ctx.lineTo(xPos(i, j + currentAnimPc.subVal, data), yPos(i, j + 1));
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| - ctx.stroke();
|
| - if (config.datasetFill) {
|
| - // ctx.lineTo(yAxisPosX + (valueHop * (data.datasets[i].data.length - 1)), xAxisPosY - zeroY);
|
| - ctx.lineTo(prevXpos, xAxisPosY - zeroY);
|
| - ctx.lineTo(xPos(i, frstpt, data), xAxisPosY - zeroY);
|
| - ctx.lineTo(xPos(i, frstpt, data), yPos(i, frstpt));
|
| - ctx.closePath();
|
| - if (typeof data.datasets[i].fillColor == "function") { ctx.fillStyle = data.datasets[i].fillColor("FILLCOLOR", data, config, i, -1, currentAnimPc.mainVal, -1, "Line", ctx, yAxisPosX, lmaxvalue[i], yAxisPosX + valueHop * (data.datasets[i].data.length - 1), lmaxvalue[i] - ((config.animationLeftToRight) ? 1 : 1*currentAnimPc.mainVal) * (lmaxvalue[i] - lminvalue[i])); }
|
| - else if (typeof data.datasets[i].fillColor == "string") ctx.fillStyle = data.datasets[i].fillColor;
|
| - else ctx.fillStyle = config.defaultFillColor;
|
| - ctx.fill();
|
| - } else {
|
| - ctx.closePath();
|
| - }
|
| - if (config.pointDot) {
|
| - if (typeof data.datasets[i].pointColor == "function") ctx.fillStyle = data.datasets[i].pointColor("POINTCOLOR", data, config, i, -1, animPc, -1, "Line", ctx, yAxisPosX, lmaxvalue[i], yAxisPosX + valueHop * (data.datasets[i].data.length - 1), lmaxvalue[i] - ((config.animationLeftToRight) ? 1 : 1*currentAnimPc.mainVal) * (lmaxvalue[i] - lminvalue[i]));
|
| - else ctx.fillStyle = data.datasets[i].pointColor;
|
| - if (typeof data.datasets[i].pointStrokeColor == "function") ctx.strokeStyle = data.datasets[i].pointStrokeColor("POINTSTROKECOLOR", data, config, i, -1, animPc, -1, "Line", ctx, yAxisPosX, lmaxvalue[i], yAxisPosX + valueHop * (data.datasets[i].data.length - 1), lmaxvalue[i] - ((config.animationLeftToRight) ? 1 : 1*currentAnimPc.mainVal) * (lmaxvalue[i] - lminvalue[i]));
|
| - else ctx.strokeStyle = data.datasets[i].pointStrokeColor;
|
| - ctx.lineWidth = config.pointDotStrokeWidth;
|
| - for (var k = 0; k < data.datasets[i].data.length; k++) {
|
| - if (!(typeof(data.datasets[i].data[k]) == 'undefined')) {
|
| - var currentAnimPc = animationCorrection(animPc, data, config, i, k, 0);
|
| - if (currentAnimPc.mainVal > 0 || !config.animationLeftToRight) {
|
| - ctx.beginPath();
|
| - ctx.arc(xPos(i, k, data), yPos(i, k), config.pointDotRadius, 0, Math.PI * 2, true);
|
| - ctx.fill();
|
| - ctx.stroke();
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| - };
|
| -
|
| - function yPos(dataSet, iteration) {
|
| - return xAxisPosY - zeroY - currentAnimPc.mainVal * (calculateOffset(logarithmic, data.datasets[dataSet].data[iteration], calculatedScale, scaleHop) - zeroY);
|
| - };
|
| -
|
| - function xPos(ival, iteration, data) {
|
| - if (typeof data.datasets[ival].xPos == "object") {
|
| - if (!(typeof data.datasets[ival].xPos[Math.floor(iteration + 0.0001)] == "undefined")) {
|
| - var width = valueHop * nbValueHop;
|
| - var deb = (typeof data.xBegin != "undefined") ? data.xBegin : 1 * data.labels[0];
|
| - var fin = (typeof data.xEnd != "undefined") ? data.xEnd : 1 * data.labels[data.labels.length - 1];
|
| - if (fin <= deb) fin = deb + 100;
|
| - if (1 * data.datasets[ival].xPos[Math.floor(iteration + 0.0001)] >= deb && data.datasets[ival].xPos[Math.floor(iteration + 0.0001)] <= fin) {
|
| - var p1 = yAxisPosX + width * ((1 * data.datasets[ival].xPos[Math.floor(iteration + 0.0001)] - deb) / (fin - deb));
|
| - var p2 = p1;
|
| - if (Math.abs(iteration - Math.floor(iteration + 0.0001)) > 0.0001) {
|
| - var tt = iteration + Math.floor(iteration + 0.0001);
|
| - var p2 = xPos(ival, Math.ceil(iteration - 0.0001), data);
|
| - }
|
| - return p1 + (iteration - Math.floor(iteration + 0.0001)) * (p2 - p1);
|
| - }
|
| - }
|
| - }
|
| - return yAxisPosX + (valueHop * iteration);
|
| - };
|
| - };
|
| -
|
| - function log10(val) {
|
| - return Math.log(val) / Math.LN10;
|
| - };
|
| -
|
| - function setRect(ctx, config) {
|
| - if (config.clearRect) {
|
| - if (!config.multiGraph) {
|
| - clear(ctx);
|
| - ctx.clearRect(0, 0, width, height);
|
| - }
|
| - } else {
|
| - clear(ctx);
|
| - ctx.clearRect(0, 0, width, height);
|
| -
|
| - ctx.fillStyle = config.savePngBackgroundColor;
|
| - ctx.strokeStyle = config.savePngBackgroundColor;
|
| - ctx.beginPath();
|
| - ctx.moveTo(0, 0);
|
| - ctx.lineTo(0, ctx.canvas.height);
|
| - ctx.lineTo(ctx.canvas.width, ctx.canvas.height);
|
| - ctx.lineTo(ctx.canvas.width, 0);
|
| - ctx.lineTo(0, 0);
|
| - ctx.stroke();
|
| - ctx.fill();
|
| - }
|
| - };
|
| -
|
| - function defMouse(ctx, data, config) {
|
| - if (config.annotateDisplay == true) {
|
| - if (cursorDivCreated == false) oCursor = new makeCursorObj('divCursor');
|
| - if (isIE() < 9 && isIE() != false) ctx.canvas.attachEvent("on" + config.annotateFunction.split(' ')[0], function(event) {
|
| - if ((config.annotateFunction.split(' ')[1] == "left" && event.which == 1) ||
|
| - (config.annotateFunction.split(' ')[1] == "middle" && event.which == 2) ||
|
| - (config.annotateFunction.split(' ')[1] == "right" && event.which == 3) ||
|
| - (typeof(config.annotateFunction.split(' ')[1]) != "string")) doMouseAction(config, ctx, event, data, "annotate", config.mouseDownRight)
|
| - });
|
| - else ctx.canvas.addEventListener(config.annotateFunction.split(' ')[0], function(event) {
|
| - if ((config.annotateFunction.split(' ')[1] == "left" && event.which == 1) ||
|
| - (config.annotateFunction.split(' ')[1] == "middle" && event.which == 2) ||
|
| - (config.annotateFunction.split(' ')[1] == "right" && event.which == 3) ||
|
| - (typeof(config.annotateFunction.split(' ')[1]) != "string")) doMouseAction(config, ctx, event, data, "annotate", config.mouseDownRight)
|
| - }, false);
|
| - }
|
| - if (config.savePng) {
|
| - if (isIE() < 9 && isIE() != false) ctx.canvas.attachEvent("on" + config.savePngFunction.split(' ')[0], function(event) {
|
| - if ((config.savePngFunction.split(' ')[1] == "left" && event.which == 1) ||
|
| - (config.savePngFunction.split(' ')[1] == "middle" && event.which == 2) ||
|
| - (config.savePngFunction.split(' ')[1] == "right" && event.which == 3) ||
|
| - (typeof(config.savePngFunction.split(' ')[1]) != "string")) saveCanvas(ctx, data, config);
|
| - });
|
| - else ctx.canvas.addEventListener(config.savePngFunction.split(' ')[0], function(event) {
|
| - if ((config.savePngFunction.split(' ')[1] == "left" && event.which == 1) ||
|
| - (config.savePngFunction.split(' ')[1] == "middle" && event.which == 2) ||
|
| - (config.savePngFunction.split(' ')[1] == "right" && event.which == 3) ||
|
| - (typeof(config.savePngFunction.split(' ')[1]) != "string")) saveCanvas(ctx, data, config);
|
| - }, false);
|
| - }
|
| -
|
| - if (isIE() < 9 && isIE() != false) ctx.canvas.attachEvent("onmousewheel", function(event) {
|
| - if (cursorDivCreated) document.getElementById('divCursor').style.display = 'none';
|
| - });
|
| - else ctx.canvas.addEventListener("DOMMouseScroll", function(event) {
|
| - if (cursorDivCreated) document.getElementById('divCursor').style.display = 'none';
|
| - }, false);
|
| -
|
| -
|
| -
|
| - function add_event_listener(type, func, chk)
|
| - {
|
| - if(typeof func != 'function')
|
| - return;
|
| -
|
| - function do_func(event) {
|
| - if (chk == null || chk(event)) doMouseAction(config,ctx,event,data,"mouseaction",func);
|
| - };
|
| -
|
| - var hash = type+' '+func.name;
|
| - if(hash in ctx._eventListeners) {
|
| - if(ctx.canvas.removeEventListener)
|
| - ctx.canvas.removeEventListener(type, ctx._eventListeners[hash]);
|
| - else if(ctx.canvas.detachEvent)
|
| - ctx.canvas.detachEvent(type, ctx._eventListeners[hash]);
|
| - }
|
| -
|
| - ctx._eventListeners[hash] = do_func;
|
| -
|
| - if(ctx.canvas.addEventListener) {
|
| - if(type=="mousewheel") type="DOMMouseScroll";
|
| - ctx.canvas.addEventListener(type, do_func, false);
|
| - } else if(ctx.canvas.attachEvent) {
|
| - ctx.canvas.attachEvent("on"+type, do_func);
|
| - }
|
| - };
|
| -
|
| - add_event_listener("mousedown", config.mouseDownLeft, function(e) { return e.which == 1; });
|
| - add_event_listener("mousedown", config.mouseDownMiddle, function(e) { return e.which == 2; });
|
| - add_event_listener("mousedown", config.mouseDownRight, function(e) { return e.which == 3; });
|
| - add_event_listener("mousemove", config.mouseMove);
|
| - add_event_listener("mouseout", config.mouseOut);
|
| - add_event_listener("mousewheel", config.mouseWheel);
|
| - };
|
| -};
|
| -
|
| -function animationCorrection(animationValue, data, config, vdata, vsubdata, addone) {
|
| - var animValue = animationValue;
|
| - var animSubValue = 0;
|
| - if (vsubdata != -1) {
|
| - if (animValue < 1 && (vdata < (config.animationStartWithDataset - 1) && (config.animationStartWithDataset - 1) != -1)) {
|
| - animValue = 1;
|
| - }
|
| - if (animValue < 1 && (vsubdata < (config.animationStartWithData - 1) && (config.animationStartWithData - 1) != -1)) {
|
| - animValue = 1;
|
| - }
|
| - var totreat = 1;
|
| - var newAnimationValue = animationValue;
|
| - if (animValue < 1 && config.animationByDataset) {
|
| - animValue = 0;
|
| - totreat = 0;
|
| - var startDataset = (config.animationStartWithDataset - 1);
|
| - if ((config.animationStartWithDataset - 1) == -1) startDataset = 0
|
| - var nbstepsperdatasets = config.animationSteps / (data.datasets.length - startDataset);
|
| - if (animationValue >= (vdata - startDataset + 1) * nbstepsperdatasets / config.animationSteps) animValue = 1;
|
| - else if (animationValue >= (vdata - startDataset) * nbstepsperdatasets / config.animationSteps) {
|
| - var redAnimationValue = animationValue - (vdata - startDataset) * nbstepsperdatasets / config.animationSteps;
|
| - if (!config.animationLeftToRight) {
|
| - animValue = redAnimationValue * (data.datasets.length - startDataset);
|
| - } else {
|
| - newAnimationValue = redAnimationValue * (data.datasets.length - startDataset);
|
| - }
|
| - totreat = 1;
|
| - }
|
| - }
|
| - if (totreat == 1 && animValue < 1 && config.animationLeftToRight) {
|
| - animValue = 0;
|
| - var startSub = (config.animationStartWithData - 1);
|
| - if ((config.animationStartWithData - 1) == -1) startSub = 0
|
| - var nbstepspervalue = config.animationSteps / (data.datasets[vdata].data.length - startSub - 1 + addone);
|
| - if (newAnimationValue >= (vsubdata - startSub) * nbstepspervalue / config.animationSteps) {
|
| - animValue = 1;
|
| - if (newAnimationValue <= (vsubdata + 1 - startSub) * nbstepspervalue / config.animationSteps) {
|
| - animSubValue = (data.datasets[vdata].data.length - startSub - 1) * (newAnimationValue - ((vsubdata - startSub) * nbstepspervalue / config.animationSteps));
|
| - }
|
| - }
|
| - }
|
| - } else {
|
| - if (animValue < 1 && (vdata < (config.animationStartWithData - 1))) {
|
| - animValue = 1;
|
| - }
|
| - }
|
| - return {
|
| - mainVal: animValue,
|
| - subVal: animSubValue,
|
| - animVal: animValue + animSubValue
|
| - };
|
| -};
|
| -
|
| -
|
| -function drawLegend(legendMsr,data,config,ctx,typegraph) {
|
| - if (config.legendBorders == true) {
|
| - ctx.save();
|
| - ctx.beginPath();
|
| - ctx.lineWidth = config.legendBordersWidth;
|
| - ctx.strokeStyle = config.legendBordersColors;
|
| - ctx.moveTo(legendMsr.xLegendBorderPos, legendMsr.yLegendBorderPos);
|
| - ctx.lineTo(legendMsr.xLegendBorderPos, legendMsr.yLegendBorderPos + legendMsr.legendBorderHeight);
|
| - ctx.lineTo(legendMsr.xLegendBorderPos + legendMsr.legendBorderWidth, legendMsr.yLegendBorderPos + legendMsr.legendBorderHeight);
|
| - ctx.lineTo(legendMsr.xLegendBorderPos + legendMsr.legendBorderWidth, legendMsr.yLegendBorderPos);
|
| - ctx.lineTo(legendMsr.xLegendBorderPos, legendMsr.yLegendBorderPos);
|
| - ctx.lineTo(legendMsr.xLegendBorderPos + legendMsr.legendBorderWidth, legendMsr.yLegendBorderPos);
|
| - ctx.lineTo(legendMsr.xLegendBorderPos, legendMsr.yLegendBorderPos);
|
| - ctx.lineTo(legendMsr.xLegendBorderPos, legendMsr.yLegendBorderPos + legendMsr.legendBorderHeight);
|
| - ctx.stroke();
|
| - ctx.closePath();
|
| - ctx.fillStyle = "rgba(0,0,0,0)"; // config.legendFillColor;
|
| - ctx.fillStyle = config.legendFillColor;
|
| - ctx.fill();
|
| - ctx.restore();
|
| - }
|
| - nbcols = legendMsr.nbLegendCols - 1;
|
| - ypos = legendMsr.yFirstLegendTextPos - (config.legendFontSize + config.legendSpaceBetweenTextVertical);
|
| - xpos = 0;
|
| - if (legendMsr.drawLegendOnData) fromi = data.datasets.length;
|
| - else fromi = data.length;
|
| - for (var i = fromi - 1; i >= 0; i--) {
|
| - orderi = i;
|
| - if (legendMsr.reverseLegend) {
|
| - if (legendMsr.drawLegendOnData) orderi = data.datasets.length - i - 1;
|
| - else orderi = data.length - i - 1;
|
| - }
|
| - if (legendMsr.drawLegendOnData) tpof = typeof(data.datasets[orderi].title);
|
| - else tpof = typeof(data[orderi].title)
|
| - if (tpof == "string") {
|
| - if (legendMsr.drawLegendOnData) lgtxt = fmtChartJS(config, data.datasets[orderi].title, config.fmtLegend).trim();
|
| - else lgtxt = fmtChartJS(config, data[orderi].title, config.fmtLegend).trim();
|
| - if (lgtxt != "") {
|
| - nbcols++;
|
| - if (nbcols == legendMsr.nbLegendCols) {
|
| - nbcols = 0;
|
| - xpos = legendMsr.xFirstLegendTextPos;
|
| - ypos += config.legendFontSize + config.legendSpaceBetweenTextVertical;
|
| - } else {
|
| - xpos += legendMsr.widestLegend + config.legendSpaceBetweenTextHorizontal;
|
| - }
|
| - ctx.save();
|
| - ctx.beginPath();
|
| - if (legendMsr.drawLegendOnData) {
|
| - if (typeof data.datasets[orderi].strokeColor == "function") ctx.strokeStyle = data.datasets[orderi].strokeColor("STROKECOLOR", data, config, orderi, -1, 1, -1, typegraph, ctx, -1, -1, -1, -1);
|
| - else if (typeof data.datasets[orderi].strokeColor == "string") ctx.strokeStyle = data.datasets[orderi].strokeColor;
|
| - else ctx.strokeStyle = config.defaultStrokeColor;
|
| - } else {
|
| - if (typeof data[orderi].color == "function") ctx.strokeStyle = data[orderi].color("COLOR", data, config, orderi, -1, 1, data[orderi].value, typegraph, ctx, 1, 1, 1, 1);
|
| - else if (typeof data[orderi].color == "string") ctx.strokeStyle = data[orderi].color;
|
| - else ctx.strokeStyle = config.defaultStrokeColor;
|
| - }
|
| - if (legendMsr.legendBox) {
|
| - ctx.lineWidth = 1;
|
| - ctx.moveTo(xpos, ypos);
|
| - ctx.lineTo(xpos + config.legendBlockSize, ypos);
|
| - ctx.lineTo(xpos + config.legendBlockSize, ypos - config.legendFontSize);
|
| - ctx.lineTo(xpos, ypos - config.legendFontSize);
|
| - ctx.lineTo(xpos, ypos);
|
| - ctx.closePath();
|
| - if (legendMsr.drawLegendOnData) {
|
| - if (typeof data.datasets[orderi].fillColor == "function") ctx.fillStyle = data.datasets[orderi].fillColor("LEGENDFILLCOLOR", data, config, orderi, -1, 1, -1, typegraph, ctx, xpos, ypos, xpos + config.legendBlockSize, ypos - config.legendFontSize);
|
| - else if (typeof data.datasets[orderi].fillColor == "string") ctx.fillStyle = data.datasets[orderi].fillColor;
|
| - else ctx.fillStyle = config.defaultFillColor;
|
| - } else {
|
| - if (typeof data[orderi].color == "function") ctx.fillStyle = data[orderi].color("LEGENDFILLCOLOR", data, config, orderi, -1, 1, -1, typegraph, ctx, xpos, ypos - config.legendFontSize, xpos + config.legendBlockSize, ypos);
|
| - else if (typeof data[orderi].color == "string") ctx.fillStyle = data[orderi].color;
|
| - else ctx.fillStyle = config.defaultFillColor;
|
| - }
|
| - ctx.fill();
|
| - } else {
|
| - ctx.lineWidth = config.legendColorIndicatorStrokeWidth ?
|
| - config.legendColorIndicatorStrokeWidth : config.datasetStrokeWidth;
|
| - if (config.legendColorIndicatorStrokeWidth && config.legendColorIndicatorStrokeWidth > config.legendFontSize) {
|
| - ctx.lineWidth = config.legendFontSize;
|
| - }
|
| - ctx.moveTo(xpos + 2, ypos - (config.legendFontSize / 2));
|
| - ctx.lineTo(xpos + 2 + config.legendBlockSize, ypos - (config.legendFontSize / 2));
|
| - }
|
| - ctx.stroke();
|
| - ctx.restore();
|
| - ctx.save();
|
| - ctx.beginPath();
|
| - ctx.font = config.legendFontStyle + " " + config.legendFontSize + "px " + config.legendFontFamily;
|
| - ctx.fillStyle = config.legendFontColor;
|
| - ctx.textAlign = "left";
|
| - ctx.textBaseline = "bottom";
|
| - ctx.translate(xpos + config.legendBlockSize + config.legendSpaceBetweenBoxAndText, ypos);
|
| - ctx.fillText(lgtxt, 0, 0);
|
| - ctx.stroke();
|
| - ctx.restore();
|
| - }
|
| - }
|
| - }
|
| -};
|
|
|