A full clock utility library. Stopwatch, timer, alarm, audio & formatters — all in one file.
<!-- in your HTML head --> <link rel="stylesheet" href="cdn.jsdelivr.net/ .../clockify.css"> <!-- then use ck- classes --> <div class="ck-app"> <div class="ck-time"> 00:00.00 </div> <button class="ck-btn main"> start </button> </div>
// via CDN script tag <script src="cdn.jsdelivr.net/ .../index.js"></script> // then use window.Clockify const sw = Clockify.createStopwatch(); sw.onTick((ms, fmt) => { el.textContent = fmt; }); sw.start();
No dependencies. No bloat. Just a single JS file with clean, well-documented functions.
Start, pause, reset, lap. Accurate time tracking using real timestamps with fastest/slowest lap detection.
Countdown from any hours/minutes/seconds. Pause and resume with drift-free accuracy. onDone callback.
Set alarms by time and day of week. Persistent via localStorage. No duplicates. onRing callback.
Web Audio API beeps with no audio files required. Customisable frequency and duration. startRinging / stopRinging.
pad2(), fmtSW(), fmtTM() — clean time formatting helpers for any display use case.
Alarms auto-save to localStorage. Survive page refresh. Custom storage key support.
Drop it in and go. Works with npm, ES modules, or a plain script tag.
import { createStopwatch } from 'devclockify-js'; const sw = createStopwatch(); sw.onTick((ms, formatted) => { console.log(formatted); // "01:23.45" }); sw.onLap((lap, allLaps) => { console.log('Lap:', lap.formatted); }); sw.start(); sw.lap(); sw.pause(); sw.reset(); sw.getTime(); // "01:23.45" sw.getLaps(); // [{n:1, t:5430, formatted:"00:05.43"}] sw.isRunning(); // true / false
import { createTimer } from 'devclockify-js'; const timer = createTimer(); timer.set(0, 5, 30); // 0h 5m 30s timer.onTick((secondsLeft, formatted) => { console.log(formatted); // "05:28" }); timer.onDone(() => { console.log('Timer done!'); }); timer.start(); timer.pause(); timer.reset(); timer.getTime(); // "04:58" timer.getSecondsLeft(); // 298
import { createAlarmManager } from 'devclockify-js'; const manager = createAlarmManager(); manager.add('07:00', 'wake up', [1,2,3,4,5]); // Mon–Fri manager.add('09:00', 'weekend', [0,6]); // Sat & Sun manager.add('12:00', 'lunch'); // every day manager.onRing((alarm) => { console.log('Ringing:', alarm.label); setTimeout(() => manager.stopRing(), 10000); }); manager.start(); manager.getAll(); manager.toggle(alarmId); manager.delete(alarmId); manager.isRinging();
import { makeBeep, startRinging, stopRinging } from 'devclockify-js'; makeBeep(); // default 880Hz, 0.35s makeBeep(440, 0.5); // lower pitch, longer makeBeep(1200, 0.1); // high ping const ring = startRinging(); setTimeout(() => stopRinging(ring), 5000);
Every function, parameter and return value.
| method | description | returns |
|---|---|---|
| .start() | Start or resume the stopwatch | void |
| .pause() | Pause the stopwatch | void |
| .reset() | Reset everything to zero | void |
| .lap() | Record current lap split | lapObj | null |
| .getMs() | Get elapsed milliseconds | number |
| .getTime() | Get formatted time string | "MM:SS.cs" |
| .getLaps() | Get all recorded laps | array |
| .isRunning() | Check if running | boolean |
| .onTick(cb) | Callback every ~50ms | void |
| .onLap(cb) | Callback on lap recorded | void |
| method | description | returns |
|---|---|---|
| .set(h, m, s) | Set countdown duration | void |
| .start() | Start or resume countdown | void |
| .pause() | Pause the countdown | void |
| .reset() | Reset to last set duration | void |
| .getTime() | Get formatted time remaining | "MM:SS" |
| .getSecondsLeft() | Get seconds remaining | number |
| .isRunning() | Check if running | boolean |
| .onTick(cb) | Callback every ~200ms | void |
| .onDone(cb) | Callback when done | void |
| method | description | returns |
|---|---|---|
| .add(time, label, days) | Add a new alarm | alarm | null |
| .delete(id) | Remove an alarm by id | void |
| .toggle(id) | Toggle alarm on/off | void |
| .getAll() | Get all alarms | array |
| .getById(id) | Get single alarm | alarm | null |
| .clearAll() | Delete all alarms | void |
| .start() | Start the alarm checker | void |
| .stop() | Stop the alarm checker | void |
| .stopRing() | Stop currently ringing alarm | void |
| .isRinging() | Check if ringing | boolean |
| .onRing(cb) | Callback when alarm fires | void |
| .onStop(cb) | Callback when ring stops | void |
| .getDayNames(days) | Convert day numbers to names | string[] |
Understand the inner engine details of devclockify-js, lifecycle handling, state persistence, and styling mechanics.
devclockify-js balances drift-free accuracy with performance optimization. Instead of processing simple increments inside a standard setInterval (which natively suffers from runtime throttling and frame drifts), the system relies on physical system clock differences (delta time) calculated from instances of Date.now().
Modules invoke dynamic rendering loops through callbacks. It is recommended to mount and clear listeners within application component context rules to optimize rendering operations:
The Alarm Manager operates with persistent data binding layers:
localStorage objects fail configuration calls or strict cross-domain permission settings.Audio utilities use raw synthesizer nodes powered by the browser's native Web Audio API context, generating distinct oscillators without requiring static audio file paths.
Note: Modern browsers block sound patterns unless a deliberate interaction event (Click/Touch) from the viewport user explicitly triggers the process first.