robcowie / jquery-stopwatch

A jQuery plugin that renders a count-up clock from a defined start time

Home Page:http://robcowie.github.com/jquery-stopwatch/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Question

chadcrowell opened this issue · comments

Hi Rob - love the stopwatch - its doing exactly what I need. Question. I am trying to do this:

$('.task-timer').live("click", function() {
    var task_id = $(this).attr('id');
    var task_time = $.jStorage.get('timer-'+task_id,'0');
    $('#task-'+task_id+' .task-time').stopwatch({
        startTime: task_time
    }).stopwatch('toggle');
});

The local storage line allows a default in case there is nothing stored in that location. The default, obviously is 0, so we're either getting the stored time or 0 and setting task_time to that. The problem is when I try to send task_time to stopwatch as its start time it shows me 00:00:00 and then NaN:NaN:NaN. I've tried 0 '0' and '00:00:00' as the default values. Any idea what it should be? Or, can I not send a var into startTime? Thanks Chad

HI Chad,

Currently, startTime expects an integer representing milliseconds. 0 should therefore work. I'm on a train right now so I can't easily test the code but I'll have a look later today.

If you have any ideas about a more useful way of providing a start time, feel free to let me know. I haven't actually used that particular feature; I just threw it in there as I was coding it.

As a follow up - I just tried sending 0 in again and it worked, but the timer started at 16:00:00. I think that happened last night but it was late... I notice that your demos on jsfiddle start at 16:00:00 - is that built into your plugin somehow? I see the init function has startTime as 0, so I don't know where its coming from. Weird! Thanks for the help.

It's a Date thing; Although the plugin uses elapsed milliseconds internally, the default formatter function creates a javascript Date() object using the current milliseconds and returns a string representation using Date methods (i.e. getHours()). I chose to do this as a convenient way of formatting the milliseconds.

Unfortunately, when creating a new Date() instance using milliseconds from the start of the epoch, it returns a Date based on the local timezone, so 0 only really means 0 in GMT. I'll replace the default formatter and ditch the use of Date().

For info, you can provide your own formatter function by passing it as formatter in an options array. It recieves the milliseconds and is expected to return a string.

Right, I've pushed a fix for the default formatting. Let me know if it works for you. Back to your original issue...

If I understand correctly, you want to store the elapsed time using jStorage in order to initialise the stopwatch correctly across sessions. The simplest way to do this (I think) is to store the elapsed milliseconds for a stopwatch by binding to the tick event, then simply retrieve it and pass it to the stopwatch. Your original code snippet would look something like:

$('.task-timer').live("click", function() {
    var task_id = $(this).attr('id');
    var timer_id = 'timer-' + task_id;
    var task_time = $.jStorage.get(timer_id, 0);

    $('#task-' + task_id + ' .task-time').stopwatch({
        startTime: task_time
    }).bind('tick.stopwatch', function(e, millis) {
        $.jStorage.set(timer_id, millis);
    }).stopwatch('toggle');    
});

I had thought about the GMT when I saw your location and the 16:00:00. Looks like I do have a counter starting at 0 now- thanks for the update. Will work on the localstorage connection now. I appreciate your promtness!

Hi Rob - everything is going well with my app- your help has been invaluable. Another question along these lines. First, here is the entire section of code that I ended up with based on your previous help. The timers are loading great with jstorage and starting from 0 with new timers:

$('.task-timer').live("click", function() {
    //create time for task date
    var currentTime = new Date();
    var month = currentTime.getMonth() + 1;
    var day = currentTime.getDate();
    var year = currentTime.getFullYear();
    var now = (month + "/" + day + "/" + year);
    var task_time_date = $.jStorage.get('date-'+task_id,now);

    //IDs and such
    var list_id = $(this).attr('rel');
    var task_id = $(this).attr('id');

    //Get stored task time or default of 0
    var task_time = $.jStorage.get('timer'+task_id,0);

    //Start and stop the timer
    $('#' + task_id + ' .task-time').stopwatch({
        startTime: task_time //this is stored time or 0
    }).bind('tick.stopwatch', function(e, millis) {
        $.jStorage.set('timer'+task_id, millis);
    }).stopwatch('toggle');

    //Toggle the class for emphasis
    $(this).parents('li').toggleClass('time-active');
});

So, I have a list of task lists and when I click one, it loads in the list of tasks to which we can add time using the above function. What I am trying to do is to retrieve and show saved time at the time the task list is loaded next to any tasks that have time recorded and saved via jstorage. I am almost there. Here is what I am using:

//loop all tasks and load in existing time for each
$('#workspace .task-list li').livequery(function() {
    var task_id = $(this).attr('id');
    //Get stored task time or default of 0
    var task_time = $.jStorage.get('timer'+task_id,0);
    if(task_time != 0) {
        $('#' + task_id + ' .task-time').stopwatch({
            startTime: task_time
        });
    }
});

So, using livequery, when new .task-list li's are loaded into the DOM, each one will get the following code applied. So, its grabbing the task ID from each li and checking jstorage for saved time under that ID. If there is stored time, we want to display the stored time in the task list, otherwise (0), do nothing. I have verified that we're checking for saved time correctly - via an alert I see 2 task ID's alerted in a list of 10, and they are the 2 where I've previously recorded time. So, I just need help on the stopwatch code that displays the stopwatch with the elapsed time (task_time) but with the timer stopped. The code above shows nothing. At one point I had the millisecond count showing by just displaying task_time, so i know I needed to pass that into stopwatch to format it correctly. Then at another time I had it showing up correctly, but the timer was running. I can't make that happen again so I don't know what that code was.

Thanks.

Hi Chad. Good to hear you are making progress with your app. For my own interest, are you able to explain what it is or link to a demo?

Without modifying the stopwatch implementation I think you can achieve what you need by calling .stopwatch('render', task_time) in your livequery handler...

$('#workspace .task-list li').livequery(function() {
    var task_id = $(this).attr('id');
    // Get stored task time or default of 0
    var task_time = $.jStorage.get('timer'+task_id,0);
    if (task_time != 0) {
        $('#' + task_id + ' .task-time').stopwatch({
            startTime: task_time
        }).stopwatch('render', task_time);
    }
});

Currently a call to render requires the milliseconds as the only argument. I don't like this as it allows the internal elapsed time and the displayed (rendered) elapsed time to differ, which is obviously not desirable.

I think I'll modify the render method to remove the required millisecond arg, though this will be a backward incompatible change:

.stopwatch('render', task_time)

will become

.stopwatch('render')

I think I can deal with that backwards incompatibility- small change for sure. I'd rather not disclose what it is here publicly but if you email me at chadcrowell / at / gmail / dot / com I'll show you what its all about. Thanks for your continued help!