ETI Archive Quoter

Adds a 'Quote' button to posts in the archives

  1. // ==UserScript==
  2. // @name ETI Archive Quoter
  3. // @description Adds a 'Quote' button to posts in the archives
  4. // @namespace pendevin
  5. // @include http://boards.endoftheinter.net/showmessages.php*
  6. // @include http://archives.endoftheinter.net/showmessages.php*
  7. // @include https://boards.endoftheinter.net/showmessages.php*
  8. // @include https://archives.endoftheinter.net/showmessages.php*
  9. // @require http://code.jquery.com/jquery-2.1.4.min.js
  10. // @version 2.1
  11. // ==/UserScript==
  12.  
  13. //ll breaks without noconflict jquery
  14. this.$ = this.jQuery = jQuery.noConflict(true);
  15.  
  16. //adds a style to a document and returns the style object *JQUERY
  17. //css is a string, id is an optional string that determines the object's id
  18. function addStyle(css, id) {
  19. //create a style
  20. var style = $('<style type="text/css">');
  21. //add the css data to it
  22. style.html(css);
  23. if (id) {
  24. //remove any style that has our id
  25. $('#' + id).remove();
  26. //give our style the id after removing the other stuff. idk if it matters, but i'm too lazy to find out
  27. style.attr('id', id);
  28. }
  29. //add the style into the head
  30. $('head').append(style);
  31. //we're outta here
  32. return style;
  33. }
  34.  
  35. //finds the last index of a regular expression value
  36. //takes a string and a regex object
  37. //kinda slow :(
  38. function reLastIndex(string, regex) {
  39. var index = -1;
  40. //we're going backwards from the end and searching for the first occurrence we find
  41. for (var i = string.length - 1; i > 0; i--) {
  42. //once we find it, we're outta here
  43. if (string.substring(i).search(regex) != -1) {
  44. index = i;
  45. break;
  46. }
  47. }
  48. return index;
  49. }
  50.  
  51. //puts the message body of any quoted-message in its own message div like normal messages for easier styling(hiding)
  52. //livelinks ready *JQUERY
  53. function rearrangeQuotes(container) {
  54. //this is a for loop or something
  55. $(container).find('.quoted-message').each(function(i, quote) {
  56. quote = $(quote);
  57. //create message div for quote
  58. var quoteBody = $('<div class="message">');
  59. //add everything but the message-top to the message div
  60. quote.contents().each(function(i2, node) {
  61. node = $(node);
  62. if (!node.hasClass('message-top') && !node.hasClass('message')) {
  63. quoteBody.append(node);
  64. }
  65. });
  66. //add the new message div to the quoted-message if it's got anything in it
  67. if (quoteBody.contents()[0]) {
  68. quote.append(quoteBody);
  69. }
  70. });
  71. }
  72.  
  73. //add in those pesky triggers
  74. function addQuoteLinks() {
  75. //i'm lazy so rearrange the quotes
  76. $('#u0_1 .message-container').each(function(i, container) {
  77. rearrangeQuotes(container);
  78. });
  79.  
  80. //make sure this topic is closed
  81. if (location.hostname == 'archives.endoftheinter.net' || $('em').text().match(/This topic has been closed/)) {
  82. $('#u0_1 .message-container>.message-top').each(function(i, top) {
  83. top = $(top);
  84. //message detail link
  85. var messageDetail = top.children('[href^="/message.php"]');
  86. //new quote link
  87. var link = $('<span class="linky quote">Quote</span>');
  88. messageDetail.after('&nbsp;|&nbsp;', link);
  89. //oh look we got quoted
  90. link.on(
  91. 'click',
  92. top.next().find('.message:first'),
  93. function(e) {
  94. postToText(e.data);
  95. }
  96. );
  97. });
  98. }
  99. }
  100.  
  101. //takes a post and returns the text required to get it
  102. function postToText(post) {
  103. post = $(post);
  104. var text = $('<div>' + post.html() + '</div>');
  105.  
  106. //get rid of sigs
  107. //if people fuck with the sig belt, this probably won't work
  108. var lastIndex = reLastIndex(text.html(), /(<br>|<\/div>)?\n?---\n?<br>/g);
  109. if (lastIndex != -1) {
  110. text.html(text.html().substring(0, lastIndex));
  111. }
  112. //in case of sig parser
  113. text.find('.sig').remove();
  114.  
  115. //deal with spoilers
  116. text.find('.spoiler_closed').each(function(i, spoiler) {
  117. spoiler = $(spoiler);
  118. //build our spoiler notation
  119. var pointA = spoiler.find('span>a>b').text();
  120. var pointB = spoiler.find('.spoiler_on_open').html();
  121. var spoiled = '<spoiler' + (pointA != '<spoiler />' ? ' caption="' + pointA.slice(1, -3) + '">' : '>') + pointB.substring(pointB.indexOf('</a>') + 4, pointB.lastIndexOf('<a class="caption"')) + '</spoiler>';
  122. //replace the old spoiler
  123. spoiler.replaceWith(spoiled);
  124. });
  125.  
  126. //deal with quotes
  127. //this guy only handles rearranged quotes
  128. //go in reverse order so it can handle nested quotes
  129. $(text.find('.quoted-message').get().reverse()).each(function(i, quote) {
  130. quote = $(quote);
  131. //build our quote notation
  132. var msgID = quote.attr('msgid');
  133. //quoted text omitted
  134. var omitted = (quote.children(':last-child').children(':last-child').text() == ('[quoted text omitted]'));
  135. //quoting empty posts
  136. var quoteContent = quote.children(':last-child').html() != undefined ? quote.children(':last-child').html() : '';
  137. //remove trailing linebreaks
  138. quoteContent = quoteContent.replace(/(\n|<br>)+$/g, '');
  139. var quoted = '<quote' + (msgID != '' ? ' msgid="' + msgID + '"' : '') + (!omitted ? '>' + quoteContent + '</quote>' : ' />');
  140. //replace the old quote
  141. quote.replaceWith(quoted);
  142. //if next element is a br, get rid of it
  143. if (quoted.nextSibling && quoted.nextSibling.nodeName == 'BR') {
  144. $(quoted).next().remove();
  145. }
  146. });
  147.  
  148. //deal with images
  149. //works with all image settings don't worry
  150. text.find('.imgs').each(function(i, imgs) {
  151. imgs = $(imgs);
  152. //there's possibly a bunch of images per div
  153. imgs.children('a').each(function(i2, img) {
  154. img = $(img);
  155. //stick all the images after the imgs div
  156. var imged = $('<img src="' + img.attr('imgsrc') + '">');
  157. imgs.before(imged);
  158. });
  159. //get rid of the imgs div and replace with a br
  160. imgs.replaceWith('<br>');
  161. });
  162.  
  163. //deal with links
  164. //the selector takes care of youtube video embed
  165. text.find('a:not([href^="javascript"])').each(function(i, a) {
  166. a = $(a);
  167. //just need the href to make a link
  168. a.replaceWith(a.attr('href'));
  169. });
  170.  
  171. //deal with pre tags
  172. text.find('.pr').each(function(i, pre) {
  173. pre = $(pre);
  174. //replacing pre tags so easy
  175. var post = $('<pre>' + pre.html() + '</pre>');
  176. pre.replaceWith(post);
  177. });
  178.  
  179. //if you have the userpics script, get rid of the userpic
  180. text.find('.photo-album-image').remove();
  181.  
  182. //if you have my youtube embed script or something similar
  183. text.find('a[href="javascript:void(0);"]').each(function(i, thing) {
  184. thing = $(thing);
  185. //remove that thingy
  186. thing.parent().remove()
  187. console.log(thing.attr('href'));
  188. });
  189.  
  190. //final clean-up and display
  191. var alert = text.html();
  192. //remove trailing newlines
  193. alert = alert.replace(/(\n|<br>)+$/g, '');
  194. //add quote thingy and replace brs for newlines
  195. alert = '<quote msgid="' + post.attr('msgid') + '">' + alert + '</quote>\n';
  196. alert = alert.replace(/<br>\n?/g, '\n');
  197. //create shadow
  198. var shadow = $('<div id="AQshadowbox">');
  199. //create textbox to go on top of shadow
  200. var light = $('<textarea id="AQtextarea">' + alert + '</textarea>');
  201. //add these guys to the document
  202. $('body').append(shadow, light);
  203. //listen for removal
  204. shadow.on(
  205. 'click',
  206. function(e) {
  207. shadow.remove();
  208. light.remove();
  209. }
  210. );
  211. }
  212.  
  213. //styles
  214. addStyle('\
  215. #AQshadowbox{\
  216. position:fixed;\
  217. top:0px;\
  218. left:0px;\
  219. width:100%;\
  220. height:100%;\
  221. background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA9JREFUeNpiYGBgaAAIMAAAhQCB69VMmQAAAABJRU5ErkJggg==);\
  222. }\
  223. #AQtextarea{\
  224. position:fixed;\
  225. top:0px;\
  226. left:0px;\
  227. width:70%;\
  228. height:70%;\
  229. margin:15%;\
  230. border:4px solid;\
  231. }\
  232. ', 'archive-quoter');
  233. addStyle('.linky{cursor:pointer;text-decoration:underline;}', 'linky');
  234. //initialize
  235. addQuoteLinks();