Skip to content

Instantly share code, notes, and snippets.

@tuanchauict
Last active May 10, 2023 05:21
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save tuanchauict/7c7ee9edd642cf49ca8685996ca099f0 to your computer and use it in GitHub Desktop.
Save tuanchauict/7c7ee9edd642cf49ca8685996ca099f0 to your computer and use it in GitHub Desktop.
Attach a stopwatch to Leetcode

This script attaches a stopwatch into the toolbar of Leetcode's problem page.

The feature is simple:

  • Start/Stop the stopwatch
  • Auto start after 2 mins remaining on the problem
  • Restore unstopped stopwatch for the next visit on the problem

Use this script with any browser extension allowing attaching JS to the page. (I use User JavaScript and CSS)

Happy Leetcoding!

function attachStopWatch() {
if (document.getElementById("stopwatch")) {
// Already attached
return;
}
const container = document.getElementsByClassName("css-1lexzqe-TabHeaderContainer e5i1odf2");
if (container.length > 0) {
container[0].appendChild(createStopWatchElement());
}
}
function createStopWatchElement() {
const root = document.createElement("div");
root.className = "css-1lelwtv-TabHeader e5i1odf4 stopwatch--root";
root.id = "stopwatch";
root.innerHTML = '<div class="css-1uwsqgo-TabHeaderRow e5i1odf3"><div class="tab-header__20aW"><span class="stopwatch--label"></span>&nbsp;&nbsp;<span class="stopwatch--clock"></span></div></div>';
const stateNode = root.getElementsByClassName("stopwatch--label")[0];
const clockNode = root.getElementsByClassName("stopwatch--clock")[0];
const startCounting = function (startTimeMillis) {
if (root.intervalId) {
return;
}
localStorage.setItem(getStorageKey(), startTimeMillis);
root.intervalId = setInterval(clockTick, 500, clockNode, startTimeMillis);
stateNode.innerText = "Stop";
clockNode.innerText = toTimeString(getCurrentTimeInMillis() - startTimeMillis);
}
const stopCounting = function () {
clearInterval(root.intervalId);
root.intervalId = null;
localStorage.removeItem(getStorageKey());
stateNode.innerText = "Start";
}
const previousRunTime = localStorage.getItem(getStorageKey());
if (previousRunTime) {
startCounting(parseInt(previousRunTime));
} else {
stateNode.innerText = "Start";
clockNode.innerText = "00:00:00";
}
root.onclick = function () {
if (root.intervalId) {
stopCounting();
} else {
startCounting(getCurrentTimeInMillis());
}
}
const ONE_MIN = 60*1000;
setTimeout(function() {startCounting(getCurrentTimeInMillis() - ONE_MIN)}, 2*ONE_MIN);
return root;
}
function getStorageKey() {
const path = location.pathname;
const arr = path.split('/');
return "stopwatch_" + arr[2];
}
function clockTick(clockNode, startTime) {
const diff = getCurrentTimeInMillis() - startTime;
clockNode.innerText = toTimeString(diff);
}
function getCurrentTimeInMillis() {
return new Date().getTime();
}
function toTimeString(time) {
const hours = Math.floor(time / (1000 * 60 * 60));
const minutes = Math.floor((time % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((time % (1000 * 60)) / 1000);
return pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2);
}
function pad(num, size) {
var s = "000000000" + num;
return s.substr(s.length - size);
}
setInterval(attachStopWatch, 1000);
@tuanchauict
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment