Skip to content

Instantly share code, notes, and snippets.

@double-beep
Last active October 28, 2021 16:24
Show Gist options
  • Save double-beep/7dce3a02154bda4d81e6d514645307d1 to your computer and use it in GitHub Desktop.
Save double-beep/7dce3a02154bda4d81e6d514645307d1 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name StackFocus
// @namespace https://github.com/SpectricSO/stack-scripts
// @version 1.0.0+21AF26D3—-117B344092BD
// @author SpectricSO
// @contributor double-beep
// @match https://stackoverflow.com/*
// @resource Clear https://cdn.sstatic.net/Img/stacks-icons/Clear.svg
// @license MIT
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_getResourceText
// ==/UserScript==
/* globals Stacks */
(function () {
'use strict';
const configurationCacheKey = 'preferences';
const getConfiguration = () => GM_getValue(configurationCacheKey);
const defaultConfiguration = { // true => show, false => hide
findajob: true,
teamsadvert: true,
oblock: true,
linked: true,
related: true,
hotnetworkq: true
};
if (!getConfiguration()) GM_setValue(configurationCacheKey, defaultConfiguration); // first install, set the defaults for the user
/*function addRobotoFont(){
const roboto = document.createElement('link');
roboto.rel = 'stylesheet';
roboto.href = 'https://fonts.googleapis.com/css?family=Roboto&display=swap';
document.head.appendChild(roboto);
}*/
function calibrate() {
const configuration = getConfiguration();
// because the elements sometimes may not exist, checking if they do will add some more lines of code, thus making it harder to read
// instead, we change the style of a fake element which always exists
const fake = document.createElement('fake');
// Find a job module
(document.querySelectorAll('li .fs-fine')[1] || fake).style.display = configuration.findajob ? 'block' : 'none';
[...document.querySelectorAll('#nav-jobs, #nav-companies')].forEach(element => (element || fake).style.display = configuration.findajob ? 'block' : 'none');
(document.querySelectorAll('.nav-links')[2] || fake).style.display = configuration.teamsadvert ? 'block' : 'none'; // SO Teams ad below sidebar
(document.querySelector('.s-sidebarwidget[data-tracker="cb=1"]') || fake).style.display = configuration.oblock ? 'block' : 'none';
(document.querySelector('.sidebar-linked') || fake).style.display = configuration.linked ? 'block' : 'none'; // linked questions
(document.querySelector('.sidebar-related') || fake).style.display = configuration.related ? 'block' : 'none'; // related questions
(document.querySelector('#hot-network-questions') || fake).style.display = configuration.hotnetworkq ? 'block' : 'none'; // hot network questions
}
function createCheckbox(labelText, configurationProperty) {
const shouldCheck = getConfiguration()[configurationProperty];
return `
<div class="grid gs4">
<div class="grid--cell">
<input class="s-checkbox" type="checkbox" name="stack-focus-config-options" id="stack-focus-${configurationProperty}-option"
data-property="${configurationProperty}"${shouldCheck ? ' checked' : ''}/>
</div>
<label class="grid--cell s-label fw-normal" for="stack-focus-${configurationProperty}-option">Show the ${labelText}</label>
</div>`;
}
function getAllCheckboxes() {
return [
createCheckbox('find a job module', 'findajob'),
createCheckbox('Teams ad below the left sidebar', 'teamsadvert'),
createCheckbox('Overflow Blog, Featured on Meta and Hot Meta Posts', 'oblock'),
createCheckbox('linked questions', 'linked'),
createCheckbox('related questions', 'related'),
createCheckbox('hot network questions', 'hotnetworkq')
].join('\n');
}
function logic() {
const configurationModalHtml = `
<aside class="s-modal" id="stack-focus-modal" role="dialog" aria-labelledby="stack-focus-modal-title" aria-describedby="stack-focus-modal-body"
role="dialog" aria-hidden="true" data-controller="s-modal" data-target="s-modal.modal">
<div class="s-modal--dialog ps-relative" data-controller="se-draggable" role="document">
<h1 class="s-modal--header fw-bold c-move" id="stack-focus-modal-title" data-target="se-draggable.handle">Stack Focus configuration</h1>
<div class="s-modal--body fs-body2" id="stack-focus-modal-body">${getAllCheckboxes()}</div>
<div class="grid gs8 gsx s-modal--footer">
<button class="grid--cell s-btn s-btn__primary" type="button" data-action="s-modal#hide">I'm done!</button>
</div>
<button class="s-modal--close s-btn s-btn__muted" href="#" aria-label="Close" data-action="s-modal#hide">${GM_getResourceText('Clear')}</button>
</div>
</aside>`;
document.body.insertAdjacentHTML('beforeend', configurationModalHtml);
// listener to update the configuration on change
document.querySelectorAll('input[name="stack-focus-config-options"]').forEach(element => {
element.addEventListener('change', event => {
const isChecked = event.target.checked;
const configurationProperty = event.target.getAttribute('data-property');
const configuration = getConfiguration();
if (!configuration || !configurationProperty) return; // something went wrong apparently
configuration[configurationProperty] = isChecked;
GM_setValue(configurationCacheKey, configuration);
calibrate();
});
});
$(document).on('keyup', event => {
// open on Ctrl + Q (81 is Q)
if (event.keyCode === 81 && event.ctrlKey) Stacks.showModal(document.querySelector('#stack-focus-modal'));
});
}
//addRobotoFont();
calibrate();
logic();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment