MTurk QualSorter

Keep track of qualifications and create a more sortable list.

// ==UserScript==
// @name			MTurk QualSorter
// @namespace	localhost
// @description	Keep track of qualifications and create a more sortable list.
// @version		0.3b
// @include		https://www.mturk.com/mturk/dashboard*
// @include		https://www.mturk.com/mturk/qualtable*
// @require		http://code.jquery.com/jquery-2.1.1.js
// @require		http://code.jquery.com/ui/1.10.3/jquery-ui.js
// @require		http://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.1/js/jquery.dataTables.js
// @resource datatab https://greasyfork.org/scripts/4258-datatables-css-cdn-with-images/code/Datatables%20CSS%20CDN%20with%20Images.js?version=13654
// @grant			GM_setValue
// @grant			GM_getValue
// @grant			GM_addStyle
// @grant			GM_getResourceText
// @author			DeliriumTremens 2014
// ==/UserScript==

//
//
// GET CSS MODULES
//
var jqtableCSS = GM_getResourceText("datatab");
GM_addStyle(jqtableCSS);
//
// END CSS MODULES
//
//
// ******************************************************************
//
//
//	START VARIABLE DEFINITIONS
//
var qualCount = null; // hold onto that sweet, sweet qual count
var qualPrev = GM_getValue("quals"); // store the previous qual count
var qualDiff = 0; // difference in qual count between dashboard refreshes
var nextPage = "https://www.mturk.com/mturk/findquals?requestable=false&earned=true";

$.get("https://www.mturk.com/mturk/findquals?requestable=false&earned=true", function(data) {
    var $quals = $(data).find('td[class="title_orange_text"]').text().trim();
    $quals = $quals.substr(8);
    qualCount = $quals.slice(0, -8);
    qualCount = parseInt(qualCount);
    qualDiff = qualCount - qualPrev;
    addQualElement();
    GM_setValue("quals",qualCount);
});

var qualObject = {}; // Storage for qualification details to be sent to database
var QualStorage = {}; // QualStorage object definition
var Scraping = true; // Used to start and kill scraping
var scrapeNumber = 0; // Unused currently
var currScrape = null; // Container for current page being scraped
//
//	END VARIABLE DEFINITIONS
//
//
// ******************************************************************
//
//
//	START INDEXEDDB METHODS
//
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.mozIDBTransaction;
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.mozIDBKeyRange;
var idbKeyRange = window.IDBKeyRange;
QualStorage.indexedDB = {};
QualStorage.indexedDB.db = null;
var v = 1; // Database version.
var dbExists = true; // Boolean if database exists.

// Method for creating the new database.
QualStorage.indexedDB.create = function () {
	var request = indexedDB.open("QualDB", v);
	request.onupgradeneeded = function (e) {
		QualStorage.indexedDB.db = e.target.result;
		var db = QualStorage.indexedDB.db;
		var newDB = false;
		if(!db.objectStoreNames.contains("Quals")) {
			var store = db.createObjectStore("Quals", {
				keyPath: "qualId"
			});
			store.createIndex("qualName", "qualName", {
				unique: false
			});
			store.createIndex("author", "author", {
				unique: false
			});
			store.createIndex("desc", "desc", {
				unique: false
			});
			store.createIndex("assDate", "assDate", {
				unique: false
			});
			store.createIndex("retDate", "retDate", {
				unique: false
			});
			store.createIndex("users", "users", {
				unique: false
			});
			store.createIndex("value", "value", {
				unique: false
			});
			newDB = true;
		}
		db.close();
	}
	request.onsuccess = function (e) {
		QualStorage.indexedDB.db = e.target.result;
		var db = QualStorage.indexedDB.db;
		db.close();
	}
	//request.onerror = console.log(request.errorCode);
}

QualStorage.indexedDB.addQual = function (qual) {
    var request = indexedDB.open("QualDB", v);
	var qualPut = qual;
    request.onsuccess = function (e) {
        QualStorage.indexedDB.db = e.target.result;

        var db = QualStorage.indexedDB.db;
        var newDB = false;

        if (!db.objectStoreNames.contains("Quals")) {
            db.close();
        } else {
            var trans = db.transaction(["Quals"], 'readwrite');
            var store = trans.objectStore("Quals");
            var request;

            request = store.put({
                qualId: qualPut["qualId"],
                qualName: qualPut["qualName"],
                author: qualPut["author"],
                desc: qualPut["desc"],
                assDate: qualPut["assDate"],
                retDate: qualPut["retDate"],
                users: qualPut["users"],
                value: qualPut["value"]
            });
            request.onsuccess = function (e) {
            }
            request.onerror = function (e) {
            }
        }
        db.close();
    }
    request.onerror = QualStorage.indexedDB.onerror;
}

