3
\$\begingroup\$

I've made my attempt to code timer entirely by hand using jQuery. No external libraries to manage time at all.

$(document).ready(function() {
	var setSessionMinutes = 5,
		setBreakMinutes = 5,
		sessionMinutes = setSessionMinutes,
		breakMinutes = setBreakMinutes,
		counterSeconds = -1,
		countTimeout,
		runState = false;

	function setClockValues() {
		$('#break').html(setBreakMinutes);
		$('#session').html(setSessionMinutes);
		$('#time').html(formatTime(setSessionMinutes, 0));
		sessionMinutes = setSessionMinutes;
		breakMinutes = setBreakMinutes;
		counterSeconds = -1;
	};
	setClockValues();

	function formatTime(minutes, seconds) {
		minutes = minutes >= 10 ? minutes : '0' + minutes;
		seconds = seconds >= 10 ? seconds : '0' + seconds;
		return minutes + ':' + seconds;
	}

	//change values by buttons
	$('#minusbreak').click(function() {
		$('#break').html(setBreakMinutes > 0 ? --setBreakMinutes : 0);
		breakMinutes = setBreakMinutes;
	});
	$('#plusbreak').click(function() {
		$('#break').html(++setBreakMinutes);
		breakMinutes = setBreakMinutes;
	});
	$('#minusSession').click(function() {
		$('#session').html(setSessionMinutes > 0 ? --setSessionMinutes : 0);
		$('#time').html(formatTime(setSessionMinutes, 0));
		sessionMinutes = setSessionMinutes;
	});
	$('#plusSession').click(function() {
		$('#session').html(++setSessionMinutes);
		$('#time').html(formatTime(setSessionMinutes, 0));
		sessionMinutes = setSessionMinutes;
	});

	function countDown() {
		if (counterSeconds < 0 && sessionMinutes >= 0) {
			--sessionMinutes;
			counterSeconds = 59;
		}
		$('#time').html(formatTime(sessionMinutes, counterSeconds));
		--counterSeconds;
		if (counterSeconds >= 0 && sessionMinutes >= 0)
			countTimeout = setTimeout(countDown, 1000);
		else {
			$('#finish').get(0).play();
			setTimeout(countDownBreak, 1000);
		}
	}

	function countDownBreak() {
		if (counterSeconds < 0 && breakMinutes >= 0) {
			--breakMinutes;
			counterSeconds = 59;
		}
		$('#time').html(formatTime(breakMinutes, counterSeconds));
		--counterSeconds;
		if (counterSeconds >= 0 && breakMinutes >= 0)
			countTimeout = setTimeout(countDownBreak, 1000);
		else {
			stopCountDown();
			$('#status').html('start');
			runState = false;
			$('#finish').get(0).play();
		}
	}
	function stopCountDown() {
		clearTimeout(countTimeout);
		setClockValues();
	}

	//   start/stop timer
	$('#status').click(function() {
		switch (runState) {
			case false:
				$('#status').html('reset');
				countDown();
				runState = true;
				break;
			case true:
				$('#status').html('start');
				stopCountDown();
				runState = false;
				break;
		}
	});

});

You can also see it on CodePen.io.

I realise this code should be 3/4 or even half current length, more DRY etc., but I'd like to get some opinions about code without much optimization to know better where I currently am with my progress. After all, I could spend 12 hours to make it beautiful (which I eventually will), but that would destroy purpose of this post.

About setTimeout instead of setInterval: I did it on purpose because of this.

\$\endgroup\$
1
\$\begingroup\$

Feedback

I know it has been nearly 3 years since this was posted and you likely have learned more about javascript and jQuery since then. Perhaps the information below is old news but nevertheless...

I like the styles and the sound that plays when the timer is done is fun! I did notice that if I decrease the Session Length to 0 and click the start button, it shows -01:59 and then appears to jump up to 05:58. Perhaps it would be wise to not allow the user to click the start button if the value for session length is 0.

Recommendations

I only see a couple things I would change:

  • It is recommended that DOM elements be stored in a variable - e.g.

    var breakElement = $('#break');
    

    And then later on use breakElement instead of $('#break') - e.g.

    breakElement.html(setBreakMinutes);
    
  • The switch statement at the end seems a bit heavy - why not just use an if/else:

    switch (runState) {
            case false:
                $('#status').html('reset');
                countDown();
                runState = true;
                break;
            case true:
                $('#status').html('start');
                stopCountDown();
                runState = false;
                break;
        }
    

    While it is only few lines shorter, there is no need to remember the break statements:

    if (runState) {
        $('#status').html('start');
        stopCountDown();
        runState = false;
    }
    else {
        $('#status').html('reset');
        countDown();
        runState = true;
    }
    
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.