JavaScript loop/array - javascript

I have the simple javascript code below which im initializing from a JSON Array Object using SimpleJSON java api how do I set data=dataSets[i] inside of a loop rather then hardcoding it.
var scatterChart = new Chart(ctx, {
type : 'scatter',
data : {
datasets : [
{
borderColor : window.chartColors.red,
backgroundColor : color(window.chartColors.red)
.alpha(0.2).rgbString(),
label : 'Sample1'
data : dataSets[0]
},
{
data : dataSets[1]
},
{
borderColor : window.chartColors.blue,
backgroundColor : color(window.chartColors.blue)
.alpha(0.2).rgbString(),
data : dataSets[2]
},
{
data : dataSets[3]
}, {
data : dataSets[4]
}, {
data : dataSets[5]
}, {
data : dataSets[6]
}, {
data : dataSets[7]
}, {
data : dataSets[8]
}, {
data : dataSets[9]
}, {
data : dataSets[10]
} ]`

You could also map the dataSets to an array of objects with the dataSet being the data property, then you could extend the first and the third with some extra properties:
// transform the datasets (from the api?) to the structure that you want
var dataSetsWithData = dataSets
.map(dataSet => ({ data: dataSet})) ;
// you now have an array of objects
// manually add the extra properties for the ones you're intresed in
dataSetsWithData[0] = {
// keep the original properties, in this case just "data"
...dataSetsWithData[0],
// additional properties for this particular index
borderColor : window.chartColors.red,
backgroundColor : color(window.chartColors.red)
.alpha(0.2).rgbString(),
label : 'Sample1'
};
dataSetsWithData[2] = {
// keep the original properties, in this case just "data"
...dataSetsWithData[0],
// additional properties for this particular index
borderColor : window.chartColors.blue,
backgroundColor : color(window.chartColors.blue).alpha(0.2).rgbString(),
};
var scatterChart = new Chart(ctx, {
type : 'scatter',
data : {
datasets : dataSetsWithData
}
});

You could set up your array without the data property (lets call it settings):
var settings = [
{
borderColor : window.chartColors.red,
backgroundColor : color(window.chartColors.red)
.alpha(0.2).rgbString(),
label : 'Sample1'
},
null,
{
borderColor : window.chartColors.blue,
backgroundColor : color(window.chartColors.blue)
.alpha(0.2).rgbString(),
}
];
Then we take dataSets and extend it with our settings:
var datasets = dataSets.map((data,i) => {
...(settings[i] || {}),
data
});
The upper code is ESnext so you might use this instead:
var datasets = dataSets.map(function(data,i){
return Object.assign({data:data},settings[i]);
});
Then we can draw the graph:
var scatterChart = new Chart(ctx, {
type : 'scatter',
data : { datasets }
});

you can write down as following using forEach
var dataArray=[];
dataSets.forEach(function(d,i){
var tempObj={};
tempObj["data"]=d;
if(i==0){
tempObj["borderColor"] = window.chartColors.red;
tempObj["backgroundColor"] =
color(window.chartColors.red).alpha(0.2).rgbString();
tempObj["label"] = 'Sample1';
}else if(i==2){
tempObj["borderColor"] = window.chartColors.blue;
tempObj["backgroundColor"] =
color(window.chartColors.blue).alpha(0.2).rgbString();
}
dataArray.push(tempObj);
});
var scatterChart = new Chart(ctx, {
type : 'scatter',
data : {
datasets :dataArray
}
if you wan to use for loop then,
var dataArray=[];
for(i=0;i<dataSets.length;i++){
var tempObj={};
tempObj["data"]=dataSets[i];
if(i==0){
tempObj["borderColor"] = window.chartColors.red;
tempObj["backgroundColor"] =
color(window.chartColors.red).alpha(0.2).rgbString();
tempObj["label"] = 'Sample1';
}else if(i==2){
tempObj["borderColor"] = window.chartColors.blue;
tempObj["backgroundColor"] =
color(window.chartColors.blue).alpha(0.2).rgbString();
}
dataArray.push(tempObj);
}
var scatterChart = new Chart(ctx, {
type : 'scatter',
data : {
datasets :dataArray
}

Related

Uncaught TypeError: Cannot read property 'hidden' of undefined(Chart.js)

I'm trying to draw a lineChart and the Errormessage,
Uncaught TypeError: Cannot read property 'hidden' of undefined, occurs and I really don't know what am I missing.
Make canvas with id,'chart'
get the 'JsonObject' from DB using controller
(In the JsonObject, I put the chart type, 'line', and also put the JsonArray, the data)
move the data from JsonArray to Array using function 'getArray' to remove the index
set the chart configuration and make a chart.
function makeChart(year,month,name){
var chart = $('#chart'); //
var valueArray = new Array();
$.ajax({
dataType : 'json',
url : '/individual/makeChart',
data : {
'year': year,
'month': month,
'name' : name
},
async : false,
success : function(json) {
valueArray = getArray(json);
var config = {
type : json.type,
data : {
datasets : [{
borderColor : "#3e95cd",
data : ['1','2','3','4','5','6','7','8','9','10','11','12'],
label : 'region'
}, {
borderColor : "#c45850",
data : ['1','2','3','4','5','6','7','8','9','10','11','12'],
label : 'country'
}],
},
options:{
showLines:true,
legend:{
display:true,
labels:{
fontSize:15,
fontColor:"#000000",
fontStyle:"bold"
}
},
responsive : true,
scales : {
yAxes : [{
ticks : {
beginAtZero : true,
fontSize : 15,
fontColor : "#000000",
fontStyle : "bold"
}
}],
xAxes : [{
ticks : {
fontSize : 15,
fontColor : "#000000",
fontStyle : "bold"
}
}]
}
}
}
new Chart(chart,config); // the problem occurs here!
}
});
}
function getArray(json){
var a = new Array();
a = json.Data[0];
return a;
}

How do I keep chart.js charts in one JS file, and not get errors when the ID from the JS file don't exist on one specific html page?

I'm quite new with JS, and have a problem with Chart.js and multiple charts.
I load all libraries like jquery and chart.js from CDNs
Then I have one plugins.js for localy loaded plugins
And one js called main.js with all the custom JS.
I get this error:
Uncaught TypeError: Cannot read property 'style' of undefined
My question is:
How do I keep all my Chart.js charts in one .js file, that get loaded on all website pages, but not all pages contains all charts.
(I have a site that consists on multiple pages with different charts, and I'm thinking it's smarter to load all at once in one JS-file)
Appreciate any other pointers also. :)
-
About the code
I've posted the code below and also created a JSFiddle: https://jsfiddle.net/NoLooseEnds/1pt3m41a/
In the main.js I have all my Chart.js data like so (among other things):
// *************************************
// Chart.js
// *************************************
// Global Settings
Chart.defaults.global.defaultFontColor = "rgba(43,43,43,1)";
Chart.defaults.global.defaultFontFamily = "'ApexNew-Medium', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif";
Chart.defaults.global.defaultFontSize = 12;
Chart.defaults.global.defaultFontStyle = "normal";
Chart.defaults.global.maintainAspectRatio = false;
// Disable click on legend
Chart.defaults.global.legend.onClick = (e) => e.stopPropagation();
// Bar Charts settings
var barChart__options = {
};
// Doughnut settings
var dnutChart__options = {
legend: {
position: "bottom",
// Disable click on legend
onClick: (e) => e.stopPropagation()
}
};
// *************************************
// Datasets
// *************************************
// Bar Chart X
var barChartX__data = {
labels: ["Alpha", "Bravo", "Charlie"],
datasets: [
{
label: "2015",
borderWidth: 0,
backgroundColor: "rgba(43,43,43,1)",
data: [410,430,110]
},
{
label: "2016",
borderWidth: 0,
backgroundColor: "rgba(233,131,0,1.0)",
data: [405,360,150]
}
]
};
const barChartX = $("#barChartX");
let ChartX = new Chart(barChartX, {
type: "bar",
data: barChartX__data,
options: barChart__options
});
// Doughnut Chart Y
var dnutChartY__data = {
labels: ["Alpha", "Bravo"],
datasets: [
{
label: "Points",
borderWidth: 0,
backgroundColor: ["rgba(43,43,43,1)", "rgba(233,131,0,1.0)"],
data: [90,270]
}
]
};
const dnutChartY = $("#dnutChartY");
let ChartY = new Chart(dnutChartY, {
type: "doughnut",
data: dnutChartY__data,
options: dnutChart__options
});
// Doughnut Chart Z
var dnutChartZ__data = {
labels: ["Alpha", "Bravo", "Charlie"],
datasets: [
{
label: "Points",
borderWidth: 0,
backgroundColor: ["rgba(233,131,0,1.0)","rgba(239,162,64,1.0)","rgba(244,193,127,1.0)"],
data: [405,360,150]
}
]
};
const dnutChartZ = $("#dnutChartZ");
let ChartZ = new Chart(dnutChartZ, {
type: "doughnut",
data: dnutChartZ__data,
options: dnutChart__options
});
And my HTML like so:
<div class="example__chart">
<div>
<canvas id="barChartX" height="400" width="400"></canvas>
</div>
<!--
<div>
<canvas id="dnutChartY" height="400" width="400"></canvas>
</div>
-->
<div>
<canvas id="dnutChartZ" height="400" width="400"></canvas>
</div>
</div>
As you can see I have commented out a part to trigger the error.
You can create a helper function and check whenever the DOM element exists for the barChartX, dnutChartY, dnutChartZ or any other DOM element like this:
var doChart = function(o, d) {
if (typeof(o) != 'undefined' && o.length > 0) {
return new Chart(o, d);
} else {
return null;
}
}
Then your Chart.js code will be like this
// *************************************
// Chart.js
// *************************************
// Global Settings
Chart.defaults.global.defaultFontColor = "rgba(43,43,43,1)";
Chart.defaults.global.defaultFontFamily = "'ApexNew-Medium', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif";
Chart.defaults.global.defaultFontSize = 12;
Chart.defaults.global.defaultFontStyle = "normal";
Chart.defaults.global.maintainAspectRatio = false;
// Disable click on legend
Chart.defaults.global.legend.onClick = (e) => e.stopPropagation();
var doChart = function(o, d) {
if (typeof(o) != 'undefined' && o.length > 0) {
return new Chart(o, d);
} else {
return null;
}
}
// Bar Charts settings
var barChart__options = {};
// Doughnut settings
var dnutChart__options = {
legend: {
position: "bottom",
// Disable click on legend
onClick: (e) => e.stopPropagation()
}
};
// *************************************
// Datasets
// *************************************
// Bar Chart X
var barChartX__data = {
labels: ["Alpha", "Bravo", "Charlie"],
datasets: [{
label: "2015",
borderWidth: 0,
backgroundColor: "rgba(43,43,43,1)",
data: [410, 430, 110]
},
{
label: "2016",
borderWidth: 0,
backgroundColor: "rgba(233,131,0,1.0)",
data: [405, 360, 150]
}
]
};
const barChartX = $("#barChartX");
/*let ChartX = new Chart(barChartX, {
type: "bar",
data: barChartX__data,
options: barChart__options
});*/
let ChartX = doChart(barChartX, {
type: "bar",
data: barChartX__data,
options: barChart__options
});
// Doughnut Chart Y
var dnutChartY__data = {
labels: ["Alpha", "Bravo"],
datasets: [{
label: "Points",
borderWidth: 0,
backgroundColor: ["rgba(43,43,43,1)", "rgba(233,131,0,1.0)"],
data: [90, 270]
}]
};
const dnutChartY = $("#dnutChartY");
let ChartY = doChart(dnutChartY, {
type: "doughnut",
data: dnutChartY__data,
options: dnutChart__options
});
// Doughnut Chart Z
var dnutChartZ__data = {
labels: ["Alpha", "Bravo", "Charlie"],
datasets: [{
label: "Points",
borderWidth: 0,
backgroundColor: ["rgba(233,131,0,1.0)", "rgba(239,162,64,1.0)", "rgba(244,193,127,1.0)"],
data: [405, 360, 150]
}]
};
const dnutChartZ = $("#dnutChartZ");
let ChartZ = doChart(dnutChartZ, {
type: "doughnut",
data: dnutChartZ__data,
options: dnutChart__options
});
Please check my working example with no javascript errors here: http://zikro.gr/dbg/html/chartsjs/
UPDATE
Please have a look at the JSFiddle example here: https://jsfiddle.net/h1dafqjx/2/
UPDATE 2
Problem analysis and solution
The problem you are facing, is that you want to have multiple declarations and chart setups in one javascript file that you are going to use on many location which may happen some of these locations do not have some of the declared elements, thus you want your code to handle those cases.
You declare a chart like this:
const barChartX = $("#barChartX");
let ChartX = new Chart(barChartX, {
type: "bar",
data: barChartX__data,
options: barChart__options
});
In order to handle a missing DOM element, like when the $("#barChartX") does not exists, you need to create a condition to check those cases.
For excample:
const barChartX = $("#barChartX");
if(typeof(barChartX) != 'undefined' && barChartX.length > 0) {
let ChartX = new Chart(barChartX, {
type: "bar",
data: barChartX__data,
options: barChart__options
});
}
With the obove code, you check if the barChartX is defined and if it actually contains any elements with the barChartX.length > 0 condition.
Now, in order to do not repeat things, we keep it simple and do all that checking in a function. Thus we create the function doChart like this:
var doChart = function(o, d) {
if (typeof(o) != 'undefined' && o.length > 0) {
return new Chart(o, d);
} else {
return null;
}
}
The first parameter o is the DOM element we want to check and the second parameter d is the chart object properties.
For example:
let ChartX = doChart(barChartX, {
type: "bar",
data: barChartX__data,
options: barChart__options
});
Here we pass to the doChart function the barChartX jQuery object of the element in order for the function to check if exists. Then we pass the chart object parameters by the second parameter named d, which is the chart object properties for creating the new chart:
{
type: "bar",
data: barChartX__data,
options: barChart__options
}

Pikaday.js : Uncaught RangeError: Maximum call stack size exceeded

I created a simple app which have table and chart with date filters. There's 4 choices. Today, Yesterday, This Month, and Last Month, and one Submit button. It's working perfectly when page load. The table show list all of model and the chart show data what I want expected, perfect.
When I choosed a choice (for example : This Month) and click submit for first time, table and chart is refreshing, perfect.
But when I choosed for second time, It's give me error, and page is freeze
pikaday.js:70 Uncaught RangeError: Maximum call stack size exceeded.
Here's my part code
chartView.on("form:filter", function(data){
var criterion = data
filteredData.filter(criterion)
data1 = filteredData.filter(criterion)
chartView.trigger("view:render");
})
Here's full part code
programming.module("Program.Chart",function(Chart, programming, Backbone, Marionette, $, _){
Chart.Controller = {
getData : function(){
var data1 = programming.request("data:entities");
if(data1 !== undefined){
var filteredData = programming.Program.FilteredCollection({
collection : data1,
filterFunction : function(criterion){
return function(data){
var dateModel = moment(data.get("tanggal"),'DD/MM/YYYY');
var startDate = moment(criterion.date1,'DD/MM/YYYY')
var endDate = moment(criterion.date2,'DD/MM/YYYY')
if(dateModel.isSameOrAfter(startDate)){
if(dateModel.isSameOrBefore(endDate)){
return data
}
}
}
}
})
chartView = new Chart.chartV({
collection: filteredData
})
chartView.on("form:filter", function(data){
var criterion = data
filteredData.filter(criterion)
data1 = filteredData.filter(criterion)
chartView.trigger("view:render");
})
chartView.on("view:render", function(){
//DatePicker
var format = "DD/MM/YYYY"
var date1 = new Pikaday({
field : $("#date1",this.el)[0],
format : format
})
$("#date1",this.el)[0].value = moment().add('days').format(format)
var date2 = new Pikaday({
field : $("#date2",this.el)[0],
format : format
})
$("#date2",this.el)[0].value = moment().add('days').format(format)
var selectdate = $('#publicdate',this.el)[0];
selectdate.addEventListener("change",function(){
var value = selectdate.value;
var date1 = $('#date1',this.el)[0];
var date2 = $('#date2',this.el)[0];
if(value==="today"){
date1.value = moment().add('days').format(format)
date2.value = moment().add('days').format(format)
$(date1).attr('disabled',true);
$(date2).attr('disabled',true);
} else if(value==="yesterday"){
date1.value = moment().add(-1,'days').format(format)
date2.value = moment().add(-1,'days').format(format)
$(date1).attr('disabled',true);
$(date2).attr('disabled',true);
} else if(value==="thismonth"){
date1.value = moment().add('month').startOf('month').format(format)
date2.value = moment().add('month').endOf('month').format(format)
$(date1).removeAttr('disabled',true);
$(date2).removeAttr('disabled',true);
} else if(value==="lastmonth"){
date1.value = moment().add(-1,'month').startOf('month').format('DD/MM/YYYY')
date2.value = moment().add(-1,'month').endOf('month').format('DD/MM/YYYY')
$(date1).attr('disabled',true);
$(date2).attr('disabled',true);
}
})
//Chartist JS
var labels = data1.models.map(function(model){
return model.get("tanggal");
})
var tshirtv = [];
var casev = [];
var tanggal = [];
var series = data1.models.map(function(model,index){
tanggal[index] = model.get("tanggal");
if(model.get("produk")==="T-Shirt"){
tshirtv[index] = model.get("jumlah");
casev[index] ="0";
} else if(model.get("produk")==="Case"){
casev[index] = model.get("jumlah");
tshirtv[index] ="0";
}
})
tshirtv = tshirtv.filter(()=>true)
casev = casev.filter(()=>true)
var series = [
{
name : "T-shirt",
data : tshirtv
},
{
name : "Case",
data : casev
}
]
//Line Chart
var data = {
labels : labels,
series : series
}
var option = {
showArea : true,
lineSmooth : false,
showPoint : true,
chartPadding : {
bottom:60,
top:60,
},
axisX : {
showGrid:false,
},
axisY : {
onlyInteger : true,
},
plugins : [
Chartist.plugins.ctAxisTitle({
axisX: {
axisClass: 'ct-axis-title',
offset: {
x: 0,
y: 50
},
textAnchor: 'middle'
},
axisY: {
axisTitle: 'Jumlah Penjualan',
axisClass: 'ct-axis-title',
offset: {
x: 0,
y: 0
},
textAnchor: 'middle',
flipTitle: false
}
}),
Chartist.plugins.ctPointLabels({
textAnchor : "middle"
}),
Chartist.plugins.legend()
]
}
//Donut Chart
var data2 = {
labels : ['T-Shirt', 'Case'],
series : [12,23]
}
var option2 = {
chartPadding : {
top : 0,
},
labelInterpolationFnc : function(value,series){
return value + ": " +data2.series[series].value
},
donut:true,
donutWidth : 60,
plugins : [
Chartist.plugins.legend()
]
}
new Chartist.Line($('.statistic',this.el)[0],data,option)
//new Chartist.Pie($('.statistic2',this.el)[0],data2,option2)
})
programming.wrapper.show(chartView)
} else {
chartView = new Chart.notfound()
programming.wrapper.show(chartView)
}
}
}
})

Add options to Charts.js

I cannot figure out where to put the options in Chart.js on my bar graph. (I am not a programmer.)
Here is the code that I have:
<canvas id="canvasOne" height="450" width="450"></canvas>
<script>
var barChartData = {
labels: ["test "],
datasets: [
{
fillColor: "#153b63",
data: [61]
},
{
fillColor: "#e99555",
data: [25]
}]
}
var myLine = new Chart(document.getElementById("canvasOne").getContext("2d")).Bar(barChartData);
</script>
All I want to do is hide the labels. The option to do this exists, and it's called scaleShowLabels: false, but I have no idea where to put it in the code. The documentation does not show this either.
You need to pass it as an option:
options = {
scaleShowLabels : false
};
var barChartData = {
labels : ["test "],
datasets : [
{
fillColor : "#153b63",
data : [61]
},
{
fillColor : "#e99555",
data : [25]
}
]
};
var myLine = new Chart(document.getElementById("canvasOne").getContext("2d")).Bar(barChartData, options);

In jqxGrid, how do I add a new calculated column from JSON data?

In jqxGrid, how do I add a new calculated column from JSON data?
My JSON data has fields baseQuantity and unitCost. I want to add a new field called totalCost which would be baseQuantity * unitCost.
I'm trying to add the data using loadComplete, but it doesn't seem to work.
ANOTHER alternative I could do is to loop through objData and inject a new field with the calculated value. But aside from that, is there any way I could do it via jqxGrid's API?
var jsonString = [{ "baseQuantity":"1", "unitCost":"2"}, { "baseQuantity":"3", "unitCost":"4"}];
var objData = $.parseJSON(jsonString);
var srcData = {
datatype: "json",
datafields: [
{ name : 'baseQuantity', type : 'number' },
{ name : 'unitCost', type : 'number' }
],
localdata : objData
};
var adapterData = new $.jqx.dataAdapter(srcData, {
loadComplete: function (records) {
var modifiedDataArray = new Array();
for (var i = 0; i < records.length; i++) {
var modifiedData = records[i];
modifiedData.totalPayment = modifiedData.baseQuantity * modifiedData.unitCost;
modifiedDataArray.push(programme);
}
return modifiedDataArray;
}
});
$('div#jqxGrid').jqxGrid({
width: '100%',
source: adapterData,
theme: getTheme(),
pageable: true,
autoheight: true,
sortable: true,
altrows: true,
columns: [
{ datafield: 'baseQuantity', text: 'Base Qty.', width: 120 }
{ datafield: 'unitCost', text: 'Unit Payment' , width: 120 }
]
});
Use the cellrenderer function:
http://www.jqwidgets.com/jquery-widgets-documentation/documentation/jqxgrid/jquery-grid-api.htm
{ text: 'totalCost', datafield: 'totalCost', width: 70, cellsalign: 'right', columntype: 'number',
cellsrenderer: function (row, columnfield, value, defaulthtml, columnproperties) {
var rowData = $("#jqxGrid").jqxGrid('getrowdata', row);
return rowData.baseQuantity * rowData.unitCost;
}
}
Don't use the event "loadComplete" but "beforeLoadComplete" instead. Here is an example :
var dataAdapter = new $.jqx.dataAdapter(source,
{
beforeLoadComplete: function (records) {
records[0]['firstname'] = "Michael";
return records;
}
}
);
Than you can loop through all records, and generate you computed column. This is the official solution they seems to give here : http://www.jqwidgets.com/community/topic/computed-column/

Categories

Resources