Create a countdown timer with Titanium Appcelerator

In this post we will try to show you how to make a countdown timer using Titanium Appcelerator for Iphone or Android applications.

First we will create an OOP countDown object that can be used independently in the background of the application and then we will connect it with some interface elements.

The countDown object

To have functional a countdown timer we’ll need to declare some properties and some methods.

As properties we will set:

time:{ m : minutes, s : seconds },
total_seconds : m*60+s

I think this is pretty clear, time is an object with minutes and seconds and total_seconds contains the number of seconds until we reach 00:00.

We will need to set methods that will allow us to:

  • set a time to count from
  • stop the timer
  • start it.

We also ned to set some callback functions that will be executed on each tick of the timer ย  – fn_tick – and one that will execute when the timer reaches 00:00 named fn_end.

We won’t make a callback for start because we know when this occurs we can trigger it by ourselves.

The countDown timer will look like this:

var my_timer = new countDown( minutes, seconds, fn_tick, fn_complete);

on this we will be able to apply

my_timer.set( minutes, seconds );
my_timer.start();
my_tmer.stop();

Below is the code that defines the countDown (pretty simple).

var countDown =  function( m , s, fn_tick, fn_end  ) {
	return {
		total_sec:m*60+s,
		timer:this.timer,
		set: function(m,s) {
			this.total_sec = parseInt(m)*60+parseInt(s);
			this.time = {m:m,s:s};
			return this;
		},
		start: function() {
			var self = this;
			this.timer = setInterval( function() {
				if (self.total_sec) {
					self.total_sec--;
					self.time = { m : parseInt(self.total_sec/60), s: (self.total_sec%60) };
					fn_tick();
				}
				else {
					self.stop();
					fn_end();
				}
				}, 1000 );
			return this;
		},
		stop: function() {
			clearInterval(this.timer)
			this.time = {m:0,s:0};
			this.total_sec = 0;
			return this;
		}
	}
}

And now to use it in our code we will do something like this:

var my_timer = new countDown(1 , 5 ,
	function()	{
		//something here...
	},
	function() {
		// something here...
	}
);
 
my_timer.start();

Ok, the above example is useless, we will need to display the current time on each tick of the countdown times (so on each second) and at the end we’ll have to alert the user when we reached 00:00.

We will also need some interface elements to access the countdown methods and to display the current time.

For this we will create a label named display_lbl, that will show the time and also 3 buttons : set_btn , start_btn and stop_btn.

Creating the code is pretty simple so I won’t put the code here but you will be able to take a look at it downloading the countdown project.

What is most important is to connect the interface with the countdown timer.

So we create the timer and set the fn_tick and fn_end functions

var my_timer = new countDown(5,30, 
		function() {
			display_lbl.text = my_timer.time.m+" : "+my_timer.time.s;
		},
		function() {
			alert("The time is up!");
		}
	);

And this is how we connect the buttons with my_timer

 
set_btn.addEventListener('click',function(){
	display_lbl.text = "5 : 30";
	my_timer.set(5,30);
});
 
stop_btn.addEventListener('click',function(){
	my_timer.stop();
});
 
start_btn.addEventListener('click',function(){
	my_timer.start();
});

As you see we also set the label’s text to the initial value when we set the timer because otherwise we’ll loose the first second. We do this here to keep the timer object clean of any external interaction so we can use it even without an interface.

This is how the final project looks like

Countdown timer with Appcelerator

Please keep in mind that this is just a simple example and we don’t have a control mechanism to detect when the user stopped the timer or it reached by itself 00:00 – but you can add it as an exercise ๐Ÿ™‚

You can download the Resources folder of the project from here.

Everything is MIT licensed and you can use it in any application you want to, but spreading the word would be nice.

Check the Spanish version of this post:
Crear un temporizador regresivo con Titanium Appcelerator

