Styling The Timetable View in JavaScript Scheduler

In this blog post we are going to look at the most common adjustments in the appearance of a timetable that developers want to make based on the questions we have received regarding MindFusion Scheduler library for Java Script.

Here is how our timetable will look at the end:

Styling the Timetable View in JS Scheduler

I. General Looks

The overall appearance of the scheduling library is controlled by themes. MindFusion Scheduler comes with a collection of 9 predefined themes. In order to apply a theme you need to:

  • add a reference to the CSS file in the web page where you want the calendar to appear:
    <link rel="stylesheet" type="text/css" href="themes/gray.css">
  • assign the name of the theme to the theme property of the Calendar class:
    calendar.theme = "gray";
  • Themes can change dramatically the color scheme of the control including the forms that appear for item creation. We recommend that you choose the theme that is most closely related to the colors you want to see and customize it, if necessary.

    Themes in the JavaScript Scheduler

    Each of the themes is in a CSS file and you can search by the color code and replace the occurrences of a given color with another one to fine-tune the color scheme.

    II. Timetable Settings

    Initially, a timetable renders only one day – today. The timetableSettings property, just like the *settings properties for all views supported by the Calendar (—SingleMonth, RespurceView, MonthRange etc.) expose the properties that let you customize the look of the calendar.

    In the case with the timetableView, the number of columns that are rendered depends on the number of dates added to the dates propеrty of timetableSettings In our case we want to show the week, so we add 7 dates:

    //get the current date
    var currDay = schedule.DateTime.today();
    calendar.timetableSettings.dates.clear();
    
    for (var i = 1; i < 8; i++) {
    	calendar.timetableSettings.dates.add(currDay.addDays(-1 * currDay.dayOfWeek + i));	
    	}
    }

    Setting the Number Of Dates in a Timetable in the JavaScript Scheduler

    We also want to scroll week by week. By default the timetable scrolls with one day. In order to scroll more you need to set the scrollStep property to a bigger number:

    calendar.timetableSettings.scrollStep = 7;

    The next thing that we need is to change the time scale. We want the scales to be per 20 minutes and we want to cover the time interval from 10 to 16 o’clock. These is regulated with the startTime and endTime fields of timetableSettings These properties take as an argument the number of minutes. So, if you want your day to start at 8 o’clock your start time needs to be 8×60=480 minutes or you need to assign 480 as value to the startTime property.

    // set the start time to 10:00 AM
    calendar.timetableSettings.  = 600;
    // set the end time to 16:00 PM
    calendar.timetableSettings.endTime = 1020;

    What we want to specify is the format of the header. The default format is based on the locale settings of the user that runs the application. In our application the date in the timetable header renders as DD/MM/YYYY. We will use the titleFormat property. We also use cellTime to change the time scales between each two hours. The default value is 30 minutes. We change it to 20 with the cellTime property.

    calendar.timetableSettings.titleFormat = "d MMMM 
     dddd";
    calendar.timetableSettings.cellTime = schedule.TimeSpan.fromMinutes(20);
    calendar.timetableSettings.cellSize = 20;

    Adjusting the Timetable Settings in the JavaScript Scheduler

    We also increase the cell size – this is the height of rows that are defined by each 20-minute interval. The calendar also shows just one header – that with the dates. We want to render the days header, which shows the day of the week. The property for that is showDayHeader

    calendar.timetableSettings.showDayHeader = true;

    III. CSS Styling

    We’ve customized our timetable as much as we could through the properties and fields of the Calendar control. We would like to add some additional styling, which can be done through css. We use the style inspector of the browser to identify the styles that are applied on the elements that interest us. We would like to show the lines that separate 20 minute cells in yellow and the lines that separate hours in red. Let’s start with the hour lines. The css to render them in red is this one:

    .mfp-timetable-view .mfp-content .mfp-column .mfp-cell-wrap:nth-child(3n+1) .mfp-cell { 
    			border-top: 1px solid red; 
    }

    The class that styles cells is called mfo-cell-wrap. This class regulates the styling for all cells, so we need to apply red border only on the cells that interest us, and they are the 1st, 4th, 9th etc. cell. We want the rest of the cells to be yellow. This is done with the CSS “not” keyword:

    .mfp-timetable-view .mfp-content .mfp-column .mfp-cell-wrap:not(:nth-child(3n+1)) .mfp-cell {  
    			border-top: 1px solid yellow; 
    	}

    This colors the rows of the timetable red/yellow but does not color the delimeters between the time scales. They are regulated by another CSS class and are div elements:

    .mfp-timetable-view.gray .mfp-header-timeline .mfp-group-time div:not(:first-child)
    	{
    
    		border-top: solid 1px yellow;
    	}
    		
    	.mfp-timetable-view.gray .mfp-header-timeline .mfp-hour
    	{
    		border-top: solid 1px red;
    	}

    Note that the CSS style names are with the suffix “gray”. This is the name of the theme. In many cases the class that needs to be changed is bound to a certain theme.

    The last thing that we want to add as styling is a background for the weekend days. We use again the nth-child CSS property. This time the “children” are the 6th and 7th element, so we define styles for them:

    .mfp-timetable-view .mfp-content .mfp-column:nth-child(5n + 6), .mfp-column:nth-child(5n + 7) {
    			background-color: rgba(145, 179, 188, 0.4);
    		}

    We note one more thing. When we create an appointment, the text of the subject is not visible because the line height is too small for the item styling. We have two options: either to increase the cell height, which is set with cellSize and is 20 or to style the item, so that the subject is visible. We choose the latter. We will make the resize line-s smaller because that’s what hiding the subject: the big resize lines:

    .mfp-item-vertical-detail .mfp-subject {
    	flex-shrink: 0 !important;
    }
    
    .mfp-item-vertical-detail .mfp-resize-start,
    .mfp-item-vertical-detail .mfp-resize-end {
    	flex-shrink: 1 !important;
    }

    Here is the final result:

    Styling the Timetable Vew in JS Scheduler

    You can download the sample with all libraries ued and the full source code from this link:

    Styling a Timetable in the JavaScript Scheduler

    You can post technical questions, comments and recommendations about MindFusion Scheduling for JavaScript at the library online forum.

    About Scheduling for JavaScript: MindFusion Js Scheduler is the right solution for all applications that need to render interactive timetables, rich event calendars, lists with appointments or resources. Fully responsive, highly customizable and easy to integrate, you can quickly program the JavaScript scheduling library according to your needs. The library supports a variety of export options, styling through themes, 6 calendar views and much more. Find out more at https://mindfusion.eu/javascript-scheduler.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:

    /// 
    
    var p = MindFusion.Scheduling;

    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 < 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 && 
    				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 < item2.startTime &&
    	    item1.endTime < item2.endTime )
    		  return false;
    		  
    	if( item1.startTime > item2.endTime &&
    	    item1.endTime > 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:

    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 < 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:

    
    

    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