Combo Chart with the Free JS Chart Library

MindFusion Free Js Chart is a charting library that enables you to create and customize the most popular chart types in pure JavaScript. The library is free for commercial use. No attribution is required.

Here we will take a brief look at the steps you need to take to build this beautiful combo chart from scratch.

I. Setup

The chart needs an HTML Canvas element to render onto and we create one in our web page:

<canvas id="combiChart" width="400" height="400"></canvas>

It is important to provide an id to the Canvas element, because we will reference it from the JavaScript code.

We also need to reference the two JavaScript libraries that provide the charting functionality:

<script type="text/javascript" src="Scripts/MindFusion.Common.js"></script>
<script type="text/javascript" src="Scripts/MindFusion.Charting.js"></script>

And we add a reference to another JavaScript file, that will hold the code for the combo chart:

<script type="text/javascript" src="CombiChart.js"></script>

II. Chart Settings

We create the chart control using the HTML Element of the Canvas:

var chartEl = document.getElementById('combiChart');
chartEl.width = chartEl.offsetParent.clientWidth;
chartEl.height = chartEl.offsetParent.clientHeight;

var chart = new Controls.BarChart(chartEl);

We create a bar chart, to which we will add line rendering capabilities. It is also possible to create a line chart and add rendering of bars to it.

Next, we add a title and a grid to the chart:

chart.title = "Corporate Sales";
chart.titleMargin = new Charting.Margins(0, 20, 0, 20);
chart.gridType = GridType.Horizontal;
chart.barSpacingRatio = 1.5;

The barSpacingRatio indicates how much free space will be left between the group of bars relative to the bar width.

III. Chart Series

We create two series for the bars. Free JS Chart offers a variety of series types to choose from and we use two different series for the bars. The first one is BarSeries We use it because it supports setting the X-labels by default:

var labels = new Collections.List([
	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
]);

var series1 = new Charting.BarSeries(new Collections.List([2, 4, 6,  8, 10, 12, 14, 16, 18, 20, 22, 24]), null, null, labels);

The other series of type SimpleSeries – it needs only two parameters – a list with the data and a list with the labels:

var series2 = new Charting.SimpleSeries(new Collections.List([1.4, 8, 13, 15, 13, 8, 2, 8, 13, 15, 13, 8]), null);

We don’t have labels, so we set null. Then we add the series to a collection:

var series = new Collections.ObservableCollection(new Array(series1, series2));
chart.series = series;

and assign the collection to the series property of the chart. We create the line series as an instance of the Series2D class:

//the line series
var series3 = new Charting.Series2D(new Collections.List([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]), new Collections.List([1.7, 6, 10.5, 11.5, 11.5, 10, 8, 12, 15.5, 17.5, 17.5, 16]), null);
series3.title = "Average value";
var lseries = new Collections.ObservableCollection(new Array(series3));

We add it to another collections.

The chart renders by default bars. We will make it render a line series with the help of a LineRenderer We create an instance of the LineRenderer class and provides it with the collection of series that we want to appear as lines. In our case it is just one:

//add a renderer for the line series
var lRenderer = new Charting.LineRenderer(lseries);
lRenderer.seriesStyle = new Charting.UniformSeriesStyle(lbrush, lstroke, 6);
chart.plot.seriesRenderers.add(lRenderer);

Each chart has a plot and the plot has a SeriesRenderer property that holds all renderers for the chart data. By default, a bar chart has a BarRenderer Now we add to this collection the LineRenderer that will draw the series in lseries as lines.

IV. Legend

The chart legend is rendered when showLegend is set to true:

//legend settings
chart.showLegend = true;
chart.legendMargin = new Charting.Margins(10, 10, 10, 10);
chart.legendTitle = "Year";

We set the title of the legend to be “Year” and add some margin. The labels of the legend are taken from the title property of each Series Since the series are rendered by two different renderers we need to tell the legend which are the renders so it can take the labels from both of them and not only from the bar series. This is done with the content property of the legendRenderer:

chart.legendRenderer.content = chart.plot.seriesRenderers;

V. Styling

The styling of the Series is done with different Style instances. For the bar chart we use a PerSeriesStyle instance. It colors all elements of a given series with the respective brush and stroke in the brushes and strokes instances that were provided as parameters:

var firstBrush = new Drawing.Brush("#8898B8");
var secondBrush = new Drawing.Brush("#4E567D");
var firstStroke = new Drawing.Brush("#60759f");
var secondStroke = new Drawing.Brush("#3b415e");

 // assign one brush per series
var brushes = new Collections.List([firstBrush, secondBrush]);
var strokes = new Collections.List([firstStroke, secondStroke]); 
chart.plot.seriesStyle = new Charting.PerSeriesStyle(brushes, strokes);

We assign this style to the seriesStyle property of the plot. The line series is colored with an instance of the UniformSeriesStyle class. It applies one brush and one stroke to all elements in all series:

var lbrush = new Drawing.Brush("#F49B96");
var lstroke = new Drawing.Brush("#f07b75");

//add a renderer for the line series
var lRenderer = new Charting.LineRenderer(lseries);
lRenderer.seriesStyle = new Charting.UniformSeriesStyle(lbrush, lstroke, 6);

The third argument indicates the stroke thickness. Note that now we assign the new style to the seriesStyle property of the LineRenderer rest of the settings for the chart appearance are in the theme property:

//theme settings for customizing the chart's appearance
chart.theme.legendBackground = new Drawing.Brush("#f2f2f2");
chart.theme.legendTitleFontSize = 14;
chart.theme.legendBorderStroke = new Drawing.Brush("#cecece");

chart.theme.axisTitleFontSize = 14;
chart.theme.axisLabelsFontSize = 12;
chart.theme.axisTitleFontName = "Verdana";
chart.theme.axisLabelsFontName = "Verdana";

chart.theme.dataLabelsFontName = "Verdana";
chart.theme.dataLabelsFontSize = 12;

chart.theme.gridLineStyle = Drawing.DashStyle.Dash;
chart.theme.gridColor1 = chart.theme.gridColor2 = new Drawing.Color("#ffffff");
chart.theme.gridLineColor = new Drawing.Color("#cecece");

chart.theme.highlightStroke = new Drawing.Brush("#F49B96");
chart.theme.highlightStrokeThickness = 4;

Here we change the font for the labels, style the legend and the grid. Finally, we customize the stroke that highlights chart elements when the user hovers with the mouse over them.

And that’s the end of this tutorial. You can download the full source code of the sample with the libraries of Free JS Chart from this link: http://mindfusion.eu/samples/javascript/free_chart/CombiChart.zip

You can find out more about MindFusion Free JS Chart library at https://mindfusion.eu/free-js-chart.html.

Custom Nodes in WPF Diagram

Here we will look how to define custom diagram nodes in the WPF diagram control, how to style them, how to make their properties appear in the property grid and how to save and load them with the diagram’s saveToXml and loadFromXml methods.

Here is a screenshot of our SubjectNode custom node class that is used in an application for a school curriculum:

I. XAML Template

You will need to add a XAML template for the node us you are creating a custom node because you want to have special-looking nodes. Let’s create a node that has 3 text fields and a background. We will declare the template for this node that we call SubjectNode in XAML this way:

<style targettype="local:SubjectNode">
    <Setter Property="Template">
      <Setter.Value>
        <DataTemplate DataType="local:SubjectNode">
          <Grid>

            <Rectangle
		Stroke="{Binding Stroke}"
		Fill="{Binding Background}" />

            <Grid>              

               <StackPanel Margin="4,8,0,0"  Orientation="Vertical" Grid.Column="1">
                <TextBlock Text="{Binding Subject}" FontWeight="800" Foreground="Black" />
                <TextBlock Text="{Binding Teacher}" Foreground="Blue" />
                <TextBlock Text="{Binding Remarks}" FontSize="9" Foreground="Black" />
              </StackPanel>
            </Grid>

          </Grid>
        </DataTemplate>
      </Setter.Value>
    </Setter>
  </style>

That goes in the contents of <ResourceDictionary>…..</ResourceDictionary> in the xaml file where you store this resourrce dictionary.

You see here that we use a gird as the principal layout container. There we add a rectangle, whose Fill property is bound to a property called Background in the SubjectNode. Next we have another grid that holds a StackPanel. The stack panel is with vertical orientation and it arranges the three TextBlock-s for the three custom fields of the node.

II. Declaring the Custom Node Class

When you create a custom node you need to inherit the TemplatedNode class. In the static construcotr you should call OverrideMetadata on the DefaultStyleKeyProperty to make it use the template that we’ve declared in XAML:

public class SubjectNode : TemplatedNode
{
	static SubjectNode()
	{
		DefaultStyleKeyProperty.OverrideMetadata(
			typeof(SubjectNode), new FrameworkPropertyMetadata(typeof(SubjectNode)));
}

public SubjectNode()
{			
}

Then we declare a constructor without any parameters that is required for the node to be created in XAML. If you want users to be able to create instance of the SubjectNode through drag and drop, you need to declare one more constructor:

	// Required for creating nodes by dragging them from the NodeListView
public SubjectNode(SubjectNode prototype) : base(prototype)
{
	Subject = prototype.Subject;
	Teacher = prototype.Teacher;
	Remarks = prototype.Remarks;
}

III. Properties

We declare the properties that we want: Subject, TeacherName, Remarks and Background as dependency properties the standard way:

public Brush Background
{
	get { return (Brush)GetValue(BackgroundProperty); }
	set { SetValue(BackgroundProperty, value); }
}

public static readonly DependencyProperty BackgroundProperty = DependencyProperty.Register(
	"Background",
	typeof(Brush),
	typeof(SubjectNode),
	new PropertyMetadata(new SolidColorBrush(Color.FromRgb(223, 235, 250))));

and for the text properties:

public string Remarks
{
	get { return (string)GetValue(RemarksProperty); }
	set { SetValue(RemarksProperty, value); }
}

public static readonly DependencyProperty RemarksProperty = DependencyProperty.Register(
	"Remarks",
	typeof(string),
	typeof(SubjectNode),
	new PropertyMetadata(""));

If we want the properties to be listed in a property grid we need to add a new class that inherits from DiagramNodeProperties. In it we do nothing but list the custom properties together with their type:

public class SubjectNodeProperties : DiagramNodeProperties
{
        internal string Subject;
	internal string Teacher;
	internal string Remarks;
	internal Brush Background;
} 

IV. More Options

Standard diagram nodes support undo and redo as well serialization out of the box. If you want your custom class to support those features as well you need to implement a few more methods. The methods to support undo/redo are SaveProperties and RestoreProperties. They take an instance of the DiagramItemProperties class that allows you to transfer data between the instance of the current node and its DiagramItemProperties instance that store the values of the node’s properties:

protected override void RestoreProperties(DiagramItemProperties props)
{
	base.RestoreProperties(props);
	var state = (SubjectNodeProperties)props;
	Subject = state.Subject;
	Teacher = state.Teacher;
	Remarks = state.Remarks;
	Background = state.Background;
}

protected override void SaveToXml(XmlElement xmlElement, XmlPersistContext context)
{
	base.SaveToXml(xmlElement, context);
	context.WriteString(Subject, "Subject", xmlElement);
	context.WriteString(Teacher, "Teacher", xmlElement);
	context.WriteString(Remarks, "Remarks", xmlElement);
	context.WriteBrush(Background, "Background", xmlElement);
}

The Diagram uses XML for serialization, so if you want your node to be saved and loaded correctly through the Diagram‘s saveToXml and loadFromXml methods you should implement SaveToXml and LoadFromXml. There you write the values o the custom properties of SubjectNode to XML elements and read them from XML elements as well:

protected override void SaveToXml(XmlElement xmlElement, XmlPersistContext context)
{
	base.SaveToXml(xmlElement, context);
	context.WriteString(Subject, "Subject", xmlElement);
	context.WriteString(Teacher, "Teacher", xmlElement);
	context.WriteString(Remarks, "Remarks", xmlElement);
	context.WriteBrush(Background, "Background", xmlElement);
}

protected override void LoadFromXml(XmlElement xmlElement, XmlPersistContext context)
{
	base.LoadFromXml(xmlElement, context);
	Subject = context.ReadString("Subject", xmlElement);
	Teacher = context.ReadString("Teacher", xmlElement);
	Remarks = context.ReadString("Remarks", xmlElement);
	Background = context.ReadBrush("Background", xmlElement);
}

You can download the sample that uses custom SubjectNode from http://mindfusion.eu/samples/wpf/diagram/Curriculum.zip

About Diagramming for WPF: This is the right tool to create flowcharts in WPF that always meet your requirements. The library offers more than 100 predefined node shapes, extensive event set and more than 15 exporters and importers. Each diagram that you build has a completely customizable look through styles, themes and appearance properties for each part of the flowchart. The numerous samples and detailed documentation help you learn quickly how to integrate the component into your own application. You can download the trial version, which has no feature restrictions and does not expire from the WPF Diagram Page on MindFusion website.

New Release for the Free JS Chart Library

MindFusion Free JS Chart has a new release with the following new features:

– All Series can accept now simple JavaScript array-s as arguments instead of Collections.List instances
– The ToolTip class is greatly extended with many new properties that allow you to customize the apparance and position of tooltips
– The Color.knownColors field lists all standard CSS color names
– Brush and Pen instances can be created with simple strings that specify the HTML code of the color as argument instead of Color objects.
– The yLabelAlignment property of BiaxialChart specifies horizontal alignment of Y-axis labels.
– Texts are now properly underlined when FontStyle.Underline is set.

Free JS Chart is MindFusion charting library that is offered free of charge for commercial use. No attribution is required.

More about MindFusion Free JS Chart at https://mindfusion.eu/free-js-chart.html

Appointment Scheduler in JavaScript

In this blog post we will build from scratch an appointment schedule for 4 practitioners. Each appointment is logged with the patient name and contact details. Each appointment can be scheduled in one of 4 rooms. We will also implement a check to see if the room that we want to assign to an appointment is free at the particular time.

You can run the sample online from the link below:

I. Project Setup

The first thing we’ll do is to create a DIV element and assign it an id. The JS Schedule library needs and HTML div element where the timetable will be rendered. We create one:

<div id="calendar" style="height: 100%;width: 100%"></div>

You can position the div element wherever you wish. It’s location and size determine the location and the size of the schedule.

Next, we need to reference the Schedule library file. It is called MindFusion.Scheduling. We reference it at the end of the web page, right after the closing BODY tag:

<script src="scripts/MindFusion.Scheduling.js" type="text/javascript"></script>
<script src="AppointmentSchedule.js" type="text/javascript"></script>

We will write the JavaScript code for the appointment schedule in a separate JS file, which we call AppointmentSchedule. We have added a reference to it as well.

II. Schedule Settings

In the JavaScript code behind file we first create a mapping to the MindFusion.Scheduling namespace and a reference to the Intellisense file:

/// <reference path="MindFusion.Scheduling-vsdoc.js">

var p = MindFusion.Scheduling;</reference>

Next, we use the id of the DIV element to create an instance of the Calendar class:

// create a new instance of the calendar
calendar = new p.Calendar(document.getElementById("calendar"));

We set the currentView property of the calendar to CalendarView Timetable:

// set the view to Timetable, which displays the allotment 
// of resources to distinct hours of a day
calendar.currentView = p.CalendarView.Timetable;

We use the timetableSettings property to specify the time range for each day. The starttime and endTime properties set exactly the begin and end of the time interval rendered by the timetable columns. They are measured in minutes, from midnight of the day they refer to. We want the schedule to start from 7 A that is why we set 420 as value to the startTime property – the minutes in 7 hours.

calendar.timetableSettings.startTime = 420;
calendar.timetableSettings.endTime = 1260;

The titleFormat property specifies how the date at each timetable column will be rendered. The format string follows the standard date and time pattern for JavaScript:

calendar.timetableSettings.titleFormat = "dddd d MMM yyyy";
calendar.itemSettings.tooltipFormat = "%s[hh:mm tt] - %e[hh:mm tt] %h (Contact: %d)";

The tooltipFormat follows a custom formatting pattern, used by Js Scheduler. It supports special format strings like:

  • %s for start time
  • %e for end time
  • %h for header e.g. the text of the item header
  • %d for description: the text that was assigned as a description of the appointment.

III. Contacts, Locations and Grouping

The 4 practitioners are instances of the Contact class:

resource = new p.Contact();
resource.firstName = "Dr. Lora";
resource.lastName = "Patterson";
resource.tag = 2;
calendar.schedule.contacts.add(resource);

It is important to add them to the contacts property of the schedule. The rooms where the appointments take place are Location instances:

resource.name = "Room 112";
calendar.schedule.locations.add(resource);

The grouping of the data that is rendered by the timetable is done is a method called group:

function group(value) {
	calendar.contacts.clear();
	if (value == p.GroupType.GroupByContacts) {
		// add the contacts by which to group to the calendar.contacts collection
		calendar.contacts.addRange(calendar.schedule.contacts.items());
	}
	calendar.locations.clear();
	if (value == p.GroupType.GroupByLocations) {
		// add the locations by which to group to the calendar.locations collection
		calendar.locations.addRange(calendar.schedule.locations.items());
	}
	calendar.groupType = value;
}

When we’ve created the locations and contacts, we added them to the locations and contacts collections of the schedule property of the Calendar . Grouping of the appointments is done based on the contacts and locations collections of the Calendar (not the schedule ). That is why in the group method we clear the data from the respective collection and add to it all data from the corresponding collection in the schedule Of course, we must set the groupType property to the appropriate GroupType value.

IV. Appointments

When the user selects a range of cells the new Appointment dialog appears automatically. There they can enter all necessary data. We want to implement check if a given room is free when the user tries to create a new appointment in this room. We will do the check in the handler of the itemCreating event. The itemCreating event is raised when the new item has not been ready yet and the ItemModifyingEventArgs object that is provided to the event handler gives the opportunity to cancel the event:

calendar.itemCreating.addEventListener(handleItemCreating);

function handleItemCreating(sender, args)
{
	var appLocation = args.item.location;
	
	if(appLocation != null )
	{
		if(appLocation.name != "")
		{
			var items = calendar.schedule.items.items();
			for(var i = 0; i &lt; calendar.schedule.items.count(); i++)
			{
				if( items[i].location == null)
					continue;
				
				//if the location is the same as the location of another appointment
				//at that time we cancel the creating of the appointment
				if( items[i].location.name == appLocation.name &amp;&amp; 
				overlappingAppointments (args.item, items[i]))
				{
					args.cancel = true;
					alert("The room is already taken");
				}
	
			}
		}
	}
}

We use a helper method called overlappingAppointments, whose only task is to compare the time range of two items and return true if their time span overlaps – entirely or partially.

/* checks if the time allotted to two different appointments overlaps */
function overlappingAppointments(item1, item2)
{
	if( item1.startTime &lt; item2.startTime &amp;&amp;
	    item1.endTime &lt; item2.endTime )
		  return false;
		  
	if( item1.startTime &gt; item2.endTime &amp;&amp;
	    item1.endTime &gt; item2.endTime )
		  return false;	
		  
		  return true;	  		
}

V. Timeline

Our timetable renders one day at a time. When the user wants to add an appointment that is due in 10 days, they will need to do a lot of scrolling. We can solve the problem by adding a date list at the top o the timetable. The list is another Calendar instance and but its currentView is set to CalendarView List.

We first need to add another DIV element that will be used by the constructor of the new Calendar:

<div id="datePicker" style="height: 25px; display: inline-block; margin-bottom: 10px"></div>

Then we create new Calendar object and make it render a list with dates:

datePicker = new p.Calendar(document.getElementById("datePicker"));
datePicker.currentView = p.CalendarView.List;

By default each Calendar renders the current date when it starts. We make it display a succession of 30 days. We want each day to have a prefix that indicates its week day. In addition, we hide the header of the calendar and stop the default “New Appointment” form from rendering when the user clicks on a cell:

datePicker.listSettings.visibleCells = datePicker.listSettings.numberOfCells = 30;
datePicker.listSettings.headerStyle = p.MainHeaderStyle.None;
datePicker.listSettings.generalFormat = "ddd d";
datePicker.useForms = false;

How do we “wire” the selected date in the timeline to the active date in the timetable? We handle the selectionEnd event and there we assign the selected date from the timeline as the active date of the timetable:

function handleSelectionEnd(sender, args) {
	var startDate = args.startTime;
	var endDate = args.endTime;

	// show the selected date range in the timetable
	calendar.timetableSettings.dates.clear();
	while (startDate &lt; endDate) {
		calendar.timetableSettings.dates.add(startDate);
		startDate = p.DateTime.addDays(startDate, 1);
	}
}

A timetable renders those dates, that are added to its dates property. We add just one date – the date that was selected in the list.

Let’s not forget to call the render method once we’ve finished all customizations on both Calendar render the calendar control

calendar.render();
//render the timeline control
datePicker.render();

VI. Styling

The general styling of the two Calendar instances is done with one of the predefined themes of the Js Scheduler library. First, we need to add a reference to the CSS file, where it is defined. We’ve chosen the “pastel” theme, which is defined in pastel.css:

