Skip to Content

timer()

Time actions (or groups of actions).

JavaScript July 2, 2019

Usage

JavaScript
nebula.timer(uniqueID, action, name)

Parameters

uniqueID
(Required) (String) A unique ID to identify this timer
Default: None

action
(Optional) (String) What action to be performed
Default: "start" or "stop" (See below)

name
(Optional) (String) The name of the action being timed
Default: false

Parameter Notes

action can be one of the following:

  • “start”: Begin timing (or if timer already running, trigger an “out lap”).
  • “lap”: Stop a previous timer and immediately start again.
  • “end”: End timing (it can not be modified once it has ended).

Request or provide clarification »

Examples

JavaScript
jQuery('.start-timer a').on('click touch tap', function(){
    nebula.timer('example', 'start');
    return false;
});

jQuery('.lap-timer a').on('click touch tap', function(){
    nebula.timer('example', 'lap');
    return false;
});

jQuery('.end-timer a').on('click touch tap', function(){
    nebula.timer('example', 'end');
    return false;
});

Demo


Example

Open the JavaScript console to see the data for this example.

Start Timer

New Lap

End

Additional Notes

This function stores timing data using performance.now() in a window nebulaTimings object- this object is organized by uniqueID.

Each uniqueID contains an object of data including:

  • started: When the timer was started
  • cumulative: The total time of all laps
  • total: The total time of current and previous laps.
  • lap: An object of lap data including:
    • name: The name of the lap
    • out: Whether this an out lap (an inactive time between two “hot” laps).
    • started: The time this lap was started
    • stopped: The time this lap was stopped
    • duration: How long this lap took
    • progress: The total time from when all timings started until the end of this lap.

For further clarification, an “out” lap is an inactive lap that is between two “hot” laps. This can happen when the user does some other action in between two timed actions. An out lap is triggered when a second (or more) “start” action is used- when this happens, the previous lap is labeled an “out” lap.

This function also adds performance.mark() for each individual item and performance.measure() for each uniqueID. This data can be accessed using the User Timing API with functions such as performance.getEntries() or performance.getEntriesByType.

Source File

Located in /assets/js/nebula.js on line 4083.

Note: This function contains 2 to-do comments.

JavaScript
nebula.timer = function(uniqueID, action, name){
    if ( !window.performance ){ //Safari 11+
        return false;
    }

    if ( typeof nebula.timings === 'undefined' ){
        nebula.timings = [];
    }

    //uniqueID is required
    if ( !uniqueID || uniqueID === 'start' || uniqueID === 'lap' || uniqueID === 'end' ){
        return false;
    }

    if ( !action ){
        if ( typeof nebula.timings[uniqueID] === 'undefined' ){
            action = 'start';
        } else {
            action = 'lap';
        }
    }

    //Can not lap or end a timing that has not started.
    if ( action !== 'start' && typeof nebula.timings[uniqueID] === 'undefined' ){
        return false;
    }

    //Can not modify a timer once it has ended.
    if ( typeof nebula.timings[uniqueID] !== 'undefined' && nebula.timings[uniqueID].total > 0 ){ //@todo "Nebula" 0: Use optional chaining
        return nebula.timings[uniqueID].total;
    }

    //Update the timing data!
    var currentTime = performance.now();

    if ( action === 'start' && typeof nebula.timings[uniqueID] === 'undefined' ){
        nebula.timings[uniqueID] = {};
        nebula.timings[uniqueID].started = currentTime;
        nebula.timings[uniqueID].cumulative = 0;
        nebula.timings[uniqueID].total = 0;
        nebula.timings[uniqueID].lap = [];
        nebula.timings[uniqueID].laps = 0;

        var thisLap = {
            name: false,
            started: currentTime,
            stopped: 0,
            duration: 0,
            progress: 0,
        };
        nebula.timings[uniqueID].lap.push(thisLap);

        if ( typeof name !== 'undefined' ){
            nebula.timings[uniqueID].lap[0].name = name;
        }

        //Add the time to User Timing API (if supported)
        if ( typeof performance.measure !== 'undefined' ){
            performance.mark(uniqueID + ' [Start]');
        }
    } else {
        var lapNumber = nebula.timings[uniqueID].lap.length;

        //Finalize the times for the previous lap
        nebula.timings[uniqueID].lap[lapNumber-1].stopped = currentTime;
        nebula.timings[uniqueID].lap[lapNumber-1].duration = currentTime-nebula.timings[uniqueID].lap[lapNumber-1].started;
        nebula.timings[uniqueID].lap[lapNumber-1].progress = currentTime-nebula.timings[uniqueID].started;
        nebula.timings[uniqueID].cumulative = currentTime-nebula.timings[uniqueID].started;

        //An "out" lap means the timing for this lap may not be associated directly with the action (Usually resetting for the next actual timed lap).
        if ( action === 'start' ){
            nebula.timings[uniqueID].lap[lapNumber-1].out = true; //If another 'start' was sent, then the previous lap was an out lap
        } else {
            nebula.timings[uniqueID].lap[lapNumber-1].out = false;
        }

        //Prepare the current lap
        if ( action !== 'end' ){
            nebula.timings[uniqueID].laps++;
            if ( lapNumber > 0 ){
                nebula.timings[uniqueID].lap[lapNumber] = {};
                nebula.timings[uniqueID].lap[lapNumber].started = nebula.timings[uniqueID].lap[lapNumber-1].stopped;
            }

            if ( typeof name !== 'undefined' ){
                nebula.timings[uniqueID].lap[lapNumber].name = name;
            }

            //Add the time to User Timing API (if supported)
            if ( typeof performance.measure !== 'undefined' ){
                var lapID = name || lapNumber;
                performance.mark(uniqueID + ' [Lap ' + lapID + ']');
            }
        }

        //Return individual lap times unless 'end' is passed- then return total duration. Note: 'end' can not be updated more than once per uniqueID! Subsequent calls will return the total duration from first call.
        if ( action === 'end' ){
            //Add the time to User Timing API (if supported)
            if ( typeof performance.measure !== 'undefined' ){
                performance.mark(uniqueID + ' [End]');

                if ( performance.getEntriesByName(uniqueID + ' [Start]', 'mark') ){ //Make sure the start mark exists
                    performance.measure(uniqueID, uniqueID + ' [Start]', uniqueID + ' [End]');
                }
            }

            nebula.timings[uniqueID].stopped = currentTime;
            nebula.timings[uniqueID].total = currentTime-nebula.timings[uniqueID].started;
            //@todo "Nebula" 0: Add all hot laps together (any non-"out" laps)
            return nebula.timings[uniqueID].total;
        } else {
            if ( !nebula.timings[uniqueID].lap[lapNumber-1].out ){
                return nebula.timings[uniqueID].lap[lapNumber-1].duration;
            }
        }
    }
};

Override

To override or disable this JavaScript function, simply redeclare it with the exact same function name.

JavaScript
nebula.timer = function(uniqueID, action, name){
    //Write your own code here, leave it blank, or return false.
}