JR Mturk Panda Crazy Queue Helper

A script add on for Panda Crazy for displaying queue and sorting queue after submitting hits.

目前为 2017-04-08 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name JR Mturk Panda Crazy Queue Helper
  3. // @version 0.3.2
  4. // @namespace https://greasyfork.org/users/6406
  5. // @description A script add on for Panda Crazy for displaying queue and sorting queue after submitting hits.
  6. // @include http*://*mturk.com/mturk/myhits*
  7. // @include http*://*mturk.com/mturk/findhits*
  8. // @include http*://*mturk.com/mturk/sorthits*
  9. // @include http*://*mturk.com/mturk/sortmyhits*
  10. // @include http*://*mturk.com/mturk/viewhits*
  11. // @include http*://*mturk.com/mturk/continue*
  12. // @include http*://*mturk.com/mturk/accept*
  13. // @include http*://*mturk.com/mturk/previewandaccept*
  14. // @include http*://*mturk.com/mturk/submit
  15. // @include http*://*mturk.com/mturk/return*
  16. // @include http*://*mturk.com/mturk/*searchbar*
  17. // @include http*://*mturk.com/mturk/return?requesterId=*
  18. // @include http*://*mturk.com/mturk/preview?*&prevsubmithitId=*
  19. // @exclude http*://*mturk.com/mturk/findhits?*hit_scraper*
  20. // @require http://code.jquery.com/jquery-2.1.4.min.js
  21. // @grant GM_xmlhttpRequest
  22. // @grant GM_getValue
  23. // @grant GM_setValue
  24. // ==/UserScript==
  25.  
  26. var gScriptVersion="0.3.2", gQueueHelperFormat2 = true;
  27. var gScriptName="pandacrazy";
  28. var gLocation=window.location.href;
  29. var gPandaCrazyLives=false, gHitExternalNextLink="", gHitExternalNextAcceptLink="", gTitle="";
  30. var gPandaCrazyVersion=-1, gHitReturnLink="", gThisJob=null, gNoHits=false, gButtonSet=false;
  31. var gQueueData=null, gPE=0, gTabTextMode=0, gTabTextTimer=0, gOriginalTitle=document.title, gCurrentPostion = 0, gQueueNextHit=null;
  32. var gSubmitHitID="", gReturnedHitID=""; // previous hitID submitted or returned just to be sure it doesn't get redone.
  33. var gCorrectVersion=false, gFirstChange=false, gQueueSessOptions=null, gSubmitButton=null, gHitId=null, gIdNum=-1, gTabHitIds={};
  34. var gThisTarget=(new Date().getTime()) + "_JRID"; // target ID from the time to distinguish different scripts and tabs.
  35. var gThisId=-1; // ID number to represent the id in the Panda Crazy external data number ID just for separating messages.
  36. var gQueueSessOptionsDef={"nextPosition":"--","nextIsLast":false,"nextIsSame":false,"tabNum":-1};
  37. var gQueueLocalOptionsDef={"displayTabTitleQ":true,"displayTabTitleTime":true,"displayTabTitleName":true,"displayTabTitleToggle":false,"toggleTime":4000};
  38. var jobDataDefault={"requesterName":"","requesterId":"","groupId":"","pay":"","title":"","duration":"0","hitsAvailable":0,"timeLeft":"","totalSeconds":0,"hitId":"","qual":"",
  39. "continueURL":"","returnURL":"","durationParsed":{},"jobNumber":"-1","friendlyRName":"","friendlyTitle":"","assignedOn":"","description":"","keywords":"","timeData":{}};
  40.  
  41. function formatAMPM(theFormat,theDate,theTimeZone) {
  42. var d = (theDate) ? theDate : new Date();
  43. if (theTimeZone == "mturk") {
  44. var mturkTZOffset = -8, today = new Date(); if (today.dst()) mturkTZOffset++;
  45. var utc = d.getTime() + (d.getTimezoneOffset() * 60000), MturkTime = utc + (3600000 * mturkTZOffset);
  46. d = new Date(MturkTime);
  47. }
  48. var minutes = d.getMinutes().toString().length == 1 ? '0'+d.getMinutes() : d.getMinutes(),
  49. hours = d.getHours(), ampm = hours >= 12 ? 'pm' : 'am',
  50. months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'], days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
  51. hours = (hours>= 12) ? (hours-12) : hours;
  52. hours = (hours.toString().length == 1) ? '0'+hours : hours;
  53. if (theFormat=="short") return ('0' + (d.getMonth()+1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + d.getFullYear() + '(' + hours + ':' + minutes + ampm + ')';
  54. else if (theFormat=="dayandtime") return days[d.getDay()] + ' ' + hours + ':' + minutes + ampm;
  55. else if (theFormat=="onlydate") return ('0' + (d.getMonth()+1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + d.getFullYear();
  56. else return days[d.getDay()]+' '+months[d.getMonth()]+' '+d.getDate()+' '+d.getFullYear()+' '+hours+':'+minutes+ampm;
  57. }
  58. function formatTimeZone(theFormat,theDate,theTimeZone) { return formatAMPM(theFormat,theDate,theTimeZone); }
  59. function getTimeLeft(theTime) {
  60. if (theTime!==null && theTime!=="") {
  61. var tempArray = (theTime.indexOf("second") != -1) ? theTime.split("second")[0].trim().split(" ") : null;
  62. var seconds = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
  63. tempArray = (theTime.indexOf("minute") != -1) ? theTime.split("minute")[0].trim().split(" ") : null;
  64. var minutes = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
  65. tempArray = (theTime.indexOf("hour") != -1) ? theTime.split("hour")[0].trim().split(" ") : null;
  66. var hours = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
  67. tempArray = (theTime.indexOf("day") != -1) ? theTime.split("day")[0].trim().split(" ") : null;
  68. var days = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
  69. tempArray = (theTime.indexOf("week") != -1) ? theTime.split("week")[0].trim().split(" ") : null;
  70. var weeks = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
  71. return( {"weeks":weeks,"days":days,"hours":hours,"minutes":minutes,"seconds":seconds} );
  72. } else return null;
  73. }
  74. function formatTimeLeft(resetNow,thisDigit,timeString,lastDigit) {
  75. formatTimeLeft.timeFill = formatTimeLeft.timeFill || 0;
  76. if (resetNow) formatTimeLeft.timeFill = 0;
  77. var missingDigit = (lastDigit!="0" && thisDigit=="0") ? true : false;
  78. if (( thisDigit!="0" || missingDigit) && formatTimeLeft.timeFill<2) {
  79. formatTimeLeft.timeFill++;
  80. if (missingDigit) { return "00 " + timeString + "s"; }
  81. else {
  82. var addZero = (thisDigit<10) ? ((formatTimeLeft.timeFill==1) ? false : true) : false, plural = (thisDigit==1) ? false : true;
  83. return ((addZero) ? "0" : "") + thisDigit + " " + ((plural) ? (timeString+"s") : timeString) + " ";
  84. }
  85. } else return "";
  86. }
  87. function convertToTimeString(timeData) {
  88. var returnString = "";
  89. returnString += formatTimeLeft(true,timeData.weeks,"week","0"); returnString += formatTimeLeft(false,timeData.days,"day",timeData.weeks);
  90. returnString += formatTimeLeft(false,timeData.hours,"hour",timeData.days); returnString += formatTimeLeft(false,timeData.minutes,"minute",timeData.hours);
  91. returnString += formatTimeLeft(false,timeData.seconds,"second",timeData.minutes);
  92. return returnString.trim();
  93. }
  94. function convertTimeToSeconds(timeData) {
  95. var totalSeconds = timeData.seconds + ((timeData.minutes) ? (timeData.minutes*60) : 0) + ((timeData.hours) ? (timeData.hours*3600) : 0) +
  96. ((timeData.days) ? (timeData.days*86400) : 0) + ((timeData.weeks) ? (timeData.weeks*604800) : 0);
  97. return totalSeconds;
  98. }
  99. function convertSecondsToTimeData(seconds) {
  100. var timeData = {};
  101. timeData.weeks = Math.floor(seconds/604800); seconds = seconds - (timeData.weeks*604800);
  102. timeData.days = Math.floor(seconds/86400); seconds = seconds - (timeData.days*86400);
  103. timeData.hours = Math.floor(seconds/3600); seconds = seconds - (timeData.hours*3600);
  104. timeData.minutes = Math.floor(seconds/60); seconds = seconds - (timeData.minutes*60);
  105. timeData.seconds = seconds;
  106. return timeData;
  107. }
  108. function continueLink(theHitId) { return "https://www.mturk.com/mturk/continue?hitId=" + theHitId; }
  109. function returnLink(theHitId) { return "https://www.mturk.com/mturk/return?hitId=" + theHitId + "&inPipeline=false"; }
  110. function convertToSeconds(milliseconds,fixed) { fixed = fixed || 2; var seconds = parseFloat((milliseconds/1000.0 * 100) / 100).toFixed(fixed) + ""; return seconds.replace(/\.0*$/,""); }
  111. function convertToMilliseconds(seconds) { if (seconds) return seconds*1000 + ""; else return "0"; }
  112. function createDiv(theHtml) { var inner = (theHtml) ? theHtml : ""; return $('<div>').html(inner); }
  113. function createSpan(theHtml) { var inner = (theHtml) ? theHtml : ""; return $('<span>').html(inner); }
  114. function createButton(theText) { var inner = (theText) ? theText : ""; return $('<button>').html(inner); }
  115. function createSelect(theId,theOptions) {
  116. var theSelect = $('<select>').attr({"id":theId});
  117. for (var i=0,len=theOptions.length; i<len; i++) { theSelect.append("<option value='" + theOptions[i] + "'>" + theOptions[i] + "</option>"); }
  118. return theSelect;
  119. }
  120. function createSelectNumbers(theId,first,min,max) {
  121. var buildArray = [first];
  122. for (var i=min; i<=max; i++) { buildArray.push(i); }
  123. return createSelect(theId,buildArray);
  124. }
  125. function parseVersionString (str) {
  126. var x = str.split('.');
  127. var maj = parseInt(x[0]) || 0; var min = parseInt(x[1]) || 0; var pat = parseInt(x[2]) || 0;
  128. return {"major": maj, "minor": min, "patch": pat};
  129. }
  130. (function($){ $.fn.disableSelection = function() { return this.attr('unselectable', 'on').css('user-select', 'none').on('selectstart', false); }; })(jQuery);
  131. function saveSessionData() {
  132. sessionStorage.setItem("JR_PC_QueueHelper",JSON.stringify(gQueueSessOptions));
  133. }
  134. function loadSessionData() {
  135. gQueueSessOptions = JSON.parse(sessionStorage.getItem('JR_PC_QueueHelper'));
  136. gQueueNextHit = JSON.parse(sessionStorage.getItem('JR_queueOrder_hitID',null));
  137. if (!gQueueSessOptions) {
  138. sessionStorage.setItem("JR_PC_QueueHelper",JSON.stringify(gQueueSessOptionsDef));
  139. gQueueSessOptions = JSON.parse(sessionStorage.getItem('JR_PC_QueueHelper'));
  140. }
  141. }
  142. function checkVersion(greaterThanVersion,newVersion) { // Check if newVersion is GREATER than the greaterThanVersion
  143. var greaterThanVersionObj = parseVersionString(greaterThanVersion), newVersionObj = parseVersionString(newVersion);
  144. if (newVersionObj.major > greaterThanVersionObj.major ) return true;
  145. else if (greaterThanVersionObj.major==newVersionObj.major) {
  146. if (newVersionObj.minor > greaterThanVersionObj.minor) return true;
  147. else if (greaterThanVersionObj.minor==newVersionObj.minor && newVersionObj.patch > greaterThanVersionObj.patch) return true;
  148. }
  149. return false;
  150. }
  151. function checkMode() {
  152. if (gLocation.indexOf("mturk/myhits?JRPC=nexthit") != -1) return "queuePageNextStart";
  153. else if (gLocation.indexOf("mturk/sortmyhits?JRPC=nexthit") != -1) return "queuePageNextStart";
  154. else if (gLocation.indexOf("mturk/sortmyhits?") != -1) return "queuePageStart";
  155. else if (gLocation.indexOf("mturk/myhits") != -1) return "queuePageStart";
  156. else if (gLocation.indexOf("mturk/continue") != -1) return "hitPage";
  157. else if (gLocation.indexOf("mturk/accept") != -1 && gLocation.indexOf("&prevHitSubmitted=") != -1) return "accepted";
  158. else if (gLocation.indexOf("mturk/previewandaccept") != -1) return "accepted";
  159. else if (gLocation.indexOf("mturk/preview") != -1) return "previewPage";
  160. else if (gLocation.indexOf("mturk/submit") != -1) return "submitPage";
  161. else if (gLocation.indexOf("mturk/return") != -1) return "returnPage";
  162. return null;
  163. }
  164. function getTimeLeft(theTime) {
  165. if (theTime) {
  166. var tempArray = (theTime.indexOf("second") != -1) ? theTime.split("second")[0].trim().split(" ") : null;
  167. var seconds = (tempArray) ? tempArray[tempArray.length-1] : "0";
  168. tempArray = (theTime.indexOf("minute") != -1) ? theTime.split("minute")[0].trim().split(" ") : null;
  169. var minutes = (tempArray) ? tempArray[tempArray.length-1] : "0";
  170. tempArray = (theTime.indexOf("hour") != -1) ? theTime.split("hour")[0].trim().split(" ") : null;
  171. var hours = (tempArray) ? tempArray[tempArray.length-1] : "0";
  172. tempArray = (theTime.indexOf("day") != -1) ? theTime.split("day")[0].trim().split(" ") : null;
  173. var days = (tempArray) ? tempArray[tempArray.length-1] : "0";
  174. tempArray = (theTime.indexOf("week") != -1) ? theTime.split("week")[0].trim().split(" ") : null;
  175. var weeks = (tempArray) ? tempArray[tempArray.length-1] : "0";
  176. return( {"weeks":weeks,"days":days,"hours":hours,"minutes":minutes,"seconds":seconds} );
  177. } else return null;
  178. }
  179. function clearOldTabMessages() {
  180. var storageKeys = Object.keys(localStorage);
  181. for (i = 0; i < storageKeys.length; i++) {
  182. if (storageKeys[i].substring(0,14) == 'JR_message_TAB' && storageKeys[i].substr(storageKeys[i].length - gScriptName.length) == gScriptName) {
  183. localStorage.removeItem(storageKeys[i]);
  184. }
  185. }
  186. }
  187. function createMessageData(command,data,target,idNum,tabNum) { return {"time":(new Date().getTime()),"command":command,"data":data,"theTarget":target,"idNum":idNum,"tabNum":tabNum}; }
  188. function createHitData(hitId,target,idNum,prevId) { return {"hitId":hitId,"idNum":idNum,"prevId":prevId}; }
  189. function sendCommandMessage(data) { localStorage.setItem("JR_message_" + gScriptName, JSON.stringify(data)); }
  190.  
  191. function sendMessageData(command,theData) {
  192. var messageData = createMessageData(command,theData);
  193. sendCommandMessage(messageData);
  194. }
  195. function sendPingMessage(target) { localStorage.setItem("JR_message_ping_" + gScriptName, JSON.stringify(createMessageData("areYouThere",
  196. {"version":gScriptVersion,"extName":"QueueHelper"},target,null,null))); }
  197. function sendPongMessage(target,idNum) { localStorage.setItem("JR_message_pong_" + gScriptName, JSON.stringify(createMessageData("iAmHere",null,target,idNum,null))); }
  198. function sendQueuePageMessage(target,idNum) { localStorage.setItem("JR_message_" + gScriptName, JSON.stringify(createMessageData("getQueueData",null,target,idNum,null))); }
  199. function setQueueHitMessage(target,idNum,hitId,prevId) { sessionStorage.setItem("JR_queueOrder_hitID", JSON.stringify(createHitData(hitId,target,idNum,prevId))); }
  200. function sendSubmittedMessage(target,thisHitID,idNum) { localStorage.setItem("JR_message_" + gScriptName,
  201. JSON.stringify(createMessageData("submitted",{"hitId":thisHitID},target,idNum,null))); }
  202. function sendReturnedMessage(target,thisHitID,idNum) { localStorage.setItem("JR_message_" + gScriptName,
  203. JSON.stringify(createMessageData("returned",{"hitId":thisHitID},target,idNum,null))); }
  204. function sendAcceptedHitMessage(target,thisJobData,idNum) { localStorage.setItem("JR_message_" + gScriptName,
  205. JSON.stringify(createMessageData("acceptedhit",{"jobData":thisJobData},target,idNum,null))); }
  206. function sendDoingHitMessage(tabNum,target,thisHitID,mode,idNum) { localStorage.setItem("JR_message_" + mode + "_" + tabNum + "_" + gScriptName,
  207. JSON.stringify(createMessageData("doinghit",{"hitId":thisHitID},target,idNum,tabNum))); }
  208. function setSessionData() {
  209. if ($("#JRPCQAdvSel").length) gQueueSessOptions.nextPosition = $("#JRPCQAdvSel").val();
  210. if ($("#JRPCQEasySel").val()=="Last") gQueueSessOptions.nextIsLast = true; else gQueueSessOptions.nextIsLast = false;
  211. if ($("#JRPCQSameSel").val()=="No") gQueueSessOptions.nextIsSame = false; else gQueueSessOptions.nextIsSame = true;
  212. saveSessionData();
  213. }
  214. function setupOptionsMenu() {
  215. var insideContent = $("#JR_QueueOptionsMenu");
  216. createDiv("Queue Options Window").css({"font-size":"22px","text-align":"center","margin":"8px 0"}).appendTo(insideContent);
  217. var optionsArea = createDiv("").css({"font-size":"14px","text-align":"left","padding":"0 10px","margin-top":"20px"}).appendTo(insideContent);
  218. createDiv(createSpan("Go to the ").append(createSelect("JRPCQEasySel",["First","Last","--"])).append(createSpan(" hit in the queue."))).appendTo(optionsArea);
  219. createDiv(createSpan("Go to the next hit at position ").css({}).append(createSelectNumbers("JRPCQAdvSel","--",1,24)).append(createSpan(" in the queue."))).appendTo(optionsArea);
  220. createDiv(createSpan("Go to the next hit with same description? ").css({}).append(createSelect("JRPCQSameSel",["No","Yes"]))).appendTo(optionsArea);
  221. createButton("OK").css({"margin-top":"40px","margin-left":"10px"}).click(function() { toggleOptionsMenu(); }).appendTo(optionsArea);
  222. $("#JRPCQEasySel").val((gQueueSessOptions.nextPosition!="--") ? "--" : ((gQueueSessOptions.nextIsLast) ? "Last" : "First"));
  223. $("#JRPCQAdvSel").val(gQueueSessOptions.nextPosition);
  224. $("#JRPCQSameSel").val((gQueueSessOptions.nextIsSame) ? "Yes" : "No");
  225. $("#JRPCQEasySel").change(function() { if ($(this).val()!="--") $("#JRPCQAdvSel").val("--"); else $("#JRPCQAdvSel").val("1"); setSessionData(); });
  226. $("#JRPCQAdvSel").change(function() { if ($(this).val()!="--") $("#JRPCQEasySel").val("--"); else $("#JRPCQEasySel").val("First"); setSessionData(); });
  227. $("#JRPCQSameSel").change(function() { setSessionData(); });
  228. }
  229. function toggleOptionsMenu() {
  230. toggleOptionsMenu.display = toggleOptionsMenu.display || false;
  231. toggleOptionsMenu.display = !toggleOptionsMenu.display;
  232. if (toggleOptionsMenu.display) $("#JR_QueueOptionsMenu").show();
  233. else $("#JR_QueueOptionsMenu").hide();
  234. }
  235. function requestUrl(theUrl, theNumber, theFunction, errorFunction, data1, data2, theResponseType) {
  236. theResponseType = theResponseType || "";
  237. GM_xmlhttpRequest({
  238. method: "GET",
  239. url: theUrl,
  240. responseType: theResponseType,
  241. onload: function(response) { if (typeof theFunction == 'function') theFunction(response,theNumber,data1,data2); },
  242. onerror: function(response) { errorRequest(response,theNumber); }
  243. });
  244. }
  245. function grabJobData(index) {
  246. var jobData = jQuery.extend(true, {}, jobDataDefault), titleElement = $("#capsule" + index + "-0"), timeLeft = null, keywordsArray=[];
  247. if (titleElement.length) {
  248. jobData.title = $(titleElement).text().trim();
  249. var returnLinkURL = $(titleElement).closest("tr").find("a:contains('Return this HIT'):first");
  250. jobData.returnURL = (returnLinkURL.length) ? "https://www.mturk.com" + $(returnLinkURL).attr("href") : "";
  251. var continueLinkURL = $(titleElement).closest("tr").find("a:contains('Continue work on this HIT'):first");
  252. jobData.continueURL = (continueLinkURL.length) ? "https://www.mturk.com" + $(continueLinkURL).attr("href") : "";
  253. jobData.hitId = (jobData.continueURL!=="") ? jobData.continueURL.split("hitId=")[1] : "";
  254. var requesterElement = $(".requesterIdentity:first");
  255. jobData.requesterName = (requesterElement.length) ? $(requesterElement).text().trim() : "";
  256. var contactRequesterUrl = $("#capsule" + index + "target").find("a:contains('Contact the Requester of this HIT'):first");
  257. jobData.requesterId = (contactRequesterUrl.length) ? $(contactRequesterUrl).attr("href").split("requesterId=")[1].split("&")[0] : "";
  258. var durationToComplete = $("#duration_to_complete\\.tooltip--" + index);
  259. jobData.duration = (durationToComplete.length) ? $(durationToComplete).closest("tr").find(".capsule_field_text").text().trim() : "";
  260. jobData.durationParsed = getTimeLeft(jobData.duration);
  261. var description = $("#description\\.tooltip--" + index);
  262. jobData.description = (description.length) ? $(description).closest("tr").find(".capsule_field_text").text().trim() : "";
  263. var rewardElement = $("#reward\\.tooltip--" + index);
  264. jobData.pay = (rewardElement.length) ? $(rewardElement).closest("tr").find(".reward").text().replace("$","").trim() : "";
  265. } else {
  266. var capsulelinkElement = $("form[name='hitForm'] .capsulelink_bold");
  267. var tableInfo = $(capsulelinkElement).closest("table").closest("table");
  268. jobData.groupId = (gLocation.indexOf("groupId=") != -1) ? gLocation.split("groupId=")[1].split("&")[0] : "";
  269. jobData.title = $(capsulelinkElement).find("div").text().trim();
  270. jobData.hitId = $("input[name='hitId']").eq(0).val();
  271. jobData.continueURL = (jobData.hitId!=="") ? continueLink(jobData.hitId) : "";
  272. jobData.returnURL = (jobData.hitId!=="") ? returnLink(jobData.hitId) : "";
  273. jobData.requesterId = ($("input[name='requesterId']:first").val()) ? $("input[name='requesterId']:first").attr("value") : "";
  274. jobData.requesterName = $("#requester\\.tooltip").closest("tr").find(".capsule_field_text:first").text().trim();
  275. timeLeft = $("a#time_left\\.tooltip"); jobData.duration = (timeLeft.length) ? timeLeft.parent().next().html().trim() : "";
  276. jobData.duration = $("#time_left\\.tooltip").closest("td").next().text().trim();
  277. jobData.durationParsed = getTimeLeft(jobData.duration); jobData.timeData = jobData.durationParsed; jobData.timeLeft = convertToTimeString(jobData.durationParsed);
  278. jobData.totalSeconds = convertTimeToSeconds(jobData.timeData);
  279. jobData.hitsAvailable = $("#number_of_hits\\.tooltip").closest("td").next().text().trim();
  280. jobData.pay = $("#reward\\.tooltip").closest("td").next().text().replace("$","").replace(" per HIT","").trim();
  281. }
  282. return jobData;
  283. }
  284. function inOtherTabs(hitId) { var foundIt=false; $.each(gTabHitIds, function(key,value) { if (value==hitId) foundIt=true; }); return foundIt; }
  285. function doSortResultsTable(sortresultsForm) {
  286. var sortResultsTable = $(sortresultsForm).next("table"), jobDatas = [];
  287. $(sortResultsTable).find("> tbody > tr").each(function(i, row) {
  288. var returnData = grabJobData(i);
  289. if (!inOtherTabs(returnData.hitId)) jobDatas.push(returnData);
  290. });
  291. return jobDatas;
  292. }
  293. function firstOrLast(i) { return (gQueueSessOptions.nextIsLast) ? (i>0) : (i<gQueueData.length-1); }
  294. function letsFindNext() {
  295. }
  296. function findNextHitQueue(currentHitID,sameDescription) {
  297. if (!gQueueData || currentHitID === "") return null;
  298. sameDescription = sameDescription || "";
  299. var i=-1, skip=false, targetHit=null, nextPosition = (gQueueSessOptions.nextPosition=="--") ? -2 : parseInt(gQueueSessOptions.nextPosition);
  300. var getLast = (gQueueSessOptions.nextIsLast) ? true : ((nextPosition>gQueueData.length-1) ? true : false);
  301. for (j=0,len=gQueueData.length;j<len;j++) {
  302. if (gQueueData[j].hitId==currentHitID) gCurrentPostion = j+1; // find the currenthit position
  303. if (!targetHit || getLast) { // if targethit not found or looking for last hit then keep on looking for target hit!
  304. if (gQueueData[j].hitId!=currentHitID && gQueueData[j].hitId!=gSubmitHitID && gQueueData[j].hitId!=gReturnedHitID && !inOtherTabs(gQueueData[j].hitId)) {
  305. if (sameDescription==="" || gQueueData[j].title==sameDescription) targetHit = gQueueData[j];
  306. }
  307. if (!getLast && nextPosition>0 && j<nextPosition) targetHit=null;
  308. }
  309. }
  310. if (!targetHit && gQueueData.length>1 && getLast) targetHit = gQueueData[gQueueData.length-1];
  311. return targetHit;
  312. }
  313. function doYourQueue() {
  314. if (!gPandaCrazyLives) {
  315. requestUrl("https://www.mturk.com/mturk/sortmyhits?searchSpec=HITSearch%23T%231%2310%23-1%23T%23!Status!0!rO0ABXQACEFzc2lnbmVk!%23!Deadline!0!%23!&selectedSearchType=hitgroups&searchWords=&sortType=Deadline%3A0&pageSize=25",1,function(theResult,theNumber,data1,data2) {
  316. },function() { errorRequest(); } );
  317. }
  318. }
  319. function queuePageStart() {
  320. var sortresultsForm = $("#sortresults_form"), hitsText = $(sortresultsForm).prev(), lastTables = $(sortresultsForm).next().next();
  321. $(hitsText).find(".title_orange_text_bold").append(createSpan("PC Enhanced Mode").css({"font-size":"11px","padding":"1px 2px","background-color":"#FFE4C4","color":"black"}));
  322. var displayHits = $(sortresultsForm).next(), afterThis = $("#subtabs_and_searchbar");
  323. theMainContainer = createDiv().attr({"id":"JRMQContainer"}).insertAfter(afterThis);
  324. //createDiv().attr({"id":"JRNormalQueue"}).append(hitsText).append(displayHits).appendTo(theMainContainer);
  325. createDiv().attr({"id":"JRNormalQueue"}).appendTo(theMainContainer);
  326. $("#JRNormalQueue").append($(hitsText)); $("#JRNormalQueue").append($(sortresultsForm)); $("#JRNormalQueue").append($(displayHits));
  327. createDiv().attr({"id":"JREnhancedQueue1"}).appendTo(theMainContainer); createDiv().attr({"id":"JREnhancedQueue"}).appendTo(theMainContainer);
  328. if (gScriptMode=="queuePageNextStart") {
  329. gScriptMode = "queuePageNext";
  330. $("body").children("div,table").css("opacity","0.1");
  331. setTimeout(function() {
  332. var hitData = doSortResultsTable($("#sortresults_form"));
  333. if (hitData.length>0) {
  334. setTimeout(function() {
  335. window.location.replace(hitData[0].continueURL);
  336. },(!gPandaCrazyLives) ? 700 : 1);
  337. } else {
  338. $("body").children("div,table").css("opacity","1");
  339. gScriptMode = "queuePage";
  340. }
  341. },(!gPandaCrazyLives) ? 1 : 1000);
  342. } else gScriptMode = "queuePage";
  343. }
  344. function setNextHit() {
  345. var targetHit = findNextHitQueue(gHitId, (gQueueSessOptions.nextIsSame) ? gTitle : "");
  346. if (!targetHit && gQueueSessOptions.nextIsSame) targetHit = findNextHitQueue(gHitId, "");
  347. if (targetHit) {
  348. var realHitId = $("input[name='hitId']").eq(0).val();
  349. if (gHitExternalNextLink) $(gHitExternalNextLink).attr("href", targetHit.continueURL + "&prevsubmithitId=" + gHitId);
  350. var theReturnLinkHref = "https://www.mturk.com/mturk/return?hitId=" + realHitId + "&hitNextId=" + targetHit.hitId + "&inPipeline=false";
  351. setQueueHitMessage(gThisTarget,gIdNum,targetHit.hitId,gHitId);
  352. if (gHitReturnLink.length) $(gHitReturnLink).attr("href", theReturnLinkHref);
  353. } else {
  354. if (gHitExternalNextLink) {
  355. var theNextLinkHref = "/mturk/myhits?JRPC=nexthit";
  356. if (theNextLinkHref.indexOf("&prevsubmithitId=") == -1) theNextLinkHref = theNextLinkHref + "&prevsubmithitId=" + gHitId;
  357. $(gHitExternalNextLink).attr('href', theNextLinkHref );
  358. }
  359. if (gHitExternalNextAcceptLink && $(gHitExternalNextAcceptLink).attr("href").indexOf("&prevsubmithitId=") == -1) {
  360. $(gHitExternalNextAcceptLink).attr("href", gHitExternalNextAcceptLink.attr("href") + "&prevsubmithitId=" + gHitId);
  361. }
  362. }
  363. }
  364. function mainListener(e) {
  365. var returnedStorage = JSON.parse(e.newValue), messageSender=null;
  366. if (!returnedStorage) return;
  367. if (!gPandaCrazyLives) {
  368. if ( e.key.substring(0,16) == 'JR_message_pong_' && e.key.substr(e.key.length - gScriptName.length) == gScriptName && // Receiving correct message from Panda Crazy
  369. returnedStorage && returnedStorage.theTarget == gThisTarget) { // Receiving as a targeted message for first message from Panda Crazy
  370. gPandaCrazyLives = true; // We now know Panda Crazy is running.
  371. gPandaCrazyVersion = returnedStorage.version; gIdNum = returnedStorage.idNum;
  372. gQueueSessOptions.tabNum = (gQueueSessOptions.tabNum!=-1) ? gQueueSessOptions.tabNum : gIdNum;
  373. saveSessionData();
  374. gTabHitIds[gQueueSessOptions.tabNum] = gHitId;
  375. gCorrectVersion = checkVersion("0.3.7",gPandaCrazyVersion); gFirstChange = checkVersion("0.4.9",gPandaCrazyVersion);
  376. if (gScriptMode=="queuePageStart" || gScriptMode=="queuePageNextStart" || gScriptMode=="hitPage" || gScriptMode=="previewPage") sendQueuePageMessage(gThisTarget,gIdNum);
  377. }
  378. } else if (gHitId!=="" && e.key.substring(0,13) == "JR_message_D_") {
  379. messageSender = returnedStorage.tabNum;
  380. if (messageSender && messageSender!=-1) delete gTabHitIds[messageSender];
  381. setNextHit();
  382. } else if (gHitId!=="" && e.key.substring(0,13) == "JR_message_S_") {
  383. messageSender = returnedStorage.tabNum;
  384. gTabHitIds[messageSender] = returnedStorage.data.hitId;
  385. sendDoingHitMessage(gQueueSessOptions.tabNum,gThisTarget,gHitId,"R",gIdNum);
  386. setNextHit();
  387. } else if (gHitId!=="" && e.key.substring(0,13) == "JR_message_SD_") {
  388. sendDoingHitMessage(gQueueSessOptions.tabNum,gThisTarget,gHitId,"TAB",gIdNum);
  389. } else if (gHitId!=="" && (e.key.substring(0,13) == "JR_message_R_" || e.key.substring(0,15) == "JR_message_TAB_") ) {
  390. messageSender = returnedStorage.tabNum;
  391. gTabHitIds[messageSender] = returnedStorage.data.hitId;
  392. setNextHit();
  393. } else if (gCorrectVersion && returnedStorage && returnedStorage.data) { // Panda Crazy is up and running with correct version.
  394. if (e.key.substring(0,11) == 'JR_message_' && e.key.substr(e.key.length - gScriptName.length) == gScriptName && // Receiving correct message from Panda Crazy
  395. (returnedStorage.theTarget == gThisTarget || returnedStorage.theTarget===null)) { // Receiving as a targeted message or a ping message
  396. if (returnedStorage.data.queue) { gQueueData = returnedStorage.data.queue; sendDoingHitMessage(gQueueSessOptions.tabNum,gThisTarget,gHitId,"TAB",gIdNum); }
  397. if (returnedStorage.data.PE) gPE = returnedStorage.data.PE;
  398. if (returnedStorage.command=="ping") sendPongMessage(gThisTarget,gIdNum);
  399. if (gSubmitButton.length && (gScriptMode=="hitPage")) {
  400. if (!gButtonSet) {
  401. gButtonSet = true;
  402. createDiv("Q").css({"position":"fixed","width":"10px","text-align":"right","height":"20px","top":"22px","right":"2px","float":"right","padding":"0px 3px","background-color":"black","color":"white","opacity": "0.3","cursor":"pointer"}).disableSelection().click(function() { toggleOptionsMenu(); }).appendTo("body");
  403. createDiv("").css({"position":"fixed","width":"400px","height":"200px","top":"25px","right":"20px","float":"right","background-color":"#eceadf","border":"3px solid #000"}).attr({"id":"JR_QueueOptionsMenu"}).hide().appendTo("body");
  404. setupOptionsMenu();
  405. if (gHitId!=="") {
  406. sendDoingHitMessage(gQueueSessOptions.tabNum,gThisTarget,gHitId,"TAB",gIdNum);
  407. }
  408. }
  409. setNextHit();
  410. } else if (gScriptMode=="accepted" && gThisJob===null && !gNoHits) {
  411. gThisJob = grabJobData(99); sendAcceptedHitMessage(gThisTarget,gThisJob,gIdNum); setNextHit();
  412. }
  413. }
  414. }
  415. }
  416. clearOldTabMessages(); loadSessionData();
  417. gScriptMode = checkMode();
  418. var goToNext = "";
  419. if (gLocation.indexOf("&prevsubmithitId=") != -1) { // Get previous hitId from the url and send submitted message to Panda Crazy.
  420. gSubmitHitID = (gLocation.split("&prevsubmithitId=")[1]).split("&")[0]; sendSubmittedMessage(gThisTarget,gSubmitHitID,gIdNum);
  421. }
  422. else if (gLocation.indexOf("mturk.com/mturk/submit") != -1 && gQueueNextHit && gQueueNextHit.prevId) { // Get previous and next hitId from the storageSession for hits that do not have an iframe.
  423. goToNext = "https://www.mturk.com/mturk/continue?hitId=" + gQueueNextHit.hitId; sendSubmittedMessage(gThisTarget,gQueueNextHit.prevId,gIdNum);
  424. }
  425. if (gScriptMode=="returnPage") { // If on a return page then grab hitId from url and send returned message to Panda Crazy.
  426. gReturnedHitID = (gLocation.indexOf("hitId=") != -1) ? (gLocation.split("hitId=")[1]).split("&")[0] : "";
  427. sendReturnedMessage(gThisTarget,gReturnedHitID,gIdNum);
  428. }
  429. if (gScriptMode=="submitPage" || gScriptMode=="returnPage") { // if on submit page or return page get the next hit and go to that page after a second.
  430. //console.log("return page: " + gLocation);
  431. if (gLocation.indexOf("&hitNextId=") != -1) goToNext = "https://www.mturk.com/mturk/continue?hitId=" + (gLocation.split("&hitNextId=")[1]).split("&")[0];
  432. if (goToNext!=="") { $("body").html(""); setTimeout(function() { window.location.replace(goToNext); },1300); }
  433. else if (gScriptMode=="returnPage" && gLocation.indexOf("&fromQueue=true") != -1) {
  434. $("body").html(""); gScriptMode = null; setTimeout(function() { window.location.replace("https://www.mturk.com/mturk/myhits?JRPC=nexthit"); },800);
  435. }
  436. }
  437. sessionStorage.removeItem("JR_queueOrder_hitID");
  438. if (gScriptMode) {
  439. window.addEventListener("storage", mainListener, false);
  440. gHitReturnLink = $("a[href*='mturk/return']");
  441. gNoHits = ($("#alertboxMessage").length) ? ( (($("#alertboxMessage").html()).indexOf("There are no HITs in this group available") != -1) ? true : false) : false;
  442. gSubmitButton = document.getElementsByName("/submit");
  443. if (gSubmitButton.length) {
  444. gHitExternalNextLink = $("#hitExternalNextLink"); gHitExternalNextAcceptLink = $("#hitExternalNextAcceptLink");
  445. gHitExternalNextLink.attr('href',gHitExternalNextLink.attr("href").replace("&sortType=&","&"));
  446. var returnLinkNode = $("img[src='/media/return_hit.gif']").closest("a");
  447. if (gScriptMode=="hitPage") returnLinkNode.attr('href',returnLinkNode.attr('href') + "&fromQueue=true");
  448. var capsuleNode = $("td.capsulelink_bold:first div").eq(0);
  449. var hitIdNode = $("input[name='hitId']");
  450. gHitId = (hitIdNode.length>0) ? $("input[name='hitId']").eq(0).val() : "";
  451. if (gScriptMode=="queuePageStart" || gScriptMode=="queuePageNextStart") sendDoingHitMessage(gQueueSessOptions.tabNum,gThisTarget,gHitId,"SD",gIdNum);
  452. gTitle = (capsuleNode.length) ? $(capsuleNode).html().trim() : "";
  453. setInterval( function() {
  454. var theTimer = $("#theTime").text();
  455. var theTimeLeftNode = $("a#time_left\\.tooltip");
  456. var theDuration = (theTimeLeftNode.length) ? theTimeLeftNode.parent().next().html().trim() : "";
  457. var requesterTip = $("#requester\\.tooltip");
  458. var requesterNameNode = (requesterTip.length) ? $(requesterTip).closest("tr").find(".capsule_field_text:first") : null;
  459. var theRequesterName = (requesterNameNode.length) ? $(requesterNameNode).text().trim() : "";
  460. setNextHit();
  461. gTabTextTimer+=1000;
  462. if (gTabTextTimer>=4000) {
  463. gTabTextTimer=0;
  464. gTabTextMode = 1 - gTabTextMode;
  465. }
  466. if (gQueueData!==null) document.title = "( " + gCurrentPostion + "/" + gQueueData.length + " ) " + theRequesterName + " :: " + gOriginalTitle;
  467. //console.log("Next link is now: " + $(gHitExternalNextLink).attr('href'));
  468. },1000);
  469. } else if (gScriptMode=="queuePageNextStart") { setTimeout(function() { queuePageStart(); },300); }
  470. window.onbeforeunload = function() { sendDoingHitMessage(gQueueSessOptions.tabNum,gThisTarget,gHitId,"D",gIdNum); };
  471. sendPingMessage(gThisTarget);
  472. //setTimeout(function() { doYourQueue(); },1200);
  473. }