Block Requesters (Fixed)

Hide HITs from requesters you're not interested in (FIXED FOR GOOGLE CHROME)

目前为 2015-07-09 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Block Requesters (Fixed)
  3. // @author Aphit (adopted from Ergo)
  4. // @version 1.0.0
  5. // @description Hide HITs from requesters you're not interested in (FIXED FOR GOOGLE CHROME)
  6. // @include https://www.mturk.com/mturk/findhits*
  7. // @include https://www.mturk.com/mturk/searchbar*
  8. // @include https://www.mturk.com/mturk/viewsearchbar*
  9. // @include https://www.mturk.com/mturk/sorthits*
  10. // @include https://www.mturk.com/mturk/viewhits*
  11. // @include https://www.mturk.com/mturk/accept*
  12. // @include https://www.mturk.com/mturk/preview*
  13. // @include https://www.mturk.com/mturk/return*
  14. // @include https://www.mturk.com/mturk/sortsearchbar*
  15. // @namespace https://greasyfork.org/users/6438
  16. // ==/UserScript==
  17.  
  18.  
  19.  
  20. //CHANGES
  21.  
  22. function GM_setValue( cookieName, cookieValue, lifeTime ) {
  23. if( !cookieName ) { return; }
  24. if( lifeTime == "delete" ) { lifeTime = -10; } else { lifeTime = 31536000; }
  25. document.cookie = escape( cookieName ) + "=" + escape( getRecoverableString( cookieValue ) ) +
  26. ";expires=" + ( new Date( ( new Date() ).getTime() + ( 1000 * lifeTime ) ) ).toGMTString() + ";path=/";
  27. }
  28.  
  29. function GM_getValue( cookieName, oDefault ) {
  30. var cookieJar = document.cookie.split( "; " );
  31. for( var x = 0; x < cookieJar.length; x++ ) {
  32. var oneCookie = cookieJar[x].split( "=" );
  33. if( oneCookie[0] == escape( cookieName ) ) {
  34. try {
  35. eval('var footm = '+unescape( oneCookie[1] ));
  36. } catch(e) { return oDefault; }
  37. return footm;
  38. }
  39. }
  40. return oDefault;
  41. }
  42.  
  43. function GM_deleteValue( oKey ) {
  44. //yes, they didn't seem to provide a way to delete variables in Greasemonkey, and the user must use about:config to
  45. //delete them - so the stored variables will pile up forever ...
  46. GM_setValue( oKey, '', 'delete' );
  47. }
  48.  
  49. var GM_falsifiedMenuCom = [], hasPageGMloaded = false;
  50. window.addEventListener('load',function () {hasPageGMloaded=true;doGMMeenoo();},false)
  51. function GM_registerMenuCommand( oText, oFunc ) {
  52. GM_falsifiedMenuCom[GM_falsifiedMenuCom.length] = [oText,oFunc];
  53. if( hasPageGMloaded ) { doGMMeenoo(); } //if the page has already loaded, do it now
  54. }
  55.  
  56. function doGMMeenoo() {
  57. if( !GM_falsifiedMenuCom.length ) { return; }
  58. //create a menu of commands in the top corner
  59. var foo = document.getElementById('GM_Falsify_me'), bar, par = document.body ? document.body : document.documentElement;
  60. if( foo ) { par.removeChild(foo); }
  61. foo = document.createElement('GMmenoo');
  62. foo.id = 'GM_Falsify_me';
  63. par.appendChild(foo);
  64. with( foo.style ) {
  65. border = '1px solid #000';
  66. backgroundColor = '#bbf';
  67. color = '#000';
  68. position = 'fixed';
  69. zIndex = '100000';
  70. top = '0px';
  71. right = '0px';
  72. padding = '2px';
  73. overflow = 'hidden';
  74. height = '1.3em';
  75. }
  76. foo.appendChild(bar = document.createElement('b'))
  77. bar.style.cursor = 'move';
  78. bar.onclick = function () {
  79. this.parentNode.style.left = this.parentNode.style.left ? '' : '0px';
  80. this.parentNode.style.right = this.parentNode.style.right ? '' : '0px';
  81. };
  82. bar.appendChild(document.createTextNode('User Script Commands'));
  83. foo.appendChild(bar = document.createElement('ul'));
  84. bar.style.margin = '0px';
  85. bar.style.padding = '0px';
  86. bar.style.listStylePosition = 'inside';
  87. for( var i = 0; GM_falsifiedMenuCom[i]; i++ ) {
  88. var baz = document.createElement('li'), bing;
  89. baz.appendChild(bing = document.createElement('a'));
  90. bing.setAttribute('href','#');
  91. bing.onclick = new Function('GM_falsifiedMenuCom['+i+'][1](arguments[0]);return false;');
  92. bing.onfocus = function () { this.parentNode.style.height = ''; };
  93. bing.onblur = function () { this.parentNode.style.height = '1.3em'; };
  94. bing.appendChild(document.createTextNode(GM_falsifiedMenuCom[i][0]));
  95. bar.appendChild(baz);
  96. }
  97. foo.onmouseover = function () { this.style.height = ''; };
  98. foo.onmouseout = function () { this.style.height = '1.3em'; };
  99. }
  100.  
  101. // GM_log = opera.postError;
  102.  
  103. window._content = window;
  104.  
  105. function getRecoverableString(oVar,notFirst) {
  106. var oType = typeof(oVar);
  107. if( ( oType == 'null' ) || ( oType == 'object' && !oVar ) ) {
  108. //most browsers say that the typeof for null is 'object', but unlike a real
  109. //object, it will not have any overall value
  110. return 'null';
  111. }
  112. if( oType == 'undefined' ) { return 'window.uDfXZ0_d'; }
  113. if( oType == 'object' ) {
  114. //Safari throws errors when comparing non-objects with window/document/etc
  115. if( oVar == window ) { return 'window'; }
  116. if( oVar == document ) { return 'document'; }
  117. if( oVar == document.body ) { return 'document.body'; }
  118. if( oVar == document.documentElement ) { return 'document.documentElement'; }
  119. }
  120. if( oVar.nodeType && ( oVar.childNodes || oVar.ownerElement ) ) { return '{error:\'DOM node\'}'; }
  121. if( !notFirst ) {
  122. Object.prototype.toRecoverableString = function (oBn) {
  123. if( this.tempLockIgnoreMe ) { return '{\'LoopBack\'}'; }
  124. this.tempLockIgnoreMe = true;
  125. var retVal = '{', sepChar = '', j;
  126. for( var i in this ) {
  127. if( i == 'toRecoverableString' || i == 'tempLockIgnoreMe' || i == 'prototype' || i == 'constructor' ) { continue; }
  128. if( oBn && ( i == 'index' || i == 'input' || i == 'length' || i == 'toRecoverableObString' ) ) { continue; }
  129. j = this[i];
  130. if( !i.match(basicObPropNameValStr) ) {
  131. //for some reason, you cannot use unescape when defining peoperty names inline
  132. for( var x = 0; x < cleanStrFromAr.length; x++ ) {
  133. i = i.replace(cleanStrFromAr[x],cleanStrToAr[x]);
  134. }
  135. i = '\''+i+'\'';
  136. } else if( window.ActiveXObject && navigator.userAgent.indexOf('Mac') + 1 && !navigator.__ice_version && window.ScriptEngine && ScriptEngine() == 'JScript' && i.match(/^\d+$/) ) {
  137. //IE mac does not allow numerical property names to be used unless they are quoted
  138. i = '\''+i+'\'';
  139. }
  140. retVal += sepChar+i+':'+getRecoverableString(j,true);
  141. sepChar = ',';
  142. }
  143. retVal += '}';
  144. this.tempLockIgnoreMe = false;
  145. return retVal;
  146. };
  147. Array.prototype.toRecoverableObString = Object.prototype.toRecoverableString;
  148. Array.prototype.toRecoverableString = function () {
  149. if( this.tempLock ) { return '[\'LoopBack\']'; }
  150. if( !this.length ) {
  151. var oCountProp = 0;
  152. for( var i in this ) { if( i != 'toRecoverableString' && i != 'toRecoverableObString' && i != 'tempLockIgnoreMe' && i != 'prototype' && i != 'constructor' && i != 'index' && i != 'input' && i != 'length' ) { oCountProp++; } }
  153. if( oCountProp ) { return this.toRecoverableObString(true); }
  154. }
  155. this.tempLock = true;
  156. var retVal = '[';
  157. for( var i = 0; i < this.length; i++ ) {
  158. retVal += (i?',':'')+getRecoverableString(this[i],true);
  159. }
  160. retVal += ']';
  161. delete this.tempLock;
  162. return retVal;
  163. };
  164. Boolean.prototype.toRecoverableString = function () {
  165. return ''+this+'';
  166. };
  167. Date.prototype.toRecoverableString = function () {
  168. return 'new Date('+this.getTime()+')';
  169. };
  170. Function.prototype.toRecoverableString = function () {
  171. return this.toString().replace(/^\s+|\s+$/g,'').replace(/^function\s*\w*\([^\)]*\)\s*\{\s*\[native\s+code\]\s*\}$/i,'function () {[\'native code\'];}');
  172. };
  173. Number.prototype.toRecoverableString = function () {
  174. if( isNaN(this) ) { return 'Number.NaN'; }
  175. if( this == Number.POSITIVE_INFINITY ) { return 'Number.POSITIVE_INFINITY'; }
  176. if( this == Number.NEGATIVE_INFINITY ) { return 'Number.NEGATIVE_INFINITY'; }
  177. return ''+this+'';
  178. };
  179. RegExp.prototype.toRecoverableString = function () {
  180. return '\/'+this.source+'\/'+(this.global?'g':'')+(this.ignoreCase?'i':'');
  181. };
  182. String.prototype.toRecoverableString = function () {
  183. var oTmp = escape(this);
  184. if( oTmp == this ) { return '\''+this+'\''; }
  185. return 'unescape(\''+oTmp+'\')';
  186. };
  187. }
  188. if( !oVar.toRecoverableString ) { return '{error:\'internal object\'}'; }
  189. var oTmp = oVar.toRecoverableString();
  190. if( !notFirst ) {
  191. //prevent it from changing for...in loops that the page may be using
  192. delete Object.prototype.toRecoverableString;
  193. delete Array.prototype.toRecoverableObString;
  194. delete Array.prototype.toRecoverableString;
  195. delete Boolean.prototype.toRecoverableString;
  196. delete Date.prototype.toRecoverableString;
  197. delete Function.prototype.toRecoverableString;
  198. delete Number.prototype.toRecoverableString;
  199. delete RegExp.prototype.toRecoverableString;
  200. delete String.prototype.toRecoverableString;
  201. }
  202. return oTmp;
  203. }
  204. var basicObPropNameValStr = /^\w+$/, cleanStrFromAr = new Array(/\\/g,/'/g,/"/g,/\r/g,/\n/g,/\f/g,/\t/g,new RegExp('-'+'->','g'),new RegExp('<!-'+'-','g'),/\//g), cleanStrToAr = new Array('\\\\','\\\'','\\\"','\\r','\\n','\\f','\\t','-\'+\'->','<!-\'+\'-','\\\/');
  205.  
  206. /* GM_xmlhttpRequest implementation adapted from the
  207. Turnabout GM compatibility library:
  208. http://www.reifysoft.com/turnabout.php
  209. Used under the following license:
  210.  
  211. Copyright (c) 2005, Reify Software, Inc.
  212. All rights reserved.
  213.  
  214. Redistribution and use in source and binary forms,
  215. with or without modification, are permitted provided
  216. that the following conditions are met:
  217.  
  218. 1) Redistributions of source code must retain the
  219. above copyright notice, this list of conditions
  220. and the following disclaimer.
  221. 2) Redistributions in binary form must reproduce the
  222. above copyright notice, this list of conditions
  223. and the following disclaimer in the documentation
  224. and/or other materials provided with the
  225. distribution.
  226. 3) Neither the name of the Reify Software, Inc. nor
  227. the names of its contributors may be used to
  228. endorse or promote products derived from this
  229. software without specific prior written permission.
  230.  
  231. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
  232. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
  233. WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  234. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  235. PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  236. THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
  237. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  238. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  239. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  240. USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  241. HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  242. IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  243. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  244. USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  245. OF SUCH DAMAGE.
  246.  
  247. */
  248. //yes, I know the domain limitations, but it's better than an outright error
  249. function GM_xmlhttpRequest(details) {
  250. var xmlhttp = new XMLHttpRequest();
  251. xmlhttp.onreadystatechange = function() {
  252. var responseState = {
  253. responseXML:(xmlhttp.readyState==4 ? xmlhttp.responseXML : ''),
  254. responseText:(xmlhttp.readyState==4 ? xmlhttp.responseText : ''),
  255. readyState:xmlhttp.readyState,
  256. responseHeaders:(xmlhttp.readyState==4 ? xmlhttp.getAllResponseHeaders() : ''),
  257. status:(xmlhttp.readyState==4 ? xmlhttp.status : 0),
  258. statusText:(xmlhttp.readyState==4 ? xmlhttp.statusText : '')
  259. }
  260. if (details["onreadystatechange"]) {
  261. details["onreadystatechange"](responseState);
  262. }
  263. if (xmlhttp.readyState==4) {
  264. if (details["onload"] && xmlhttp.status>=200 && xmlhttp.status<300) {
  265. details["onload"](responseState);
  266. }
  267. if (details["onerror"] && (xmlhttp.status<200 || xmlhttp.status>=300)) {
  268. details["onerror"](responseState);
  269. }
  270. }
  271. }
  272. try {
  273. //cannot do cross domain
  274. xmlhttp.open(details.method, details.url);
  275. } catch(e) {
  276. if( details["onerror"] ) {
  277. //simulate a real error
  278. details["onerror"]({responseXML:'',responseText:'',readyState:4,responseHeaders:'',status:403,statusText:'Forbidden'});
  279. }
  280. return;
  281. }
  282. if (details.headers) {
  283. for (var prop in details.headers) {
  284. xmlhttp.setRequestHeader(prop, details.headers[prop]);
  285. }
  286. }
  287. xmlhttp.send((typeof(details.data)!='undefined')?details.data:null);
  288. }
  289.  
  290. function GM_addStyle(css) {
  291. var NSURI = 'http://www.w3.org/1999/xhtml';
  292. var hashead = document.getElementsByTagName('head')[0];
  293. var parentel = hashead || document.documentElement;
  294. var newElement = document.createElementNS(NSURI,'link');
  295. newElement.setAttributeNS(NSURI,'rel','stylesheet');
  296. newElement.setAttributeNS(NSURI,'type','text/css');
  297. newElement.setAttributeNS(NSURI,'href','data:text/css,'+encodeURIComponent(css));
  298. if( hashead ) {
  299. parentel.appendChild(newElement);
  300. } else {
  301. parentel.insertBefore(newElement,parentel.firstChild);
  302. }
  303. }
  304.  
  305. if(window.navigator.vendor.match(/Google/)) {
  306. var div = document.createElement("div");
  307. div.setAttribute("onclick", "return window;");
  308. unsafeWindow = div.onclick();
  309. };
  310.  
  311.  
  312. //CHANGES
  313.  
  314.  
  315.  
  316. requesterIndex = GM_getValue("requesterIndex");
  317. if(!requesterIndex) {
  318. //alert(requesterIndex);
  319. requesterIndex="";
  320. GM_setValue("requesterIndex","");
  321. }
  322.  
  323.  
  324. function showUpdates() {
  325. updated = GM_getValue('requesterUpdated');
  326. if (updated) {
  327. tables = document.evaluate("//table",document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);
  328. table = tables.snapshotItem(6);
  329. action = updated.split(',');
  330. rId = action[1].split('::')[0];
  331. rName = action[1].split('::')[1];
  332. div = document.createElement('div');
  333. div.id = 'updated';
  334. status = "<div class='message success'><h6><span id='alertboxHeader'>"+action[0]+" "+rName;
  335. if (action[0]=='Blocked') {
  336. status+=" <a style='font-size:80%;' href='javascript:unblockRequester(\""+rId+"\",\""+rName+"\");' title='Unblock this requester'>undo</a>";
  337. }
  338. div.innerHTML = status + "</h6></span></div>";
  339. table.parentNode.insertBefore(div, table);
  340. GM_deleteValue('requesterUpdated');
  341. }
  342. }
  343.  
  344. function hideHIT(element) {
  345. pa=element, step=0;
  346. while (step++ < 14) {
  347. ch = pa;
  348. pa = pa.parentNode;
  349. }
  350. pa.className = "blocked";
  351. }
  352.  
  353. function unhideHIT(element) {
  354. pa=element, step=0;
  355. while (step++ < 14) {
  356. ch = pa;
  357. pa = pa.parentNode;
  358. }
  359. pa.className = "";
  360. }
  361.  
  362. function hideMatchingHITs() {
  363. var numBlocked=0;
  364. theseRequesters = document.evaluate("//a[starts-with(@href,'/mturk/searchbar?selectedSearchType=hitgroups&requesterId=')]",document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);
  365. for (i=0; i<theseRequesters.snapshotLength; i++) {
  366. rLink = theseRequesters.snapshotItem(i);
  367. rLink.parentNode.nowrap = false;
  368. rName = rLink.innerHTML;
  369. rId = rLink.href.toString().split('=')[2];
  370. if (requesterIndex.indexOf(rId) != -1 && location.href.indexOf(rId) == -1) {
  371. newElement = document.createElement('a');
  372. newElement.innerHTML = "&nbsp;<a style='font-size:80%;' href='javascript:unblockRequester(\""+rId+"\",\""+rName+"\");' title='Unblock this requester'>unblock</a>";
  373. rLink.parentNode.insertBefore(newElement, rLink.nextSibling);
  374. hideHIT(rLink);
  375. numBlocked+=1;
  376. } else {
  377. newElement = document.createElement('a');
  378. newElement.innerHTML = "&nbsp;<a href='javascript:blockRequester(\""+rId+"\","+i+");' style='font-size:80%;' title='Block this requester'>x</a>";
  379. rLink.parentNode.insertBefore(newElement, rLink.nextSibling);
  380. }
  381. }
  382. return numBlocked;
  383. }
  384.  
  385. unsafeWindow.unhideAllHITs = function () {
  386. theseRequesters = document.evaluate("//a[starts-with(@href,'/mturk/searchbar?selectedSearchType=hitgroups&requesterId=')]",document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);
  387. for (i=0; i<theseRequesters.snapshotLength; i++) {
  388. unhideHIT(theseRequesters.snapshotItem(i));
  389. }
  390. }
  391.  
  392. function showNumBlocked(numBlocked) {
  393. collapseAll = document.getElementById('collapseall');
  394. showAllBlocked = document.createElement("span");
  395. showAllBlocked.innerHTML = '&nbsp;&nbsp;<font color="#9ab8ef">|</font>&nbsp;&nbsp;<a href="javascript:unhideAllHITs();" class="footer_links" id="showblocked">Show ' + numBlocked + ' Blocked</a>';
  396. collapseAll.parentNode.insertBefore(showAllBlocked, collapseAll.nextSibling);
  397. }
  398.  
  399.  
  400. unsafeWindow.blockRequester = function (rId,i) {
  401. rName = theseRequesters.snapshotItem(i).innerHTML;
  402. rEntry = rId+"::"+rName;
  403. requesterIndex+= rEntry+"}{";
  404. if (confirm("Hide HITs from "+rName+" ("+rId+")?")) {
  405. window.setTimeout(function() {
  406. GM_setValue("requesterIndex", requesterIndex);
  407. GM_setValue("requesterUpdated", "Blocked,"+rEntry);
  408. }, 0);
  409. //window.setTimeout(GM_setValue, 0, "requesterIndex", requesterIndex);
  410. //window.setTimeout(GM_setValue, 0, "requesterUpdated", "Blocked,"+rEntry);
  411. document.location.reload();
  412. }
  413. }
  414.  
  415. unsafeWindow.unblockRequester = function (rId,rName) {
  416. theseRequesters = document.evaluate("//a[starts-with(@href,'/mturk/searchbar?selectedSearchType=hitgroups&requesterId=')]",document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);
  417. rEntry = rId+"::"+rName;
  418. half = requesterIndex.split(rId+"::");
  419. left = half[0];
  420. temp = half[1].split('}{');
  421. right = temp[1]+"}{";
  422. if (temp.length>1) {
  423. for (i=2;i<temp.length-1;i++) {
  424. right+=temp[i]+"}{";
  425. }
  426. }
  427. requesterIndex = left + right;
  428. window.setTimeout(function() {
  429. GM_setValue("requesterIndex", requesterIndex);
  430. GM_setValue("requesterUpdated", "Unblocked,"+rEntry);
  431. }, 0);
  432. //window.setTimeout(GM_setValue, 0, "requesterIndex", requesterIndex);
  433. //window.setTimeout(GM_setValue, 0, "requesterUpdated", "Unblocked,"+rEntry);
  434. document.location.reload();
  435. }
  436.  
  437. function addGlobalStyle(css) {
  438. head = document.getElementsByTagName('head')[0];
  439. if (!head) { return; }
  440. style = document.createElement('style');
  441. style.type = 'text/css';
  442. style.innerHTML = css;
  443. head.appendChild(style);
  444. }
  445.  
  446. addGlobalStyle('.blocked { display: none; }');
  447. showUpdates();
  448. showNumBlocked(hideMatchingHITs());