Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pause functionality not working for all timers #73

Closed
wgpalexander opened this issue Aug 7, 2016 · 9 comments
Closed

Pause functionality not working for all timers #73

wgpalexander opened this issue Aug 7, 2016 · 9 comments

Comments

@wgpalexander
Copy link

Hi guys,

Firstly - great script, I'm using it within PhoneGap to create my first basic test app and it's proving very useful.

I am creating a simple timer on one screen where we have 3 simultaneous timers:

  1. Elapsed - counts up to a set interval duration (e.g. 20s first, then 10s, then 30s)
  2. TotalTime - counts up, will cover multiple intervals (e.g. 1 min in this simple case)
  3. Remaining - is a countdown timer from the total of all intervals (e.g. 1 min in this simple case)

Lets ignore the complexities around refreshing the Elapsed timer for each interval and getting the total time for the countdown for the moment.

I start all timers simultaneously using $('#Go').click - assuming this is all I do the counters work well.

I have a pause button triggered by $('#Pause').click which then pauses all the timers at whatever reading they were on using the following code:

$('#Pause').click(function() {
// Now need to pause the timers
$('#Elapsed').timer('pause');
$('#TotalTime').timer('pause');
$('#Remaining').timer('pause');

  • some other unrelated code
    }); // End Pause click

When I resume the timers however Elapsed seems to work as intended, but the other two timers jump out of sync - e.g. I have a demo running in the background just now which is meant to last 30s but TotalTime is 6:55 and Remaining is -7:25.

I tried flashing an alert when paused to confirm the state of the timers and they all do return "paused" as I would expect so I think I'm implementing it properly.

I noted that there was a closed case for a similar issue which you corrected with the latest version - I tried replacing the script with that one but the problem persisted (and actually created a new one whereby there is a slight delay starting the timers which knocks some other stuff out.)

Would you be able to advise whether this is a script issue or a user issue? Would be great to get this resolved as I can finally close off that piece of my app :)

Many thanks
Wayne

@walmik
Copy link
Owner

walmik commented Aug 7, 2016

@wgpalexander
Hi Wayne! Firstly thank you for using the jQuery timer plugin for your project!

Secondly, I d like some more info so that I can set up a local representation of this issue you are facing. To get some context, is it like you want something to be done for say 1 minute (TotalTime) and then Elapsed shows the time that s passing by and Remaining (TotalTime - Elapsed) but with a countdown? If that is the case then I m not able to figure out what is the need for TotalTime to be a timer at all.

Also, do you have a JavaScript setInterval running to count something from the timers? Ideally you shouldnt need this.

At this moment I m not sure if this is a plugin issue or not, but whatever it is, we ll fix it :)

@wgpalexander
Copy link
Author

Hi walmik - thanks for the prompt response.

In summary - I am looking to time a series of workout intervals, the sum of which is a total workout. I want to show the user

  1. the time ELAPSED in the specific interval;
  2. the TOTAL TIME that they have been working out for (e.g. could be several intervals)
  3. the total REMAINING time left in the workout (could be the sum of a number of intervals again)

Consider this example -

I want to do as many chin ups as I can in 3 minutes, then rest for 1 minute before another session of 3 minutes work. That is 3 intervals.

REMAINING would be set to 7 mins (3+1+3) and would count down to 4 mins over the first interval.
ELAPSED and through TOTAL TIME would simultaneously count up to 3 mins

After 3 minutes I have coded that the ELAPSED timer is removed & replaced with another ELAPSED timer with the new interval (all this works already so no worries here) and the next interval of 1 minute counts up without intervention.
TOTAL TIME continues to count seamlessly so will head towards 4 minutes
REMAINING continues to count down seamlessly so will head towards 3 minutes remaining (the final interval)

Again for the final interval the ELAPSED counter is removed & replaced with another 3 minute one which starts counting up immediately
TOTAL TIME will continue to count up seamlessly towards 7 minutes
REMAINING will continue to seamlessly count down to 0

While hopefully this background helps, the issue seems to be with the pause mechanics within the script. When I run my app without pausing all the timers count up/down as required and work perfectly. When I pause & then resume they seem to go out of sync.

I'm not using setInterval.

Thanks again!

@walmik
Copy link
Owner

