Usage
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).
Examples
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; });
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/modules/utilities.js on line 590.
No Hooks
This function does not have any filters or actions available. Request one?Note: This function contains 1 to-do comment.
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' ){ nebula.help('nebula.timer() requires a uniqueID.', '/functions/timer/'); 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' ){ nebula.help('nebula.timer() cannot lap or end a timing that has not started.', '/functions/timer/'); return false; } //Can not modify a timer once it has ended. if ( typeof nebula.timings[uniqueID] !== 'undefined' && nebula.timings[uniqueID].total > 0 ){ return nebula.timings[uniqueID].total; } //Update the timing data! let currentTime = performance.now(); if ( action === 'start' && typeof nebula.timings[uniqueID] === 'undefined' ){ nebula.timings[uniqueID] = { started: currentTime, cumulative: 0, total: 0, lap: [], laps: 0 }; let 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 { let 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' ){ let 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. Remember: Some functionality is conditionally loaded via dynamic imports, so if your function is not overriding properly, try listening for a DOM event (described below).
For non-module import functions:
nebula.timer = function(uniqueID, action, name){ //Write your own code here, leave it blank, or return false. }
For dynamically imported module function overrides:
jQuery(window).on('load', function(){ nebula.timer = function(uniqueID, action, name){ //Write your own code here, leave it blank, or return false. } });
Custom Nebula DOM events do also exist, so you could also try the following if the Window Load listener does not work:
jQuery(document).on('nebula_module_loaded', function(module){ //Note that the module variable is also available to know which module specifically was imported if ( typeof nebula.timer === 'function' ){ nebula.timer = function(uniqueID, action, name){ //Write your own code here, leave it blank, or return false. } } });