Reddit - Quick user tagging

When tagging a new user the tag field defaults to the most recently used tag

目前為 2022-07-01 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Reddit - Quick user tagging
  3. // @description When tagging a new user the tag field defaults to the most recently used tag
  4. // @author James Skinner <spiralx@gmail.com> (http://github.com/spiralx)
  5. // @namespace http://spiralx.org/
  6. // @version 2.1.2
  7. // @license MIT
  8. // @icon data:image/png;base64,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
  9. // @supportURL https://greasyfork.org/en/scripts/370256-reddit-quick-user-tagging/feedback
  10. // @match *://*.reddit.com/r/*
  11. // @match *://*.reddit.com/user/*
  12. // @grant none
  13. // @run-at document-end
  14. // @require https://unpkg.com/jquery@3/dist/jquery.min.js
  15. // @require https://greasyfork.org/scripts/389748-console-message-v2/code/console-message-v2.js?version=730537
  16. // ==/UserScript==
  17.  
  18. /* jshint asi: true, esnext: true, laxbreak: true */
  19. /* global jQuery, message, Watcher */
  20.  
  21. /**
  22.  
  23. ==== 2.1.2 (2022.07.01) ====
  24. * Update icon and add license and supportURL metadata fields
  25.  
  26. ==== 2.1.1 (2022.04.16) ====
  27. * Clicking 'Clear tag' closes tag popup
  28.  
  29. ==== 2.1.0 (2021.11.05) ====
  30. * Fix when ConsoleMessage not available
  31.  
  32. ==== 2.0.5 (2021.06.08) ====
  33. * Update icons
  34.  
  35. ==== 2.0.4 (2021.06.02) ====
  36. * Set width of tag dialog to 800px
  37.  
  38. ==== 2.0.0 (2019.09.03) ====
  39. * Rename script and update version to 2.0.0
  40.  
  41. ==== 1.0.0 (2018.10.09) ====
  42. * Rewrite code base
  43. * Set previous tag on preset tag clicked
  44.  
  45. ==== 0.9.0 (2018.10.09) ====
  46. * Made tag modal wider and text smaller to accomodate more preset tags
  47. * Added clear tag link to the right of the colour drop-down
  48.  
  49. ==== 0.8.0 (2018.07.13) ====
  50. * Changed console.message require to use GreasyFork
  51.  
  52. ==== 0.7.0 (2018.02.13) ====
  53. * Changed the rendering of the tag preview to match how RES does it
  54. * Moved output to all use console.message
  55.  
  56. ==== 0.6.0 (2018.02.11) ====
  57. * Use unpkg.com for jQuery
  58. * Add console.message for logging
  59. * Use localstorage to save tags
  60. * Use new Tag class to store tag info
  61. * Updated ID for text field in tag popup
  62.  
  63. ==== 0.5.1 (2018.02.11) ====
  64. * Update icons to match other Reddit script
  65.  
  66. ==== 0.5.0 (26.08.2017) ====
  67. * Change to simple use of GM_getValue and GM_setValue for storage
  68.  
  69. ==== 0.4.0 (21.08.2017) ====
  70. * Update all other tags correctly when changing a user's tag
  71. * Handle removing all other tags when clearing a user's tag
  72.  
  73. ==== 0.3.0 (13.07.2017) ====
  74.  
  75. * Checks tag link to see if tag set, always overwrites if not
  76. * Updates other tags for same user on current page
  77.  
  78. ==== 0.2.1 (27.06.2017) ====
  79. * Changed timeout of field set function to 250ms
  80.  
  81. ==== 0.2.0 (31.05.2017) ====
  82. * Updated jQuery to v3.2.1
  83. * Added timeout before overriding tag/colour fields
  84. * Update preview when setting tag/colour
  85.  
  86. */
  87.  
  88. ; (($, Watcher, message) => {
  89.  
  90. const STYLES = {
  91. func: { color: '#c41', 'font-weight': 'bold' },
  92. attr: { color: '#1a2', 'font-weight': 'bold' },
  93. value: { color: '#05f' },
  94. punc: { 'font-weight': 'bold' },
  95. // comment: { color: 'c1007f' },
  96. // error: { color: '#f4f', 'font-weight': 'bold' },
  97. // link: { color: '#05f', 'text-decoration': 'underline' },
  98. }
  99.  
  100. // --------------------------------------------------------------------------
  101.  
  102. /*console.dir(console)
  103. console.dir(window)
  104. console.dir(message)
  105. console.dir(message())*/
  106.  
  107. if (message) {
  108. message().extend({
  109. tag({ text, colour }) {
  110. return this.text(text, {
  111. fontSize: '0.9em',
  112. padding: '0 4px',
  113. border: 'solid 1px rgb(199, 199, 199)',
  114. borderRadius: 3,
  115. ...getStyleForColour(colour)
  116. })
  117. }
  118. })
  119. }
  120.  
  121. // --------------------------------------------------------------------------
  122. // Woooooo
  123. // --------------------------------------------------------------------------
  124.  
  125. const TAG_STORAGE_KEY = 'resPreviousUserTag'
  126.  
  127. /*
  128. const OLD_TAGS_STORAGE_KEY = 'resrem'
  129.  
  130. try {
  131. if (!localStorage[ TAG_STORAGE_KEY ] && localStorage[ OLD_TAGS_STORAGE_KEY ]) {
  132. const tag = JSON.parse(localStorage[ OLD_TAGS_STORAGE_KEY ]).shift()
  133.  
  134. if (tag) {
  135. localStorage[ TAG_STORAGE_KEY ] = JSON.stringify(tag)
  136. }
  137. }
  138. } catch (ex) {
  139. console.warn(ex)
  140. }
  141. */
  142.  
  143. // --------------------------------------------------------------------------
  144.  
  145. const TAG_DIALOG_OPEN_TIMEOUT = 200
  146.  
  147. const BACKGROUND_TO_TEXT_COLOUR_MAP = {
  148. none: 'inherit',
  149. aqua: 'black',
  150. lime: 'black',
  151. pink: 'black',
  152. silver: 'black',
  153. white: 'black',
  154. yellow: 'black'
  155. }
  156.  
  157. // --------------------------------------------------------------------
  158.  
  159. const CLEAR_TAG_LINK = `
  160. <a href="javascript:void(0)"
  161. title="Clear tag">
  162. clear tag
  163. </a>
  164. `
  165.  
  166. const NO_PREVIEW_TAG = `
  167. <span class="RESUserTag">
  168. <a href="javascript:void 0"
  169. title="Set a tag"
  170. class="RESUserTagImage userTagLink truncateTag"
  171. >&nbsp;</a>
  172. </span>
  173. `
  174.  
  175. const QUICK_REPEAT_TAG = `
  176. <span class="RESUserTag" style="filter: hue-rotate(90deg) saturate(0.5);">
  177. <a href="javascript:void 0"
  178. title="Repeat previous tag"
  179. class="RESUserTagImage userTagLink truncateTag"
  180. >&nbsp;</a>
  181. </span>
  182. `
  183.  
  184. // --------------------------------------------------------------------------
  185.  
  186. const EMPTY_TAG = Object.freeze({
  187. text: '',
  188. colour: 'none'
  189. })
  190.  
  191. const isEmptyTag = ({ text, colour } = EMPTY_TAG) => text === '' && colour === 'none'
  192.  
  193. const areEqualTags = (a, b) => a.text === b.text && a.colour === b.colour
  194.  
  195. // --------------------------------------------------------------------------
  196.  
  197. let previousUserTag = EMPTY_TAG
  198. let ctx = null
  199.  
  200. if (message) {
  201. let msg = message()
  202. .text('reddit-save-res-tag.init', STYLES.func)
  203. .text(': ', STYLES.punc)
  204.  
  205. if (localStorage[ TAG_STORAGE_KEY ]) {
  206. previousUserTag = JSON.parse(localStorage[ TAG_STORAGE_KEY ])
  207.  
  208. msg = msg
  209. .text('previousUserTag', STYLES.attr)
  210. .text(' = ', STYLES.punc)
  211. .tag(previousUserTag)
  212. } else {
  213. msg = msg.text('No previous tag found')
  214. }
  215.  
  216. msg.print()
  217. } else if (localStorage[ TAG_STORAGE_KEY ]) {
  218. previousUserTag = JSON.parse(localStorage[ TAG_STORAGE_KEY ])
  219. }
  220.  
  221. // --------------------------------------------------------------------------
  222.  
  223. class TagContext {
  224. constructor ($thingElem) {
  225. this.$thingElem = $thingElem
  226.  
  227. this.authorId = $thingElem.data('author-fullname')
  228.  
  229. this.$dialog = $('.userTagger-dialog-head').closest('.RESHover')
  230.  
  231. this.user = $('.RESHover .RESHoverTitle .res-icon + span').text() || null
  232.  
  233. this.$textField = $('#userTaggerText')
  234. this.$colourField = $('#userTaggerColor')
  235. this.$previewElem = $('#userTaggerPreview')
  236. this.$presetTags = $('#userTaggerPresetTags')
  237. }
  238.  
  239. clearFields () {
  240. this.$textField.val('').focus()
  241. this.$colourField.val('none')
  242. this.$previewElem.html(NO_PREVIEW_TAG)
  243. }
  244.  
  245. setFields ({ text, colour }) {
  246. this.$textField.val(text)
  247. this.$colourField.val(colour)
  248. this.$previewElem.html(getPreviewForTag({ text, colour }))
  249. }
  250.  
  251. getTag () {
  252. return {
  253. text: this.$textField.val().trim(),
  254. colour: this.$colourField.val()
  255. }
  256. }
  257. }
  258.  
  259. // --------------------------------------------------------------------------
  260.  
  261. function getStyleForColour (colour) {
  262. return {
  263. color: BACKGROUND_TO_TEXT_COLOUR_MAP[ colour ] || 'white',
  264. backgroundColor: colour === 'none'
  265. ? 'transparent'
  266. : colour
  267. }
  268. }
  269.  
  270. // --------------------------------------------------------------------------
  271.  
  272. const getPreviewForTag = ({ text, colour }) => {
  273. const { color, backgroundColor } = getStyleForColour(colour)
  274.  
  275. return `
  276. <span class="RESUserTag">
  277. <a href="javascript:void 0"
  278. title="${text}"
  279. class="userTagLink hasTag truncateTag"
  280. style="color: ${color}; background-color: ${backgroundColor};"
  281. >${text}</a>
  282. </span>
  283. `
  284. }
  285.  
  286. // --------------------------------------------------------------------------
  287.  
  288. function onTagSelected (tag) {
  289. // console.info(`onTagSelected: tag = %o, ctx = %o, prevTag = %o`, tag, ctx, previousUserTag)
  290.  
  291. if (message) {
  292. message()
  293. .text('onTagSelected', STYLES.func)
  294. .text('(', STYLES.punc)
  295. .text('tag', STYLES.attr)
  296. .text(': ', STYLES.punc)
  297. .tag(tag)
  298. .text('): ', STYLES.punc)
  299. .text('previousUserTag', STYLES.attr)
  300. .text(' = ', STYLES.punc)
  301. .tag(previousUserTag)
  302. .text(', ', STYLES.punc)
  303. .text('ctx', STYLES.attr)
  304. .text(' = ', STYLES.punc)
  305. .object(ctx)
  306. .print()
  307. }
  308.  
  309. const $tagLinks = $(`.id-${ctx.authorId}`)
  310. .next()
  311. .children(0)
  312.  
  313. if (isEmptyTag(tag)) {
  314. $tagLinks
  315. .html('&nbsp;')
  316. .css('background-color', 'transparent')
  317. .removeClass('hasTag')
  318. .addClass('RESUserTagImage')
  319. } else if (!areEqualTags(tag, previousUserTag)) {
  320. previousUserTag = tag
  321. localStorage[TAG_STORAGE_KEY] = JSON.stringify(previousUserTag)
  322.  
  323. $tagLinks
  324. .text(tag.text)
  325. .css(getStyleForColour(tag.colour))
  326. .addClass('hasTag')
  327. .removeClass('RESUserTagImage')
  328. }
  329.  
  330. ctx = null
  331. }
  332.  
  333. // --------------------------------------------------------------------------
  334.  
  335. $('body')
  336. .on('click.resrem', 'a.userTagLink', function () {
  337. const $tagLink = $(this)
  338. const $thing = $tagLink.closest('.thing')
  339.  
  340. // console.info(`a.userTagLink.click`, this, $thing)
  341.  
  342. setTimeout(() => {
  343. ctx = new TagContext($thing)
  344. ctx.$dialog.width(800)
  345.  
  346. const authorHasTag = $tagLink.hasClass('hasTag')
  347.  
  348. if (!authorHasTag && !isEmptyTag(previousUserTag)) {
  349. ctx.setFields(previousUserTag)
  350. }
  351.  
  352. $(CLEAR_TAG_LINK)
  353. .click(function () {
  354. ctx.clearFields()
  355. $('#userTaggerSave').click()
  356. return false
  357. })
  358. .css({ marginLeft: 'auto' })
  359. .insertAfter(ctx.$colourField)
  360.  
  361. const $srcField = ctx.$previewElem.parent().next()
  362.  
  363. ctx.$presetTags
  364. .one('click.resrem', '.userTagLink', function () {
  365. const $clicked = $(this)
  366. const clickedTag = {
  367. text: $clicked.text(),
  368. colour: $clicked.css('background-color')
  369. }
  370.  
  371. // console.info(`preset .userTagLink.click`, this, clickedTag, ctx)
  372. onTagSelected(clickedTag)
  373. })
  374. .parent()
  375. .insertBefore($srcField)
  376.  
  377. $srcField.next().css({ float: 'left', width: '50%' })
  378. }, TAG_DIALOG_OPEN_TIMEOUT)
  379. })
  380. .on('click.resrem', '#userTaggerSave', function () {
  381. // console.info(`#userTaggerSave.click`, this, ctx)
  382.  
  383. if (ctx) {
  384. onTagSelected(ctx.getTag())
  385. }
  386. })
  387.  
  388. // --------------------------------------------------------------------------
  389. /*
  390. console.log(Watcher)
  391. const watcher = new Watcher(document.body)
  392.  
  393. console.log(watcher)
  394.  
  395. watcher.add(
  396. {
  397. selector: 'a.userTagLink.RESUserTagImage',
  398. events: 1,
  399. },
  400. ({ added }) => {
  401. for (const a of added) {
  402. $(a).after(QUICK_REPEAT_TAG)
  403. }
  404. }
  405. )
  406.  
  407. watcher.start()
  408. */
  409.  
  410. // --------------------------------------------------------------------------
  411.  
  412. /*
  413. <div class="RESHover RESHoverInfoCard RESDialogSmall" style="top: 387.918px; left: 215.767px; width: 350px; display: block; opacity: 1;">
  414. <h3 class="RESHoverTitle" data-hover-element="0">
  415. <div>
  416. <span class="res-icon"></span>&nbsp;<span>Plan-Six</span>
  417. </div>
  418. </h3>
  419.  
  420. <div class="RESCloseButton">x</div>
  421.  
  422. <div class="RESHoverBody RESDialogContents" data-hover-element="1">
  423. <form id="userTaggerToolTip">
  424. <div class="fieldPair">
  425. <label class="fieldPair-label" for="userTaggerText">Text</label>
  426.  
  427. <input class="fieldPair-text" type="text" id="userTaggerText">
  428. </div>
  429.  
  430. <div class="fieldPair">
  431. <label class="fieldPair-label" for="userTaggerColor">Color</label>
  432.  
  433. <select id="userTaggerColor">
  434. <option style="color: inherit; background-color: none" value="none">none</option>
  435. <option style="color: black; background-color: aqua" value="aqua">aqua</option>
  436. <option style="color: white; background-color: black" value="black">black</option>
  437. <option style="color: white; background-color: blue" value="blue">blue</option>
  438. <option style="color: white; background-color: cornflowerblue" value="cornflowerblue">cornflowerblue</option>
  439. <option style="color: white; background-color: fuchsia" value="fuchsia">fuchsia</option>
  440. <option style="color: white; background-color: gray" value="gray">gray</option>
  441. <option style="color: white; background-color: green" value="green">green</option>
  442. <option style="color: black; background-color: lime" value="lime">lime</option>
  443. <option style="color: white; background-color: maroon" value="maroon">maroon</option>
  444. <option style="color: white; background-color: navy" value="navy">navy</option>
  445. <option style="color: white; background-color: olive" value="olive">olive</option>
  446. <option style="color: white; background-color: orange" value="orange">orange</option>
  447. <option style="color: white; background-color: orangered" value="orangered">orangered</option>
  448. <option style="color: black; background-color: pink" value="pink">pink</option>
  449. <option style="color: white; background-color: purple" value="purple">purple</option>
  450. <option style="color: white; background-color: red" value="red">red</option>
  451. <option style="color: black; background-color: silver" value="silver">silver</option>
  452. <option style="color: white; background-color: teal" value="teal">teal</option>
  453. <option style="color: black; background-color: white" value="white">white</option>
  454. <option style="color: black; background-color: yellow" value="yellow">yellow</option>
  455. </select>
  456. </div>
  457.  
  458. <div class="fieldPair">
  459. <label class="fieldPair-label" for="userTaggerPreview">Preview</label>
  460.  
  461. <span id="userTaggerPreview" style="color: white; background-color: olive;">
  462. <span class="RESUserTag">
  463. <a class="userTagLink hasTag truncateTag" style="background-color: olive; color: white !important;" title="Sexist" href="javascript:void 0">Sexist</a>
  464. </span>
  465. </span>
  466. </div>
  467. <a class="userTagLink hasTag truncateTag" style="background-color: olive; color: white !important;" title="Feminist" href="javascript:void 0">Feminist</a>
  468.  
  469. <div class="fieldPair res-usertag-ignore">
  470. <label class="fieldPair-label" for="userTaggerIgnore">Ignore</label>
  471.  
  472. <div id="userTaggerIgnoreContainer" class="toggleButton ">
  473. <span class="toggleThumb"></span>
  474. <div class="toggleLabel res-icon" data-enabled-text="" data-disabled-text=""></div>
  475. <input id="userTaggerIgnore" name="userTaggerIgnore" type="checkbox">
  476. </div>
  477.  
  478. <a class="gearIcon" href="#res:settings/userTagger/hardIgnore" title="RES Settings > User Tagger > hardIgnore"> configure </a>
  479. </div>
  480.  
  481. <div class="fieldPair">
  482. <label class="fieldPair-label" for="userTaggerLink">
  483. <span class="userTaggerOpenLink">
  484. <a title="open link" href="javascript:void 0">Source URL</a>
  485. </span>
  486. </label>
  487.  
  488. <input class="fieldPair-text" type="text" id="userTaggerLink" value="https://www.reddit.com/r/giantbomb/comments/7x251d/all_systems_goku_02/du5fpwr/">
  489. </div>
  490.  
  491. <div class="fieldPair">
  492. <label class="fieldPair-label" for="userTaggerVotesUp" title="Upvotes you have given this redditor">Upvotes</label>
  493.  
  494. <input type="number" style="width: 50px;" id="userTaggerVotesUp" value="0">
  495. </div>
  496.  
  497. <div class="fieldPair">
  498. <label class="fieldPair-label" for="userTaggerVotesDown" title="Downvotes you have given this redditor">Downvotes</label>
  499.  
  500. <input type="number" style="width: 50px;" id="userTaggerVotesDown" value="0">
  501. </div>
  502.  
  503. <div class="res-usertagger-footer">
  504. <a href="/r/dashboard#userTaggerContents" target="_blank" rel="noopener noreferer">View tagged users</a>
  505.  
  506. <input type="submit" id="userTaggerSave" value="✓ save tag">
  507. </div>
  508. </form>
  509. </div>
  510. </div>
  511.  
  512. */
  513.  
  514. })(jQuery, typeof Watcher !== 'undefined' ? Watcher : null, typeof message !== 'undefined' ? message : null)
  515.  
  516. jQuery.noConflict(true)