Wednesday, September 28, 2005
Blogger Calendar Addin (Modified)  

A few months ago, I added a calendar to this blog which highlights the days on which I have written a post. Although this comes standard for some blog software, it must be added for Blogger. I have been asked several times about how to this can be done. Thus, I have decided to write post on it which I can point to rather than having to keep copying and pasting the same email.

First, thanks to Phil Ringnalda for the code for the calendar addin. He originally wrote the code to display on archive pages. I made a few changes which allow the current month's calendar to appear on the main page with days highlighted for when posts have been added to the blog in the current month. Adding this to your Blogger site is not difficult. Here are the steps:

1. The first step has the most amount of code, but it is really quite simple. For a copy of the code click here (Right-click and select "Save As.." or the equivalent to save the file). Or you can copy it from this page. The JavaScript just needs to be copied in to the header section of your Blogger template which is between the tags <HEAD> and </HEAD>.

<script type="text/javascript" language="JavaScript">
/* you absolutely, positively must change the value for dateType below to match your
"Date Header Format" as set in your blog's Settings
if your date format is:
"Sunday, June 24, 2001" use 1
"6/24/2001" use 2
"6.24.2001" use 3
"20010624" use 4
"2001/06/24" use 5
"2001-06-24" use 6
"24.6.01" use 7
"June 24, 2001" use 8
"june 24, 2001" use 9
something else, change to one of those and use the right number! */

dateType = "1";

tableFontStyle = "10px Verdana";
tableFontColor = "#FFFFFF";
tableBackgroundStyle = "#808080";
tableBackgroundLinkStyle = "#ffff99";
tableTodayBackgroundStyle = "#abcabc";
// tableBorderStyle is the CSS style applied to the outside of the table,
// and around each cell
tableBorderStyle = "1px solid black";
tableTodayBorderStyle = "1px solid red";
// tableBorder is the ugly old HTML border attribute
tableBorder = "0";

/* Added Code
Defaults:*/
var this_month = getCurrentMonth();
var this_year = getCurrentYear();
var this_day = getFirstDayOfCurrentMonth();
month = 1;
day = 1;
year = 2005;
thisDate = this_day + ", " + this_month + " 1, " + this_year;

/* change the lowMonthNames if you use a non-English language and you use
one of the date styles
with the month name in the date, but be sure they are in lower case
(these are used for matching, not displaying */

lowMonthNames = new Array("january", "february", "march", "april", "may", _
"june", "july", "august", "september", "october", "november", "december");

// you can change the displayMonthNames and displayWeekdayNames to anything
// that suits you

displayMonthNames = new Array("January", "February", "March", "April", "May", _
"June", "July", "August", "September", "October", "November", "December");
displayWeekdayNames = new Array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", _
"Sat");

/* if you already do something with the body onload event (or want to later),
add a call to it in this function or put the "if (inArchives)
drawCalendar();" call in your existing onload function */
function doOnloadTasks(){
/*if (inArchives) {*/
drawCalendar();
/*}*/
}

// time to stop changing things, unless you are sure you know
// what you're doing!
function getCurrentMonth() {
var months=new Array(13);
months[1]="January";
months[2]="February";
months[3]="March";
months[4]="April";
months[5]="May";
months[6]="June";
months[7]="July";
months[8]="August";
months[9]="September";
months[10]="October";
months[11]="November";
months[12]="December";
var time=new Date();
var this_month=months[time.getMonth() + 1];
return this_month;
}
function getFirstDayOfCurrentMonth () {
var days = new Array(8);
days[1]="Sunday";
days[2]="Monday";
days[3]="Tuesday";
days[4]="Wednesday";
days[5]="Thursday";
days[6]="Friday";
days[7]="Saturday";
var current_date=new Date();
current_date.setDate(1);
var this_day=days[current_date.getDay() + 1];
return this_day;
}
function getCurrentYear() {
var current_date=new Date();
var this_year=current_date.getYear();
if (this_year < 2000) {
this_year = this_year + 1900;
}
return this_year;
}
links = new Array();
inArchives = false;
if (location.href.indexOf("<$BlogArchiveFileName$>") > -1) _
inArchives = true;

