Displaying Events on a Calendar Control from an External Database

Description

You can customize the calendar control to display events drawn from an SQL database. The first half of this guide gives step by step instructions on how to build a calendar control that can do this. The second half of the guide looks at the Javascript and Xbasic involved.

A calendar control populated by events drawn from an SQL database.

One way to accomplish this is through an ajax callback. The ajax callback is executed everytime a user navigates to a new month and contains a query against the 'Orders' table in the 'Northwind' database. This query gets a list of the orders that occurred on each day in each month. In order to display the results of this query on the calendar some adjustments to the default calendar settings must also be changed. The boxes for each day need to be enlarged so that this data can be displayed on the calendar on the day that the event occurred. For a visual explanation on how to do this watch this seven part video: Part 1 Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, or read the guide below.

Set the UX Properties 

  1. In the UX Builder's UX Properties page scroll down to the 'CSS/SVG' section. Click the [...] button next to the 'Local CSS definitions' property.

  2. In the 'CSS Editor - []' open the 'Code' tab at the bottom of the editor.

  3. Add the following definition for a 'hiddenItems' css class and click OK.

    .hiddenItem {display: none;}
    This css class prevents the dates from previous or later months being displayed on the calendar. For example, if you were looking at the month of August, then the last day of July and the first day of September would not be displayed. This is different from the default setting, which is to number the days of other months but have them appear disabled; using the disabled css class. The .hiddenItem class is called in the calendar's 'Date item out of range class name' property.
  4. Scroll down to the 'Other' section on the Properties list. Find the 'Date format' property and set it to be 'MM/dd/yyyy'.

Customize the Layout of the Calendar. 

  1. In the UX Builder on the UX Controls page open the 'Data Controls' menu. Click on the [Calendar] option to add a calendar control to the component. Give the calendar the name 'dt1'.

  2. Highlight the calendar control in the controls tree. In the properties list on the right go to the 'Field Properties' section and set the 'Default value' property to '8/1/1994'. Most of the events listed in the northwinds SQL table that will be used for this example are from 1994.

  3. Go to the 'Date/Time Picker Properties' section. Check the 'Draw boxes around dates' checkbox property.

  4. Set the 'Date item hover class name' property to be 'None' by writing 'None' next to the property.

    This prevents a highlight from appearing when a user hovers over a date.
  5. Set the 'Date item selected class name' property to be 'None' by writing 'None' next to this property as well.

    This prevents a highlight from occuring when a user selects a date.
  6. Set the 'Date item out of range class name' property to be 'hiddenItem'.

  7. Click the [...] button next to the 'Date item style' property.

  8. Scroll down to the 'Positioning and Size' section of the Style Editor. Set the 'Width' and 'Height' properties to be "1.5in". Click OK.

    This setting increases the size of each day's box inside the calendar.
  9. In the calendar's 'Date/Time Picker Properties' section check the 'Has events' property

  10. Click the '+' button next to the 'Has events' property to expand the events list. Next to the onItemDraw event write 'calendarDrawItem'.

    Every time an item is drawn this javascript function is called. An 'item' here refers to a given day in a month.
  11. Next to the 'onMonthNavigate' event write 'calendarMonthNavigate'.

    This calls a javascript function that draws the events everytime you navigate to a new month.
  12. Expand the 'Events' menu and click on the 'Client-side' events page. In the 'Client-Side Events' list highlight the 'onRenderComplete' event.

  13. Add the following function call to the 'onRenderComplete' event.

    calendarMonthNavigate();

Create a Connection to the AADemo-Northwind database 

  1. In the main toolbar click on the 'SQL' button and select the 'AlphaDAO Connection Strings' option.

  2. Click the "Create 'AADemo-Northwind' demo connection string" hyperlink.

  3. Select the 'Microsoft Access Database Engine' radio button option at the bottom of the page. Click the "OK - Create a named connection string called 'AADemo-Northwind'" option. Click OK again.

  4. Click 'Close'.

Add Javascript Definitions 

  1. In the UX Builder's main menu on the left expand the 'Code' menu. Click to open the "Javascript functions" page

  2. Add the following javascript function definitions to the 'Javascript functions' page.

    function calendarDrawItem(ele,date,type) {
    	var curObj = {dialog.object}.getControl('DT1');
    	var calData = curObj._data;
    	
    	if(typeof curObj._menuItems == 'undefined') {
    		curObj._menuItems = {};
    	}
    	if(type == 'date') {
    		if(typeof calData != 'undefined') {
    			var dateStr = date.getFullYear() + '-' +(date.getMonth() + 1) + '-' + date.getDate();
    			if(typeof calData[dateStr] != 'undefined') {
    				var tempData = calData[dateStr];
    				var maxItemsToShow = 1
    				if(tempData.length > maxItemsToShow ) {
    					var windowContent = '';
    					var menuItems = [];
    					for(var i = 0; i < tempData.length; i++) {
    						menuItems.push({
    							html: '<span title="'+tempData[i].detail+'">' + tempData[i].name + '</span>',
    							onClick: Function('editEvent(\'' + tempData[i].id + '\')')
    						});
    					}	
    					curObj._menuItems[dateStr] = menuItems;
    					ele.innerHTML = ele.innerHTML + '<br><span onmouseover="showEventList(this,\''+dateStr+'\');">Multiple... (' + tempData.length + ')</span>';
    				} else {
    					for(var i = 0; i < tempData.length; i++) {
    						ele.innerHTML = ele.innerHTML + '<br>' + '<a class="{dialog.style}Link" href="#" title="'+tempData[i].detail+'" onclick="editEvent(\''+tempData[i].id+'\');$e.stopEvent(event); return false;">' +tempData[i].name +'</a>' ;
    					}		
    				}
    			}
    		}
    	}
    }
    
    function calendarMonthNavigate(date) {
    	var calObj = {dialog.object}.getControl('DT1');
    
    	delete calObj._menuItems;
    	var menuName = '_CalendarDetailsMenu';
    	if(typeof calObj[menuName] != 'undefined') {	
    		calObj[menuName].hide();
    	}
    	var data = '_month=' + (calObj._dp._month+1) + '&_year=' +  calObj._dp._year;
    	{grid.Object}.ajaxCallback('G','','getEvents','',data);
    }
    
    function editEvent(id) {
    	alert('Display Order:' + id );
    }
    
    function showEventList(objEle, dateStr) {
    	var menuName = '_CalendarDetailsMenu';
    	var curObj = {dialog.object}.getControl('DT1');
    	if(typeof curObj[menuName] == 'undefined') {
    		curObj[menuName] = new A5.Menu([],{
    			theme: '{dialog.style}',
    			iconColumn: {show: false}
    		});
    	}
    	
    	curObj[menuName].populate(curObj._menuItems[dateStr]);
    	curObj[menuName].show('popup',objEle);
    }

Add Xbasic Definitions 

  1. In the 'Code' menu click to open the 'Xbasic functions' page.

  2. In the Xbasic functions page add the following Xbasic function definitions.

    function getEvents as c (e as p)
    dim month as c 
    dim year as c 
    dim startDate as d 
    dim endDate as d 
    
    startDate = date_value(val(e._year),val(e._month),1)
    if val(e._month) < 12 then 
    	endDate = date_value(val(e._year),val(e._month)+1,1) -1
    else
    	endDate = date_value(val(e._year)+1,1,1) -1
    end if 
    
    dim jsonData as c 
    dim def as p
    dim defn as p
    defn.type = "sql"
    defn.connectionString = "::Name::AADemo-Northwind"
    defn.tableName = <<%sql%
    SELECT Orders.OrderID as OrderId, 
    	concatenate(orders.orderid,': ', customers.companyname) as eventName, 
    	Orders.OrderDate as orderDate, 
    	concatenate('Order: ', orders.orderid, ': ', customers.contactname, ' ', customers.companyname)  AS eventdescription 
    FROM Orders Orders
    	 INNER JOIN Customers Customers
    		 ON  Orders.CustomerID = Customers.CustomerID
    %sql%
    
    defn.startDate = year(startDate) + "-" + month(startDate) + "-" + day(startDate)
    defn.endDate = year(endDate) + "-" + month(endDate) + "-" + day(endDate)
    defn.eventDate = "orderDate"
    defn.eventId = "orderId"
    defn.eventName = "eventName"
    defn.eventDescription = "eventdescription"  
    
    jsonData = a5_GetCalendarEventDataJSON(defn)
    dim js as c  = ""
    
    js = js + "var _cal = {dialog.object}.getControl('DT1');" + crlf()
    js = js + "_cal._data = " + jsonData + ";" + crlf()
    js = js + "_cal.refresh();" 
    getEvents = js 
    
    end function

