Super Reddit Alt-Text Display

Displays any alt-text from faces in the comments, eliminating the need to mouse over.

当前为 2014-07-28 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Super Reddit Alt-Text Display
  3. // @namespace reddit_alt_text
  4. // @description Displays any alt-text from faces in the comments, eliminating the need to mouse over.
  5. // @include http://*.reddit.com/*
  6. // @include https://*.reddit.com/*
  7. // @match http://*.reddit.com/*
  8. // @match https://*.reddit.com/*
  9. // @version 2.5.1
  10. // ==/UserScript==
  11.  
  12. // This work is licensed under the Creative Commons Attribution 2.0 Generic License.
  13. // To view a copy of this license, visit http://creativecommons.org/licenses/by/2.0/.
  14.  
  15. // This is not a "real" url regex, it just looks for url like things and hopes
  16. var linkRegex = new RegExp("\\b(?:(http(?:s?)\://)|(?:www\\d{0,3}[.])|(?:[a-z0-9.\-]+[.][a-z]{2,4}/))(?:\\S*)\\b", "i")
  17. var inlineEmoteRegex = new RegExp("-inp?(?:-|$)")
  18.  
  19. function inBlacklist(theLink) {
  20. if (theLink.href.substr(-2,2) == "/b") { // Don't expand the spoiler tags from r/gameofthrones
  21. return true;
  22. }
  23. if (theLink.href.substr(-8,8) == "/spoiler") { // Don't expand alt-text on spoiler tags from r/mylittlepony
  24. return true;
  25. }
  26. return false;
  27. }
  28.  
  29. function addStyle(newStyle) {
  30. var head = document.getElementsByTagName("head")[0];
  31. var cssNode = document.createElement('style')
  32. cssNode.type = 'text/css'
  33. cssNode.appendChild(document.createTextNode(newStyle))
  34. head.appendChild(cssNode)
  35. }
  36.  
  37. altTextStyle = ".SuperRedditAltTextDisplay_Text {color: gray; word-wrap: break-word}\n" +
  38. ".SuperRedditAltTextDisplay_Inline {display: inline-block;}\n" +
  39. ".SuperRedditAltTextDisplay_Text a {color: gray; text-decoration:underline}\n"
  40.  
  41. addStyle(altTextStyle)
  42.  
  43. function expandEmotes(postDiv) {
  44. // Convert the live result of getElementsByTagName to a static array because
  45. // we don't want to see the links we add to the div.
  46. var innerLinks = Array.prototype.slice.call(postDiv.getElementsByTagName("a"));
  47. for (var j in innerLinks) {
  48. if (innerLinks[j].title && innerLinks[j].title != " " && !inBlacklist(innerLinks[j])
  49. && innerLinks[j].className.indexOf("emoteTextExpanded") == -1) {
  50. // If a link has alt-text copy it to a div next to the link
  51. var altText = innerLinks[j].title
  52. var theDiv = document.createElement("div")
  53. theDiv.setAttribute("class", "SuperRedditAltTextDisplay_Text")
  54. if (inlineEmoteRegex.exec(innerLinks[j].href)) {
  55. theDiv.setAttribute("class", "SuperRedditAltTextDisplay_Text SuperRedditAltTextDisplay_Inline")
  56. }
  57. else {
  58. theDiv.setAttribute("class", "SuperRedditAltTextDisplay_Text")
  59. }
  60. // Hunt for links in the text
  61. while (altText) {
  62. linkResult = linkRegex.exec(altText)
  63. if (linkResult) {
  64. // Copy pre-link text
  65. theDiv.appendChild(document.createTextNode(altText.substr(0,linkResult.index)))
  66. // Add the link
  67. var newLinkElement = document.createElement("a")
  68. if ( linkResult[1] ) {
  69. newLinkElement.href = linkResult[0]
  70. }
  71. else {
  72. newLinkElement.href = "http://" + linkResult[0]
  73. }
  74. newLinkElement.appendChild(document.createTextNode(linkResult[0]))
  75. theDiv.appendChild(newLinkElement)
  76. // Chop off the used text and continue
  77. altText = altText.substr(linkResult.index + linkResult[0].length)
  78. }
  79. else {
  80. theDiv.appendChild(document.createTextNode(altText))
  81. altText = ""
  82. }
  83. }
  84. var linkNextSibling = innerLinks[j].nextSibling
  85. if (innerLinks[j].className.indexOf("imgFound") != -1) {
  86. // Inserting the div after a link will confuse the RES image expander, so if RES ran
  87. // before us insert our div after the expand button.
  88. linkNextSibling = linkNextSibling.nextSibling
  89. }
  90. if (innerLinks[j].className.indexOf("hiddenEmoteExpanded") != -1) {
  91. // Our hidden emote script ran before us, so skip over the span it added after the link
  92. linkNextSibling = linkNextSibling.nextSibling
  93. }
  94. if (innerLinks[j].className.indexOf("youtubeLinkFound") != -1) {
  95. // Our youtube script ran before us, so skip over the div it added after the link
  96. linkNextSibling = linkNextSibling.nextSibling
  97. }
  98. innerLinks[j].parentNode.insertBefore(theDiv, linkNextSibling)
  99. innerLinks[j].className += " emoteTextExpanded"
  100. }
  101. }
  102. }
  103.  
  104. function expandChildMDs(elm) {
  105. // Find all user created content sections and expand emotes in them
  106. var mdElements = elm.getElementsByClassName("md")
  107. for (var i in mdElements) {
  108. if (mdElements[i].tagName == 'DIV') {
  109. expandEmotes(mdElements[i]);
  110. }
  111. }
  112. }
  113.  
  114. // hasClass, stolen from the Reddit Enhancement Suite
  115. function hasClass(ele,cls) {
  116. if ((typeof(ele) == 'undefined') || (ele == null)) {
  117. console.log(arguments.callee.caller);
  118. return false;
  119. }
  120. return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
  121. }
  122.  
  123. // Add a listener for the DOMNodeInserted event so we can expand emotes in new comments
  124. // created by either a reply or by clicking "load more comments" in large threads.
  125. function handleInsertion( event ) {
  126. if ((event.target.tagName == 'DIV') && (hasClass(event.target, "thing"))) {
  127. // Insertion event for "load more comments" & new replies
  128. // The actual even we see will be the insertion of the outer "thing" div
  129. //GM_log("Scanning DIV.thing")
  130. expandChildMDs(event.target)
  131. }
  132. else if ((event.target.tagName == 'FORM') && (hasClass(event.target, "usertext"))) {
  133. // Insertion event for text expando blocks
  134. //GM_log("Scanning FORM.usertext")
  135. expandChildMDs(event.target)
  136. }
  137. /*
  138. else {
  139. GM_log("Other insertion: " + event.target.tagName + " : " + event.target.className)
  140. }
  141. */
  142. }
  143.  
  144. // Add a listener for the DOMNodeInserted event so we can expand emotes on the RES dashboard
  145. // This gets it's own listener because watching sitetable causes unnecessary rescans on normal submission pages.
  146. function handleSitetableInsertion( event ) {
  147. if ((event.target.tagName == 'DIV') && (hasClass(event.target, "sitetable")) && (hasClass(event.target, "linklisting"))) {
  148. // Insertion event for RES dashboard widgets
  149. // Note: This causes rescans on some other pages too
  150. //GM_log("Scanning DIV.sitetable.linklisting")
  151. expandChildMDs(event.target)
  152. }
  153. else if ((event.target.tagName == 'DIV') && (hasClass(event.target, "parent"))) {
  154. // Insertion event fow "show parent" on the RES dashboard
  155. //GM_log("Scanning DIV.parent")
  156. expandChildMDs(event.target)
  157. }
  158. }
  159.  
  160. // Initial expansion of static content
  161. expandChildMDs(document)
  162.  
  163. document.body.addEventListener('DOMNodeInserted', handleInsertion, false);
  164.  
  165. if (RegExp("^https?://(?:www.)?reddit.com/r/dashboard", "i").exec(window.location)) {
  166. // Add the listener for sitetable if we're on the RES dashboard
  167. document.body.addEventListener('DOMNodeInserted', handleSitetableInsertion, false);
  168. }
  169. else if (RegExp("^https?://(?:www.)?reddit.com/user/", "i").exec(window.location) && document.getElementsByClassName("neverEndingReddit")) {
  170. // Add this listener for RES never ending reddit on user pages
  171. document.body.addEventListener('DOMNodeInserted', handleSitetableInsertion, false);
  172. }