function datesplitter(date, datetype){
switch(datetype){
case "1" :
date = date.substring(date.indexOf(",")+2);
year = date.substring(date.length-4);
day = date.substring(date.indexOf(" ")+1,date.indexOf(","));
wordMonth = date.substring(0,date.indexOf(" "));
wordMonth = wordMonth.toLowerCase();
for (i = 0; i < 12; i++){
if (lowMonthNames[i] == wordMonth){
month = i;
i = 12;
}
}
break;
case "2" :
year = date.substring(date.length-4);
month = date.substring(0,date.indexOf("/"))-1;
day = date.substring(date.indexOf("/")+1,date.lastIndexOf("/"));
break;
case "3" :
year = date.substring(date.length-4);
month = date.substring(0,date.indexOf("."))-1;
day = date.substring(date.indexOf(".")+1,date.lastIndexOf("."));
break;
case "4" :
year = date.substring(0,4);
month = date.substring(4,6);
if (month.charAt(0) == "0") month = month.substring(1);
month = month-1;
day = date.substring(6);
if (day.charAt(0) == "0") day = day.substring(1);
break;
case "5" :
year = date.substring(0,4);
month = date.substring(date.indexOf("/")+1,date.lastIndexOf("/"));
if (month.charAt(0) == "0") month = month.substring(1);
month = month-1;
day = date.substring(date.lastIndexOf("/")+1);
if (day.charAt(0) == "0") day = day.substring(1);
break;
case "6" :
year = date.substring(0,4);
month = date.substring(date.indexOf("-")+1,date.lastIndexOf("-"));
if (month.charAt(0) == "0") month = month.substring(1);
month = month-1;
day = date.substring(date.lastIndexOf("-")+1);
if (day.charAt(0) == "0") day = day.substring(1);
break;
case "7" :
year = date.substring(date.length-2);
if (year.charAt(0) == "0") year = year.charAt(1);
year = parseInt(year);
if (year < 50) year = 2000 + year; else year = 1900 + year;
month = date.substring(date.indexOf(".")+1,date.lastIndexOf("."))-1;
day = date.substring(0,date.indexOf("."));
break;
case "8" :
year = date.substring(date.length-4);
day = date.substring(date.indexOf(" ")+1,date.indexOf(","));
wordMonth = date.substring(0,date.indexOf(" "));
wordMonth = wordMonth.toLowerCase();
for (i = 0; i < 12; i++){
if (lowMonthNames[i] == wordMonth){
month = i;
i = 12;
}
}
break;
case "9" :
year = date.substring(date.length-4);
day = date.substring(date.indexOf(" ")+1,date.indexOf(","));
wordMonth = date.substring(0,date.indexOf(" "));
for (i = 0; i < 12; i++){
if (lowMonthNames[i] == wordMonth){
month = i;
i = 12;
}
}
break;
default :
year = 1980;
month = 1;
day = 1;
}
oDate = new Date(year, month, day);
return oDate;
}

function countDays(date){
// given a date object, return number of days in that month
monthcount = new Array ("31", "28", "31", "30", "31", "30", "31", "31", _
"30", "31", "30", "31");
year = date.getFullYear();
if (year % 4 == 0){
if (year % 100 == 0){
if (year % 400 == 0){
monthcount[1]++;
}
}
else {
monthcount[1]++;
}
}
return monthcount[date.getMonth()];
}

function drawCalendar(){
// Set a variable for today's month and year
todaysDate = new Date();
todaysMonth = todaysDate.getMonth() + 1;
todaysYear = getCurrentYear();
todaysMonthYear = todaysMonth + "" + todaysYear;
todaysFullDate = todaysDate.getDate();
if (todaysFullDate < 10) {
todaysFullDate = "0" + todaysFullDate;
}
if (todaysMonth < 10) {
todaysFullDate = todaysFullDate + "0" + todaysMonth + todaysYear;
}else{
todaysFullDate = todaysFullDate + "" + todaysMonth + todaysYear;
}
// only executes in a DOM compliant browser
if (document.getElementById){
if (document.createElement){
// IE is just barely compliant, if you use a deprecated style of
// attribute setting
navigator.appVersion.indexOf("MSIE") > 0 ? isIE = true : isIE = false;
if (inArchives) {
calStart = realDate;
}else{
calStart = datesplitter(thisDate,dateType);
}
calStart.setDate(1);
dayCount = countDays(calStart);
leadblanks = calStart.getDay();
oTable = document.createElement("TABLE");
oTBody = document.createElement("TBODY");
oRow = document.createElement("TR");
oCell = document.createElement("TD");
if (isIE)
oCell.colSpan="7";
else
oCell.setAttribute("colspan", "7");
oDateLabel = document.createTextNode(displayMonthNames[calStart.getMonth()] _
+ " " + calStart.getFullYear());
oCell.appendChild(oDateLabel);
oRow.appendChild(oCell);
oTBody.appendChild(oRow);
oRow = document.createElement("TR");
for (i=0;i<7;i++){
oCell = document.createElement("TD");
oCell.style.border = tableBorderStyle;
oDay = document.createTextNode(displayWeekdayNames[i]);
oCell.appendChild(oDay);
oRow.appendChild(oCell);
}
oTBody.appendChild(oRow);
dayindex = 1;
while (dayindex <= dayCount){
this_index_month = calStart.getMonth() + 1;
if (this_index_month < 10) {
this_index_month = "0" + this_index_month;
}
this_index_day = dayindex;
if (dayindex < 10) {
this_index_day = "0" + dayindex;
}
this_index = calStart.getFullYear() + "" + this_index_month + "" + _
this_index_day;
this_index = this_index - 0;
oRow = document.createElement("TR");
for (i=0;i<leadblanks;i++){
oCell = document.createElement("TD");
oCell.style.border = tableBorderStyle;
if (isIE)
oSpace = document.createTextNode(" ");
else
{
oSpace = document.createTextNode("*");
oCell.style.color = tableBackgroundStyle;
}
oCell.appendChild(oSpace);
oRow.appendChild(oCell);
}
for (b=leadblanks;b<7;b++){
oCell = document.createElement("TD");
oCell.style.border = tableBorderStyle;
addLink = false;
thisLinkMonthYear = "00000";
this_index_month = calStart.getMonth() + 1;
if (this_index_month < 10) {
this_index_month = "0" + this_index_month;
}
this_index_day = dayindex;
if (dayindex < 10) {
this_index_day = "0" + dayindex;
}
this_index = calStart.getFullYear() + "" + this_index_month + "" + _
this_index_day;
this_index = this_index - 0;
if (links[this_index] != null){
thisLinkDate = new Date(links[this_index].slice(2) - 0);
thisLinkMonth = thisLinkDate.getMonth() + 1;
thisLinkYear = thisLinkDate.getFullYear();
thisLinkMonthYear = thisLinkMonth + "" + thisLinkYear;
if (inArchives) {
addLink = true;
}else{
if (todaysMonthYear == thisLinkMonthYear) {
addLink = true;
}else{
addLink = false;
}
}
}
thisFullDay = dayindex;
if (thisFullDay < 10) {
thisFullDay = "0" + thisFullDay;
}
if (todaysMonth < 10) {
thisFullDay = thisFullDay + "0" + todaysMonth + todaysYear;
}else{
thisFullDay = thisFullDay + todaysMonth + todaysYear;
}
// If a link is to be added
if (links[this_index] != null && addLink){
oLink = document.createElement("A");
if (isIE)
oLink.href=links[this_index];
else
oLink.setAttribute("href", links[this_index]);
oLinkText = document.createTextNode(dayindex);
oLink.appendChild(oLinkText);
oCell.appendChild(oLink);
oCell.style.background = tableBackgroundLinkStyle;
// Mark the current day of the month
if (inArchives == false && todaysFullDate == thisFullDay) {
oCell.style.border = tableTodayBorderStyle;
}
}
// If no link is to be added
else
if (dayindex <= dayCount){
oDayText = document.createTextNode(dayindex);
oCell.appendChild(oDayText);
// Mark the current day of the month
if (inArchives == false && todaysFullDate == thisFullDay) {
oCell.style.border = tableTodayBorderStyle;
}
}else{
if (isIE)
oSpace = document.createTextNode(" ");
else
{
oSpace = document.createTextNode("*");
oCell.style.color = tableBackgroundStyle;
}
oCell.appendChild(oSpace);
}
oRow.appendChild(oCell);
oTBody.appendChild(oRow);
dayindex++;
}
leadblanks = 0;
}
oTBody.style.font = tableFontStyle;
/* Added 16 May 2005 */
oTBody.style.color = tableFontColor;
oTBody.style.textAlign = "center";
oTable.appendChild(oTBody);
if (isIE)
oTable.style.background = tableBackgroundStyle;
else
oTable.setAttribute("bgColor", tableBackgroundStyle);
oTable.border = tableBorder;
oTable.style.border = tableBorderStyle;
calendarSpot = document.getElementById("CalendarHere");
calendarSpot.appendChild(oTable);
}
}
}
// Function returns index value for links array
// based on date
function getIndex(thisDate) {
index_month = thisDate.getMonth() + 1;
if (index_month < 10) {
index_month = "0" + index_month;
}
index_day = thisDate.getDate();
if (index_day < 10) {
index_day = "0" + index_day;
}
index_num = thisDate.getFullYear() + "" + index_month + "" + index_day;
index_num = index_num - 0;
return index_num;
}
</script>



