UNPKG

chartnew.js

Version:

Simple HTML5 Charts using the canvas element

1,418 lines (1,368 loc) 287 kB
/* * 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 (isIE() < 9 && isIE() != false) return(true); 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.Stac