mmmturkeybacon Queue Order Fix

After completing a HIT anywhere within your queue (i.e. HITs Assigned To You), this script will automatically continue the HIT at the top of your queue.

目前为 2015-04-19 提交的版本。查看 最新版本

// ==UserScript==
// @name        mmmturkeybacon Queue Order Fix
// @version     2.13
// @description After completing a HIT anywhere within your queue (i.e. HITs Assigned To You), this script will automatically continue the HIT at the top of your queue. 
// For example, if you sort your queue by Time Left (least first), you can use this script to work on the HITs that are closest to expiring instead of mturk's default behavior ignoring what your queue is sorted by and putting the oldest HIT next in line. You should only need to set the sort order once. HITs accepted after setting the sort order will be sorted automatically by mturk. Additionally you can manually continue the HIT at the top of your queue if you visit "https://www.mturk.com/mturk/myhits?first". Create a bookmark on your toolbar to quickly jump to the first HIT in your queue. This is especially useful if you just caught a HIT that will expire quickly.
// @author      mmmturkeybacon
// @namespace   http://userscripts.org/users/523367
// @match       https://*.mturk.com/mturk/myhits
// @match       https://*.mturk.com/mturk/myhits?first
// @match       https://*.mturk.com/mturk/sortmyhits?*
// @match       https://*.mturk.com/mturk/viewmyhits?*
// @match       https://*.mturk.com/mturk/continue*
// @match       https://*.mturk.com/mturk/submit
// @match       https://*.mturk.com/mturk/return?requesterId=*
// @exclude     https://*.mturk.com/mturk/continue*&MTBQOF+enabled=false
// @require     https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js
// @grant       GM_log
// ==/UserScript==

/*
 * Mechanical Turk has two types of HITs. By far the ExternalQuestion HITs are 
 * the most common. These HITs use an iframe to display the task, disable the 
 * yellow Submit HIT button, and use the hidden link with the id hitExternalNextLink
 * to direct the browser to a new page after the task has been submitted in the
 * iframe. The second type of HIT is the QuestionForm HIT. These HITs do not use
 * an iframe, use the yellow Submit HIT button to submit, and do not use
 * hitExternalNextLink to direct the browser to a new page.
 *
 * For ExternalQuestion HITs, fixing the queue order is as simple as replacing
 * hitExternalNextLink with the URL of the next link you wish to work on.
 *
 * QuestionForm HITs don't use the hitExternalNextLink, however we can utilize
 * the fact that after a QuestionForm HIT is submitted the URL ends with 
 * /mturk/submit to redirect the browser to the top of the queue.
 *
 */

/* NOTE: This script doesn't actually do anything on the /mturk/myhits page but running it on that page makes it convenient to disable the script by unchecking it in the greasemonkey dropdown menu. */

/* A previous version of this script bound to the return key, but using "@grant none" was required to coexist with MTurk Confirm Return HIT. I think it is better to run in the sandbox
 * and not worrry about jquery conflicts so now this script simply redirects to the head of the queue when it sees the /mturk/return? URL. */
//j$ = this.$ = this.jQuery = jQuery.noConflict(true);

var TIMEOUT_TIMELIMIT = 10000; // 10000 [ms]
var ON_ERROR_REDIRECT_URL = '/mturk/myhits';
var DEFAULT_SORT_URL = '/mturk/sortmyhits?searchSpec=HITSearch%23T%231%2326%23-1%23T%23!Status!0!rO0ABXQACEFzc2lnbmVk!%23!Deadline!0!%23!&selectedSearchType=hitgroups&searchWords=&sortType=Deadline%3A0'; // a maximum of 26 HITs on a single page