2. The second step is to set the date format in the JavaScript which you just copied. Look for the "Date Header Format" section of the code. Select the date format which is identical to the "Date Header Format' which you selected in Blogger (Settings | Formatting in Blogger). Select the appropriate format and modify the line

dateType = "1";

by setting dateType equal to correct number.

3. Also on the Settings page in Blogger, change the numer of posts displayed to a number which is high enough to display the maximum number of posts you would put out in a month. I have set this to around 35 because generally I will not post more than once a day in a given month.

4. 3. In your template, replace your <BlogDateHeader> to </BlogDateHeader> section with:

<BlogDateHeader>
<script type="text/javascript">
var postDate="<$BlogDateHeaderDate$>";
realDate = datesplitter(postDate,dateType);
anchorDate = realDate.valueOf();
index_num = getIndex(realDate);
links[index_num] = "#d" + anchorDate;
document.write("<a name='d" + anchorDate + "'></a>");
</script>
<$BlogDateHeaderDate$>
</BlogDateHeader>



5. Add the following to your template, in the place that you want the calendar to appear:

<span id="CalendarHere"><!-- tells the script where to put the calendar --></span>



6. Finally, change the <BODY> tag in your template to:

<BODY onload="doOnloadTasks();">



The way it works is that after the page is loaded, the doOnloadTasks script is run. This calls a number of scripts which start to write out the calendar for the current month as defined by the page. When you are on an archived page, it will display the calendar for the archived month. (Note, you must archive by month for the calendar to display correctly on archive pages. Change this setting on the Archiving page under Settings in Blogger.) As the calendar is written, it checks whether there is a post on the current page for the date the script is writing to the calendar. For days with posts, the day is change to a highlighted day.

Feel free to email me if you have any questions about how to get this to work.

Also, apparently there is a blog dedicated to describing Blogger Template tricks.

Posted by David at 8:00 AM  |  Comments (1)  | Link

1 Comments:

i'm going to try it this evening!

thanks in advance!

By Blogger astronautje, at June 10, 2006 10:28 AM  

Post a Comment