Fluid Square Calendar with jQueryUI Datepicker Tutorial

In this tutorial I’ll show you the steps taken to customize an un-styled jQueryUI Datepicker widget as well as how to overcome a few common formatting problems relating to styling the jQueryUI Datepicker, using pure CSS. It will take you from starting with a completely blank document to having a fully structured HTML page using the jQuery Mobile framework with a fluid, square calendar.
 
Disclaimer: The following was only tested using the latest version of Google Chrome.

Getting Started

First thing you need is the stand-alone Datepicker Widget and its CSS. You can use those download links or you can customize your jQueryUI package yourself by going to jQueryUI’s Download Builder.
 
Then you’ll need to create the page that will hold the datepicker. You can do this manually, or you can copy the code below for a jQuery Mobile version. I’ve highlighted the important pieces of the code.
 

<!doctype html>

<html lang="en">
    <head>
        <meta charset="utf-8">

        <title>Calendar Test</title>
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
        <meta name="description" content="jQuery Calendar Test">
        <meta name="author" content="B-rad">
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.css" />
		<link rel="stylesheet" href="jquery-ui-1.10.3.css" />
		<style>
		
		</style>
    </head>
    <body>
		
        <div data-role="page" id="dailyMinder">
            <div data-role="header" data-position="fixed" data-tap-toggle="false">
                <h1>Calendar Test</h1>
            </div>
			
            <div data-role="main" class="ui-content">
				<div id="calendar"></div>
            </div>
        </div>
		
        <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.js"></script>
		<script src="jquery-ui-datepicker.min.js"></script>
		<script type="text/javascript">
		$('#calendar').datepicker({
			inline: true,
			firstDay: 0,
			showOtherMonths: true,
			dayNamesMin: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
		});
		
		</script>
    </body>
</html>

The first highlights add the jQuery Mobile stylesheet from their CDN (using a schemeless URI) and add the custom, no-theme stylesheet for the Datepicker (your path may differ depending on where you extracted it to).
 
The second highlight is where the Datepicker will appear.
 
The last highlight adds the jQuery and jQueryMobile javascript (from their CDN), the jQueryUI-datepicker javascript, and the javascript necessary to display a Datepicker whose first day of the week is Sunday, will display the other months’ days and specifies the shorthand notation for the days of the week.
 
You should now have a page that looks like the following:

The CSS – Basic Customization

Now that you have all the necessary files and setup work done, lets start by adding borders to the calendar. Find the “.ui-datepicker td” class and change from “border: 0;” to the following:

.ui-datepicker td {
	border: 1px solid #428bdd; /* edited - border: 0; */
	padding: 1px;
}

While we’re at it, lets make the title bold, a little larger, make it so the cursor doesn’t change while mousing over the title, and add the “Prev/Next” words in there to change the months:

.ui-datepicker .ui-datepicker-title {
	margin: 0 2.3em;
	line-height: 1.8em;
	text-align: center;
	font-weight: bold;	/* make month title bold */
	font-size: 1.2em;	/* make month title larger */
	cursor: default;	/* keep default cursor over month */
}
.ui-icon {
	display: block;
	/*text-indent: -99999px;	remove this line */
	overflow: hidden;
	background-repeat: no-repeat;
}

We can see that the “Prev/Next” don’t quite line up with the rest of the Datepicker and the cursor isn’t the appropriate type, so lets fix that:

.ui-datepicker .ui-datepicker-prev-hover,
.ui-datepicker .ui-datepicker-next-hover {
	cursor: pointer; /* link cursor */
	top: 1px;
}
.ui-datepicker .ui-datepicker-prev {
	top: 4px;		/* lower the text */
	left: 2px;
}
.ui-datepicker .ui-datepicker-next {
	top: 4px;		/* lower the text */
	right: 10px;	/* edited - right: 2px; */
}
.ui-datepicker .ui-datepicker-next-hover {
	right: 9px;		/* edited - right: 1px; */
}

Lastly, lets make it span the whole width of the page (fluidly):

