Could you repeat that?

After a few weeks, working on and off, I’ve almost completely implemented an event calendar that supports repeating events.
 
In my previous update, I mentioned looking at an iCal implementation (which didn’t meet my needs), as well as finding a forum that laid out the groundwork for implementing recurring events in a database. However, I stumbled upon a much simpler solution:
 
A pseudo-cronjob implementation (forum link).
 
From the link above, I would have 3 fields/objects:
 
events (maps an id to the event name, start time, and array of dates)
event-dates (maps a date to an array of id’s)
endlessEvents*
 
*Note: Not yet implemented. Will end up storing a pattern for identifying whether an event falls on a particular day.
 
For events that have a definite end date (either after a number of occurrences or on a specific date), I enumerate all the dates that event would fall on and add the event ID to the specified date(s) in the map of event-dates.
 
If I need to delete an event, I would just need to get the ID and iterate over the map, removing the ID wherever found.
 
If I need to edit an event for a particular day, I would clone the event but give it a different ID, remove the old ID from the event-dates map for that particular day, and add the new event ID.


All that’s left to implement for the calendar is:

  • Endless event pattern matching
  • Editing / Removing an event
  • Modifying the implementation of “ends after x occurrences” to “ends on (date)”

After that, it’s just a short step to implement a checklist displaying what events are happening today. Then I get to play with PhoneGap to try and convert it to an Android / iPhone app.

Side Projects – Update

To update on the side projects I’ve been working on:

Medication Reminder – What was tried:

 
I tried using jQuery iCalendar but couldn’t figure out how to get it to actually display a calendar or link it to a calendar (it appears it’s only for converting an event into an iCal format) so I decided not to go down that route.

Medication Reminder – What has worked:

 
I’ve had a large amount of success using jQueryUI’s Datepicker (now rolled into jQueryMobile 1.4). Since the intended platforms are mobile devices and intended use is for medication reminders, for those that take a lot of medications, having individual visible events on a calendar would either extend the cells of the calendar or overflow on top of the days below it or be cutoff all together resulting in not all the “advertised” information being displayed, I opted to just color the cell in the calendar if there was SOMETHING for that day. Then, when the user click on that day, a window pops up detailing what all is to be taken that day, and if in the past, when the medication was actually taken.
 
By using the “beforeShowDay” option, I can check to see if there are any medications to be taken that day and set the highlight class as necessary. I also realized that since the class name the beforeShowDay option expects is just a string, I could have multiple classes like: “highlight big-date” (trivially) to highlight the date on the calendar and make the date number really big.
 
With this, I got the idea to include the date itself as a “class” so I could quickly pick the EXACT DOM element for a specific date and perform other DOM manipulations using jQuery (e.g.: if mobile device, do nothing special, but if desktop browser / tablet / sufficiently large display, inject medication name / time).
 
With the “medication-event” rendering problem solved (mostly), I’m now focusing on how to store the “medication-events” in a (relatively) small and robust manner (similar to iCal), specifically as it relates to recurring events. I’ve drawn a lot of inspiration from Google Calendar as far as how to present the input of a “medication-event” (“if it’s not broken, don’t fix it” and “don’t reinvent the wheel” come to mind) and from this thread on webdeveloper.com on how to store the “medication-event”. It has also provided some insight on how to render the recurring events as well as how to handle exceptions (e.g.: take daily at 7 am, except on weekends take at 9 am).
 
One other feature I implemented at the last minute to the “Add event” form is adding an auto-complete functionality for the medication name input. Not knowing what’s “common” prescribed medications, I just took a list from needymeds.org and modified the auto-complete to display the suggestions in a scrollable window (to prevent it from “breaking” the flow of the input page). An added benefit is that the brand names are included so the user can type either the generic / chemical name or the brand name and still find the medication (hopefully).

Medication Reminder – What remains:

 
Once the “medication-event” handling is complete, I’m ready to merge the calendar and the easy “one-touch taken medication” features and move on to packaging the web app in Phonegap to be able to leverage the native notification / popup features of Android/iOS.
 
You can view the event calendar at: http://beta.bradleymize.com/cal/
You can view the “one-touch taken medication” feature at: http://beta.bradleymize.com/pills/

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 */
}

Project Euler: Problem 19 – Counting Sundays

Problem 19:

You are given the following information, but you may prefer to do some research for yourself.

  • 1 Jan 1900 was a Monday.
  • Thirty days has September,
    April, June and November.
    All the rest have thirty-one,
    Saving February alone,
    Which has twenty-eight, rain or shine.
    And on leap years, twenty-nine.
  • A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.

How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?

Idea:

Until I saw that the Calendar class could add months/days/years to a given calendar, I had no idea how I was going to approach this that would be pretty (store the number of days per month, taking into account leap years, finding which day was sunday, and just iterating). The add method made this trivial.

int answer = 0;

GregorianCalendar calendar = new GregorianCalendar(1901,Calendar.JANUARY,1);

while(calendar.get(Calendar.YEAR) != 2001) {
   if(calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
      answer++;
   }
   calendar.add(Calendar.MONTH, 1);
}

System.out.println("Answer: "+answer);