// ==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 ";
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
//
//