Thread reply button for Lithium communities

Add a "Thread Reply" button to forum post pages on many Lithium-based forums. This button initiates a reply to the original post instead of the linked post, even if you are not at the first page.

  1. // ==UserScript==
  2. // @name Thread reply button for Lithium communities
  3. // @namespace http://sites.google.com/site/cerisesorbet/
  4. // @description Add a "Thread Reply" button to forum post pages on many Lithium-based forums. This button initiates a reply to the original post instead of the linked post, even if you are not at the first page.
  5. // @include http://lithosphere.lithium.com/*
  6. // @include http://bookclubs.barnesandnoble.com/*
  7. // @include http://forums.verizon.com/*
  8. // @include http://boards.adultswim.com/*
  9. // @include http://community.secondlife.com/*
  10. // @include https://community.secondlife.com/*
  11. // @version 20150312
  12. // @license MIT License
  13. // @copyright (c) 2012-2015 Cerise Sorbet
  14. // @grant none
  15. // ==/UserScript==
  16.  
  17. // return global thread ID, or 0 if missing
  18. function GetReplyThreadNumber() {
  19. var links = document.getElementsByTagName('link');
  20. if (links.length) {
  21. var x; for (x = 0; x < links.length; x++) {
  22. if (links[x].rel == 'canonical') {
  23. var pathChop = links[x].href.split('/');
  24. var tdpIndex = pathChop.indexOf('td-p');
  25. if (~tdpIndex)
  26. return Number(pathChop[tdpIndex + 1]);
  27. }
  28. }
  29. }
  30. return 0;
  31. }
  32.  
  33. function MakeThreadReplyButton() {
  34. // Is there an active reply button? If not, give up.
  35. var replySpan = document.getElementsByClassName('primary-action message-reply');
  36. if (replySpan.length) {
  37. var replyLink = replySpan[0].getElementsByTagName('a');
  38. if (replyLink.length == 0)
  39. return;
  40. }
  41. else
  42. return;
  43.  
  44. var replyThreadNumber = GetReplyThreadNumber();
  45. if (replyThreadNumber) {
  46. // create the new button
  47. var threadReplyButton = document.createElement('span');
  48. threadReplyButton.className = 'primary-action';
  49. threadReplyButton.innerHTML = '<a class="lia-button lia-button-primary" style="margin-right: 10px" id="cerise-thread-reply-'
  50. + replyThreadNumber + '" rel="nofollow:"><span>Thread Reply</span></button>';
  51.  
  52. // squeeze in the new one
  53. var bottomBar = document.getElementsByClassName("lia-menu-bar lia-menu-bar-bottom");
  54. if (bottomBar.length) {
  55. var buttonDiv = bottomBar[0].getElementsByClassName('lia-menu-bar-buttons');
  56. if (buttonDiv.length) {
  57. buttonDiv[0].style.display = ''; // div is there but typically hidden
  58. buttonDiv[0].appendChild(threadReplyButton);
  59.  
  60. // The button is installed, so add an event handler.
  61. threadReplyButton.firstChild.addEventListener('click', DoThreadReply, true);
  62. }
  63. }
  64. }
  65. }
  66.  
  67. function DoThreadReply() {
  68. var threadNumber = this.id.replace(/^cerise-thread-reply-/, '');
  69.  
  70. // Get the board_id to build a reply URL
  71. var XMLReq = new XMLHttpRequest();
  72. var XMLhref = window.location.protocol + '//' + window.location.hostname
  73. + '/restapi/vc/messages/id/' + threadNumber + '?xslt=json.xsl&amp;restapi.response_style=view';
  74. XMLReq.open('GET', XMLhref, true);
  75. XMLReq.onreadystatechange = function(e) {
  76. if (XMLReq.readyState == 4) {
  77. if(XMLReq.status != 200) { // HTTP error
  78. alert('Unable to get reply link, HTTP error ' + XMLReq.status);
  79. }
  80. else {
  81. try {
  82. var article = JSON.parse(XMLReq.responseText);
  83. }
  84. catch(err) {
  85. alert("Unable to get reply link, can't parse server response.");
  86. return;
  87. }
  88.  
  89. if (!article.response.status) { // all responses should have this
  90. alert('Unable to get reply link, missing REST response status');
  91. }
  92. else if (article.response.status != "success") { // internal Lithium error, like no permission or deleted message
  93. errorText = article.response.error.code ? '[' + article.response.error.code + '] ' : '[unknown] ';
  94. if (article.response.error.message)
  95. errorText += article.response.error.message;
  96. alert("Can't get reply link, Lithium error:\n" + errorText);
  97. }
  98. else { // must be a success...
  99. var message = article.response.message;
  100. if (!message.board_id.$)
  101. alert("Can't get message ID for thread reply");
  102. else if (!message.board.href)
  103. alert("Can't get board ID for thread reply");
  104. else {
  105. window.location.href = window.location.protocol + '//' + window.location.hostname
  106. + '/t5/forums/replypage/board-id/'
  107. + message.board.href.split('/').pop() + '/message-id/' + message.board_id.$;
  108. }
  109. }
  110. }
  111. }
  112. };
  113.  
  114. XMLReq.send(null);
  115. }
  116.  
  117. MakeThreadReplyButton();