walmik commented Aug 10, 2016

@wgpalexander

HI Wayne! I m sorry I couldnt look into this right away after writing to you as I got real busy at work! Anyway, could you please try something?

Please download the latest timer plugin and get hold of any jquery. Basically put these 2 files in a new folder. In the same folder create a new index.html and paste in the following contents. Once you do that, can you please use that as a playground and see if you are facing the same issue?

<!DOCTYPE html>
<html>
<head>
    <title>jQuery timer test</title>
    <style type="text/css">
        * {
            padding: 10px;
            margin: 5px;
            font-family: sans-serif;
        }
        input {
            font-size: 16px;
        }
    </style>
</head>
<body>
    <h1>jQuery timer test</h1>
    <div>
        <input type="text" name="elapsed" id="elapsed" placeholder="0 sec" />
        <input type="text" name="totalTime" id="totalTime"  placeholder="0 sec"  />
        <input type="text" name="remaining" id="remaining"  placeholder="10 sec"  />
    </div>
    <div>
        <button id="start">Start</button>
        <button id="pause">Pause</button>
        <button id="resume">Resume</button>
    </div>
    <script src="jquery.min.js"></script>
    <script src="timer.jquery.min.js"></script>
    <script type="text/javascript">
        (function() {
            var $elapsed = $('#elapsed');
            var $totalTime = $('#totalTime');
            var $remaining = $('#remaining');

            // Callback function that resets elapsed timer to 1 minute
            function resetElapsedTo1() {
                $elapsed.timer('remove');
                startElapsedTimer(60, resetElapsedTo3);
            }

            // Callback function that resets elapsed timer to 3 minutes
            function resetElapsedTo3() {
                $elapsed.timer('remove');
                startElapsedTimer(180);
            }

            // Generic function to start elapsed timer
            function startElapsedTimer(duration, callback) {
                $elapsed.timer({
                    duration: duration,
                    callback: callback || function() {}
                });
            }

            // Start all timers
            $('#start').on('click', function() {
                startElapsedTimer(180, resetElapsedTo1);
                $totalTime.timer({
                    duration: 420
                });
                $remaining.timer({
                    duration: 420,
                    countdown: true
                });
                $(this).attr('disabled', true); // to avoid accidentally clicking this instead of resume
            });

            // Pause all timers
            $('#pause').on('click', function() {
                $elapsed.timer('pause');
                $totalTime.timer('pause');
                $remaining.timer('pause');
            });

            // Resume all timers
            $('#resume').on('click', function() {
                $elapsed.timer('resume');
                $totalTime.timer('resume');
                $remaining.timer('resume');
            });
        })();
    </script>
</body>
</html>

Lemme know how it goes.

@wgpalexander
Copy link
Author

That script seems to work - I will see if I can somehow use it to amend my existing script & come back to you.

@wgpalexander
Copy link
Author

@walmik - firstly thanks for the continued help with this! As luck would have it I had some time tonight to look at the script. Your one above seems to work.

Unfortunately I still cannot get mine to work properly (I will continue to debug using your script when I can get another chance to look at it).

I have recreated my issue however in a simple html file so I can share it with you. This has the same issue I have in my main file - see below:

