Last active
September 29, 2018 16:35
-
-
Save zmasek/fb4af125f837feddac83eb6bafa5c689 to your computer and use it in GitHub Desktop.
Colorize favorite Reddit subs on homepage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Reddit favorites coloring | |
// @version 1 | |
// @description Color favorite sub threads on homepage | |
// @include /^https?://www\.reddit\.com/.*$/ | |
// @run-at document-end | |
// @author Zlatko Masek | |
// @grant none | |
// ==/UserScript== | |
const FAVORITES = new Set(); | |
const ALPHA = '0.2'; | |
const HEX_LENGTH = 6; | |
const convertStringToArrayBuffer = (str) => { | |
let bytes = new Uint8Array(str.length); | |
for (let iii = 0; iii < str.length; iii++) { | |
bytes[iii] = str.charCodeAt(iii); | |
} | |
return bytes; | |
} | |
const convertArrayBufferToHexaDecimal = (buffer) => { | |
let data_view = new DataView(buffer); | |
let iii, len, hex = '', | |
c; | |
for (iii = 0, len = data_view.byteLength; iii < len; iii += 1) { | |
c = data_view.getUint8(iii).toString(16); | |
if (c.length < 2) { | |
c = '0' + c; | |
} | |
hex += c; | |
} | |
return hex; | |
} | |
const hexToRgbA = (hex) => { | |
if (hex.length === 3) { | |
hex = [hex[0], hex[0], hex[1], hex[1], hex[2], hex[2]]; | |
} else { | |
hex = hex.split(''); | |
} | |
hex = `0x${hex.join('')}`; | |
return `rgba(${[(hex >> 16) & 255, (hex >> 8) & 255, hex & 255, ALPHA].join(', ')})`; | |
} | |
const colorize = () => { | |
for (const favorite of FAVORITES) { | |
const favoriteElements = document.querySelectorAll(`a[href="${favorite}"]`); | |
const promise = window.crypto.subtle.digest({ | |
name: 'SHA-1' | |
}, convertStringToArrayBuffer(favorite)); | |
promise.then((result) => { | |
const hex = convertArrayBufferToHexaDecimal(result).substring(0, HEX_LENGTH); | |
for (const element of favoriteElements) { | |
const el = element.parentElement.parentElement.parentElement.parentElement; | |
if (el.hasAttribute('class')) { | |
el.style['background-color'] = hexToRgbA(hex); | |
} | |
} | |
}); | |
} | |
} | |
const removeColor = (favorite) => { | |
const favoriteElements = document.querySelectorAll(`a[href="${favorite}"]`); | |
for (const element of favoriteElements) { | |
const el = element.parentElement.parentElement.parentElement.parentElement; | |
if (el.hasAttribute('class') && el.hasAttribute('style')) { | |
el.removeAttribute('style'); | |
} | |
} | |
} | |
const updateFavorites = () => { | |
const favoriteElements = document.querySelectorAll('[id^="focus-fav"]'); | |
for (const element of favoriteElements) { | |
FAVORITES.add(element.getAttribute('href')); | |
} | |
colorize(); | |
} | |
const init = () => { | |
const findLink = () => { | |
const linkNode = document.querySelector('[id^="focus-fav"]'); | |
if (linkNode) { | |
clearInterval(intervalFind); | |
updateFavorites(); | |
const hamburgerNode = linkNode.parentNode; | |
const hamburgerCallback = (mutationsList) => { | |
for (const mutation of mutationsList) { | |
if (mutation.addedNodes[0] !== undefined) { | |
if (mutation.addedNodes[0].nodeName === 'A' && mutation.addedNodes[0].id.startsWith("focus-fav")) { | |
updateFavorites(); | |
} | |
} | |
if (mutation.removedNodes[0] !== undefined) { | |
if (mutation.removedNodes[0].nodeName === 'A' && mutation.removedNodes[0].id.startsWith("focus-fav")) { | |
FAVORITES.delete(mutation.removedNodes[0].getAttribute('href')); | |
removeColor(mutation.removedNodes[0].getAttribute('href')); | |
} | |
} | |
} | |
} | |
const hamburgerObserver = new MutationObserver(hamburgerCallback); | |
hamburgerObserver.observe(hamburgerNode, { | |
childList: true, | |
subtree: true | |
}); | |
const listCallback = (mutationsList) => { | |
if (FAVORITES.size) { | |
colorize(); | |
} | |
} | |
const listNode = document.querySelector('div[data-redditstyle]').nextSibling; | |
const listObserver = new MutationObserver(listCallback); | |
listObserver.observe(listNode, { | |
childList: true, | |
subtree: true | |
}); | |
} | |
} | |
const intervalFind = setInterval(findLink, 1000); | |
} | |
init(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment