zing/VQ helper

A script for zings / VQ with buttons to make it easier to submit and allows keyboard shortcuts.

  1. // ==UserScript==
  2. // @name zing/VQ helper
  3. // @version 0.91
  4. // @namespace https://greasyfork.org/en/users/12083
  5. // @description A script for zings / VQ with buttons to make it easier to submit and allows keyboard shortcuts.
  6. // @author habibalex
  7. // @include http*://*ibotta.com/*
  8. // @include https://www.mturk.com/mturk/*
  9. // @grant GM_getValue
  10. // @grant GM_setValue
  11. // ==/UserScript==
  12.  
  13. // 0.9 fixed auto-submit
  14. // 0.7 based off John Ramirez (JohnnyRS) script JR zing receipt helper script
  15. // 0.6 - Added a warning when submit after option is checked. It will only warn once.
  16. // This script will hide the instructions but you can click on the instruction text to show the full
  17. // instructions again. You will see 2 buttons at the top of the receipts for easy access. If the receipts
  18. // are different then click on the first button. If they are the same then click on the second button.
  19. // Once you push a button it will fill in the bottom radio buttons and submit the hit if you checked the
  20. // checkbox called submit after. By default it will not submit after so you have to press the submit button
  21. // or press enter after the submit button gets focused. You can also use keyboard shortcuts to make it easier.
  22. // Keyboard shortcuts follow the submit after setting so be careful. Pressing n or 1 will select
  23. // the no option. Pressing y or 2 will select the yes option. Then you can press enter to submit the hit or
  24. // click the submit button if the submit after option is off.
  25. //
  26. // 0.5 - Added a setting checkbox to submit after button pressed. It is turned off by default and saved.
  27. // 0.4 - Added buttons at top. Allows keypad numbers to work. Hides the instructions at top.
  28.  
  29. var gSubmitAfter = false, gWarned = false;
  30. var gLogging = false, gDebugging = true;
  31. if (typeof console.log == 'function') gLogging = gDebugging; // Fix for browsers without console.log
  32. else gDebugging=false;
  33.  
  34. function loadSettings() {
  35. gSubmitAfter = JSON.parse(GM_getValue("JR_submitafter",gSubmitAfter));
  36. gWarned = JSON.parse(GM_getValue("JR_theWarning",gWarned));
  37. }
  38. function saveSettings() {
  39. GM_setValue("JR_submitafter",JSON.stringify(gSubmitAfter));
  40. GM_setValue("JR_theWarning",JSON.stringify(gWarned));
  41. }
  42. function createButton(theId,theValue,theName,theStyle) {
  43. var theButton = document.createElement("input");
  44. theButton.id = theId;
  45. theButton.value = theValue;
  46. theButton.type = "button";
  47. if (theName) theButton.name = theName;
  48. if (theStyle) theButton.setAttribute("style",theStyle);
  49. return theButton;
  50. }
  51. function createCheckbox(theId,theValue,theName,theStyle) {
  52. var theCheckbox = document.createElement("input");
  53. theCheckbox.id = theId;
  54. theCheckbox.value = theValue;
  55. theCheckbox.type = "checkbox";
  56. if (theName) theCheckbox.name = theName;
  57. if (theStyle) theCheckbox.setAttribute("style",theStyle);
  58. return theCheckbox;
  59. }
  60. function createMyElement(theElement,theClass,theId,theStyle) {
  61. var theElement = document.createElement(theElement);
  62. if (theId) theElement.id = theId;
  63. if (theClass) theElement.className = theClass;
  64. if (theStyle) theElement.setAttribute("style",theStyle);
  65. return theElement;
  66. }
  67. function searchInnerText(node,theText) {
  68. return node.innerHTML.indexOf(theText);
  69. }
  70. function searchInClass(theClass,theIndex,theText) {
  71. var classNode = document.getElementsByClassName(theClass)[theIndex];
  72. if (typeof classNode !== 'undefined') {
  73. var retVal = searchInnerText(classNode,theText);
  74. return (retVal!=-1) ? classNode.innerHTML.substr(retVal) : retVal;
  75. }
  76. }
  77. function toggleInstructions(theDiv) {
  78. arguments.callee.hiddenToggle = arguments.callee.hiddenToggle || false;
  79. arguments.callee.hiddenToggle = !arguments.callee.hiddenToggle;
  80. theDiv.style.overflow="hidden";
  81. if (arguments.callee.hiddenToggle) {
  82. theDiv.style.height="25px";
  83. } else {
  84. theDiv.style.height="auto";
  85. }
  86. }
  87. function moveInDiv(theNode,nodeNumbers) {
  88. var removedNode = null;
  89. var myDiv = createMyElement("div","theInstructions");
  90. var myH1 = createMyElement("h1","toggleMe");
  91. myH1.appendChild(document.createTextNode("Click here to show/hide instructions!"));
  92. myH1.setAttribute("style","color:blue;");
  93. myDiv.appendChild(myH1);
  94. for (var i=0; i<nodeNumbers+1; i++) {
  95. removedNode = theNode.removeChild(theNode.children[0]);
  96. myDiv.appendChild(removedNode);
  97. }
  98. return myDiv;
  99. }
  100. function answerRadio(theRadio,submitButton,submitMe) {
  101. window.scrollTo(0,document.body.scrollHeight +20);
  102. theRadio.checked=true;
  103. if (submitMe) submitButton.click(); // Only when one of my buttons are pressed.
  104. else submitButton.focus(); // Only gives focus to the submit button and will not auto submit it for pressing keys.
  105. }
  106.  
  107. function answerRadio2(theRadio,theTextBox){
  108. theRadio.checked=true;
  109. theTextBox.focus();
  110. setTimeout(function(){ theTextBox.value = ""; }, 200);
  111. }
  112.  
  113. if (searchInClass("warning",0,"ATTENTION: We are actively monitoring quality. Workers who repeatedly ignore the instructions")) {
  114. var h1Name = document.getElementsByClassName("container-fluid");
  115. if(h1Name.length > 0 && document.getElementsByClassName("container-fluid")[0].childNodes[1].textContent == "Does this receipt contain the following products?"){
  116. console.log('got here');
  117. var theRadio = document.getElementById("receiptvalid");
  118. var theTextBox = document.getElementById("receipt_moderation_total");
  119. document.onkeydown = function (e) {
  120. if (e.keyCode == 192) { // ` character
  121. answerRadio2(theRadio,theTextBox);
  122. }
  123. };
  124. }else{
  125. if (gDebugging && gLogging) console.log(".found a zing I can work with");
  126.  
  127. var container = document.getElementsByClassName("container")[1];
  128. var instructions = moveInDiv(container,5);
  129. container.insertBefore(instructions,container.firstChild);
  130.  
  131. var noDuplicates = document.getElementById("duplicatefalse");
  132. var yesDuplicates = document.getElementById("duplicatetrue");
  133. var submitButton = document.getElementsByClassName("submitctrl")[0].getElementsByClassName("btn")[0];
  134.  
  135. var receipts = document.getElementsByClassName("row")[1];
  136. var liNodes = document.getElementsByTagName("li");
  137. var noBtn = createButton("noButton","No - DIFFERENT receipts (n) (1)","","margin-left: 25px; padding: 2px 40px;")
  138. var yesBtn = createButton("yesButton","Yes - Same receipts (y) (2)","","margin-left: 25px; padding: 2px 40px;")
  139. noBtn.onclick = function() { answerRadio(noDuplicates,submitButton,gSubmitAfter); };
  140. yesBtn.onclick = function() { answerRadio(yesDuplicates,submitButton,gSubmitAfter); };
  141.  
  142. var myDiv = createMyElement("div","row","","padding:10px 0 20px 0; text-align:center;");
  143. var myCheckbox = createCheckbox("mySubmitAfter","Submit After","mySubmitAfter","margin:0 5px 0 20px;");
  144. myDiv.appendChild(noBtn);
  145. myDiv.appendChild(yesBtn);
  146. myDiv.appendChild(myCheckbox);
  147. myDiv.appendChild(document.createTextNode('Submit after'));
  148. receipts.parentNode.insertBefore(myDiv, receipts);
  149.  
  150. var theDivInstructions = document.getElementsByClassName("theInstructions")[0];
  151. toggleInstructions(theDivInstructions);
  152. theDivInstructions.onclick = function() { toggleInstructions(theDivInstructions); };
  153.  
  154. loadSettings();
  155. myCheckbox.checked = gSubmitAfter;
  156. myCheckbox.onchange = function() {
  157. if (myCheckbox.checked) {
  158. var gConfirmed = true;
  159. if (!gWarned) var gConfirmed = confirm("Warning: This option will submit the hit after pressing a button or using a keyboard shortcut. Be careful.\nYou can turn this option off at any time to verify your answer is correct. This is your only warning.");
  160. if (gConfirmed) { gSubmitAfter = true; gWarned = true; }
  161. else myCheckbox.checked = false;
  162. } else gSubmitAfter = false;
  163. saveSettings();
  164. }
  165.  
  166. document.onkeydown = function (e) {
  167. if (e.keyCode == 78 || e.keyCode == 49 || e.keyCode == 97) { // n=(78) or 1=(49)(97) pressed
  168. answerRadio(noDuplicates,submitButton,gSubmitAfter);
  169. } else if (e.keyCode == 89 || e.keyCode == 50 || e.keyCode == 98) { // y=(89) or 2=(50)(98) pressed
  170. answerRadio(yesDuplicates,submitButton,gSubmitAfter);
  171. }
  172. };
  173. }
  174. }else{
  175. var reqId = document.getElementById('requester.tooltip')
  176. var reqName = reqId.parentNode.nextElementSibling.textContent.trim()
  177. if(reqName == 'Venue Quality'){
  178. var hitWrap = document.getElementById('hit-wrapper');
  179. var task = hitWrap.getElementsByClassName('question-wrapper')
  180. var noBtn = createButton("noButton","No - DIFFERENT (n) (1)","","margin-left: 25px; padding: 2px 40px;")
  181. var yesBtn = createButton("yesButton","Yes - Same (y) (2)","","margin-left: 25px; padding: 2px 40px;")
  182. var showInstr = createButton("showInstr","Show Instructions","","margin-left: 25px; padding: 2px 40px;")
  183. var submitButton = document.getElementsByName("/submit")[0];
  184.  
  185. debugger;var radios = hitWrap.getElementsByClassName("question selection");
  186. var noDuplicates = radios[1];
  187. var yesDuplicates = radios[0];
  188.  
  189. noBtn.onclick = function() { answerRadio(noDuplicates,submitButton,gSubmitAfter); };
  190. yesBtn.onclick = function() { answerRadio(yesDuplicates,submitButton,gSubmitAfter); };
  191.  
  192. var theDivInstructions = hitWrap.getElementsByClassName("overview-wrapper")[0];
  193.  
  194.  
  195.  
  196.  
  197. showInstr.onclick = function (){
  198. if(theDivInstructions.style.display == '') theDivInstructions.style.display = 'none';
  199. else theDivInstructions.style.display = '';
  200. }
  201.  
  202.  
  203. var myDiv = createMyElement("div","row","","padding:10px 0 20px 0; text-align:center;");
  204. var myCheckbox = createCheckbox("mySubmitAfter","Submit After","mySubmitAfter","margin:0 5px 0 20px;");
  205. myDiv.appendChild(noBtn);
  206. myDiv.appendChild(yesBtn);
  207. myDiv.appendChild(myCheckbox);
  208.  
  209. myDiv.appendChild(document.createTextNode('Submit after'));
  210.  
  211. myDiv.appendChild(showInstr);
  212. task[0].parentNode.insertBefore(myDiv,task[0])
  213.  
  214.  
  215.  
  216. theDivInstructions.style.display = 'none';
  217. loadSettings();
  218. myCheckbox.checked = gSubmitAfter;
  219. myCheckbox.onchange = function() {
  220. if (myCheckbox.checked) {
  221. var gConfirmed = true;
  222. if (!gWarned) var gConfirmed = confirm("Warning: This option will submit the hit after pressing a button or using a keyboard shortcut. Be careful.\nYou can turn this option off at any time to verify your answer is correct. This is your only warning.");
  223. if (gConfirmed) { gSubmitAfter = true; gWarned = true; }
  224. else myCheckbox.checked = false;
  225. } else gSubmitAfter = false;
  226. saveSettings();
  227. }
  228. document.onkeydown = function (e) {
  229. if (e.keyCode == 78 || e.keyCode == 49 || e.keyCode == 97) { // n=(78) or 1=(49)(97) pressed
  230. answerRadio(noDuplicates,submitButton,gSubmitAfter);
  231. } else if (e.keyCode == 89 || e.keyCode == 50 || e.keyCode == 98) { // y=(89) or 2=(50)(98) pressed
  232. answerRadio(yesDuplicates,submitButton,gSubmitAfter);
  233. }
  234. };
  235.  
  236.  
  237. }
  238. }