Run the Component 

Run the component in Live Preview. The events from the SQL Table should be displayed in the calendar on the day when they occurred.

Line by Line Javascript Explanation 

In the Calendars 'Has events' properties two events were defined. These were the onItemDraw event, that was tied to the calendarDrawItem() function, and the onMonthNavigate event, that was tied to the calendarMonthNavigate() function.

calendarMonthNavigate()

function calendarMonthNavigate(date) {
	var calObj = {dialog.object}.getControl('DT1');

	delete calObj._menuItems;
	var menuName = '_CalendarDetailsMenu';
	if(typeof calObj[menuName] != 'undefined') {	
		calObj[menuName].hide();
	}
	var data = '_month=' + (calObj._dp._month+1) + '&_year=' +  calObj._dp._year;
	{grid.Object}.ajaxCallback('G','','getEvents','',data);
}

The first thing that this function does is to get a pointer to the calendar control. This is done using the dialog object's getControl() method. This method takes as an argument the variable name of the calendar control, 'dt1'. This pointer is then assigned to a variable named 'calObj'

var calObj = {dialog.object}.getControl('DT1');

An if statement then handles the logic that will shut down any pop-up menus that occur in situations where a calendar has more than one event displayed. Any pop-up menus are forced to close when you navigate to a new month.

delete calObj._menuItems;
	var menuName = '_CalendarDetailsMenu';
	if(typeof calObj[menuName] != 'undefined') {	
		calObj[menuName].hide();
	}

A variable named 'data' gets the year and the month that the user navigated to. This information is stored in the calendar control's _dp._month and _dp._year properties. The 'data' javascript variable is constructed in the form of a query string. First the variable gets the month value, '_month=', by using the pointer to the calendar control defined earlier, 'calObj', to find the _dp._month value. Because the month array is zero based, '+1' must be added to the end of the query in order to get the correct month. After finding which month the user entered the query then finds the year that the user entered.

var data = '_month=' + (calObj._dp._month+1) + '&_year=' +  calObj._dp._year;

When a user navigates to a new month an Ajax callback is made. This ajax callback calls an Xbasic function called 'getEvents' as well as the 'data' variable. The getEvents function, discussed in the 'Line by Line Xbasic' section, returns orders or events for a given month in json format. These orders and events are originally stored in an SQL database and this data is converted to json on the server. The data is then stored as a property of the calendar object.

{grid.Object}.ajaxCallback('G','','getEvents','',data);

The calendarDrawItem() Function

function calendarDrawItem(ele,date,type) {
	var curObj = {dialog.object}.getControl('DT1');
	var calData = curObj._data;
	
	if(typeof curObj._menuItems == 'undefined') {
		curObj._menuItems = {};
	}
	if(type == 'date') {
		if(typeof calData != 'undefined') {
			var dateStr = date.getFullYear() + '-' +(date.getMonth() + 1) + '-' + date.getDate();
			if(typeof calData[dateStr] != 'undefined') {
				var tempData = calData[dateStr];
				var maxItemsToShow = 1
				if(tempData.length > maxItemsToShow ) {
					var windowContent = '';
					var menuItems = [];
					for(var i = 0; i < tempData.length; i++) {
						menuItems.push({
							html: '<span title="'+tempData[i].detail+'">' + tempData[i].name + '</span>',
							onClick: Function('editEvent(\'' + tempData[i].id + '\')')
						});
					}	
					curObj._menuItems[dateStr] = menuItems;
					ele.innerHTML = ele.innerHTML + '<br><span onmouseover="showEventList(this,\''+dateStr+'\');">Multiple... (' + tempData.length + ')</span>';
				} else {
					for(var i = 0; i < tempData.length; i++) {
						ele.innerHTML = ele.innerHTML + '<br>' + '<a class="{dialog.style}Link" href="#" title="'+tempData[i].detail+'" onclick="editEvent(\''+tempData[i].id+'\');$e.stopEvent(event); return false;">' +tempData[i].name +'</a>' ;
					}		
				}
			}
		}
	}
}

The calendarDrawItem() function draws the events that happen on a given day. The 'Item' in the function's name effectively means 'day'. In order to draw events this function uses json data that is created after the ajax callback from the calendarMonthNavigate() javascript function is made to the Xbasic getEvent() function on the server. The server-side function uses a date passed to it to retrieve SQL data from the Northwinds database, and then converts this data into JSON data. The returned JSON data is then stored in the calendar object itself. The getEvent() function is described in detail in the 'Line by Line Xbasic' section below.

The first thing the calendarDrawItem() function does is to get a pointer to the calendar object and assign this pointer to a javascript variable named 'curObj'. The variable 'calData' then uses this pointer to the calendar object to reference the json data; that was placed inside the calendar object after the ajax callback in the calendarMonthNavigate() function was made. The json data is stored in a variable called '_data'.

var curObj = {dialog.object}.getControl('DT1');
	var calData = curObj._data;

An if statement states that if the variable named 'curObj._menuItems' is undefined then this variable should be defined as a javascript object. This statement is used for cases where a given day or item has more than one event or order.

if(typeof curObj._menuItems == 'undefined') {
		curObj._menuItems = {};
	}

The calendarDrawItem() function is called multiple times during the drawing of the calendar. It gets called when the month navigators are drawn and when the date navigators are called. When the days or 'items' are drawn, the 'type' variable, that is passed into the calendarDrawItem() function as an argument, is equal to the date. The days in the control only need to be populated if the 'type' is equal to date. This is accomplished using a second if statement states. This states that if the calendar data is defined then a block of code should be executed.

if(type == 'date') {
		if(typeof calData != 'undefined') {...}}

The calendarDrawItem() function also takes 'date' as an argument that is passed into the function. The 'date' argument represents the day, or item, that the function is currently drawing. The 'ele' argument represents the id of the element on the calendar that is currently being drawn.

A javascript variable called 'dateStr', or date string, is constructed. This variable contains the year, month, and date of the day or item that is being drawn. The 'dateStr' variable exactly matches the format shown in the JSON object, i.e. year-month-day or, for example, '1994-8-4'. Because the formats used in the JSON object and the variable are the same, it is easy to quickly lookup data inside the object using only the variable; and return the orders or events for a particular day.

var dateStr = date.getFullYear() + '-' +(date.getMonth() + 1) + '-' + date.getDate();

If orders do exist for the day that is currently being drawn, then a second code block is executed.

if(typeof calData[dateStr] != 'undefined') {...}

This second code block determines whether if the orders, or events, should be displayed by themselves or in a menu. If there are multiple orders on a given day, then the menu option is used. A variable called 'maxItemsToShow' specifies that only 1 order should be shown on a given day. This number can be changed to allow more orders to be displayed before the pop-up menu option is used.

var maxItemsToShow = 1

An if statement then describes that if there are more orders than the 'maxItemsToShow' variable allows, then a block of code that creates a pop-up menu should be run.

if(tempData.length > maxItemsToShow ) {...}

The first half of the code block refers to the pop-up menu. The pop-up menu definition contains two variables. The first, 'windowContent', is an empty string and the second, 'menuItems', is an empty array.

var windowContent = '';
					var menuItems = [];

A 'for' statement loops over all of the orders for the specified day. The statement then populates the empty 'menuItems' array using the orders it finds. To do this, the statement pushes a json object on to the array. The json object contains two properties, 'html' and 'onClick'.

