Skip to content

Instantly share code, notes, and snippets.

@spiralx
Last active September 27, 2017 10:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spiralx/2bbd7b50363450484cfce6b0735295ca to your computer and use it in GitHub Desktop.
Save spiralx/2bbd7b50363450484cfce6b0735295ca to your computer and use it in GitHub Desktop.
Reddit - Remember RES user tag UserScript
// ==UserScript==
// @name Reddit - Remember RES tag action
// @description Saves previously set tag and colour to use again.
// @author James Skinner <spiralx@gmail.com> (http://github.com/spiralx)
// @namespace http://spiralx.org/
// @version 0.5.0
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiAAABYgAWToQQYAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuNWWFMmUAAAF3SURBVDhP1ZI/SAJhGMZN3WpKOAgsKGiIoKWg0K2LXIJWj6DAhpAgKMiW7irBqziHbhYE12sLGtWGKHBx0kHcQrBJXNIz9e35vvsQoj841g9+fHy8z/PyHZzrXzANNbgKF2ASHsOhOYGTUIb3cBSq4hyKa3Ey2GsMeMRvvzALd+AVvIPbcAb+yAq8hBehUOgxnU5TtVol27ap3W5TpVKhVCpFsiw/IHMusstwgOHxeDZM07T7/T5Rr0vUfacBvR7uHWIzwzBayK+zDm8KktFo9FXEifaXiHbnxAXEZKKtqcHSSCTygs6nBYuWZfEhR1eIzjbFBdzsYcma8xKQyWQInXmn6jCeSCQ6fDoEqqqyzxhzqgK/368Xi0UeKJfLpGka5fN5yuVyrEClUonPCoUCSZLE/oMvjGBwqut6q16vU6PRoGw2yxc0m02q1WoUj8fffD5fjGWdyvdMeL3ew2AweKsoynM4HH4KBAKW2+0+wExyIn8Hl+sDt5ENCrpr91QAAAAASUVORK5CYII=
// @icon64 data:image/png;base64,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
// @match *://*.reddit.com/r/*/comments/*
// @match *://*.reddit.com/user/*
// @grant GM_getValue
// @grant GM_setValue
// @run-at document-end
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.js
// @require https://greasyfork.org/scripts/10443-datacache-simple-storage-wrapper/code/DataCache%20-%20Simple%20storage%20wrapper.js?version=56961
// ==/UserScript==
/* jshint asi: true, esnext: true */
/* global jQuery, MutationSummary */
/**
### 0.5.0 (26.08.2017)
* Change to simple use of GM_getValue and GM_setValue for storage
### 0.4.0 (21.08.2017)
* Update all other tags correctly when changing a user's tag
* Handle removing all other tags when clearing a user's tag
### 0.3.0 (13.07.2017)
* Checks tag link to see if tag set, always overwrites if not
* Updates other tags for same user on current page
### 0.2.1 (27.06.2017)
* Changed timeout of field set function to 250ms
### 0.2.0 (31.05.2017)
* Updated jQuery to v3.2.1
* Added timeout before overriding tag/colour fields
* Update preview when setting tag/colour
*/
; ($ => {
'use strict'
const NORMAL = 'font-weight: normal; text-decoration: none; color: black'
const ERROR = 'font-weight: bold; color: #f4f'
const LINK = 'color: #05f; text-decoration: underline'
const BOLD = 'font-weight: bold'
const BLUE = [ 'color: #05f', 'color: #000' ]
const GREEN = [ 'color: #c1007f', 'color: #000' ]
const qval = (v, n) => `${n}=%c"${v}"%c`
// --------------------------------------------------------------------
const bgToTextColorMap = {
none: 'inherit',
aqua: 'black',
black: 'white',
blue: 'white',
cornflowerblue: 'white',
fuchsia: 'white',
gray: 'white',
green: 'white',
lime: 'black',
maroon: 'white',
navy: 'white',
olive: 'white',
orange: 'white',
orangered: 'white',
pink: 'black',
purple: 'white',
red: 'white',
silver: 'black',
teal: 'white',
white: 'black',
yellow: 'black'
}
// --------------------------------------------------------------------------
class Tag {
constructor(text = '', colour = 'none') {
this.text = text
this.colour = colour
}
get css() {
return {
backgroundColor: this.colour === 'none' ? 'transparent' : this.colour,
color: bgToTextColorMap[this.colour]
}
}
equals(other) {
return this.text === other.text && this.colour === other.colour
}
json() {
return JSON.stringify(this)
}
dump() {
console.log(`Tag(${qval(this.text, 'text')}, ${qval(this.colour, 'colour')})`, ...BLUE, ...BLUE)
}
}
Tag.parse = str => {
const { text, colour } = JSON.parse(str)
return new Tag(text, colour)
}
const previousTag = {
text: GM_getValue('tag', $('.pagename a').text()),
colour: GM_getValue('colour', 'olive')
}
// --------------------------------------------------------------------------
const tags = JSON.parse(localStorage.getItem('resrem') || '[]').map(v => new Tag(v.text, v.colour))
console.info(`onScriptInit: ${qval(previousTag.text, 'text')}, ${qval(previousTag.colour, 'colour')}`, ...BLUE, ...BLUE)
console.group(`tags(${qval(tags.length, 'length')})`, ...GREEN)
tags.forEach(t => t.dump())
console.groupEnd()
function getLastTag() {
return tags.length ? tags[0] : new Tag($('.pagename a').text(), 'olive')
}
function saveTag(tag) {
const idx = tags.findIndex(t => t.equals(tag))
if (idx !== -1) {
tags.splice(idx, 1)
}
tags.unshift(tag)
localStorage.setItem('resrem', JSON.stringify(tags))
return idx === -1
}
// console.info('Loaded "%s" and "%s"', previousTag.text, previousTag.colour)
// --------------------------------------------------------------------------
function onTagModalOpened() {
const $tagField = $('#userTaggerTag')
const $colourField = $('#userTaggerColor')
const $previewField = $('#userTaggerPreview')
const pt = getLastTag()
console.info(`onTagModalOpened: ${qval($tagField.val(), 'tag')}, ${qval($colourField.val(), 'colour')} (${qval(previousTag.text, 'oldTag')}, ${qval(previousTag.colour, 'oldCol')})`,
...GREEN, ...GREEN, ...BLUE, ...BLUE)
pt.dump()
console.dir(pt.css)
// console.info(`onTagModalOpened: tag="${$tagField.val()}", colour="${$colourField.val()}" (oldTag="${previousTag.text}", oldCol="${previousTag.colour}")`)
$tagField.val(previousTag.text)
$colourField.val(previousTag.colour)
$previewField
.css({
backgroundColor: previousTag.colour === 'none' ? 'transparent' : previousTag.colour,
color: bgToTextColorMap[previousTag.colour]
})
.text(previousTag.text)
}
// --------------------------------------------------------------------------
function onSaveTag() {
const text = $('#userTaggerTag').val()
const colour = $('#userTaggerColor').val()
const user = $('#userTaggerName').val()
if (text) {
previousTag.text = text
previousTag.colour = colour
const newTag = new Tag(text, colour)
saveTag(newTag)
console.info(`onSaveTag: ${qval(text, 'newText')}, ${qval(colour, 'newColour')}`, ...GREEN, ...GREEN)
newTag.dump()
console.info(tags)
// $(`a.userTagLink:not(.hasTag)[username=${user}]`)
$(`a.userTagLink[username=${user}]`)
.text(previousTag.text)
.css({
backgroundColor: previousTag.colour === 'none' ? 'transparent' : previousTag.colour,
color: bgToTextColorMap[previousTag.colour]
})
.addClass('hasTag')
.removeClass('RESUserTagImage')
} else {
previousTag.text = ''
previousTag.colour = 'none'
$(`a.userTagLink[username=${user}]`)
.text('')
.removeAttr('style')
.removeClass('hasTag')
.addClass('RESUserTagImage')
}
GM_setValue('tag', previousTag.text)
GM_setValue('colour', previousTag.colour)
}
// --------------------------------------------------------------------------
$('body')
.on('click.resrem', 'a.userTagLink:not(.hasTag)', () => {
setTimeout(onTagModalOpened, 250)
})
.on('click.resrem', '#userTaggerSave', onSaveTag)
})(jQuery)
jQuery.noConflict(true)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment