SA Buttons

Something Awful Forums functions.

  1. // ==UserScript==
  2. // @name SA Buttons
  3. // @namespace http://uberg.nu/
  4. // @version 1.44
  5. // @description Something Awful Forums functions.
  6. // @author Ubergnu
  7. // @match https://forums.somethingawful.com/*
  8. // @grant GM_setValue
  9. // @grant GM_getValue
  10. // ==/UserScript==
  11.  
  12.  
  13. // Some UI values/constants
  14. //
  15. var SPOILER_TEXT_COLOR = ""; // Override for spoiler text color. Set this if there's a custom CSS (like SA Dark Redesign) that messes things up.
  16. var BUTTON_TEXT_COLOR = "#444444";
  17. var BUTTON_TEXT_COLOR_ACTIVE = "#DDDDDD";
  18. var BUTTON_BACKGROUND = "";
  19. var BUTTON_BACKGROUND_ACTIVE = "#888888";
  20. var ELEM_VISIBLE = 1;
  21. var ELEM_HIDDEN = 0;
  22. var ELEM_DIMMED = 0.3;
  23. var MAX_BAN_MESSAGES = 3;
  24. var NO_BANS_IMAGE = "https://i.imgur.com/YQ5tnzB.png";
  25.  
  26. // Misc globals.
  27. var avatarState;
  28. var spoilerState;
  29. var imageState = false;
  30. var videoState = true;
  31.  
  32. // Add Menu buttons. Comment out unwanted ones here. Or set the order.
  33. //
  34. $("#content #thread .profilelinks").append("<li class='liSAB btnStop'>Stop</li>");
  35. $("#content #thread .profilelinks").append("<li class='liSAB btnFold'>Fold</li>");
  36. $("#content #thread .profilelinks").append("<li class='liSAB btnFade'>Avs</li>");
  37. $("#content #thread .profilelinks").append("<li class='liSAB btnCtrl'>Buts</li>");
  38. $("#content #thread .profilelinks").append("<li class='liSAB btnSplr'>Splr</li>");
  39. $("#content #thread .profilelinks").append("<li class='liSAB btnProb'>Prob</li>");
  40.  
  41. // Insert CSS into <head> of page.
  42. //
  43. function addCss() {
  44.  
  45. // Count the number of buttons in use.
  46. var buttonCount = $(".postlinks").eq(0).find(".liSAB").length;
  47.  
  48. // Drop shadow for popup.
  49. var boxShadow = "box-shadow: 8px 8px 25px 0px rgba(0,0,0,0.75) !important;";
  50.  
  51. var s = "";
  52. s += ".btnClosePopup {";
  53. s += "font-family: 'Roboto',sans-serif !important;";
  54. s += "font-size: 12px !important;";
  55. s += "border: none;";
  56. s += "outline: 0;";
  57. s += "background-color: #3b6d7d;";
  58. s += "color: #EEEEEE;";
  59. s += "border-radius: 9px !important;";
  60. s += "width: 130px !important;";
  61. s += "height: 30px !important; ";
  62. s += "margin-top: 5px;";
  63. s += "float: right;";
  64. s += "cursor: pointer;";
  65. s += boxShadow;
  66. s += "}";
  67.  
  68. s += ".btnClosePopup:hover {";
  69. s += "background: #82b7c7 !important;";
  70. s += "color: #000000! important;";
  71. s += "}";
  72.  
  73. s += ".SAB-dialog:focus";
  74. s += "{";
  75. s += "outline: none !important;";
  76. s += "}";
  77.  
  78. s += ".msgContent {";
  79. s += "font-family: 'Roboto',sans-serif;";
  80. s += "font-size: 14px;";
  81. s += "width: 508px;"; //412
  82. s += "height: 258px;"; //154
  83. s += "background-color: #EEEEEE;";
  84. s += "margin: 0 auto;";
  85. s += "padding: 5px;";
  86. s += "overflow: auto;";
  87. s += "border-radius: 5px !important;";
  88. s += "}";
  89.  
  90. s += "#msgPopupContent::-webkit-scrollbar-track";
  91. s += "{";
  92. s += "-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);";
  93. s += "border-radius: 10px !important;";
  94. s += "background-color: #F5F5F5;";
  95. s += "}";
  96.  
  97. s += "#msgPopupContent::-webkit-scrollbar";
  98. s += "{";
  99. s += "width: 12px;";
  100. s += "background-color: #F5F5F5;";
  101. s += "}";
  102. s += "";
  103.  
  104. s += "#msgPopupContent::-webkit-scrollbar-thumb";
  105. s += "{";
  106. s += "border-radius: 10px;";
  107. s += "-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);";
  108. s += "background-color: #bbbcbd;";
  109. s += "}";
  110.  
  111. //#msgPopupWindow
  112. s += ".msgPopup {";
  113. s += "background-color: #3b6d7d;";
  114. s += "border-radius: 10px !important;";
  115. s += "box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75) !important;";
  116. s += "padding-top: 10px;";
  117. s += "display:none;";
  118. s += boxShadow;
  119. s += "}";
  120.  
  121. //s += "#thread ul.profilelinks li:nth-last-of-type(-n+6) { "; // Use this if the buttons count screws up (comment out the row below).
  122. s += "#thread ul.profilelinks li:nth-last-of-type(-n+" + buttonCount + ") { ";
  123. s += "max-height: 15px !important; ";
  124. s += "padding: 0px 13px 10px 13px !important; ";
  125. s += "margin: 5px 0px 10px 0px; ";
  126. s += "line-height: 25px !important; ";
  127. s += "}";
  128.  
  129. s += ".SAButton {";
  130. s += "border-radius: 11px !important;";
  131. s += "position: relative;";
  132. s += "font-size: 11px;";
  133. s += "height: 22px !important;";
  134. s += "padding: 2px;";
  135. s += "margin: 0px 0 0px 0 !important;";
  136. s += "cursor: pointer;";
  137. s += "color: " + BUTTON_TEXT_COLOR + ";";
  138. s += "}";
  139.  
  140. s += ".ui-widget-overlay.SAB-custom-overlay";
  141. s += "{";
  142. s += "background-color: black;";
  143. s += "background-image: none;";
  144. s += "opacity: 0.4;";
  145. s += "z-index: 1040; ";
  146. s += "}";
  147.  
  148. s += ".SAB-draggable";
  149. s += "{";
  150. s += "border-top-left-radius: 20px !important;";
  151. s += "border-bottom: none;";
  152. s += "border-top-right-radius: 20px !important;";
  153. s += "box-shadow: inset 0 0 27px #3b6d7d !important;";
  154. s += "width: 96%;";
  155. s += "margin-left: 9px;";
  156. s += "cursor: move;";
  157. s += "}";
  158.  
  159. // Inject CSS
  160. var head = document.getElementsByTagName('head')[0];
  161. var newCss = document.createElement('style');
  162. newCss.type = "text/css";
  163. newCss.innerHTML = s;
  164. head.appendChild(newCss);
  165.  
  166. // Get the current text color in use (it can change if a custom CSS is installed). Can be overridden by changing the SPOILER_TEXT_COLOR constant.
  167. if (SPOILER_TEXT_COLOR === "")
  168. {
  169. //var col = $(".postbody").eq(0).attr("color");
  170. var elem = document.getElementsByClassName("postbody")[0];
  171. var col = window.getComputedStyle(elem, null).getPropertyValue("color");
  172. SPOILER_TEXT_COLOR = col;
  173. }
  174. }
  175. addCss();
  176.  
  177.  
  178. // Functions that's probably not wanted by everyone.
  179. //
  180. // Remove special titles.
  181. $(".special_title").hide();
  182. // Completly hide ignored users posts.
  183. $("a[title=\"DON'T DO IT!!\"]").parents().eq(3).hide();
  184.  
  185.  
  186. // Menu buttons layout
  187. //
  188. var li = $(".postlinks .liSAB");
  189. li.addClass("SAButton");
  190. li.hover(
  191. function(){
  192. $(this).css("color", BUTTON_TEXT_COLOR_ACTIVE);
  193. $(this).css("height", "20px !important;");
  194. $(this).css("max-height", "20px !important;");
  195. $(this).css("border-radius", "10px !important;");
  196. $(this).animate({backgroundColor: BUTTON_BACKGROUND_ACTIVE}, 'fast', function(){
  197. if (!$(this).is(":hover"))
  198. li.css("background-color", BUTTON_BACKGROUND);
  199. });
  200. }, function() {
  201. li.css("background-color", BUTTON_BACKGROUND);
  202. li.css("color", BUTTON_TEXT_COLOR);
  203. });
  204.  
  205.  
  206. // Init the spoiler texts with saved value. Keep it in global var.
  207. //
  208. spoilerState = GM_getValue("SAB_spoilers");
  209. toggleSpoilerText(spoilerState);
  210.  
  211.  
  212. // Toggle play/pause for <video> with a click.
  213. //
  214. //$(".gfy_video").click(function(){
  215. //$(".gifv_video, .gfy_video").click(function(){
  216. //$(".gfy_video").click(function(){
  217. // $(".gifv_video , .gfy_video").click(function(){
  218.  
  219. // var tag = $(this).attr("tag");
  220. // alert("tag: " + tag);
  221. // if(typeof tag == "undefined") {
  222. // tag = "play";
  223. // }
  224.  
  225. // tag = tag === "pause" ? "play" : "pause";
  226.  
  227. // if (tag === "pause")
  228. // {
  229. // $(this).find("video")[0].pause();
  230. // $(this).attr("tag", "pause");
  231. // } else {
  232. // $(this).find("video")[0].play();
  233. // $(this).attr("tag", "play");
  234. // }
  235.  
  236. // // if (videoState) {
  237. // // $(this).find("video")[0].pause();
  238. // // } else {
  239. // // $(this).find("video")[0].play();
  240. // // }
  241. // // videoState = !videoState;
  242. // });
  243.  
  244.  
  245. // Shrink images in posts by double clicking them. Click to restore.
  246. //
  247. $(".postbody").find("img").dblclick(function(){
  248.  
  249. var tag = $(this).attr("tag");
  250. //alert("img tag: " + tag);
  251. if(typeof tag == "undefined")
  252. tag = "max";
  253.  
  254. tag = tag == "min" ? "max" : "min";
  255.  
  256. if (tag == "min")
  257. {
  258. $(this).css("height", "20px");
  259. $(this).css("width", "auto");
  260. $(this).attr("tag", "min");
  261. } else {
  262. $(this).css("height", "");
  263. $(this).attr("tag", "max");
  264. }
  265. });
  266.  
  267.  
  268. // Prob button click.
  269. //
  270. $(".postlinks ul .btnProb").click(function(){
  271.  
  272. // Older Forums version, keep just in case.
  273. //var userID = $(this).parents().eq(2).find('td').eq(0).find('a').eq(1).attr('href');
  274. //var parts = userID.split("=");
  275. //var linkAddress = "/banlist.php?userid=" + parts[2];
  276.  
  277. // Get userID and call showProbInfo() for that user.
  278. //
  279. var classes = $(this).parents().eq(3).find('tr').eq(0).find('td').eq(0).attr("class");
  280. var userID = classes.replace(/[^0-9]/gi, '');
  281. var linkAddress = "/banlist.php?userid=" + userID;
  282.  
  283. showProbInfo(linkAddress);
  284. });
  285.  
  286.  
  287. // Show popup with ban/probation reason.
  288. //
  289. function showProbInfo(address) {
  290.  
  291. // Get the last MAX_BAN_MESSAGES number of entries from the Leper's Colony page.
  292. $.get(address, function (data) {
  293. $(".result").html(data);
  294. var infoText = "";
  295. var rawText = "";
  296.  
  297. // Assemble the popup text.
  298. for(let i=0; i<MAX_BAN_MESSAGES; i++)
  299. {
  300. var text = "";
  301. var infoRow = $('a[name="list"]', $(data)).nextAll().eq(0).children(":first").children('tr').eq(1+i).children('td'); //.eq(3);
  302. var time = $(infoRow).eq(1).text();
  303. var infoField = $(infoRow).eq(3);
  304.  
  305. if (typeof $(infoField).html() != "undefined")
  306. text = $(infoField).html();
  307.  
  308. rawText += text;
  309. infoText += "<i><font size='2'>" + time + "</font></i><br/>" + text;
  310. if (i<MAX_BAN_MESSAGES)
  311. infoText += "<br/><br/>";
  312. }
  313.  
  314. // No probations/bans was found. Show a special message.
  315. if (rawText.length === 0) {
  316. var img = "<center><img src='" + NO_BANS_IMAGE + "'/></center>";
  317. infoText = "<i><font size='2'>This user is pure as the driven snow.</font></i><br/><br/>" + img;
  318. }
  319.  
  320. // HTML for the popup.
  321. var win = "<div class='msgPopup' id='msgPopupWindow'>";
  322. win += "<p class='msgContent' id='msgPopupContent'>";
  323. //win += infoText;
  324. win += "</p></div>";
  325.  
  326. // Inject popup HTML into page.
  327. var html = $.parseHTML(win);
  328. $("#something_awful").append(html);
  329.  
  330. // Open dialog window.
  331. $(html).dialog({
  332. autoOpen: true,
  333. width: 550,
  334. height: 400,
  335. modal: true,
  336. resizable: true,
  337. open: function(event, ui) {
  338.  
  339. // Clear all classes from jquery dialog.
  340. var main = $("div[aria-describedby='msgPopupWindow']");
  341. $(main).removeClass();
  342. $(main).addClass("SAB-dialog");
  343. $(main).find("div").not(":eq(0)").removeClass();
  344. $(main).find("button").removeClass();
  345.  
  346. // Custom title bar
  347. var titleBar = $(main).find("div").eq(0);
  348. $(titleBar).removeClass();
  349. $(titleBar).addClass("ui-dialog-titlebar SAB-draggable");
  350.  
  351. // Add own classes and content
  352. $(".ui-dialog-titlebar-close", ui.dialog | ui).hide();
  353. $(".msgContent").html(infoText);
  354. $("#msgPopupWindow").addClass('msgPopup');
  355. $("#msgPopupContent").addClass('msgContent');
  356. $(main).find("button").addClass('btnClosePopup');
  357. $(main).find("button").eq(0).hide();
  358. $('.ui-widget-overlay').addClass('SAB-custom-overlay');
  359. },
  360. buttons: [
  361. {
  362. text: "Close",
  363. "class": 'btnClosePopup',
  364. click: function () {
  365. $(this).dialog("close");
  366. $('.ui-widget-overlay').removeClass('SAB-custom-overlay');
  367. $("#msgPopupWindow").remove(); // Remove the injected HTML when closing popup.
  368. }
  369. },
  370. ],
  371. });
  372. });
  373. }
  374.  
  375.  
  376. // Stop avatar animations
  377. //
  378. $(".postlinks ul .btnStop").click(function(){
  379. var avs = $(".title img");
  380. for(i=0; i<avs.length; i++)
  381. setFirstFrame(avs[i], i);
  382. gmSetValue("SA_animations", false);
  383. });
  384.  
  385.  
  386. // Toggle dim/hide/show all avatars
  387. //
  388. $(".postlinks ul .btnFade").click(function(){
  389.  
  390. if (avatarState == "on"){
  391. $(".title img").animate({opacity: ELEM_DIMMED});
  392. $(".title canvas").animate({opacity: ELEM_DIMMED});
  393. gmSetValue("SA_avatars", "dim");
  394. avatarState = "dim";
  395. }
  396. else if(avatarState == "dim"){
  397. $(".title img").animate({opacity: ELEM_HIDDEN});
  398. $(".title canvas").animate({opacity: ELEM_HIDDEN});
  399. gmSetValue("SA_avatars", "off");
  400. avatarState = "off";
  401. }
  402. else if(avatarState == "off"){
  403. $(".title img").animate({opacity: ELEM_VISIBLE});
  404. $(".title canvas").animate({opacity: ELEM_VISIBLE});
  405. gmSetValue("SA_avatars", "on");
  406. avatarState = "on";
  407. }
  408. });
  409.  
  410. // Show/hide spoilers.
  411. //
  412. $(".postlinks ul .btnSplr").click(function() {
  413. toggleSpoilerText(!spoilerState);
  414. });
  415.  
  416. function toggleSpoilerText(state) {
  417. if (state) {
  418. $(".bbc-spoiler").css("background", "transparent");
  419. $(".bbc-spoiler").css("color", SPOILER_TEXT_COLOR);
  420. gmSetValue("SAB_spoilers", true);
  421. spoilerState = true;
  422. } else {
  423. $(".bbc-spoiler").css("background", "black");
  424. $(".bbc-spoiler").css("color", "black");
  425. gmSetValue("SAB_spoilers", false);
  426. spoilerState = false;
  427. }
  428. }
  429.  
  430.  
  431. // Toggle visibility for report/quote buttons
  432. //
  433. $(".postlinks ul .btnCtrl").toggle(
  434. function(){
  435. $(".postlinks .postbuttons").children().animate({opacity: ELEM_VISIBLE});
  436. gmSetValue("SA_reportButtons", true);
  437. }, function(){
  438. $(".postlinks .postbuttons").children().animate({opacity: ELEM_HIDDEN});
  439. gmSetValue("SA_reportButtons", false);
  440. }
  441. );
  442.  
  443.  
  444. // Hide/show posts
  445. //
  446. $(".postlinks ul .btnFold").click(function () {
  447. $(this).parents().eq(2).prev().find("dl[class='userinfo']").slideToggle(300);
  448. $(this).parents().eq(2).prev().children().last().slideToggle(300);
  449. //$(this).parents().eq(2).prev().children().first().children().first().children().slideToggle(500);
  450. });
  451.  
  452.  
  453. // Stop avatar animations if set
  454. //
  455. if (!GM_getValue("SA_animations", true))
  456. {
  457. var avs = $(".title img");
  458.  
  459. for(i=0; i<avs.length; i++)
  460. {
  461. setFirstFrame(avs[i]);
  462. //console.log(avs[i]);
  463. }
  464. }
  465.  
  466.  
  467. // Hide/show Report/Quote buttons depending on settings
  468. //
  469. if (GM_getValue("SA_reportButtons", false))
  470. $(".postlinks .postbuttons").children().animate({opacity: ELEM_VISIBLE});
  471. else
  472. $(".postlinks .postbuttons").children().animate({opacity: ELEM_HIDDEN});
  473.  
  474.  
  475. // Hide/show avatars depending on settings
  476. //
  477. avatarState = GM_getValue("SA_avatars");
  478. switch(avatarState)
  479. {
  480. case "on":
  481. $(".title img").animate({opacity: ELEM_VISIBLE});
  482. $(".title canvas").animate({opacity: ELEM_VISIBLE});
  483. GM_setValue("SA_avatars", "on");
  484. break;
  485. case "off":
  486. $(".title img").animate({opacity: ELEM_HIDDEN});
  487. $(".title canvas").animate({opacity: ELEM_HIDDEN});
  488. GM_setValue("SA_avatars", "off");
  489. break;
  490. case "dim":
  491. $(".title img").animate({opacity: ELEM_DIMMED});
  492. $(".title canvas").animate({opacity: ELEM_DIMMED});
  493. GM_setValue("SA_avatars", "dim");
  494. break;
  495. default:
  496. $(".title img").animate({opacity: ELEM_VISIBLE});
  497. $(".title canvas").animate({opacity: ELEM_VISIBLE});
  498. GM_setValue("SA_avatars", "on");
  499. break;
  500. }
  501.  
  502. // Hide the whole user Title (avatar+text+tags)
  503. //
  504. $(".postlinks ul .btnText").click(function(){
  505. //var userTitle = $(this).parent().parent().parent().parent().find(".userinfo .title");
  506. var userTitle = $(this).parents().eq(3).find(".userinfo .title");
  507. var opa;
  508.  
  509. if (avatarState == "on"){ opa = ELEM_VISIBLE; }
  510. else if(avatarState == "dim"){ opa = ELEM_DIMMED; }
  511. else if(avatarState == "off"){ opa = ELEM_HIDDEN; }
  512.  
  513. if (userTitle.css('opacity') == ELEM_HIDDEN) {
  514. userTitle.animate({ opacity: opa });
  515. }else{
  516. userTitle.animate({ opacity: ELEM_HIDDEN });
  517. }
  518.  
  519. });
  520.  
  521.  
  522. // -------------------------------------------
  523. // Misc stuff
  524. // -------------------------------------------
  525.  
  526. // Stop avatar animations
  527. //
  528. function setFirstFrame (img, idx) {
  529. var newCanvas = document.createElement("canvas");
  530. newCanvas.height = img.height;
  531. newCanvas.width = img.width;
  532.  
  533. newCanvas.id = "cnvAv";
  534.  
  535. newCanvas.getContext("2d").drawImage(img, 0, 0);
  536. img.parentNode.replaceChild(newCanvas, img);
  537.  
  538.  
  539. if (avatarState == "on")
  540. $(newCanvas).animate({opacity: ELEM_VISIBLE});
  541.  
  542. else if(avatarState == "dim")
  543. $(newCanvas).animate({opacity: ELEM_DIMMED});
  544.  
  545. else if(avatarState == "off")
  546. $(newCanvas).animate({opacity: ELEM_HIDDEN});
  547.  
  548. }
  549.  
  550.  
  551. // Workaround for getting/setting values from inside an event
  552. //
  553. function gmSetValue(key, val)
  554. {
  555. setTimeout(function() {
  556. GM_setValue(key, val);
  557. }, 0);
  558. }
  559.  
  560. function gmGetValue(key, defaultval)
  561. {
  562. setTimeout(function() {
  563. avatarState = GM_getValue(key, defaultval);
  564. }, 0);
  565.  
  566. return avatarState;
  567. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址