Adding Alarms to the Digital Clock

Adding Alarms to the Digital Clock

Last week, we created a jQuery & CSS3 – powered digital clock. In this update, we will add support for setting alarms using the HTML5 audio element.

The Idea

To extend the digital clock with support for alarms, we need to add a few crucial pieces of functionality to the code from last week:

  • We need to have a way for people to set and edit alarms. This would require some kind of dialog with fields for setting the time of the alarm;
  • Every second, we will need to check whether an alarm should go off. If it should, we will play a small audio file and display a “Time’s up” dialog.

These features will require changes to the HTML, CSS and jQuery. Let’s begin!

Setting an Alarm

Setting an Alarm

The HTML

We will have two dialogs – one for setting/editing an alarm, and another that is displayed when an alarm goes off.

index.html

<div class="overlay">

	<div id="alarm-dialog">

		<h2>Set alarm after</h2>

		<label class="hours">
			Hours
			<input type="number" value="0" min="0" />
		</label>

		<label class="minutes">
			Minutes
			<input type="number" value="0" min="0" />
		</label>

		<label class="seconds">
			Seconds
			<input type="number" value="0" min="0" />
		</label>

		<div class="button-holder">
			<a id="alarm-set" class="button blue">Set</a>
			<a id="alarm-clear" class="button red">Clear</a>
		</div>

		<a class="close"></a>

	</div>

</div>

<div class="overlay">

	<div id="time-is-up">

		<h2>Time's up!</h2>

		<div class="button-holder">
			<a class="button blue">Close</a>
		</div>

	</div>

</div>

Both of these dialogs are hidden with CSS and are shown with the jQuery fadeIn() method when they are needed. Another thing worth noting is that the alarm dialog uses the HTML5 number input types with a min value of 0. Number inputs are very easy to validate with JavaScript (more about that in the next section) and they also bring up the number keyboard on mobile devices.

Next is the HTML5 audio element. It contains source tags with two different audio formats. The first is an mp3 version of the alarm sound, and the second ogg. The ogg format is only needed in Firefox, which doesn’t yet support mp3 playback due to licensing issues. Pretty much all other browsers which support HTML5 audio also support mp3.

index.html

<audio id="alarm-ring" preload>
	<source src="assets/audio/ticktac.mp3" type="audio/mpeg" />
	<source src="assets/audio/ticktac.ogg" type="audio/ogg" />
</audio>

The preload attribute tells the browser that these sound files should be downloaded ahead of time, which will make them immediately available once we decide to play them (otherwise there would be a delay the first time an alarm is played until they are downloaded). Playing the audio file is extremely simple thanks to JavaScript’s HTML5 audio API (more on that in the next fragment).

The jQuery

In this section of the tutorial, we will extend the jQuery code of the digital clock to support and play the alarms. I won’t be explaining the code we wrote last time, only the new additions.

The first thing we have to do is to define a number of variables, important for the functioning of the alarms:

assets/js/script.js

var dialog = $('#alarm-dialog').parent(),
	alarm_set = $('#alarm-set'),
	alarm_clear = $('#alarm-clear'),
	time_is_up = $('#time-is-up').parent();

// This will hold the number of seconds left
// until the alarm should go off
var alarm_counter = -1;

Next, we have to check whether there is an alarm pending on every tick of the update_time() function.

// Is there an alarm set?

if(alarm_counter > 0){

	// Decrement the counter with one second
	alarm_counter--;

	// Activate the alarm icon
	alarm.addClass('active');
}
else if(alarm_counter == 0){

	time_is_up.fadeIn();

	// Play the alarm sound. This will fail
	// in browsers which don't support HTML5 audio

	try{
		$('#alarm-ring')[0].play();
	}
	catch(e){}

	alarm_counter--;
	alarm.removeClass('active');
}
else{
	// The alarm has been cleared
	alarm.removeClass('active');
}

When the counter reaches 0, this would mean that we should play the alarm sound and show the “Time is up” dialog. Notice that although I am selecting the #alarm-ring audio element with jQuery, I am accessing the first DOM element within the collection so I get access to the JavaScript play() method that is available on audio elements.

TIme's up!

TIme’s up!

The last thing left to do, is to handle the “Set an alarm” dialog and the various buttons:

// Handle setting and clearing alamrs

$('.alarm-button').click(function(){

	// Show the dialog
	dialog.trigger('show');

});

dialog.find('.close').click(function(){
	dialog.trigger('hide')
});

