4chan embedded quote fixer

Puts embedded quotes in end of post rather than beginning when inlining on click

Ajankohdalta 14.11.2018. Katso uusin versio.

  1. // ==UserScript==
  2. // @name 4chan embedded quote fixer
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description Puts embedded quotes in end of post rather than beginning when inlining on click
  6. // @author You
  7. // @match http://boards.4chan.org/*/thread/*
  8. // @match https://boards.4chan.org/*/thread/*
  9. // @grant none
  10. // ==/UserScript==
  11. //window.onload(function() {
  12. setTimeout(function() {
  13. let quotesList = Array.from(document.getElementsByClassName("quotelink")).filter(node => window.getComputedStyle(node).getPropertyValue("font-size") === "10.6667px");
  14.  
  15. //add preview inlined to class of embedded quote, wrap whole thing in mutation observer
  16. //on click, add html, gray out link (add linkfade to classlist)
  17. //on another click, find embedded post 1 layer deep, remove(), and then change link back to normal
  18.  
  19. quotesList.forEach(node => {
  20. node.addEventListener("click", qEV);
  21. });
  22.  
  23. Array.from(document.getElementsByTagName("span")).filter(el => {
  24. try {
  25. if (el.children.length > 0 && el.children[0].classList.contains("quotelink")) return true;
  26. } catch(error) {
  27. //console.log("custom error in span EL", el);
  28. return false;
  29. }
  30. }).forEach(el => el.addEventListener("click", qSpanClick));
  31.  
  32. addRemoveCapability();
  33. }, 5500);
  34. //});
  35.  
  36.  
  37. function qSpanClick(e) {
  38. e.preventDefault();
  39. }
  40.  
  41. function addRemoveCapability() {
  42. //turns all delete checkboxes to simply post removal buttons
  43. Array.from(document.getElementsByClassName("postInfo desktop")).forEach(el => el.children[0].addEventListener("click", postRemove));
  44. }
  45.  
  46. function postRemove(e) {
  47. e.preventDefault();
  48. e.target.parentNode.parentNode.parentNode.remove();
  49. }
  50.  
  51. function qEV(e, node=e.target) {
  52. //console.log("quote clicked.");
  53. e.preventDefault();
  54.  
  55. if (!node.classList.contains("linkfade")) {
  56. //if not grayed out, first time clicking, adding node
  57. node.classList.add("linkfade");
  58.  
  59. //finding post and constructing new post
  60. let postsArr = Array.from(document.getElementsByClassName("postNum desktop")).filter(el => el.children[1].innerText === node.innerText.slice(2));
  61. //console.log("postsAArr", postsArr);
  62. let post = postsArr[0].parentNode.parentNode.parentNode;
  63. //console.log("particular post from postArr", post.outerHTML);
  64. let newPost = post.cloneNode(true);
  65. //newPost.outerHTML = post.outerHTML;
  66. newPost.classList.add("inlined");
  67. newPost.children[1].classList.remove("highlight");
  68. newPost.style.display = "";
  69. newPost.style.marginTop = "10px";
  70. newPost.children[1].style.border = "1px solid #a1b7c899";
  71. newPost.children[0].style.display = "none";
  72. //console.log("newPost before adding", newPost.outerHTML, "oldPost", post.outerHTML, "boolean", newPost.outerHTML === post.outerHTML);
  73.  
  74. //adding to parent post
  75. if (node.parentNode.parentNode.parentNode.parentNode.children[2].classList.contains("file")) {
  76. node.parentNode.parentNode.parentNode.parentNode.children[3].appendChild(newPost);
  77. setTimeout(function() {node.parentNode.parentNode.parentNode.parentNode.children[3].children[0].remove();});
  78. } else {
  79. node.parentNode.parentNode.parentNode.parentNode.children[2].appendChild(newPost);
  80. setTimeout(function() {node.parentNode.parentNode.parentNode.parentNode.children[2].children[0].remove();});
  81. }
  82. //console.log("node just added", newPost);
  83. setTimeout(function(){newPost.style.display = "";}, 50);
  84.  
  85. //resetting event listeners
  86. resetQLEV();
  87. } else {
  88. //grayed out, second time clicking, removing node
  89. node.classList.remove("linkfade");
  90. let idx = node.parentNode.parentNode.parentNode.parentNode.children[2].classList.contains("file") ? 3 : 2;
  91. Array.from(node.parentNode.parentNode.parentNode.parentNode.children[idx].children).forEach(el => {if (el.classList.contains("inlined")
  92. && node.innerText.slice(2) === el.children[1].children[1].children[3].children[1].innerText) el.remove();});
  93. }
  94. }
  95.  
  96. function resetQLEV() {
  97. let newQuotesList = Array.from(document.getElementsByClassName("quotelink")).filter(node => window.getComputedStyle(node).getPropertyValue("font-size") === "10.6667px");
  98. newQuotesList.forEach(node => node.removeEventListener("click", qEV));
  99. newQuotesList.forEach(node => node.addEventListener("click", qEV));
  100. let newSpanList = Array.from(document.getElementsByTagName("span")).filter(el => {
  101. try {
  102. if (el.children.length > 0 && el.children[0].classList.contains("quotelink")) return true;
  103. } catch(error) {
  104. //console.log("custom error in span EL", el);
  105. return false;
  106. }
  107. });
  108. newSpanList.forEach(el => el.removeEventListener("click", qSpanClick));
  109. newSpanList.forEach(el => el.addEventListener("click", qSpanClick));
  110. Array.from(document.getElementsByClassName("postInfo desktop")).forEach(el => el.children[0].removeEventListener("click", postRemove));
  111. addRemoveCapability();
  112. }
  113.  
  114. let observer = new MutationObserver(resetQLEV);
  115. observer.observe(document.getElementsByClassName("thread")[0], {childList: true});