`

<title>jQuery timer test</title> <script type="text/javascript" src="jquery.mobile-1.4.5.min.js"></script> <script type="text/javascript" src="jquery-1.12.0.min.js"></script> <script type="text/javascript" src="timer.jquery.min.js"></script>
<h1>jQuery timer test</h1>

<div id="PhaseGearContent">Interval <div class ="timerdisplay" id="Elapsed">0 sec</div></div>
<div id="PassedGearContent">Elapsed <div class ="timerdisplay" id="TotalTime">0 sec</div></div>
<div id="LeftGearContent">Remaining <div class ="timerdisplay" id="Remaining"></div></div>

<br><br>

<div id="Go">Start</div>
<div id="Pause">Pause</div>

<script type="text/javascript">

    // Set up variables - in real script this is more complex
    var totalDurCount = '30s';
    var Duration      = [
                            '0',        // Item 0
                            '10',       // Item 1
                            '7',        // Item 2
                            '8',        // Item 3
                            '5'         // Item 4
                        ]; // End var Duration


    // Function to set up timer - function created as will need loads of callbacks
    // Used on workout page as will time each phase
    // May need to expand in future to include animation triggers etc.
    //
    // INPUT: duration = seconds duration for timer
    //
    function startTimer(duration, cbk) {

        // Load variable dur based on duration input
        var dur = duration;

        if(dur == 0)
        {
            // If the item has a nil duration need to make timer stop at 0
            // and then somehow callback to continue the function loops

            return cbk();
        }    
        else
        {
            // Set the duration for the timer using the input
            var d = "'" + duration + "s'";

            // Now need to start the timer
            // Use the jQuery timer plugin code

            $('#Elapsed').timer({

                seconds: 0,

                duration: d,

                callback: cbk

            }); // End Elapsed

        } // End if

    } // End startTimer


    // Hide pause button by default
    alert('Hello World');
    $('#Pause').hide();

    // When we click go...
    $('#Go').click(function() {

        $('#TotalTime').timer();

        $('#Remaining').timer({
            countdown: true,
            duration: totalDurCount
        });

        // Change buttons displayed
        $('#Go').hide();
        $('#Pause').show();

        // Get number of seconds in elapsed timer
        var e = $('#Elapsed').data('seconds');

        // If 'undefined' then set to 0
        if(!e) {e = 0;}

        // If number of seconds is nil then
        // start timer - else resume timer
        if(e == 0)
        {

            // Phase 1
            startTimer(Duration[1],
                function() {
                    $('#Elapsed').timer('remove');

            // Phase 2        
            startTimer(Duration[2],
                function() {
                    $('#Elapsed').timer('remove');

            // Phase 3
            startTimer(Duration[3],
                function() {
                    $('#Elapsed').timer('remove');

            // Phase 4
            startTimer(Duration[4],
                function() {

                // Series of finishing items
                $('#Pause').hide();
                $('#Elapsed').text('0 sec');
                $('#TotalTime').timer('pause');
                $('#Remaining').timer('pause');
                alert('Finished!');


            }); // End startTimer 4
            }); // End startTimer 3
            }); // End startTimer 2
            }); // End startTimer 1 

        }
        else
        {

            // Now need to resume the timers
            $('#Elapsed').timer('resume');
            $('#TotalTime').timer('resume');
            $('#Remaining').timer('resume');

        } // End if

    }); // End Go click

    // When we click pause
    $('#Pause').click(function() {

        // Now need to pause the timers
        $('#Elapsed').timer('pause');
        $('#TotalTime').timer('pause');
        $('#Remaining').timer('pause');     

        // Hide Pause and show Go option
        $('#Pause').hide();
        $('#Go').show();

    }); // End Pause click

</script>
`

I'm fairly new to JS and coding in general so go easy on my code ability :)

Think it might be something in the resume element of the "if"... But I could be wrong.

@walmik
Copy link
Owner

walmik commented Aug 12, 2016

Hi Wayne, I think I see the problem. The resume functionality is never reached in your code. The Remaining timer is always "started" as a result. Never resumed. You can test this by adding a console log at the point where you are attempting to resume the timer(s) and check if you are actually reaching there in your code.

I also feel you may need to really revisit some of this code, especially the cascading startTimers one inside the other. One minor thing I d like to point out is, if you are using all the values in seconds, you dont really need to specify a timing in seconds like this 10s. You can just set it as 10.

@wgpalexander
Copy link
Author

Hi walmik,

Thanks for the response again. I agree that the coding probably needs revised - I drafted it a while ago and was just looking to prove I could do a series of timers in a row one after the other. Out of interest, how would you execute the same task?

Pushing the lazy coding to one side, I added some alerts (in place of console logs) to the script and it does fire the pause/resume commands as far as I can tell. See below code.

Would you be able to copy into a new document and see if you get the same issue on your machine?