32 thoughts on “Create a countdown timer with Titanium Appcelerator”

  1. I got quite a few compiling bugs in this original code. I was able to modify it a bit to overcome them.

    I also discovered that pressing the Start button multiple times makes the countdown fly, many alerts to pop-up, and the iPhone simulator to crash.

    I added some code to detect if the countdown was already started and to alert the user to stop pressing start. You could also disabled the Start button.

    I’d be happy to make this code available for inclusion if anyone knows who to contact.

  2. Thanks for the code:

    I put the code into an Android app, and find the counter stops when I switch tasks and sometimes even when the phone goes to standby. Any ideas?

    At Justin Noel:
    It helps to have a variable “counting” to determine if the counter already runs and eliminate redundant button clicks.

  3. You will just have to change the countdown function to accept hours too.
    All you have to do is to accept another argument ‘h’ and modify the function to calculate and display the new format.

  4. Hi,

    is it possible to create a pause-function to the timer and maybe call minutes and seconds from an external xml-file?

    What I want is to create a timer in a podcast tableview using rss to show the remaining m’s and s’s..

    hope you can help me ๐Ÿ™‚

  5. I’m sure it’s possible.

    You would have to parse the time field in the xml and find the difference between that time and the present (when the user plays with the app). After this you only have to stop the timer, set its new value and start it again (assuming you have one counter only on the page).

    In case you need a pause method it would be similar with the stop one except the lines that reset the time and seconds to 0 (comment this 2 lines ). Let me know if I understood me or you need more info.

  6. Thx for your quick response – I think you understood it perfectly..

    How do you parse a time field in an xml – I’ve tried, but there doesn’t seem to be any variable to do that – do you have a trick?

    Maybe a few lines of code, as I’m new to programming ๐Ÿ™‚

    The pause method is not a must, but it would be nice to have..

  7. You need to get the xml and it’s fields. Depending on how the time string is formatted you can try a regex or something ready made. How’s the field formatted?

    The pause method you can add it yourself, as I just suggested ๐Ÿ™‚

  8. Forgort to mention, that my xml-file only consists of an rss-code – sorry.. I’ve never used xml before and still I’m learning basic JavaScript – so I’m pretty much a noob trying to get it ๐Ÿ™‚

    using an edited version of this code – http://pastie.org/838012 – in Titanium and a simple rss-feed like this – http://rss.cnn.com/services/podcasting/newscast/rss.xml

    I was trying to load it into:

    var my_timer = new countDown( THIS AREA
    function() {
    display_lbl.text = my_timer.time.m+” : “+my_timer.time.s;
    },
    function() {
    alert(“The time is up!”);
    }
    );

    But that didn’t work – should I implement the countDown-code in the pastie-example linked above?

    As you can hear (and see) I’m pretty new to it all, but this is actually the first time I’m getting some good advice and help getting on.. The last few months have been struggling hard to work around my problems not getting answers in Q&A on appcelerators website..

    So I’m very grateful that you are willing to help me.. Thank you!

  9. My last comment was made in a rush as my laptop battery level was at 2 % – with this saying that I should have been more detailed in my description of what i didn’t understand ๐Ÿ™‚

    I’ve never worked with xml before, so I’m pretty much unaware of how those fields work – what I tried out was to add fields in my rss like this:

    something
    1,2,
    etc…

    then load the description into my_timer instead of 1,2,

    var my_timer = new countDown( MY CONTENT HERE (rss-description)
    function() {

    but that didn’t work.. Maybe I should mention that I’m using this code to load my rss-feed/xml-file – http://pastie.org/838012

    Implementing the timer into the “pastie”-code didn’t seem to work either – I’m pretty sure that this is just a simple problem, but as you can hear, I’m pretty new to this JavaScript-programming – so I’m so happy that you’re willing to help and give me some advice..

    The last couple of months I’ve had to solve problems by myself – I’ve never got a solution to my problem in Q&A on the appcelerator-forum :/
    That can be quite hard being a noob!

    I’m so grateful for your help – thank you.. Please say if I should make myself more clear or paste some of my own code.. This is just such a simple feature, but very necessary when making a music-app ๐Ÿ™‚

  10. I think the field you need is the length, right?
    In this case you just have to get it as you get the url of the audio

    mp3_length = itemList.item(c).getElementsByTagName("enclosure").item(0)
    .getAttribute("length");

    I think this is in ms so from here you need to convert the ms into minutes and seconds to adapt it to the timer script

    ms_time_m = parseInt((mp3_length/1000)/60);
    ms_time_s = (mp3_length/1000)%60;

    and

    counter = new countDown(ms_time_m,ms_time_s, fn_tick, fn_complete);

    Download the code to see how fn_tick anf fn_complete are used.

  11. Thx again – now I have the timer recognizing my mp3_length variable, but it still doesn’t count down nor does it convert ms to m and s. It shows in display_lbl – but that’s it.

    I’ve put the “ms_time_m = parseInt((mp3_length/1000)/60);
    ms_time_s = (mp3_length/1000)%60;” in the countDown-part, but maybe it is in the wrong place?

    It also shows a bug with the “var my_timer = new countDown(ms_time_m,ms_time_s, fn_tick, fn_complete);”

    How does the constant variables like “new countDown(1,30,” and “my_timer.set(5,30);” change? I’ve tried placing “e.rowData.mp3Length” instead, but that doesn’t have any effect at all – it shows a bug!

  12. Okay, so here is my code http://pastie.org/1588443

    This:

    stream.addEventListener(‘progress’, function(e){
    Titanium.API.info(‘Time Played: ‘ + Math.round(e.progress) + ‘ seconds’);
    });

    shows the duration as the podcast plays, but only in seconds – maybe I could use this if there’s a way to convert it, as it doesn’t necessarily have to be a countdown – it might as well be an indication of how long the song have been playing!

  13. yes, you could use this, which I think is better than to use a separate timer.
    Maybe like this:

    stream.addEventListener('progress', function(e){
    Titanium.API.info('Time Played: ' + Math.round(e.progress) + ' seconds');
    display_label.text = parseInt(e.progress/60)+':'+e.progress%60;
    });

    this will show you something like : 12:34. If the file is bigger than 60 min you will need to adjust your algorithm.

  14. Thx, that did the trick ๐Ÿ™‚ sort of..

    I edited it a bit:

    stream.addEventListener(‘progress’, function(e){
    Titanium.API.info(‘Time Played: ‘ + Math.round(e.progress) + ‘ seconds’);
    item_counter_label.text = parseInt(e.progress/60)+’:’+Math.round(e.progress)%60;
    });

    Now the problem to fix, is that it shows like this 0:1, 0:2, 0:3 –> 1:0, 1:1, 1:2 etc.. When it would be best to have it like this 0:01, 0:02, 0:03 –> 1:00, 1:01, 1:02 etc..

    Is there a workaround for this or should I just be happy that it works? ๐Ÿ™‚

  15. Hi again..

    It turns out it only did the trick less than sort of.. ๐Ÿ™

    Now, if I choose a podcast it plays and the counter ticks, but if I choose another podcast, the counter doesn’t respond – not even in API.info… If I go back to the first podcast it doesn’t respond either.. Seems the evenListener can only recognize the duration when clicking the first time!

    Is there an explanation to this or am I just not seeing the obvious?

    /Anders

  16. It seems that the audio player looses the progress event when you change the track. There is another bug related to the change event ( even for me it seems to work ) but might be related. I’ll try to create a test case and submit a bug to the Appcelerator. I think you might have to recreate a stream each time you want to change the track until they fix the bug or reply me.

  17. Okay, either way, thank you so much for your help!

    What I really want to do is to create a player playing a playlist – there’s still no way to use the native music player with url-files, is there?

Comments are closed.