JR Mturk Panda Crazy Queue Helper

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

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        JR Mturk Panda Crazy Queue Helper
// @version     0.3.10
// @namespace   https://greasyfork.org/users/6406
// @description A script add on for Panda Crazy for displaying queue and sorting queue after submitting hits.
// @author      (JohnnyRS on mturkcrowd.com and mturkgrind.com) [email protected]
// @include     http*://worker.mturk.com/*
// @require     http://code.jquery.com/jquery-2.1.4.min.js
// @grant 		GM_xmlhttpRequest
// @grant       GM_getValue
// @grant       GM_setValue
// ==/UserScript==

var gScriptVersion="0.3.10", gQueueHelperFormat2 = true, gFromQueue = false;
var gScriptName="pandacrazy", gScriptID="PQ35";
var gLocation=window.location.href, gPrevHit="", gPrevTitle="";
var gPandaCrazyLives=false, gHitExternalNextLink="", gHitExternalNextAcceptLink="", gTitle="", gNewSite=true;
var gPandaCrazyVersion=-1, gHitReturnLink="", gThisJob=null, gNoHits=false, gButtonSet=false, gRequesterName="";
var gQueueData=[], gPE=0, gTabTextMode=0, gTabTextTimer=0, gOriginalTitle=document.title, gCurrentPostion = 0, gQueueNextHit=null;
var gSubmitHitID="", gReturnedHitID="", gGroupId=""; // previous hitID submitted or returned just to be sure it doesn't get redone.
var gCorrectVersion=false, gFirstChange=false, gQueueSessOptions=null, gSubmitButton=null, gHitId="", gIdNum=-1, gTabHitIds={}, gAssignmentId = "";
var gThisTarget=""; // target ID from the time to distinguish different scripts and tabs.
var gTabTarget={"tabId":Math.floor(new Date().getTime() / 100), "scriptID":gScriptID}; // target ID from the time to distinguish different scripts and tabs.
var gThisId=-1; // ID number to represent the id in the Panda Crazy external data number ID just for separating messages.
var gQueueSessOptionsDef={"nextPosition":"--","nextIsLast":false,"nextIsSame":false,"tabNum":-1,"nextMonitor":false};
var gQueueLocalOptionsDef={"displayTabTitleQ":true,"displayTabTitleTime":true,"displayTabTitleName":true,"displayTabTitleToggle":false,"toggleTime":4000};
var gJobDataDefault = {"requesterName":"","requesterId":"","groupId":"","pay":"","title":"","duration":"0","hitsAvailable":0,"timeLeft":"","totalSeconds":0,"hitId":"",
		"qual":"","continueURL":"","returnURL":"","durationParsed":{},"jobNumber":"-1","friendlyRName":"","friendlyTitle":"","assignedOn":"","description":"",
		"keywords":"","timeData":{},"assignmentID":"","hitSetID":"","secondsOff":-1,"goHam":false};

function speakThisNow(thisText) {
    if('speechSynthesis' in window){
        var speech = new SpeechSynthesisUtterance(thisText);
        speech.lang = 'en-US';
        window.speechSynthesis.speak(speech);
    }
}
function formatAMPM(theFormat,theDate,theTimeZone) {
    var d = (theDate) ? theDate : new Date();
    if (theTimeZone == "mturk") {
        var mturkTZOffset = -8, today = new Date(); if (today.dst()) mturkTZOffset++;
        var utc = d.getTime() + (d.getTimezoneOffset() * 60000), MturkTime = utc + (3600000 * mturkTZOffset);
        d = new Date(MturkTime);
    }
    var minutes = d.getMinutes().toString().length == 1 ? '0'+d.getMinutes() : d.getMinutes(),
        hours = d.getHours(), ampm = hours >= 12 ? 'pm' : 'am',
        months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'], days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
	hours = (hours>= 12) ? (hours-12) : hours;
	hours = (hours.toString().length == 1) ? '0'+hours : hours;
    if (theFormat=="short") return ('0' + (d.getMonth()+1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + d.getFullYear() + '(' + hours + ':' + minutes + ampm + ')';
    else if (theFormat=="dayandtime") return days[d.getDay()] + ' ' + hours + ':' + minutes + ampm;
    else if (theFormat=="onlydate") return ('0' + (d.getMonth()+1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + d.getFullYear();
    else return days[d.getDay()]+' '+months[d.getMonth()]+' '+d.getDate()+' '+d.getFullYear()+' '+hours+':'+minutes+ampm;
}
function formatTimeZone(theFormat,theDate,theTimeZone) { return formatAMPM(theFormat,theDate,theTimeZone); }
function getTimeLeft(theTime) {
    if (theTime!==null && theTime!=="") {
        var tempArray = (theTime.indexOf("second") != -1) ? theTime.split("second")[0].trim().split(" ") : null;
		var seconds = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
		tempArray = (theTime.indexOf("minute") != -1) ? theTime.split("minute")[0].trim().split(" ") : null;
		var minutes = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
		tempArray = (theTime.indexOf("hour") != -1) ? theTime.split("hour")[0].trim().split(" ") : null;
		var hours = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
		tempArray = (theTime.indexOf("day") != -1) ? theTime.split("day")[0].trim().split(" ") : null;
		var days = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
		tempArray = (theTime.indexOf("week") != -1) ? theTime.split("week")[0].trim().split(" ") : null;
		var weeks = (tempArray) ? parseInt(tempArray[tempArray.length-1]) : 0;
		return( {"weeks":weeks,"days":days,"hours":hours,"minutes":minutes,"seconds":seconds} );
    } else return null;
}
function formatTimeLeft(resetNow,thisDigit,timeString,lastDigit) {
	formatTimeLeft.timeFill = formatTimeLeft.timeFill || 0;
	if (resetNow) formatTimeLeft.timeFill = 0;
	var missingDigit = (lastDigit!="0" && thisDigit=="0") ? true : false;
	if (( thisDigit!="0" || missingDigit) && formatTimeLeft.timeFill<2) {
		formatTimeLeft.timeFill++;
		if (missingDigit) { return "00 " + timeString + "s"; }
		else {
			var addZero = (thisDigit<10) ? ((formatTimeLeft.timeFill==1) ? false : true) : false, plural = (thisDigit==1) ? false : true;
			return ((addZero) ? "0" : "") + thisDigit + " " + ((plural) ? (timeString+"s") : timeString) + " ";
		}
	} else return "";
}
function convertToTimeString(timeData) {
	var returnString = "";
	returnString += formatTimeLeft(true,timeData.weeks,"week","0"); returnString += formatTimeLeft(false,timeData.days,"day",timeData.weeks);
	returnString += formatTimeLeft(false,timeData.hours,"hour",timeData.days); returnString += formatTimeLeft(false,timeData.minutes,"minute",timeData.hours);
	returnString += formatTimeLeft(false,timeData.seconds,"second",timeData.minutes);
	return returnString.trim();
}
function convertTimeToSeconds(timeData) {
	var totalSeconds = timeData.seconds + ((timeData.minutes) ? (timeData.minutes*60) : 0) + ((timeData.hours) ? (timeData.hours*3600) : 0) +
			((timeData.days) ? (timeData.days*86400) : 0) + ((timeData.weeks) ? (timeData.weeks*604800) : 0);
	return totalSeconds;
}
function convertSecondsToTimeData(seconds) {
	var timeData = {};
	timeData.weeks = Math.floor(seconds/604800); seconds = seconds - (timeData.weeks*604800);
	timeData.days = Math.floor(seconds/86400); seconds = seconds - (timeData.days*86400);
	timeData.hours = Math.floor(seconds/3600); seconds = seconds - (timeData.hours*3600);
	timeData.minutes = Math.floor(seconds/60); seconds = seconds - (timeData.minutes*60);
	timeData.seconds = seconds;
	return timeData;
}
function continueLink(theHitId) { return "https://www.mturk.com/mturk/continue?hitId=" + theHitId; }
function returnLink(theHitId) { return "https://www.mturk.com/mturk/return?hitId=" + theHitId + "&inPipeline=false"; }
function convertToSeconds(milliseconds,fixed) { fixed = fixed || 2; var seconds = parseFloat((milliseconds/1000.0 * 100) / 100).toFixed(fixed) + ""; return seconds.replace(/\.0*$/,""); }
function convertToMilliseconds(seconds) { if (seconds) return seconds*1000 + ""; else return "0"; }
function createDiv(theHtml) { var inner = (theHtml) ? theHtml : ""; return $('<div>').html(inner); }
function createSpan(theHtml) { var inner = (theHtml) ? theHtml : ""; return $('<span>').html(inner); }
function createButton(theText) { var inner = (theText) ? theText : ""; return $('<button>').html(inner); }
function createSelect(theId,theOptions) {
	var theSelect = $('<select>').attr({"id":theId});
	for (var i=0,len=theOptions.length; i<len; i++) { theSelect.append("<option value='" + theOptions[i] + "'>" + theOptions[i] + "</option>"); }
	return theSelect;
}
function createSelectNumbers(theId,first,min,max) {
	var buildArray = [first];
	for (var i=min; i<=max; i++) { buildArray.push(i); }
	return createSelect(theId,buildArray);
}
function parseVersionString (str) {
    var x = str.split('.');
    var maj = parseInt(x[0]) || 0; var min = parseInt(x[1]) || 0; var pat = parseInt(x[2]) || 0;
    return {"major": maj, "minor": min, "patch": pat};
}
(function($){ $.fn.disableSelection = function() { return this.attr('unselectable', 'on').css('user-select', 'none').on('selectstart', false); }; })(jQuery);
function saveSessionData() { sessionStorage.setItem("JR_PC_QueueHelper",JSON.stringify(gQueueSessOptions)); }
function errorRequest(response) {
	if (response && response.error) { console.log("error: " + response.error); }
}
function requestUrl(theUrl, theFunction, theResponseType, acceptText) {
    theResponseType = theResponseType || ""; acceptText = acceptText || "text/html";
    GM_xmlhttpRequest({
        method: "GET",
        url: theUrl,
		headers: { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "User-Agent": "Mozilla/5.0", "Accept": acceptText },
        responseType: theResponseType,
        onload: function(response) { if (typeof theFunction == 'function') theFunction(response); },
        onerror: function(response) { errorRequest(response); }
    });
}
function getLocalStorage() { // JR_TabTargetID | JR_PC_QReturnedHitId | JR_PC_QPrevHitId | JR_PC_QPrevTitle || JR_PC_QPrevMode
	var savedTabTarget = JSON.parse(sessionStorage.getItem('JR_TabTargetID')) || null;
	if (!savedTabTarget || gLocation.indexOf("&newSession=yes") != -1) sessionStorage.setItem('JR_TabTargetID',JSON.stringify(gTabTarget));
	else gTabTarget = savedTabTarget;
	gThisTarget = gTabTarget.tabId + "_" + gScriptID;
	gReturnedHitID = sessionStorage.getItem("JR_PC_QReturnedHitId") || ""; gPrevHit = sessionStorage.getItem('JR_PC_QPrevHitId') || "";
	gPrevTitle = sessionStorage.getItem('JR_PC_QPrevTitle') || ""; gPrevMode = sessionStorage.getItem('JR_PC_QPrevMode') || "";
    sessionStorage.removeItem('JR_PC_QPrevHitId'); sessionStorage.removeItem('JR_PC_QPrevTitle');
	sessionStorage.removeItem("JR_PC_QReturnedHitId"); sessionStorage.removeItem("JR_PC_QPrevMode");
	gQueueSessOptions = JSON.parse(sessionStorage.getItem('JR_PC_QueueHelper')) || null;
}
function loadAllData() {
	var timeNow = Math.floor(new Date().getTime() / 1000), storageKeys = Object.keys(localStorage);
	for (i = 0; i < storageKeys.length; i++)   {
		if ( storageKeys[i].substring(0,9) == 'JR_QTabs_' ) {
			storageValue = JSON.parse(localStorage.getItem(storageKeys[i],null));
			if (storageValue) {
				if ( (timeNow - storageValue.seconds) > 8) localStorage.removeItem(storageKeys[i]); // Remove any tab info that is older than 8 seconds.
				else gTabHitIds[storageValue.tabId] = {"key":storageKeys[i], "groupId": storageValue.groupId, "hitId":storageValue.hitId, "assignmentId":storageValue.assignmentId};
			}
		}
	}
	gQueueNextHit = JSON.parse(sessionStorage.getItem('JR_queueOrder_hitID',null));
	if (!gQueueSessOptions) {
		sessionStorage.setItem("JR_PC_QueueHelper",JSON.stringify(gQueueSessOptionsDef));
		gQueueSessOptions = JSON.parse(sessionStorage.getItem('JR_PC_QueueHelper'));
	}
	doYourQueue();
	sessionStorage.removeItem("JR_queueOrder_hitID");
}
function checkNewMode() {
    var checkModeVar = "";
	if (gLocation.match(/mturk\.com\/projects\/.*\/tasks\/.*assignment_id.*$/) !== null) { checkModeVar = "hitPage"; } // found Hit page.
	else if (gLocation.match(/\/tasks.*JRPC\=nexthit.*/) !== null) { checkModeVar = "queuePageNextStart"; } // wants to go to next hit in queue.
	else if (gLocation.match(/\/tasks.*JRPC\=gohit[0-9]*/) !== null) { checkModeVar = "goToNum"; } // wants to go to a specific nummber in queue.
	else if (gLocation.match(/\/tasks.*JRPC\=lasthit.*/) !== null) { checkModeVar = "goLastHit"; } // wants to go to last hit in queue.
	else if (gLocation.match(/\/tasks.*JRPC\=monitornext.*/) !== null) { checkModeVar = "monitorQueue"; } // monitor queue data and go to first one accepted.
	else if (gLocation.match(/\/tasks.*JRPC\=openhits[0-9]/) !== null) { checkModeVar = "openHits"; } // wants to open first # hits in tabs if necessary.
	if (gLocation.match(/\/tasks.*from\_queue\=true.*/) !== null) { gFromQueue = true }
    if (checkModeVar!=="") return checkModeVar; else return null;
}
function getTimeLeft(theTime) {
    if (theTime) {
        var tempArray = (theTime.indexOf("second") != -1) ? theTime.split("second")[0].trim().split(" ") : null;
		var seconds = (tempArray) ? tempArray[tempArray.length-1] : "0";
		tempArray = (theTime.indexOf("minute") != -1) ? theTime.split("minute")[0].trim().split(" ") : null;
		var minutes = (tempArray) ? tempArray[tempArray.length-1] : "0";
		tempArray = (theTime.indexOf("hour") != -1) ? theTime.split("hour")[0].trim().split(" ") : null;
		var hours = (tempArray) ? tempArray[tempArray.length-1] : "0";
		tempArray = (theTime.indexOf("day") != -1) ? theTime.split("day")[0].trim().split(" ") : null;
		var days = (tempArray) ? tempArray[tempArray.length-1] : "0";
		tempArray = (theTime.indexOf("week") != -1) ? theTime.split("week")[0].trim().split(" ") : null;
		var weeks = (tempArray) ? tempArray[tempArray.length-1] : "0";
		return( {"weeks":weeks,"days":days,"hours":hours,"minutes":minutes,"seconds":seconds} );
    } else return null;
}
function clearOldTabMessages() {
	var storageKeys = Object.keys(localStorage);
	for (i = 0; i < storageKeys.length; i++)   {
		if (storageKeys[i].substring(0,14) == 'JR_message_TAB' &&  storageKeys[i].substr(storageKeys[i].length - gScriptName.length) == gScriptName) {
			localStorage.removeItem(storageKeys[i]);
		}
	}
}
function createMessageData(command,data,target,idNum,tabNum) { return {"time":(new Date().getTime()),"command":command,"data":data,"theTarget":target,"idNum":idNum,"tabNum":tabNum}; }
function createHitData(targetHit,idNum,prevId) { return {"targetHit":targetHit,"idNum":idNum,"prevId":prevId}; }

function setQueueHitMessage(target,idNum,targetHit,prevId) {
		sessionStorage.setItem("JR_queueOrder_hitID", JSON.stringify(createHitData(targetHit,idNum,prevId))); }
function sendSubmittedMessage(target,thisHitID,idNum) { localStorage.setItem("JR_message_" + gScriptName,
		JSON.stringify(createMessageData("submitted",{"hitId":thisHitID},target,idNum,null))); }
function sendReturnedMessage(target,thisHitID,idNum) { localStorage.setItem("JR_message_" + gScriptName,
		JSON.stringify(createMessageData("returned",{"hitId":thisHitID},target,idNum,null))); }
function setSessionData() {
	if ($("#JRPCQAdvSel").length) gQueueSessOptions.nextPosition = $("#JRPCQAdvSel").val();
	if ($("#JRPCQEasySel").val()=="Last") gQueueSessOptions.nextIsLast = true; else gQueueSessOptions.nextIsLast = false;
	if ($("#JRPCQSameSel").val()=="No") gQueueSessOptions.nextIsSame = false; else gQueueSessOptions.nextIsSame = true;
	if ($("#JRPCQMonitor").val()=="No") gQueueSessOptions.nextMonitor = false; else gQueueSessOptions.nextMonitor = true;
	saveSessionData();
}
function setupOptionsMenu() {
	var insideContent = $("#JR_QueueOptionsMenu");
	createDiv("Queue Options Window").css({"font-size":"22px","text-align":"center","margin":"8px 0"}).appendTo(insideContent);
	var optionsArea = createDiv("").css({"font-size":"14px","text-align":"left","padding":"0 10px","margin-top":"20px"}).appendTo(insideContent);
	createDiv(createSpan("Go to the ").append(createSelect("JRPCQEasySel",["First","Last","--"])).append(createSpan(" hit in the queue."))).appendTo(optionsArea);
	createDiv(createSpan("Go to the next hit at position ").css({}).append(createSelectNumbers("JRPCQAdvSel","--",1,24)).append(createSpan(" in the queue."))).appendTo(optionsArea);
	createDiv(createSpan("Go to the next hit with same description? ").css({}).append(createSelect("JRPCQSameSel",["No","Yes"]))).appendTo(optionsArea);
	createDiv(createSpan("Monitor Next at end of Queue? ").css({}).append(createSelect("JRPCQMonitor",["No","Yes"]))).appendTo(optionsArea);
	createButton("OK").css({"margin-top":"40px","margin-left":"10px"}).click(function() { toggleOptionsMenu(); }).appendTo(optionsArea);
	$("#JRPCQEasySel").val((gQueueSessOptions.nextPosition!="--") ? "--" : ((gQueueSessOptions.nextIsLast) ? "Last" : "First"));
	$("#JRPCQAdvSel").val(gQueueSessOptions.nextPosition);
	$("#JRPCQSameSel").val((gQueueSessOptions.nextIsSame) ? "Yes" : "No");
	$("#JRPCQMonitor").val((gQueueSessOptions.nextMonitor) ? "Yes" : "No");
	$("#JRPCQEasySel").change(function() { if ($(this).val()!="--") $("#JRPCQAdvSel").val("--"); else $("#JRPCQAdvSel").val("1"); setSessionData(); });
	$("#JRPCQAdvSel").change(function() { if ($(this).val()!="--") $("#JRPCQEasySel").val("--"); else $("#JRPCQEasySel").val("First"); setSessionData(); });
	$("#JRPCQSameSel").change(function() { setSessionData(); });
	$("#JRPCQMonitor").change(function() { setSessionData(); });
}
function toggleOptionsMenu() {
	toggleOptionsMenu.display = toggleOptionsMenu.display || false;
	toggleOptionsMenu.display = !toggleOptionsMenu.display;
	if (toggleOptionsMenu.display) $("#JR_QueueOptionsMenu").show();
	else $("#JR_QueueOptionsMenu").hide();
}
function doResultsJSON(theData) {
	var jobData = {}, jobDatas = [], projectData = {}, theResults = null;
	if ("tasks" in theData) {
		theResults = theData.tasks;
		for (var i=0,len=theResults.length; i<len; i++) {
			projectData = theResults[i].project;
			jobData = jQuery.extend(true, {}, gJobDataDefault);
			jobData.requesterName=projectData.requester_name; jobData.title=projectData.title; jobData.requesterId=projectData.requester_id;
			jobData.hitId=theResults[i].task_id; jobData.totalSeconds=projectData.assignment_duration_in_seconds; jobData.description=projectData.description;
			jobData.assignmentId=theResults[i].assignment_id; jobData.durationParsed=convertSecondsToTimeData(jobData.totalSeconds);
			jobData.duration=convertToTimeString(jobData.durationParsed); jobData.timeData=convertSecondsToTimeData(theResults[i].time_to_deadline_in_seconds);
			jobData.timeLeft=convertToTimeString(jobData.timeData); jobData.hitsAvailable=projectData.assignable_hits_count;
			jobData.pay=parseFloat(projectData.monetary_reward.amount_in_dollars).toFixed(2);
			jobData.continueURL="https://worker.mturk.com" + theResults[i].task_url; jobData.returnURL = ""; jobData.groupId=projectData.hit_set_id;
			jobDatas.push(jobData); jobData={};
		}
	}
	return jobDatas;
}
function setQueueGlobals() {
	gCurrentPostion = 0;
	if (gQueueData) {
		for (j=0,len=gQueueData.length;j<len;j++) {
			if (gQueueData[j].hitId == gHitId) gCurrentPostion = j+1; // find the currenthit position
		}
	}
}
function parseQueuePage(theResult,theNumber) {
	var theData = null, jsonReceived = (theResult.responseHeaders.indexOf("application/json") != -1) ? true : false;
	if (!jsonReceived) {
	} else {
		theData = theResult.response;
		gQueueData = doResultsJSON(theData);
		if (gScriptMode == "hitPage") {
			setQueueGlobals();
			document.title = "( " + gCurrentPostion + "/" + gQueueData.length + " ) " + gRequesterName + " :: " + gOriginalTitle; // Change title constantly for changes.
		}
	}
}
function doYourQueue() {
	while(gQueueData.length > 0) { gQueueData.pop(); }
	var queueStoreData = JSON.parse(localStorage.getItem("JR_QUEUE_StoreData")), returnValue=false;
	if (queueStoreData) { gQueueData = queueStoreData.queue; setQueueGlobals(); returnValue=true; }
	else requestUrl("https://worker.mturk.com/tasks?format=json", parseQueuePage, "json", "application/json" );
	return returnValue;
}
function inOtherTabs(hitId) {
	var lFoundIt=false;
	var checkForHit = function(key,value) {
		if (value.hitId == hitId && key != gTabTarget.tabId) lFoundIt = true;
	};
	$.each(gTabHitIds, checkForHit);
	return lFoundIt;
}
function findNextHitQueue(currentHitID,sameTitle,countCurrent) {
	if (!gQueueData || currentHitID === "") return null;
    sameTitle = sameTitle || "";
	var i=-1, skip=false, targetHit=null, lastHit=null, counter=0, nextPosition = (gQueueSessOptions.nextPosition=="--") ? -2 : parseInt(gQueueSessOptions.nextPosition);
	var getLast = (gQueueSessOptions.nextIsLast) ? true : ((nextPosition>gQueueData.length-1) ? true : false);
	for (j=0,len=gQueueData.length;j<len;j++) {
		if (gQueueData[j].hitId==currentHitID) gCurrentPostion = j+1; // find the currenthit position
		if (!targetHit) {
			if ( (countCurrent || gQueueData[j].hitId!=currentHitID) && gQueueData[j].hitId!=gSubmitHitID && gQueueData[j].hitId!=gReturnedHitID ) {
				counter++; lastHit = gQueueData[j];
				if ( !getLast && (sameTitle==="" || gQueueData[j].title==sameTitle) && (nextPosition==-2 || nextPosition==counter) ) { targetHit = gQueueData[j]; }
			}
		}
	}
	if (!targetHit && gQueueData.length>1 && (getLast || nextPosition>counter)) targetHit = lastHit;
	return targetHit;
}
function findTheNexthit(theQueue,queuePage) {
    var foundNextOne = null, theHitId = ""; // initialize variable to represent not found so stay on current hit.
	for (j=0,len=theQueue.length;j<len && !foundNextOne;j++) { // go through array of hits one by one.
        theHitId = (queuePage) ? theQueue[j].task_id : theQueue[j].hitId;
        if (!inOtherTabs(theHitId)) foundNextOne=theQueue[j]; // if not in other tabs then set up variable to next hit.
    }
    if (foundNextOne) { // was next hit found and not current hit?
        if (gScriptMode=="monitorQueue") speakThisNow("Hits in Queue. Going to first."); // alert user to a hit found.
        if (queuePage) window.location.replace("https://worker.mturk.com" + foundNextOne.task_url.replace("&ref=w_pl_prvw","&from_queue=true"));
        else window.location.replace(foundNextOne.continueURL.replace("&ref=w_pl_prvw","&from_queue=true"));
    } else {
        $("body").children("div,table").css("opacity","1"); // next hit not found or it's the current hit so just undim.
        if (gScriptMode=="monitorQueue") setTimeout( monitorQueue,(gPandaCrazyLives) ? 900 : 3000); // use a timer for interval and lessen chance of pre's if too fast.
    }
}
function queuePageNewStart() {
	var jobData = jQuery.extend(true, {}, gJobDataDefault);
    var queueDataDiv = $(".task-queue-header:first").next().find("div"); // look for the queue header div and put in variable.
    var reactInfoList = queueDataDiv[1].dataset.reactProps; // grab the list of hits in queue
	if (reactInfoList) { // was list found?
		var queueData = JSON.parse(reactInfoList).bodyData; // convert the list of hits into an array of objects.
        findTheNexthit(queueData, true);
	}
}
function setNextHit() {
	if (gSubmitButton && gSubmitButton.length===0) return;
	var targetHit = findNextHitQueue(gHitId, (gQueueSessOptions.nextIsSame) ? gTitle : "",false);
	if (!targetHit && gQueueSessOptions.nextIsSame) targetHit = findNextHitQueue(gHitId, "",false);
	if (targetHit && (gQueueSessOptions.nextIsSame || gQueueSessOptions.nextPosition!="--" || gQueueSessOptions.nextIsLast) ) { setQueueHitMessage(gThisTarget,gIdNum,targetHit,gHitId); }
}
function monitorQueue() {
    gPandaCrazyLives = doYourQueue();
	if (gQueueData!==null && gQueueData.length>0) { // found a hit in the queue.
        findTheNexthit(gQueueData, false);
	} else {
		setTimeout( monitorQueue,(gPandaCrazyLives) ? 900 : 3000); // use a timer for interval and lessen chance of pre's if too fast.
	}
}

if (gLocation.indexOf("worker.mturk.com") != -1) {
	getLocalStorage();
	if (gReturnedHitID !== "") {
		sendReturnedMessage(gThisTarget,gReturnedHitID,gIdNum); // Tell Panda Crazy that hit has been returned.
	}
	if (gPrevHit !== "" && $(".mturk-alert-content:contains('The HIT has been successfully submitted.')").length) { // Check if a hit was submitted.
		gSubmitHitID = gPrevHit; // set global submitted variable for use in getting next hit.
		sendSubmittedMessage(gThisTarget,gPrevHit,gIdNum); // send submitted message to Panda Crazy.
	}
	gScriptMode = checkNewMode();
	if (gScriptMode) {
		clearOldTabMessages(); loadAllData();
		window.onbeforeunload = function() {
			localStorage.removeItem("JR_QTabs_" + gThisTarget);
		};
		if (gScriptMode=="hitPage") {
			gPandaCrazyLives = doYourQueue();
			if ($(".btn-secondary:contains('Return')").length) { // only hit pages accepted will have a return button.
				$(".navbar-brand:first").after("<span style='margin-left:10px; font-size:11px;'>[ <a href='https://worker.mturk.com/tasks' style='color:cyan;'>Your HITs Queue</a> ]</span>");
				gGroupId = gLocation.split("/projects/")[1].split("/")[0]; // grab the current group id.
				gHitId = gLocation.split("/tasks/")[1].split("?")[0]; // grab the current hit id.
				gAssignmentId = gLocation.split("assignment_id=")[1].split("&")[0]; // grab the current session id.
				var returnDetect = function() {
					var returnCancelled = function() { sessionStorage.removeItem("JR_PC_QReturnedHitId"); };
					sessionStorage.setItem("JR_PC_QReturnedHitId",gHitId);
					setTimeout(returnCancelled ,800);
				};
				$(".btn-secondary:contains('Return')").closest("form").submit( returnDetect );
				if (gQueueNextHit && gPrevHit!=gHitId) {
					$("body").children("div,table").css("opacity","0.1");
					window.location.replace(gQueueNextHit.targetHit.continueURL.replace("&ref=w_pl_prvw","&from_queue=true"));
				} else {
					var nextTargetHit = null;
					if (inOtherTabs(gHitId)) {
						for (j=0,len=gQueueData.length;j<len && !nextTargetHit;j++) { // go through array of hits one by one.
							if (!inOtherTabs(gQueueData[j].hitId) && gQueueData[j].hitId != gPrevHit && Object.keys(gTabHitIds).length>0) nextTargetHit=gQueueData[j];
							// if not in other tabs then set up variable to next hit.
						}
						if (gFromQueue && nextTargetHit) {
							if (nextTargetHit.hitId != gHitId) window.location.replace(nextTargetHit.continueURL.replace("&ref=w_pl_prvw","&from_queue=true"));
						} else if (gQueueSessOptions && gQueueSessOptions.nextMonitor) {
                            window.location.replace("https://worker.mturk.com/tasks?JRPC=monitornext");
						} else window.location.replace("https://worker.mturk.com/tasks");
					} else {
						var projectDetailBar = $(".project-detail-bar"); // set variable to the detail bar to grab details.
						if (projectDetailBar.length) { // if found detail bar.
							var tempPrevDiv = projectDetailBar[0].getElementsByClassName("col-sm-4 col-xs-5");
							if (tempPrevDiv.length===0) tempPrevDiv = projectDetailBar[0].getElementsByClassName("col-md-6 col-xs-12");
							if (tempPrevDiv.length===0) tempPrevDiv = projectDetailBar[0].getElementsByClassName("col-xs-12");
							if (tempPrevDiv.length===0) tempPrevDiv = projectDetailBar[0].getElementsByClassName("p-l-xs");
							var reactInfo = (tempPrevDiv.length>0) ? tempPrevDiv[0].firstElementChild.dataset.reactProps : null;
							if (reactInfo) { reactInfo = JSON.parse(reactInfo).modalOptions; gRequesterName = reactInfo.requesterName; gTitle = reactInfo.projectTitle; }
						}
						sessionStorage.setItem("JR_PC_QPrevHitId",gHitId); sessionStorage.setItem("JR_PC_QPrevTitle",gTitle); // set local variables for previous hit and title
						localStorage.setItem("JR_QTabs_" + gThisTarget, JSON.stringify({"groupId": gGroupId, "hitId": gHitId,
							"assignmentId": gAssignmentId, "tabId": gTabTarget.tabId, "seconds": Math.floor(new Date().getTime() / 1000)}) );
						if (!gButtonSet) {
							gButtonSet = true;
							createDiv("Q").css({"position":"fixed","width":"10px","text-align":"right","height":"20px","top":"82px","right":"2px","float":"right","box-sizing":"content-box",
								"padding":"0px 3px","background-color":"black","color":"white","opacity": "0.3","cursor":"pointer","font-size":"11px","line-height":"13px",
								"font-family":"verdana, arial, sans-serif"}).disableSelection().click( toggleOptionsMenu ).appendTo("body");
							createDiv("").css({"position":"fixed","width":"400px","height":"200px","top":"90px","right":"20px","float":"right","background-color":"#eceadf",
								"border":"3px solid #000","line-height":"13px"}).attr({"id":"JR_QueueOptionsMenu"}).hide().appendTo("body");
							setupOptionsMenu();
						}
						var doQtabsSet = function() {
							gPandaCrazyLives = doYourQueue();
							if (gQueueData!==null) { // Has Queue Data been found?
								setQueueGlobals();
								document.title = "( " + gCurrentPostion + "/" + gQueueData.length + " ) " + gRequesterName + " :: " + gOriginalTitle; // Change title constantly for changes.
								localStorage.setItem("JR_QTabs_" + gThisTarget, JSON.stringify({"groupId": gGroupId, "hitId": gHitId,
									"assignmentId": gAssignmentId, "tabId": gTabTarget.tabId, "seconds": Math.floor(new Date().getTime() / 1000)}) );
								setNextHit();
							}
							setTimeout( doQtabsSet,(gPandaCrazyLives) ? 1000 : 3000);
						};
						setTimeout( doQtabsSet,(gPandaCrazyLives) ? 1000 : 3000);
					}
				}
			}
		} else if ( $(".no-result-row").length && gScriptMode != "monitorQueue") {

		} else if ( (gScriptMode=="queuePageNextStart" || gScriptMode=="monitorQueue") &&
				!$(".no-result-row").length) { // If not an empty queue and looking for next hit or monitoring queue.
			$("body").children("div,table").css("opacity","0.1"); // dim page and set to looking for next hit.
			gQueueSessOptions.nextPosition="--"; gQueueSessOptions.nextIsLast=false; gQueueSessOptions.nextIsSame=false; saveSessionData(); // reset options.
			queuePageNewStart();
		} else if (gScriptMode=="monitorQueue") { // wants to monitor empty queue for any new hits.
			$("h1:contains('Your HITs Queue'):first").append($("<span>").attr("class","1supportive-label").css({"font-size":"11px"}).html(" (Monitoring queue for a hit to open.)"));
			setTimeout( monitorQueue,(gPandaCrazyLives) ? 1000 : 3000); // use a timer for interval and lessen chance of pre's if too fast.
		} else if (gScriptMode=="goToNum" || gScriptMode=="goLastHit" || gScriptMode=="openHits") { // user looking for a specific hit in queue or the last one.
			$("body").children("div,table").css("opacity","0.1");
			var queueDataDiv = $(".task-queue-header:first").next().find("div"); // set variable to queue header div to find queue list.
			var reactInfoList = queueDataDiv[1].dataset.reactProps, positionNum = 1; // set queue list variable
			if (reactInfoList) {
				queueData = JSON.parse(reactInfoList).bodyData; // convert the list to an array of objects.
				if (gScriptMode=="openHits") {
					var numOpenHitsFirst = gLocation.split("JRPC=openhits")[1]; // find the open hits command to split it from the number.
					if (numOpenHitsFirst) numOpenHits = numOpenHitsFirst.match(/\d+/)[0]; // match the first number found and set variable to it.
					if (numOpenHits>1 && numOpenHits<=15) { // make sure the hit numbers is 2 to 15.
						var hitPosition = 2;
						var nowOpenHits = function() {
							window.open("https://worker.mturk.com" + queueData[hitPosition-1].task_url.replace("&ref=w_pl_prvw","&from_queue=true") + "&newSession=yes","_blank");
							hitPosition++; numOpenHits--;
							if (numOpenHits>1 && numOpenHits<queueData.length) setTimeout(nowOpenHits, 1870);
							else { window.location.replace("https://worker.mturk.com" + queueData[0].task_url.replace("&ref=w_pl_prvw","&from_queue=true")); window.focus(); }
						}
						nowOpenHits();
						positionNum = 0;
					}
				}
				if (gScriptMode=="goToNum") { // if looking for a specific position.
					var positionNumFirst = gLocation.split("JRPC=gohit")[1]; // find the go hit command to split it from the number.
					if (positionNumFirst) positionNum = positionNumFirst.match(/\d+/)[0]; // match the first number found and set variable to it.
					if (positionNum>0 && positionNum<26 && positionNum<=queueData.length) { // make sure the number is 1 to 25 and less than queue length.
						gQueueSessOptions.nextPosition = positionNum; gQueueSessOptions.nextIsLast=false; gQueueSessOptions.nextIsSame=false; // reset options to look for next position.
					} else gScriptMode="goLastHit";
				}
				if (gScriptMode=="goLastHit") { // if looking for last hit.
					positionNum = queueData.length; // set position number to the last hit in queue.
				    gQueueSessOptions.nextPosition="--"; gQueueSessOptions.nextIsLast=true; gQueueSessOptions.nextIsSame=false; // reset options to look for last hit.
				}
				saveSessionData(); // save the options for the next hit.
				if (positionNum>0)
					window.location.replace("https://worker.mturk.com" + queueData[positionNum-1].task_url.replace("&ref=w_pl_prvw","&from_queue=true")); // go to the hit at the position set.
			}
		}
    } else if (gLocation=="https://worker.mturk.com/" && gQueueSessOptions && gQueueSessOptions.nextMonitor) {
        window.location.replace("https://worker.mturk.com/tasks?JRPC=monitornext");
	} else {
		sessionStorage.setItem("JR_PC_QueueHelper",JSON.stringify(gQueueSessOptionsDef));
		sessionStorage.removeItem("JR_queueOrder_hitID");
	}
}