SitePoint Sponsor

User Tag List

Results 1 to 2 of 2
  1. #1
    SitePoint Member
    Join Date
    Oct 2008
    Posts
    1
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Thumbs down javascript calendar (month and day)

    Hi, I'm looking for a basic calendar feature to add to a website.
    I would like the month to display on top, preferably in short form (JAN, FEB)
    and the date underneath that. All of this overtop of an image, like a page a
    day pad type look to it.

    Any help would be appreciated, thanks David.

  2. #2
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    There are many different ways of respresenting the month and day in terms of html code. It could be a div with paragraphs, or a combination of heading and paragraph, but I'm going to use a definition list because it provides some useful styling hooks without having to resort to too many class names, and we are in some way defining that for the specified month we are interested in a particular day.

    Code javascript:
    <dl class="calendarPage">
        <dt>Month</dt>
        <dd>Day</dd>
    </dl>

    The css provides the presentational styling that we desire:

    Code javascript:
    .calendarPage {
        background-image: url(../images/calendarDayPage.jpg);
        border: 1px solid gray;
        height: 100px;
        width: 100px;
    }
    .calendarPage dt {
    	font-size: larger;
    	text-align: center;
    }
    .calendarPage dd {
    	font-weight: bold;
    	margin: 0;
    	padding: 0;
    	text-align: center;
    }

    So now we just need a way to update the month and day section. We can use a getElementsByClassName function. The one I'll use here is by Dustin Diaz. Some web browsers even have this function built in, so you can use a compatibility script to ensure that if you can't use the browser version, then you can at least fall back on a custom one.

    Code javascript:
    // [url]http://www.quirksmode.org/blog/archives/2008/05/getelementsbycl.html[/url]
    function getElementsByClassName(node, classname) {
    	if (node.getElementsByClassName)
    		return node.getElementsByClassName(classname);
    	else {
    		return dustinDiazGetElementsByClass(classname, node);
    	}
    }
    // [url]http://www.dustindiaz.com/getelementsbyclass/[/url]
    function dustinDiazGetElementsByClass(searchClass, node, tag) {
    	var classElements = new Array();
    	if (!node)
    		node = document;
    	if (!tag)
    		tag = '*';
    	var els = node.getElementsByTagName(tag);
    	var elsLen = els.length;
    	var pattern = new RegExp("(^|\\\\s)" + searchClass + "(\\\\s|$)");
    	for (i = 0, j = 0; i < elsLen; i++) {
    		if (pattern.test(els[i].className)) {
    			classElements[j] = els[i];
    			j++;
    		}
    	}
    	return classElements;
    }

    That was quite a lot of explaining and would have been made a lot simpler if I had used an identifier instead, but using a class name allows you to use it multiple times on a page which can be quite useful.

    Now we can get on with the actual coding for the page. We want to get the calendar page and the date, and update one with the other. Because there may be multiple pages that require updating, we can easily go through each calendarPage that was found and perform the same updates to them.

    Code javascript:
    var calendarPage = getElementsByClassName(document, 'calendarPage');
    forEach(calendarPage, function (page) {
    	var date = getMonthAndDay();
    	updateMonthAndDay(page, date);
    });

    That forEach function is a common one. Most web browsers have it built in to the array object, but IE still doesn't. Instead of coding it out manually each time for different circumstances, we can have a custom forEach function that can be used in many different circumstances. It also means that when we call forEach, the intent of our code is much clearer than it would be otherwise. A simple implementation of forEach is:

    Code javascript:
    function forEach(block, fn) {
    	var i;
    	for (i = 0; i < block.length; i += 1) {
    		fn(block[i]);
    	}
    }

    You may want to look at the Mozilla reference for the array forEach method, because there is also a some compatibility code there that can be used instead.

    The getMonthAndDay and updateMonthAndDay functions need to be covered now. We're wanting the months to be represented by the word names, and not the numbered versions. We can pull out the parts that we from the following date structure:
    Fri Oct 24 11:58:51 UTC+1300 2008

    Code javascript:
    function getMonthAndDay() {
    	var monthAndDay = {};
    	var now = new Date().toString();
    	var dateRegex = /\S+ (\S+) (\S+)/;
    	var results = now.match(dateRegex);
    	monthAndDay.month = results[1];
    	monthAndDay.day = results[2];
    	return monthAndDay;
    }

    The month and day are returned as an object so that we can work with and pass them more easily than if they were separate entities.

    When it comes to updating the month and day, we just need to know about the calendar page and pass in the date object which holds the month and day.

    Code javascript:
    function updateMonthAndDay(el, date) {
    	var month = el.getElementsByTagName('dt')[0];
    	var day = el.getElementsByTagName('dd')[0];
    	updateText(month, date.month);
    	updateText(day, date.day);
    }

    Updating the text is a simple process of removing the existing contents, before placing down the new text that's to be there.

    Code javascript:
    function updateText(el, text) {
    	removeContents(el);
    	el.appendChild(document.createTextNode(text));
    }
    function removeContents(el) {
    	while (el.hasChildNodes()) {
    		el.removeChild(el.firstChild);
    	}
    }

    And we should now be all finished.

    To summarize, here is the full javascript code. First will be the main code that's used, then that'll be followed by the common javsacript functions that I keep in a separate common.js file.

    calendarPage.js
    Code javascript:
    var calendarPage = getElementsByClassName(document, 'calendarPage');
    forEach(calendarPage, function (page) {
    	var date = getMonthAndDay();
    	updateMonthAndDay(page, date);
    });
    function getMonthAndDay() {
    	var monthAndDay = {};
    	var now = new Date().toString();
    	var dateRegex = /\S+ (\S+) (\S+)/;
    	var match = now.match(dateRegex);
    	monthAndDay.month = match[1];
    	monthAndDay.day = match[2];
    	return monthAndDay;
    }
    function updateMonthAndDay(el, date) {
    	var month = el.getElementsByTagName('dt')[0];
    	var day = el.getElementsByTagName('dd')[0];
    	updateText(month, date.month);
    	updateText(day, date.day);
    }

    common.js
    Code javascript:
    // [url]http://www.quirksmode.org/blog/archives/2008/05/getelementsbycl.html[/url]
    function getElementsByClassName(node, classname) {
    	if (node.getElementsByClassName)
    		return node.getElementsByClassName(classname);
    	else {
    		return dustinDiazGetElementsByClass(classname, node);
    	}
    }
    // [url]http://www.dustindiaz.com/getelementsbyclass/[/url]
    function dustinDiazGetElementsByClass(searchClass, node, tag) {
    	var classElements = new Array();
    	if (!node)
    		node = document;
    	if (!tag)
    		tag = '*';
    	var els = node.getElementsByTagName(tag);
    	var elsLen = els.length;
    	var pattern = new RegExp("(^|\\\\s)" + searchClass + "(\\\\s|$)");
    	for (i = 0, j = 0; i < elsLen; i++) {
    		if (pattern.test(els[i].className)) {
    			classElements[j] = els[i];
    			j++;
    		}
    	}
    	return classElements;
    }
    function forEach(block, fn) {
    	var i;
    	for (i = 0; i < block.length; i += 1) {
    		fn(block[i]);
    	}
    }
    function updateText(el, text) {
    	removeContents(el);
    	el.appendChild(document.createTextNode(text));
    }
    function removeContents(el) {
    	while (el.hasChildNodes()) {
    		el.removeChild(el.firstChild);
    	}
    }
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •