Update: If you came here via search engine looking for a “jQuery scheduler,” this might not be what you’re looking for. If you’re looking for something like Google Calendar where you can schedule events, try Ext SchedulerwdCalendar, or FullCalendar. Here are a few more.

Remember the scheduler app that I wrote? It’s a tiny web app that doesn’t do much: You add a bunch of entries to a time slot, and it randomly picks an entry from each time slot. Essentially, you use it when you’ve got a lot of choices (e.g., scheduling volunteers to work at an event), and you’d like to have a random way of picking those choices.

Regardless of how simple it is, it was a perfect candidate on which for me to practice my JavaScript and CSS skills.

How do you organize jQuery code? How do you use CSS to make an intuitive UI? Those were the kinds of questions I tried to answer when fiddling with this web app. I’ll show you what I did to make it look cool and make it work the way I want.

Incremental Work

I made a few versions since I first wrote the app.

Scheduler 1.0

The first version of the app meets all the original requirements:

  • You can add names to the schedule.
  • You can generate a schedule with a name randomly selected from each time slot.

Scheduler 2.0

After getting the app to do what it’s supposed to do, I wanted to add a few more features, so I made version 2:

  • I changed “employee” to “entry.” I wanted to make it more generic.
  • You can edit the times. They’re still defaulted to certain hours (so it still meets my friend’s requirements), but now if other people want to use it, they can change the values to meet their needs.
  • You can add and delete rows. Now that you can edit the times and add/delete rows, the app is flexible enough to act as a crude calendar for scheduling appointments.
  • There’s a button to delete all entries. If you add too many entries and want to start over, there’s now an easy “reset” button.
  • I wanted to make the buttons look nicer.
Scheduler 2.1

Scheduler 2.1

After version 2, I thought I was done, but then after a while, I decided to make a tad more changes, so now there’s version 2.1:

  • The buttons are renamed and regrouped. “Delete All Entries” and “Delete Last Row” seemed too long, so I shortened them.
  • UI cues were added. When you hover over each button, I want the user to get an impression of what the effect would be. When the user clicks “- Row,” the last row is highlighted red, to cue the user that the last row will be deleted if the user clicks the button.

Pretty Buttons

I’m a good developer, but I suck at designing. Thankfully, though, there’s plenty of resources out there for me to work from.

The buttons in the first version of the app were a combination of icons from famfamfam and some inspiration from ParticleTree. For the later versions, I used a technique I read in a Smashing Magazine article. It uses some CSS3 techniques like border-radius, text-shadow, and box-shadow. IE doesn’t support any of it (as expected), but the button degrades nicely in IE, so I’m happy with that. Here’s the sample code  from the article on how to style such a button:

button.awesome, .button.awesome {
	background: #222 url(/images/alert-overlay.png) repeat-x;
	display: inline-block;
	padding: 5px 10px 6px;
	color: #fff;
	text-decoration: none;
	font-weight: bold;
	line-height: 1;
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	-moz-box-shadow: 0 1px 3px rgba(0,0,0,0.5);
	-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.5);
	text-shadow: 0 -1px 1px rgba(0,0,0,0.25);
	border-bottom: 1px solid rgba(0,0,0,0.25);
	position: relative;
	cursor: pointer;
}

Because CSS3 isn’t officially supported in browsers yet, you have to use the browser-specific implementations for each browser: -moz-border-radius for Firefox and -webkit-border-radius for Safari and Chrome, for example. Also note that they use a PNG image overlay to give the button a cool gradient effect.

The buttons in version 2.1 have an extra bottom border, and I gave them different rounded edges for fun. When I regrouped the buttons together, making the “add” buttons green and the “delete” buttons red made it look too much like a Christmas-decorated button menu. So, I settled for them give a very subtle color on the bottom of the button, so the “add” and “delete” colors are still there, but it doesn’t look so Christmas-y.

Oh, and there’s one other thing I added, which I feel is important to the user experience of the app: I removed text selection on the buttons. Normally, when you double-click on text on a webpage, the web browser automatically selects that text for you. When you’re building a custom button in a web application, you don’t want that button text to be selected when a user clicks on it too many times. So, I discovered how to disable that behavior in each browser using jQuery:

$('.actions a')
	.attr('unselectable','on')
	.css('MozUserSelect','none')
	.bind('selectstart.ui', function() {
		return false;
	});

I forget which is which (obviously, “MozUserSelect” is referring to Firefox), but each line disables text selection for those action buttons in their respective web browsers. I’m sure this snippet of code will be very handy whenever I make any more web apps.

UI Cues

I liked the idea of having some sort of visible cue whenever the user hovers over a button. For instance, when you hover over “- Entries,” you’ll notice that all the entries on the schedule will be highlighted red. This helps illustrate the function of the button. To do this, I took advantage of jQuery’s hover() function. It allows you to specify a function to call on a button’s hover state, as well as a function to call when the cursor is no longer hovering over the button. When the cursor hovers over the “- Entries” button, the following function is called:

// Highlight entries to be deleted to cue user of deletion action
function removeEntriesHighlight() {
	$('.entry').addClass('deleting');
}

The “deleting” class is then styled with CSS to highlight the entries red.

Organizing JavaScript

Writing clean JavaScript code can be tricky. It seems as though everyone does it differently, depending on the coding style and what libraries are used. This is the approach I used:

  • Put plugin code in an anonymous function
  • Put the rest of your code in a domready block
  • Initialize reusable variables at the top of the domready block
  • Separate code into functions within that domready block
  • Have an init

So essentially, my code looks like this:

$(function() { // domready block

	// initialize variables
	var foo = 'bar',
		foo1 = 'bar2;

	// run
	init();

	function init() {
		// init code
		blah();
		blah2();
	}

	function blah() {
	}

	function blah2() {
	}

	// ... and so on
}

;(function($) {
	// custom jQuery plugin code goes here
})(jQuery);

It makes the code look fairly organized, or so at least I think it does. If you’ve got any better tips on writing clean jQuery code, let me know! I’m still learning and trying to come up with a best practice.

Version Control

Last but not least, there’s version control. As any good developer knows, you should use some type of version control system to manage your code. Otherwise, if your code gets accidentally lost or deleted, you can’t get it back!

I’ve been testing out Mercurial lately, and I really like it. It feels as easy to use as Subversion, and I’m really liking the whole idea of being able to commit locally vs pushing changes onto the server. If you haven’t given Mercurial a try yet, I highly recommend it.

BitBucket offers free Mercurial hosting, so I’ve been using that to host the source code for my scheduler app. Feel free to check out my source code if you like. :)

Well, that’s all I’ve got. I hope that was informative. If you’ve got any JavaScript or CSS tips or perhaps any suggestions for my web app, let me know.

Word image made with Wordle.