QualStorage.indexedDB.getQuals = function () {
    var request = indexedDB.open("QualDB", v);

    request.onsuccess = function (e) {
        QualStorage.indexedDB.db = e.target.result;

        var db = QualStorage.indexedDB.db;
        var transaction = db.transaction('Quals', 'readonly');
        var store = transaction.objectStore('Quals');

        var results = [];
        var tmp_results = {};

        store.openCursor().onsuccess = function (event) {
            var cursor = event.target.result;
            if (cursor) {
                var qual = cursor.value;
                if (tmp_results[cursor.key] === undefined) {
                    tmp_results[cursor.key] = [];
                    tmp_results[cursor.key][0] = qual.qualId;
                    tmp_results[cursor.key][1] = qual.qualName;
                    tmp_results[cursor.key][2] = qual.author;
                    tmp_results[cursor.key][3] = qual.desc;
                    tmp_results[cursor.key][4] = qual.assDate;
                    tmp_results[cursor.key][5] = qual.retDate;
                    tmp_results[cursor.key][6] = qual.users;
                    tmp_results[cursor.key][7] = qual.value;
                }
                cursor.continue();
            } else {
                for (var key in tmp_results) {
                    results.push(tmp_results[key]);
                }
                buildQualTable(results);
            }
        }
        db.close();
    }
}
//
//	END INDEXEDDB METHODS
//
//
// ******************************************************************
//
//
//	START SCRAPER METHODS
//
getNextURL = function (data) {
    var nextURL = $(data).find('a[href^="/mturk/viewquals"]:contains("Next")').attr("href");
    return nextURL;
}

scrapeQuals = function (nextPage) {
    QualStorage.indexedDB.create();
    var nextPage = nextPage;
    var currPage = $.get(nextPage, function(data) {
        var maxpagerate = $(data).find('td[class="error_title"]:contains("You have exceeded the maximum allowed page request rate for this website.")');
        if (maxpagerate.length === 0) {
            $('.updateLink').html(parseInt((scrapeNumber / qualCount) * 100) + "\%");
            
            var qualId = $(data).find('a[id*="requestQualLink"]');
            var title = $(data).find('a[class="capsulelink"]');
            
            scrapeNumber += title.length;
            
            var author = $(data).find('td[class="capsule_field_title"]:contains("Author:")').next();
            var value = $(data).find('td[class="capsule_field_title"]:contains("Qualification Value:")').next();
    		var users = $(data).find('td[class="capsule_field_title"]:contains("Qualified Users:")').next();
    		var description = $(data).find('td[class="capsule_field_title"]:contains("Description:")').next();
    		var dateassigned = $(data).find('td[class="capsule_field_title"]:contains("Date Assigned:")').next();
    		var dateretake = $(data).find('td[class="capsule_field_title"]:contains("Retake date:")').next();
            for (var i = 0; i < title.length; i++) {
               	qualObject["qualId"] = qualId.eq(i).attr("href").split('=')[1];
               	qualObject["qualName"] = title.eq(i).text().trim();
               	qualObject["author"] = author.eq(i).text().trim();
               	qualObject["desc"] = description.eq(i).text().trim();
               	qualObject["assDate"] = dateassigned.eq(i).text().trim();
               	qualObject["retDate"] = dateretake.eq(i).text().trim();
               	qualObject["users"] = users.eq(i).text().trim();
               	qualObject["value"] = value.eq(i).text().trim();
               	QualStorage.indexedDB.addQual(qualObject);
               	qualObject = {};
            }
            nextPage = getNextURL(data);
            if (! nextPage) {
            	$('.updateLink').html("Update ");   
            } else {
            	setTimeout(scrapeQuals(nextPage), 500);
            }
        } else {
            setTimeout(scrapeQuals(nextPage), 2000);
        }
    });        
}

//
//	END SCRAPER METHODS
//
//
// ******************************************************************
//
//
// START EVENT HANDLERS
//
addQualElement = function () {
	var allas, thisa;
	allas = document.getElementsByTagName('a');
	for (var i = 0; i < allas.length; i++)
	{
    	thisa = allas[i];
    	if ( thisa.innerHTML.match(/Transfer Earnings/))
    	{
        	var hed = document.createElement('tr');
        	hed.className = "metrics-table-header-row";
        
        	var qualsHeader = document.createElement('th');
        	qualsHeader.innerHTML = "Qualifications";
        	qualsHeader.className = "metrics-table-first-header";
        	hed.appendChild(qualsHeader);
        
        	var qualsValue = document.createElement('th');
        	qualsValue.innerHTML = "Value";
        	hed.appendChild(qualsValue);
        
        	var row = document.createElement('tr');
        	row.className = "odd";
            
            var qualsAssignedText = document.createElement('p');
            qualsAssignedText.setAttribute("name", "qualTitle");
        	qualsAssignedText.innerHTML = "Qualifications Assigned &nbsp;";
 
        	var cellLeft = document.createElement('td');
        	cellLeft.className = "metrics-table-first-value";
        	cellLeft.appendChild(qualsAssignedText);
        	row.appendChild(cellLeft);
                   
        	var cellRight = document.createElement('td');
            cellRight.innerHTML = qualCount + (qualDiff === 0 ? '' : (' (' + (qualDiff > 0 ? ('+' + qualDiff) : (qualDiff)) + ')'));
        	row.appendChild(cellRight);
                    
        	thisa.parentNode.parentNode.parentNode.insertBefore(hed,thisa.parentNode.parentNode.nextSibling);
        	hed.parentNode.insertBefore(row,hed.nextSibling);
        	//thisa.parentNode.parentNode.parentNode.insertBefore(row,thisa.parentNode.parentNode.nextSibling);
            
            $('p[name="qualTitle"]').append('<a href="#" class="updateLink" >Update </a>');
            $('p[name="qualTitle"]').append('<button title="View Qual Table" name="qualTableBut" class="qualTableBut" style="position:absolute;border-style:none;width:7px;height:10px;padding:0;margin-left:10px;margin-top:2px;background-image:url(https://i.imgur.com/iu7zXPz.png);background-color:transparent;cursor:pointer;"></button>').button();
    	}
	}
}

buildQualTable = function (qualStore) {
    $('#qualTable').append('<thead><tr><th>Qual ID</th><th>Qual Name</th><th>Author</th><th>Description</th><th width="75px">Assgn</th><th>Retake</th><th>Users</th><th>Value</th></tr></thead>');	
    $('#qualTable').append('<tbody></tbody>');
    for (var j = 0; j < qualStore.length; j++) {
        var qualRow = String(".qualRow" + j);
        
    	var tr = document.createElement("tr");
        tr.setAttribute('class', ('qualRow' + j));
        
		$(tr).append("<td>" + qualStore[j][0] + "</td>");        
        $(tr).append("<td>" + qualStore[j][1] + "</td>");
        $(tr).append("<td>" + qualStore[j][2] + "</td>");
        $(tr).append("<td style='width:350px'>" + qualStore[j][3] + "</td>");
        $(tr).append("<td>" + qualStore[j][4] + "</td>");
        $(tr).append("<td>" + qualStore[j][5] + "</td>");
        $(tr).append("<td>" + qualStore[j][6] + "</td>");
        $(tr).append("<td>" + qualStore[j][7] + "</td>");    
        
        $('#qualTable tbody').append(tr);
    }
    $('#qualTable').dataTable({
        paging: false
    });
}

$(document).on('click', '.updateLink', function () {
    scrapeQuals(nextPage);
});

$(document).ready( function () {
    if (document.URL === "https://www.mturk.com/mturk/qualtable") {
        $('body').html('');
        var qualTable = document.createElement("table");
        qualTable.setAttribute('class', 'display');
        qualTable.setAttribute('id', 'qualTable');
        $('body').append(qualTable);
        
        var qualElements = QualStorage.indexedDB.getQuals();
    }
});

$(document).on('click', '.qualTableBut', function () {
    window.open("https://www.mturk.com/mturk/qualtable", '_blank');
});
//
//	END EVENT HANDLERS
//
//