`

<title>jQuery timer test</title> <script type="text/javascript" src="jquery.mobile-1.4.5.min.js"></script> <script type="text/javascript" src="jquery-1.12.0.min.js"></script> <script type="text/javascript" src="timer.jquery.min.js"></script>
<h1>jQuery timer test</h1>

<div id="PhaseGearContent">Interval <div class ="timerdisplay" id="Elapsed">0 sec</div></div>
<div id="PassedGearContent">Elapsed <div class ="timerdisplay" id="TotalTime">0 sec</div></div>
<div id="LeftGearContent">Remaining <div class ="timerdisplay" id="Remaining"></div></div>

<br><br>

<div id="Go">Start</div>
<div id="Pause">Pause</div>

<script type="text/javascript">

    // Set up variables - in real script this is more complex
    var totalDurCount = '30s';
    var Duration      = [
                            '0',        // Item 0
                            '10',       // Item 1
                            '7',        // Item 2
                            '8',        // Item 3
                            '5'         // Item 4
                        ]; // End var Duration


    // Function to set up timer - function created as will need loads of callbacks
    // Used on workout page as will time each phase
    // May need to expand in future to include animation triggers etc.
    //
    // INPUT: duration = seconds duration for timer
    //
    function startTimer(duration, cbk) {

        // Load variable dur based on duration input
        var dur = duration;

        if(dur == 0)
        {
            // If the item has a nil duration need to make timer stop at 0
            // and then somehow callback to continue the function loops

            return cbk();
        }    
        else
        {
            // Set the duration for the timer using the input
            var d = "'" + duration + "s'";

            // Now need to start the timer
            // Use the jQuery timer plugin code

            $('#Elapsed').timer({

                seconds: 0,

                duration: d,

                callback: cbk

            }); // End Elapsed

        } // End if

    } // End startTimer


    // Hide pause button by default
    alert('Hello World');
    $('#Pause').hide();

    // When we click go...
    $('#Go').click(function() {

        $('#TotalTime').timer();

        $('#Remaining').timer({
            countdown: true,
            duration: totalDurCount
        });

        // Change buttons displayed
        $('#Go').hide();
        $('#Pause').show();

        // Get number of seconds in elapsed timer
        var e = $('#Elapsed').data('seconds');

        // If 'undefined' then set to 0
        if(!e) {e = 0;}

        // If number of seconds is nil then
        // start timer - else resume timer
        if(e == 0)
        {

            // Phase 1
            startTimer(Duration[1],
                function() {
                    $('#Elapsed').timer('remove');

            // Phase 2        
            startTimer(Duration[2],
                function() {
                    $('#Elapsed').timer('remove');

            // Phase 3
            startTimer(Duration[3],
                function() {
                    $('#Elapsed').timer('remove');

            // Phase 4
            startTimer(Duration[4],
                function() {

                // Series of finishing items
                $('#Pause').hide();
                $('#Elapsed').text('0 sec');
                $('#TotalTime').timer('pause');
                $('#Remaining').timer('pause');
                alert('Finished!');


            }); // End startTimer 4
            }); // End startTimer 3
            }); // End startTimer 2
            }); // End startTimer 1 

        }
        else
        {

            alert('Resumed!');

            // Now need to resume the timers
            $('#Elapsed').timer('resume');
            $('#TotalTime').timer('resume');
            $('#Remaining').timer('resume');

        } // End if

    }); // End Go click

    // When we click pause
    $('#Pause').click(function() {

        // Now need to pause the timers
        $('#Elapsed').timer('pause');
        $('#TotalTime').timer('pause');
        $('#Remaining').timer('pause');     

        // Hide Pause and show Go option
        $('#Pause').hide();
        $('#Go').show();

        alert('Paused!');

    }); // End Pause click

</script>
`

@wgpalexander
Copy link
Author

Walmik - I've played around with the script and got it working. I've simplified the start button to simply kick the timers off and added a separate resume button. This seems to have solved the issue - although I'm unclear why - but I'm happy regardless! Thanks for your help!

@walmik
Copy link
Owner

walmik commented Aug 14, 2016

@wgpalexander
That sounds great Wayne! One take away for me personally in this exercise, is to improve the timer such that even if start is triggered on a paused timer, then it acts as a resume. I ll look into that and any other issues related to resume in general by adding some tests.

I ll close this issue for now but do not hesitate to reach out again if you face more issues. If you want we can setup a Google hangout call and I can address/recommend any improvements that I can think of on your project. All free of charge of course. I m just glad you are using the timer plugin for your project and I want to support it :)

@walmik walmik closed this as completed Aug 14, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants