Greasy Fork is available in English.

JR Mturk Panda Crazy

My own Panda master for mturk with zing and queue smart

Version vom 29.04.2016. Aktuellste Version

// ==UserScript==
// @name        JR Mturk Panda Crazy
// @version     0.1.2
// @description My own Panda master for mturk with zing and queue smart
// @include     http*://www.allbyjohn.com/mturk/pandacrazy.html
// @include     http*://www.mturk.com/mturk/welcome?pandacrazy=on*
// @require     http://code.jquery.com/jquery-2.1.4.min.js
// @require     http://code.jquery.com/ui/1.11.4/jquery-ui.min.js
// @require     https://cdnjs.cloudflare.com/ajax/libs/jquery-layout/1.3.0-rc-30.79/jquery.layout.min.js
// @require     https://greasyfork.org/scripts/2350-filesaver-js/code/filesaverjs.js?version=6255
// @resource    jQueryUICSS          http://code.jquery.com/ui/1.11.4/themes/pepper-grinder/jquery-ui.css
// @resource    jQueryLayoutCSS      https://cdnjs.cloudflare.com/ajax/libs/jquery-layout/1.3.0-rc-30.79/layout-default.css
// @connect     allbyjohn.com
// @connect     mturk.com
// @connect     tiny.cc
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_deleteValue
// @grant       GM_addStyle
// @grant 		GM_xmlhttpRequest 
// @grant       GM_getResourceText
// @namespace   https://greasyfork.org/users/6406
// ==/UserScript==

var gDatabaseVersion = "JRAPR16-1.1-1.1.1"; // JR[Date]-[requesters DB Reset].[Alarms DB reset]-[requesters DB Version].[Options DB Version].[Tabs DB Version]
var gResetDBVersion = gDatabaseVersion.split("-")[1];
var gDefaultDBVersion = gDatabaseVersion.split("-")[2];
var gDelayedSave = false;
var gNotification = true;
var gMyLayout = null, gAcceptedLogTab = null, gStatusLogTab = null, mCoinSound = [];
var gMainData = {"hitCollection":{},"displayInfo":"1",
                 "accepted":0,"skipped":0,"errors":0,"searched":0,"noHits":0,"fullQueue":0,"orphan":0,"tooFast":0,
                 "hitsInQueue":0,"queueStatus":null,"notQual":0,"lastElapsed":0,"jobs":0,"payCounter":0};
var gMainMenu = [{"name":"Main","theobject":null}];
var gDefaultRequestersOptions = {};
var gDefaultLayout = {};
var gDefaultSounds = {};
var gHitBgColor="#AFEEEE", gFilteredHitBgColor="#D1E5E5", gSearchesHitBgColor="#AED2D2", gButtonOffBgColor="#FFFFF0", gButtonOnBgColor="#008000"; 
var gButtonDelayHamBgColor="#00A3CC", gButtonDisabledBgColor="#D3D3D3", gHitMutedColor="#8B4513";
var gTitleColor="#000080", gButtonOffColor="black", gButtonOnColor="white", gButtonDisabledColor="#808080";
var gHitMutedBorderStyle="dotted", gHitBorderStyle="solid";
var gZingOptions = {
    "0.01":{"SearchGroupAllowed":1,"TallyCountTotalAllowed":0,"MaxProductsSearch":0,"AcceptCodesSearching":false,"MaxReceiptImages":3},
    "0.03":{"SearchGroupAllowed":2,"TallyCountTotalAllowed":0,"MaxProductsSearch":2,"AcceptCodesSearching":true,"MaxReceiptImages":3},
    "0.05":{"SearchGroupAllowed":3,"TallyCountTotalAllowed":0,"MaxProductsSearch":4,"AcceptCodesSearching":true,"MaxReceiptImages":4},
    "0.07":{"SearchGroupAllowed":7,"TallyCountTotalAllowed":0,"MaxProductsSearch":5,"AcceptCodesSearching":true,"MaxReceiptImages":8}
};
var gZingFuncOptions = {
    "1":{"filterName":"Parse Zing Hit Page","functionName":parseZingHitPage}
};
var gAlarmSounds = {
    "less2":{"nameVar":"JR_PANDA_Soundless2","default":"http://tiny.cc/c6c1ay","audio":null,"desc":"Hits paying less than $0.02: "},
    "less2Short":{"nameVar":"JR_PANDA_Soundless2Short","default":"http://tiny.cc/kyh1ay","audio":null,"desc":"Hits paying less than $0.02 with a short timer: "},
    "less5":{"nameVar":"JR_PANDA_Soundless5","default":"http://tiny.cc/g7h1ay","audio":null,"desc":"Hits paying less than $0.05: "},
    "less5Short":{"nameVar":"JR_PANDA_Soundless5Short","default":"http://tiny.cc/99h1ay","audio":null,"desc":"Hits paying less than $0.05 with a short timer: "},
    "less15":{"nameVar":"JR_PANDA_Soundless15","default":"http://tiny.cc/qai1ay","audio":null,"desc":"Hits paying less than $0.15: "},
    "less15Short":{"nameVar":"JR_PANDA_Soundless15Short","default":"http://tiny.cc/uai1ay","audio":null,"desc":"Hits paying less than $0.15 with a short timer: "},
    "less99":{"nameVar":"JR_PANDA_Soundless99","default":"http://tiny.cc/gbi1ay","audio":null,"desc":"Hits paying MORE than $0.15: "},
};
var gSoundFile = gAlarmSounds.less2.audio;
var gTabIndex = 0;
var gMouseDownTimeoutId = null;
var gPressAndHold = false;
var gGroupingData = [{"theNumber":"0","name":"First","description":"First grouping by default.","grouping":[]}];
var gTabsData = [];
var gDefaultTabsData = [{"tabName":"Main","tabNumber":"1","positions":null},{"tabName":"Daily Hits","tabNumber":"2","positions":null},{"tabName":"Rare Hits","tabNumber":"3","positions":null}];
var gPositions = {};
var gMainOptions = {};
var gDefaultMainOptions = {"cycleNumber":970,"HamCycleNumber":700,"autoSlowDown":true,"cycleAutoIncrease":5,"alarmVolume":80,cycleIncrease:5,cycleDecrease:5,cycleAdding:650,queueTimer:60000,hamDelayTimer:0};
var gRequestersData = {};
var gDefaultRequestersData = { 
    "0":{"requesterName":gDatabaseVersion,"requesterId":28,"action":"","groupId":"","pay":"","qual":"","title":"","queueLimit":0,"duration":"0","audioforce":"","dailyLimit":0,"mute":false,"position":null,"tabNumber":"0","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "4":{"requesterName":"Zing","requesterId":"AGVV5AWLJY7H2","action":"Panda","groupId":"30B721SJLR5BYYBNQJ0CVKJESN00OC","pay":"0.01","qual":"ibotta","title":"Are these the same?","queueLimit":15,"duration":"0","audioforce":"less2","dailyLimit":0,"mute":false,"position":null,"tabNumber":"2","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "5":{"requesterName":"Zing","requesterId":"AGVV5AWLJY7H2","action":"Panda","groupId":"30B721SJLR5BYYBNQJ0CVKJEQOZ0OB","pay":"0.01","qual":"","title":"Are these the same?","queueLimit":15,"duration":"0","audioforce":"less2","dailyLimit":0,"mute":false,"position":null,"tabNumber":"2","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "6":{"requesterName":"Zing","requesterId":"AGVV5AWLJY7H2","action":"Panda","groupId":"3ZXRRTK2NDCB5NW5M24C9P2OWG41OF","pay":"0.01","qual":"ibotta","title":"Does this receipt contain the following products?","queueLimit":4,"duration":"0","audioforce":"less2","dailyLimit":0,"mute":false,"position":null,"tabNumber":"2","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "7":{"requesterName":"Zing","requesterId":"AGVV5AWLJY7H2","action":"Panda","groupId":"3NYGPW9OTYRQLJTE9DQJQJRQJ2IZPS","pay":"0.01","qual":"","title":"Does this receipt contain the following products?","queueLimit":4,"duration":"0","audioforce":"less2","dailyLimit":0,"mute":false,"position":null,"tabNumber":"2","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "8":{"requesterName":"Zing","requesterId":"AGVV5AWLJY7H2","action":"Panda","groupId":"3R35RPFD7JUTQN8612HRYP7E6LZ1PV","pay":"0.03","qual":"ibotta","title":"Does this receipt contain the following products?","queueLimit":6,"duration":"0","audioforce":"less2","dailyLimit":0,"mute":false,"position":null,"tabNumber":"2","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "9":{"requesterName":"Zing","requesterId":"AGVV5AWLJY7H2","action":"Panda","groupId":"3ZXRRTK2NDCB5NW5M24C9P2OVF61OE","pay":"0.03","qual":"","title":"Does this receipt contain the following products?","queueLimit":6,"duration":"0","audioforce":"less2","dailyLimit":0,"mute":false,"position":null,"tabNumber":"2","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "10":{"requesterName":"Zing","requesterId":"AGVV5AWLJY7H2","action":"Panda","groupId":"3CRC4NO2BIQQWQ3GX0HLFPTFOD30SA","pay":"0.05","qual":"ibotta","title":"Does this receipt contain the following products?","queueLimit":12,"duration":"60 minutes","audioforce":"less2","dailyLimit":0,"mute":false,"position":null,"tabNumber":"2","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "11":{"requesterName":"Zing","requesterId":"AGVV5AWLJY7H2","action":"Panda","groupId":"3787DLY3Y49RIF1DIJQB3Z8BUNP1T2","pay":"0.05","qual":"","title":"Does this receipt contain the following products?","queueLimit":12,"duration":"0","audioforce":"less2","dailyLimit":0,"mute":false,"position":null,"tabNumber":"2","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "13":{"requesterName":"Viral Mturk","requesterId":"A2UFLDVZ75JD9M","action":"Panda","groupId":"3ZXEP6UEGGA75UPGRQ2UPK3XA4YO8B","pay":"0.25","qual":"","title":"Rate the quality of ads on YouTube","queueLimit":0,"duration":"0","audioforce":"","dailyLimit":0,"mute":false,"position":null,"tabNumber":"0","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "14":{"requesterName":"MyLikes","requesterId":"A239M0XNXTKQZ7","action":"Panda","groupId":"3EGCY5R6XY0PS57S4R2H1KZW7LSAYC","pay":"0.01","qual":"","title":"Identify Images with Mature Content","queueLimit":0,"duration":"0","audioforce":"","dailyLimit":0,"mute":false,"position":null,"tabNumber":"0","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "15":{"requesterName":"MyLikes","requesterId":"A239M0XNXTKQZ7","action":"Panda","groupId":"3USMLONC9E5D7T4TWRD6UWVBJLN85E","pay":"0.03","qual":"","title":"Identify Images with Mature Content","queueLimit":0,"duration":"0","audioforce":"","dailyLimit":0,"mute":false,"position":null,"tabNumber":"0","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "16":{"requesterName":"MyLikes","requesterId":"A239M0XNXTKQZ7","action":"Panda","groupId":"37G59K9AEU0BNMXNCLOH5POEZUC9YI","pay":"0.03","qual":"","title":"Identify Videos with Mature Content","queueLimit":0,"duration":"15 minutes","audioforce":"","dailyLimit":0,"mute":false,"position":null,"tabNumber":"0","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "17":{"requesterName":"Steven Snow","requesterId":"A3GAVAUPTHM0B8","action":"Panda","groupId":"3X19M43Z4VULD73G1I2N3GGRYF10D8","pay":"0.06","qual":"","title":"steven snow search 3X..D8","queueLimit":0,"duration":"0","audioforce":"","dailyLimit":0,"mute":false,"position":null,"tabNumber":3,"once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "18":{"requesterName":"Steven Snow","requesterId":"A3GAVAUPTHM0B8","action":"Panda","groupId":"3TJJ8HSJVIVGSMA3ZXVL0CV5EGV28D","pay":"0.05","qual":"","title":"steven snow url 3T..8D","queueLimit":0,"duration":"0","audioforce":"","dailyLimit":0,"mute":false,"position":null,"tabNumber":"3","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "19":{"requesterName":"Venue Quality","requesterId":"A14AT838CPSKA6","action":"Panda","groupId":"3EM4DVSA8U8J6KF08Q5EM8I2NYE308","pay":"0.01","qual":"","title":"locations same","queueLimit":0,"duration":"0","audioforce":"","dailyLimit":0,"mute":false,"position":null,"tabNumber":"0","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "20":{"requesterName":"Venue Quality","requesterId":"A14AT838CPSKA6","action":"Panda","groupId":"3D8O2NKTAGFJD90I499E0D26RON13W","pay":"0.01","qual":"","title":"locations adult","queueLimit":0,"duration":"5 minutes","audioforce":"","dailyLimit":0,"mute":false,"position":null,"tabNumber":"0","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "21":{"requesterName":"Venue Quality","requesterId":"A14AT838CPSKA6","action":"Panda","groupId":"ZZAWVTYW3Z9ZTAX43ZD0","pay":"0.01","qual":"","title":"locations family","queueLimit":0,"duration":"0","audioforce":"","dailyLimit":0,"mute":false,"position":null,"tabNumber":"0","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "22":{"requesterName":"Annabel","requesterId":"A3HB3KPJ2RZ2K8","action":"Panda","groupId":"3CVHT3IKTXQR8KSLQHD2N8KOQZPR06","pay":"0.50","qual":"","title":"Comparing two statements with each other","queueLimit":0,"duration":"60 minutes","audioforce":"","dailyLimit":0,"mute":false,"position":null,"tabNumber":"0","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "23":{"requesterName":"Rob Grady","requesterId":"AM07BBZNC6UTQ","action":"Panda","groupId":"33X7UBO5WUFB78Y5WJ3MVC35LFMU05","pay":"0.03","qual":"","title":"Transcribe Waffle House Guest Check","queueLimit":0,"duration":"5 minutes","audioforce":"","dailyLimit":0,"mute":false,"position":null,"tabNumber":"0","once":false,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0},
    "24":{"requesterName":"PredictWallStreet.com","requesterId":"A17T7LCJF0818V","action":"Search","groupId":"329HSLC9WDXX9F2DN54ARF87CMFHGG","pay":"0.80","qual":"","title":"Predict 100 Stocks - Up or Down?","queueLimit":0,"duration":"60 minutes","audioforce":"","dailyLimit":0,"mute":false,"position":null,"tabNumber":"0","once":true,"dailyDone":0,"day":0,"filterMode":0,"hamTimer":0}
};
var gExcludeIds = ["38FT9G80DL83PUCSQBVANJBIKGSLHM"];
var jqUI_CssSrc = GM_getResourceText("jQueryUICSS");
var jqLayout_CssSrc = GM_getResourceText("jQueryLayoutCSS");

Date.prototype.stdTimezoneOffset = function() {
    var jan = new Date(this.getFullYear(), 0, 1);
    var jul = new Date(this.getFullYear(), 6, 1);
    return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
}

Date.prototype.dst = function() {
    return this.getTimezoneOffset() < this.stdTimezoneOffset();
}
function formatAMPM(theFormat,theDate,theTimeZone) {
    var d = (theDate) ? theDate : new Date();
    if (theTimeZone == "mturk") {
        var mturkTZOffset = -8;
        var today = new Date();
        if (today.dst()) mturkTZOffset++;
        var utc = d.getTime() + (d.getTimezoneOffset() * 60000);
        var MturkTime = utc + (3600000 * mturkTZOffset);
        d = new Date(MturkTime);
    }
    var minutes = d.getMinutes().toString().length == 1 ? '0'+d.getMinutes() : d.getMinutes(),
        hours = d.getHours().toString().length == 1 ? '0'+d.getHours() : d.getHours(),
        ampm = d.getHours() >= 12 ? 'pm' : 'am',
        months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
        days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
    if (theFormat=="short") return ('0' + (d.getMonth()+1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + d.getFullYear() + '(' + 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 checkNotifications() {
  // Let's check if the browser supports notifications
  if (!("Notification" in window)) return false;
  else if (Notification.permission === "granted") return true;
  else if (Notification.permission !== 'denied') {
    Notification.requestPermission(function (permission) {
      if (permission === "granted") return true;
    });
  }
  return false;
}
function showNotification( title, message, tag ) {
    var n = new Notification(title, {
        body: message,
        icon: "http://www.allbyjohn.com/mturk/Messaging-Online-icon.png",
        tag: tag});
    if (navigator.userAgent.search("Chrome") >= 0) n.onshow = function () { setTimeout(n.close.bind(n), 20000); }
}

// Database using setValue and getValue
function convertDatabase(theDataBase,resetDBVersion,defaultDBVersion) {
    var newDataBase = {};
    $.each(theDataBase, function( index, value ) {
        newDataBase[index] = value;
    });
    newDataBase[0].requesterName = gDatabaseVersion;
    return newDataBase;
}
function getBase64Audio(theData) {
    var base64AudioData = new Uint8Array(theData);
    var i = base64AudioData.length;
    var binaryString = new Array(i);
    while (i--) { binaryString[i] = String.fromCharCode(base64AudioData[i]); }
    var data = binaryString.join('');
    return(window.btoa(data));
}
function loadSoundFiles(soundNumber,keyArray,resetDBVersion) {
    if (soundNumber < keyArray.length) {
        if (gResetDBVersion.split(".")[1] > resetDBVersion.split(".")[1]) GM_deleteValue(gAlarmSounds[keyArray[soundNumber]].nameVar);
        console.log("JR reset version: " + resetDBVersion + " | new reset version: " + gResetDBVersion);
        var gotBase64 = GM_getValue(gAlarmSounds[keyArray[soundNumber]].nameVar,null);
        this.firstTime = this.firstTime || false;
        if (gotBase64 === null) {
            if (!this.firstTime) $("#JRWaitDialog").append(createDiv("For your first time this might take a few seconds.<br>Loading Alarms ").attr({"class":"alarmsLoad"}));
            this.firstTime = true;
            requestUrl(gAlarmSounds[keyArray[soundNumber]].default,0,function(theResult,theNumber,data1,data2) {
                $("#JRWaitDialog .alarmsLoad").append(createSpan(" ."));
                var base64 = getBase64Audio(theResult.response);
                GM_setValue(gAlarmSounds[keyArray[soundNumber]].nameVar,JSON.stringify(base64));
                gAlarmSounds[keyArray[soundNumber]].audio = new Audio("data:audio/wav;base64," + base64);
                loadSoundFiles(soundNumber+1,keyArray,resetDBVersion);
            },function() { errorRequest(); }, "", "", "arraybuffer");
        } else {
            gAlarmSounds[keyArray[soundNumber]].audio = new Audio("data:audio/wav;base64," + JSON.parse(gotBase64));
            loadSoundFiles(soundNumber+1,keyArray,resetDBVersion);
        }
    } else continueLoading();
}

function loadSettings() {
    var tempData = JSON.parse(GM_getValue("JR_PANDA_RequestersData",JSON.stringify(gDefaultRequestersData)));
    var savedDBVersion = tempData[0].requesterName;
    var resetDBVersion = savedDBVersion.split("-")[1];
    var defaultDBVersion = savedDBVersion.split("-")[2];
    if (gResetDBVersion.split(".")[0] > resetDBVersion.split(".")[0]) {
        GM_deleteValue("JR_PANDA_RequestersData");
        tempData = JSON.parse(GM_getValue("JR_PANDA_RequestersData",JSON.stringify(gDefaultRequestersData)));
    }
    gRequestersData = convertDatabase(tempData,resetDBVersion,defaultDBVersion);
    GM_deleteValue("JR_PANDA_MainOptions");
    gMainOptions = JSON.parse(GM_getValue("JR_PANDA_MainOptions",JSON.stringify(gDefaultMainOptions)));
    gTabsData = JSON.parse(GM_getValue("JR_PANDA_TabsData",JSON.stringify(gDefaultTabsData)));
    loadSoundFiles(0,Object.keys(gAlarmSounds),resetDBVersion);
}
function saveSettings() {
    GM_setValue("JR_PANDA_RequestersData",JSON.stringify(gRequestersData));
    GM_setValue("JR_PANDA_MainOptions",JSON.stringify(gMainOptions));
    GM_setValue("JR_PANDA_TabsData",JSON.stringify(gTabsData));
}
function checkDelayedSave() { if (gDelayedSave) saveSettings(); }

function toggleButton(thisButton,doThisOn,doThisOff,mode,modeStatus) {
    var theStatus = $(thisButton).data("status");
    var doStatus = (modeStatus) ? modeStatus : (theStatus != "on" && theStatus!=mode) ? "on" : "off";
    if (mode && theStatus!=mode) $(thisButton).data("status",mode);
    else $(thisButton).data("status",doStatus);
    if (doStatus=="on" && doThisOn) doThisOn($(thisButton).data("theNumber"),thisButton,mode);
    if (doStatus=="off" && doThisOff) doThisOff($(thisButton).data("theNumber"),thisButton,mode);
    updateHitColors($(thisButton).data("theNumber"),thisButton);
}
function toggleButtonOff(thisButton,doThisOn,doThisOff) {
    $(thisButton).data("status","off");
    updateHitColors($(thisButton).data("theNumber"),thisButton);
    if (doThisOff) doThisOff($(thisButton).data("theNumber"),thisButton);
}
function createDiv(theHtml) { var inner = (theHtml) ? theHtml : ""; return $('<div>').html(inner); }
function createSpan(theHtml) { var inner = (theHtml) ? theHtml : ""; return $('<span>').html(inner); }
function createTextInput(theValue) { return $("<input>").attr({ "type": "text", "value": theValue }); }
function createCheckbox(theValue) { return $("<input>").attr({ "type": "checkbox", "value": theValue }); }
function createLink(theText,theUrl,theTarget,theTitle) { return $('<a>',{text: theText,target: theTarget,title: theTitle,href: theUrl}); }
function createSpanButton(toDo,theHtml,theBackgroundColor,theColor,theFontSize) {
    var backgroundColor = (theBackgroundColor) ? theBackgroundColor : "initial";
    var textColor = (theColor) ? theColor : "initial";
    var fontSize = (theFontSize) ? theFontSize : "9px";
    var theButton = createSpan(theHtml).data("status","off")
        .data("backgroundColor",backgroundColor)
        .data("textColor",textColor)
        .data("htmlText",theHtml)
        .disableSelection()
        .dblclick(function(e) { e.stopPropagation(); })
        .css({"font-size":fontSize,
            "padding":"0px 2px",
            "background-color":backgroundColor,
            "color":textColor,
            "border":"2px groove red",
            "cursor":"default",
            "margin":"0px 1px"});
    if (toDo) theButton.click(toDo);
    return theButton;
}
function createContainer() {
    var containerDiv = createDiv();
    containerDiv.css({"padding-left":"3px", "padding-right":"3px","padding-top":"0px","padding-bottom":"1px"});
    return containerDiv;
}
function createPanels(goAppend) {
    var panelContainer = createContainer()
        .attr("id","panelContainer")
        .appendTo(goAppend);
    return panelContainer;
}
function createPanel(goAppend) {
    var panel = createContainer().appendTo(goAppend);
    return panel;
}
function createTabs(goAppend,isSortable,idName) {
    var tabList = $("<ul>");
    var tabsContainer = createContainer()
        .attr("id",idName)
        .css({"height":"99%"})
        .appendTo(goAppend);
    tabList.appendTo(tabsContainer);
    tabsContainer.tabs().delegate( "span.ui-icon-close", "click", function() {
      console.log("JR removing this tab");
      $("#JRMainTabs").tabs( "refresh" );
    });
    if (isSortable) tabList.sortable({placeholder:"sortable-placeholder",delay:300,"items":"li:not(.ui-not-sortable)",dropOnEmpty: true});
    return tabsContainer;
}
function createTab(tabContainer,theTitle,isSortable,theID,tabData,appendClose) {
    var theClasses = (!appendClose) ? "ui-not-sortable" : "";
    var theTabDiv = createContainer().attr("id","tabs-" + (++gTabIndex));
    var theTabLi = $("<li>").html("<a href='#tabs-" + gTabIndex + "'>" + theTitle + "</a>")
        .attr({"id":theID,"class":theClasses})
        .css({"font-size":"10px"})
        .data({"tabData":tabData})
        .appendTo( tabContainer.find("ul") );
    if (appendClose) theTabLi.append(createSpan("Remove Tab").attr({"class":"ui-icon ui-icon-close","role":"presentation"}));
    theTabDiv.data({"tabData":tabData}).appendTo(tabContainer);
    if (isSortable) {
        theTabLi.click( function() { $(this).focus(); $(this).find(".tabContents").focus(); })
            .droppable({
                tolerance: 'pointer',
                over: function( event, ui ) {
                    $("#JRMainTabs").tabs("option", "active", $(event.target).index());
                    $(event.target).focus(); $(event.target).find(".tabContents").focus();
                }
            });
        theTabDiv.html("<br clear='all' class='cleartab'></br>");
    }
    tabContainer.tabs("refresh");
    return theTabDiv;
}
function playSoundNow( AudioObject ) {
    if (gSoundFile) gSoundFile.pause();
    gSoundFile = AudioObject;
    gSoundFile.currentTime = 0;
    gSoundFile.volume = gMainOptions.alarmVolume/100;
    gSoundFile.play();
}

var theCycler = (function() {
    var privateVars = {
        _timers: [],
        _theQueue: [],
        _theFrontOfTheLineQueue: [],
        _theFrontOfTheLineTimer: [],
        _before: new Date(),
        _theCycle: 500,
        _realCycle: 500,
        _theCycleElapsed: 0,
        _theCycleSkipping: 0,
        _paused: false,
        _hamNumber: 0,
        _timeoutVar: null
    }

    var privateFunctions = {
        _getInTimer: function(theNumber) {
             for (var i=0, len=privateVars._timers.length; i<len; i++) {
                 if (privateVars._timers[i].theNumber == theNumber) return(privateVars._timers[i]);
            }
            return null;
       },
        _checkInQueue: function(theNumber) {
            for (var i=0, len=privateVars._theQueue.length; i<len; i++) {
                if (privateVars._theQueue[i].theNumber == theNumber) return(i);
            }
            return -1;
        },
        _removeFromQueue: function(theNumber) {
            var foundNumber = privateFunctions._checkInQueue(theNumber);
            if (foundNumber != -1) return privateVars._theQueue.splice(foundNumber, 1)[0];
            else return null;
        },
        _goFrontOfTheLineTimer: function() {
            var frontOfTheLineNumber = privateVars._theFrontOfTheLineTimer.shift();
            var frontOfTheLineItem = privateFunctions._getInTimer(frontOfTheLineNumber);
            if (frontOfTheLineItem) {
                frontOfTheLineItem.runFunction.apply("frontoftheline",[frontOfTheLineItem.elapsed,frontOfTheLineItem.theNumber] );
                return true;
            } else return false;
        },
        _goFrontOfTheLine: function() {
            var frontOfTheLineNumber = privateVars._theFrontOfTheLineQueue.shift();
            var frontOfTheLineItem = privateFunctions._removeFromQueue(frontOfTheLineNumber);
            if (frontOfTheLineItem) {
                privateVars._theQueue.push(frontOfTheLineItem);
                frontOfTheLineItem.runFunction.apply("frontoftheline",[privateVars._theCycleElapsed,frontOfTheLineItem.theNumber] );
                return true;
            } else return false;
        },
        _goHam: function() {
            var hamCalled = false;
            var foundNumber = privateFunctions._checkInQueue(privateVars._hamNumber);
            if (foundNumber != -1) {
                hamCalled = privateVars._theQueue[foundNumber].runFunction.apply("goham",[privateVars._theCycleElapsed,privateVars._hamNumber] );
            }
            return hamCalled;
        },
        _doTimers: function() {
            var timerCalled = false;
            for(var i=0, len=privateVars._timers.length; i<len; i++) {
                privateVars._timers[i].elapsed += privateVars._theCycleElapsed;
                if (privateVars._timers[i].elapsed >= privateVars._timers[i].miliSeconds) {
                    var returnStatus = privateVars._timers[i].runFunction.apply("timer",[privateVars._timers[i].elapsed,privateVars._timers[i].theNumber] );
                    privateVars._timers[i].elapsed = 0;
                    if (returnStatus && privateVars._timers[i].cycleTimer) timerCalled = true;
                }
            }
            return timerCalled;
        },
        _doQueue: function() {
            var skipThis = true;
            var firstTime = true;
            var firstNumber = privateVars._theQueue[0].theNumber;
            do {
                var queueItem = privateVars._theQueue.shift();
                privateVars._theQueue.push(queueItem);
                skipThis = !queueItem.runFunction.apply("queue",[privateVars._theCycleElapsed,queueItem.theNumber] );
            } while (privateVars._theQueue.length > 0 && skipThis && firstNumber != privateVars._theQueue[0].theNumber);
        },
        _theLoop: function() {
            var continueCheck = true;
            var elapsed = new Date().getTime() - privateVars._before.getTime();
            if (elapsed >= privateVars._realCycle) {
                privateVars._theCycleElapsed = elapsed;
                privateVars._before = new Date();
                if (privateVars._theFrontOfTheLineTimer.length > 0) continueCheck = !privateFunctions._goFrontOfTheLineTimer();
                if (privateVars._theFrontOfTheLineQueue.length > 0) continueCheck = !privateFunctions._goFrontOfTheLine();
                if (continueCheck && privateVars._timers.length>0) continueCheck = !privateFunctions._doTimers();
                if (continueCheck && privateVars._hamNumber != 0) { continueCheck = false; privateFunctions._goHam(); }
                if (continueCheck && privateVars._theQueue.length>0) {
                    privateFunctions._doQueue();
                }
            }
            privateVars._timeoutVar = setTimeout(privateFunctions._theLoop, 0);
        }
    }
    var output = {
        addJob: function(func, theNumber, miliSeconds, cycleTimer) {
            if (typeof func === 'function' && !isNaN(miliSeconds)) {
                if (privateFunctions._checkInQueue(theNumber)!=-1) return;
                for(var i=0, len=privateVars._timers.length; i<len; i++) {
                    if (privateVars._timers[i].theNumber == theNumber) return;
                }
                var jobData = {'theNumber': theNumber, 'runFunction': func, 'miliSeconds': miliSeconds, 'cycleCounter': 0, 'elapsed': miliSeconds, 'cycleTimer': cycleTimer};
                if (miliSeconds == 0) privateVars._theQueue.push(jobData);
                else if (miliSeconds > 0) privateVars._timers.push(jobData);
            }
            if (privateVars._timeoutVar===null) privateFunctions._theLoop();
        },
        removeJob: function(theNumber) {
            var returnValue = false;
            privateFunctions._removeFromQueue(theNumber);
            for (var i=0, len=privateVars._timers.length; i<len; i++) {
                if (privateVars._timers[i].theNumber == theNumber) {
                    privateVars._timers.splice(i, 1);
                    returnValue=true;
                    break;
                }
            }
            if (privateVars._theQueue.length == 0 && privateVars._timers.length == 0) privateVars._timeoutVar = null;
            return returnValue;
        },
        pause: function() {
            privateVars._paused = true;
            clearTimeout(privateVars._timeoutVar);
        },
        isPaused: function() { return privateVars._paused; },
        unpause: function() {
            privateVars._paused = false;
            if (privateVars._timers.length>0 || privateVars._theQueue.length>0) 
                privateVars._timeoutVar = setTimeout(privateFunctions._theLoop, 0);
        },
        frontOfTheLineTimer: function( theNumber ) { privateVars._theFrontOfTheLineTimer.push(theNumber); },
        frontOfTheLine: function( theNumber ) { privateVars._theFrontOfTheLineQueue.push(theNumber); },
        hamOn: function( theNumber ) { privateVars._hamNumber = theNumber; },
        hamOff: function() { privateVars._hamNumber = 0; },
        isHamOn: function() { return (privateVars._hamNumber>0) ? true : false; },
        jobs: function() { return privateVars._theQueue.length; },
        skippingReset: function() { privateVars._theCycleSkipping = 0; privateVars._realCycle = privateVars._theCycle; },
        cycleIncrease: function(increaseNumber) { 
            increaseNumber = increaseNumber || gMainOptions.cycleIncrease;
            privateVars._theCycleSkipping += increaseNumber; 
            privateVars._realCycle += increaseNumber;
        },
        cycleDecrease: function() {
            privateVars._theCycleSkipping = (privateVars._theCycleSkipping > 0)
                ? privateVars._theCycleSkipping -= gMainOptions.cycleDecrease : 0;
            privateVars._realCycle = privateVars._theCycle + privateVars._theCycleSkipping;
        },
        cycle: function() { return privateVars._theCycle; },
        cycleSkipping: function() { return privateVars._theCycleSkipping; },
        cycleChange: function(newSkipping) { 
            privateVars._theCycleSkipping = newSkipping; privateVars._realCycle = privateVars._theCycle + privateVars._theCycleSkipping;
        },
        cycleAdd: function(newSkipping) { 
            privateVars._theCycleSkipping += newSkipping; privateVars._realCycle = privateVars._theCycle + privateVars._theCycleSkipping;
        },
        cycleResetChange: function(newCycle) { 
            privateVars._theCycle = newCycle; privateVars._theCycleSkipping = 0; privateVars._realCycle = newCycle;
        }
    };
    return output;
})();

function displayMainStatus() {
    var statusText = "", theMode="";
    var theJobs = (gMainData.jobs==0) ? "-- No Jobs to Search. " : "-- Running: " + gMainData.jobs + " jobs ";
    $("#JrMainStatus .JRJobsArea").html(theJobs);
    theMode = $("#JrMainStatus .JRCycleInfoArea").data("mode");
    var theCycle = (theMode=="Elapsed") ? "[ Elapsed Time: " + gMainData.lastElapsed + "ms | " : 
        (theMode=="Cycle") ? "[ Cycling every: " + theCycler.cycle() + "ms | " :
        (theMode=="CycleSkipping") ? "[ Cycling Slowed: " + theCycler.cycleSkipping() + "ms | " : 
        (theMode=="Hamcycle") ? "[ Min Ham Cycle: " + gMainOptions.HamCycleNumber + "ms | " : "";
    if (isActiveMenu(gMainMenu,"Cycle")) { 
        theCycle = "[ Elapsed Time: " + gMainData.lastElapsed + "ms | Cycling every: " + theCycler.cycle() + "ms | Cycling Slowed: " + 
            theCycler.cycleSkipping() + "ms | Min Ham Cycle: " + gMainOptions.HamCycleNumber + "ms ]";
        $("#JrMainStatus .JRCycleInfoArea").html(theCycle);
        $("#JrMainStatus .JRResultAccSkipArea").html("");
        $("#JrMainStatus .JRErrorArea").html("");
        $("#JrMainStatus .JRMturkQueueArea").html("");
        $("#JrMainStatus .JRSearchedArea").html("");
        $("#JrMainStatus .JRPayArea").html("");
    } else {
        $("#JrMainStatus .JRCycleInfoArea").html(theCycle);
        theMode = $("#JrMainStatus .JRResultAccSkipArea").data("mode");
        var theAccSkip = (theMode=="Accepted") ? "Accepted: " + gMainData.accepted + " | " : 
            (theMode=="Skipped") ? "Skipped: " + gMainData.skipped + " | " : "";
        $("#JrMainStatus .JRResultAccSkipArea").html(theAccSkip);
        theMode = $("#JrMainStatus .JRErrorArea").data("mode");
        var theErrors = (theMode=="Errors") ? "Errors: " + gMainData.errors + " | " : 
            (theMode=="TooFast") ? "Too Fast: " + gMainData.tooFast + " | " : "";
        $("#JrMainStatus .JRErrorArea").html(theErrors);
        $("#JrMainStatus .JRMturkQueueArea").html("Mturk Queue: " + gMainData.hitsInQueue + " | ");
        $("#JrMainStatus .JRSearchedArea").html("Searched: " + gMainData.searched + " | ");
        $("#JrMainStatus .JRPayArea").html("Pay Accepted: " + gMainData.payCounter.toFixed(2) + " ]");
    }
}
function displayControlsStatus() {
}
function displayHitStatus( theNumber ) {
    var hitInfo = gMainData.hitCollection[theNumber];
    var hitStatus = hitInfo.status;
    var statusText = "";
    statusText += "[ Acc: " + hitStatus.accepted + " | Skip: " + hitStatus.skipped + " | Srch: " + hitStatus.searched + " ] ";
    $("#JRCellStatus_" + theNumber).html( statusText );
    displayMainStatus();
}
function processResults( theNumber, result ) {
    var hitInfo = (theNumber>0) ? gMainData.hitCollection[theNumber] : null;
    var hitData = (hitInfo) ? hitInfo.data : null;
    var hitStatus = (hitInfo) ? hitInfo.status : null;
    switch(result) {
        case "NOTQUALIFIED":
            if (hitStatus) hitStatus.notQual++;
            gMainData.notQual++;
            break;
        case "NOMORE":
        case "NOACCEPT":
            if (hitStatus) hitStatus.noHits++;
            gMainData.noHits++;
            break;
        case "TOOFAST":
            if (hitStatus) hitStatus.tooFast++;
            gMainData.tooFast++;
            theCycler.cycleIncrease(gMainOptions.cycleAutoIncrease);
            break;
        case "LOGGEDOFF":
            theCycler.pause();
            $("#JRPauseButton").html("Resume").css({"background-color":"red","color":"white"});
            alert("You are logged out of Amazon. Can't accept hits. Please log back in");
            break;
        case "DAILYLIMIT":
            theCycler.pause();
            $("#JRPauseButton").html("Resume").css({"background-color":"red","color":"white"});
            alert("Congratulations!! You have reached your daily limit. Wait for tomorrow.");
            break;
        case "NOTCOMPLETED":
        case "ERROR":
            if (hitStatus) hitStatus.error++;
            gMainData.error++;
            break;
        case "QUEUEMAX":
            if (hitStatus) hitStatus.fullQueue++;
            gMainData.fullQueue++;
            break;
        case "SKIPPED":
            if (hitStatus) hitStatus.skipped++;
            gMainData.skipped++;
            break;
        case "ACCEPTED":
            if (hitStatus) hitStatus.accepted++;
            if (hitData.hamTimer > 0) hitInfo.lastAccept = new Date();
            var newDate = new Date().setHours(0,0,0,0);
            if (hitData.dailyLimit && hitData.dailyLimit>0) hitData.dailyDone = (newDate == hitData.day) ? hitData.dailyDone + 1 : 1;
            if (hitData.once) hitData.dailyDone = 1;
            hitData.day = newDate;
            gMainData.accepted++;
            gMainData.hitsInQueue++;
            var hitPay = parseFloat(hitData.pay);
            gMainData.payCounter = Math.round( (gMainData.payCounter + hitPay) * 100) / 100;
            var theDuration = hitInfo.minutes;
            if (theDuration==0 && hitData.duration!="0") {
                theDuration = (hitData.duration.indexOf("weeks")!=-1) ? 5000 : (hitData.duration.indexOf("day")!=-1) ? 1500 : (hitData.duration.indexOf("hours")!=-1) ? 200 : 
                    (hitData.duration.indexOf("hour")!=-1) ? 60 : (hitData.duration.indexOf("minutes")!=-1) ? parseInt(hitData.duration.split("minutes")[0]) : 1;
                hitInfo.minutes = theDuration;
            }
            var theSoundFile = "less99";
            var notificationTitle = "Accepted Hit From: " + hitData.requesterName;
            var notificationMessage = "Pay: " + hitData.pay + "\nDuration: " + hitData.duration + "\nTitle: " + hitData.title;
            if (!hitData.mute) {
                if ( hitPay < 0.02 ) { theSoundFile = (theDuration != 0 && theDuration<=2) ? "less2Short" : "less2"; }
                else if ( hitPay <= 0.05 ) { theSoundFile =  (theDuration != 0 && theDuration<=5) ? "less5Short" : "less5"; }
                else if ( hitPay <= 0.15 ) { theSoundFile = (theDuration != 0 && theDuration<=15) ? "less15Short" : "less15"; }
                else if ( hitPay < 0.99 ) { theSoundFile = "less99"; }
                if (hitData.audioforce != "") theSoundFile = hitData.audioforce;
                playSoundNow(gAlarmSounds[theSoundFile].audio);
            }
            $("#JRCellNum_" + theNumber).stop(true,true);
            $("#JRCellNum_" + theNumber).css({"background-color":"yellow"});
            $("#JRCellNum_" + theNumber).animate({backgroundColor: $("#JRCellNum_" + theNumber).data("backgroundColor")}, 40000);
            if (gNotifications) showNotification( notificationTitle, notificationMessage, "accepted");
            if ( hitInfo.ham == "paused" ) toggleButton($("#JRHamB_" + theNumber),hamOn,hamOff);
            addToAcceptedLog( hitData.requesterName + " - <a href='" + pandaLink(hitData.groupId) + "' target='_blank' style='color:cyan;'>" + hitData.groupId + "</a> - " + hitData.title );
            updateHitCell(theNumber);
            break;
    }
    if (theNumber > 0) displayHitStatus(theNumber);
}

function requestUrl(theUrl, theNumber, theFunction, errorFunction, data1, data2, theResponseType) {
    var theResponseType = theResponseType || "";
    GM_xmlhttpRequest({
        method: "GET",
        url: theUrl,
        responseType: theResponseType,
        onload: function(response) { if (typeof theFunction == 'function') theFunction(response,theNumber,data1,data2); },
        onerror: function(response) { if (typeof errorFunction == 'function') errorFunction(response,theNumber); }
    });
}

function pandaLink(thegroupId) { return "https://www.mturk.com/mturk/previewandaccept?groupId=" + thegroupId; }
function previewLink(thegroupId) { return "https://www.mturk.com/mturk/preview?groupId=" + thegroupId; }
function requesterSearch(theRequester) { return "https://www.mturk.com/mturk/searchbar?selectedSearchType=hitgroups&qualifiedFor=on&requesterId=" + theRequester; }
function acceptLink(theHitData) { return "https://www.mturk.com/mturk/accept?hitId=" + theHitData.hitId + "&prevHitSubmitted=" + theHitData.prevHitSubmitted +
    "&prevRequester=" + theHitData.prevRequester + "&prevReward=" + theHitData.prevReward + "&requesterId=" + theHitData.requesterId + "&groupId=" + 
    theHitData.groupId + "&signature=" + theHitData.signature;
}
function checkLimits(theNumber) {
    //console.log("JR checking " + theNumber + " for their limits.");
    var hitInfo = gMainData.hitCollection[theNumber];
    var hitData = hitInfo.data;
    var returnValue = false;
    if (hitData.queueLimit == 0 && hitData.dailyLimit == 0 && !hitData.once) returnValue = true;
    else if (hitData.once && hitData.dailyDone>0) {
        if (hitInfo.hitCell.data("status")=="on") hitInfo.hitCell.data("status","off");
        toggleButtonOff( hitInfo.hitCell.find(".JRCollectButton"),startCollecting,stopCollecting);
        console.log("JR found 1 so turning off.");
        returnValue = false;
    } else if (hitData.dailyLimit > 0 && hitData.dailyLimit < gMainData.dailyDone) returnValue = false;
    else if (hitData.queueLimit > 0 && hitData.queueLimit <= gMainData.hitsInQueue) returnValue = false;
    else returnValue = true;
    return returnValue;
}
function searchRequestersInfo( theNumber, hitNumber, requestersInfo ) {
    var hitInfo = gMainData.hitCollection[hitNumber];
    var hitData = hitInfo.data;
    if (hitInfo.collecting != "off") {
        hitInfo.status.searched++;
        displayHitStatus(hitNumber);
        for (var i=0, len=requestersInfo.data.length; i<len; i++) {
            if ( requestersInfo.data[i].groupId == hitData.groupId ) {
                //console.log("JR found something");
                return i;
            }
        }
    }
    return -1;
}
function parseHitSearchPage(theResult,theNumber) {
    var hitInfo = (theNumber>0) ? gMainData.hitCollection[theNumber] : null;
    var hitData = (hitInfo) ? hitInfo.data : null;
    var parser = new DOMParser();
    var xmlDoc = parser.parseFromString(theResult.responseText,"text/html");
    var errorTitle_Array = xmlDoc.getElementsByClassName("error_title");
    var errorTitle = (errorTitle_Array.length) ? errorTitle_Array[0] : null;
    if (errorTitle && errorTitle.innerHTML.indexOf("You have exceeded the maximum allowed page request rate") != -1) {
        processResults( theNumber, "TOOFAST" );
        return;
    } else if (errorTitle && errorTitle.innerHTML.indexOf("Your search did not match any HITs") != -1) {
        return;
    } else {
        //console.log("JR HitsearchPage : might have something");
        var tempNode = $(xmlDoc).find("#sortresults_form");
        if ($(tempNode).length) {
            //console.log("JR HitsearchPage : checking something");
            var requestersInfo = {"counter":0,"data":[]};
            $(tempNode).next("table").find("tbody:first").children("tr").each( function() {
                //console.log("JR HitsearchPage : checking a hit");
                requestersInfo.data[requestersInfo.counter] = {};
                var capsuleNode = $(this).find("a#capsule" + requestersInfo.counter + "-0");
                if (capsuleNode) {
                    //console.log("JR HitsearchPage : hit capsuleNode found");
                    var title = $(capsuleNode).html().split("<span")[0];
                    var playerClass = $(this).find('a[id^="private_hit.view_a_HIT_in_group.tooltip"]');
                    var groupIdNumber = (playerClass.length) ? "" : $(capsuleNode).closest("tr").find("a:contains('View a HIT in this group')")
                        .attr("href").replace("/mturk/preview?groupId=","");
                    console.log("JR HitsearchPage : I found this groupID: " + groupIdNumber);
                    var requesterIdentity = $(this).find("span.requesterIdentity");
                    var requesterName = $(requesterIdentity).html().trim();
                    var capsuleFieldTextIdentity = $(requesterIdentity).closest(".capsule_field_text").find("a");
                    var requesterIdNumber = (capsuleFieldTextIdentity.length) ? $(capsuleFieldTextIdentity).attr("href")
                        .replace("/mturk/searchbar?selectedSearchType=hitgroups&requesterId=","") : "";
                    var rewardNode = $(this).find("#reward\\.tooltip--" + requestersInfo.counter);
                    var thePay = ( $(rewardNode).length ) ? $(rewardNode).parent().next().find("span").html().replace("$","").trim() : "";
                    if (gExcludeIds.indexOf(groupIdNumber)==-1) {
                        console.log("JR HitsearchPage : found a hit");
                        requestersInfo.data[requestersInfo.counter].requesterName = requesterName;
                        requestersInfo.data[requestersInfo.counter].hitTitle = title;
                        requestersInfo.data[requestersInfo.counter].requesterId = requesterIdNumber;
                        requestersInfo.data[requestersInfo.counter].groupId = groupIdNumber;
                    } else console.log("JR excluded hit");
                    requestersInfo.counter++;
                }
            });
            var foundTheNumber = -1;
            if (requestersInfo.data.length > 0) {
                console.log("JR HitsearchPage : I found some hits: " + requestersInfo.data.length);
                var goUrl = ""; console.log("HitsearchPage : Number=" + theNumber);
                if (theNumber<=0) {
                    $.each(gMainData.hitCollection, function( index, value ) {
                        foundTheNumber = searchRequestersInfo(index, index, requestersInfo);
                        if (foundTheNumber != -1) {
                            console.log("HitsearchPage : I found a matching hit for a panda: " + requestersInfo.data[foundTheNumber].groupId);
                            goUrl = (value.data.action=="SearchAndFilter") ? previewLink(requestersInfo.data[foundTheNumber].groupId) : pandaLink(requestersInfo.data[foundTheNumber].groupId);
                            gMainData.hitCollection[0].goToUrl.push({"url":goUrl,"theNumber":i});
                        }
                    });
                } else {
                    for (var i=0, len=requestersInfo.data.length; i<len; i++) {
                        goUrl = (hitData.action=="SearchAndFilter") ? previewLink(requestersInfo.data[i].groupId) : pandaLink(requestersInfo.data[i].groupId);
                        hitData.groupId = requestersInfo.data[i].groupId; console.log("HitsearchPage : GroupID=" + requestersInfo.data[i].groupId);
                        hitInfo.newTitle = requestersInfo.data[i].hitTitle
                        hitInfo.goToUrl.push({"url":goUrl,"theNumber":theNumber});
                        updateHitCell(theNumber);
                    }
                    if (hitData.maxHam!="" && hitData.maxHam!="0" && hitInfo.ham=="on") hamOn(theNumber);
                    theCycler.frontOfTheLine(theNumber);
                }
            }
        }
    }
}
function parseQueuePage(theResult,theNumber) {
    var parser = new DOMParser();
    var xmlDoc = parser.parseFromString(theResult.responseText,"text/html");
    var alertBoxHeader = $(xmlDoc).find("#alertboxHeader");
    if ($(xmlDoc).find("td.error_title:contains('There are currently no HITs assigned to you.')").length > 0) {
        //addToStatusLog("---- nothing in queue");
        gMainData.hitsInQueue = 0;
    } else {
        var numberQueueText = $(xmlDoc).find("td.title_orange_text").html();
        if (numberQueueText) {
            var words = numberQueueText.trim().split(' ');
            if ($.isNumeric(words[words.length - 2])) gMainData.hitsInQueue = parseInt(words[words.length - 2]);
        }
    }
}
function errorRequest(res,theNumber) {
    console.log("error: " + res.statusText);
    //setStatusText(theNumber,"...... Searching - Error .....","errors");
}
function parseZingHitPage(theResult,theNumber,formData) {
    var parser = new DOMParser();
    var xmlDoc = parser.parseFromString(theResult.responseText,"text/html");
    var hitInfo = gMainData.hitCollection[theNumber];
    var hitData = hitInfo.data;
    
    var thisZingOptions = gZingOptions[hitData.pay];
    thisZingOptions = (gZingOptions[hitData.pay]) ? gZingOptions[hitData.pay] : gZingOptions["0.01"];
    
    var goAccept = false;
    var theSearching = $(xmlDoc).find(".row-fluid .span6").eq(0);
    var receiptItemsCount = $(theSearching).find(".receipt_items .fieldswrapper").length;
    var inputCount = $(theSearching).find("input[type=text]").length;
    var multipleQuantityCount = $(theSearching).find("input[type=text].multiple_quantity").length;
    var codesCount = inputCount - 1 - multipleQuantityCount;
    var thePicturesCount = $(xmlDoc).find(".receipt_images").eq(0).find("img").length; //console.log("pictures: " + thePicturesCount);
    
    var limitReceptItems = thisZingOptions.SearchGroupAllowed;
    var limitTallyCount = thisZingOptions.TallyCountTotalAllowed;
    var limitCodes = (thisZingOptions.AcceptCodesSearching) ? 10 : 0;
    var limitImages = thisZingOptions.MaxReceiptImages;
    if (receiptItemsCount <= limitReceptItems && multipleQuantityCount <= limitTallyCount && codesCount <= limitCodes && thePicturesCount <= limitImages) goAccept = true;
    if ( goAccept ) {
        if (checkLimits(theNumber)) {
            var acceptHitURL = acceptLink(formData);
            hitInfo.goToUrl.push({"url":acceptHitURL,"theNumber":theNumber});
            theCycler.frontOfTheLine(theNumber);
        } else {
            $("#JRCellNum_" + theNumber).stop(true,true);
            $("#JRCellNum_" + theNumber).css({"background-color":"#FF9999"});
            $("#JRCellNum_" + theNumber).animate({backgroundColor: $("#JRCellNum_" + theNumber).data("backgroundColor")}, 40000);
        }
    } else processResults( theNumber, "SKIPPED" );
}
function parseMturkHitPage(theResult,theNumber) {
    var hitInfo = gMainData.hitCollection[theNumber];
    var hitData = hitInfo.data;
    var parser = new DOMParser();
    var xmlDoc = parser.parseFromString(theResult.responseText,"text/html");
    var alertBoxHeader = xmlDoc.getElementById("alertboxHeader");
    var dailyLimit = false;
    if (alertBoxHeader) {
        var alertHeaderHTML = alertBoxHeader.innerHTML;
        if (alertHeaderHTML.indexOf("There are no more available HITs") != -1 || alertHeaderHTML.indexOf("There are no HITs in this group") != -1) {
            processResults( theNumber, "NOMORE" );
            return;
        } else if (alertHeaderHTML.indexOf("You have accepted the maximum number of HITs allowed") != -1) {
            processResults( theNumber, "QUEUEMAX" );
            return;
        } else if (alertHeaderHTML.indexOf("The HIT you were viewing could not be accepted") != -1) {
            processResults( theNumber, "NOACCEPT" );
            return;
        } else if (alertHeaderHTML.indexOf("You are not qualified to accept") != -1 || alertHeaderHTML.indexOf("Your Qualifications do not meet the") != -1) {
            processResults( theNumber, "NOTQUALIFIED" );
            return;
        }
        dailyLimit = (alertHeaderHTML.indexOf("There are no HITs available for you at this time") != -1);
    }
    var loggedOff1 = xmlDoc.getElementById("ap_signin_custom_message");
    var loggedOff2 = xmlDoc.getElementById("#lnkWorkerSignin");
    var loggedOff3 = xmlDoc.getElementById("#signin-slot");
    if (loggedOff1 || loggedOff2 || loggedOff3) {
        processResults( theNumber, "LOGGEDOFF" );
        return;
    }
    var errorTitle = $(xmlDoc).find("td.error_title").eq(0);
    var hitAccepted = $(xmlDoc).find("img[src$='/media/return_hit.gif']");
    var notAccepted = $(xmlDoc).find("input[src$='/media/accept_hit.gif']");
    if (errorTitle.length && errorTitle.html().indexOf("You have exceeded the maximum allowed page request rate") != -1) {
        processResults( theNumber, "TOOFAST" );
    } else if (errorTitle.length && errorTitle.html().indexOf("Your request was not completed successfully") != -1) {
        processResults( theNumber, "NOTCOMPLETED" );
    } else if (dailyLimit) {
        processResults( theNumber, "DAILYLIMIT" );
    } else if (hitAccepted.length) {
        var updated = false;
        var hitGroupId = ($(xmlDoc).find("form[name='hitForm']").length) ? $(xmlDoc).find("form[name='hitForm']").eq(0).find("input[name='groupId']").eq(0).val() : "";
        hitData.groupId = hitGroupId;
        var capsuleNode = $(xmlDoc).find("td.capsulelink_bold:first div").eq(0);
        var theTitle = (capsuleNode.length) ? $(capsuleNode).html().trim() : hitData.title;
        if (hitData.title != theTitle) { hitData.title = theTitle; updated=true; }
        var timeLeft = $(xmlDoc).find("a#time_left\\.tooltip");
        var theDuration = (timeLeft.length) ? timeLeft.parent().next().html().trim() : hitData.duration;
        if (hitData.duration != theDuration) { hitData.duration = theDuration; updated=true; }
        var requesterTip = $(xmlDoc).find("#requester\\.tooltip");
        var requesterNameNode = (requesterTip.length) ? $(requesterTip).eq(0).parent().next() : null;
        var theRequesterName = ($(requesterNameNode)) ? ( ($(requesterNameNode).find("a").length) ? $(requesterNameNode).find("a").html().trim() : $(requesterNameNode).html().trim() ) : "";
        theRequesterName = (theRequesterName) ? theRequesterName : hitData.requesterName;
        if (hitData.requesterName != theRequesterName) { hitData.requesterName = theRequesterName; updated=true; }
        var numberHitsTip = $(xmlDoc).find("#number_of_hits\\.tooltip");
        var theNumberHits = (numberHitsTip.length) ? numberHitsTip.parent().next().html().trim() : hitInfo.numberHits;
        hitInfo.numberHits = theNumberHits;
        var rewardTip = $(xmlDoc).find("#reward\\.tooltip");
        var theReward = (rewardTip.length) ? rewardTip.parent().next().find("span").html().replace("$","").trim() : hitData.pay;
        if (hitData.pay != theReward) { hitData.pay = theReward; updated=true; }
        processResults( theNumber, "ACCEPTED" );
        if (updated) gDelayedSave = true;
        console.log("accepted: " + theNumber + " | updated: " + updated + " | groupId: " + hitGroupId);
    } else if (notAccepted.length) {
        var formData = {};
        formData.hitId = $(xmlDoc).find("input[name='hitId']").eq(0).val();
        formData.prevHitSubmitted = $(xmlDoc).find("input[name='prevHitSubmitted']").eq(0).val();
        formData.prevRequester = $(xmlDoc).find("input[name='prevRequester']").eq(0).val();
        formData.requesterId = $(xmlDoc).find("input[name='requesterId']").eq(0).val();
        formData.prevReward = $(xmlDoc).find("input[name='prevReward']").eq(0).val();
        formData.groupId = $(xmlDoc).find("input[name='groupId']").eq(0).val();
        formData.signature = $(xmlDoc).find("input[name='signature']").eq(0).val();
        var iframeSrc = $(xmlDoc).find("iframe").attr("src");
        var acceptHitURL = acceptLink(formData);
        if (iframeSrc) {
            if (formData.requesterId=="AGVV5AWLJY7H2") {
                if (hitData.filterMode>0 && hitData.filterMode <= Object.keys(gZingFuncOptions).length) {
                    requestUrl(iframeSrc, theNumber, gZingFuncOptions[hitData.filterMode].functionName, errorRequest, formData, "");
                } else {
                    console.log("Filter Mode is off");
                    hitInfo.goToUrl.push({"url":acceptHitURL,"theNumber":theNumber});
                    theCycler.frontOfTheLine(theNumber);
                }
            }
        }
    } else { processResults( theNumber, "ERROR" ); }
}

function makeStatus() { return {"accepted":0,"skipped":0,"errors":0,"tooFast":0,"noHits":0,"fullQueue":0,"hitsStreak":0,"noHitsStreak":0,"searched":0,"orphan":0,"hitsResults":0,"notQual":0}; }
function buttonStatus(buttonName,theData,buttonChange) {
    if (buttonName=="collect") {
    } else if (buttonName=="ham") {
    }
}
function addHitCollection(theData,theNumber,tabIndex) {
    var pandaUrl = pandaLink(theData.groupId);
    var previewUrl = previewLink(theData.groupId);
    var filterFuncData = (theData.action.indexOf("Filter") != -1) ? ((theData.requesterId=="AGVV5AWLJY7H2") ? gZingFuncOptions : null) : null;
    gMainData.hitCollection[theNumber] =
        {"collecting":"off","pandaUrl":pandaUrl,"previewUrl":previewUrl,"goToUrl":[],"theNumber":theNumber,"data":theData,"status":makeStatus(),"specialOptions":null,"hitCell":null,"ham":"off","minutes":0,"newTitle":"","numberHits":"0","once":false,"filterFuncData":filterFuncData,"searching":"off","lastAccept":null,"tabIndex":tabIndex};
    return theNumber;
}
function findHitsPageOff(thisButton) {
    $(thisButton).data("useHitSearch","off");
    theCycler.removeJob(-10);
    theCycler.hamOff();
}
function findHitsPageOn( thisButton ) {
    var theHitNumber = null, hitInfo = null, hitData = null, okToPanda = false;  
    if ( theCycler.isHamOn ) hamOff();
    $(thisButton).data("useHitSearch","on");
    theCycler.addJob( function( elapsed, theNumber ) {
        if (gMainData.hitCollection[0].goToUrl.length) {
            var theGoToUrl = gMainData.hitCollection[0].goToUrl.shift();
            var hitInfo = gMainData.hitCollection[theGoToUrl.theNumber];
            var hitData = hitInfo.data;
            if (checkLimits(theGoToUrl.theNumber)) {
                gMainData.lastElapsed = elapsed;
                requestUrl(theGoToUrl.url,theGoToUrl.theNumber,parseMturkHitPage, errorRequest);
            }
        } else {
            gMainData.searched++;
            gMainData.lastElapsed = elapsed;
            requestUrl("https://www.mturk.com/mturk/sortsearchbar?searchSpec=HITGroupSearch%23T%231%2310%23-1%23T%23!only_available_hits!0!rO0ABXQABHRydWU-!keyword_list!2!rO0ABXQAAA--!Reward!6!rO0ABXQABDAuMDA-!%23!LastUpdatedTime!1!%23!&selectedSearchType=hitgroups&searchWords=&sortType=LastUpdatedTime%3A1&%2Fsort.x=14&%2Fsort.y=9", -10 ,parseHitSearchPage,errorRequest, "" );
        }
        displayMainStatus();
        return true;
    }, -10, 0, true);
    theCycler.hamOn(-10);
}
function addQueueCheck() {
    theCycler.addJob( function( elapsed, theNumber ) {
        gMainData.queueStatus.searched++;
        requestUrl("https://www.mturk.com/mturk/myhits",1,function(theResult,theNumber,data1,data2) {
            //console.log("checking queue number");
            return parseQueuePage(theResult);
        },function() { errorRequest(); } );
        displayMainStatus();
        return true;
    }, -1, gMainOptions.queueTimer, true);
}
function startCollecting(theNumber,thisButton) {
    var hitInfo = gMainData.hitCollection[theNumber], theGoToUrl = null;
    var hitData = hitInfo.data;
    if (hitData.once) hitData.dailyDone = 0;
    hitInfo.collecting = "on";
    console.log("Turning on " + theNumber);
    theCycler.addJob( function( elapsed, theNumber ) {
        var hitInfo = gMainData.hitCollection[theNumber];
        var hitData = hitInfo.data;
        if (hitInfo.ham == "ontimed") { 
            if (hitData.hamTimer > 0 && hitInfo.lastAccept) {
                var nowTime = new Date();
                var elapsedTime = nowTime - hitInfo.lastAccept;
                var theSeconds = elapsedTime / 1000;
                var theMinutes = Math.floor(theSeconds / 60);
                var offHamMode = (hitInfo.ham == "ontimed") ? "paused" : "off";
                if (theSeconds >= hitData.hamTimer) {
                    toggleButton($("#JRHamB_" + theNumber),hamOn,hamOff,offHamMode);
                    hitInfo.lastAccept = null;
                }
            }
        }
        //console.log("going to checklimits for " +theNumber+ " hitInfo status = " + hitInfo.hitCell.data("status"));
        if ( checkLimits(theNumber) ) {
            hitInfo.status.searched++;
            if (hitInfo.goToUrl.length) {
                console.log("Found a gotoUrl so I must do Url");
                if ( (hitInfo.data.action.substring(0,6) == "Search" || hitInfo.data.action == "FilterPanda") && !hitInfo.hitCell.data("firstPanda") )
                    theGoToUrl = hitInfo.goToUrl.shift();
                else theGoToUrl = hitInfo.goToUrl[0];
                var theUrl=theGoToUrl.url;
            } else {
                var theUrl = ( hitInfo.data.action == "Panda" ) ? hitInfo.pandaUrl : (hitInfo.data.action.substring(0,6) == "Search") ? requesterSearch(hitData.requesterId) : hitInfo.previewUrl;
            }
            gMainData.searched++;
            gMainData.lastElapsed = elapsed;
            //console.log("Doing Number: " + theNumber + " | going to: " + theUrl);
            if (theUrl.indexOf("selectedSearchType=hitgroups")!=-1) requestUrl(theUrl,theNumber,parseHitSearchPage, errorRequest, hitInfo.status.searched, "");
            else requestUrl(theUrl,theNumber,parseMturkHitPage, errorRequest, hitInfo.status.searched, "");
            displayHitStatus(theNumber);
            return true;
        } else {
            $("#JRCellNum_" + theNumber).stop(true,true);
            $("#JRCellNum_" + theNumber).css({"background-color":"#FF9999"});
            $("#JRCellNum_" + theNumber).animate({backgroundColor: $("#JRCellNum_" + theNumber).data("backgroundColor")}, 40000);
            return false;
        }
    }, theNumber, 0, true);
    gMainData.jobs++;
    addQueueCheck();
}
function stopCollecting(theNumber,thisButton) {
    //console.log("turning off " + theNumber);
    if (gMainData.hitCollection[theNumber].collecting == "on") { 
        gMainData.hitCollection[theNumber].collecting = "off";
        gMainData.hitCollection[theNumber].goToUrl.splice(0,gMainData.hitCollection[theNumber].goToUrl.length);
        theCycler.removeJob(theNumber); 
        gMainData.jobs--;
    }
    if (theCycler.jobs() == 0) theCycler.removeJob(-1); // Stop mturk queue checking. Doesn't matter how many hits now.
    displayHitStatus(theNumber);
}
function stopAll() {
    $.each(gMainData.hitCollection, function( index, value ) {
        if (value.collecting == "on") {
            toggleButton( $("#JRCollectB_" + index),startCollecting,stopCollecting);
            if (value.collecting=="off" && value.ham != "off") toggleButtonOff($("#JRHamB_" + index),hamOn,hamOff);
        }
    });
}
function hamOn(theNumber,thisButton) {
    var onMode = "on";
    $(".JRHamButton").each( function() {
        if ( $(this).data("theNumber") != theNumber ) $(this).data("disabled",true);
        updateHitColors($(this).data("theNumber"));
    });
    if (gMainData.hitCollection[theNumber].ham == "paused") onMode = "ontimed";
    gMainData.hitCollection[theNumber].ham = onMode;
    theCycler.hamOn(theNumber);
    theCycler.skippingReset();
    theCycler.cycleResetChange(gMainOptions.HamCycleNumber);
}
function hamOff(theNumber,thisButton,theMode) {
    var passedMode = theMode || "off";
    var hitInfo = gMainData.hitCollection[theNumber];
    if (hitInfo.ham.substring(0,2) == "on") {
        $(".JRHamButton").each( function() {
            if ( $(this).data("disabled") ) $(this).data("disabled",false);
            updateHitColors($(this).data("theNumber"));
        });
    }
    if (hitInfo.ham == "ontimed") passedMode = "paused";
    gMainData.hitCollection[theNumber].ham = passedMode;
    $("#JRCellNum_" + theNumber).data("firstPanda",false);
    theCycler.hamOff();
    theCycler.skippingReset();
    theCycler.cycleResetChange(gMainOptions.cycleNumber);
}
function muteJob(theNumber) {
    var hitInfo = gMainData.hitCollection[theNumber];
    hitInfo.data.mute = !hitInfo.data.mute;
    hitInfo.hitCell.data("mute",hitInfo.data.mute);
    updateHitColors( theNumber );
    saveSettings();
}
function addTab(tabContainer,theTitle,isSortable,theID,tabData,appendClose) {
    var theTab = createTab(tabContainer,theTitle,isSortable,theID,tabData,appendClose)
        .data({"tabData":tabData});
    createDiv().insertBefore(theTab.find("br.cleartab"))
        .data({"tabData":tabData})
        .attr({"class":"tabContents connectedSortable"})
        .css({"overflow":"auto"})
        .sortable({dropOnEmpty: true,delay:400,connectWith: ".connectedSortable",tolerance: "pointer","items":".JRHitCell:not(.ui-not-sortable)",
            helper:"clone",opacity: 0.9,appendTo:"body",
            start: function( event, ui ) {
                //$(".hasTooltip").tooltip("disable");
                ui.item.addClass('noclick');
                ui.item.data("oldPosition",ui.item.index());
                ui.item.data("received",false);
            },
            receive: function( event, ui ) {
                ui.item.data("received",true);
                gTabsData[ui.item.data("hitInfo").tabIndex].positions.splice(ui.item.data("oldPosition"), 1);
                $(event.target).data("tabData").positions.splice(ui.item.index(), 0, ui.item.data("theNumber"));
                ui.item.data("hitInfo").tabIndex = $(gTabsData).index($(event.target).data("tabData"));
                ui.item.data("hitData").tabNumber = $(event.target).data("tabData").tabNumber;
                saveSettings();
            },
            stop: function( event, ui ) {
                if (ui.item.data("hitInfo") && !ui.item.data("received")) {
                    var thePositions = gTabsData[ui.item.data("hitInfo").tabIndex].positions;
                    console.log("JR positions before: " + JSON.stringify(thePositions));
                    thePositions.splice(ui.item.index(), 0, thePositions.splice(ui.item.data("oldPosition"), 1)[0]);
                    console.log("JR positions after: " + JSON.stringify(thePositions));
                    saveSettings();
                }
                $(".hasTooltip").tooltip("enable");
            }
        });
    return theTab;
}
function dataEdited(thisArea,theValue) {
    $("#JREditDialog").data("edited",true);
    $("div[aria-describedby='JREditDialog'] .ui-dialog-buttonpane button:contains('Save')").button().show();
    var inputEdit = createTextInput(theValue).css({"width":"300px"});
    $(inputEdit).focus( function() { $(this).select(); });
    $(thisArea).find("span").replaceWith(inputEdit);
    $(inputEdit).focus();
}
function dataTrueFalse(thisArea,theValue) {
    $("#JREditDialog").data("edited",true);
    $("div[aria-describedby='JREditDialog'] .ui-dialog-buttonpane button:contains('Save')").button().show();
    if (theValue) returnValue=false;
    else returnValue=true;
    $(thisArea).find("span").html(returnValue.toString());
    return returnValue;
}
function dataPandaSearch(thisArea,theValue) {
    $("#JREditDialog").data("edited",true);
    $("div[aria-describedby='JREditDialog'] .ui-dialog-buttonpane button:contains('Save')").button().show();
    if (theValue) returnValue=false;
    else returnValue=true;
    $(thisArea).find("span").html(returnValue.toString());
    return returnValue;
}
function saveGroupCreateData() {
    gGroupingData.push({"theNumber":++gGroupingData[0].theNumber,
        "name":$("#JREditDialog").find("groupName").val().toString(),
        "description":$("#JREditDialog").find("groupDesc").val().toString(),
        "grouping":$("#JREditDialog").find("theGrouping")});
    saveSettings();
}
function saveAlarmsData() {
    $.each(gAlarmSounds, function( index, value ) {
        var importFileID = "importFileInput-" + index;
        value.audio = $("#" + importFileID).data("audio");
        var base64 = $("#" + importFileID).data("base64");
        if (base64) GM_setValue(value.nameVar,JSON.stringify(base64));
    });
    saveSettings();
}
function saveTimersData() {
    var cycleEdit = $("#JREditDialog #timersCycleEdit input");
    if (cycleEdit.length) gMainOptions.cycleNumber = parseInt($(cycleEdit).eq(0).val());
    var goHamEdit = $("#JREditDialog #timersGoHamEdit input");
    if (goHamEdit.length) gMainOptions.HamCycleNumber = parseInt($(goHamEdit).eq(0).val());
    var hamDelayEdit = $("#JREditDialog #timersHamDelayEdit input");
    if (hamDelayEdit.length) gMainOptions.hamDelayTimer = parseInt($(hamDelayEdit).eq(0).val());
    var checkQueueEdit = $("#JREditDialog #timersCheckQueueEdit input");
    if (checkQueueEdit.length) {
        gMainOptions.queueTimer = parseInt($(checkQueueEdit).eq(0).val());
        if (theCycler.jobs() > 0) { theCycler.removeJob(-1); addQueueCheck(); };
    }
    var cycleIncreaseEdit = $("#JREditDialog #timersCycleIncreaseEdit input");
    if (cycleIncreaseEdit.length) gMainOptions.cycleIncrease = parseInt($(cycleIncreaseEdit).eq(0).val());
    var cycleDecreaseEdit = $("#JREditDialog #timersCycleDecreaseEdit input");
    if (cycleDecreaseEdit.length) gMainOptions.cycleDecrease = parseInt($(cycleDecreaseEdit).eq(0).val());
    var cycleAddingEdit = $("#JREditDialog #timersCycleAddingEdit input");
    if (cycleAddingEdit.length) {
        gMainOptions.cycleAdding = parseInt($(cycleAddingEdit).eq(0).val());
        $("#JrCycleAddingButton").find("span").html("Add " + gMainOptions.cycleAdding);
    }
    var cycleAutoIncreaseEdit = $("#JREditDialog #timersCycleAutoIncreaseEdit input");
    if (cycleAutoIncreaseEdit.length) gMainOptions.cycleAutoIncrease = parseInt($(cycleAutoIncreaseEdit).eq(0).val());
    saveSettings();
    theCycler.cycleResetChange(gMainOptions.cycleNumber);
    displayMainStatus();
}
function saveJobData() {
    var theNumber = $("#JREditDialog").data("theNumber");
    var hitInfo = gMainData.hitCollection[theNumber];
    var hitData = hitInfo.data;
    var requesterNameEdit = $("#JREditDialog #requesterNameEdit input");
    if (requesterNameEdit.length) hitData.requesterName = $(requesterNameEdit).eq(0).val();
    var requesterIdEdit = $("#JREditDialog #requesterIdEdit input");
    if (requesterIdEdit.length) hitData.requesterId = $(requesterIdEdit).eq(0).val();
    var actionEdit = $("#JREditDialog #actionEdit input");
    if (actionEdit.length) hitData.action = $(actionEdit).eq(0).val();
    var groupIdEdit = $("#JREditDialog #groupIdEdit input");
    if (groupIdEdit.length) {
        hitData.groupId = $(groupIdEdit).eq(0).val();
        hitInfo.pandaUrl = pandaLink(hitData.groupId);
        hitInfo.previewUrl = previewLink(hitData.groupId);
    }
    var payEdit = $("#JREditDialog #payEdit input");
    if (payEdit.length) hitData.pay = $(payEdit).eq(0).val();
    var qualEdit = $("#JREditDialog #qualEdit input");
    if (qualEdit.length) hitData.qual = $(qualEdit).eq(0).val();
    var titleEdit = $("#JREditDialog #titleEdit input");
    if (titleEdit.length) hitData.title = $(titleEdit).eq(0).val();
    var durationEdit = $("#JREditDialog #durationEdit input");
    if (durationEdit.length) hitData.duration = $(durationEdit).eq(0).val();
    var queueLimitEdit = $("#JREditDialog #queueLimitEdit input");
    if (queueLimitEdit.length) hitData.queueLimit = Number($(queueLimitEdit).eq(0).val());
    var dailyLimitEdit = $("#JREditDialog #dailyLimitEdit input");
    if (dailyLimitEdit.length) hitData.dailyLimit = Number($(dailyLimitEdit).eq(0).val());
    var onceEdit = $("#JREditDialog #onceEdit input");
    if (onceEdit.length) hitData.once = $(onceEdit).eq(0).val();
    var hamTimerEdit = $("#JREditDialog #hamTimerEdit input");
    if (hamTimerEdit.length) hitData.hamTimer = $(hamTimerEdit).eq(0).val();
    var dailyDoneEdit = $("#JREditDialog #dailyDoneEdit input");
    if (dailyDoneEdit.length) hitData.dailyDone = $(dailyDoneEdit).eq(0).val();
    var audioforceEdit = $("#JREditDialog #audioforceEdit input");
    if (audioforceEdit.length) hitData.audioforce = $(audioforceEdit).eq(0).val();
    var filterModeEdit = $("#JREditDialog #filterModeEdit select");
    if (filterModeEdit.length) hitData.filterMode = $(filterModeEdit).eq(0).val();
    updateHitCell(theNumber);
    saveSettings();
    updateHitColors( theNumber );
}
function saveEditedData() {
    if ( $("#JREditDialog").data("edited") ) {
        if ($("#JREditDialog").data("editing") == "job") saveJobData();
        else if ($("#JREditDialog").data("editing") == "timers") saveTimersData();
        else if ($("#JREditDialog").data("editing") == "alarms") saveAlarmsData();
        else if ($("#JREditDialog").data("editing") == "groupCreate") saveGroupCreateData();
    }
}
function saveToFile(theData) {
    var blob = new Blob( [JSON.stringify(theData)], {type: "text/plain"});
    saveAs(blob, "PandaCrazy_" + formatAMPM("short") + ".json");
}
function exportJobs() {
    //load from database to temp data variable
    $("#JRWaitDialog").html("");
    $("#JRWaitDialog").dialog("open");
    saveToFile({"Requesters":gRequestersData,"Options":gMainOptions,"Tabsdata":gTabsData});
    $("#JRWaitDialog").dialog("close");
}
function importJobs(theFile) {
    //load json text and verify it's correct data for the database
    $("#JRWaitDialog").html("");
    $("#JRWaitDialog").dialog("open");
    $("#JRWaitDialog").dialog("option", "title", "Please wait for importing data");
    if (window.File && window.FileReader && window.FileList && window.Blob) {
        var reader = new FileReader();
        reader.onload = function() {
            $("#JRWaitDialog").append(createDiv("Loaded file in memory."))
            var textData = reader.result;
            setTimeout( function() {
                try {
                    $("#JRWaitDialog").append(createDiv("Parsing the imported Data."))
                    var theData = JSON.parse(textData);
                    $("#JRWaitDialog").append(createDiv("Stopping all Jobs"))
                    stopAll();
                    setTimeout( function() {
                        $("#JRWaitDialog").append(createDiv("Removing all Job Cells"))
                        $("#JRMainTabs").find(".ui-tabs-panel").each( function() {
                            $(this).find(".JRHitCell").each( function() {
                                $(this).remove();
                            });
                        });
                        setTimeout( function() {
                            $("#JRWaitDialog").append(createDiv("Removing all Tabs"))
                            $.each(gTabsData, function( index, value ) {
                                var panelId = $("#JRTab_" + value.tabNumber).closest( "li" ).remove().attr( "aria-controls" );
                                $( "#" + panelId ).remove();
                                $("#JRMainTabs").tabs( "refresh" );
                            });
                            setTimeout( function() {
                                $("#JRWaitDialog").append(createDiv("Deleting Collection Data"))
                                $.each(gMainData.hitCollection, function( index, value ) {
                                    delete gMainData.hitCollection[index];
                                });
                                setTimeout( function() {
                                    $("#JRWaitDialog").append(createDiv("Deleting Requesters Data"))
                                    $.each(gRequestersData, function( index, value ) {
                                        delete gRequestersData[index];
                                    });
                                    setTimeout( function() {
                                        $("#JRWaitDialog").append(createDiv("Deleting Tabs"))
                                        $.each(gTabsData, function( index, value ) {
                                            delete gTabsData[index];
                                        });
                                        setTimeout( function() {
                                            $("#JRWaitDialog").append(createDiv("Adding imported data in the database."))
                                            gRequestersData = convertDatabase(theData["Requesters"]);
                                            gTabsData = theData["Tabsdata"];
                                            $.each(gTabsData, function( index, value ) {
                                                addTab($("#JRMainTabs"),value.tabName,true,"JRTab_" + value.tabNumber,value,true).css({"overflow":"visible"});
                                            });
                                            fillTabs();
                                            setTimeout( function() {
                                                $("#JRMainTabs").tabs("option", "active", 0);
                                                $("#JRWaitDialog").append(createDiv("Importing is finished."))
                                                $("#JRWaitDialog").dialog("option", "title", "Importing data is now done.");
                                                $("div[aria-describedby='JRWaitDialog'] .ui-dialog-buttonpane button:contains('Close')").button().show();
                                            },1);
                                        },1);
                                    },1);
                                },1);
                            },1);
                        },1);
                    },1);
                } catch(e) {
                    console.log("Could not parse text in file. Sorry.");
                }
            },50);
        }
        reader.readAsBinaryString(theFile);
        reader.onerror = function() {
            alert('Unable to read ' + file.fileName);
        };
        return true;
    } else {
        alert('The File APIs are not fully supported by your browser. Fallback required.');
        return false;
    }
}
function showGroupCreateDialog(theGrouping,theButton) {
    $("#JREditDialog").dialog("option","height",300);
    $("#JREditDialog").dialog("option","width",550);
    $("#JREditDialog").dialog("option", "title", "Name your group to create it:");
    $("#JREditDialog").data({"edited":false,"editing":"groupCreate","theGrouping":theGrouping})
    $(theButton).html("Create");
    $("#JREditDialog").data("button",theButton);
    $("#JREditDialog").html("");
    var groupingArea = createDiv().attr("class","groupingArea").css({"margin":"15px 15px"}).appendTo($("#JREditDialog"));
    createDiv().html("Type in the name of this grouping:").css({"font-size":"15px","text-align":"center"})
        .append(createTextInput("").attr("class","groupName").css({"width":"250px","margin-left":"30px"})).appendTo(groupingArea);
    createDiv().html("Type in the description of this grouping:").css({"font-size":"15px","text-align":"center"})
        .append(createTextInput("").attr("class","groupDesc").css({"width":"250px","margin-left":"30px"})).appendTo(groupingArea);
    $("#JREditDialog").dialog("open");
}
function showExportImportDialog(porting,theButton) {
    $("#JREditDialog").dialog("option","height",300);
    $("#JREditDialog").dialog("option", "title", porting + " data");
    $("#JREditDialog").data("button",theButton);
    $("#JREditDialog").html("");
    $("div[aria-describedby='JREditDialog'] .ui-dialog-buttonpane button:contains('Save')").button().hide();
    var exportImportArea = createDiv().attr("class","exportImportArea").css("margin","15px 15px").appendTo($("#JREditDialog"));
    if (porting=="Export") {
        createSpanButton( function(e) { 
            var theButton = $("#JREditDialog").data("button");
            $("#JREditDialog").data("button",null);
            toggleButton(theButton,null,null);
            $("#JREditDialog").dialog("close");
            exportJobs();
        },"Export to File",gButtonOffBgColor,gButtonOffColor,"12px").appendTo(exportImportArea);
        createSpanButton( null,"Copy Exported Data",gButtonOffBgColor,gButtonOffColor,"12px").appendTo(exportImportArea);
    } else {
        createDiv().css({"margin":"5px 0 10px 0"}).append($("<input>").attr({"type":"file","id":"importFileInput"})
            .change( function(event) { $("#importFromFileButton").data("disabled",false).css({"background-color":gButtonOffBgColor}); } )).appendTo(exportImportArea);
        createSpanButton( function(e) { 
                if ( !$(this).data("disabled") ) importJobs( $("#importFileInput").prop("files")[0] );
                var theButton = $("#JREditDialog").data("button");
                $("#JREditDialog").data("button",null);
                toggleButton(theButton,null,null);
                $("#JREditDialog").dialog("close");
            },"Import From File",gButtonDisabledBgColor,gButtonOffColor,"12px").appendTo(exportImportArea)
            .attr({"id":"importFromFileButton"})
            .data("disabled",true);
    }
    $("#JREditDialog").dialog("open");
}
function showAddJobsDialog(theButton) {
    $("#JREditDialog").dialog("option","height",300);
    $("#JREditDialog").dialog("option", "title", "Add a new PANDA!");
    $("#JREditDialog").data("button",theButton);
    $("#JREditDialog").html("");
    $("div[aria-describedby='JREditDialog'] .ui-dialog-buttonpane button:contains('Save')").button().hide();
    var addJobArea = createDiv().attr("class","addJobArea").css("margin","15px 15px").appendTo($("#JREditDialog"));
    createDiv().html("Below enter the preview or the previewandaccept url.<br>You may enter just the groupID number too. This is needed for panda jobs.<br>")
        .append(createTextInput("").attr("class","groupIdInput").css({"width":"400px","margin-left":"30px"}))
        .append(createDiv()
            .append(createCheckbox().attr("class","collectNow").prop('checked', true).css("margin-left","70px")).append(createSpan("Start Collecting"))
            .append(createCheckbox().attr("class","onlyOnce").css("margin-left","20px")).append(createSpan("Collect only once"))).appendTo(addJobArea);
    var addGroupIDButtonArea = createDiv().append(createSpanButton( function(e) {
        var theValue = $("#JREditDialog .groupIdInput:first").val();
        var collectNow = $("#JREditDialog .collectNow:first").prop('checked');
        var onlyOnce = $("#JREditDialog .onlyOnce:first").prop('checked');
        $("#JREditDialog .groupIDError").html("");
        var parsedGroupID = "";
        if (theValue=="") { $("#JREditDialog .groupIDError").html("Please Enter a url or GroupID first."); }
        else if (theValue.indexOf("groupId=")!=-1) {
            parsedGroupID = theValue.split("groupId=")[1];
            if (parsedGroupID.indexOf("&")!=-1) parsedGroupID = parsedGroupID.split("&")[0];
        } else if (theValue.indexOf("mturk.com")==-1) {
            parsedGroupID = theValue;
        } else { $("#JREditDialog .groupIDError").html("Please Enter a url or GroupID first."); }
        if (parsedGroupID!="") {
            console.log("found GroupID: " + parsedGroupID);
            var newHitData = jQuery.extend(true, {}, gRequestersData[0]);
            newHitData.requesterName = parsedGroupID; newHitData.requesterId = ""; newHitData.action = "Panda"; newHitData.groupId = parsedGroupID;
            newHitData.pay = "0.00"; newHitData.qual = ""; newHitData.title = parsedGroupID; newHitData.queueLimit = 0; newHitData.duration = "";
            newHitData.audioforce = ""; newHitData.hitlimit = ""; newHitData.mute = false; newHitData.position = null;
            newHitData.tabNumber = gTabsData[0].tabNumber; newHitData.once = onlyOnce; newHitData.hamTimer = gMainOptions.hamDelayTimer;
            var newCell = addHitData(newHitData,0);
            updateHitCell(newCell.data("theNumber"));
            if (collectNow) {
                newCell.data("status","on");
                toggleButton( newCell.find(".JRCollectButton"),startCollecting,stopCollecting );
            }
            $("#JRMainTabs").tabs("option", "active", 0);
            var theButton = $("#JREditDialog").data("button");
            toggleButton(theButton,null,null);
            $("#JREditDialog").dialog("close");
        }
    },"Add Panda for Group ID hit",gButtonOffBgColor,gButtonOffColor,"12px"))
        .css({"margin":"6px 0 0 35px"}).appendTo(addJobArea);
    createSpan("").attr("class","groupIDError").css({"color":"red","margin-left":"10px"}).appendTo(addGroupIDButtonArea);
    createDiv().html("Enter the requesterID number. Only needed for search Jobs.<br>").css({"margin-top":"20px"})
        .append(createTextInput("").css({"width":"400px","margin-left":"30px"})).appendTo(addJobArea);
    createDiv().append(createSpanButton( function(e) {},"Add Search Hit for requester ID",gButtonOffBgColor,gButtonOffColor,"12px"))
        .css({"margin":"6px 0 0 35px"}).appendTo(addJobArea);
    $("#JREditDialog").dialog("open");
}
function alarmReaderEditor(fileInput) {
    $("#JREditDialog").data("edited",true);
    $("div[aria-describedby='JREditDialog'] .ui-dialog-buttonpane button:contains('Save')").button().show();
    console.log("JR " + fileInput.prop("files")[0].name + " : " + fileInput.prop("files")[0].size);
    if (fileInput.prop("files")[0].size > 150000) console.log("JR sorry this is too big");
    var reader = new FileReader();
    reader.onload = function() {
        var readerContents = reader.result;
        var base64Audio = btoa(readerContents);
        var newAudio = new Audio("data:audio/wav;base64," + base64Audio);
        playSoundNow( newAudio );
        fileInput.data("base64",base64Audio);
        fileInput.data("audio",newAudio);
    }
    reader.readAsBinaryString(fileInput.prop("files")[0]);
    reader.onerror = function() {
        alert('Unable to read ' + file.fileName);
    };
}
function showAlarmsDialog( theNumber, theButton ) {
    $("#JREditDialog").dialog("option","height",700);
    $("#JREditDialog").dialog("option","width",650);
    $("#JREditDialog").dialog("option", "title", "Edit your alarms according to what you like:");
    $("#JREditDialog").data("button",theButton);
    $("#JREditDialog").data({"edited":false,"editing":"alarms"})
    $("#JREditDialog").html("");
    $("div[aria-describedby='JREditDialog'] .ui-dialog-buttonpane button:contains('Save')").button().hide();
    var alarmsArea = createDiv().attr("class","alarmsArea").css({"margin":"15px 15px"}).appendTo($("#JREditDialog"));
    createDiv().html("")
        .css({"font-size":"15px","text-align":"center"}).appendTo(alarmsArea);
    $.each(gAlarmSounds, function( index, value ) {
        var importFileID = "importFileInput-" + index; console.log(importFileID);
        createDiv().attr("class","alarmInputEdits")
            .append(createDiv().append(createSpanButton(function() { playSoundNow($("#" + importFileID).data("audio")); }
                    ,"- Play -","ivory","black","13px").css({"margin-right":"20px"}))
                .append(createSpan(value.desc).css({"font-weight":"bolder","textDecoration":"underline"}))
                .css({"margin-top":"10px"}))
            .append(createDiv().html("Change to: ").append($("<input>").attr({"type":"file","id":importFileID,"accept":"audio/*"}).data("audio",value.audio).data("base64",null)
                .change( function() { alarmReaderEditor($(this)); })).css({"margin":"8px 0 0 80px"})).appendTo(alarmsArea);
    });
    $("#JREditDialog").dialog("open");
}
function showEditTimersDialog( theNumber, theButton ) {
    $("#JREditDialog").dialog("option","height",610);
    $("#JREditDialog").dialog("option","width",650);
    $("#JREditDialog").data("button",theButton);
    $("#JREditDialog").dialog("option", "title", "Edit this hit:");
    $("#JREditDialog").data({"edited":false,"editing":"timers"})
    $("#JREditDialog").html("");
    $("div[aria-describedby='JREditDialog'] .ui-dialog-buttonpane button:contains('Save')").button().hide();
    var timersArea = createDiv().attr("class","timersArea").css({"margin":"15px 15px"}).appendTo($("#JREditDialog"));
    createDiv().html("All the timers on this page is measured in Milliseconds.<br>1000 Milliseconds is equal to 1 second.<br>Click on numbers to edit.")
        .css({"font-size":"15px","text-align":"center"}).appendTo(timersArea);
    createDiv().html("Cycle Timer: ").append(createSpan(gMainOptions.cycleNumber.toString())).css("margin-top","30px")
        .attr({"class":"timersLine","id":"timersCycleEdit"}).appendTo(timersArea)
        .click( function() { dataEdited($(this),gMainOptions.cycleNumber); });
    createDiv().html("GoHam Cycle Timer: ").append(createSpan(gMainOptions.HamCycleNumber.toString())).css("margin-top","10px")
        .attr({"class":"timersLine","id":"timersGoHamEdit"}).appendTo(timersArea)
        .click( function() { dataEdited($(this),gMainOptions.HamCycleNumber); });
    createDiv().html("Default GoHam Delay Timer: ").append(createSpan(gMainOptions.hamDelayTimer.toString())).css("margin-top","10px")
        .attr({"class":"timersLine","id":"timersHamDelayEdit"}).appendTo(timersArea)
        .click( function() { dataEdited($(this),gMainOptions.hamDelayTimer); });
    createDiv().html("Check Queue Timer Every: ").append(createSpan(gMainOptions.queueTimer.toString())).css("margin-top","10px")
        .attr({"class":"timersLine","id":"timersCheckQueueEdit"}).appendTo(timersArea)
        .click( function() { dataEdited($(this),gMainOptions.queueTimer); });
    var AdvancedArea = createDiv().attr("class","advancedArea").css({"border":"1px solid grey","margin":"20px 0 0 0","padding":"5px 3px"}).appendTo(timersArea);
    createDiv().html("Advanced Options:").css({"font-size":"15px","text-align":"center"}).appendTo(AdvancedArea);
    createDiv().html("Cycle Increase Button: ").append(createSpan(gMainOptions.cycleIncrease.toString())).css("margin-top","15px")
        .attr({"class":"timersLine","id":"timersCycleIncreaseEdit"}).appendTo(AdvancedArea)
        .click( function() { dataEdited($(this),gMainOptions.cycleIncrease); });
    createDiv().html("Cycle Decrease Button: ").append(createSpan(gMainOptions.cycleDecrease.toString())).css("margin-top","10px")
        .attr({"class":"timersLine","id":"timersCycleDecreaseEdit"}).appendTo(AdvancedArea)
        .click( function() { dataEdited($(this),gMainOptions.cycleDecrease); });
    createDiv().html("Cycle Add Time Button: ").append(createSpan(gMainOptions.cycleAdding.toString())).css("margin-top","10px")
        .attr({"class":"timersLine","id":"timersCycleAddingEdit"}).appendTo(AdvancedArea)
        .click( function() { dataEdited($(this),gMainOptions.cycleAdding); });
    createDiv().html("Cycle Auto Slowdown Increase: ").append(createSpan(gMainOptions.cycleAutoIncrease.toString())).css("margin-top","10px")
        .attr({"class":"timersLine","id":"timersCycleAutoIncreaseEdit"}).appendTo(AdvancedArea)
        .click( function() { dataEdited($(this),gMainOptions.cycleAutoIncrease); });
    $("#JREditDialog").dialog("open");
}
function showEditHitDialog( theNumber, theButton ) {
    var hitInfo = gMainData.hitCollection[theNumber];
    var hitData = hitInfo.data;
    $("#JREditDialog").dialog("option","height",640);
    $("#JREditDialog").dialog("option","width",600);
    $("#JREditDialog").data({"theNumber":theNumber,"edited":false,"editing":"job"})
    $("#JREditDialog").html("");
    $("div[aria-describedby='JREditDialog'] .ui-dialog-buttonpane button:contains('Add Job')").button().hide();
    $("div[aria-describedby='JREditDialog'] .ui-dialog-buttonpane button:contains('Save')").button().hide();
    var requesterArea = createDiv().attr("class","requesterArea").css("margin","15px 8px").appendTo($("#JREditDialog"));
    createDiv().html("Details of hit. All can be edited except for details in red.<br>Click on details to edit.")
        .css({"font-size":"15px","text-align":"center"}).appendTo(requesterArea);
        
    createDiv().html("Queue Limit: ").append(createSpan( hitData.queueLimit.toString() )).css({"margin-top":"10px"})
        .attr({"class":"requesterLine","id":"queueLimitEdit"}).appendTo(requesterArea)
        .click( function() { dataEdited($(this),hitData.queueLimit.toString()); });
    createDiv().html("Daily Limit: ").append(createSpan( hitData.dailyLimit.toString() ))
        .attr({"class":"requesterLine","id":"dailyLimitEdit"}).appendTo(requesterArea)
        .click( function() { dataEdited($(this),hitData.dailyLimit.toString()); });
    createDiv().html("Daily Done: ").append(createSpan(hitData.dailyDone.toString()))
        .attr({"class":"requesterLine","id":"dailyDoneEdit"}).appendTo(requesterArea)
        .click( function() { dataEdited($(this),hitData.dailyDone.toString()); });
    createDiv().html("Ham Timer (seconds): ").append(createSpan( hitData.hamTimer.toString() ))
        .attr({"class":"requesterLine","id":"hamTimerEdit"}).appendTo(requesterArea)
        .click( function() { dataEdited($(this),hitData.hamTimer.toString()); });
    createDiv().html("Once: ").append(createSpan( hitData.once.toString() ))
        .attr({"class":"requesterLine","id":"onceEdit"}).appendTo(requesterArea)
        .click( function() { hitData.once=dataTrueFalse($(this),hitData.once); });
    var advancedArea = createDiv().attr("class","advancedArea").css({"border":"1px solid grey","margin":"20px 0 0 0","padding":"5px 3px"}).appendTo(requesterArea);
    createDiv().html("Advanced Options most are changed by the script automatically:").css({"font-size":"15px","text-align":"center"}).appendTo(advancedArea);
    createDiv().html("The Number: ").append(createSpan(theNumber)).appendTo(advancedArea).css({"margin-top":"5px","color":"red"});
    createDiv().html("Action: ").append(createSpan(hitData.action))
        .attr({"class":"requesterLine","id":"actionEdit"}).appendTo(advancedArea)
        .click( function() { dataEdited($(this),hitData.action); });
    createDiv().html("Requester Name: ").append(createSpan(hitData.requesterName))
        .attr({"class":"requesterLine","id":"requesterNameEdit"}).appendTo(advancedArea)
        .click( function() { dataEdited($(this),hitData.requesterName); });
    createDiv().html("Requester ID: ").append(createSpan(hitData.requesterId))
        .attr({"class":"requesterLine","id":"requesterIdEdit"}).appendTo(advancedArea)
        .click( function() { dataEdited($(this),hitData.requesterId); });
    createDiv().html("Group ID: ").append(createSpan(hitData.groupId))
        .attr({"class":"requesterLine","id":"groupIdEdit"}).appendTo(advancedArea)
        .click( function() { dataEdited($(this),hitData.groupId); });
    createDiv().html("Pay: ").append(createSpan(hitData.pay))
        .attr({"class":"requesterLine","id":"payEdit"}).appendTo(advancedArea)
        .click( function() { dataEdited($(this),hitData.pay); });
    createDiv().html("Qualifications: ").append(createSpan(hitData.qual)).css("color","red") // Can not be edited.
        .attr({"class":"requesterLine","id":"qualEdit"}).appendTo(advancedArea);
    createDiv().html("Title: ").append(createSpan(hitData.title))
        .attr({"class":"requesterLine","id":"titleEdit"}).appendTo(advancedArea)
        .click( function() { dataEdited($(this),hitData.title); });
    createDiv().html("Duration: ").append(createSpan(hitData.duration))
        .attr({"class":"requesterLine","id":"durationEdit"}).appendTo(advancedArea)
        .click( function() { dataEdited($(this),hitData.duration); });
    createDiv().html("Force Audio: ").append(createSpan(hitData.audioforce))
        .attr({"class":"requesterLine","id":"audioforceEdit"}).appendTo(advancedArea)
        .click( function() { dataEdited($(this),hitData.audioforce); });
    if (hitData.action.indexOf("Filter") != -1) {
        var filterModeArea = createDiv().html("Filter Mode: ")
            .attr({"class":"requesterLine","id":"filterModeEdit"}).appendTo(advancedArea)
            .change( function() { dataEdited($(this),hitData.filterMode.toString()); });
        var filterSelection = $("<select>").attr("name","filterMode").appendTo(filterModeArea);
        var selected = "";
        for (var i=0,len=Object.keys(hitInfo.filterFuncData).length; i<len; i++) {
            selected = (hitData.filterMode==i+1) ? " selected='selected'" : "";
            filterSelection.append("<option value=" + Object.keys(hitInfo.filterFuncData)[i] + selected + ">" + hitInfo.filterFuncData[i+1].filterName + "</option>");
        }
        var selected = (hitData.filterMode==0) ? " selected='selected'" : "";
        filterSelection.append("<option value=0 " + selected + ">Off</option>");
    }
    var buttonJobArea = createDiv().css({"margin-top":"35px"}).appendTo(requesterArea);
    var muteJobButton = createSpanButton( function() {
            muteJob(theNumber);
            $(this).html( (hitData.mute) ? "Turn on Alarm" : "Mute Alarm" );
        },(hitData.mute) ? "Turn on Alarm" : "Mute Alarm",gButtonOffBgColor,gButtonOffColor,"13px")
        .css({"border-color":"blue"})
        .attr({"class":"requesterLine","id":"muteJobButton"}).appendTo(buttonJobArea);
    var deleteJobButton = createSpanButton( function() {
            createYesNoDialog( theNumber, function(theNumber) {
                $("#JRCellNum_" + theNumber).remove();
                stopCollecting(theNumber);
                gMainData.hitCollection[theNumber].data = null;
                gMainData.hitCollection[theNumber].collecting = "deleted";
                delete gRequestersData[theNumber];
                saveSettings();
                $("#JREditDialog").dialog( "close");
            });
        },"Delete Job",gButtonOffBgColor,gButtonOffColor,"13px")
        .attr({"class":"requesterLine","id":"deleteJobButton"}).css({"margin-left":"80px"}).appendTo(buttonJobArea);
    $("#JREditDialog").dialog("open");
}
function createWaitDialog() {
    createContainer().attr("id","JRWaitDialog")
        .data("button",null)
        .appendTo("body")
        .dialog({
            dialogClass: "no-close",
            autoOpen: false,
            title: "Please Wait",
            height: 230,
            width: 300,
            modal: true,
            buttons: {
                "Close": function() {
                    var theButton = $(this).data("button");
                    $(this).data("button",null);
                    toggleButton(theButton,null,null);
                    $("div[aria-describedby='JRWaitDialog'] .ui-dialog-buttonpane button:contains('Close')").button().hide();
                    $(this).dialog( "close");
                }
            }
        });
    $("div[aria-describedby='JRWaitDialog'] .ui-dialog-buttonpane button:contains('Close')").button().hide();
}
function createEditDialog() {
    createContainer().attr("id","JREditDialog")
        .data("button",null)
        .appendTo("body")
        .dialog({
            dialogClass: "no-close",
            autoOpen: false,
            title: "Details",
            height: 600,
            width: 500,
            modal: true,
            buttons: {
                "Save": function() { 
                    saveEditedData(); 
                    var theButton = $(this).data("button");
                    toggleButton(theButton,null,null);
                    $(this).data("button",null);
                    $(this).dialog( "close");
                },
                "Close": function( event, ui ) {
                    var theButton = $(this).data("button");
                    toggleButton(theButton,null,null);
                    $(this).data("button",null);
                    $(this).dialog( "close");
                }
            }
        });
}
function createYesNoDialog(theNumber, yesFunction) {
    createContainer().attr("id","JRYesNoDialog")
        .html("Are you sure you want to delete this Job?")
        .data("button",null)
        .appendTo("body")
        .dialog({
            dialogClass: "no-close",
            autoOpen: true,
            title: "Delete Job?",
            modal: true,
            buttons: {
                "Yes": function() { yesFunction(theNumber); $(this).dialog( "close"); },
                "No": function() { $(this).dialog( "close"); }
            }
        });
}
function shortGroupID( groupId ) { return groupId.slice(0,2) + ".." + groupId.slice(-4); }
function updateHitCell(theNumber) {
    var hitInfo = gMainData.hitCollection[theNumber];
    var hitData = hitInfo.data;
    var hitCell = $("#JRCellNum_" + theNumber).eq(0);
    $(hitCell).find(".myTitle").html(hitData.requesterName).attr({"title":hitData.requesterName + "\n" + hitData.groupId});
    $(hitCell).find(".myfloater").html(".. " + shortGroupID(hitData.groupId));
    if (gMainData.displayInfo==0) {
        $(hitCell).find(".myExtra").html("");
        $(hitCell).find(".myDescription").html("");
    } else if (gMainData.displayInfo==1) {
        $(hitCell).find(".myExtra").html(hitData.pay + ( (hitData.qual=="") ? "" : " (" + hitData.qual + ") " ) + ( (hitInfo.numberHits=="0") ? "" : " [" + hitInfo.numberHits + "] " ));
        $(hitCell).find(".myDescription").html(hitData.title);
    }
}
function updateHitColors(theNumber,thisButton) {
    if (theNumber) {
        var hitInfo = gMainData.hitCollection[theNumber];
        var hitData = hitInfo.data;
        var collectButtonStatus = $("#JRCellNum_" + theNumber).find(".JRCollectButton").data("status");
        $("#JRCellNum_" + theNumber).data("status",collectButtonStatus);
        var gohamButtonStatus = $("#JRCellNum_" + theNumber).find(".JRHamButton").data("status");
        var gohamButtonDisabled = $("#JRCellNum_" + theNumber).find(".JRHamButton").data("disabled");
        var hitCellMute = $("#JRCellNum_" + theNumber).data("mute");
        var hitCellTypeAction = hitData.action;
        var hitBgColor = (hitCellTypeAction.substring(0,6)=="Search") ? gSearchesHitBgColor : (hitCellTypeAction=="FilterPanda") ? gFilteredHitBgColor : gHitBgColor;
        var titleColor = (hitCellMute) ? gHitMutedColor : gTitleColor;
        var borderStyle = (hitCellMute) ? gHitMutedBorderStyle : gHitBorderStyle;
        var collectBgColor = (collectButtonStatus=="off") ? gButtonOffBgColor : gButtonOnBgColor;
        var collectColor = (collectButtonStatus=="off") ? gButtonOffColor : gButtonOnColor;
        var gohamBgColor = (gohamButtonDisabled) ? gButtonDisabledBgColor : (gohamButtonStatus=="off") ? gButtonOffBgColor : (gohamButtonStatus=="paused") ? gButtonDelayHamBgColor : gButtonOnBgColor;
        var goHamColor = (gohamButtonDisabled) ? gButtonDisabledColor : (gohamButtonStatus=="off") ? gButtonOffColor : gButtonOnColor;
        $("#JRCellNum_" + theNumber).css({"background-color":hitBgColor});
        $("#JRCellNum_" + theNumber).css({"border-style":borderStyle});
        $("#JRCellNum_" + theNumber).find(".myTitle").css({"color":titleColor});
        $("#JRCellNum_" + theNumber).find(".JRCollectButton").css({"background-color":collectBgColor});
        $("#JRCellNum_" + theNumber).find(".JRCollectButton").css({"color":collectColor});
        $("#JRCellNum_" + theNumber).find(".JRHamButton").css({"background-color":gohamBgColor});
        $("#JRCellNum_" + theNumber).find(".JRHamButton").css({"color":goHamColor});
        $("#JRCellNum_" + theNumber).find(".myfloater").css({"background-color":hitBgColor});
    } else {
        var buttonStatus = $(thisButton).data("status");
        var buttonBgColor = (buttonStatus=="off") ? gButtonOffBgColor : gButtonOnBgColor;
        var buttonColor = (buttonStatus=="off") ? gButtonOffColor : gButtonOnColor;
        $(thisButton).css({"background-color":buttonBgColor});
        $(thisButton).css({"color":buttonColor});
    }
}
function createHitCell(goAppend,hitData,cellNumber) {
    var theContainer = createContainer();
    var hitInfo = gMainData.hitCollection[cellNumber];
    var backgroundColor = (hitData.action.substring(0,6)=="Search") ? gSearchesHitBgColor : (hitData.action=="FilterPanda") ? gFilteredHitBgColor : gHitBgColor;
    var floaterRight = createDiv()
        .attr({"class":"myfloater"})
        .click(function(e) {console.log("Copy panda"); e.stopPropagation();})
        .css({"float":"right","margin-right":"-3px","padding":"0 1px 0 3px","font-weight":"900","background-color":backgroundColor,
            "color":"purple","font-size":"7px","z-index":"999","position":"relative"})
        .html(".. " + shortGroupID(hitData.groupId)).appendTo(theContainer);
    var theInfoArea = createDiv();
    var titleColor = (hitData.mute) ? gHitMutedColor : gTitleColor;
    createDiv().html(hitData.requesterName).css({"font-weight":"900","color":titleColor,"font-size":"13px"})
        .attr({"class":"myTitle hasTooltip","title":hitData.requesterName + "\n" + hitData.groupId})
        .tooltip({ show: {delay:1100} }).appendTo(theContainer);
    if (gMainData.displayInfo==0) {
        var htmlDescription = "";
    } else if (gMainData.displayInfo==1) {
        var htmlDescription = hitData.pay + ( (hitData.qual=="") ? "" : " (" + hitData.qual + ") " );
    }
    var htmlTitle = hitData.title;
    createDiv().html(htmlDescription).attr({"class":"myExtra"})
        .css({"font-size":"11px"}).appendTo(theContainer);
    createDiv().html(htmlTitle).css({"font-size":"10px"})
        .attr({"class":"myDescription hasTooltip","title":hitData.title}).tooltip({ show: {delay:1100} }).appendTo(theContainer);
    createDiv().html(" ").attr({"class":"myStatus","id":"JRCellStatus_" + cellNumber})
        .css({"color":"darkred","font-weight":"400","font-size":"10px"}).appendTo(theContainer);
    createCheckbox("testing").css({"float":"right","position":"relative"}).attr("class","myCheckBox").hide().appendTo(theContainer);
    var theButtonArea = createDiv().css({"padding":"2px"}).appendTo(theContainer);
    createSpanButton( function(e) {
            var thisHitInfo = $(this).data("hitInfo");
            toggleButton( $(this),startCollecting,stopCollecting);
            if (thisHitInfo.collecting=="off" && thisHitInfo.ham != "off") toggleButtonOff($("#JRHamB_" + $(this).data("theNumber")),hamOn,hamOff);
            e.stopPropagation();
        },"Collect",gButtonOffBgColor,gButtonOffColor,"12px")
        .bind("mousedown", function() {
            $(this).closest(".tabContents").sortable("disable");})
        .bind("mouseup mouseleave", function() { 
            $(this).closest(".tabContents").sortable("enable");})
        .attr({"id":"JRCollectB_" + cellNumber,"class":"JRCollectButton JRButton"})
        .data({"theNumber":cellNumber,"hitCell":theContainer,"hitInfo":hitInfo,"status":"off","disabled":false}).appendTo(theButtonArea);
    createSpanButton( function(e) {
            if ( !$(this).data("disabled") && !gPressAndHold ) {
                var thisHitInfo = $(this).data("hitInfo");
                if (thisHitInfo.collecting == "off") toggleButton($("#JRCollectB_" + $(this).data("theNumber")),startCollecting,stopCollecting);
                if (thisHitInfo.ham == "paused") toggleButtonOff($(this),hamOn,hamOff);
                else toggleButton($(this),hamOn,hamOff);
                gPressAndHold=false;
                e.stopPropagation();
            } else if (gPressAndHold) gPressAndHold=false;
        },"GoHam",gButtonOffBgColor,gButtonOffColor,"12px")
        .bind("mousedown", function(e) {
            var thisButton = $(this);
            $(this).closest(".tabContents").sortable("disable");
            gMouseDownTimeoutId = setTimeout( function() {
                gPressAndHold=true;
                console.log("mousedown timer finished");
                var thisNumber = $(thisButton).data("theNumber");
                if ($(thisButton).data("hitInfo").collecting == "off") toggleButton($("#JRCollectB_" + thisNumber),startCollecting,stopCollecting);
                toggleButton($(thisButton),hamOn,hamOff,"paused","off");
            }, 500);
            e.stopPropagation();
        })
        .bind("mouseup mouseleave", function(e) { 
            clearTimeout(gMouseDownTimeoutId);
            $(this).closest(".tabContents").sortable("enable");
            e.stopPropagation();
        })
        .attr({"id":"JRHamB_" + cellNumber,"class":"JRHamButton JRButton"})
        .data({"theNumber":cellNumber,"hitCell":theContainer,"hitInfo":hitInfo,"status":"off","disabled":false}).appendTo(theButtonArea);
    createSpanButton( function(e) {
            showEditHitDialog($(this).data("theNumber"),$(this));
            e.stopPropagation();
        },"details",gButtonOffBgColor,gButtonOffColor,"9px")
        .bind("mousedown", function() {
            $(this).closest(".tabContents").sortable("disable");})
        .bind("mouseup mouseleave", function() { 
            $(this).closest(".tabContents").sortable("enable");})
        .attr({"id":"JRDetailsB_" + cellNumber,"class":"JRDetailsButton JRButton"})
        .data({"theNumber":cellNumber,"hitCell":theContainer,"hitInfo":hitInfo,"status":"off","disabled":false}).appendTo(theButtonArea);
    var borderStyle = (hitData.mute) ? "dotted" : "solid";
    theContainer.width("200px")
        .attr({"id":"JRCellNum_" + cellNumber,"class":"JRHitCell"})
        .data({"backgroundColor":backgroundColor,"borderColor":"MidnightBlue","titleColor":gTitleColor,"theNumber":cellNumber,"status":"off",
                "mute":hitData.mute,"firstPanda":false,"typeAction":hitData.action,"hitData":hitData,"hitInfo":hitInfo,"oldPosition":null})
        .css({"border-color":"MidnightBlue", "border-width":"3px", "border-style":borderStyle,
            "margin":"2px 4px",
            "background-color":backgroundColor,
            "font-size":"11px",
            "cursor":"move",
            "overflow":"hidden",
            "float":"left",
            "white-space":"nowrap"})
        .bind("contextmenu", function(event) {
            if ($(event.target).is(".JRButton")) return;
            event.preventDefault();
            muteJob($(this).data("theNumber"));
        })
        .bind("mouseup mouseleave", function(event) {
            if ($(event.target).is(".JRButton")) { event.stopPropagation(); return; }
        })
        .dblclick( function() {
            var thisHitInfo = $(this).data("hitInfo");
            var thisHitData = thisHitInfo.data;
            var newHitData = jQuery.extend(true, {}, gRequestersData[0]);
            newHitData.requesterName = thisHitData.requesterName; newHitData.requesterId = thisHitData.requesterId; newHitData.groupId = thisHitData.groupId;
            newHitData.pay = "0.00"; newHitData.qual = ""; newHitData.title = thisHitData.title; newHitData.queueLimit = 0; newHitData.duration = thisHitData.duration;
            newHitData.audioforce = ""; newHitData.hitlimit = ""; newHitData.mute = false; newHitData.position = null; newHitData.maxHam = "";
            newHitData.tabNumber = gTabsData[0].tabNumber; newHitData.hamTimer = gMainOptions.hamDelayTimer;
            if ( $(this).data("typeAction").substring(0,6) != "Search" ) {
                $("#JRMainTabs").tabs("option", "active", 1);
                newHitData.action = "Search";
                var newHitCell = addHitData(newHitData,0);
                gMainData.hitCollection[ $(newHitCell).data("theNumber") ].title = thisHitInfo.newTitle;
            } else if (newHitData.groupId != "") {
                $("#JRMainTabs").tabs("option", "active", 0);
                newHitData.action = "Panda"; newHitData.tabNumber = gTabsData[0].tabNumber; newHitData.title = "Any Hit"; newHitData.pay = "0.00";
                var myDisabled = theCycler.isHamOn();
                var newHitCell = addHitData(newHitData,0);
                $(newHitCell).find(".JRHamButton").data({"disabled":myDisabled});
                updateHitColors(newHitCell.data("theNumber"));
            }
        })
        .click( function(event) {
            if ($(event.target).is(".JRButton")) { event.stopPropagation(); return; }
            if ($(this).hasClass('noclick')) {
                $(this).removeClass('noclick');
            } else {
                var thisHitInfo = $(this).data("hitInfo");
                if ( $(this).data("typeAction").substring(0,6) == "Search" ) {
                    var firstPanda = !($(this).data("firstPanda"));
                    var borderColor = (firstPanda) ? "red" : $(this).data("borderColor");
                    thisHitInfo.goToUrl.splice(0,thisHitInfo.goToUrl.length);
                    $(this).css({"border-color":borderColor});
                    $(this).data("firstPanda",firstPanda);
                }
            }
        });
    theContainer.appendTo(goAppend);
    displayHitStatus(cellNumber);
    return theContainer;
}
function addHitData(newHitData,tabIndex) {
    var inTabId = "#" + $("#JRTab_" + newHitData.tabNumber).attr("aria-controls");
    gRequestersData[gRequestersData[0].requesterId] = newHitData;
    $(inTabId).data("tabData").positions.push(gRequestersData[0].requesterId);
    var theNumber = addHitCollection(newHitData,gRequestersData[0].requesterId,tabIndex);
    gRequestersData[0].requesterId++;
    newHitCell = createHitCell($(inTabId).find(".tabContents"),newHitData,theNumber).data({"removeMe":false,"pandaHam":"off"});
    gMainData.hitCollection[theNumber].hitCell = newHitCell;
    saveSettings();
    return newHitCell;
}
function addToMenu(theMenuArray,theName,theMenuObject) {
    if (theName=="Main") theMenuArray[0].theobject = theMenuObject;
    else {
        theMenuArray.push({"name":theName,"theobject":theMenuObject});
        $(theMenuObject).hide();
    }
}
function activeMenu(theMenuArray,theName,theNumber) {
    for (var i=0,len=theMenuArray.length; i<len; i++) {
        if (theMenuArray[i].name == theName) $(theMenuArray[i].theobject).show();
        else $(theMenuArray[i].theobject).hide();
    }
    displayMainStatus();
}
function isActiveMenu(theMenuArray,theName) {
    for (var i=0,len=theMenuArray.length; i<len; i++) {
        if (theMenuArray[i].name == theName && $(theMenuArray[i].theobject).is(":visible")) return true;
    }
    return false;
}
function addToLog(addNode,logNode) {
    var logLength = logNode.find(".logDiv").length;
    if (logLength > 3000) logNode.find(".logDiv:first").remove();
    var firstLogDiv = logNode.find(".logDiv:first");
    if (firstLogDiv.length) firstLogDiv.before(createDiv().css({"margin-left":"18px","text-indent":"-15px"}).attr("class","logDiv").append(addNode));
    else logNode.append(createDiv().css({"margin-left":"18px","text-indent":"-15px"}).attr("class","logDiv").append(addNode));
}
function addToStatusLog(theText) { addToLog(createSpan(theText.trim()),$("#JRStatusLog")); }
function addToAcceptedLog(theText) { addToLog(createSpan(theText.trim()),$("#JRAcceptedLog")); }
function addToMturkgrindLog(thisStuff) { 
    $("#JRMTGTab").css("background-color","#DEB887");
    $("#JRMturkgrindLog").one('mouseover', function() { $("#JRMTGTab").css("background-color",""); })
    addToLog(thisStuff,$("#JRMturkgrindLog"));
}
function addToMturkforumLog(theText) { addToLog(createSpan(theText),$("#JRMturkforumLog")); }
function addToHWTFLog(thisStuff) { 
    $("#JRHWTFTab").css("background-color","#DEB887");
    $("#JRHWTFLog").one('mouseover', function() { $("#JRHWTFTab").css("background-color",""); })
    addToLog(thisStuff,$("#JRHWTFLog"));
}
function fillInPositions() { // Initialize positions because they are not set.
    $.each(gRequestersData, function( index, value ) {
        if (index>0) {
            var goInTab = null;
            $.each(gTabsData, function( tabsIndex, tabsValue ) { 
                if (goInTab === null) goInTab = tabsValue;
                if (tabsValue.tabNumber == value.tabNumber) goInTab = tabsValue;
            });
            if (goInTab) {
                if (goInTab.positions === null) goInTab.positions = [];
                goInTab.positions.push(index);
                value.tabNumber = goInTab.tabNumber;
            }
        }
    });
}
function fillTabs() {
    var theNumber=0, newHitCell=null, thisTab=null, thisData=null, thisTabControls=null;
    $.each(gTabsData, function( index, value ) { 
        thisTab = $("#" + ($("#JRTab_" + value.tabNumber).attr("aria-controls")));
        if (value.positions) {
            console.log(JSON.stringify(value.positions));
            for (var ii=0,len2=value.positions.length; ii<len2; ii++) {
                var thisPositionNumber = value.positions[ii];
                if (thisPositionNumber in gRequestersData) {
                    thisData = gRequestersData[thisPositionNumber];
                    theNumber = addHitCollection(thisData,thisPositionNumber,index);
                    newHitCell = createHitCell($(thisTab).find(".tabContents"),thisData,theNumber)
                        .data({"removeMe":false,"pandaHam":"off"});
                    gMainData.hitCollection[theNumber].hitCell = newHitCell;
                    gMainData.hitCollection[theNumber].data.tabNumber = value.tabNumber;
                } else { 
                    console.log("error: " + thisPositionNumber + " was not in requestersData");
                    value.positions.splice(ii, 1);
                    ii--;
                    len2=value.positions.length;
                }
            }
        } else value.posistions = [];
        $(thisTab).find(".tabContents").append(createDiv("").attr("class","JRHitCell").data("hitInfo",{"tabIndex":index}));
        value.positions.push(-999);
    });
}
function refreshAllCells() {
    $.each(gMainData.hitCollection, function( index, value ) {
        updateHitCell(index);
    });
}
function showButtonUsed(thisButton) {
    thisButton.css({"background-color": "#CCC6B0"});
    thisButton.animate({"background-color": gButtonOffBgColor}, 500);
}
function startPandaCrazy() {
    gMainData.queueStatus = makeStatus();
    var panels = createPanels("body")
        .css({"height":"auto"});

    var northPanel = createPanel("body");
    northPanel.addClass("ui-layout-north");
    var mainControls = createDiv().appendTo(northPanel);
    mainControls.css({"background-color":"aliceblue",
                   "font-size":"10px",
                   "color":"midnightblue",
                   "padding":"5px 4px",
                   "border-color":"black", "border-width":"2px", "border-style":"groove"});
    createSpan("Vol: ").appendTo(mainControls);
    createSpan().attr("id","JRVolumeControl").css({"display":"inline-block","width":"80px","margin":"3px 8px 0px 2px"})
        .slider({range: "min",min: 0,max: 100,value: gMainOptions.alarmVolume,step: 5,
            stop: function(event, ui) {
                gMainOptions.alarmVolume = ui.value;
                gSoundFile.volume = gMainOptions.alarmVolume/100;
                if (gSoundFile.paused == true) {
                    gSoundFile = gAlarmSounds["less2"].audio;
                    gSoundFile.currentTime = 0;
                    gSoundFile.play();
                }
            } 
        })
        .appendTo(mainControls);
    
    $("#JRWaitDialog").append(createDiv("Setting up Menu."));
    setTimeout( function() {
        var theMenuArea = createSpan().attr("id","menuArea").appendTo(mainControls);
        var mainMenuControls = createSpan().appendTo(theMenuArea).attr("id","JrMainMenuControls").css({"margin":"10px 0"});
        addToMenu(gMainMenu,"Main",mainMenuControls);
        var jobsMenuControls = createSpan().appendTo(theMenuArea).attr("id","JrJobsMenuArea").css({"margin":"10px 0"});
        addToMenu(gMainMenu,"Jobs",jobsMenuControls);
        var displayMenuControls = createSpan().appendTo(theMenuArea).attr("id","JrDisplayMenuArea").css({"margin":"10px 0"});
        addToMenu(gMainMenu,"Display",displayMenuControls);
        var groupingMenuControls = createSpan().appendTo(theMenuArea).attr("id","JrGroupingMenuArea").css({"margin":"10px 0"});
        addToMenu(gMainMenu,"Grouping",groupingMenuControls);
        var cycleMenuControls = createSpan().appendTo(theMenuArea).attr("id","JrCycleMenuArea").css({"margin":"10px 0"});
        addToMenu(gMainMenu,"Cycle",cycleMenuControls);
        var optionsMenuControls = createSpan().appendTo(theMenuArea).attr("id","JrOptionsMenuArea").css({"margin":"10px 0"});
        addToMenu(gMainMenu,"Options",optionsMenuControls);
        activeMenu(gMainMenu,"Main");

        createSpan(" | ").appendTo(mainMenuControls);

        createSpan().append(createSpanButton(function() { activeMenu(gMainMenu,"Jobs"); },"Jobs","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(mainMenuControls);
        createSpan().append(createSpanButton(function() { activeMenu(gMainMenu,"Main"); },"Main","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(jobsMenuControls);
        createSpan(" -Jobs- ").appendTo(jobsMenuControls);
        createSpan().append(createSpanButton(function() { 
            toggleButton(this,function(theNumber,thisButton) { showAddJobsDialog(thisButton); },null);
        },"Add","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(jobsMenuControls);
        createSpan().append(createSpanButton(function() {
            toggleButton(this,function(theNumber,thisButton) { showExportImportDialog("Export",thisButton); },null);
        },"Export","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(jobsMenuControls);
        createSpan().append(createSpanButton(function(theNumber,thisButton) {
            toggleButton(this,function(theNumber,thisButton) { showExportImportDialog("Import",thisButton); },null);
        },"Import","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(jobsMenuControls);

        createSpan().append(createSpanButton(function() { activeMenu(gMainMenu,"Display"); },"Display","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(mainMenuControls);
        createSpan().append(createSpanButton(function() { activeMenu(gMainMenu,"Main"); },"Main","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(displayMenuControls);
        createSpan(" -Display- ").appendTo(displayMenuControls);
        createSpan().append(createSpanButton(function() {
            showButtonUsed($(this)); gMainData.displayInfo=0; refreshAllCells();
        },"Minimum Info","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(displayMenuControls);
        createSpan().append(createSpanButton(function() {
            showButtonUsed($(this)); gMainData.displayInfo=1; refreshAllCells();
        },"Extended Info","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(displayMenuControls);

        createSpan().append(createSpanButton(function() { activeMenu(gMainMenu,"Grouping"); },"Grouping","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(mainMenuControls);
        createSpan().append(createSpanButton(function() { activeMenu(gMainMenu,"Main"); },"Main","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(groupingMenuControls);
        createSpan(" -Grouping- ").appendTo(groupingMenuControls);
        createSpan().append(createSpanButton(function() {  },"Collect","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(groupingMenuControls);
        createSpan().append(createSpanButton(function() {  },"Stop","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(groupingMenuControls);
        createSpan().append(createSpanButton(function() {
            if ( $(this).data("creating") ) {
                var theGrouping = [];
                $(".JRHitCell .myCheckBox").each( function() {
                    if ($(this).prop("checked")) {
                        theGrouping.push($(this).closest(".JRHitCell").data("theNumber"));
                    }
                });
                $(".JRHitCell .myCheckBox").hide();
                showGroupCreateDialog(theGrouping,$(this));
            } else {
                toggleButton(this,function(theNumber,thisButton) { 
                    $(thisButton).html("Click to save Group");
                    $(".JRHitCell .myCheckBox").show().prop("checked",false);
                    $(thisButton).data("creating",true);
                },null);
            }
        },"Create","ivory","black","12px")).css({"margin":"10px 0"}).data("creating",false).appendTo(groupingMenuControls);
        createSpan().append(createSpanButton(function() {  },"Add to..","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(groupingMenuControls);
        createSpan().append(createSpanButton(function() {  },"View all","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(groupingMenuControls);

        createSpan().append(createSpanButton(function() { activeMenu(gMainMenu,"Cycle");
            $("#JrMainStatus .JRCycleInfoArea").stop(true,true);
            $("#JrMainStatus .JRCycleInfoArea").css({"color":"red"}); 
        },"Cycler","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(mainMenuControls);
        createSpan().append(createSpanButton(function() { 
            activeMenu(gMainMenu,"Main"); $("#JrMainStatus .JRCycleInfoArea").stop(true,true);
            $("#JrMainStatus .JRCycleInfoArea").animate({"color": "#191970"}, 30000);
        },"Main","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(cycleMenuControls);
        createSpan(" -Cycler- ").appendTo(cycleMenuControls);
        createSpan().append(createSpanButton(function() {
            showButtonUsed($(this)); theCycler.skippingReset(); displayMainStatus();
        },"Reset","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(cycleMenuControls);
        createSpan().append(createSpanButton(function() {
            showButtonUsed($(this)); theCycler.cycleIncrease(); displayMainStatus();
        },"Increase","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(cycleMenuControls);
        createSpan().append(createSpanButton(function() {
            showButtonUsed($(this)); theCycler.cycleDecrease(); displayMainStatus();
        },"Decrease","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(cycleMenuControls);
        createSpan().append(createSpanButton(function() {
            showButtonUsed($(this)); theCycler.cycleAdd(gMainOptions.cycleAdding); displayMainStatus();
        },"Add " + gMainOptions.cycleAdding,"ivory","black","12px")).css({"margin":"10px 0"}).attr("id","JrCycleAddingButton").appendTo(cycleMenuControls);
        createSpan().append(createSpanButton(function() { displayMainStatus(); },"Edit Cycle Timers","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(cycleMenuControls);

        createSpan().append(createSpanButton(function() { activeMenu(gMainMenu,"Options"); },"Options","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(mainMenuControls);
        createSpan().append(createSpanButton(function() { activeMenu(gMainMenu,"Main"); },"Main","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(optionsMenuControls);
        createSpan(" -Options- ").appendTo(optionsMenuControls);
        createSpan().append(createSpanButton(function() {
            toggleButton(this,function(theNumber,thisButton) { showEditTimersDialog("Timers",thisButton); },null);
        },"Timers","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(optionsMenuControls);
        createSpan().append(createSpanButton(function() {
            toggleButton(this,function(theNumber,thisButton) { showAlarmsDialog("Alarms",thisButton); },null);
        },"Alarms","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(optionsMenuControls);
        createSpan().append(createSpanButton(function() { },"General","ivory","black","12px")).css({"margin":"10px 0"}).appendTo(optionsMenuControls);

        var mainStatus = createDiv().appendTo(northPanel).attr("id","JrMainStatus");
        mainStatus.css({"background-color":"aliceblue",
                       "font-size":"12px",
                       "color":"#191970",
                       "font-weight":"bold",
                       "padding":"5px 5px",
                       "border-color":"black", "border-width":"2px", "border-style":"groove"});
        createSpan().attr({"class":"JRJobsArea","title":"Click to Show Number of Panda, Searches or Filtered Jobs."}).data("mode","Jobs").tooltip({ show: {delay:600} }).appendTo(mainStatus);
        createSpan().attr({"class":"JRCycleInfoArea","title":"Click to Show Elapsed Time, Cycle Time, Added Time for Slow Down or Min Ham Cycle Time."}).data("mode","Elapsed")
            .tooltip({ show: {delay:600} })
            .click( function() {
                var theMode = $(this).data("mode");
                $(this).data("mode", (theMode=="Elapsed") ? "Cycle" : (theMode=="Cycle") ? "CycleSkipping" : (theMode=="CycleSkipping") ? "Hamcycle" : "Elapsed")
                    .stop(true,true)
                    .css({"color":"red"})
                    .animate({"color": "#191970"}, 30000);
                displayMainStatus();
            }).css({"cursor":"pointer"}).appendTo(mainStatus);
        createSpan().attr({"class":"JRResultAccSkipArea","title":"Click to Show Accepted or Skipped Hits."}).data("mode","Accepted")
            .tooltip({ show: {delay:600} })
            .click( function() {
                var theMode = $(this).data("mode");
                $(this).data("mode", (theMode=="Accepted") ? "Skipped" : "Accepted")
                    .stop(true,true)
                    .css({"color":"red"})
                    .animate({"color": "#191970"}, 30000);
                displayMainStatus();
            }).css({"cursor":"pointer"}).appendTo(mainStatus);
        createSpan().attr({"class":"JRErrorArea","title":"Click to Show Number of Too Fast or Error Pages."}).data("mode","TooFast")
            .tooltip({ show: {delay:600} })
            .click( function() {
                var theMode = $(this).data("mode");
                $(this).data("mode", (theMode=="TooFast") ? "Errors" : "TooFast")
                    .stop(true,true)
                    .css({"color":"red"})
                    .animate({"color": "#191970"}, 30000);
                displayMainStatus();
            }).css({"cursor":"pointer"}).appendTo(mainStatus);
        createSpan().attr({"class":"JRMturkQueueArea","title":"Number of Hits in Mturk Queue. Only verifies queue after specified time in options."}).data("mode","Queue")
            .tooltip({ show: {delay:600} }).appendTo(mainStatus)
            .click( function() {
                theCycler.frontOfTheLineTimer(-1);
            }).css({"cursor":"pointer"}).appendTo(mainStatus);
        createSpan().attr({"class":"JRSearchedArea","title":"Number of Searched Hits."}).data("mode","Searched").tooltip({ show: {delay:600} }).appendTo(mainStatus);
        createSpan().attr({"class":"JRPayArea","title":"Total Amount for Accepted Hits."}).data("mode","Pay").tooltip({ show: {delay:600} }).appendTo(mainStatus);

        var centerPanel = createPanel("body");
        centerPanel.addClass("ui-layout-center");

        var theControls = createDiv().attr("id","JRTheControls").appendTo(centerPanel);
        theControls.css({"background-color":"aliceblue",
                       "font-size":"10px",
                       "color":"midnightblue",
                       "padding":"5px 4px",
                       "border-color":"black", "border-width":"2px", "border-style":"groove"});
        createSpanButton(function() { 
            if (theCycler.isPaused()) { theCycler.unpause(); $(this).html("Pause").css({"background-color":"ivory","color":"black"}); }   
            else { theCycler.pause(); $(this).html("Resume").css({"background-color":"red","color":"white"}); }
        },"Pause","ivory","black","12px").attr("id","JRPauseButton").appendTo(theControls);
        createSpanButton( function() { 
            toggleButton(this,function(theNumber,thisButton) {
                $("#JRWaitDialog").data("button",thisButton);
                $("#JRWaitDialog").html("");
                $("#JRWaitDialog").dialog("open");
                saveSettings();
                createDiv("Database Saved.<br>You may close this dialog.").css({"font-size":"18px","margin-top":"30px","text-align":"center"}).appendTo($("#JRWaitDialog"));
                $("div[aria-describedby='JRWaitDialog'] .ui-dialog-buttonpane button:contains('Close')").button().show();
            },null);
        },"Save","ivory","black","12px").appendTo(theControls); 
        createSpanButton( function() { stopAll(); },"Stop All","ivory","black","12px").appendTo(theControls); 
        createSpanButton( function() {
            toggleButton(this,function(theNumber,thisButton) { showAddJobsDialog(thisButton); },null);
        },"Add Job","ivory","black","12px").appendTo(theControls); 

        $("#JRWaitDialog").append(createDiv("Setting up tabs."));
        setTimeout( function() {
            var mainTabs = createTabs(centerPanel,true,"JRMainTabs").css({"overflow":"hidden"}).show();
            if (gTabsData[0].positions === null) fillInPositions();
            var firstTab = true;
            $.each(gTabsData, function( index, value ) {
                addTab(mainTabs,value.tabName,true,"JRTab_" + value.tabNumber,value,!firstTab).css({"overflow":"visible"});
                if (firstTab) firstTab = false;
            });

            var southPanel = createPanel("body");
            southPanel.addClass("ui-layout-south");
            var logTabs = createTabs(southPanel,true,"JRStatusTabs");
            gAcceptedLogTab = addTab(logTabs,"Accepted",false,"JRStatusTab_0",null,false);
            gStatusLogTab = addTab(logTabs,"Status log",false,"JRStatusTab_1",null,false);
            createDiv().appendTo(gAcceptedLogTab)
                .attr("id","JRAcceptedLog")
                .css({"background-color":"black","overflow":"auto","color":"white","font-size":"9px"});
            createDiv().appendTo(gStatusLogTab)
                .attr("id","JRStatusLog")
                .css({"background-color":"black","overflow":"auto","color":"white","font-size":"9px"});
            logTabs.tabs("option", "active", 1)

            $("#JRWaitDialog").append(createDiv("Creating Panda Cells."));
            setTimeout( function() {
                fillTabs();
                mainTabs.tabs("option", "active", 0);
                gMyLayout = $('body').layout({
                    center__onresize: function() {
                        var newHeight = $(".ui-layout-south").innerHeight() - 35;       
                        gStatusLogTab.find("div").css({"height":newHeight}); 
                        gAcceptedLogTab.find("div").css({"height":newHeight});
                        $("#JRMainTabs").css({"height":$(".ui-layout-center").innerHeight() - $("#JRTheControls").innerHeight() - 8});
                        $("#JRMainTabs").find(".tabContents").css({"height":$(".ui-layout-center").innerHeight() - $("#JRMainTabs").find(".ui-tabs-nav").innerHeight() - $("#JRTheControls").innerHeight() - 8})
                    },
                });
                gMyLayout.sizePane("north", 65);
                gMyLayout.sizePane("south", 140);
                $("#JRStatusLog").css({"height":$(".ui-layout-south").innerHeight() - 35});
                $("#JRAcceptedLog").css({"height":$(".ui-layout-south").innerHeight() - 35});

                theCycler.cycleResetChange(gMainOptions.cycleNumber);
                gNotifications = checkNotifications();
                displayMainStatus();
                $("#JRWaitDialog").append(createDiv("Display is done.<br>Starting up script."));
                setTimeout( function() {
                    $("#JRWaitDialog").dialog("close");
                },1000);
            },10);
        },10);
    },10);
}
function continueLoading() {
    $("#JRWaitDialog").append(createDiv("Creating UI Display."));
    setTimeout( function() {
        startPandaCrazy();
    },10);
}

$("body").html("").css("height",screen.height-310);
$(function() {
    createEditDialog();
    createWaitDialog();
    
    $("#JRWaitDialog").html("Setting up Panda Crazy!");
    $("#JRWaitDialog").dialog("open");
    $("#JREditDialog").dialog("option","height",310);
    $("#JREditDialog").dialog("option","width",320);
    $("#JRWaitDialog").dialog('option', 'position', 'center');
    $("#JRWaitDialog").dialog("option", "title", "Please wait. Loading....");
    setTimeout( function() {
        var nowDate = new Date();
        //console.log(formatTimeZone("onlydate",nowDate,"mturk"));
        $("#JRWaitDialog").append(createDiv("Loading settings in memory."));
        setTimeout( function() {
            loadSettings();
        },10);
    },10);
});

GM_addStyle(jqUI_CssSrc);
GM_addStyle(jqLayout_CssSrc);
GM_addStyle( " \
    body, input, select, td, li, div, textarea, p { \
        font-size:11px; \
        line-height: 14px; \
        font-family:verdana,arial,sans-serif; \
    } \
    .sortable-placeholder { \
        height: 1.5em; line-height: 1.2em; background-color:burlywood; \
    } \
    .ui-state-highlight { \
        height: 1.5em; line-height: 1.2em; \
    } \
    .requesterLine { \
        padding: 2px 0; \
    }\
    .requesterLine span { \
        font-weight: bold; \
    }\
    .ui-tooltip { \
        white-space: pre-line; \
        font-size:16px !important; \
        max-width: 400px; \
        width:400px; \
    } \
    .ui-tooltip-content { \
        max-width: 400px; \
        font-size:16px !important; \
    } \
    .no-close .ui-dialog-titlebar-close { \
        display: none; \
    } \
    .ui-state-hover .ui-icon { \
        background-image: url('https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/themes/pepper-grinder/images/ui-icons_ffffff_256x240.png') !important; \
    } \
    .ui-state-active .ui-icon { \
         background-image: url('https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/themes/pepper-grinder/images/ui-icons_b83400_256x240.png') !important; \
    } \
    .ui-state-default .ui-icon { \
        background-image: url('https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/themes/pepper-grinder/images/ui-icons_b83400_256x240.png'); \
    } \
    .ui-widget-content { \
        background: #eceadf url('https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/themes/pepper-grinder/images/ui-bg_fine-grain_10_eceadf_60x60.png') 50% 50% repeat; \
    } \
    #JRMainTabs li .ui-icon-close { float: left; margin: 0.4em 0.2em 0 0; cursor: pointer; } \
    #JRStatusTabs li .ui-icon-close { float: left; margin: 0.4em 0.2em 0 0; cursor: pointer; } \
");