Search code examples
javascriptractivejs

Make stopwatch alive between request


I am new to Ractive.js. I need to implement a stop watch which will be running even if I click for another page. My stopwatch is running but when I click to another page and then come back to my current page, the stopwatch is gone. What can I try next?

Here are my attempts below.

In my view:

<div class="modal-footer">
        <div class="form-group">
            <div class="pull-left">
                Stopwatch: {{#stopWatch}} {{hours}} h: {{minutes}} m: {{seconds}} s{{/stopWatch}}
            </div>
            <button id="btnStart" class="btn btn-primary" type="button" on-click="startStopWatch">Start</button>
            <button id="btnReset" class="btn btn-secondary" type="button" on-click="startStopWatch">Reset</button>
        </div>
        <label class="pull-left stopWatch">  Time Spent:</label>
    </div>

My startStopWatch function:

function startStopWatch(ev, cfg) {
    var rjs = this || cfg.rjs;
    var $btn = $(ev.node);
    var btnText = $btn.text();
    var sg;

    if (btnText === 'Start') {
        $btn.html('Stop');
        sg = new cmnDt.stopWatch();
        sg.start(rjs, sg);
    } else if (btnText === 'Stop'){
        $btn.html('Start');
        sg = ev.context.sw;
        sg.stop(rjs, sg);
    }

    if (btnText === 'Reset' && ev.context.sw) {
        sg = ev.context.sw;
        sg.reset(rjs, sg);
        $('#btnStart').html('Start');
    }
}

My stopWatch function:

function stopWatch() {

        var currentSeconds = 0;
        var currentMinutes = 0;
        var currentHours = 0;
        var timer;

        function start(rjs, sw) {
            printTime(rjs, sw);
            timer = setInterval(function () {
                getTime();
                printTime(rjs, sw);
            }, 1000);
        }

        function getTime(rjs) {
            currentSeconds = currentSeconds + 1;
            if (currentSeconds === 60) {
                currentMinutes += Math.round((currentSeconds) / 60);
                currentSeconds = 0;
            } else if (currentSeconds === 60 && currentMinutes === 60) {
                currentMinutes = 0;
                currentSeconds = 0;
                currentHours += 1;
            }
        }

        function printTime(rjs, sw) { 
            rjs.set({'sw': sw, 'stopWatch.seconds': currentSeconds, 
                    'stopWatch.minutes': currentMinutes, 'stopWatch.hours': currentHours});
        }

        function stop(rjs, sw) {
            clearInterval(timer);
            printTime(rjs, sw);
            $('.stopWatch').text(' Time Spent: ' + currentMinutes + ' m : ' + currentSeconds + ' s.');
        }

        function reset(rjs, sw) {
            clearInterval(timer);
            currentSeconds = 0;
            currentMinutes = 0;
            currentHours = 0;
            printTime(rjs, sw);
        }

        return {
            start: start,
            stop: stop,
            reset: reset
        };
    }

Solution

  • If you change the site and come back, your whole script is initialized from start. You need to store the current value of the stop watch, and the timestamp of the current value, permanently.

    For this there are two options: local storage and cookies.

    In ractive, here is an example how local storage is meant to be used: http://examples.ractivejs.org/todos

    if you implement, say, one function saveToStorage() and one initFromStorage(), then your stopwatch may show the true time if you come back to the site. But be aware that the stop watch is not "running in some background". It is just initializing from the last moment stored. This is vital because for instance your stop watch cannot trigger events while you are on another site.


    Edit 15.3.16

    Find here a working stop watch in the fiddle:

    https://jsfiddle.net/cw67L17e/2/

    I started altering your code, but I thought then it is best to design from start. I have no time to dig into the specialities of ractivejs. But I do hope you can learn some new and useful ideas by studying it. A short hint how to use is in the fiddle at the right.

    Remarks:

    • Just for measuring time, you don't need a "stop watch" in the narrow sense. As you will see, it is sufficient to store time stamps. You actually need only the prepareToLeave() and resume() methods.
    • I suggest don't handle seconds, minutes and hours as combined type. Just handle timestamps and convert them whenever necessary, as shown in millisToHMS(). Because handling millis is a generic approach that will allow many other tasks too.
    • Consider the localStorage.setItem() and localStorage.getItem().
    • If you want to automatize, you could call resume() as soon as the document is ready, or loaded (document.ondomcontentready). There you have to find your ractivejs way.