dialog.click(function(e){

	// When the overlay is clicked, 
	// hide the dialog.

	if($(e.target).is('.overlay')){
		// This check is need to prevent
		// bubbled up events from hiding the dialog
		dialog.trigger('hide');
	}
});

alarm_set.click(function(){

	var valid = true, after = 0,
		to_seconds = [3600, 60, 1];

	dialog.find('input').each(function(i){

		// Using the validity property in HTML5-enabled browsers:

		if(this.validity && !this.validity.valid){

			// The input field contains something other than a digit,
			// or a number less than the min value

			valid = false;
			this.focus();

			return false;
		}

		after += to_seconds[i] * parseInt(parseInt(this.value));
	});

	if(!valid){
		alert('Please enter a valid number!');
		return;
	}

	if(after < 1){
		alert('Please choose a time in the future!');
		return;	
	}

	alarm_counter = after;
	dialog.trigger('hide');
});

alarm_clear.click(function(){
	alarm_counter = -1;

	dialog.trigger('hide');
});

// Custom events to keep the code clean
dialog.on('hide',function(){

	dialog.fadeOut();

}).on('show',function(){

	// Calculate how much time is left for the alarm to go off.

	var hours = 0, minutes = 0, seconds = 0, tmp = 0;

	if(alarm_counter > 0){

		// There is an alarm set, calculate the remaining time

		tmp = alarm_counter;

		hours = Math.floor(tmp/3600);
		tmp = tmp%3600;

		minutes = Math.floor(tmp/60);
		tmp = tmp%60;

		seconds = tmp;
	}

	// Update the input fields
	dialog.find('input').eq(0).val(hours).end().eq(1).val(minutes).end().eq(2).val(seconds);

	dialog.fadeIn();

});

time_is_up.click(function(){
	time_is_up.fadeOut();
});

There are a few interesting things about this code. Notice how I am using the built-in validity property on line 35, which is exists for the number input type in modern browsers. It tells us whether the content of the input field is a number greater than 0 (remember that they have a minimum value of 0).

Another other thing worth noting is the way the code for the alarm dialog is organized with custom events. When the show event is triggered, we calculate the remaining hours, minutes and seconds of the alarm, which are then inserted into the input fields.

With this our pretty digital clock with alarms is ready! I hope that you’ve liked this quick tutorial and will find it handy in your own projects.

Join our newsletter and get our PSDs!17,405 people learn about HTML5, JS and more. Join them!

by Martin Angelov

Martin is a web developer with an eye for design from Bulgaria. He founded Tutorialzine in 2009 and publishes new tutorials weekly.

13 Comments

  1. Md. Elias says:

    This is awesome

  2. Pushker says:

    awesome , always learns new things from you.

  3. sanjeev says:

    Awesome Tutorial !!

  4. sany2k8 says:

    Excellent......

  5. Kien Nguyen says:

    Thank you! I used your clock for my page and it's look so cool ^^

  6. Great tutorial Martin...!!
    I never used HTML5 audio element. You have nicely explained its use with alarm clock.
    Thanks.

  7. Sheng Slogar says:

    Very cool! I was wondering why you didn't have an alarm hooked up, yet you had an alarm clock icon! Great job! (One side note, though: Shouldn't you allow the enter key to be pressed to set the alarm? And shouldn't you be able to set the alarm by clicking the clock's icon? Or are you trying to be more like a real digital clock with just buttons to control it?)

    1. Martin Angelov says:

      Those are all good suggestions! I will have to leave them as an exercise for the readers though :)

  8. This is an awesome tutorial. Thanks for the inspiration :)

  9. adicahyana says:

    this is a good job. wanna use on my web. thx for share mate

  10. Karthikeyan says:

    Great Job Martin :)

  11. Joshua says:

    What is this code for?

    if($(e.target).is('.overlay')){
    // This check is need to prevent
    // bubbled up events from hiding the dialog
    dialog.trigger('hide');

    What are bubbled up events? Does it break if you take that out?

  12. Dj says:

    Hi. Really cool clock. Could you make it into a poker clock? So that you can start the time and every X minutes, the alarm comes in and displays a text? (at the poker clock the next blind would be displayed) Would that work anyway? This text was translated from German to English, because my English is not so good.

Add Comment

Add a Reply

HTML is escaped automatically. Surround code blocks with <pre></pre> for readability.
Perks:   **bold**   __italics__   [some text](http://example.com) for links