Extended prototypes

This page will explain how the files in the demo pack were used to create a data populated calendar object that interacts with an arbitary HTML form.

You can add any protoype you want to the native calendar object or extend existing prototypes. To ensure the object works correctly these native protoypes should not be overwritten: draw, selectDate, defineDate, isDefined.

To ensure the calendar populates a form with data you will need to extend the selectDate prototype from the INZU_calendar object. This is the example form we will be interacting with, it can be any form:


Tickets Quantity Price
Total: $0.00
Please select a date from the calendar... $0.00

This is the HTML code for the form above.

<div id="booking-select" style="margin-top:16px;">
  <form action="booking_process.php" method="post"> 
  
  <table width="100%" border="0" cellspacing="0" cellpadding="0">
  
  <thead id="booking-head">
  <tr>
  <th align="left">Tickets</th>
  <th width="72" align="center">Quantity</th>
  <th width="56" align="right">Price</th>
  </tr>
  </thead>
<tfoot id="booking-total"> <tr> <td align="left"></td> <td align="center"><strong>Total:</strong></td> <td align="right" id="basketTotal">&#36;0.00</td> </tr> </tfoot>
<tbody id="booking-selected"> <tr> <td align="left">Please select a date from the calendar...</td> <td align="center"><input type="text" maxlength="3" style="width:20px;"/></td> <td align="right">&#36;0.00</td> </tr> </tbody>
</table>
<input name="booking_date" id="booking_date" type="hidden"/> <input name="variations" id="variations_amt" type="hidden"/> <input name="" type="submit" style="float:right;margin-top:6px"/>
</form> </div>

The selectDate prototype

The 'selectDate' prototype is triggered when a user clicks on any day of the month. It is included in the native object that is served by Inzu.

calendar.selectDate = function(dayElement, year, month, day) {}

The prototype's parameters are as follows:

dayElement
The table cell element (an available day) that has been clicked.

year, month, day
The year, month and day of the cell that has been clicked.


Now let's extend the selectDate prototype:

calendar.selectDate = function(dayElement, year, month, day) {

this.day = day;

if ( dayElement.classList.contains("available") || dayElement.classList.contains( "selected") ) {

...

We start off with two lines - this.day lets the object know what day is selected, and the conditional statement ensures that the following code is only executed for days that are available or already selected.

The INZU_calendar object will automatically give table cells the right CSS class names according to data supplied from the Inzu API, so days that have availability have the class "available".


As users click different dates we delete any existing rows from our form. We also create a list for all the ticket variations available for that particular date. This list will be used to form the checkout URL.


for ( var i = document.getElementById("booking-selected").rows.length; i > 0; i--) {
	
	document.getElementById("booking-selected").deleteRow(i-1);
	
}

var variations_list = "";

With the form cleared, we now cycle through all the ticket variations available for the selected date, adding a table row in the form for each ticket variation.

Note we have also included a keyUp behaviour on the amount fields, this adjusts the total amount displayed according to the amount of tickets inputted. The adjustTotal method attached is a custom method added to the calendar object. See how this is done at the end of this page.

for ( var variation in day_sel ) {

variations_list += variation + ",";

// Check if date is sold out

var day_sold = day_sel[variation].info.sold;

// Add variation info to order form

var tBody = document.getElementById("booking-selected");

if ( day_sold == "sold_out" ) {
	
newRow = tBody.insertRow(-1);
td1 = newRow.insertCell(-1);
td1.setAttribute("id", "booking-title");
td1.innerHTML = '<strong>SOLD OUT</strong>';

} else {
	
// Variation title

td1 = newRow.insertCell(-1);
td1.setAttribute("id" ,"booking-title");
td1.innerHTML = this.variations[variation].type_title ;

// Quantity form fields

td2 = newRow.insertCell(-1);
td2.setAttribute("id", "highlight");
td2.setAttribute("align", "center");
td2.innerHTML='<input id="amount_'+variation+'" name="amount_'+variation+'" type="text" value="" maxlength="3" style="width:20px;" onkeyup="calendar.adjustTotal();"  />';

// Variation price form fields

if (this.variations[variation].free_entry) {
	
var price = 0;
var user_price = "FREE";

} else {
	
var user_price = "$" + this.variations[variation].price;
var price = this.variations[variation].price;

}

td3 = newRow.insertCell(-1);
td3.setAttribute("align", "right");
td3.innerHTML = user_price+'<input id="price_'+variation+'" type="hidden" value="'+price+'" />';

}


}

With the rows added for each ticket variation, we now highlight the selected day on the calendar by changing it's class and unhighlighting the previously selected date:

dayElement.classList.toggle("selected");

// Deselect last chosen date

if ( typeof this.lastSelected !== "undefined" && this.lastSelectedMonth == this.month ) {
	
	document.getElementById(this.lastSelected).classList.toggle("selected");

}

We also let the object know which day has been selected for next time a date is selected.

this.lastSelected = dayElement.id;
this.lastSelectedMonth = this.month;

The form's hidden fields are populated with the selected date and the variation list. The number of variations list is passed in the form so we can successfully cycle through the POST data when the form is submitted.

document.getElementById('booking_date').value = this.year + "-" + this.month + "-" + this.day;
document.getElementById("variations").value = variations_list.slice(0, -1);

The adjustTotal function is called at the end to reset the total amount read out.

this.adjustTotal();

Crucially we return the selectDate prototype with the existing selectDate prototype, thereby extending it rather than overwriting it.

return INZU_calendar.prototype.selectDate.apply(this, arguments);

The adjustTotal method

The 'adjustTotal' method is not part of the native object served by Inzu, it has been added to display a running total based on the amout of tickets a user has inputted.

calendar.adjustTotal = function adjustTotal(resetTotal) {

var total = 0;
var amount_selected = 0;

if ( !resetTotal ) {
	
for ( var variation in this.variations ) {

 if ( document.getElementById('amount_' + variation) !== null ) {
	
  amtSel = parseInt(document.getElementById('amount_' + variation).value) || 0;
  amount_selected += amtSel;

  price = parseFloat(document.getElementById('price_' + variation).value);

 }

 if ( amtSel > 0) total += price * amtSel;

 }

}


total = Math.round( total * 100 ) / 100; 
total = total.toFixed(2);

document.getElementById('basketTotal').innerHTML = "&#36;" + total;

}