B4J Tutorial [ABMaterial]: Me like Donuts

Mashiane

Expert
Licensed User
Ola

So me runs into this nice charting library, morris chart. Me see a nice donut. Me likes donut.

Donut.gif


Their examples are quite nice and straight forward and easy to implement using Custom Component. The hovering effects on the charts are also impressive. So I start testing the implementation with the various options. Mind you still need to finish the rest and add some colors.

Let's look at some of the charts doable below..., I like the ease of just feeding this a list of records, especially from a DBUtils.ExecuteMaps call, and yes, you can add individual records.

Usage:
BuildPage

B4X:
page.AddExtraCSSFile("custom/morris.css")
page.AddExtraJavaScriptFile("custom/raphael.min.js")
page.AddExtraJavaScriptFile("custom/morris.js")

Then in [B]ConnectPage[/B], you can define the chart etc.
Explore Components Source Code
 
Last edited:

Mashiane

Expert
Licensed User
A simple area chart... (Basic example that explains everything)

SimpleArea.png


B4X:
'you can get this with DbUtils.ExecuteMaps
    Dim records As List
    records.Initialize
    'records.Add(CreateMap("x": "2010 Q4", "y": 3, "z": 7))
    records.Add(CreateMap("x": "2011 Q1", "y": 3, "z": 4))
    records.Add(CreateMap("x": "2011 Q2", "y": Null, "z": 1))
    records.Add(CreateMap("x": "2011 Q3", "y": 2, "z": 5))
    records.Add(CreateMap("x": "2011 Q4", "y": 8, "z": 2))
     'records.Add(CreateMap("x": "2012 Q1", "y": 4, "z": 4))
    
    'define the morrischart
    Dim mmc As MashMorrisChart
    mmc.Initialize(page,"mmc","250px")
    'define the chart type
    mmc.ChartType = mmc.EnumMorrisChartType.Area
    'define the x axis, the column to read x values, the angle of the x values and whether the x values are numberic/not
    mmc.SetXAxis("x",0,False)
    'add a series, we want to plot y and z values
    mmc.AddSeries("y","Y","")
    mmc.AddSeries("z","Z","")
    'add the values to plot to the chart
    mmc.SetData(records)
    page.cell(3,1).AddComponent(mmc.ABMComp)
 

Mashiane

Expert
Licensed User
Line Charts (demonstrating single chart record addition)

LinChart.gif


B4X:
'formatting dates
    Dim mmc4 As MashMorrisChart
    mmc4.Initialize(page,"mmc4", "250px")
    'define the x axis, the column to read x values, the angle of the x values and whether the x values are numberic/not
    mmc4.SetXAxis("period",0,False)
    mmc4.AddSeries("licensed","Licensed","")
    mmc4.AddSeries("sorned","SORN","")
    mmc4.AddData(CreateMap("period": "2012-10-01", "licensed": 3407, "sorned": 660))
    mmc4.AddData(CreateMap("period": "2012-09-30", "licensed": 3351, "sorned": 629))
    mmc4.AddData(CreateMap("period": "2012-09-29", "licensed": 3269, "sorned": 618))
    mmc4.AddData(CreateMap("period": "2012-09-20", "licensed": 3246, "sorned": 661))
    mmc4.AddData(CreateMap("period": "2012-09-19", "licensed": 3257, "sorned": 667))
    mmc4.AddData(CreateMap("period": "2012-09-18", "licensed": 3248, "sorned": 627))
    mmc4.AddData(CreateMap("period": "2012-09-17", "licensed": 3171, "sorned": 660))
    mmc4.AddData(CreateMap("period": "2012-09-16", "licensed": 3171, "sorned": 676))
    mmc4.AddData(CreateMap("period": "2012-09-15", "licensed": 3201, "sorned": 656))
    mmc4.AddData(CreateMap("period": "2012-09-10", "licensed": 3215, "sorned": 622))
    page.cell(5,1).AddComponent(mmc4.ABMComp)
 

Mashiane

Expert
Licensed User
X Axis Label Angle

You can easily change the angle of the X Axis Labels by just updating it in the SetXAxis Method.

Lets make the angle 60 degrees by (replace 0 (zero) in SetXAxis with 60

B4X:
mmc5.SetXAxis("period",60,False)
XAxisLabelAngle.png
 

Mashiane

Expert
Licensed User
Stacked Bar Chart...

Stacked.png


We have done two major things here..

1. Made the angle of the X Axis to be 90 degress and then
2. Turned the stacked property to true.

B4X:
'bar chart
    Dim mmc6 As MashMorrisChart
    mmc6.Initialize(page,"mmc6", "250px")
    'define the chart type
    mmc6.ChartType = mmc6.EnumMorrisChartType.Bar
    'define the x axis, the column to read x values, the angle of the x values and whether the x values are numberic/not
    mmc6.SetXAxis("x",90,False)
    'add a series, we want to plot y and z values
    mmc6.AddSeries("y","Y","")
    mmc6.AddSeries("z","Z","")
    'add the values to plot to the chart
    mmc6.SetData(records)
    mmc6.stacked = True
    page.cell(6,1).AddComponent(mmc6.ABMComp)
 

Mashiane

Expert
Licensed User
Plotting Time

B4X:
Dim mmc7 As MashMorrisChart
    mmc7.Initialize(page,"mmc7", "250px")
    mmc7.ChartType = mmc7.EnumMorrisChartType.Area
    mmc7.SetXAxis("x",0,False)
    mmc7.AddSeries("y","Y","")
    mmc7.AddSeries("z","Z","")
    mmc7.AddData(CreateMap("x": "2013-03-30 22:00:00", "y": 3, "z": 3))
    mmc7.AddData(CreateMap("x": "2013-03-31 00:00:00", "y": 2, "z": 0))
    mmc7.AddData(CreateMap("x": "2013-03-31 02:00:00", "y": 0, "z": 2))
    mmc7.AddData(CreateMap("x": "2013-03-31 04:00:00", "y": 4, "z": 4))
    page.cell(6,2).AddComponent(mmc7.ABMComp)
Whilst you can plot quarters, weeks ('2011 W07'), days (as demonstrated above), you can also plot time related charts as demonstrated below. Below is an area chart showing DST.

PlotTime.png
 

Mashiane

Expert
Licensed User
Text Labels

By turning off parseTime = false, the x axis values are not DateTime based.

B4X:
Dim mmc8 As MashMorrisChart
    mmc8.Initialize(page,"mmc8", "250px")
    mmc8.SetXAxis("elapsed",0,False)
    mmc8.AddSeries("value","Value","")
    mmc8.AddData(CreateMap("elapsed": "I", "value": 34))
    mmc8.AddData(CreateMap("elapsed": "II", "value": 24))
    mmc8.AddData(CreateMap("elapsed": "III", "value": 3))
    mmc8.AddData(CreateMap("elapsed": "IV", "value": 12))
    mmc8.AddData(CreateMap("elapsed": "V", "value": 13))
    mmc8.AddData(CreateMap("elapsed": "VI", "value": 22))
    mmc8.AddData(CreateMap("elapsed": "VII", "value": 5))
    mmc8.AddData(CreateMap("elapsed": "VIII", "value": 26))
    mmc8.AddData(CreateMap("elapsed": "IX", "value": 12))
    mmc8.AddData(CreateMap("elapsed": "X", "value": 19))
    mmc8.parseTime = False
    page.cell(7,1).AddComponent(mmc8.ABMComp)

TextLabels.png
 

Mashiane

Expert
Licensed User
The example below, by just setting units = "%" ensures that your labels are are percentages.

DonutX.png


B4X:
Dim mmc9 As MashMorrisChart
    mmc9.Initialize(page,"mmc9", "250px")
    mmc9.ChartType = mmc7.EnumMorrisChartType.Donut
    mmc9.AddSlice("foo",70)
    mmc9.AddSlice("bar", 15)
    mmc9.AddSlice("baz", 10)
    mmc9.AddSlice("A really really long labe", 5)
    mmc9.OutputPercentage = True
    page.cell(7,2).AddComponent(mmc9.ABMComp)
The OutputPercentage property only works with the Donut to put the % sign on the label. For the line charch, we used..

B4X:
mmc8.units = "%"
 

Mashiane

Expert
Licensed User
Decided to add some bling to the Donut..

This adds some different colors, ability to set the color of the label and the background for each item.

DonutUpdate.gif


B4X:
Dim mmc9 As MashMorrisChart
    mmc9.Initialize(page,"mmc9", "250px")
    mmc9.ChartType = mmc7.EnumMorrisChartType.Donut
    mmc9.AddSlice("foo",70,mmc9.EnumColor.red)
    mmc9.AddSlice("bar", 15, mmc9.EnumColor.green)
    mmc9.AddSlice("baz", 10, mmc9.EnumColor.blue)
    mmc9.AddSlice("A really really long labe", 5, mmc9.EnumColor.cyan)
    mmc9.OutputPercentage = True
    mmc9.labelColor = mmc9.EnumColor.black
    mmc9.backgroundColor = mmc9.EnumColor.white
    page.cell(7,2).AddComponent(mmc9.ABMComp)
 

Mashiane

Expert
Licensed User
Complete Example Code: (Component Code In First Post)

NB: Colors for series are compulsory...

B4X:
'you can get this with DbUtils.ExecuteMaps
    Dim records As List
    records.Initialize
    'records.Add(CreateMap("x": "2010 Q4", "y": 3, "z": 7))
    records.Add(CreateMap("x": "2011 Q1", "y": 3, "z": 4))
    records.Add(CreateMap("x": "2011 Q2", "y": Null, "z": 1))
    records.Add(CreateMap("x": "2011 Q3", "y": 2, "z": 5))
    records.Add(CreateMap("x": "2011 Q4", "y": 8, "z": 2))
     'records.Add(CreateMap("x": "2012 Q1", "y": 4, "z": 4))
    
    'define the morrischart
    Dim mmc As MashMorrisChart
    mmc.Initialize(page,"mmc","250px")
    'define the chart type
    mmc.ChartType = mmc.EnumMorrisChartType.Area
    'define the x axis, the column to read x values, the angle of the x values and whether the x values are numberic/not
    mmc.SetXAxis("x",0)
    'add a series, we want to plot y and z values
    mmc.AddSeries("y","Y",mmc.EnumColor.amber)
    mmc.AddSeries("z","Z",mmc.EnumColor.blue)
    'add the values to plot to the chart
    mmc.SetData(records)
    page.cell(3,1).AddComponent(mmc.ABMComp)
    
    
    Dim mmc1 As MashMorrisChart
    mmc1.Initialize(page,"mmc1", "250px")
    'define the chart type
    mmc1.ChartType = mmc.EnumMorrisChartType.Area
    'define the x axis, the column to read x values, the angle of the x values and whether the x values are numberic/not
    mmc1.SetXAxis("x",0)
    'add a series, we want to plot y and z values
    mmc1.AddSeries("y","Y",mmc1.EnumColor.cyan)
    mmc1.AddSeries("z","Z",mmc1.EnumColor.deeporange)
    'add the values to plot to the chart
    mmc1.SetData(records)
    'chart behave like a line chart
    mmc1.behaveLikeLine = True
    page.cell(3,2).AddComponent(mmc1.ABMComp)

    'bar chart
    Dim mmc2 As MashMorrisChart
    mmc2.Initialize(page,"mmc2", "250px")
    'define the chart type
    mmc2.ChartType = mmc.EnumMorrisChartType.Bar
    'define the x axis, the column to read x values, the angle of the x values and whether the x values are numberic/not
    mmc2.SetXAxis("x",0)
    'add a series, we want to plot y and z values
    mmc2.AddSeries("y","Y",mmc2.EnumColor.green)
    mmc2.AddSeries("z","Z",mmc2.EnumColor.purple)
    'add the values to plot to the chart
    mmc2.SetData(records)
    page.cell(4,1).AddComponent(mmc2.ABMComp)
    
    'bar chart
    Dim mmc3 As MashMorrisChart
    mmc3.Initialize(page,"mmc3", "250px")
    'define the chart type
    mmc3.ChartType = mmc.EnumMorrisChartType.Bar
    'define the x axis, the column to read x values, the angle of the x values and whether the x values are numberic/not
    mmc3.SetXAxis("x",0)
    'add a series, we want to plot y and z values
    mmc3.AddSeries("y","Y",mmc3.EnumColor.amber)
    mmc3.AddSeries("z","Z",mmc3.EnumColor.blue)
    'add the values to plot to the chart
    mmc3.SetData(records)
    mmc3.axes = False
    page.cell(4,2).AddComponent(mmc3.ABMComp)
    
    'formatting dates
    Dim mmc4 As MashMorrisChart
    mmc4.Initialize(page,"mmc4", "250px")
    'define the x axis, the column to read x values, the angle of the x values and whether the x values are numberic/not
    mmc4.SetXAxis("period",0)
    mmc4.AddSeries("licensed","Licensed",mmc4.EnumColor.brown)
    mmc4.AddSeries("sorned","SORN",mmc4.EnumColor.indigo)
    mmc4.AddData(CreateMap("period": "2012-10-01", "licensed": 3407, "sorned": 660))
    mmc4.AddData(CreateMap("period": "2012-09-30", "licensed": 3351, "sorned": 629))
    mmc4.AddData(CreateMap("period": "2012-09-29", "licensed": 3269, "sorned": 618))
    mmc4.AddData(CreateMap("period": "2012-09-20", "licensed": 3246, "sorned": 661))
    mmc4.AddData(CreateMap("period": "2012-09-19", "licensed": 3257, "sorned": 667))
    mmc4.AddData(CreateMap("period": "2012-09-18", "licensed": 3248, "sorned": 627))
    mmc4.AddData(CreateMap("period": "2012-09-17", "licensed": 3171, "sorned": 660))
    mmc4.AddData(CreateMap("period": "2012-09-16", "licensed": 3171, "sorned": 676))
    mmc4.AddData(CreateMap("period": "2012-09-15", "licensed": 3201, "sorned": 656))
    mmc4.AddData(CreateMap("period": "2012-09-10", "licensed": 3215, "sorned": 622))
    page.cell(5,1).AddComponent(mmc4.ABMComp)
    
    'formatting dates
    Dim mmc5 As MashMorrisChart
    mmc5.Initialize(page,"mmc5", "250px")
    'define the x axis, the column to read x values, the angle of the x values and whether the x values are numberic/not
    mmc5.SetXAxis("period",60)
    mmc5.AddSeries("licensed","Licensed",mmc5.EnumColor.yellow)
    mmc5.AddSeries("sorned","SORN",mmc5.EnumColor.purple)
    mmc5.AddData(CreateMap("period": "2012-10-01", "licensed": 3407, "sorned": 660))
    mmc5.AddData(CreateMap("period": "2012-09-30", "licensed": 3351, "sorned": 629))
    mmc5.AddData(CreateMap("period": "2012-09-29", "licensed": 3269, "sorned": 618))
    mmc5.AddData(CreateMap("period": "2012-09-20", "licensed": 3246, "sorned": 661))
    mmc5.AddData(CreateMap("period": "2012-09-19", "licensed": 3257, "sorned": 667))
    mmc5.AddData(CreateMap("period": "2012-09-18", "licensed": 3248, "sorned": 627))
    mmc5.AddData(CreateMap("period": "2012-09-17", "licensed": 3171, "sorned": 660))
    mmc5.AddData(CreateMap("period": "2012-09-16", "licensed": 3171, "sorned": 676))
    mmc5.AddData(CreateMap("period": "2012-09-15", "licensed": 3201, "sorned": 656))
    mmc5.AddData(CreateMap("period": "2012-09-10", "licensed": 3215, "sorned": 622))
    page.cell(5,2).AddComponent(mmc5.ABMComp)
    
    
    
    'bar chart
    Dim mmc6 As MashMorrisChart
    mmc6.Initialize(page,"mmc6", "250px")
    'define the chart type
    mmc6.ChartType = mmc6.EnumMorrisChartType.Bar
    'define the x axis, the column to read x values, the angle of the x values and whether the x values are numberic/not
    mmc6.SetXAxis("x",90)
    'add a series, we want to plot y and z values
    mmc6.AddSeries("y","Y",mmc6.EnumColor.amber)
    mmc6.AddSeries("z","Z",mmc6.EnumColor.blue)
    'add the values to plot to the chart
    mmc6.SetData(records)
    mmc6.stacked = True
    page.cell(6,1).AddComponent(mmc6.ABMComp)
    
    'bar chart
    Dim mmc7 As MashMorrisChart
    mmc7.Initialize(page,"mmc7", "250px")
    mmc7.ChartType = mmc7.EnumMorrisChartType.Area
    mmc7.SetXAxis("x",0)
    mmc7.AddSeries("y","Y",mmc7.EnumColor.amber)
    mmc7.AddSeries("z","Z",mmc7.EnumColor.blue)
    mmc7.AddData(CreateMap("x": "2013-03-30 22:00:00", "y": 3, "z": 3))
    mmc7.AddData(CreateMap("x": "2013-03-31 00:00:00", "y": 2, "z": 0))
    mmc7.AddData(CreateMap("x": "2013-03-31 02:00:00", "y": 0, "z": 2))
    mmc7.AddData(CreateMap("x": "2013-03-31 04:00:00", "y": 4, "z": 4))
    page.cell(6,2).AddComponent(mmc7.ABMComp)
    
    'bar chart
    Dim mmc8 As MashMorrisChart
    mmc8.Initialize(page,"mmc8", "250px")
    mmc8.SetXAxis("elapsed",0)
    mmc8.AddSeries("value","Value",mmc8.EnumColor.lightblue)
    mmc8.AddData(CreateMap("elapsed": "I", "value": 34))
    mmc8.AddData(CreateMap("elapsed": "II", "value": 24))
    mmc8.AddData(CreateMap("elapsed": "III", "value": 3))
    mmc8.AddData(CreateMap("elapsed": "IV", "value": 12))
    mmc8.AddData(CreateMap("elapsed": "V", "value": 13))
    mmc8.AddData(CreateMap("elapsed": "VI", "value": 22))
    mmc8.AddData(CreateMap("elapsed": "VII", "value": 5))
    mmc8.AddData(CreateMap("elapsed": "VIII", "value": 26))
    mmc8.AddData(CreateMap("elapsed": "IX", "value": 12))
    mmc8.AddData(CreateMap("elapsed": "X", "value": 19))
    mmc8.parseTime = False
    mmc8.postunits = "%"
    page.cell(7,1).AddComponent(mmc8.ABMComp)
    
    Dim mmc9 As MashMorrisChart
    mmc9.Initialize(page,"mmc9", "250px")
    mmc9.ChartType = mmc7.EnumMorrisChartType.Donut
    mmc9.AddSlice("foo",70,mmc9.EnumColor.red)
    mmc9.AddSlice("bar", 15, mmc9.EnumColor.green)
    mmc9.AddSlice("baz", 10, mmc9.EnumColor.blue)
    mmc9.AddSlice("A really really long labe", 5, mmc9.EnumColor.cyan)
    mmc9.OutputPercentage = True
    mmc9.labelColor = mmc9.EnumColor.black
    '' mmc9.backgroundColor = mmc9.EnumColor.white
    page.cell(7,2).AddComponent(mmc9.ABMComp)
 

Mashiane

Expert
Licensed User
Hello, excellent work. But, how can I test if I do not know in which port I will load the sample page?
Hi @Johan Hormaza , thanks. Im not sure I get your question. You want to test the component?

If so, you need to create a normal ABM app, add a page to it and just define the component on the page. It will use the same port as your defined port for the app.
 

Johan Hormaza

Active Member
Licensed User
Hi @Johan Hormaza , thanks. Im not sure I get your question. You want to test the component?

If so, you need to create a normal ABM app, add a page to it and just define the component on the page. It will use the same port as your defined port for the app.
Ok ready, I already understood thanks for this great contribution.
 

Mashiane

Expert
Licensed User
This example draws up a bar chart with two series from different data sets of information. See the SQL statements to extracts the records.

B4X:
chartcompletedprojects.Initialize(page,"chartcompletedprojects","300px")
    chartcompletedprojects.ChartType = chartcompletedprojects.EnumMorrisChartType.Bar
    chartcompletedprojects.SetXAxis("x",0)
    chartcompletedprojects.behavelikeline = False
    chartcompletedprojects.axes = True
    chartcompletedprojects.parsetime = False
    chartcompletedprojects.smooth = True
    chartcompletedprojects.grid = True
    chartcompletedprojects.resize = True
    chartcompletedprojects.stacked = False
    chartcompletedprojects.hideHover = False
    chartcompletedprojects.postunits = ""
    chartcompletedprojects.outputpercentage = False
    chartcompletedprojects.backgroundcolor = chartcompletedprojects.EnumColor.transparent
    chartcompletedprojects.labelcolor = chartcompletedprojects.EnumColor.black
    chartcompletedprojects.preunits = ""
    chartcompletedprojects.xLabelFormat = ""
    chartcompletedprojects.yLabelFormat =  ""
    Dim jSQL As SQL = ABMShared.SQLGet
    chartcompletedprojects.AddSeries("a","Total",chartcompletedprojects.EnumColor.blue)
    chartcompletedprojects.AddSeries("b","Completed",chartcompletedprojects.EnumColor.green)
    Dim recm As Map: recm.Initialize
    recm.put("x","Projects (Count)")
    Dim sa As String = ABMShared.SQLSelectSingleResult(jSQL, "select (COUNT(id)) As a from projects", Null)
    recm.put("a",sa)
    Dim sb As String = ABMShared.SQLSelectSingleResult(jSQL, "select count(id) as b from projects where actualprogress = 100", Null)
    recm.put("b",sb)
    chartcompletedprojects.AddData(recm)
    ABMShared.SQLClose(jSQL)
    page.Cell(2,1).AddComponent(chartcompletedprojects.ABMComp)
 
Top