$(document).ready(function()
{
    var this_URL = window.location.href.split("mturk.com")[1];
    /* preview?groupId=GROUPIDSTRING&isPreviousIFrame= indicates not in queue
     * preview?isPreviousIFrame= indicates we are in the queue pipeline */
    var hitExternalNextLink = $('a[href^="/mturk/preview?isPreviousIFrame="][id="hitExternalNextLink"]');
    var sortmyhits_URL = localStorage.getItem('mtbqof_sortmyhits_URL') || DEFAULT_SORT_URL;

    if (hitExternalNextLink.length > 0)
    { // This HIT is in the queue pipeline.
        if (this_URL.split('?')[0] == '/mturk/continue')
        {
            $.ajax({
                url: sortmyhits_URL,
                type: 'GET',
                success: function(data)
                {
                    var $src = $(data);
                    var maxpagerate = $src.find('td[class="error_title"]:contains("You have exceeded the maximum allowed page request rate for this website.")');
                    if (maxpagerate.length == 0)
                    {
                        var $continue_links = $src.find('a[href^="/mturk/continue"]');
                        var num_hits = $src.find('td[class="title_orange_text"]:contains("Results")').text().trim().split(' ')[2];
                        var hit_rank = $continue_links.index($src.find('a[href^="'+this_URL+'"]')) + 1;
                        if (hit_rank > 0 && num_hits > 0);
                        {
                            document.title = hit_rank+'/'+num_hits+' '+document.title;
                        }

                        var first_queue_URL = $continue_links.eq(0).attr('href');
                        if (first_queue_URL)
                        {
                            if (this_URL == first_queue_URL)
                            {
                                var second_queue_URL = $continue_links.eq(1).attr('href');
                                if (second_queue_URL)
                                {
                                    hitExternalNextLink.attr('href', second_queue_URL);
                                }
                                else
                                {
                                    /* No more HITs left when we last checked but it's possible one arrived afterwards,
                                     * so redirect to the first HIT in the queue if it is there. */
                                    hitExternalNextLink.attr('href', '/mturk/myhits?first');
                                }
                            }
                            else
                            {
                                hitExternalNextLink.attr('href', first_queue_URL);
                            }
                        }
                    }
                    else
                    {
                        hitExternalNextLink.attr('href', ON_ERROR_REDIRECT_URL);
                    }
                },
                error: function(xhr, status, error)
                {
                    hitExternalNextLink.attr('href', ON_ERROR_REDIRECT_URL);
                },
                timeout: TIMEOUT_TIMELIMIT
            });
        }
        else if (this_URL == '/mturk/submit' || this_URL.split('?')[0] == '/mturk/return')
        { // Next HIT after a QuestionForm HIT was submitted or next HIT after a HIT was returned.
          /* This section of code should only run on HITs that are in the pipeline. Since this code
             doesn't modify the document, it might be tempting to run this section at document-start.
             That is not possible because we need the content to be ready so that hitExternalNextLink
             is available to determine whether we are in the pipeline or not. */
            $.ajax({
                url: sortmyhits_URL,
                type: 'GET',
                success: function(data)
                {
                    var $src = $(data);
                    var maxpagerate = $src.find('td[class="error_title"]:contains("You have exceeded the maximum allowed page request rate for this website.")');
                    if (maxpagerate.length == 0)
                    {
                        var first_queue_URL = $src.find('a[href^="/mturk/continue"]').eq(0).attr('href');
                        if (first_queue_URL)
                        {
                            window.location.replace(first_queue_URL);
                        }
                    }
                    else
                    {
                        window.location.replace(ON_ERROR_REDIRECT_URL);
                    }
                },
                error: function(xhr, status, error)
                {
                    window.location.replace(ON_ERROR_REDIRECT_URL);
                },
                timeout: TIMEOUT_TIMELIMIT
            });
        }
    }
    else if (this_URL == '/mturk/myhits?first' || (this_URL.split('?')[0] == '/mturk/continue' && $('span[id="alertboxHeader"]:contains("You have already")').length > 0))
    { // When we see this URL jump to the first HIT in the queue. This is useful URL to bookmark. Or if you've already completed or returned a HIT then jump to the first HIT in the queue.
        var first_queue_URL = $('a[href^="/mturk/continue"]').eq(0).attr('href');
        if (first_queue_URL)
        {
            window.location.replace(first_queue_URL);
        }
    }
    else if (this_URL.split('?')[0] == '/mturk/sortmyhits')
    { // Modify and save the queue sort URL so the code can see all 25 (sometimes 26) on the same page to determine rank.
        localStorage.setItem('mtbqof_sortmyhits_URL', this_URL.replace("%2310%23", "%2326%23"));  // a maximum of 26 HITs on a single page
    }
    // else it's a submit link but not inside the queue pipeline, so do nothing
});