What does this solve?
GitHub only provides a few options to automatically clear one’s status in the future:
This can be annoying if for example, one wants to set a “busy” status for a couple weeks in a row, or even until a later day in the week.
The tool provided below replaces the limited options with a date and a time picker, which provide complete flexibility in how to set the date and time when that GitHub status will be cleared.
Going on a long weekend, and want to be marked away until your return on Tuesday morning, 9am? You can do so now!
How to use?
There are two ways to use this tool:
Userscript
What is a userscript?
According to Wikipedia’s page on Userscript:
A userscript (or user script) is a program, usually written in JavaScript, for modifying web pages to augment browsing.
You can run userscripts in your browser using a userscript manager, such as Violentmonkey.
Install
Add the userscript to your userscript manager. (For example, Violentmonkey will automatically come up when you click the link.)
Better GH status clear (userscript)
Use
Once installed and if enabled, the userscript will automatically fire up and change GitHub’s status modal when it pops up!
Bookmarklet
What is a bookmarklet?
According to Wikipedia’s page on Bookmarklet:
A bookmarklet is a bookmark stored in a web browser that contains JavaScript commands that add new features to the browser.
Install
You can install the bookmarklet by adding it to your browser’s bookmarks. The simplest way to do so is to drag’n’drop the button below to your bookmarks bar.
Better GH status clear (bookmarklet)
⬆️ Drag and drop the button above to your bookmarks!
Use
After opening the “Set status” modal window on GitHub, click on the bookmarklet in your browser to replace the date/time picker.
You can now select freely the date and time at which to clear your GitHub status!
Video
Source code
You can check the bookmarklet’s uncompressed source code below:
(() => {
class BetterGitHubStatusClear {
static DEBUG_MODE = false;
static get debug() {
if (this.DEBUG_MODE) {
return console.log.bind(window.console, "[BGHSC]");
} else {
return function() {};
};
};
static run() {
this.debug("Triggered.");
const select = this.getOriginalClearStatusSelect();
if (!select) {
this.debug('Could not find the "clear status" select on the page. Aborting...');
return;
};
if (select.classList.contains("bghsc")) {
this.debug('Job already done. Aborting...');
return;
};
select.classList.add("bghsc");
if (!this.DEBUG_MODE) {
select.parentElement.hidden = true;
} else {
this.debug('Not hiding the select\'s parent since DEBUG_MODE is on.');
};
var previousDateString = "";
var previousTimeString = "";
var previousDate = null;
if (select.value != " ") {
previousDate = new Date(select.value);
previousDate = new Date(
previousDate.getTime() - previousDate.getTimezoneOffset() * 60 * 1000
);
[previousDateString, previousTimeString] = previousDate.toISOString().split("T", 2);
previousTimeString = previousTimeString.split(":", 3).slice(0, 2).join(":");
};
this.debug("Current clear date/time: " + previousDate);
const html = `\
<div>
<input type="date" class="form-control" name="clear-date" value="${previousDateString}">
<input type="time" class="form-control" name="clear-time" value="${previousTimeString}">
</div>`;
select.parentElement.parentElement.insertAdjacentHTML("beforeend", html);
const that = this;
const updateSelect = function(e) {
that.debug("Updating select with new date...");
const container = select.parentElement.parentElement;
const dateString = container.querySelector("[name='clear-date']").value;
const timeString = container.querySelector("[name='clear-time']").value;
select.childNodes.forEach((option) => {
if (option?.text?.startsWith("Custom")) {
option.remove();
};
});
if (dateString == "") {
select.value = " ";
that.debug("Erased clear date.");
} else {
const dateTime = new Date(`${dateString} ${timeString}`).toISOString();
select.options.add(new Option(`Custom (${dateTime})`, dateTime, true, true));
select.value = dateTime;
that.debug(`Set clear date to ${dateTime}.`);
};
};
select.parentElement.parentElement.querySelector("[name='clear-date']").addEventListener("input", updateSelect);
select.parentElement.parentElement.querySelector("[name='clear-time']").addEventListener("input", updateSelect);
this.debug("Finished.");
};
static ensureContext() {
if (document.location.host !== "github.com") {
alert("This bookmarklet only works on GitHub.");
return false;
};
if (!this.getOriginalClearStatusSelect()) {
alert("Please open the 'Set status' modal first.");
return false;
};
return true;
};
static getOriginalClearStatusSelect() {
const xpath = "//div[contains(., 'Edit status')]//select[@id='expires_at']";
return document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;
};
}
if (!BetterGitHubStatusClear.ensureContext()) return;
BetterGitHubStatusClear.run();
})();