I have a year calendar generated in Javascript which renders each month as a row, horizontally as a group of tables. Dynamically setting the first month based on getting current serverTime. Each table is a month. The tables are:
<table id="m1"></table>
<table id="m2"></table>
<table id="m3"></table>
<table id="m4"></table>
<table id="m5"></table>
<table id="m6"></table>
<table id="m7"></table>
<table id="m8"></table>
<table id="m9"></table>
<table id="m10"></table>
<table id="m11"></table>
<table id="m12"></table>
<table id="m13"></table>
<table id="m14"></table>
and after DOM injection each month id is populated. Example for October '13 =
<table id="m2">
<tbody><tr><td>Oct 13</td>
<td></td><td></td>
<td class="avail" id="10_1_13">1</td>
<td class="avail" id="10_2_13">2</td>
<td class="avail" id="10_3_13">3</td>
<td class="avail" id="10_4_13">4</td>
<td class="avail" id="10_5_13">5</td>
<td class="avail" id="10_6_13">6</td>
<td class="avail" id="10_7_13">7</td>
<td class="avail" id="10_8_13">8</td><td class="avail" id="10_9_13">9</td><td class="avail" id="10_10_13">10</td><td class="avail" id="10_11_13">11</td><td class="avail" id="10_12_13">12</td><td class="avail" id="10_13_13">13</td><td class="avail" id="10_14_13">14</td><td class="avail" id="10_15_13">15</td><td class="avail" id="10_16_13">16</td><td class="avail" id="10_17_13">17</td><td class="avail" id="10_18_13">18</td><td class="avail" id="10_19_13">19</td><td class="avail" id="10_20_13">20</td><td class="avail" id="10_21_13">21</td><td class="avail" id="10_22_13">22</td><td class="avail" id="10_23_13">23</td><td class="avail" id="10_24_13">24</td><td class="avail" id="10_25_13">25</td><td class="avail" id="10_26_13">26</td><td class="avail" id="10_27_13">27</td><td class="avail" id="10_28_13">28</td><td class="avail" id="10_29_13">29</td><td class="avail" id="10_30_13">30</td><td class="avail" id="10_31_13">31</td><td></td><td></td><td></td><td></td></tr></tbody></table>
I have a javascript function "showBookingData(data)" which receives two dates from the server (startDate + endDate) for a booking which I pass to a render function "highlightBookTableMonthsChange(start, end)" to show a colored booked period on the calendar matching the start and end dates.
This render function calculates the difference in dates so that it can AddClass to each of the days of the booking to show a blocked out period, and highlights the relevant table.
The render function receives the dates in the following JSON =
{"d":[{"__type":"booking+PropDates","dataValueField":"02/19/14","dataValueField2":"02/26/14"}]}
The Problem:
My Render function 'highlightBookTableMonthsChange(start, end)' receives the dates correctly but seems to calculate from this point onwards different output dates varying from the early 1900's through to early 2100's for bookings in the next six months - depending on the time format of the client computer !!! So I need to tie down a format somewhere to avoid what I believe is some sort of assumed date calculations going on within the code at client side.
Javascript Functions:
function showBookingData(data) {
var len = data.d.length;
var i = 0;
for (i = 0; i < len; i++) {
var sptype = data.d[i].__type;
var startDate = data.d[i].dataValueField;
var endDate = data.d[i].dataValueField2;
// alert("{'startdate':" + startDate + ",'enddate':'" + endDate + "'}")
highlightBookTableMonthsChange(startDate, endDate)
}
}
function highlightBookTableMonthsChange(start, end) {
var start = new Date(start);
var end = new Date(end);
alert("{'startdate':" + start + ",'enddate':'" + end + "'}")
var i = 1;
$("#datesd").html($("#datesd").html()+'<br/>'+start + "" + end);
var timeDiff = Math.abs(end.getTime() - start.getTime());
var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
diffDays++;
while (start <= end) {
var startMonth = start.getMonth() + 1;
var startDate = start.getDate();
var year = start.getFullYear();
if (i == 1) {
var prevClass = $("#" + parseInt(startMonth) + "_" + startDate + "_" + year).attr("class");
if (prevClass == "lastBook" || prevClass == "fullBook")
{ $("#" + parseInt(startMonth) + "_" + startDate + "_" + year).attr("class", "fullBook"); }
else
$("#" + parseInt(startMonth) + "_" + startDate + "_" + year).attr("class", "firstBook");
}
else if (i == diffDays) {
$("#" + parseInt(startMonth) + "_" + startDate + "_" + year).attr("class", "lastBook");
}
else {
$("#" + parseInt(startMonth) + "_" + startDate + "_" + year).attr("class", "fullBook");
}
var newDate = start.setDate(start.getDate() + 1);
start = new Date(newDate);
i=i+1;
}
}
function createYearCalander() {
var i = 1;
var startDates = new Date(calanderStartDate);
var startMonth = startDates.getMonth();
var startYear = startDates.getFullYear();
if (country = "US") {
startDatee = startMonth + "/1/" + startYear;
}
else {
startDatee = "1/" + startMonth + "/" + startYear;
}
startMonth++;
for (i = 1; i <= 12; i++) { //Number of Months on Grid
createMonthTable(i, startMonth, startYear);
if (startMonth == 12) {
startMonth = 1;
startYear++;
}
else
startMonth++;
}
gerData(1); //Get Booking Date Data From Server
}
function createMonthTable(monthCount,mth,year) {
var table1 = document.getElementById('m' + monthCount);
var tblRow = tblRow = table1.insertRow(0);
var tblCell = null;
var dayys = countDaysOfMonth(mth, year);
var startDates = new Date(mth + "/1/" + year)
var firstDayOfMth = startDates.getDay(); //first day of month
var dataStarts = firstDayOfMth;
var dataEnds = firstDayOfMth + dayys;
var i = 0;
var tempDayStart = 1;
for (i = 0; i <= 37; i++) {
tblCell = tblRow.insertCell(i);
if (i == 0) {
tblCell.innerHTML = monthName(mth) + "," + year;
}
else if (i > dataStarts && i <= dataEnds) {
$(tblCell).attr("class", "avail")
tblCell.id = mth + "_" + tempDayStart + "_" + year;
tblCell.innerHTML = tempDayStart;
tempDayStart = tempDayStart + 1;
}
}
if (monthCount == 12) { //Months displayed on table grid
endDatee = mth + "/" + dayys + "/" + year;
}
}
function countDaysOfMonth(m,y)
{
return (/8|3|5|10/.test(--m) ? 30 : m == 1 ? (!(y % 4) && y % 100) || !(y % 400) ? 29 : 28 : 31);
}
function monthName(month)
{
if (month == 1)
return 'Jan'
else if (month == 2)
return 'Fab'
else if (month == 3)
return 'Mar'
else if (month == 4)
return 'Apr'
else if (month == 5)
return 'May'
else if (month == 6)
return 'Jun'
else if (month == 7)
return 'Jul'
else if (month == 8)
return 'Aug'
else if (month == 9)
return 'Sep'
else if (month == 10)
return 'Oct'
else if (month == 11)
return 'Nov'
else if (month == 12)
return 'Dec'
}
function getServerTime() {
$.ajax({
type: "POST",
//data: "{'propId':" + programId + "}",
url: "svcs/booking.asmx/getServerDate",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
calanderStartDate = data.d;
createYearCalander();
SetPrpCal();
},
error: OnError
});
}
function gerData(programId) {
Zzp = ($.super_cookie().read_value("propRz1", "zc"));
$.ajax({
type: "POST",
data: "{'cp':" + Zzp + ",'fDate':'" + startDatee + "','tDate':'" + endDatee + "'}",
url: "svcs/booking.asmx/getPropertyBookings",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
showBookingData(data)
},
error: OnError
});
}
I realize this isn't answering your question, but any reason you're rolling your own calendar functionality when there are a ton out there already that you could re-use? Date/times can get tricky.
If you have to roll your own, check out http://momentjs.com/. It will allow you to do things like get the # of days between two dates, and you can also add a day to any date.
So you can do something like (pseudocode without looking at library):
I found the answer to this via further testing:
I want to display the short format year in the left hand date column to keep the width down, but by using short date format, some client systems calculate the dates using 19** and the short format year.
So I changed the output JSON stream from the server to the date format (MM/dd/yyyyy) to force full year. This also automatically changes the date ID in the tables from "10_1_13" format for example to "10_1_2013" as the Oct 1st 2013 and accurately processes the bookings on the table. But also presents a full year in the first month column. So to correct this I trimmed the date format within the function createMonthTable(monthCount, mth, year). So the new function looks like this:
This now works perfectly ! See the output
For anybody looking for a client side flexible dynamic month horizontal calendar, which receives booking periods via JSON. This is a fast model easily styled using a little CSS. If anybody wants a css file too - then message me and I shall send one.