 	 	<link rel="stylesheet" type="text/css" href="themes/pastel.css">

Then we need only to set its name as a plain string to the theme property of the two Calendar instances:

calendar.theme = "pastel";
datePicker.theme = "pastel";

There is one more styling that we want to do: we want the appointments of each practicioner to be colored in a different color. We inspect the styling o the appointment element in the browser and find out that the styling of the items is set by the class mfp-item. We create 4 different sub-classes of mfp-item for the 4 practitioners:

.itemClass0 .mfp-item
		{
			background-color: #03738C !important;
			color: #fff !important;
		}
		.itemClass1 .mfp-item
		{
			background-color: #03A6A6 !important;
			color: #fff !important;
		}
..............

Then we need to assign the correct class to the appointments. We will do this with the cssClass property of Item We handle the itemCreated event where we get information for the appointment that was created:

calendar.itemCreated.addEventListener(handleItemCreated);

function handleItemCreated(sender, args)
{
	var contact = args.item.contacts.items()[0];
	
	if(contact != null )
		args.item.cssClass = "itemClass" + contact.tag;

}

The easiest way to assign the correct CSS class to the item is to assign data that will help us generate the correct style name. We use the tag property of Contact and assign each practitioner an id that mirrors the last letter in the CSS class we should assign to the appointments associated with this contact.

With that our appointment application is finished. You can download the full source code with the libraries and styles used from this link:

Appointment Schedule in JavaScript: Source Code Download

About MindFusion JavaScript Scheduler: MindFusion Js Scheduler is the complete solution for all applications that need to render interactive timetables, event schedules or appointment calendars. Fully responsive, highly customizable and easy to integrate, you can quickly program the JavaScript scheduling library according to your needs. Find out more at https://mindfusion.eu/javascript-scheduler.html

Combination Chart in JavaScript

In this blog post we will use the Charting for JavaScript library to create the chart that you see below:

This is a combination chart has one line series and two bar series drawn in stacks. We will use the Dashboard control to combine the building elements of the chart: data series, legend, axes, title and plot.

I. HTML Setup

We need an HTML Canvas element for the chart to draw itsself onto. It is important that we give it an id. The Canvas element will render the chart and its position and size will determine where and how big the chart will be drawn.

<canvas id="dashboard" style="width: 100%; height: 100%; display: block;"></canvas>

The Dashboard control needs the MindFusion.Charting.js library. We also need the MindFusion.Drawing module for presentation classes like brushes, pens etc. We include reference to these files at the end of the web page, before the closing BODY tag:

<a href="http://Scripts/MindFusion.Common.js">http://Scripts/MindFusion.Common.js</a>
<a href="http://Scripts/MindFusion.Charting.js">http://Scripts/MindFusion.Charting.js</a>

The two library JavaScript files are in a subfolder called Scripts. We prefer to keep the JavaScript code for the combination chart separate from the web page and we include one final JS reference:

<a href="http://CombinationChart.js">http://CombinationChart.js</a>

This is the code-behind file where we will write all code that creates and customizes the combination chart.

II. Creating the Dashboard and General Chart Settings

We add mappings to the chart and drawing namespaces that we want to use. If your IDE supports Intellisense you can also add a reference to the Intellisense file.

/// 
var Charting = MindFusion.Charting;

var Controls = Charting.Controls;
var Collections = Charting.Collections;
var Drawing = Charting.Drawing;
var Components = Charting.Components;

The Dashboard class requires and HTML element in the constructor. We get the Canvas from the web page with the help of its id:

// create the dashboard
var dashboardEl = document.getElementById('dashboard');
dashboardEl.width = dashboardEl.offsetParent.clientWidth;
dashboardEl.height = dashboardEl.offsetParent.clientHeight;
var dashboard = new Controls.Dashboard(dashboardEl);

The Dashboard control is a container for all elements of a dashboard. In order to render a chart, we need a Plot element that can visualize data. We create an instance of the Plot2D class:

var plot = new Charting.Plot2D();
plot.gridType = Charting.GridType.Horizontal;
plot.gridColor1 = plot.gridColor2 = new Drawing.Color.fromArgb(200, 243, 244, 254);

Then we specify that the plot will render a horizontal grid with light gray grid lines. Each Plot2D has a seriesRenderers property that stores all -SeriesRenderer -s that are responsible for drawing correctly the data series according to their type – LineSeries BarSeries PieSeries etc. More about that later.

III. Data Series and Renderers

Each data series is represented by a class that corresponds to its type. MindFusion Charting for JavaScript has a variety of ISeries classes, some of whom can be used in different chart types. We will first use the BarSeries class to create one of the series that render bars:

// data for first bar series
var barSeries1 = new Charting.BarSeries(
		new Collections.List([9, 11, 13, 18, 19, 22, 23, 26, 29, 32, 33, 36, 41, 46, 49, 55, 57, 58, 61, 63]), //y
		null, null,
		new Collections.List(["1999", "2000", "2001", "2002", "2003", "2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", 
		"2012", "2013", "2014", "2015", "2016", "2017", "2018"]));

The BarSeries constructor requires several arguments. The first one is the data list, the second are lists with the top and inner labels, which we do not use. The last parameter are the labels for the X-axis and we set here the desired labels.

Then we set the title property of the BarSeries – it is important because it will render as a legend item.

barSeries1.title = "Total amount of goods sold";

We create then another series for the top row of bars. We don’t need any labels any more so we use now a simple Series2D instance:

var barSeries2 = new Charting.Series2D(
		new Collections.List([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]),//x
		new Collections.List([3, 4, 5, 5, 7, 8, 7, 6, 8, 15, 17, 21, 19, 18, 17, 16, 17, 19, 20, 22]),//y
		null);

barSeries2.title = "Extra production to meet demand";

The series need a SeriesRenderer that can draw them. There are different SeriesRenderer -s for the different types of series. The different SeriesRenderer instances support different ISeries classes.

In our case we want a stack bar chart and we use the BarStackRenderer . Each SeriesRenderer accepts a list with the Series instances it must render. Here is the code for the stack bars:

// draw bars
var barRenderer = new Charting.BarStackRenderer(new Collections.ObservableCollection([barSeries1, barSeries2]));
barRenderer.seriesStyle = new Charting.PerSeriesStyle (new Collections.List([new Drawing.Brush("#230A59"), new Drawing.Brush("#3E38F2")]));
barRenderer.barSpacingRatio = 0.7;

The different SeriesRenderer instances have different sets of properties that allow you to customize how the data series will be drawn. Here we use the barSpacingRatio to specify the thickness of the stack bars.

As we mentioned earlier, the Plot2D class has a seriesRenderers property where we can add the different SeriesRenderer -s that we want to show. We add the BarStackRenderer add graphics to plot
plot.seriesRenderers.add(barRenderer);

The procedure is the same for the line chart. We create another Series2D instance:

// sample data for line graphics
var lineSeries = new Charting.Series2D(
				new Collections.List([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),//x
				new Collections.List([7, 9, 12, 15, 18, 23, 24, 27, 35, 41, 46, 49, 53, 55, 58,  61, 63, 66, 67, 69 ]),//right-y
				null);
lineSeries.title = "Peak demand";

We give it a title and create a LineRenderer that will render this series:

// draw lines
var lineRenderer = new Charting.LineRenderer(
				new Collections.ObservableCollection([lineSeries]));
lineRenderer.seriesStyle = new Charting.UniformSeriesStyle(new Drawing.Brush("#ffffff"), new Drawing.Brush("#ffffff"), 6);

Finally we add the LineRenderer to the seriesRenderers collection of the Plot2D instance.

plot.seriesRenderers.add(lineRenderer);

You might have noticed that we also set the seriesStyle property in both the BarStackRenderer and the LineRenderer classes. This is the property that specifies how the chart series will be painted. There are different classes that derive from SeriesStyle All of them concern a different pattern of applying brushes and pens to the element of a Series We use here an instance of the PerSeriesStyle class that accepts lists with brushes and strokes and applies one consequtive brush and stroke to all elements in the corresponding Series . The LineRenderer uses the UniformSeriesStyle , which accepts just two Brush instances as arguments and applies them to fill and stroke all elements in all Series instances in the SeriesRenderer .

IV. The Axes

The chart axes are instances of the Axis class. We use their min , max and interval properties to specify the numeric data of each of the two axes that our dashboard will have – X and Y:

// create axes
var xAxis = new Charting.Axis();
xAxis.interval = 0;
xAxis.minValue = -1;
xAxis.maxValue = 20;
xAxis.title = "";

// create axes
var yAxis = new Charting.Axis();
yAxis.interval = 10;
yAxis.minValue = 0;
yAxis.maxValue = 100;
yAxis.title = "Cost of goods in mlns of USD";

Then we specify to the Plot2D that the Axis instances we created are its X and Y axes:

plot.yAxis = yAxis;
plot.xAxis = xAxis;

As you might have guessed, the Axis need Renderer-s to render them. They are called respectively XAxisRenderer and YAxisRenderer .

// create renderers for the two axes
var xAxisRenderer = new Charting.XAxisRenderer(xAxis);
xAxisRenderer.margin = new Charting.Margins(0, 0, 0, 10);
xAxisRenderer.labelsSource = plot;
xAxisRenderer.showCoordinates = false;


var yAxisRenderer = new Charting.YAxisRenderer(yAxis);
yAxisRenderer.margin = new Charting.Margins(10, 0, 0, 0);

The renderers have various properties for specifying how the axes will be rendered. We use margin to add some space around the two axes.

Finally, we use the layoutBuilder property of the Dashboard class to create a GridPanel that will correctly measure and arrange all building blocks of our cobination chart:

dashboard.layoutBuilder.createAndAddPlotAndAxes(
		plot, null,
		[yAxisRenderer],
		[ xAxisRenderer ],
		null);

V. The Legend

As we said, the legend items are taken from the title property of each Series . We use a LegendRenderer to render the legend and set some of its properties:

// add legend
var legendRenderer = new Charting.LegendRenderer();
legendRenderer.content = new Collections.ObservableCollection([barRenderer, lineRenderer]);
legendRenderer.background = new Drawing.Brush("#d0d3fb");
legendRenderer.borderStroke = new Drawing.Brush("#BDBFAA");
legendRenderer.showTitle = false;
legendRenderer.horizontalAlignment = Components.LayoutAlignment.Far;

The content property of LegendRenderer allows us to specify a collection of SeriesRenderer instances. This way we can have one legend for series of different kinds. We don’t need a title for our legend, so we set showTitle to false.

The LegendRenderer requires no special positioning in the dashboard layout, so we simple add it to the rootPanel of the Dashboard and let it handle its easure and placement:

dashboard.rootPanel.children.add(legendRenderer);

VI. The Title and Subtitle

The title is an instance of the TextComponent class:

var tc = new Components.TextComponent();
tc.text = "STEADY GROWTH";
tc.fontSize = 20.4;
tc.horizontalAlignment = Components.LayoutAlignment.Near;
tc.margin = new Charting.Margins(100, 10, 0, 0);
dashboard.layoutPanel.children.add(tc);

It has various appearance properties. Just like the LegendRenderer the TextComponent can be added directly to the children of the layoutPanel.

Now that we’ve made all arrangements for the chart let’s not forget to call the draw method that will render the chart on the screen:

dashboard.draw();

That was everything. You can see an online demo of the chart here.

You can download the full source code of this combination chart in JavaScript together with all used libraries from here:

Combination Chart in JavaScript Full Code

About Charting for JavaScript: MindFusion library for interactive charts and gauges. It supports all common chart types including 3D bar charts. Charts can have a grid, a legend, unlimitd number of axes and series. Scroll, zoom and pan are supported out of the box. You can easily create your own chart series by implementing the Series interface.
The gauges library is part of Charting for JavaScript. It supports oval and linear gauge with several types of labels and ticks. Various samples show you how the implement the gauges to create and customize all popular gauge types: car dashboard, clock, thermometer, compass etc. Learn more about Charting and Gauges for JavaScript at https://mindfusion.eu/javascript-chart.html.

Multi Series Line Chart With Custom ToolTips in JavaScript

In this blog post we will build a line chart with 4 different series and custom labels on both axes. The chart renders tooltips with custom formatting. You can see the chart online here:

I. Initial Setup

We start by creating a blank HTML page and there we initialize the HTML Canvas element that will be needed by the Js Chart library.

<canvas id="chart" style="width: 100%; height: 100%; display: block;"></canvas>

You can initialize the canvas as you want – there are no special requirements as to the size, position, scroll settings or anything else. What is important is that you add an id for that canvas – it will be used by the chart library. At the bottom of the page, right before the closing BODY tag we add a reference to the charting JavaScript files that represent the chart library:

<script type="text/javascript" src="Scripts/MindFusion.Common.js"></script>
<script type="text/javascript" src="Scripts/MindFusion.Charting.js"></script>

We also add a reference to another JavaScript file called LineChartTooltips.js. We haven’t created it yet, but this will be the file that will hold the JavaScript code for our chart.

<script type="text/javascript" src="LineChartTooltips.js"></script>
<strong>II. Initializing the Line Chart</strong>

In the LineChartTooltips JavaScript file we first include a reference to the Intellisense file so we can use code completion.


<pre>/// <reference path="Scripts/jspack-vsdoc.js"></reference>

Then we add mappings to the namespaces that we want to use:

var Controls = Charting.Controls;
var Collections = Charting.Collections;
var DateTimeSeries = Charting.DateTimeSeries;
var Drawing = Charting.Drawing;
var ToolTip = Charting.ToolTip;

Now we create the JavaScript chart object. We need a reference to the HTML canvas element, which we get using its id:

var chartEl = document.getElementById('chart');
chartEl.width = chartEl.offsetParent.clientWidth;
chartEl.height = chartEl.offsetParent.clientHeight;

We use the clientWidth and clientHeight properties of the offsetElement for the chart to give the chart its size.

Next we create the LineChart control and set its title and subtitle.

// create the chart
var lineChart = new Controls.LineChart(chartEl);
lineChart.title = "Women as a percentage in all S&amp;E occupations";
lineChart.subtitle = "1993-2010";

III. Labels

The labels for the X and Y axes are set with two lists:

var xlabels = new Collections.List([
    "1993", "1995", "1997", "1999", "2003", "2006",
    "2008", "2010"]);

var ylabels = new Collections.List([
    "0%", "10%", "20%", "30%", "40%", "50%",
    "60%", "70%"]);

By default the labels at the axes are the intervals. We can replace them with the labels of a given chart series by using the supportedLabels property. This property tells the control at which chart element the labels of the series should be rendered – X or Y axis, tooltip, data labels etc. The members are from the LabelKinds enumeration.

The LineChart control uses series that support X and Y values. The best match is the Series2D class. This class supports one list with labels, which are always drawn at the data points. The easiest thing for us to do is to customize the Series2D and make it accept two lists with labels, which we will show them on both axes. Here is how we create the custom class by inheriting from Series2D

SeriesWithAxisLabels = function (xValues, yValues, xLabels, yLabels) {
    this.yLabels = yLabels;
    Charting.Series2D.apply(this, [xValues, yValues, xLabels]);
};

SeriesWithAxisLabels.prototype = Object.create(Charting.Series2D.prototype);

Our custom class is called SeriesWithAxisLabels. It accepts two lists with labels in the constructor. With one of them we call the constructor of the base class. The other we assign to a new property called yLabels.

Now we need to override the getLabel method and return the right label for the X and Y axis.

SeriesWithAxisLabels.prototype.getLabel = function (index, kind) {
    if ((kind &amp; Charting.LabelKinds.XAxisLabel) != 0 &amp;&amp; this.labels)
        return this.labels.items()[index];

    if ((kind &amp; Charting.LabelKinds.YAxisLabel) != 0 &amp;&amp; this.yLabels)
        return this.yLabels.items()[index];
   
    return "";
};

The getLabel method is responsible for providing the correct label according to the kind of labels that is requested. Here we check if we are asked for a label at the X or Y axis and return the label with the correct index from the xLabels or yLabels arrays. Here is how we create that series, which serves only to provide labels for the axes:

var series0 = new SeriesWithAxisLabels(
    new Collections.List([1, 2, 3, 4, 5, 6, 7, 8]),
    new Collections.List([0, 10, 20, 30, 40, 50, 60, 70]),
    xlabels, ylabels
);
series0.supportedLabels = Charting.LabelKinds.XAxisLabel | Charting.LabelKinds.YAxisLabel;
lineChart.series.add(series0);

Note that the data for the X and Y values of series0 corresponds to the positions on the axes where the labels should be rendered.

IV. Data

The data for the chart is provided by two series. They are also of type Series2D However, we do not want them to render the labels at the data points, which is their default behaviour. We would customize once again the Series2D class and make the labels be used for tooltips and not the data points.

We define a new SeriesWithToolTip class that overrides Series2D

SeriesWithToolTip = function (xValues, yValues, labels) { 
    Charting.Series2D.apply(this, [xValues, yValues, labels]);
};

SeriesWithToolTip.prototype = Object.create(Charting.Series2D.prototype);

The difference is the getLabel method. When asked for a label for the tooltip it returns the label at the given position from the series’ labels list:

SeriesWithToolTip.prototype.getLabel = function (index, kind) {
    if ((kind &amp; Charting.LabelKinds.ToolTip) != 0 &amp;&amp; this.labels)
        return this.labels.items()[index];   

    return Charting.Series2D.prototype.getLabel.apply(this, [index, kind]);
};

We create a data series from the SeriesWithToolTip kind this way:

//first series
var series1 = new SeriesWithToolTip(
    new Collections.List([1, 2, 3, 4, 5, 6, 7, 8]),
    new Collections.List([21.3, 21.5, 21.7, 23, 26.3, 26.1, 26.3, 27.5])
);

series1.title = "All S&amp;E occupations";
var tooltips = new Collections.List();

for (let step = 0; step &lt; series1.yData.count(); step++) {
    tooltips.add(series1.title + " for " + xlabels.items()[step] + ": " +
        series1.yData.items()[step] + "%");
}
series1.labels = tooltips;
series1.supportedLabels = Charting.LabelKinds.ToolTip;
lineChart.series.add(series1);

We generate the tooltip in a list, because we want the text to combine data from the xLabels and its yData list.

V. Styling the Chart

the JavaScript Chart library supports several styles to be applied on the chart depending on what you want to achieve. In our case the best choice is the PerSeriesStyle class, which colours all the elements of a Series with the subsequent brush from its strokes and fills collections.

// create line brushes
var firstBrush = new Drawing.Brush("transparent");
var secondBrush = new Drawing.Brush("#EA3F36");
var thirdBrush = new Drawing.Brush("#1A3D95"); 
var fourthBrush = new Drawing.Brush("#717173");
var fifthBrush = new Drawing.Brush("#407D39");

var style = new Charting.PerSeriesStyle();
style.fills = style.strokes = new Collections.List([firstBrush, secondBrush, thirdBrush, fourthBrush, fifthBrush]);
style.strokeDashStyles = new Collections.List([Drawing.DashStyle.Dash, Drawing.DashStyle.Dash,
Drawing.DashStyle.Dash, Drawing.DashStyle.Dash, Drawing.DashStyle.Dash]);
style.strokeThicknesses = new Collections.List([2, 2, 2, 2, 2]);
lineChart.plot.seriesStyle = style;

The PerSeriesStyle class also provides us with properties to specify the DashStyle and the strokeThickness of the brushes.

The styling of the axes and the fonts is done via the properties of the Theme class. Each chart has a theme property of type Theme. You can use it to customize many properties of the chart:

lineChart.legendTitle = "";
lineChart.gridType = Charting.GridType.Horizontal;
lineChart.theme.axisTitleFontSize = 14;
lineChart.theme.axisLabelsFontSize = 12;
lineChart.theme.subtitleFontStyle = Charting.Drawing.FontStyle.Bold;
lineChart.theme.titleFontStyle = Charting.Drawing.FontStyle.Bold;
lineChart.theme.subtitleFontSize = 16;
lineChart.theme.dataLabelsFontSize = 12;

Note the dataLabelsFontSize property here. It regulates the font not only for the data labels but for the labels of the legend. That is why we set it, though we do not render data labels. There are several dataLabels properties like dataLabelsFontName, which customize different aspects of the labels at chart series and legend.

VI. Legend

You can show the legend with showLegend property, which is true by default. The legendTitle property sets the title of the legend, which we set to an epty string. The labels for each series are taken from the series’ title property:

lineChart.legendTitle = "";

series1.title = "All S&amp;E occupations";
.................
series2.title = "Computer/mathematical scientists";
..................
series3.title = "Engineers";

We can customize the background and border of the legend through properties of the theme or the LegendRenderer:

lineChart.legendRenderer.background = new Drawing.Brush("#f2f2f2");
lineChart.legendRenderer.borderStroke = new Drawing.Brush("#c0c0c0");

VII. ToolTips

The tooltips are automatically rendered when the user hovers over a data point. We make the data points visible by setting showScatter to true:

lineChart.showScatter = true;

Then we set different properties of the TooltTip class to achieve the desired look of the tooltips:

ToolTip.brush = new Drawing.Brush("#fafafa");
ToolTip.pen = new Drawing.Pen("#9caac6");
ToolTip.textBrush = new Drawing.Brush("#717173");
ToolTip.horizontalPadding = 6;
ToolTip.verticalPadding = 4;
ToolTip.horizontalOffset = -6;
ToolTip.verticalOffset = -4;
ToolTip.font = new Charting.Drawing.Font("Arial", 12, Charting.Drawing.FontStyle.Bold);

The ToolTip class is a static class and we can set the properties directly.

At the end, we should always call draw() to see the chart correctly rendered on the screen:

lineChart.draw();

You can download the sample with the JavaScript chart libraries and the Intellisense file from this link:

http://mindfusion.eu/samples/javascript/chart/JsLineChartTooltips.zip

About Charting for JavaScript: MindFusion library for interactive charts and gauges. It supports all common chart types including 3D bar charts. Charts can have a grid, a legend, unlimitd number of axes and series. Scroll, zoom and pan are supported out of the box. You can easily create your own chart series by implementing the Series interface.
The gauges library is part of Charting for JavaScript. It supports oval and linear gauge with several types of labels and ticks. Various samples show you how the implement the gauges to create and customize all popular gauge types: car dashboard, clock, thermometer, compass etc. Learn more about Charting and Gauges for JavaScript at https://mindfusion.eu/javascript-chart.html.

Using MindFusion JavaScript Components With WordPress Elementor Plugin

In this blog post we will describe the steps that are necessary to follow if you want to use MindFusion JavaScript library with WordPress Elementor plugin.

This guide assumes you are familiar with Elementor. For clarity we will show you how to show the JavaScript Scheduler from the “First Schedule” sample. The steps can be repeated for any MindFusion JavaScript library.

I. Add HTML Tag

The Js Scheduler requires an element to be associated with. We create an HTML Elementor widget in the place of the web page where we want the schedule to appear. Then we write in it the HTML code that creates the calendar div:

Elementor HTML Widget

Use the <HTML> widget of Elementor to insert code for the <div> element required by MindFusion JS Scheduler

II. Copy the JavaScript and CSS Files

The First Schedule sample requires reference to two JavaScript files and a CSS file with the calendar theme.

We copy the theme we will use in a new folder called “calendar-themes” into the directory of your WordPress website. This folder should be located in the subfolder that has the name of the WordPress theme you are using. This subfolder is located in the wp/content/themes/ directory. The path should be:

http://www.yoursite.any/wp-content/themes/your-theme/calendar-themes/first-theme.css

Instead of “calendar-themes” you can use any other name for your folder.

Next, copy the MindFusion.Scheduling.js and FirstSchedule.js files in a new folder called “js”, which is located at the same place where the calendar-themes folder is placed. The path should be:

http://www.yoursite.any/wp-content/themes/your-theme/js/FirstSchedule.js

http://www.yoursite.any/wp-content/themes/your-theme/js/MindFusion.Scheduling.js
WordPress directory structure

The directory structure of a WordPress blog with the newly created “js” and “calendar-themes” folders.

III. Get a Header/Footer WordPress Plugin.

Here is a list of the available options:

https://www.cminds.com/best-5-wordpress-header-footer-management-plugins/

For the purpose of this tutorial we installed “Insert Headers and Footers” but any other plugin will do. After you install the chosen plugin add the reference to the scheduler themes and the JavaScript files according to the instructions of the plugin provider. In our case we did this from the WordPress Dashboard > Settings > Insert Headers and Footers menu.

There we placed in the “Scripts in Header” text box:

 	<link href="http://ubydesign.net/wp-content/themes/twentyseventeen/calendar-themes/first-theme.css" rel="stylesheet">

And in the “Scripts in Footer” textbox:

<script src="http://ubydesign.net/wp-content/themes/twentyseventeen/js/MindFusion.Scheduling.js" type="text/javascript"></script>
<script src="http://ubydesign.net/wp-content/themes/twentyseventeen/js/FirstSchedule.js" type="text/javascript"></script>

On our test blog we use the twentyseventeen theme. That’s how the Header/Footer settings look like:

Header/Footer settings

The header references the CSS theme of the calendar, the footer adds references to the required JavaScript files.

You can check the live page on: http://ubydesign.net/blog/js-calendar-elementor/

Learn more about MindFusion JavaScript components at: https://mindfusion.eu/products.html#javascript

For technical questions please use the MindFusion discussion board: https://mindfusion.eu/Forum/YaBB.pl

Custom Diagram Nodes With Clipped Images

In this blog post we will create an org chart diagram that uses custom nodes for each employee. The diagram will be created with the Diagramming for JavaScript library. For the nodes we use the CompositeNode class, which enables us to create diagram nodes whose appearance can be defined via composition of components and layout containers.

Click on the image below to run the sample:

Custom Composite Nodes with Clipped Images

I. References and HTML Settings

The first thing that we’ll do is create a web page for the sample and add the references to the necessary JavaScript files. In the section of the page we provide a reference to the following jQuery files:

<a href="http://common/jquery.min.js">http://common/jquery.min.js</a>
<a href="http://common/jquery-ui.min.js">http://common/jquery-ui.min.js</a>

At the end of the HTML page, just before the closing tag we place references to the two JavaScript files used by the Diagramming library:

<a href="http://MindFusion.Common.js">http://MindFusion.Common.js</a>
<a href="http://MindFusion.Diagramming.js">http://MindFusion.Diagramming.js</a>

Our sample has its JS code in a separate file called Script.js. We place a reference to it as well:

<a href="http://Script.js">http://Script.js</a>

The diagram library needs an HTML Canvas to draw itself onto. We add one in the middle of the web page:

<div style="width: 100%; height: 100%; overflow: auto;">
	<canvas id="diagram" width="2100" height="2100">
		This page requires a browser that supports HTML 5 Canvas element.
	</canvas>
</div>

II. The OrgChartNode

In the Script.js file we first add mappings to some enums and classes that we’ll use from the diagram library:

var Diagram = MindFusion.Diagramming.Diagram;
var CompositeNode = MindFusion.Diagramming.CompositeNode;
var Behavior = MindFusion.Diagramming.Behavior;

var Alignment = MindFusion.Drawing.Alignment;
var Rect = MindFusion.Drawing.Rect;

Now we call the classFromTemplate method of CompositeNode that generates a node class using a JSON template that we’ll provide:

var OrgChartNode = CompositeNode.classFromTemplate("OrgChartNode",
{
component: "GridPanel",
rowDefinitions: ["*"],
columnDefinitions: ["22", "*"],
...............

In this code we indicate the panel that will be used by the CompositeNode is a GridPanel. Then we declare two lists that set the width and height of the grid rows and columns. The number of members in each array indicate how many rows/columns the grid has. In our case we have one row that takes all place and two columns: one is with fixed with of 22 pixels, the other takes the rest of the available space.

The JSON definition of the CompositeNode continues with an array with the children:

children:
[
{
component: "Rect",
name: "Background",
pen: "black",
brush: "white",
columnSpan: 2
},
{
component: "Image",
name: "Image",
autoProperty: true,
location: "ceo.png",
margin: "1",
imageAlign: "Fit"
},

The first child uses a Rect component that we call “Background”. It is rendered with a white brush, has a black outline and spans on two columns e.g. it fills all available space or each node.

The second child is an image. Note the row:

autoProperty: true

That means that we want to be able to access this component as a property. In such cases the library generates automatic set/get methods using the name of the component. In our sample they will be setImage / getImage.

The third child is a StackPanel component. This is the container for the text labels next to the node. This child has its own collection of children nodes:

component: "StackPanel",
orientation: "Vertical",
gridColumn: 1,
margin: "1",
verticalAlignment: "Near",
children:
[
{
component: "Text",
name: "Title",
autoProperty: true,
text: "title",
font: "Arial bold"
},
{
component: "Text",
name: "FullName",
autoProperty: true,
text: "full name",
pen: "blue",
padding: "1,0,1,0"
},
{
component: "Text",
name: "Details",
autoProperty: true,
text: "details",
font: "Arial 3"
}

The children of this new StackPanel are text components, which are called Title, FullName and Details. They have their autoProperty set to true, which means we can access their value through automatic setter and getter methods.

III. The Diagram and the Nodes

in the read() function of the document we create an instance of the Diagram class using a reference to the canvas we’ve created in section I.

// create a Diagram component that wraps the "diagram" canvas
diagram = Diagram.create($("#diagram")[0]);

Then we enable interactive drawing of custom nodes by calling setCustomNodeType and Then we enable interactive drawing of custom nodes by calling setCustomNodeType and setBehavior:

// enable drawing of custom nodes interactively
diagram.setCustomNodeType(OrgChartNode);
diagram.setBehavior(Behavior.Custom);

The behavior o the diagram is set to Custom, which means that when the user starts drawing nodes the library shall draw nodes specified by CustomNodeType. The setCustomNodeType method tells the diagram that these custom nodes are of type OrgChartNode.

Now it is really easy and intuitive to create nodes:

var node1 = new OrgChartNode(diagram);
node1.setBounds(new Rect(25, 15, 60, 25));
node1.setTitle("CEO");
node1.setFullName("John Smith");
node1.setDetails(
"Our beloved leader. \r\n" +
"The CEO of this great corporation.");
node1.setImage("ceo.png");
diagram.addItem(node1);

We create a few more nodes using the same code and we bind them in a hierarchy. The links among the nodes are created by calling the Diagram Factory createDiagramLink method of the diagram Factory class:

diagram.getFactory().createDiagramLink(node1, node2);
diagram.getFactory().createDiagramLink(node1, node3);
diagram.getFactory().createDiagramLink(node1, node4);
diagram.getFactory().createDiagramLink(node4, node5);

IV. Rounded Images

We want to add now a custom feature to the node – instead of drawing the image as a rectangle we want to clip it and show it as an ellipse. We’ll do this by using a method that replaces the standard setImage method.

The new method is called createImageClip and takes as parameters two objects: one is the image URL and the other is the node that uses this image.

function createImageClip(path, node)
{
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
img = document.createElement('img');
..............

We create two HTMLElements – canvas and image, and we get the 2D context of the Canvas. Then, in an event handler of the onload event of the image we clip the canvas to an area defined by a Path. The path reads the size of the image and creates a full arc e.g. a circle inside that rectangle. Then the context draws the image and the new canvas is set as an image to the node using the setImage method:

img.src = path;
img.onload = function ()
{
canvas.width = img.width;
canvas.height = img.height;
var halfSize = img.width / 2;
ctx.save();
ctx.beginPath();
ctx.arc(halfSize, halfSize, halfSize, 0, Math.PI * 2, true);
ctx.closePath();
ctx.clip();

ctx.drawImage(img, 0, 0, img.width, img.height);

node.setImage(canvas.toDataURL());
};

You can use this approach to create clippings of images with variable shape.

Now instead of calling:

node1.setImage("ceo.png");

we call our custom method this way:

createImageClip("ceo.png", node1);

We do this for all nodes in the org chart.

That’s the end of this tutorial. You can download the sample together with all JavaScript libraries used from this link:

Custom Nodes With Image Clipping in JavaScript: Sample Download

Find out more about Diagramming for JavaScript at https://mindfusion.eu/javascript-diagram.html

Binding the Java Planner to Microsoft SQL Server Using JDBC

In this blog post we will bind to an MS SQL database called bookings. There we will select all data from a table named booking_data. The data is DateTime values. We will use the values to change the background of corresponding calendar cells in a simple Java application. The Java application renders a single-month calendar built with MindFusion Scheduler for Java library.

I. MS SQL EXPRESS Server Configuration

We download and install MS SQL EXPRESS server from https://www.microsoft.com/en-us/sql-server/sql-server-downloads. The installation also includes an application called “Sql Server Configuration Manager”. We start that application and click on the “SQL Services” tab. There we need to make sure that two services are running:

  • SQL Server
  • SQL Server Browser

You start these services by pressing the arrows in the toolbar at the top. If you cannot do this you need to change the Start Mode for this service. Double click it and in the Properties dialog that appears click on the “Service” tab. There you will find the “Start Mode” property and change it to “Manual”. Once you’ve done this you can start, stop or pause the service from the toolbar icons.

SQL Server Config Manager: Services

In order to start an SQL Server Service you might have to change its Start Mode to “Manual”.

Then we click on the “SQL Native Client” node and we select the “Client Protocols” tab. We make sure the TCP/IP Protocol is enabled.

SQL Server Config Manager: Enable TCP/IP

Make sure the TCP/IP protocol is enabled for the JDBC connection to succeed

The next step is to download Microsoft SQL Server Management Studio from https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-2017

Once we install it and start it we can create a new database called bookings. We right click on the Databases menu and choose “New Database”. We call it “bookings”. Then we expand the tree under “bookings” and right click on the “Tables” node. A window opens where we can define the columns for our new table. We add two columns:

  • id of type integer, which we set at primary key by right-clicking on it.
  • booked_date of type DateTime which will hold the dates that are booked.
Create a new table using MS SQL Server Management Studio

MS SQL Server management Studio: the dialog for defining a new table

After we are done we choose save and at this point we can provide a name for our table. We call it booking_data. With the table defined we right-click on it and choose “Edit Top 200 Rows”. There we add just three days (Jan 16th, Jan 22nd, Jan 26th) all of which in the current month. The data is auto-saved.

MS SQL Server management Studio: Table Edit

MS SQL Server Management Studio: here is how you edit the table data

The next step is to create a new user that will connect to this database. We click the “Security” node on the navigation tree and then “Logins”. Right-click and we choose “New Login”. In the dialog that opens we provide username and password. In order to do that we need to have the Login method set to “SQL Server authentication”. In the next tab “Server Roles” the new user must have “public” role. Then in “User Mapping” we tick the “bookings” database. In the Securables tab in the “Grant” grant column for the user we tick the “Connect SQL” permission. Then we close the dialog.

Grant SQL Connect to a DB User

Grant the new user the right to perform an SQL connection.

We get back to the bookings database and right-click on it. We choose “Properties” and from the dialog we click on the “Permissions” menu. There we select the user we’ve just created and in the Grant column of the underlying table we grant her the “Select” permission.

Granting User Permissions

Grant the DB user ‘Select’ permission to perform the required SQL query

With that the setup of our server and user is ready.

II. JDBC Driver & MS SQL Express Connection Properties

We download Microsoft’s JDBC Driver for MS SQL Server from this link: https://docs.microsoft.com/en-us/sql/connect/jdbc/microsoft-jdbc-driver-for-sql-server?view=sql-server-2017 and extract it. Next we create a new Java project. For this project we’ve used IntelliJ IDEA but any other Java IDE will do. In the project tree to the right we create a subfolder that we call “libs”. There we copy the jar of JDBC driver from the folder where we extracted it. Microsoft provides two versions of the driver depending on the JRE that you use. In our case we choose the version for JRE 10, which is called mssql-jdbc-7.0.0.jre10.jar. Next we right-click on the name of our project and select “Open Module Properties”. In the dialog we choose the “Modules” menu and there we click on the “Dependencies” tab and select the mssql-jdbc-7.0.0.jre10.jar module.

Configuring IntelliJ Project Modules

Configuring the IntelliJ Project to include the JDBC driver module

We click on the src folder of the project and add a new class, which we call MainWindow.java. In it we write the method establishConnection. This method is responsible for connecting to the MS SQL database “bookings”. Here is the code that makes the connection:

private void establishConnection() throws ClassNotFoundException
{

Connection conn = null;
PreparedStatement pst;

try {
// db parameters
String sql = "SELECT booked_date FROM booking_data";

String userName = "mindfusion";
String password = "mf123";

String url = "jdbc:sqlserver://DESKTOP-NV9S0TU\\SQLEXPRESS;databaseName=bookings;";

Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
conn = DriverManager.getConnection(url, userName, password);

pst = conn.prepareStatement(sql);
ResultSet rs = pst.executeQuery();

If you’ve followed strictly the steps we’ve outlined so far at this point you would successfully connect to your MS SQL Server with the credentials you’ve set up following the guide so far.

III. The Schedule Application

We download MindFusion Java Swing Scheduler from https://mindfusion.eu/java-scheduler.html and unzip it. We copy JPlanner.jar in the libs folder of the project and add it as a project dependency from the “Open Module Settings” menu. Then we define a Calendar variable and assign it to a new instance of the Calendar class.

public MainWindow() throws ClassNotFoundException
{
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(368, 362);
setTitle("MindFusion.Scheduling Sample: Minimal Application");

calendar = new Calendar();
calendar.setTheme(ThemeType.Light);
..................
..................
..................

establishConnection();
}

private Calendar calendar;

At the end of the method we call establishConnection and connect to the MS SQL Server.

IV. Styling the Calendar Dates

The aim of our sample application shall be to color those cells of the calendar that correspond to the dates we’ve read from the database. In order to do this we use the DateStyle class that sets some useful appearance properties to a range of cells that are specified with the setFrom and setTo methods. We use setBrush to change the background of the cell.

while (rs.next()) {
System.out.println(rs.getString("booked_date"));
Date date = rs.getDate("booked_date");

DateStyle dStyle = new DateStyle();
dStyle.setFrom(new DateTime(date));
dStyle.setTo(new DateTime(date));
Style style = new Style();
style.setBrush(new SolidBrush(Color.pink));
dStyle.setStyle(style);

calendar.getDayStyles().add(dStyle);

}

Finally we add the style to the DayStyles collection of the calendar.

Here is the final application:

Scheduling application in Java Swing with MS SQL Server JDBC Connection

MindFusion Java Swing application with the Scheduling library and MS SQL Server

You can download the project together with the MS SQL Server JDBC driver library and the scheduling library from this link:

Download JPlanner Sample Application That Uses MS SQL Server JDBC Connection

About MindFusion Scheduling for Java Swing: The library provides extensive feature-set for creating and customizing all sorts of calendars, task lists, time-management tables, resource allocation tables and other. It boasts various options for customizing appearance and numerous events for handling user actions. The distribution archive includes a lot of samples and extensive documentation. Learn more at https://mindfusion.eu/java-scheduler.html

Interactive Event Timetable in JavaScript

This blog post describes the main steps on how to create a schedule table, which shows the allocation of college rooms to different courses. Users can filter the courses by lecturer(s).

I. Initial Setup

We start by copying the JavaScript scheduler files that we’ll use in the directory of our project. These are:

  • MindFusion.Scheduling.js – represents the Js Scheduler library
  • MindFusion.Scheduling-vsdoc.js – provides Intellisense support
    standard.css – in a subdirectory “themes”, this is the CSS theme styling of the resource table
  • planner_lic.txt – paste your license key here to disable the trial version label.

We create then 2 more files specifically for our application:

  • ResourceView.html – the web page of the application
  • ResourceView.js – the JavaScript code that implements the dynamic features of our application.

II. The HTML Page

In the head section of our web page we first create a reference to the theme file:

 	 	<link rel="stylesheet" type="text/css" href="themes/standard.css">

At the end of the web page, just before the closing </body> tag we add a reference to the Scheduling.js file that contains the scheduling features and the ResourceView.js files that we’ll write for the application:

<script src="MindFusion.Scheduling.js" type="text/javascript"></script>
<script src="ResourceView.js" type="text/javascript"></script>

The calendar library requires an HTML <div> element, which is used to render it. We add one:

<div id="calendar" style="height: 100%; width: 100%;"></div>

It is important that you add an id to this <div> because we need to reference it in the JS code behind file.

III. Basic JavaScript Settings

At the top of the JavaScript code-behind file we add a reference to the Intellisense file. We also create a mapping to MindFusion.Scheduling namespace:

/// <reference path="MindFusion.Scheduling-vsdoc.js"></reference>
var p = MindFusion.Scheduling

Then we create the calendar object. We need a reference to the <div> element that will render it:

// create a new instance of the calendar
calendar = new p.Calendar(document.getElementById("calendar"));

For this sample we will use the ResourceView The currentView property specifies that. In addition, we set the count of visible cells in the calendar to 7. That is done through the resourceViewSettings property of the calendar

// set the view to ResourceView, which displays the distribution of resources over a period of time
calendar.currentView = p.CalendarView.ResourceView;

// set the number of visible cells to 7
calendar.resourceViewSettings.visibleCells = 7;

The itemSettings proeprty lets us customize the items in the schedule We use titleFormat and tooltipFormat to specify how the title and tooltip of each item will be rendered. Both properties use special format strings:

  • %s – the start date will be rendered
  • %e – the end date of the item will be rendered
  • %d – the details of the item will be rendered.

You can specify the way dates and time are formatted by adding the desired format in brackets:

// show hours on items
calendar.itemSettings.titleFormat = "%s[HH:mm] - %e[HH:mm] %h";
calendar.itemSettings.tooltipFormat = "%d";

Then we set the theme of the calendar to standard, whose css file we referenced in the web page:

calendar.theme = "standard";

and we make one more adjustment – the name of contacts will be taken from the last name of the person. Possible valies are “F”, “M” and “L” – for first, middle and last name.

calendar.contactNameFormat = "L";

IV. Resources

When the calendar initially loads there are several contacts and locations available. The objects that represent them are instances of the Contact and Location classes. After we create them we add them to the contacts and locations collections of the calendar schedule.

var resource;

// Add professor names to the schedule.contacts collection.
resource = new p.Contact();
resource.firstName = "Prof. William";
resource.lastName = "Dyer";
calendar.schedule.contacts.add(resource);

resource = new p.Location();
resource.name = "Room D";
calendar.schedule.locations.add(resource);

Now, when the user creates a new course they will see the Contact and Location in the Options pane of the “Create Item” form:

V. Items

The items are instances of the Item class. They represent the classes of the different lecturers. We use the startTime and endTime properties of Item to specify when the class takes place. The subject property gives the name of the class:

//always start with the current date
var date = p.DateTime.today();

item = new p.Item();
item.startTime = p.DateTime.addHours(date.addDays(1), 14);
item.endTime = p.DateTime.addHours(item.startTime, 1);
item.subject = "Classical Mechanics";

We use the location and contacts properties to set where the lecture takes place and who teaches it. Note that the contacts property is of type collection and we can assign several lecturers to one class:

item.location = calendar.schedule.locations.items()[0];
item.contacts.add(calendar.schedule.contacts.items()[0]);

We get the location and the contact from the schedule’s lists with locations and contacts We must also set the details of the item – they will be rendered as a tooltip, if you remember. We want the tooltip to show the two names of the lecturer and the location. Here is how we must define it:

item.details = item.contacts.items()[0].firstName + " " +
item.contacts.items()[0].lastName + " - " + item.location.name;

We must add the item to the items collection of the schedule we render the calendar render the calendar

calendar.render();

VI. Events

When users create new items we must set their details to tell the name and the location of the new class. We handle the itemCreating event to do this:

// attach handler - creating an item
calendar.itemCreating.addEventListener(handleItemCreating); 

function handleItemCreating(sender, args) {
    handleItemModified(sender, args);
    if (args.item.contacts.count() &gt; 0) {
        //the details field is used by the tooltip
        args.item.details = args.item.contacts.items()[0].firstName + " " +
                args.item.contacts.items()[0].lastName;

        if (args.item.location != null)
            args.item.details += " - " + args.item.location.name;
    }

}

The itemCreating event provides an instance of the ItemModifyingEventArgs class as a second argument to the handler method. There we use the item property that tells us which item is being modified. We then take the desired contact and Location information from the contacts and location properties of the item.

When a new course item is dragged to another location we must change its color accordingly. We do this by handling the itemModified event.

// attach handler - modifying an item
calendar.itemModified.addEventListener(handleItemModified);

The diferent background color of the items is achieved by custom CSS classes. We use the cssClass property of the Item class. The CSS styles are defined in the <HEAD> section of the web page:

 .mfp-planner.standard .itemClass1 .mfp-item {
            background-color: 	#0c71af;
        }

.mfp-planner.standard .itemClass2 .mfp-item {
            background-color: #f81e1e;
        }
...........

The handler method checks the new location and assigns the appropriate CSS style:

function handleItemModified(sender, args)
{
    // you don't have to check any other conditions like dragging to another room, 
    // as it will stay the same color if you make other changes (other than dragging to a different room)
    if (args.item != null){
        switch (args.item.location.name) {
            case "Room A":  //we can also implement it with for
                args.item.cssClass = 'itemClass1';
                console.log("a");
                break;
            case "Room B":
                args.item.cssClass = 'itemClass2';
                break;
            case "Room C":
                args.item.cssClass = 'itemClass3';
                break;
            case "Room D":
                args.item.cssClass = 'itemClass1';
                break;
            case "Room E":
                args.item.cssClass = 'itemClass2';
                break;
            case "Room F":
                args.item.cssClass = 'itemClass3';
                break;
            default:
                args.item.cssClass = 'itemClass1';
        }
    }
}

The item property of the args parameter of the handler method provides access to the item that was modified.

VII. Filtering Professors

We want to add one last feature to our application. We want the user to be able to render courses only by a given professor.

We first add checkboxes with the names of the lecturers. Each checkbox has the same handler method for the click event:

<input id="dyer" checked="checked" name="subscribe" type="checkbox" value="Dyer>
<label for=">Prof. William Dyer

<input id="fletcher" checked="checked" name="subscribe" type="checkbox" value="Fletcher">
<label for="fletcher">Prof. Ann Fletcher</label>
...........................

The handler method needs to look at two cases. The first case is when the class is taught by a single professor. In this case we cycle through all items and make the item visible or not depending on whether the check box with the name of the professor is checked:

// if there is at least one present professor from the lecture professors, the lecture will not disappear
function handleClick(cb) {
for (var i = 0; i &lt; calendar.schedule.items.count(); i++) {
        var item = calendar.schedule.items.items()[i]; //we iterate through every element
        if (item.contacts.count() == 1) {
            if (item.contacts.items()[0].lastName == cb.value)
                item.visible = cb.checked;
        }
      }
.......................
}

In the second case we look at courses that are taught by more than one lecturer. In this case we show the item if the checkbox with the name of at least one of the lecturers is selected:

else if (item.contacts.count() &gt; 1) {
for (var j = 0; j &lt; item.contacts.count() ; j++) {
                if (item.contacts.items()[j].lastName == cb.value) { // the checked/unchecked professor is in the contacts of this item
                    if (cb.checked == true) item.visible = true; // if there is a check, the item must be visible
                    else { // if there is no check, we see if there is at least one professor in the list of contacts of the item
                        item.visible = professorPresent(item);
                    }

                }
            }
        }

Finally we repaint the calendar:

// repaint the calendar
this.calendar.repaint(true);

Here the professorPresent method checks if at least one of the check boxes with professors that are present as lecturers in the item that we provide as argument are selected:

// return true if even 1 professor from the item's contacts is present, false otherwise
function professorPresent(item) {
    console.log(item.contacts.count());
    for (var j = 0; j &lt; item.contacts.count() ; j++) {
        var checkBoxId = item.contacts.items()[j].lastName.toLowerCase();
        var checkBox = document.getElementById(checkBoxId);
        if (checkBox!= null &amp;&amp; checkBox.checked == true) {
            return true;
        }
    }
    return false;
}

And that’s the end of this blog post. Here is a link to download the complete source code of this application:

Download The Sample Resource View Application

About MindFusion JavaScript Scheduler: MindFusion Js Scheduler is the complete solution for all applications that need to render interactive timetables, event schedules or appointment calendars. Fully responsive, highly customizable and easy to integrate, you can quickly program the JavaScript scheduling library according to your needs. Find out more at https://mindfusion.eu/javascript-scheduler.html