Linkify plain-text GIDs, web+panda:// fallbacks everywhere.

Latest update: No more middle-click listeners.

目前为 2018-02-01 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Linkify plain-text GIDs, web+panda:// fallbacks everywhere.
  3. // @namespace salembeats
  4. // @version 12.2
  5. // @description Latest update: No more middle-click listeners.
  6. // @author Cuyler Stuwe (salembeats)
  7. // @include *
  8. // @exclude *hitnotifier.com*
  9. // @exclude *pandacrazy*
  10. // @exclude *hit_forker*
  11. // @exclude *google.com*
  12. // @exclude *worker.mturk.com*handle*
  13. // @exclude *codepen.io*
  14. // @exclude https://worker.mturk.com/tasks
  15. // @exclude https://worker.mturk.com/projects/*/tasks*
  16. // @grant none
  17. // ==/UserScript==
  18.  
  19. const blacklistedLandingURLPatternsForFallbacks = [
  20. "turkerhub.com",
  21. "mturkcrowd.com",
  22. "turkernation.com",
  23. "overwatch",
  24. "pandacrazy"
  25. ];
  26.  
  27. var landingPage;
  28. var isBlacklistedForFallbacks;
  29.  
  30. const MIDDLE_BUTTON_CODE = 1;
  31.  
  32. const WINDOW_WIDTH = 520;
  33. const WINDOW_HEIGHT = 350;
  34.  
  35. const SHOULD_LINKIFY_FOUND_GIDS = true;
  36. const SHOULD_ADD_WP_GID_TO_ACCEPT_AND_PREVIEW_LINKS = true;
  37.  
  38. var mutationObserver = new MutationObserver(function(mutations) {
  39. for(let mutation of mutations) {
  40.  
  41. if(mutation.addedNodes.length > 0) {
  42. let addedNode = mutation.addedNodes[0];
  43.  
  44. if(!isBlacklistedForFallbacks &&
  45. addedNode.querySelector &&
  46. addedNode.querySelector("a[href*='worker.mturk.com/projects/']")) {
  47.  
  48. if(SHOULD_ADD_WP_GID_TO_ACCEPT_AND_PREVIEW_LINKS) {
  49. addWebPandaLinksNextToAllElementsUnder(addedNode);
  50. }
  51. }
  52.  
  53. if(addedNode.className && addedNode.className.includes("original-plus-linkified-content")) {
  54. }
  55. else {
  56. if(SHOULD_LINKIFY_FOUND_GIDS) {
  57. linkifyPlainTextGIDsUnder(addedNode);
  58. }
  59. }
  60. }
  61. }
  62. });
  63.  
  64.  
  65. function textNodesUnder(el) {
  66. var n, a=[], walk=document.createTreeWalker(el,NodeFilter.SHOW_TEXT,null,false);
  67. while(n=walk.nextNode()) a.push(n);
  68. return a;
  69. }
  70.  
  71. function linkifyPlainTextGIDsUnder(el) {
  72. let allTextNodes = textNodesUnder(el);
  73.  
  74. allTextNodes.forEach(textNode => {
  75. let trimmedText = textNode.data.trim();
  76. let regexMatch = trimmedText.match(/\b3(?:[A-Z0-9]){29}\b/);
  77. if(regexMatch) {
  78. let linkElement = document.createElement("template");
  79. linkElement.innerHTML = `<span class="original-plus-linkified-content">${trimmedText.replace(regexMatch[0], `<a href="web+panda://${regexMatch[0]}" class="linkified-plain-text-web-panda">${regexMatch[0]}</a> <span style="font-size: 0.7em; vertical-align: super;"><em>(Linkified GID)</em></span>`)}</span>`;
  80. if(!textNode.parentElement || textNode.parentElement.nodeName !== "A") {
  81. textNode.replaceWith(linkElement.content.firstChild);
  82. }
  83. }
  84. });
  85. }
  86.  
  87. function addWebPandaLinkNextTo(anchorElement) {
  88.  
  89. if(!anchorElement.href.includes("worker.mturk.com")) {
  90. return;
  91. }
  92. else if(anchorElement.href.includes("projects/") &&
  93. !anchorElement.href.endsWith("projects/")) {
  94.  
  95. let gid = (anchorElement.href.match(/projects\/([^/?&]+)/) || ["", ""])[1];
  96.  
  97. if(anchorElement.href.includes("accept_random")) {
  98. }
  99. else {
  100. }
  101.  
  102. let webPandaLink = `web+panda://${gid}`;
  103.  
  104. let newHTML = ` <span style="font-size: 0.7em; vertical-align: super;"><a href="${webPandaLink}" class="wp-gid-superscript" style="color: purple;">w+p://GID</a></span>`;
  105.  
  106. anchorElement.insertAdjacentHTML("afterend", newHTML);
  107. }
  108. }
  109.  
  110. function addWebPandaLinksNextToAllElementsUnder(element = document.body) {
  111. let mTurkWorkerHITLinks = element.querySelectorAll("a[href*='worker.mturk.com/projects/']");
  112.  
  113. for(let hitLink of mTurkWorkerHITLinks) {
  114. addWebPandaLinkNextTo(hitLink);
  115. }
  116. }
  117.  
  118. function processLinkClickEvent(event) {
  119.  
  120. let pandaQuery;
  121.  
  122. if(event.target.href.includes("hit_id=")) {
  123. pandaQuery = event.target.href.match(/hit_id=([^&/?]+)/)[1];
  124. }
  125. else if(event.target.href.includes("/accept_random") ||
  126. event.target.href.includes("worker.mturk.com/projects/")) {
  127. pandaQuery = event.target.href.match(/3[A-Za-z0-9]{29}/)[0].toUpperCase();
  128. }
  129. else if(event.target.href.startsWith("web+panda://") &&
  130. event.target.classList &&
  131. (event.target.classList.contains("linkified-plain-text-web-panda") || event.target.classList.contains("wp-gid-superscript"))) {
  132. pandaQuery = event.target.href;
  133. }
  134.  
  135. if(pandaQuery) {
  136. event.preventDefault();
  137. event.stopPropagation();
  138. event.stopImmediatePropagation();
  139.  
  140. let toOpen = `web+panda://${pandaQuery}?${event.shiftKey ? "once=true&" : ""}contextURL=${encodeURIComponent(window.location.href)}`;
  141. window.open(toOpen, undefined, (!event.shiftKey ? `width=${WINDOW_WIDTH},height=${WINDOW_HEIGHT},left=${screen.width/2 - WINDOW_WIDTH/2},top=${screen.height/2 - WINDOW_HEIGHT/2}` : ""));
  142. }
  143.  
  144. }
  145.  
  146. function main() {
  147.  
  148. landingPage = window.location.href;
  149.  
  150. for (let blacklistedURLPattern of blacklistedLandingURLPatternsForFallbacks) {
  151. if(landingPage.includes(blacklistedURLPattern)) {
  152. isBlacklistedForFallbacks = true;
  153. break;
  154. }
  155. }
  156.  
  157. if(SHOULD_LINKIFY_FOUND_GIDS) {
  158. linkifyPlainTextGIDsUnder(document.body);
  159. }
  160.  
  161. if(!isBlacklistedForFallbacks && SHOULD_ADD_WP_GID_TO_ACCEPT_AND_PREVIEW_LINKS) {
  162. addWebPandaLinksNextToAllElementsUnder(document.body);
  163. }
  164.  
  165. document.body.addEventListener("click", function(event) {
  166. if(event.target.tagName === "A") {
  167. processLinkClickEvent(event);
  168. }
  169. });
  170.  
  171. mutationObserver.observe(document.body, {childList: true, subtree: true});
  172. }
  173.  
  174. main();