// ==UserScript==
// @name JR Crowdsource keyword/ranking mturk.com scripts
// @version 0.61
// @description A userscript for crowdsource keyword and ranking hits. It should be working for the keywords for any Google location. Also it will work for the ranking hits. It will even work for the choose the best URL hits.
// @author John Ramirez (JohnnyRS)
// @include *
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js
// @require http://ajax.googleapis.com/ajax/libs/jqueryui/1.5.2/jquery-ui.min.js
// @grant GM_addStyle
// @namespace https://greasyfork.dpdns.org/users/6406
// ==/UserScript==
// Version 0.6 - Fixed some instructions which were wrong for different versions of the hit. Refined some coding to be more efficient.
// -- Fixed a few bugs on the google pages where ads where counted. Added new version for google.cz hits.
// Description: This script makes it easier to do those silly Keywords on Google search sites. It should work for any Google country.
// --Keywords on Google (version 2)
// These are the ones which ask you to fill in the page and rank of a keyword. Then they ask a question you need to find on the URL
// page they want you to search for. This script adds a button to each task which will open up a new window with the Google search page.
// On the search page it should show 50 URLs down the page. There will be a pick button on the right of the site names.
// If the color of the button is red then that it is an exact match and it's your lucky day. Purple buttons are pages that have same domain names
// but not an exact match to the URL. Click on it to fill in the page and rank numbers automatically. It will open the new page in another window.
// Pressing F9 will hide/show the instruction box if it gets in the way of the page.
// Pressing n will fill in None automatically if you can't find the URL on the page.
// Pressing p will close the search window and return you to the hit page without filling in anything.
// There will be an instruction box to the right floating over the page. It shows the question to be answered and an input text to fill in if you
// need to fill it in yourself. There are buttons you can use to submit the URL or selection as the answer. You can close the page to go back to
// the Google page with the close button. The submit button will submit anything you typed in the text field as the answer. For easier submits you can use
// keyboard shortcuts as well:
// Pressing F9 will hide/show the instruction box if it gets in the way of the page.
// Pressing w will take the URL of the page as the answer and fill it in the hit automatically.
// Pressing e will focus on the input text field where you can type in your own answer. Pressing ENTER in the field will submit the text as the answer.
// Pressing p will close that window and return you to the Google search page so you can pick another site or go back to the hit.
// Pressing s will submit whatever you selected as the answer. I took out the submit button for selections because it caused problems on some pages.
// --Keywords on Google (version 1)
// Another hit which it will work is the version 1 of these where it asks you to fill in the best sentence for the keyword.
// It does everything like version 2 but it won't have a question so just select a sentence and submit.
// --Keywords on Google (URL version)
// These are the ones where it asks for the best URL for the keywords. These are very fast. Nothing to match so press the pick button
// next to the best site and it will fill in the URL automatically and close the search page.
//
// This should work on firefox and chrome. Had to fight chrome to make it work but finally tamed it.
// Because this script has to run for every page I recommend you to disable it after you use it. Makes things go faster.
// It shouldn't interfere with any page in normal situations. But some rare situations can occur so disable it.
// Best to disable scripts for individual requesters or hits anyway. Makes browsers go much faster and won't give problems like
// not letting you type in letters or submit automatically by mistake.
//
// Version 0.4 - Added instruction box UI for the question and answer phase. Didn't like using alert boxes for that section. Added new keyboard shortcuts also.
// -- Took out the submit box for selections. Press s to submit selection as answer or push the button in the instruction box.
// Constant variables used to verify it's working for only the correct hit.
// Also to check if it's in preview mode or not.
var VERIFY1 = "copy and paste the url of the most relevant result";
var VERIFY2 = "return information about a keyword search in";
var VERIFY3 = "record a url's search ranking on";
var VERIFY4 = "open google.cz, and search the provided keyword";
var OFF1 = "You are currently in preview mode";
function getHostName(url) {
var match = url.match(/:\/\/(www[0-9]?\.)?(.[^/:]+)/i);
if (match !== null && match.length > 2 &&
typeof match[2] === 'string' && match[2].length > 0) {
return match[2];
}
else {
return "";
}
}
function getDomainName(url) {
var hostName = getHostName(url);
var splitHostName = hostName.split('.');
if ( splitHostName.length > 2 ) return splitHostName[splitHostName.length-2] + "." + splitHostName[splitHostName.length-1];
else return hostName;
}
var gLocation = document.URL.toString();
var gHostname = getHostName(gLocation);
var gMyWindow = null, gSearchURLs = [], gTaskNumber = "", gQuestions = [], GTag = -1, gMouseTimer = null, gSearchVersion = 0;
var gGoogleDomain = "google.com", gKbShortcutFired = false, gMyInstructionsBox = null;
function dataFill(action, data1, data2, data3, data4) {
if(typeof(data1)==='undefined') data1 = "";
if(typeof(data2)==='undefined') data2 = "";
if(typeof(data3)==='undefined') data3 = "";
if(typeof(data4)==='undefined') data4 = "";
var tempe = {"verify": "feetsmell", "tag": GTag, "action": action, "data1": data1, "data2": data2, "data3": data3, "data4": data4};
return tempe;
}
function urlMatch(url1, url2) {
if(typeof(url1)==='undefined' || typeof(url2)==='undefined') return 0;
var hostName1 = getDomainName(url1);
var hostName2 = getDomainName(url2);
if ( url1 == url2 ) { return 1; }
else if ( hostName1 == hostName2 ) { return 2; }
else { return 0; }
}
function createButton(theId,theValue) {
var theButton = document.createElement("INPUT"); theButton.id = theId;
theButton.value = theValue;
theButton.type = "button";
return theButton;
}
function createTextInput(theId,theValue,theSize) {
var theInput = document.createElement("INPUT"); theInput.id = theId;
theInput.value = theValue;
theInput.size = theSize;
theInput.type = "text";
return theInput;
}
function answerURL() {
data = dataFill( "submit answer", gTaskNumber, document.URL.toString() );
window.opener.postMessage(data,"*");
}
function answerSel() {
data = dataFill( "submit answer", gTaskNumber, window.getSelection().toString() );
window.opener.postMessage(data,"*");
}
function answerInput() {
data = dataFill( "submit answer", gTaskNumber, $("#enterAnswer").val() );
window.opener.postMessage(data,"*");
}
function answerNone() {
data = dataFill( "found page and rank", gTaskNumber, "None", "None", "None" );
window.opener.postMessage(data,"*");
self.close();
}
function textInputFocus() {
var gRightSideBar = $('#myInstructionsBox');
gKbShortcutFired = false;
gRightSideBar.stop (true, false).fadeTo (50, 1 );
}
function textInputFocusout() {
var gRightSideBar = $('#myInstructionsBox');
if ( !gRightSideBar.is(":hover") ) {
gRightSideBar.stop (true, false).fadeTo (2900, 0.1);
}
}
function attrInstructionsBox() {
gMyInstructionsBox = $('#myInstructionsBox');
GM_addStyle ( " \
#myInstructionsBox { \
position: fixed; \
top: 100px; \
right: 0; \
margin: 1ex; \
padding: 1em; \
background: #0B0B3B; \
width: 460px; \
z-index: 99999; \
opacity: 0.9; \
color: #F7F8E0; \
text-align: left; \
line-height: 18px; \
font-family: Helvetica,Arial,Sans-Serif; \
} \
#myInstructionsBox p { \
font-size: 14px; \
} \
#myInstructionsBox #myInstructions { \
font-size: 14px; \
color: #F7F8E0; \
padding: 2px 0 10px 8px; \
} \
#myInstructionsBox #theQuestion { \
font-size: 18px; \
color: cyan; \
margin-top: 8px; \
padding: 12px 0 15px 5px; \
background: #000000; \
} \
#myInstructionsBox #theControls { \
padding: 0 0 0 15px; \
} \
#myInstructionsBox #textinput { \
font-size: 16px; \
padding: 12px 0 15px 5px; \
color: #000000; \
} \
#myInstructionsBox ul { \
margin: 0ex; \
} \
#myInstructionsBox input { \
margin: 2px; \
color: #000000; \
font-size: 16px; \
padding: 1px 6px; \
} \
#myInstructionsBox input[type=text] { \
height: 14px; \
padding: 1px, 2px; \
width: 440px; \
font-size: 12px; \
} \
#myInstructionsBox a { \
color: white; \
} \
" );
gKbShortcutFired = false;
gMyInstructionsBox.draggable();
//-- Fade panel when not in use
gMyInstructionsBox.hover (
function () {
$(this).stop (true, false).fadeTo (50, 1 );
gKbShortcutFired = false;
},
function () {
if ( !$("#enterAnswer").is(":focus") ) {
if ( ! gKbShortcutFired ) {
$(this).stop (true, false).fadeTo (2900, 0.1);
}
gKbShortcutFired = false;
}
}
);
gMyInstructionsBox.fadeTo (2900, 0.1);
$(window).keydown ( function(e) {
if (e.keyCode == 120) { // F9 to toggle box
gKbShortcutFired = true;
if (gMyInstructionsBox.is (":visible") ) {
gMyInstructionsBox.stop (true, false).hide ();
}
else {
//-- Reappear opaque to start
gMyInstructionsBox.stop (true, false).show ();
gMyInstructionsBox.fadeTo (0, 1);
if ( !$("#enterAnswer").is(":focus") ) gRightSideBar.fadeTo (3900, 0.1);
}
e.preventDefault ();
e.stopPropagation ();
return false;
}
},false);
}
function GoogleInstructionsBox(instructions) {
var closeButton = createButton("closeMe","Close page (p)");
closeButton.onclick = function () { self.close(); }
var frag = document.createDocumentFragment();
var instructionsBox = document.createElement("div"); instructionsBox.id = "myInstructionsBox";
var instructionsH3 = document.createElement("div"); instructionsH3.id = "myInstructions";
instructionsH3.innerHTML = "[ F9 toggles visibility ] [ Box is draggable ]<br>" + instructions;
var controlsH4 = document.createElement("div"); controlsH4.id = "theControls";
if (gSearchVersion == "2" || gSearchVersion == "3") {
var noneButton = createButton("noneAnswer","None (n)");
noneButton.onclick = function () { answerNone(); }
controlsH4.appendChild(noneButton);
}
controlsH4.appendChild(closeButton);
var questionH4 = document.createElement("div"); questionH4.id = "theQuestion";
instructionsBox.appendChild(instructionsH3);
instructionsBox.appendChild(controlsH4);
if (gSearchVersion == "2" || gSearchVersion == "3") {
questionH4.innerHTML = "URL: " + gSearchURLs[0];
instructionsBox.appendChild(questionH4);
}
frag.appendChild(instructionsBox);
document.body.appendChild(frag);
attrInstructionsBox();
document.onkeydown = function (e) {
if (e.keyCode == 78) answerNone(); // n = Can't find URL.
else if (e.keyCode == 80) self.close(); // p = close this window and go back to google search.
};
}
function URLInstructionsBox(instructions,question) {
var urlButton = createButton("urlAnswer","URL (w)");
urlButton.onclick = function () { answerURL(); }
var selButton = createButton("selAnswer","Selection (s)");
selButton.onclick = function () { answerSel(); }
var closeButton = createButton("closeMe","Close page (p)");
closeButton.onclick = function () { self.close(); }
var submitButton = createButton("submitInput","Send Answer");
submitButton.onclick = function () { answerInput(); }
var textInput = createTextInput("enterAnswer","","70");
var frag = document.createDocumentFragment();
var instructionsBox = document.createElement("div"); instructionsBox.id = "myInstructionsBox";
var instructionsH3 = document.createElement("div"); instructionsH3.id = "myInstructions";
instructionsH3.innerHTML = "[ F9 toggles visibility ] [ Box is draggable ]<br>" + instructions;
var questionH4 = document.createElement("div"); questionH4.id = "theQuestion";
questionH4.innerHTML = "Question: " + question;
var controlsH4 = document.createElement("div"); controlsH4.id = "theControls";
controlsH4.innerHTML = "Answer: ";
controlsH4.appendChild(selButton);
controlsH4.appendChild(urlButton);
controlsH4.appendChild(closeButton);
var answerH4 = document.createElement("div"); answerH4.id = "yourAnswer";
answerH4.innerHTML = "Type in Answer:<br>";
answerH4.appendChild(textInput);
answerH4.appendChild(submitButton);
instructionsBox.appendChild(instructionsH3);
instructionsBox.appendChild(controlsH4);
instructionsBox.appendChild(questionH4);
instructionsBox.appendChild(answerH4);
frag.appendChild(instructionsBox);
document.body.appendChild(frag);
textInput.onfocus = function(){ textInputFocus(); };
textInput.onblur = function(){ textInputFocusout(); };
attrInstructionsBox();
document.onkeydown = function (e) {
if (e.target.id !="enterAnswer") {
if (e.keyCode == 87) answerURL(); // w = Use URL for answer.
else if (e.keyCode == 83) answerSel(); // s = to use your selection for answer.
else if (e.keyCode == 80) self.close(); // p = close this window and go back to google search.
else if (e.keyCode == 69) { // e = Type in answer
textInput.focus();
e.preventDefault ();
e.stopPropagation ();
return false;
}
} else if ( e.keyCode == 13 ) answerInput(); // enter in input text will submit input value.
};
}
function verifyMessage(e) {
if (e.data.verify === "feetsmell") {
if ( (GTag!=-1 && e.data.tag!=-1 && e.data.tag == GTag) || GTag == -1 || e.data.tag == -1) {
return true;
}
}
return false;
}
function doFrameMessage(e) {
if (e.data.action == "initialize google") {
var theData = dataFill( "search URL", GTag );
if (gSearchVersion==2 || gSearchVersion==3) {
theData = dataFill( "search URL", gSearchVersion, gSearchURLs[e.data.data1-1], gQuestions[e.data.data1-1], GTag );
} else if (gSearchVersion==1 || gSearchVersion==4) {
theData = dataFill( "search URL", gSearchVersion, GTag );
}
gMyWindow.postMessage( theData,"*");
}
else if (e.data.action == "found page and rank") {
if (gSearchVersion==3 && (e.data.data2=="None" || e.data.data3=="None")) {
document.getElementById("PageNumber-"+e.data.data1).value = "";
document.getElementById("Ranking-"+e.data.data1).value = "";
document.getElementById("BeyondPage5-"+e.data.data1).checked = true;
document.getElementById("Sentence-"+e.data.data1).value = "";
} else {
document.getElementById("PageNumber-"+e.data.data1).value = e.data.data2;
document.getElementById("Ranking-"+e.data.data1).value = e.data.data3;
if (document.getElementById("BeyondPage5-"+e.data.data1)!==null) {
document.getElementById("BeyondPage5-"+e.data.data1).checked = false;
}
if (e.data.data4 !== "") document.getElementById("WorkerResponse-"+e.data.data1).value = e.data.data4;
}
} else if (e.data.action == "found url") { // This is for version 1 of the keyword search
document.getElementById("URL-"+e.data.data1).value = e.data.data2;
} else if (e.data.action == "found answer") {
if (gSearchVersion==3) document.getElementById("Sentence-"+e.data.data1).value = e.data.data2;
else document.getElementById("WorkerResponse-"+e.data.data1).value = e.data.data2;
}
}
function doGoogleMessage(e) {
if (e.data.action == "initialize question") {
var theData = dataFill( "answer question", gTaskNumber, gQuestions[0], GTag );
gMyWindow.postMessage( theData,"*");
} else if (e.data.action == "search URL" && GTag == -1) {
gSearchVersion = e.data.data1;
if (gSearchVersion==2 || gSearchVersion==3) {
gSearchURLs[0] = e.data.data2;
gQuestions[0] = e.data.data3;
GTag = e.data.data4;
} else if (gSearchVersion==1 || gSearchVersion==4) {
GTag = e.data.data2;
}
var results = document.getElementsByClassName("g");
var i=0; var pageNum=1; var rankNum=1;
while ( (result = results[i++]) ) {
if ( result.getElementsByClassName("r").length>0 && result.getElementsByClassName("_SWb").length>0 &&
result.getElementsByClassName("_YM").length==0 && result.getElementsByClassName("kno-fb").length==0) {
var url = result.getElementsByTagName("a")[0];
var btn = document.createElement("BUTTON");
btn.innerHTML = "Pick";
btn.type = "button";
btn.style.marginRight = "6px";
btn.name = "B," + pageNum + "," + rankNum + "," + url.href;
matching = urlMatch( url.href, gSearchURLs[0] );
if ( matching == 1 ) {
btn.style.background='red';
btn.style.color='#FFFFFF';
} else if ( matching == 2 ) {
btn.style.background="Purple";
btn.style.color="#FFFFFF";
} else if ( matching == 3 ) {
btn.style.background="#F8E0F7";
btn.style.color="#000000";
}
btn.style.fontSize="small";
btn.disabled = false;
btn.onclick = function() {
var splitName = this.name.split(',');
if (gSearchVersion == 2 || gSearchVersion == 3) {
var theData = dataFill( "found page and rank", gTaskNumber, splitName[1], splitName[2] );
window.opener.postMessage(theData,"*");
gMyWindow = window.open(splitName[3]);
theData = dataFill( "start", gTaskNumber, gQuestions[0] );
gMyWindow.postMessage(theData,"*");
} else if (gSearchVersion == 1 || gSearchVersion ==4) {
var theData = dataFill( "found url", gTaskNumber, splitName[3] );
window.opener.postMessage(theData,"*");
self.close();
}
};
url.parentNode.insertBefore(btn,url);
rankNum++;
if ( rankNum>10 ) {
rankNum=1; pageNum++;
}
}
}
var myInstructions = "[ p to go back ]<br>";
if (gSearchVersion == "2" || gSearchVersion == "3") myInstructions = "[ n to fill in nothing found ] [ p to go back ]<br><br>" +
"Red buttons are perfect matches<br>Purple buttons are same domain names.";
GoogleInstructionsBox(myInstructions);
} else if (e.data.action == "submit answer") {
console.log("...G Submit answer message received: " + e.data.data1 + " - " + e.data.data2 );
var theData = dataFill( "found answer", gTaskNumber, e.data.data2 );
window.opener.postMessage( theData,"*");
gMyWindow.close();
self.close();
}
}
function doUrlMessage(e) {
if (e.data.action == "answer question" && GTag == -1) {
gTaskNumber = e.data.data1
gQuestions[0] = e.data.data2;
GTag = e.data.data3;
var myInstructions = "[ w to use the URL for the answer ] ";
myInstructions += "[ e to fill in answer ]<br />[ s to use selection as answer ] [ p to go back to google ]\n";
URLInstructionsBox(myInstructions,gQuestions[0]);
}
}
function getGoogleDomain() {
if (gSearchVersion==0) return;
var title = document.getElementsByClassName("projectTitle")[0].innerHTML;
if (title.length>0 && title!="Search: Ranking of a Url") {
var title = title.replace("Search: Keywords on ","");
title = title.replace("Search: Ranking of a Url on ","");
var splitTitle = title.split(' ');
gGoogleDomain = splitTitle[0];
}
}
function taskSearchButtons() {
if (gSearchVersion==0) return;
var tasks = document.getElementsByClassName("task cf");
var i=0;
while ( (task = tasks[i++]) ) {
var theTextReps = task.getElementsByClassName("text-rep");
var theTextRep = theTextReps[0].innerHTML;
var splitTextRep = theTextRep.split('<br>');
theKeyword = splitTextRep[0].replace(/(<([^>]+)>)/ig, "");
theKeyword = theKeyword.replace(/^keyword:\s/i,"");
theKeyword = theKeyword.replace(/&+/,"%26");
theKeyword = theKeyword.replace(/\s+$/, ''); // remove spaces at end of string
if (gSearchVersion==2 || gSearchVersion==3) { // Version 2 and 3 needs the URL and question.
var theURL="";
var theQuestion="";
if (splitTextRep.length>1) {
theURL = splitTextRep[1];
theQuestion = "Click Url and record one sentence on webpage that relates to the provided keyword";
} else {
theURL = theTextReps[1].innerHTML;
theQuestion = theTextReps[2].innerHTML.replace("Instructions: ","");
theQuestion = theQuestion.replace(/\s+$/, '');
}
theURL = theURL.replace(/(<([^>]+)>)/ig, "");
theURL = theURL.replace(/^url:\s/i,"");
theURL = theURL.replace(/\s+$/, "");
gSearchURLs[i-1] = theURL;
gQuestions[i-1] = theQuestion;
}
var btn = document.createElement("BUTTON");
btn.innerHTML = "Search";
btn.type = "button";
btn.name = "B," + i + "," + theKeyword ;
btn.style.fontSize="small";
btn.style.marginLeft = "5px";
btn.disabled = false;
btn.onclick = function() {
var splitName = this.name.split(',');
gMyWindow = window.open("http://www." + gGoogleDomain + "/search?num=50&q=" + splitName[2].replace(/\s+/g,"+") + "&jrio=feetwalk&ttt=" + splitName[1]);
};
theTextReps[0].appendChild(btn);
}
}
function mainListener(e) { // Just a repeater to the frame (Google Chrome fix because messaging to the frame wasn't working.)
if ( verifyMessage(e) ) {
if (e.origin.indexOf("google") != -1) {
var doc=document.getElementsByTagName("iframe")[0].contentWindow;
doc.postMessage(e.data,"*");
}
}
}
function frameListener(e) {
if ( verifyMessage(e) ) {
if (e.origin.indexOf("mturk") != -1 || e.origin.indexOf("google") != -1) doFrameMessage(e);
}
}
// Check if page is on crowdsource or google. If not then check if page was opened by script. If not then exit.
if ( gHostname === "work.crowdsource.com" || gLocation.indexOf("jrio=feetwalk") != -1 || window.opener || gHostname === "mturk.com" ) {
//console.log (".Script starts...");
// The magic begins here by first making sure I am on a crowdsource page
// and then checking if it's a crowdsource hit that it will work with.
// After I set up the buttons to make the search for keywords easier.
if (gHostname=="work.crowdsource.com"){ // Make sure this is on the crowdsource site.
window.addEventListener("message", function(e){ frameListener(e); }, false);
GTag = new Date().getTime(); // A unique global tag used to pass messages only for this session.
var instructions = document.getElementById("instructions").innerHTML;
if (instructions.toLowerCase().indexOf(VERIFY1) != -1) gSearchVersion = 1;
else if (instructions.toLowerCase().indexOf(VERIFY2) != -1) gSearchVersion = 2;
else if (instructions.toLowerCase().indexOf(VERIFY3) != -1) gSearchVersion = 3;
else if (instructions.toLowerCase().indexOf(VERIFY4) != -1) gSearchVersion = 4;
getGoogleDomain();
taskSearchButtons();
} else if (gLocation.indexOf("jrio=feetwalk") != -1) {
gTaskNumber = (gLocation.substr(gLocation.indexOf("jrio=feetwalk"))).split("&")[1];
gTaskNumber = gTaskNumber.replace("ttt=","");
window.addEventListener("message", function(e){ if ( verifyMessage(e) ) doGoogleMessage(e); }, false);
var theData = dataFill( "initialize google", gTaskNumber );
parent.window.opener.postMessage(theData,"*");
} else if (gHostname=="mturk.com") {
window.addEventListener("message", function(e){ mainListener(e); }, false);
} else {
var theData = dataFill( "initialize question" );
window.opener.postMessage(theData,"*");
window.addEventListener("message", function(e){ if ( verifyMessage(e) ) doUrlMessage(e); }, false);
}
}