.ui-datepicker {
	/*width: 17em;	remove this line */
	padding: .2em .2em 0;
	display: none;
}

You should now have something that looks like:

The CSS – Fixing The Height

If you’ve ever tried to customize the height of a table row based on the width, you’ve probably encountered a LOT of problems. This section will show you how to change the table row / cell height based on the width, and also how to fix the last column of the table not having a fixed width or the last table column not having the same width.
 
To get the height of the cells changed, add the following pseudo-class after “.ui-datepicker td”

.ui-datepicker td:before {
	content: "";
	display: block;
	padding-top: 100%;	/* set height of cell (padding based on width) */
}

Getting closer, but the columns aren’t the same size and the dates aren’t identically placed! Since the dates are nested inside links, we change the styles for the links, like so:

.ui-datepicker td a {
	display: block;
	padding: .2em;
	text-align: center;			/* center the date, optional */
	text-decoration: none;
	position:  absolute;		/* position the date in the cell */
	top: 0;						/* put the link at the top */
	left: 0;					/* put the link at the left */
	bottom: 0;					/* extend the link to the bottom */
	right: 0;					/* extend the link to the right */
}

Now the dates have disappeared! To get them to come back we need to change the layout of the table cell:

.ui-datepicker td {
	position: relative;	/* position elements relatively */
	border: 1px solid #428bdd; /* edited - border: 0; */
	padding: 1px;
}

Now the dates have returned and the entire cell is clickable. Now for the magical part: making the height of table cells the same as the width. To do that we just as 1 more line to our “.ui-datepicker table” class:

.ui-datepicker table {
	width: 100%;
	table-layout:fixed !important; /* sets width of each column equally (and in turn, their height) */
	font-size: .9em;
	border-collapse: collapse;
	margin: 0 0 .4em;
}

And that’s it!

You should now have a full width, fluid calendar / datepicker with square cells like so:

If you want to change the height of the cells, change the padding in the pseudo-class we added earlier. For example, having the cells half as tall as they are wide is accomplished with:

.ui-datepicker td:before {
	content: "";
	display: block;
	padding-top: 50%;	/* height half the width */
}

Side Projects

During my downtime from working on my Magic: The Gathering Web App I’ve picked up some new side projects to keep things interesting as well as give myself a break from constantly thinking about the same project; give me a change to step away and come back at it looking at the bigger picture or from an outsider’s point of view.

 

The first side project I decided to embark upon is a JSONP API. Inspired by MTGAPI.com, I started to wonder how difficult it was to make an API, particularly for JSON responses, since I already knew how to set the header of an HTTP request in PHP and I knew that JSON responses only printed out the JSON data structure of whatever was being requested. So I made a simple echo service, tested it out, and sure enough it worked! Reading more on JSONP and it’s limitations, I tested it (as best as my limited knowledge could) against common XSS attacks with the help of OWASP.

 

Now if only I had some actual data to make use of the API. 1st World Problems.

 

Another side project I’ve started is a web app that helps people remember to take their medications (at the suggestion of a family member; demo). I put it together in a day and it’s still VERY rough around the edges and I’m working on figuring out what features would be required / desired. Right now, it looks like the hard part will be handling recurrences and a calendar. Right now I’m using FullCalendar, which is great, but leaves the recurrence handling server-side and there isn’t any iCal support (which would make handling recurrences easy), but as of right now, it could work, just wouldn’t be pretty.

 

In the mean time, I’m looking at other options which includes jQuery iCalendar which can handle parsing iCal events (particularly recurring events). I am also trying out jQueryUI’s Datepicker widget as the calendar base and looking for ways to tie in event managment. Styling it appropriately has been difficult so I’ll also be posting a short tutorial on how I managed to make it a fluid, full-sized calendar with square cells.

 

Lastly, a project I haven’t started yet (but is on the horizon) is working with PhoneGap. A limitation with the medication reminder web app mentioned above is the lack of support for notifications. Once a working version of the web app is made, it is my understanding that I could package it in a PhoneGap app and port it to iPhone / Android and be able to take advantage of the native notification services which would help facilitate reminders throughout the day.