Chart.JS - a Graphing object

ChartJs

ChartJs is an opensource graphing object used in an HTML/JavaScript environment.

Scattergraph

A scattergraph is a type of chart which has many points on it, placed on it by an xy coordinates. Usually the amount of dots gives the viewer a pattern which can be used to make decisions.

Here is a sample of the code

Put this someplace on the webpage

1
2
3
<div style="width:75%">
<canvas id="pickChart"></canvas>
</div>

Then you have javascript code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
function pnlExpandPcReceivedData(d) {
var ctx = document.getElementById('pickChart');

//try {
var scatterChart = new Chart(ctx,
{
type: 'scatter',
data: {
datasets: [
{
label: 'LOE/BangAvg',
//data: [{x: 4, y:2}]
backgroundColor: "rgba(255,100,149,237)",
borderColor: "#000",
data: JSON.parse(d)
}
]
},
options: {
scales: {
yAxes: [{
scaleLabel: {
type: 'linear',
display: true,
labelString: "justification / BangAvg"
},
ticks: {
stepSize: 0.9
}
}],
xAxes: [{
scaleLabel: {
type: 'linear',
position: 'bottom',
display: true,
labelString: "LOE Cost"
}
}]

},
legend: {
display: false
},
title: {
display: true,
text: 'Cost vs LOE'
},
onClick: function (event, array) {
// array is an array of object but i cannot
// find the type of object

},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
return data['datasets'][0]['data'][tooltipItem['index']].value + ' - ' +data['datasets'][0]['data'][tooltipItem['index']].lable;
}
}
}
}
});
//} catch (e) {
// alert(e);
//}

ctx.onclick = function(evt) {
try {
var activePoint = scatterChart.getElementAtEvent(evt)[0];
var data = activePoint._chart.data;
var datasetIndex = activePoint._datasetIndex;
var label = data.datasets[datasetIndex].label;
var value = data.datasets[datasetIndex].data[activePoint._index];
console.log('taskid:', value.value);
openTab('task_edit.aspx?id=' + value.value);
} catch (e) {
// error - they clicked, but not on an id
}
};
}

There’s a lot of code here, lets review it in chunks

1
function pnlExpandPcReceivedData(d) {

Here I am declaring a function. When it is called it is being passed a set of data. This data has x, y, lable, and value. For example
[{x: 4, y:2, lable:’hello’, value:’14’}, {x: 6, y:3, lable:’second point’, value:’21’}].
This sample creates 2 records.

1
var ctx = document.getElementById('pickChart');

This gets data the UI canvas tag that was created earlier. This will hold the chart.

1
var scatterChart = new Chart(ctx,

This is creating the chart object and binding it to the control we found above

1
2
3
4
5
6
7
8
9
10
11
12
13
{
type: 'scatter',

data: {
datasets: [
{
label: 'LOE/BangAvg',
backgroundColor: "rgba(255,100,149,237)",
borderColor: "#000",
data: JSON.parse(d)
}
]
},

It’s an odd syntax, but the data, contains a datasets, and you can have 1 or more blocks inside this datasets block. In my case I have one dataset, but I could have a second set of data which would render in different colors, etc.

label: Actually, I dont think this is needed due to my use of options, tool tips, and that onpostback function.

data: (the second one) is where the point data is held. In my case I passed in a string variable. I needed the JSON.parse(d) method to convert this into an array useful to the data property.

1
options: {

The options block is where you can start customizing the layout of the graphic.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
scales: {
yAxes: [{
scaleLabel: {
type: 'linear',
display: true,
labelString: "justification / BangAvg"
},
ticks: {
stepSize: 0.9
}
}],
xAxes: [{
scaleLabel: {
type: 'linear',
position: 'bottom',
display: true,
labelString: "LOE Cost"
}
}]

Scales used to define the lables, shown on the side and botton of the form.

type: important, read about this but for me linear will always work.

1
2
3
4
},
legend: {
display: false
},

legend: system creates a default legend - pretty cool, it leverages that label property of the dataset. There are other commands tho and this sample uses those.

1
2
3
4
title: {
display: true,
text: 'Cost vs LOE'
},

Title is placed on the top of the graphic. Something happened, when I used this it cut off the top of the chart for the title and I lost a few of the points. So I addded the step size which I’m hoping forces the graph to never render a point at the very top.

1
2
3
4
5
onClick: function (event, array) {
// array is an array of object but i cannot
// find the type of object

},

I could not get this to work, but I was trying at this point to get a click routine to trigger whenever a click was activated. I figured out how to do that below.

1
2
3
4
5
6
7
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
return data['datasets'][0]['data'][tooltipItem['index']].value + ' - ' +data['datasets'][0]['data'][tooltipItem['index']].lable;
}
}
}

Tooltips are displayed whenever the cursor hovers over a point. in this code sample it’s going to the first dataset. It’s pulling the value and the lable out and displaying that information on the tooltip.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
}
});
//} catch (e) {
// alert(e);
//}

ctx.onclick = function(evt) {
try {
var activePoint = scatterChart.getElementAtEvent(evt)[0];
var data = activePoint._chart.data;
var datasetIndex = activePoint._datasetIndex;
var label = data.datasets[datasetIndex].label;
var value = data.datasets[datasetIndex].data[activePoint._index];
console.log('taskid:', value.value);
openTab('task_edit.aspx?id=' + value.value);
} catch (e) {
// error - they clicked, but not on an id
}
};

This last statement adds an onclick event to the chart. In this case it returns an array (because I assume a point could overwrite other points) and it opens a tab and renders the task_edit.aspx page passing it the value from the data that was passed in.

If the user clicks on the graph at a location without a point an error is thrown, since I do not have an activity for this sort of function, i just catch the error and exit the function.

1
}

There are a few other things to know.

At the top of the page I had to include the chart tool

 <script src="js/chartJs272/Chart.bundle.min.js" ></script>

The pnlExpandPcReceivedData() function was originally called by another javascript routine that was hooked to a button it looks like the following.

  function pnlExpandPc() {
     //alert("Expand");
     $('#pnlJsPickChart').show();
     $('#btnCollapsePc').show();
     $('#btnExpandPc').hide();
     $('#<%= txtExpColStatePc.ClientID%>').val("E");

     var projectTaskId = $('#<%= lblProjectTaskID.ClientID%>').text();

     var data = {
         "projectTaskId" : projectTaskId
     }

     $.ajax({
         type: 'POST',
         url: 'ajax.aspx/Task_GetPicklist',
         data: JSON.stringify(data),
         contentType: "application/json; charset=utf-8",
         success: function (msg) {
             pnlExpandPcReceivedData(msg.d);
         },
         error: function (msg) {
             alert(msg);
         }
     });
 }

Basically it calls an ajax routine which gets a set of data. On success it passes that data to the pnlExpandPcReceivedData() function which in turns renders the chart.

The ajax routine resembles the following

<System.Web.Services.WebMethod()>
<Script.Services.ScriptMethod(ResponseFormat:=Script.Services.ResponseFormat.Json)>
Public Shared Function Task_GetPicklist(
         projectTaskId as string) _
   As String

    Return dd_bl.Task.GetPicklist(projectTaskId)
End Function

It’s written in basic, but could had been C#, it acts as an interface betewen between the webservice and the function that get’s the data. Here is what that program looks like the following:

Public Shared Function GetPicklist(
                  projectTaskId As string) _
                As String

    dim sql as String _
            = GetSql("ID, Title, loeCost, BangAvg",
                       "(loeCost>0.00) and (BangAvg>0.00)",
                       projectTaskId)
    Dim ds As System.Data.DataSet _
            = si.DB.DsGet(sql, "aspxConnectionString")


    dim out as new List (of TaskPicklistJson)

    For Each aRow As System.Data.DataRow In ds.Tables(0).Rows
        dim p As New TaskPicklistJson
        p.value=aRow("id").ToString 
        p.x=aRow("LOE Costs").ToString
        p.y=aRow("bangAvg").ToString
        p.lable=aRow("Title").ToString 

        out.Add(p)
    Next
    dim serializer as New JavaScriptSerializer()

    Return serializer.Serialize(out)

End Function

It’s another basic function, it constructs a list of TaskPicklistJson objects, and then returns a serialized version of that list.

References

Return to [[JavaScript]] Home page.