for(var i = 0; i < tempData.length; i++) {
						menuItems.push({
							html: '<span title="'+tempData[i].detail+'">' + tempData[i].name + '</span>',
							onClick: Function('editEvent(\'' + tempData[i].id + '\')')
						});

The html property is what gets displayed in the pop-up menu. It contains a <span> tag. Inside the <span> tag is a title property that contains the actual details of the order. The <span> also contains the customer name.

html: '<span title="'+tempData[i].detail+'">' + tempData[i].name + '</span>',

The 'onClick' property fires when a user selects an item from the menu. When the event fires, a function is constructed that is called 'editEvent()'. The event id, i.e. the html element being clicked on, is also included in this function.

onClick: Function('editEvent(\'' + tempData[i].id + '\')')

The 'menuItems' object is then set inside the date object using the empty menuItems array. The following code sets the menu items for the current date in the menuItems array.

curObj._menuItems[dateStr] = menuItems;

The menuItems array now has an array containing the actual data that the pop-up menu will display. The innerhtml is simply some text that contains the word 'Multiple...' and the number of orders or events for the day where the menu is displayed. The word 'Multiple' is placed inside a <span>. This <span> contains an onmouseover event. When the mouse is moved over the word 'Multiple', the onmouseover event fires and a javascript function called 'showEventList()' is called. Several arguments are passed into this function. The first, 'this', is a pointer to the element which the mouse is hovering over. 'dateStr' is the key into the calendar object, that allows the proper date to be displayed.

ele.innerHTML = ele.innerHTML + '<br><span onmouseover="showEventList(this,\''+dateStr+'\');">Multiple... (' + tempData.length + ')</span>';

The showEventList() Function

function showEventList(objEle, dateStr) {
	var menuName = '_CalendarDetailsMenu';
	var curObj = {dialog.object}.getControl('DT1');
	if(typeof curObj[menuName] == 'undefined') {
		curObj[menuName] = new A5.Menu([],{
			theme: '{dialog.style}',
			iconColumn: {show: false}
		});
	}
	
	curObj[menuName].populate(curObj._menuItems[dateStr]);
	curObj[menuName].show('popup',objEle);
}

The showEventList() function takes as arguments 'objEle' and 'dateStr'. The key that is passed in, 'dateStr', helps identify which day in the calendar should have its orders displayed. The variable 'menuName' assigns the name '_CalendarDetailsMenu'. Next a pointer to the calendar object is obtained using the getControl() method. As in other functions, here this variable is given the name 'curObj'.

function showEventList(objEle, dateStr) {
	var menuName = '_CalendarDetailsMenu';
	var curObj = {dialog.object}.getControl('DT1');

An if statement states that if the menu is undefined, then a new A5 menu object will be created using the menuName variable. The new menu object has two properties, 'theme' and 'iconColumn'. The theme is assigned to be the set dialog style and the iconColumn property is set to not be shown.

if(typeof curObj[menuName] == 'undefined') {
		curObj[menuName] = new A5.Menu([],{
			theme: '{dialog.style}',
			iconColumn: {show: false}
		});
	}

Near the end of the function the populate() method is called. This uses the array for the current date, that was created in the calendarDrawItem() function, to populate the pop-up menu. The populated menu is then displayed using the show() method. The information in the pop-up menu is displayed underneath the hyperlink that was clicked on.

curObj[menuName].populate(curObj._menuItems[dateStr]);
	curObj[menuName].show('popup',objEle);

Line by Line Xbasic 

getEvents

function getEvents as c (e as p)
dim month as c 
dim year as c 
dim startDate as d 
dim endDate as d 

startDate = date_value(val(e._year),val(e._month),1)
if val(e._month) < 12 then 
	endDate = date_value(val(e._year),val(e._month)+1,1) -1
else
	endDate = date_value(val(e._year)+1,1,1) -1
end if 

dim jsonData as c 
dim def as p
dim defn as p
defn.type = "sql"
defn.connectionString = "::Name::AADemo-Northwind"
defn.tableName = <<%sql%
SELECT Orders.OrderID as OrderId, 
	concatenate(orders.orderid,': ', customers.companyname) as eventName, 
	Orders.OrderDate as orderDate, 
	concatenate('Order: ', orders.orderid, ': ', customers.contactname, ' ', customers.companyname)  AS eventdescription 
FROM Orders Orders
	 INNER JOIN Customers Customers
		 ON  Orders.CustomerID = Customers.CustomerID
%sql%

defn.startDate = year(startDate) + "-" + month(startDate) + "-" + day(startDate)
defn.endDate = year(endDate) + "-" + month(endDate) + "-" + day(endDate)
defn.eventDate = "orderDate"
defn.eventId = "orderId"
defn.eventName = "eventName"
defn.eventDescription = "eventdescription"  

jsonData = a5_GetCalendarEventDataJSON(defn)
dim js as c  = ""

js = js + "var _cal = {dialog.object}.getControl('DT1');" + crlf()
js = js + "_cal._data = " + jsonData + ";" + crlf()
js = js + "_cal.refresh();" 
getEvents = js 

end function

The values for e._year and e._month are passed into the getEvents() function. These are the variables that were sent back in the ajax callback created at the end of the calendarMonthNavigate() function, on the Javascript functions page. Inside the getEvents() function these values are converted into a date value using the Xbasic date_value() expression. The converted values are used to create both a start date, 'startDate', and an end date, 'endDate'. These dates represent the start date and end date of the month that contains the events that we want to display on the calendar.

dim month as c 
dim year as c 
dim startDate as d 
dim endDate as d 

startDate = date_value(val(e._year),val(e._month),1)
if val(e._month) < 12 then 
	endDate = date_value(val(e._year),val(e._month)+1,1) -1
else
	endDate = date_value(val(e._year)+1,1,1) -1
end if

Next a SQL statement joins the 'OrderId' and 'Customer' table from the Northwinds database together. The built-in function a5_GetCalendarEventDataJSON() is then called.

dim jsonData as c 
dim def as p

//...some code//

jsonData = a5_GetCalendarEventDataJSON(defn)

The a5_GetCalendarEventDataJSON() function is a helper function that helps to retrieve data in the form of a json object. This function takes a definition, 'defn', as an argument. This definition is defined in the Xbasic getEvents function with the line 'dim defn as p'. The 'defn' object contains a number of properties. First the 'defn.type' property defines the definition's type. In this case the type is 'sql' but it could also be 'dbf'. The 'defn.connectionString' property specifies the database that the data will be pulled from. In the video this is "::Name::access_northwind_odbc". This guide uses the connection string "::Name::AADemo-Northwind", the sample database created from Alpha Anywhere's main toolbar.

dim defn as p
defn.type = "sql"
defn.connectionString = "::Name::AADemo-Northwind"

The 'defn.tableName' property specifies the table or sql statement that the data will be retrieved from. This example uses a select statement, but a single table could also be used here. The statement joins both the 'OrderId' table and the 'Customer' table.

defn.tableName = <<%sql%
SELECT Orders.OrderID as OrderId, 
	concatenate(orders.orderid,': ', customers.companyname) as eventName, 
	Orders.OrderDate as orderDate, 
	concatenate('Order: ', orders.orderid, ': ', customers.contactname, ' ', customers.companyname)  AS eventdescription 
FROM Orders Orders
	 INNER JOIN Customers Customers
		 ON  Orders.CustomerID = Customers.CustomerID
%sql%

The 'defn.startDate' and the 'defn.endDate' properties describe the start date and end date in the form year, month, day. This makes the function portable across different international locations.

defn.startDate = year(startDate) + "-" + month(startDate) + "-" + day(startDate)
defn.endDate = year(endDate) + "-" + month(endDate) + "-" + day(endDate)

The field in the sql table that contains the order, or event, date is identified using the 'defn.eventDate' property. The property 'defn.eventId' then states which field contains the order/event id. Similarly, the 'defn.eventName' and 'defn.eventDescription' properties specify the fields containing the order/event name and description.

defn.eventDate = "orderDate"
defn.eventId = "orderId"
defn.eventName = "eventName"
defn.eventDescription = "eventdescription"

After all of the definition properties are defined the a5_GetCalendarEventDataJSON() function is called.

jsonData = a5_GetCalendarEventDataJSON(defn)

This function takes all of the properties that are passed to it and returns data in the form of a JSON string. This data can be viewed in Alpha Anywhere by placing 'debug(1)' in the code just after the a5_GetCalendarEventDataJSON() function call, and then examining the resulting jsonData variable. Here is what it should look like:

{
'1994-8-4' : [{id: 10248,name: '10248: Vins et alcools Chevalier',detail: 'Order: 10248: Paul Henriot Vins et alcools Chevalier'}],
'1994-8-5' : [{id: 10249,name: '10249: Toms Spezialitäten',detail: 'Order: 10249: Karin Josephs Toms Spezialitäten'}],
'1994-8-8' : [{id: 10250,name: '10250: Hanari Carnes',detail: 'Order: 10250: Mario Pontes Hanari Carnes'},{id: 10251,name: '10251: Victuailles en stock',detail: 'Order: 10251: Mary Saveley Victuailles en stock'}],
'1994-8-9' : [{id: 10252,name: '10252: Suprêmes délices',detail: 'Order: 10252: Pascale Cartrain Suprêmes délices'}],
'1994-8-10' : [{id: 10253,name: '10253: Hanari Carnes',detail: 'Order: 10253: Mario Pontes Hanari Carnes'}],
'1994-8-11' : [{id: 10254,name: '10254: Chop-suey Chinese',detail: 'Order: 10254: Yang Wang Chop-suey Chinese'}],
'1994-8-12' : [{id: 10255,name: '10255: Richter Supermarkt',detail: 'Order: 10255: Michael Holz Richter Supermarkt'}],
'1994-8-15' : [{id: 10256,name: '10256: Wellington Importadora',detail: 'Order: 10256: Paula Parente Wellington Importadora'}],
'1994-8-16' : [{id: 10257,name: '10257: HILARIÓN-Abastos',detail: 'Order: 10257: Carlos Hernández HILARIÓN-Abastos'}],
'1994-8-17' : [{id: 10258,name: '10258: Ernst Handel',detail: 'Order: 10258: Roland Mendel Ernst Handel'}],
'1994-8-18' : [{id: 10259,name: '10259: Centro comercial Moctezuma',detail: 'Order: 10259: Francisco Chang Centro comercial Moctezuma'}],
'1994-8-19' : [{id: 10260,name: '10260: Ottilies Käseladen',detail: 'Order: 10260: Henriette Pfalzheim Ottilies Käseladen'},{id: 10261,name: '10261: Que Delícia',detail: 'Order: 10261: Bernardo Batista Que Delícia'}],
'1994-8-22' : [{id: 10262,name: '10262: Rattlesnake Canyon Grocery',detail: 'Order: 10262: Paula Wilson Rattlesnake Canyon Grocery'}],
'1994-8-23' : [{id: 10263,name: '10263: Ernst Handel',detail: 'Order: 10263: Roland Mendel Ernst Handel'}],
'1994-8-24' : [{id: 10264,name: '10264: Folk och fä HB',detail: 'Order: 10264: Maria Larsson Folk och fä HB'}],
'1994-8-25' : [{id: 10265,name: '10265: Blondel père et fils',detail: 'Order: 10265: Frédérique Citeaux Blondel père et fils'}],
'1994-8-26' : [{id: 10266,name: '10266: Wartian Herkku',detail: 'Order: 10266: Pirkko Koskitalo Wartian Herkku'}],
'1994-8-29' : [{id: 10267,name: '10267: Frankenversand',detail: 'Order: 10267: Peter Franken Frankenversand'}],
'1994-8-30' : [{id: 10268,name: '10268: GROSELLA-Restaurante',detail: 'Order: 10268: Manuel Pereira GROSELLA-Restaurante'}],
'1994-8-31' : [{id: 10269,name: '10269: White Clover Markets',detail: 'Order: 10269: Karl Jablonski White Clover Markets'}]
}

The data for the month of August 1994 is displayed. This is the date choosen in the default value defined for the calendar control. Entries in the json object are keyed to each day that an order/event took place. The orders that occurred on a given day are returned in the form of an array, which in json is defined using square brackets '[]'. For the day '1994-8-4' the array looks like this:

[{id: 10248,name: '10248: Vins et alcools Chevalier',detail: 'Order: 10248: Paul Henriot Vins et alcools Chevalier'}]

Each order/event inside a given array is defined as an individual object using curly braces '{}'. For example, here is the one event that occurred on '1994-8-4'.

{id: 10248,name: '10248: Vins et alcools Chevalier',detail: 'Order: 10248: Paul Henriot Vins et alcools Chevalier'}

When a day has more than one order/event, such as '1994-8-8', then the array contains multiple objects separated by a comma. This means that on any particular day there can be as many orders as desired.

After the a5_GetCalendarEventDataJSON() function call returns the json data to the getEvents() function, the Xbasic function defines some javascript to send back in response to the ajax callback.

dim js as c  = ""

The first line of this javascript creates a variable named '_cal'. This variable gets a pointer to the calendar object using the getControl() method. All of the JSON data that was returned from the a5_GetCalendarEventDataJSON() function is then placed inside a javascript variable called '_data'. Finally, the calendar's refresh() method is called. This will re-draw the calendar control calling the itemDraw() function for each day on the calendar.

js = js + "var _cal = {dialog.object}.getControl('DT1');" + crlf()
js = js + "_cal._data = " + jsonData + ";" + crlf()
js = js + "_cal.refresh();"

See Also