Advertisement
Guest User

HIT Database FireFox

a guest
May 8th, 2014
263
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 115.26 KB | None | 0 0
  1. // ==UserScript==
  2. // @name MTurk HIT DataBase Testing
  3. // @namespace localhost
  4. // @description Extended ability to search HITs you have worked on and other useful //tools (CSV export/import, requester notes, requester block, //pending/projectedearnings)
  5. // @include https://www.mturk.com/mturk/searchbar*
  6. // @include https://www.mturk.com/mturk/findhits*
  7. // @include https://www.mturk.com/mturk/viewhits*
  8. // @include https://www.mturk.com/mturk/viewsearchbar*
  9. // @include https://www.mturk.com/mturk/sortsearchbar*
  10. // @include https://www.mturk.com/mturk/sorthits*
  11. // @include https://www.mturk.com/mturk/dashboard
  12. // @include https://www.mturk.com/mturk/preview?*
  13. // @version 1.5.6
  14. // @grant none
  15. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js
  16. // @require http://code.highcharts.com/highcharts.js
  17. // @downloadURL https://userscripts.org/scripts/source/149548.user.js
  18. // @updateURL https://userscripts.org/scripts/source/149548.user.js
  19. // ==/UserScript==
  20.  
  21. //
  22. // 2012-10-03 0.9.7: This is rewrite of MTurk Extended HIT Search (http://userscripts.org/scripts/show/146277)
  23. // with some extra features (and some missing for now: search by date).
  24. // It now uses IndexedDB (http://en.wikipedia.org/wiki/Indexed_Database_API)
  25. //
  26. // 2012-10-04 0.9.8: Improved use of indexes, check Pending Payment HITs
  27. // 0.9.9: Minor improvements
  28. //
  29. // 2012-10-04 0.10: Added date options
  30. //
  31. // 2012-10-07 0.11: Requester notes, bug fixes
  32. // 0.12: CSV export
  33. //
  34. // 2012-10-09 0.13: "Block" requesters or specific HITs
  35. //
  36. // 2012-10-10 0.14: Requester Overview, shows summary of all requesters in DB
  37. //
  38. // 2012-10-11 0.15: Blocked HITs are always on bottom of the page
  39. //
  40. // 2012-10-14 0.16: Requester Overview improvements
  41. //
  42. // 2012-10-17 0.17: Bug fixes and error checks
  43. //
  44. // 2012-10-18 0.18: Import HIT data from MTurk Extended HIT Search script
  45. //
  46. // 2012-10-21 0.19: Moved main interface to dashboard, show pending earnings on dashboard,
  47. // summary of all requesters with pending HITs.
  48. //
  49. // 2012-10-23 0.20: Added Turkopticon (https://turkopticon.differenceengines.com/) links to overview pages
  50. // 0.21: Fixed overview pages reward to include only 'Paid' and 'Approved - Pending Payment' HITs.
  51. //
  52. // 2012-10-28 0.22: Limited Auto Update.
  53. // 0.23: Minor improvements
  54. //
  55. // 2012-10-30 0.24: Projected earnings for today
  56. //
  57. // 2012-11-02 0.25: Smarter Auto Update
  58. //
  59. // 2012-11-03 0.26: GUI update
  60. //
  61. // 2012-11-05 0.30: Extra non-amazonian script monkeys
  62. //
  63. // 2012-11-06 0.31: Projected earnings progress bar
  64. //
  65. // 2012-11-08 0.32: Minor GUI fixes to look better on Chrome. Looks like it now works on stable Chrome!
  66. //
  67. // 2012-11-13 0.33: Time limits now work with Requester Overview
  68. //
  69. // 2012-11-15 0.34: Bug/compatibility fixes
  70. //
  71. // 2012-11-18 0.40: Daily Overview, update database to use YYYY-MM-DD date format.
  72. //
  73. // 2012-11-22 0.41: R and T button on HIT preview page. Auto-Approval time.
  74. //
  75. // 2012-11-30 0.42: Changes on MTurk pages. Status page in now on one page!
  76. //
  77. // 2012-12-02 1.0: Added @downloadURL and @updateURL
  78. //
  79. // 2012-12-06 1.1: Requester details.
  80. // Try to fetch few extra days at first update (not showing on status page).
  81. //
  82. // 2012-12-11 1.2: Import HITs from previously exported CSV-files.
  83. // Removed Extended HIT Search import.
  84. //
  85. // 2012-12-13 1.3: Fix CSV-import to put empty string instead if undefined if feedback is empty.
  86. //
  87. // 2012-12-14 1.4: Rewritten database update more properly.
  88. //
  89. // 2012-12-16 1.5: Fixed broken Auto Update (forgot to check that on pervious update).
  90. //
  91. // 2013-08-20 1.5.5:Firefox 23 Compatibility Issues. Removed New Windows and replaced with a Faux Frame.
  92. // ReplacedTurkopticon Links with https versions
  93. //
  94. // 2013-11-06 1.5.6:Firefox 25 Compatibility Issues. Database transaction modes weren't working with defined variables.
  95.  
  96. FauxFrameobj = document.createElement('div');
  97. FauxFrameobj.style.display = 'none';
  98. FauxFrameobj.style.position = 'fixed';
  99. FauxFrameobj.style.top = '10%';
  100. FauxFrameobj.style.left = '10%';
  101. FauxFrameobj.style.height = '80%';
  102. FauxFrameobj.style.width = '80%';
  103. FauxFrameobj.style.overflow = 'scroll';
  104. FauxFrameobj.style.padding = '10px';
  105. FauxFrameobj.style.backgroundColor = '#7fb4cf';
  106. FauxFrameobj.name = "FauxFrame";
  107. FauxFrameobj.ID = "FauxFrame";
  108. FauxFrameobj.innerHTML = "";
  109. body = document.getElementsByTagName('body')[0];
  110. body.appendChild(FauxFrameobj);
  111.  
  112. var DAYS_TO_FETCH = [];
  113. var DAYS_TO_FETCH_CHECK;
  114.  
  115. var HITStorage = {};
  116. var indexedDB = window.indexedDB || window.webkitIndexedDB ||
  117. window.mozIndexedDB;
  118. window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.mozIDBTransaction;
  119. window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.mozIDBKeyRange;
  120.  
  121. var IDBKeyRange = window.IDBKeyRange;
  122.  
  123. HITStorage.indexedDB = {};
  124. HITStorage.indexedDB = {};
  125. HITStorage.indexedDB.db = null;
  126.  
  127. HITStorage.indexedDB.onerror = function(e) {
  128. console.log(e);
  129. };
  130. var v = 4;
  131.  
  132. HITStorage.indexedDB.create = function() {
  133.  
  134. var request = indexedDB.open("HITDB", v);
  135.  
  136. request.onupgradeneeded = function (e) {
  137. HITStorage.indexedDB.db = e.target.result;
  138. var db = HITStorage.indexedDB.db;
  139. var new_empty_db = false;
  140.  
  141. if(!db.objectStoreNames.contains("HIT")) {
  142. var store = db.createObjectStore("HIT", { keyPath: "hitId" });
  143.  
  144. store.createIndex("date", "date", { unique: false });
  145. store.createIndex("requesterName", "requesterName", { unique: false });
  146. store.createIndex("title", "title", { unique: false });
  147. store.createIndex("reward", "reward", { unique: false });
  148. store.createIndex("status", "status", { unique: false });
  149. store.createIndex("requesterId", "requesterId", { unique: false });
  150.  
  151. new_empty_db = true;
  152.  
  153. // At first update try to get few extra days that do not show on status page
  154. localStorage['HITDB TRY_EXTRA_DAYS'] = 'YES';
  155. }
  156. if(!db.objectStoreNames.contains("STATS")) {
  157. var store = db.createObjectStore("STATS", { keyPath: "date" });
  158. }
  159. if(!db.objectStoreNames.contains("NOTES")) {
  160. var store = db.createObjectStore("NOTES", { keyPath: "requesterId" });
  161. }
  162. if(!db.objectStoreNames.contains("BLOCKS")) {
  163. var store = db.createObjectStore("BLOCKS", { keyPath: "id", autoIncrement: true });
  164.  
  165. store.createIndex("requesterId", "requesterId", { unique: false });
  166. }
  167.  
  168. if (new_empty_db == false)
  169. {
  170. alert("HIT DataBase date format must be upgraded (MMDDYYYY => YYYY-MM-DD)\n" +
  171. "Please don't close or reload this page until it's done.\n" +
  172. "Press OK to start. This shouldn't take long. (few minutes max)" +
  173. "Sorry for the inconvenience.");
  174. HITStorage.update_date_format(true);
  175. }
  176. db.close();
  177. //alert("DataBase upgraded to version " + v + '!');
  178. }
  179.  
  180. request.onsuccess = function(e) {
  181. HITStorage.indexedDB.db = e.target.result;
  182. var db = HITStorage.indexedDB.db;
  183. db.close();
  184. };
  185.  
  186. request.onerror = HITStorage.indexedDB.onerror;
  187. }
  188.  
  189. HITStorage.indexedDB.addHIT = function(hitData) {
  190. // Temporary extra check
  191. if (hitData.date.indexOf('-') < 0)
  192. {
  193. alert('Wrong date format in addHIT()!');
  194. return;
  195. }
  196.  
  197. var request = indexedDB.open("HITDB", v);
  198. request.onsuccess = function(e) {
  199. HITStorage.indexedDB.db = e.target.result;
  200. var db = HITStorage.indexedDB.db;
  201. var trans = db.transaction(["HIT"], "readwrite");
  202. var store = trans.objectStore("HIT");
  203.  
  204. var request = store.put(hitData);
  205.  
  206. request.onsuccess = function(e) {
  207. db.close();
  208. };
  209.  
  210. request.onerror = function(e) {
  211. console.log("Error Adding: ", e);
  212. };
  213. };
  214. request.onerror = HITStorage.indexedDB.onerror;
  215. };
  216.  
  217. HITStorage.indexedDB.importHITs = function(hitData) {
  218. var hits = hitData.length;
  219. var label = document.getElementById('status_label');
  220.  
  221. var request = indexedDB.open("HITDB", v);
  222. request.onsuccess = function(e) {
  223. HITStorage.indexedDB.db = e.target.result;
  224. var db = HITStorage.indexedDB.db;
  225. var trans = db.transaction(["HIT"], "readwrite");
  226. var store = trans.objectStore("HIT");
  227.  
  228. putNextHIT();
  229.  
  230. function putNextHIT()
  231. {
  232. if (hitData.length > 0)
  233. {
  234. store.put(hitData.pop()).onsuccess = putNextHIT;
  235. label.innerHTML = progress_bar(((hits-hitData.length)/hits*50), 50, '¦', '¦', '#7fb448', 'grey') + ' (' + hitData.length + ')';
  236. }
  237. else
  238. {
  239. HITStorage.enable_inputs();
  240. HITStorage.update_status_label('Import done', 'green');
  241. db.close();
  242. }
  243. }
  244. };
  245. request.onerror = HITStorage.indexedDB.onerror;
  246. };
  247.  
  248. HITStorage.indexedDB.addHITs = function(hitData, day_to_fetch, days_to_update) {
  249. var hits = hitData.length;
  250. if (day_to_fetch)
  251. var label = document.getElementById('status_label');
  252.  
  253. var request = indexedDB.open("HITDB", v);
  254. request.onsuccess = function(e) {
  255. HITStorage.indexedDB.db = e.target.result;
  256. var db = HITStorage.indexedDB.db;
  257. var trans = db.transaction(["HIT"], "readwrite");
  258. var store = trans.objectStore("HIT");
  259.  
  260. putNextHIT();
  261.  
  262. function putNextHIT()
  263. {
  264. if (hitData.length > 0)
  265. {
  266. store.put(hitData.pop()).onsuccess = putNextHIT;
  267. if (day_to_fetch)
  268. label.innerHTML = 'Saving ' + day_to_fetch.date + ': ' + progress_bar(((hits-hitData.length)/hits*40), 40, '¦', '¦', '#7fb448', 'grey');
  269. }
  270. else
  271. {
  272. // move to next day
  273. if (day_to_fetch)
  274. {
  275. HITStorage.indexedDB.updateHITstats(day_to_fetch);
  276. setTimeout(function() { HITStorage.do_update(days_to_update); }, 2000);
  277. HITStorage.update_status_label('Please wait: script monkeys are taking naps ??', 'red');
  278. }
  279. db.close();
  280. }
  281. }
  282. };
  283. request.onerror = HITStorage.indexedDB.onerror;
  284. };
  285.  
  286.  
  287. HITStorage.indexedDB.updateHITstats = function(date)
  288. {
  289. // Temporary extra check
  290. if (date.date.indexOf('-') < 0)
  291. {
  292. alert('Wrong date format in updateHITstats()!');
  293. return;
  294. }
  295.  
  296. var request = indexedDB.open("HITDB", v);
  297. request.onsuccess = function(e) {
  298. HITStorage.indexedDB.db = e.target.result;
  299. var db = HITStorage.indexedDB.db;
  300. var trans = db.transaction(["STATS"], "readwrite");
  301. var store = trans.objectStore("STATS");
  302.  
  303. var request = store.put(date);
  304.  
  305. request.onsuccess = function(e) {
  306. db.close();
  307. };
  308.  
  309. request.onerror = function(e) {
  310. console.log("Error Adding: ", e);
  311. };
  312. };
  313. request.onerror = HITStorage.indexedDB.onerror;
  314. };
  315.  
  316. HITStorage.prepare_update_and_check_pending_payments = function()
  317. {
  318. var request = indexedDB.open("HITDB", v);
  319. request.onsuccess = function(e) {
  320. HITStorage.indexedDB.db = e.target.result;
  321. var db = HITStorage.indexedDB.db;
  322. var trans = db.transaction(["HIT"], "readonly");
  323. var store = trans.objectStore("HIT");
  324. var index = store.index('status');
  325. var range = IDBKeyRange.only('Approved&nbsp;- Pending&nbsp;Payment');
  326.  
  327. index.openCursor(range).onsuccess = function(event) {
  328. var cursor = event.target.result;
  329. if (cursor && DAYS_TO_FETCH.length > 0)
  330. {
  331. for (var i=0; i<DAYS_TO_FETCH.length; i++)
  332. {
  333. if ( cursor.value.date == DAYS_TO_FETCH[i].date )
  334. {
  335. DAYS_TO_FETCH[i].pending_payments = true;
  336. }
  337. }
  338. cursor.continue();
  339. }
  340. else
  341. {
  342. if (DAYS_TO_FETCH.length>0) {
  343. db.close();
  344. HITStorage.update_status_label('Please wait: script monkeys are planning to fetch relevant status pages', 'red');
  345. setTimeout(function() { HITStorage.prepare_update(); }, 100);
  346. }
  347. else
  348. {
  349. db.close();
  350. HITStorage.update_done();
  351. }
  352. }
  353. };
  354. }
  355. };
  356.  
  357. // check that number of hits in DB matches what is available
  358. HITStorage.check_update = function()
  359. {
  360. var request = indexedDB.open("HITDB", v);
  361. request.onsuccess = function(e) {
  362. HITStorage.update_status_label('Please wait: checking database', 'red');
  363. HITStorage.indexedDB.db = e.target.result;
  364. var db = HITStorage.indexedDB.db;
  365. var trans = db.transaction(["HIT"], "readonly");
  366. var store = trans.objectStore("HIT");
  367. var index = store.index('date');
  368. var range = IDBKeyRange.bound(DAYS_TO_FETCH_CHECK[DAYS_TO_FETCH_CHECK.length-1].date, DAYS_TO_FETCH_CHECK[0].date, false, false);
  369.  
  370. index.count(range).onsuccess = function(event) {
  371. var count = event.target.result;
  372. var submitted_hits = 0;
  373.  
  374. for (var i=0; i<DAYS_TO_FETCH_CHECK.length; i++)
  375. {
  376. submitted_hits += DAYS_TO_FETCH_CHECK[i].submitted;
  377. }
  378.  
  379. if (submitted_hits == count)
  380. {
  381. db.close();
  382. HITStorage.update_done();
  383. }
  384. else
  385. {
  386. if (confirm("?? ERROR! Number of HITs in DataBase does not match number of HITs available! (" + count + " != " + submitted_hits + ")\n"
  387. + "Would you like to refetch all status pages now?"))
  388. {
  389. db.close();
  390. DAYS_TO_FETCH = DAYS_TO_FETCH_CHECK.slice(0);
  391. HITStorage.update_status_label('Please wait: new script monkeys are fetching relevant status pages', 'red');
  392. setTimeout(function() { HITStorage.do_update(DAYS_TO_FETCH.length); }, 100);
  393. }
  394. else
  395. {
  396. db.close();
  397. HITStorage.update_done();
  398. }
  399. }
  400. };
  401. }
  402. };
  403.  
  404. HITStorage.prepare_update = function()
  405. {
  406. var request = indexedDB.open("HITDB", v);
  407. request.onsuccess = function(e) {
  408. HITStorage.indexedDB.db = e.target.result;
  409. var db = HITStorage.indexedDB.db;
  410. var trans = db.transaction(["STATS"], "readonly");
  411. var store = trans.objectStore("STATS");
  412. var range = IDBKeyRange.bound(DAYS_TO_FETCH[DAYS_TO_FETCH.length-1].date, DAYS_TO_FETCH[0].date, false, false);
  413.  
  414. store.openCursor(range).onsuccess = function(event) {
  415. var cursor = event.target.result;
  416. if (cursor && DAYS_TO_FETCH.length > 0)
  417. {
  418. for (var i=0; i<DAYS_TO_FETCH.length; i++)
  419. {
  420. if ( cursor.value.date == DAYS_TO_FETCH[i].date
  421. && cursor.value.submitted == DAYS_TO_FETCH[i].submitted
  422. && cursor.value.approved == DAYS_TO_FETCH[i].approved
  423. && cursor.value.rejected == DAYS_TO_FETCH[i].rejected
  424. && cursor.value.pending == DAYS_TO_FETCH[i].pending)
  425. {
  426. // This day is already in DB and stats match => no need to fetch
  427. // unless there are 'Approved - Pending Payment' HITs
  428. if (DAYS_TO_FETCH[i].pending_payments === undefined || DAYS_TO_FETCH[i].pending_payments == false)
  429. DAYS_TO_FETCH.splice(i,1);
  430. }
  431. }
  432. cursor.continue();
  433. }
  434. else
  435. {
  436. if (DAYS_TO_FETCH.length>0) {
  437. db.close();
  438. setTimeout(function() { HITStorage.do_update(DAYS_TO_FETCH.length); }, 100);
  439. }
  440. else
  441. {
  442. db.close();
  443. HITStorage.update_done();
  444. }
  445. }
  446. };
  447. }
  448. };
  449.  
  450. HITStorage.indexedDB.term_matches_HIT = function(term, hit)
  451. {
  452. var keys = ['date', 'requesterName', 'title', 'feedback', 'hitId', 'requesterId'];
  453. for (var k in keys)
  454. {
  455. if (hit[keys[k]] != null && hit[keys[k]].match(term))
  456. {
  457. return true;
  458. }
  459. }
  460. return false;
  461. }
  462.  
  463. HITStorage.indexedDB.matchHIT = function(hit, options)
  464. {
  465. if (options.status == '---' || hit.status.match(options.status))
  466. {
  467. if (options.search_term == '' || HITStorage.indexedDB.term_matches_HIT(options.term, hit))
  468. {
  469. return true;
  470. }
  471. }
  472. return false;
  473. }
  474.  
  475. function hit_sort_func()
  476. {
  477. return function(a,b) {
  478. if (a.date == b.date) {
  479. if (a.requesterName < b.requesterName)
  480. return -1;
  481. if (a.requesterName > b.requesterName)
  482. return 1;
  483. if (a.title < b.title)
  484. return -1;
  485. if (a.title > b.title)
  486. return 1;
  487. if (a.status < b.status)
  488. return -1;
  489. if (a.status > b.status)
  490. return 1;
  491. }
  492. if (a.date > b.date)
  493. return 1;
  494. if (a.date < b.date)
  495. return -1;
  496. };
  497. }
  498.  
  499. HITStorage.indexedDB.getHITs = function(options) {
  500. var request = indexedDB.open("HITDB", v);
  501. request.onsuccess = function(e) {
  502. HITStorage.indexedDB.db = e.target.result;
  503. var db = HITStorage.indexedDB.db;
  504. var trans = db.transaction(["HIT"], "readonly");
  505. var store = trans.objectStore("HIT");
  506.  
  507. var req;
  508. var results = [];
  509. var index;
  510. var range;
  511.  
  512. if (options.from_date || options.to_date)
  513. {
  514. if (options.from_date != '' || options.to_date != '')
  515. {
  516. index = store.index('date');
  517. if (options.from_date == options.to_date)
  518. {
  519. range = IDBKeyRange.only(options.from_date);
  520. }
  521. else if (options.from_date != '' && options.to_date != '')
  522. {
  523. range = IDBKeyRange.bound(options.from_date, options.to_date, false, false);
  524. }
  525. else if (options.from_date == '' && options.to_date != '')
  526. {
  527. range = IDBKeyRange.upperBound(options.to_date, false);
  528. }
  529. else
  530. {
  531. range = IDBKeyRange.lowerBound(options.from_date, false);
  532. }
  533. req = index.openCursor(range);
  534. }
  535. }
  536. else if (options.index && options.index != '')
  537. {
  538. index = store.index(options.index);
  539. range = IDBKeyRange.only(options.term);
  540. req = index.openCursor(range);
  541. }
  542. else if (options.status == 'Rejected' || options.status == 'Pending Approval'
  543. || options.status == 'Approved' || options.status == 'Paid')
  544. {
  545. var s = (options.status == 'Approved')? 'Approved&nbsp;- Pending&nbsp;Payment' : options.status;
  546. options.index = 'status';
  547. index = store.index(options.index);
  548. range = IDBKeyRange.only(s);
  549. req = index.openCursor(range);
  550. }
  551. else
  552. {
  553. req = store.openCursor();
  554. }
  555.  
  556. req.onsuccess = function(event) {
  557. var cursor = event.target.result;
  558. if (cursor) {
  559. if (HITStorage.indexedDB.matchHIT(cursor.value, options))
  560. results.push(cursor.value);
  561.  
  562. cursor.continue();
  563. }
  564. else {
  565. results.sort(hit_sort_func());
  566.  
  567. if (options.export_csv && options.export_csv == true)
  568. HITStorage.export_csv(results);
  569. else
  570. HITStorage.show_results(results);
  571.  
  572. if (options.donut == '---')
  573. document.getElementById('container').style.display = 'none';
  574. else if (options.donut != '')
  575. HITStorage.prepare_donut(results, options.donut);
  576. }
  577. db.close();
  578. };
  579. };
  580. request.onerror = HITStorage.indexedDB.onerror;
  581. };
  582.  
  583. //
  584. // Show summary of all requesters
  585. //
  586. HITStorage.indexedDB.requesterOverview = function(options) {
  587.  
  588.  
  589.  
  590. var request = indexedDB.open("HITDB", v);
  591. request.onsuccess = function(e) {
  592.  
  593. HITStorage.indexedDB.db = e.target.result;
  594. var db = HITStorage.indexedDB.db;
  595.  
  596. var trans = db.transaction(["HIT"], "readonly");
  597.  
  598. var store = trans.objectStore("HIT");
  599. var index;
  600. var req;
  601.  
  602.  
  603. // [ requesterId, requesterName, sum(hits), sum(rewards), rejected, pending ]
  604. var results = [];
  605. var tmp_results = {};
  606. if (options.from_date || options.to_date)
  607. {
  608. if (options.from_date != '' || options.to_date != '')
  609. {
  610. index = store.index('date');
  611. if (options.from_date == options.to_date)
  612. {
  613. range = IDBKeyRange.only(options.from_date);
  614. }
  615. else if (options.from_date != '' && options.to_date != '')
  616. {
  617. range = IDBKeyRange.bound(options.from_date, options.to_date, false, false);
  618. }
  619. else if (options.from_date == '' && options.to_date != '')
  620. {
  621. range = IDBKeyRange.upperBound(options.to_date, false);
  622. }
  623. else
  624. {
  625. range = IDBKeyRange.lowerBound(options.from_date, false);
  626. }
  627. req = index.openCursor(range);
  628. }
  629. req.onsuccess = function(event) {
  630. HITStorage.update_status_label('req.onsuccess', 'red');
  631. var cursor = event.target.result;
  632. if (cursor) {
  633. var hit = cursor.value;
  634. var rejected = (hit.status == 'Rejected') ? 1 : 0;
  635. var pending = (hit.status.match(/Approved|Paid|Rejected/) == null) ? 1 : 0;
  636. var reward = (pending>0 || rejected>0 )? 0: hit.reward;
  637.  
  638. if (tmp_results[hit.requesterId] === undefined)
  639. {
  640. tmp_results[hit.requesterId] = [];
  641. tmp_results[hit.requesterId][0] = hit.requesterId;
  642. tmp_results[hit.requesterId][1] = hit.requesterName;
  643. tmp_results[hit.requesterId][2] = 1;
  644. tmp_results[hit.requesterId][3] = reward;
  645. tmp_results[hit.requesterId][4] = rejected;
  646. tmp_results[hit.requesterId][5] = pending;
  647. }
  648. else
  649. {
  650. tmp_results[hit.requesterId][1] = hit.requesterName;
  651. tmp_results[hit.requesterId][2] += 1;
  652. tmp_results[hit.requesterId][3] += reward;
  653. tmp_results[hit.requesterId][4] += rejected;
  654. tmp_results[hit.requesterId][5] += pending;
  655. }
  656. cursor.continue();
  657. }
  658. else {
  659. for (var key in tmp_results) {
  660. results.push(tmp_results[key]);
  661. }
  662. // sort by total reward
  663. results.sort(function(a,b) { return b[3]-a[3]; });
  664. if (options.export_csv == true)
  665. HITStorage.show_requester_overview_csv(results);
  666. else
  667. HITStorage.show_requester_overview(results, '(' + options.from_date + '–' + options.to_date + ')');
  668. HITStorage.update_status_label('Script monkeys are ready', 'green');
  669. setTimeout( function() { HITStorage.update_status_label("Search powered by non-amazonian script monkeys"); }, 3000);
  670. HITStorage.enable_inputs();
  671. }
  672. db.close();
  673. };
  674. }
  675. else {
  676. index = store.index('requesterId');
  677. req = index.openCursor();
  678. req.onsuccess = function(event) {
  679. var cursor = event.target.result;
  680. if (cursor) {
  681. var hit = cursor.value;
  682. var rejected = (hit.status == 'Rejected') ? 1 : 0;
  683. var pending = (hit.status.match(/Approved|Paid|Rejected/) == null) ? 1 : 0;
  684. var reward = (pending>0 || rejected>0 )? 0: hit.reward;
  685. if (results.length == 0)
  686. {
  687. results.push([hit.requesterId, hit.requesterName, 1, reward, rejected, pending]);
  688. }
  689. else if (results[0][0] == hit.requesterId)
  690. {
  691. results[0][2] += 1;
  692. results[0][3] += reward;
  693. results[0][4] += rejected;
  694. results[0][5] += pending;
  695. }
  696. else
  697. {
  698. results.unshift([hit.requesterId, hit.requesterName, 1, reward, rejected, pending]);
  699. }
  700. cursor.continue();
  701. }
  702. else {
  703. // sort by total reward
  704. results.sort(function(a,b) { return b[3]-a[3]; });
  705. if (options.export_csv == true)
  706. HITStorage.show_requester_overview_csv(results);
  707. else
  708. HITStorage.show_requester_overview(results);
  709. HITStorage.update_status_label('Script monkeys are ready', 'green');
  710. setTimeout( function() { HITStorage.update_status_label("Search powered by non-amazonian script monkeys"); }, 3000);
  711. HITStorage.enable_inputs();
  712. }
  713. db.close();
  714. };
  715. }
  716. };
  717. request.onerror = HITStorage.indexedDB.onerror;
  718. };
  719.  
  720. //
  721. // Show summary of one requester
  722. //
  723. HITStorage.indexedDB.showRequester = function(requesterId) {
  724. var request = indexedDB.open("HITDB", v);
  725. request.onsuccess = function(e) {
  726. HITStorage.indexedDB.db = e.target.result;
  727. var db = HITStorage.indexedDB.db;
  728. var trans = db.transaction(["HIT"], "readonly");
  729. var store = trans.objectStore("HIT");
  730. var index;
  731. var results = [];
  732.  
  733. index = store.index('requesterId');
  734. var range = IDBKeyRange.only(requesterId);
  735. index.openCursor(range).onsuccess = function(event) {
  736. var cursor = event.target.result;
  737. if (cursor) {
  738. results.push(cursor.value);
  739. cursor.continue();
  740. }
  741. else {
  742. results.sort(function(a,b)
  743. {
  744. if (a.date > b.date)
  745. return -1;
  746. if (a.date < b.date)
  747. return 1;
  748. return 0;
  749. });
  750. HITStorage.show_requester(results);
  751. HITStorage.update_status_label('Script monkeys are ready', 'green');
  752. setTimeout( function() { HITStorage.update_status_label("Search powered by non-amazonian script monkeys"); }, 3000);
  753. HITStorage.enable_inputs();
  754. }
  755. db.close();
  756. };
  757. };
  758. request.onerror = HITStorage.indexedDB.onerror;
  759. };
  760.  
  761.  
  762. // Show summary of pending HITs
  763. HITStorage.indexedDB.pendingOverview = function(options) {
  764. var request = indexedDB.open("HITDB", v);
  765. request.onsuccess = function(e) {
  766. HITStorage.indexedDB.db = e.target.result;
  767. var db = HITStorage.indexedDB.db;
  768. var trans = db.transaction(["HIT"], "readonly");
  769. var store = trans.objectStore("HIT");
  770. var index;
  771. var req;
  772.  
  773. // [ requesterId, requesterName, sum(pendings), sum(rewards) ]
  774. var results = [];
  775. var tmp_results = {};
  776.  
  777. index = store.index('status');
  778. range = IDBKeyRange.only('Pending Approval');
  779. index.openCursor(range).onsuccess = function(event) {
  780. var cursor = event.target.result;
  781. if (cursor) {
  782. var hit = cursor.value;
  783. if (tmp_results[hit.requesterId] === undefined)
  784. {
  785. tmp_results[hit.requesterId] = [];
  786. tmp_results[hit.requesterId][0] = hit.requesterId;
  787. tmp_results[hit.requesterId][1] = hit.requesterName;
  788. tmp_results[hit.requesterId][2] = 1;
  789. tmp_results[hit.requesterId][3] = hit.reward;
  790. }
  791. else
  792. {
  793. tmp_results[hit.requesterId][1] = hit.requesterName;
  794. tmp_results[hit.requesterId][2] += 1;
  795. tmp_results[hit.requesterId][3] += hit.reward;
  796. }
  797. cursor.continue();
  798. }
  799. else {
  800. for (var key in tmp_results) {
  801. results.push(tmp_results[key]);
  802. }
  803. // sort by pending hits
  804. results.sort(function(a,b) { return b[2]-a[2]; });
  805. if (options.export_csv == true)
  806. HITStorage.show_pending_overview_csv(results);
  807. else
  808. HITStorage.show_pending_overview(results);
  809. HITStorage.update_status_label('Script monkeys are ready', 'green');
  810. setTimeout( function() { HITStorage.update_status_label("Search powered by non-amazonian script monkeys"); }, 3000);
  811. HITStorage.enable_inputs();
  812. }
  813. db.close();
  814. };
  815. };
  816. request.onerror = HITStorage.indexedDB.onerror;
  817. };
  818.  
  819. // Show summary of daily stats
  820. HITStorage.indexedDB.statusOverview = function(options) {
  821. var request = indexedDB.open("HITDB", v);
  822. request.onsuccess = function(e) {
  823. HITStorage.indexedDB.db = e.target.result;
  824. var db = HITStorage.indexedDB.db;
  825. var trans = db.transaction(["STATS"], "readonly");
  826. var store = trans.objectStore("STATS");
  827. var req;
  828.  
  829. var results = [];
  830.  
  831. if (options.from_date || options.to_date)
  832. {
  833. if (options.from_date != '' || options.to_date != '')
  834. {
  835. if (options.from_date == options.to_date)
  836. {
  837. range = IDBKeyRange.only(options.from_date);
  838. }
  839. else if (options.from_date != '' && options.to_date != '')
  840. {
  841. range = IDBKeyRange.bound(options.from_date, options.to_date, false, false);
  842. }
  843. else if (options.from_date == '' && options.to_date != '')
  844. {
  845. range = IDBKeyRange.upperBound(options.to_date, false);
  846. }
  847. else
  848. {
  849. range = IDBKeyRange.lowerBound(options.from_date, false);
  850. }
  851. req = store.openCursor(range);
  852. }
  853. }
  854. else
  855. {
  856. req = store.openCursor();
  857. }
  858. req.onsuccess = function(event) {
  859. var cursor = event.target.result;
  860. if (cursor) {
  861. if (cursor.value.submitted > 0)
  862. results.push(cursor.value);
  863. cursor.continue();
  864. }
  865. else {
  866. if (options.export_csv == true)
  867. HITStorage.show_status_overview_csv(results);
  868. else
  869. HITStorage.show_status_overview(results, '(' + options.from_date + '–' + options.to_date + ')');
  870. HITStorage.update_status_label('Script monkeys are ready', 'green');
  871. setTimeout( function() { HITStorage.update_status_label("Search powered by non-amazonian script monkeys"); }, 3000);
  872. HITStorage.enable_inputs();
  873. }
  874. db.close();
  875. };
  876. };
  877. request.onerror = HITStorage.indexedDB.onerror;
  878. };
  879.  
  880. HITStorage.indexedDB.getHIT = function(id) {
  881. var request = indexedDB.open("HITDB", v);
  882. request.onsuccess = function(e) {
  883. HITStorage.indexedDB.db = e.target.result;
  884. var db = HITStorage.indexedDB.db;
  885. var trans = db.transaction(["HIT"], "readonly");
  886. var store = trans.objectStore("HIT");
  887.  
  888. var request = store.get(id);
  889.  
  890. request.onsuccess = function(e) {
  891. db.close();
  892. showDetails(e.target.result.note);
  893. };
  894.  
  895. request.onerror = function(e) {
  896. console.log("Error Getting: ", e);
  897. };
  898. };
  899. request.onerror = HITStorage.indexedDB.onerror;
  900. };
  901.  
  902. HITStorage.indexedDB.addNote = function(id, note) {
  903. var request = indexedDB.open("HITDB", v);
  904. request.onsuccess = function(e) {
  905. HITStorage.indexedDB.db = e.target.result;
  906. var db = HITStorage.indexedDB.db;
  907. var trans = db.transaction(["NOTES"], "readwrite");
  908. var store = trans.objectStore("NOTES");
  909. var request;
  910.  
  911. if (note == '')
  912. request = store.delete(id);
  913. else
  914. request = store.put({requesterId: id, note: note});
  915.  
  916. request.onsuccess = function(e) {
  917. db.close();
  918. };
  919.  
  920. request.onerror = function(e) {
  921. console.log("Error Adding: ", e);
  922. };
  923. };
  924. request.onerror = HITStorage.indexedDB.onerror;
  925. };
  926.  
  927. HITStorage.indexedDB.blockHITS = function(requesterId, title, hitElement, titleElement) {
  928. var request = indexedDB.open("HITDB", v);
  929. request.onsuccess = function(e) {
  930. HITStorage.indexedDB.db = e.target.result;
  931. var db = HITStorage.indexedDB.db;
  932.  
  933. if (!db.objectStoreNames.contains("BLOCKS"))
  934. {
  935. db.close();
  936. return;
  937. }
  938. var trans = db.transaction(["BLOCKS"], "readonly");
  939. var store = trans.objectStore("BLOCKS");
  940. var index = store.index("requesterId");
  941. var range = IDBKeyRange.only(requesterId);
  942.  
  943. index.openCursor(range).onsuccess = function(event) {
  944. var cursor = event.target.result;
  945. if (cursor && cursor.value.re)
  946. {
  947. if (cursor.value.re.test(title))
  948. {
  949. hitElement.style.display = 'none';
  950. titleElement.addEventListener("click", unblock_func(requesterId, title));
  951.  
  952. titleElement.style.fontSize = 'small';
  953.  
  954. // move blocked hits to the bottom
  955. var table = hitElement.parentNode.parentNode.parentNode.parentNode.parentNode;
  956. var hit = hitElement.parentNode.parentNode.parentNode.parentNode;
  957. table.removeChild(hit);
  958. table.appendChild(hit);
  959. }
  960. cursor.continue();
  961. }
  962. else
  963. {
  964. db.close();
  965. }
  966. };
  967. };
  968. request.onerror = HITStorage.indexedDB.onerror;
  969. };
  970.  
  971. HITStorage.indexedDB.addBlock = function(requesterId, re) {
  972. var request = indexedDB.open("HITDB", v);
  973. request.onsuccess = function(e) {
  974. HITStorage.indexedDB.db = e.target.result;
  975. var db = HITStorage.indexedDB.db;
  976. var trans = db.transaction(["BLOCKS"], "readwrite");
  977. var store = trans.objectStore("BLOCKS");
  978. var request;
  979.  
  980. request = store.put({requesterId: requesterId, re: re});
  981.  
  982. request.onsuccess = function(e) {
  983. db.close();
  984. };
  985. };
  986. request.onerror = HITStorage.indexedDB.onerror;
  987. };
  988.  
  989. // Removes all blocks for requesterId, where RE matches this HIT title
  990. HITStorage.indexedDB.removeBlocks = function(requesterId, title) {
  991. var request = indexedDB.open("HITDB", v);
  992. request.onsuccess = function(e) {
  993. HITStorage.indexedDB.db = e.target.result;
  994. var db = HITStorage.indexedDB.db;
  995. if (!db.objectStoreNames.contains("BLOCKS"))
  996. {
  997. db.close();
  998. return;
  999. }
  1000. var trans = db.transaction(["BLOCKS"], "readwrite");
  1001. var store = trans.objectStore("BLOCKS");
  1002. var index = store.index("requesterId");
  1003. var range = IDBKeyRange.only(requesterId);
  1004.  
  1005. index.openCursor(range).onsuccess = function(event)
  1006. {
  1007. var cursor = event.target.result;
  1008. if (cursor)
  1009. {
  1010. if (cursor.value.re.test(title))
  1011. store.delete(cursor.value.id);
  1012. db.close();
  1013. }
  1014. };
  1015. };
  1016. request.onerror = HITStorage.indexedDB.onerror;
  1017. };
  1018.  
  1019. HITStorage.indexedDB.updateNoteButton = function(id, label) {
  1020. var request = indexedDB.open("HITDB", v);
  1021. request.onsuccess = function(e) {
  1022. HITStorage.indexedDB.db = e.target.result;
  1023. var db = HITStorage.indexedDB.db;
  1024.  
  1025. if (!db.objectStoreNames.contains("NOTES"))
  1026. {
  1027. label.title = 'Update HIT database on statusdetail page to use this feature';
  1028. db.close();
  1029. return;
  1030. }
  1031. var trans = db.transaction(["NOTES"], "readonly");
  1032. var store = trans.objectStore("NOTES");
  1033.  
  1034. store.get(id).onsuccess = function(event)
  1035. {
  1036. if (event.target.result === undefined)
  1037. {
  1038. label.textContent = '';
  1039. }
  1040. else
  1041. {
  1042. var note = event.target.result.note;
  1043. label.textContent = note;
  1044. label.style.border = '1px dotted';
  1045. if (note.indexOf('!') >= 0)
  1046. label.style.color = 'red';
  1047. else
  1048. label.style.color = 'black';
  1049. }
  1050. db.close();
  1051. };
  1052. };
  1053. request.onerror = HITStorage.indexedDB.onerror;
  1054. };
  1055.  
  1056.  
  1057. HITStorage.indexedDB.colorRequesterButton = function(id, button) {
  1058. var request = indexedDB.open("HITDB", v);
  1059. request.onsuccess = function(e) {
  1060. HITStorage.indexedDB.db = e.target.result;
  1061. var db = HITStorage.indexedDB.db;
  1062. if (!db.objectStoreNames.contains("HIT"))
  1063. {
  1064. button.title = 'Update HIT database on statusdetail page to use this feature';
  1065. db.close();
  1066. return;
  1067. }
  1068. var trans = db.transaction(["HIT"], "readonly");
  1069. var store = trans.objectStore("HIT");
  1070.  
  1071. var index = store.index("requesterId");
  1072. index.get(id).onsuccess = function(event)
  1073. {
  1074. if (event.target.result === undefined)
  1075. {
  1076. button.style.backgroundColor = 'pink';
  1077. }
  1078. else
  1079. {
  1080. button.style.backgroundColor = 'lightgreen';
  1081. button.style.fontWeight = 'bold';
  1082. }
  1083. db.close();
  1084. };
  1085. };
  1086. request.onerror = HITStorage.indexedDB.onerror;
  1087. };
  1088.  
  1089. HITStorage.indexedDB.colorTitleButton = function(title, button) {
  1090. var request = indexedDB.open("HITDB", v);
  1091. request.onsuccess = function(e) {
  1092. HITStorage.indexedDB.db = e.target.result;
  1093. var db = HITStorage.indexedDB.db;
  1094. if (!db.objectStoreNames.contains("HIT"))
  1095. {
  1096. button.title = 'Update HIT database on statusdetail page to use this feature';
  1097. db.close();
  1098. return;
  1099. }
  1100. var trans = db.transaction(["HIT"], "readonly");
  1101. var store = trans.objectStore("HIT");
  1102.  
  1103. var index = store.index("title");
  1104. index.get(title).onsuccess = function(event)
  1105. {
  1106. if (event.target.result === undefined)
  1107. {
  1108. button.style.backgroundColor = 'pink';
  1109. }
  1110. else
  1111. {
  1112. button.style.backgroundColor = 'lightgreen';
  1113. button.style.fontWeight = 'bold';
  1114. }
  1115.  
  1116. db.close();
  1117. };
  1118. };
  1119. request.onerror = HITStorage.indexedDB.onerror;
  1120. };
  1121.  
  1122. HITStorage.indexedDB.deleteDB = function () {
  1123. var deleteRequest = indexedDB.deleteDatabase("HITDB");
  1124. deleteRequest.onsuccess = function (e)
  1125. {
  1126. alert("deleted");
  1127. }
  1128. deleteRequest.onblocked = function (e)
  1129. {
  1130. alert("blocked");
  1131. }
  1132. deleteRequest.onerror = HITStorage.indexedDB.onerror;
  1133. }
  1134.  
  1135. HITStorage.indexedDB.get_pending_approvals = function() {
  1136. var element = document.getElementById('pending_earnings_value');
  1137. var header_element = document.getElementById('pending_earnings_header');
  1138. if (element == null)
  1139. return;
  1140.  
  1141. var request = indexedDB.open("HITDB", v);
  1142. request.onsuccess = function(e) {
  1143. HITStorage.indexedDB.db = e.target.result;
  1144. var db = HITStorage.indexedDB.db;
  1145. var trans = db.transaction(["HIT"], "readonly");
  1146. var store = trans.objectStore("HIT");
  1147.  
  1148. var result = 0;
  1149. var index;
  1150. var range;
  1151.  
  1152. index = store.index('status');
  1153. range = IDBKeyRange.only('Pending Approval');
  1154.  
  1155. index.openCursor(range).onsuccess = function(event) {
  1156. var cursor = event.target.result;
  1157. if (cursor) {
  1158. result += cursor.value.reward;
  1159. cursor.continue();
  1160. }
  1161. else {
  1162. element.textContent = '$' + result.toFixed(2);
  1163. if (header_element != null)
  1164. header_element.textContent = 'Pending earnings (HITDB updated: ' + localStorage['HITDB UPDATED']+ ')';
  1165. }
  1166. db.close();
  1167. };
  1168. };
  1169. request.onerror = HITStorage.indexedDB.onerror;
  1170. };
  1171.  
  1172. HITStorage.indexedDB.get_pending_payments = function() {
  1173. var element = document.getElementById('pending_earnings_value');
  1174. if (element == null)
  1175. return;
  1176.  
  1177. var request = indexedDB.open("HITDB", v);
  1178. request.onsuccess = function(e) {
  1179. HITStorage.indexedDB.db = e.target.result;
  1180. var db = HITStorage.indexedDB.db;
  1181. var trans = db.transaction(["HIT"], "readonly");
  1182. var store = trans.objectStore("HIT");
  1183.  
  1184. var result = 0;
  1185. var index;
  1186. var range;
  1187.  
  1188. index = store.index('status');
  1189. range = IDBKeyRange.only('Approved&nbsp;- Pending&nbsp;Payment');
  1190.  
  1191. index.openCursor(range).onsuccess = function(event) {
  1192. var cursor = event.target.result;
  1193. if (cursor) {
  1194. result += cursor.value.reward;
  1195. cursor.continue();
  1196. }
  1197. else {
  1198. element.title = 'Approved - Pending Payment: $' + result.toFixed(2);
  1199. }
  1200. }
  1201. db.close();
  1202. };
  1203. request.onerror = HITStorage.indexedDB.onerror;
  1204. };
  1205.  
  1206. HITStorage.indexedDB.get_todays_projected_earnings = function(date) {
  1207. var element = document.getElementById('projected_earnings_value');
  1208. if (element == null)
  1209. return;
  1210.  
  1211. var request = indexedDB.open("HITDB", v);
  1212. request.onsuccess = function(e) {
  1213. HITStorage.indexedDB.db = e.target.result;
  1214. var db = HITStorage.indexedDB.db;
  1215. var trans = db.transaction(["HIT"], "readonly");
  1216. var store = trans.objectStore("HIT");
  1217.  
  1218. var result = 0;
  1219. var rejected = 0;
  1220. var index;
  1221. var range;
  1222.  
  1223. index = store.index('date');
  1224. range = IDBKeyRange.only(date);
  1225.  
  1226. index.openCursor(range).onsuccess = function(event) {
  1227. var cursor = event.target.result;
  1228. if (cursor) {
  1229. if (cursor.value.status == 'Rejected')
  1230. rejected += cursor.value.reward;
  1231. else
  1232. result += cursor.value.reward;
  1233. cursor.continue();
  1234. }
  1235. else {
  1236. element.textContent = '$' + result.toFixed(2);
  1237. element.title = '$' + rejected.toFixed(2) + ' rejected';
  1238.  
  1239. if (localStorage['TODAYS TARGET'] !== undefined)
  1240. {
  1241. var target = parseFloat(localStorage['TODAYS TARGET']).toFixed(2);
  1242. var my_target = document.getElementById('my_target');
  1243.  
  1244. var progress = Math.floor(result/target*40);
  1245. if (progress > 40)
  1246. progress = 40;
  1247. my_target.innerHTML = progress_bar(progress, 40, '¦', '¦', '#7fb448', 'grey') + '&nbsp;' +
  1248. ((result>target)? '+' : '') + (result-target).toFixed(2);
  1249. my_target.style.fontSize = '9px';
  1250. }
  1251. }
  1252. }
  1253. db.close();
  1254. };
  1255. request.onerror = HITStorage.indexedDB.onerror;
  1256. };
  1257.  
  1258. // Update database date format from MMDDYYYY to YYYY-MM-DD
  1259. // Shouldn't break anything even if used on already updated db
  1260. HITStorage.update_date_format = function(verbose)
  1261. {
  1262. var request = indexedDB.open("HITDB", v);
  1263. request.onsuccess = function(e) {
  1264. HITStorage.indexedDB.db = e.target.result;
  1265. var db = HITStorage.indexedDB.db;
  1266. var trans = db.transaction(["HIT"], "readwrite");
  1267. var store = trans.objectStore("HIT");
  1268.  
  1269. store.openCursor().onsuccess = function(event) {
  1270. var cursor = event.target.result;
  1271. if (cursor)
  1272. {
  1273. if (cursor.value.date.indexOf('-') < 0)
  1274. {
  1275. var i = cursor.value;
  1276. i.date = convert_date(i.date);
  1277. i.requesterName = i.requesterName.trim();
  1278. i.title = i.title.trim();
  1279. cursor.update(i);
  1280. }
  1281. cursor.continue();
  1282. }
  1283. else
  1284. {
  1285. db.close();
  1286. HITStorage.update_stats_date_format(verbose);
  1287. }
  1288. };
  1289. }
  1290. }
  1291.  
  1292. HITStorage.update_stats_date_format = function(verbose)
  1293. {
  1294. var request = indexedDB.open("HITDB", v);
  1295. request.onsuccess = function(e) {
  1296. HITStorage.indexedDB.db = e.target.result;
  1297. var db = HITStorage.indexedDB.db;
  1298. var trans = db.transaction(["STATS"], "readwrite");
  1299. var store = trans.objectStore("STATS");
  1300.  
  1301. store.openCursor().onsuccess = function(event) {
  1302. var cursor = event.target.result;
  1303. if (cursor)
  1304. {
  1305. if (cursor.value.date.indexOf('-') < 0)
  1306. {
  1307. var i = cursor.value;
  1308. i.date = convert_date(i.date);
  1309. cursor.delete();
  1310. store.put(i);
  1311. }
  1312. cursor.continue();
  1313. }
  1314. else
  1315. {
  1316. // DB should be fully updated
  1317. db.close();
  1318. if (verbose == true)
  1319. alert('Date conversion done.');
  1320. }
  1321. };
  1322. }
  1323. };
  1324.  
  1325. /* ------------------------------------------------------------- */
  1326.  
  1327. HITStorage.prepare_donut = function (donutData, type)
  1328. {
  1329. if (type == '---')
  1330. return;
  1331. var countHits = true;
  1332. if (type.match('REWARDS'))
  1333. countHits = false;
  1334.  
  1335. var tmpData = {};
  1336. var topRequesters = [];
  1337. var topHits = [];
  1338. var sum = 0;
  1339.  
  1340. for (var i=0; i < donutData.length; i++) {
  1341. var requesterName = donutData[i].requesterName.trim() + " (" + donutData[i].requesterId + ")";
  1342. var hitTitle = donutData[i].title;
  1343. var hitReward = donutData[i].reward;
  1344. sum += (countHits) ? 1 : hitReward;
  1345.  
  1346. if (tmpData[requesterName]) {
  1347. tmpData[requesterName]['HITS'] += (countHits) ? 1 : hitReward;
  1348. }
  1349. else {
  1350. tmpData[requesterName] = {};
  1351. tmpData[requesterName]['HITS'] = (countHits) ? 1 : hitReward;
  1352. }
  1353. if (tmpData[requesterName][hitTitle])
  1354. tmpData[requesterName][hitTitle] += (countHits) ? 1 : hitReward;
  1355. else
  1356. tmpData[requesterName][hitTitle] = (countHits) ? 1 : hitReward;
  1357.  
  1358. }
  1359.  
  1360. for (var key in tmpData) {
  1361. topRequesters.push({name: key, y: tmpData[key]['HITS']});
  1362. }
  1363. topRequesters.sort(function(a,b){return b.y-a.y});
  1364.  
  1365. var colors = Highcharts.getOptions().colors;
  1366.  
  1367. for (var i=0; i<topRequesters.length; i++) {
  1368. var tmpHits = [];
  1369. topRequesters[i].color = colors[i];
  1370. for (var key2 in tmpData[topRequesters[i].name]) {
  1371. if (key2 != 'HITS') {
  1372. tmpHits.push({name: key2, y: tmpData[topRequesters[i].name][key2], color: colors[i]});
  1373. }
  1374. }
  1375. tmpHits.sort(function(a,b){return b.y-a.y});
  1376. for (var j=0; j<tmpHits.length ; j++) {
  1377. var brightness = 0.2 - (j / tmpHits.length) / 5;
  1378. tmpHits[j].color = Highcharts.Color(colors[i]).brighten(brightness).get();
  1379. }
  1380. topHits = topHits.concat(tmpHits);
  1381. }
  1382.  
  1383. document.getElementById('container').style.display = 'block';
  1384.  
  1385.  
  1386. chart = new Highcharts.Chart({
  1387. chart: {
  1388. renderTo: 'container',
  1389. type: 'pie'
  1390. },
  1391. title: {
  1392. text: 'Requesters and HITs matching your latest search'
  1393. },
  1394. yAxis: {
  1395. title: {
  1396. text: ''
  1397. }
  1398. },
  1399. plotOptions: {
  1400. pie: {
  1401. shadow: false,
  1402. dataLabels: { enabled: true}
  1403. }
  1404. },
  1405. tooltip: {
  1406. animation: false,
  1407. valuePrefix: (countHits)? '' : '$',
  1408. valueSuffix: (countHits)? ' HITs' : '',
  1409. valueDecimals: (countHits)? 0 : 2,
  1410. pointFormat: (countHits)? '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> (of all ' + sum + ' HITs)<br/>' :
  1411. '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> (of all $' + sum.toFixed(2) + ')<br/>'
  1412. },
  1413. series: [{
  1414. name: 'Requesters',
  1415. data: topRequesters,
  1416. size: '60%',
  1417. dataLabels: {
  1418. formatter: function() {
  1419. if (countHits) {
  1420. return this.y/sum >= 0.20 ? this.point.name: null;
  1421. }
  1422. else {
  1423. return this.y/sum >= 0.20 ? this.point.name : null;
  1424. }
  1425. },
  1426. color: 'black',
  1427. distance: -10
  1428. }
  1429. }, {
  1430. name: 'HITs',
  1431. data: topHits,
  1432. innerSize: '60%',
  1433. dataLabels: {
  1434. formatter: function() {
  1435. if (countHits) {
  1436. return this.y/sum > 0.05 ? this.point.name : null;
  1437. }
  1438. else {
  1439. return this.y/sum > 0.05 ? this.point.name : null;
  1440. }
  1441. },
  1442. color: 'black',
  1443. }
  1444. }]
  1445. });
  1446. }
  1447.  
  1448. // Stolen from Today's Projected Earnings (http://userscripts.org/scripts/show/95331)
  1449. HITStorage.getHTTPObject = function()
  1450. {
  1451. if (typeof XMLHttpRequest != 'undefined')
  1452. {
  1453. return new XMLHttpRequest();
  1454. }
  1455. try
  1456. {
  1457. return new ActiveXObject("Msxml2.XMLHTTP");
  1458. }
  1459. catch (e)
  1460. {
  1461. try
  1462. {
  1463. return new ActiveXObject("Microsoft.XMLHTTP");
  1464. }
  1465. catch (e) {}
  1466. }
  1467. return false;
  1468. }
  1469.  
  1470. // Stolen from Today's Projected Earnings (http://userscripts.org/scripts/show/95331)
  1471. // date format MMDDYYYY!
  1472. HITStorage.process_page = function(link, date, hitData)
  1473. {
  1474. var page = HITStorage.getHTTPObject();
  1475. page.open("GET", link, false);
  1476. page.send(null);
  1477. return HITStorage.parse_data(page.responseText, date, hitData);
  1478. }
  1479.  
  1480. // Partly stolen from Today's Projected Earnings (http://userscripts.org/scripts/show/95331)
  1481. // date format MMDDYYYY!
  1482. HITStorage.parse_data = function(page_text, date, hitData)
  1483. {
  1484. var index = 0;
  1485. var index2 = 0;
  1486. var page_html = document.createElement('div');
  1487. page_html.innerHTML = page_text;
  1488.  
  1489. var requesters = page_html.getElementsByClassName('statusdetailRequesterColumnValue');
  1490. var titles = page_html.getElementsByClassName('statusdetailTitleColumnValue');
  1491. var amounts = page_html.getElementsByClassName('statusdetailAmountColumnValue');
  1492. var statuses = page_html.getElementsByClassName('statusdetailStatusColumnValue');
  1493. var feedbacks = page_html.getElementsByClassName('statusdetailRequesterFeedbackColumnValue');
  1494.  
  1495. var requesterName;
  1496. var hitTitle;
  1497. var hitReward;
  1498. var hitStatus;
  1499. var requesterId;
  1500. var hitId;
  1501.  
  1502. for(var k = 0; k < amounts.length; k++)
  1503. {
  1504. requesterName = requesters[k].textContent;
  1505. requesterLink = requesters[k].childNodes[1].href;
  1506. hitTitle = titles[k].textContent;
  1507. index = amounts[k].innerHTML.indexOf('$');
  1508. hitReward = parseFloat(amounts[k].innerHTML.substring(index+1));
  1509. hitStatus = statuses[k].innerHTML;
  1510. hitFeedback = feedbacks[k].textContent;
  1511.  
  1512.  
  1513. index = requesterLink.search("requesterId=");
  1514. requesterId = requesterLink.substring(index+12, requesterLink.lastIndexOf('&'));
  1515. hitId = requesterLink.substring(81, index-1);
  1516.  
  1517. var hit = {
  1518. hitId : hitId,
  1519. date : convert_date(date),
  1520. requesterName : requesterName.trim(),
  1521. requesterLink : requesterLink.trim(),
  1522. title : hitTitle.trim(),
  1523. reward : hitReward,
  1524. status : hitStatus,
  1525. feedback : hitFeedback.trim(),
  1526. requesterId : requesterId
  1527. };
  1528.  
  1529. //HITStorage.indexedDB.addHIT(hitData);
  1530. hitData.push(hit);
  1531. }
  1532.  
  1533. return amounts.length;
  1534. }
  1535.  
  1536. // Returns available days (YYYY-MM-DD)
  1537. HITStorage.getAllAvailableDays = function(try_extra_days)
  1538. {
  1539. var days = [];
  1540.  
  1541. var page = HITStorage.getHTTPObject();
  1542. page.open("GET", 'https://www.mturk.com/mturk/status', false);
  1543. page.send(null);
  1544.  
  1545. var page_html = document.createElement('div');
  1546. page_html.innerHTML = page.responseText;
  1547.  
  1548. var dateElements = page_html.getElementsByClassName('statusDateColumnValue');
  1549. var submittedElements = page_html.getElementsByClassName('statusSubmittedColumnValue');
  1550. var approvedElements = page_html.getElementsByClassName('statusApprovedColumnValue');
  1551. var rejectedElements = page_html.getElementsByClassName('statusRejectedColumnValue');
  1552. var pendingElements = page_html.getElementsByClassName('statusPendingColumnValue');
  1553. var earningsElements = page_html.getElementsByClassName('statusEarningsColumnValue');
  1554.  
  1555. for (var i=0; i<dateElements.length; i++)
  1556. {
  1557. var date = dateElements[i].childNodes[1].href.substr(53);
  1558. date = convert_date(date);
  1559.  
  1560. days.push( { date: date,
  1561. submitted: parseInt(submittedElements[i].textContent),
  1562. approved : parseInt(approvedElements[i].textContent),
  1563. rejected : parseInt(rejectedElements[i].textContent),
  1564. pending : parseInt(pendingElements[i].textContent),
  1565. earnings : parseFloat(earningsElements[i].textContent.slice(1)) });
  1566. }
  1567.  
  1568. if (try_extra_days > 0)
  1569. {
  1570. var date = days[days.length-1].date;
  1571. var d = new Date();
  1572. d.setFullYear(parseInt(date.substr(0,4)), parseInt(date.substr(5,2))-1, parseInt(date.substr(8,2)));
  1573.  
  1574. for (var i=0; i<try_extra_days; i++)
  1575. {
  1576. d.setDate(d.getDate()-1);
  1577. var month = '0' + (d.getMonth() + 1);
  1578. var day = '0' + d.getDate();
  1579. if (month.length > 2)
  1580. month = month.substr(1);
  1581. if (day.length > 2)
  1582. day = day.substr(1);
  1583. date = '' + d.getFullYear() + '-' + month + '-' + day;
  1584.  
  1585. days.push( { date: date,
  1586. submitted: -1,
  1587. approved : -1,
  1588. rejected : -1,
  1589. pending : -1,
  1590. earnings : -1 } );
  1591. }
  1592. }
  1593.  
  1594. return days;
  1595. }
  1596.  
  1597. HITStorage.getLatestHITs = function()
  1598. {
  1599. if (localStorage['HITDB AUTO UPDATE'] === undefined || localStorage['HITDB AUTO UPDATE'] == 'OFF')
  1600. return;
  1601.  
  1602. if (localStorage['HITDB TIMESTAMP'] !== undefined)
  1603. {
  1604. if (new Date().getTime() < new Date(parseInt(localStorage['HITDB TIMESTAMP'])).getTime() + 90000)
  1605. {
  1606. return;
  1607. }
  1608. }
  1609. localStorage['HITDB TIMESTAMP'] = new Date().getTime();
  1610.  
  1611. var auto_button = document.getElementById('auto_button');
  1612. var page = HITStorage.getHTTPObject();
  1613. page.open("GET", 'https://www.mturk.com/mturk/status', false);
  1614. page.send(null);
  1615. auto_button.textContent += ' +';
  1616.  
  1617. var page_html = document.createElement('div');
  1618. page_html.innerHTML = page.responseText;
  1619.  
  1620. var dateElements = page_html.getElementsByClassName('statusDateColumnValue');
  1621. var submittedElements = page_html.getElementsByClassName('statusSubmittedColumnValue');
  1622. var approvedElements = page_html.getElementsByClassName('statusApprovedColumnValue');
  1623. var rejectedElements = page_html.getElementsByClassName('statusRejectedColumnValue');
  1624. var pendingElements = page_html.getElementsByClassName('statusPendingColumnValue');
  1625. var earningsElements = page_html.getElementsByClassName('statusEarningsColumnValue');
  1626.  
  1627. if (dateElements[0].childNodes[1].textContent.trim() != 'Today')
  1628. return;
  1629.  
  1630. var url = dateElements[0].childNodes[1].href;
  1631. var date = url.substr(53); // keep MMDDYYYY
  1632. var submitted = parseInt(submittedElements[0].textContent);
  1633. //var approved = parseInt(approvedElements[0].textContent);
  1634. //var rejected = parseInt(rejectedElements[0].textContent);
  1635. //var pending = parseInt(pendingElements[0].textContent);
  1636. //var earnings = parseFloat(earningsElements[0].textContent.slice(1));
  1637. var pages_done = null;
  1638. if (localStorage['HITDB AUTOUPDATE PAGES'] !== undefined)
  1639. {
  1640. pages_done = JSON.parse(localStorage['HITDB AUTOUPDATE PAGES']);
  1641. }
  1642. if (pages_done == null || pages_done.date != date)
  1643. pages_done = {date: date};
  1644.  
  1645. var new_hits = 0;
  1646. var page = 1 + Math.floor(submitted/25);
  1647. page = (page<1) ? 1 : page;
  1648.  
  1649. var hitData = [];
  1650. if (submitted != pages_done.submitted)
  1651. {
  1652. url = "https://www.mturk.com/mturk/statusdetail?sortType=All&pageNumber=" + page + "&encodedDate=" + date;
  1653. HITStorage.process_page(url, date, hitData);
  1654. new_hits += submitted - pages_done.submitted;
  1655. pages_done.submitted = submitted;
  1656. localStorage['HITDB AUTOUPDATE PAGES'] = JSON.stringify(pages_done);
  1657. auto_button.textContent += '+';
  1658. }
  1659.  
  1660. if (page > 1)
  1661. {
  1662. extra_page = page-1;
  1663.  
  1664. while (extra_page >= 1)
  1665. {
  1666. if (pages_done[extra_page] != true)
  1667. {
  1668. url = "https://www.mturk.com/mturk/statusdetail?sortType=All&pageNumber=" + extra_page + "&encodedDate=" + date;
  1669. if (HITStorage.process_page(url, date, hitData) == 25)
  1670. {
  1671. pages_done[extra_page] = true;
  1672. localStorage['HITDB AUTOUPDATE PAGES'] = JSON.stringify(pages_done);
  1673. auto_button.textContent += '+';
  1674. }
  1675. break;
  1676. }
  1677. extra_page -= 1;
  1678. }
  1679. }
  1680. HITStorage.indexedDB.addHITs(hitData);
  1681. }
  1682.  
  1683. // Gets status details for given date (MMDDYYYY)
  1684. // Collects all HITs for given date to hitData array
  1685. HITStorage.getHITData = function(day_to_fetch, hitData, page, days_to_update)
  1686. {
  1687. var dataDate = convert_iso_date(day_to_fetch.date);
  1688. page = page || 1;
  1689. detailed_status_page_link = "https://www.mturk.com/mturk/statusdetail?sortType=All&pageNumber=" + page + "&encodedDate=" + dataDate;
  1690.  
  1691. if (HITStorage.process_page(detailed_status_page_link, dataDate, hitData) == 0)
  1692. {
  1693. if (day_to_fetch.submitted == -1 || hitData.length == day_to_fetch.submitted)
  1694. {
  1695. setTimeout(function(){ HITStorage.indexedDB.addHITs(hitData, day_to_fetch, days_to_update); }, 1000);
  1696. }
  1697. else
  1698. {
  1699. alert("There was an error while fetching HITs for date: " + day_to_fetch.date + ".\n" +
  1700. "Script monkeys expected " + day_to_fetch.submitted + " bananas, but got " + hitData.length + "! ??");
  1701. HITStorage.update_done();
  1702. }
  1703. }
  1704. else
  1705. {
  1706. HITStorage.update_status_label('Please wait: script monkeys are fetching status pages (' +
  1707. day_to_fetch.date + ', page ' + page + ')', 'red');
  1708. setTimeout(function(){ HITStorage.getHITData(day_to_fetch, hitData, page+1, days_to_update); }, 1000);
  1709. }
  1710. }
  1711.  
  1712. HITStorage.formatTime = function(msec)
  1713. {
  1714. if (isNaN(msec))
  1715. return "-";
  1716. var seconds = Math.floor(msec / 1000) % 60;
  1717. var minutes = Math.floor((msec / 1000) / 60) % 60;
  1718. var hours = Math.floor(((msec / 1000) / 60) / 60) % 24;
  1719. var days = Math.floor(((msec / 1000) / 60) / 60 / 24);
  1720.  
  1721. if (hours > 0)
  1722. seconds = "";
  1723. else
  1724. seconds = "" + seconds + "s";
  1725. minutes == 0 ? minutes = "" : minutes = "" + minutes + "m ";
  1726. hours == 0 ? hours = "" : hours = "" + hours + "h ";
  1727.  
  1728. if (days > 0)
  1729. return '' + days + ' day' + ((days>1)? 's' : ' ') + hours;
  1730. return hours + minutes + seconds;
  1731. }
  1732.  
  1733. HITStorage.update_status_label = function(new_status, color)
  1734. {
  1735. var label = document.getElementById('status_label');
  1736. label.innerHTML = new_status;
  1737. label.style.color = color || 'black';
  1738. }
  1739.  
  1740. // validate input field dates
  1741. // Accept YYYY-MM-DD
  1742. HITStorage.validate_date = function(input)
  1743. {
  1744. date = input.value;
  1745.  
  1746. if (date.match(/^[01]\d\/[0123]\d\/20\d\d$/) != null)
  1747. {
  1748. var d = date.split('\/');
  1749. date = d[2] + '-' + d[0] + '-' + d[1];
  1750. input.value = date;
  1751. }
  1752.  
  1753. if (date.match(/^$|^20\d\d\-[01]\d\-[0123]\d$/) != null)
  1754. {
  1755. input.style.backgroundColor = 'white';
  1756. return true;
  1757. }
  1758. input.style.backgroundColor = 'pink';
  1759. return false;
  1760. }
  1761.  
  1762. HITStorage.validate_dates = function()
  1763. {
  1764. from = document.getElementById('from_date');
  1765. to = document.getElementById('to_date');
  1766.  
  1767. if (HITStorage.validate_date(from) && HITStorage.validate_date(to))
  1768. {
  1769. if (from.value > to.value && to.value != '')
  1770. {
  1771. alert('Invalid date!');
  1772. return false;
  1773. }
  1774.  
  1775. return true;
  1776. }
  1777. alert('Invalid date!');
  1778. return false;
  1779. }
  1780.  
  1781. HITStorage.start_search = function()
  1782. {
  1783. if (HITStorage.validate_dates() == false)
  1784. return;
  1785.  
  1786. HITStorage.update_status_label('Using local HIT database', 'green');
  1787.  
  1788. var options = {};
  1789. options.term = document.getElementById('search_term').value;
  1790. options.status = document.getElementById('status_select').value;
  1791. options.donut = document.getElementById('donut_select').value;
  1792. options.from_date = document.getElementById('from_date').value;
  1793. options.to_date = document.getElementById('to_date').value;
  1794. options.export_csv = document.getElementById('export_csv').checked;
  1795.  
  1796. HITStorage.disable_inputs();
  1797. setTimeout(function(){ HITStorage.do_search(options); }, 500);
  1798. }
  1799.  
  1800. HITStorage.disable_inputs = function()
  1801. {
  1802. document.getElementById('delete_button').disabled = true;
  1803. document.getElementById('search_button').disabled = true;
  1804. document.getElementById('update_button').disabled = true;
  1805. document.getElementById('overview_button').disabled = true;
  1806. document.getElementById('import_button').disabled = true;
  1807. document.getElementById('pending_button').disabled = true;
  1808. document.getElementById('status_button').disabled = true;
  1809. document.getElementById('from_date').disabled = true;
  1810. document.getElementById('to_date').disabled = true;
  1811. document.getElementById('search_term').disabled = true;
  1812. document.getElementById('status_select').disabled = true;
  1813. document.getElementById('donut_select').disabled = true;
  1814. }
  1815.  
  1816. HITStorage.enable_inputs = function()
  1817. {
  1818. document.getElementById('delete_button').disabled = false;
  1819. document.getElementById('search_button').disabled = false;
  1820. document.getElementById('update_button').disabled = false;
  1821. document.getElementById('overview_button').disabled = false;
  1822. document.getElementById('import_button').disabled = false;
  1823. document.getElementById('pending_button').disabled = false;
  1824. document.getElementById('status_button').disabled = false;
  1825. document.getElementById('from_date').disabled = false;
  1826. document.getElementById('to_date').disabled = false;
  1827. document.getElementById('search_term').disabled = false;
  1828. document.getElementById('status_select').disabled = false;
  1829. document.getElementById('donut_select').disabled = false;
  1830. }
  1831.  
  1832.  
  1833. HITStorage.do_search = function(options)
  1834. {
  1835. HITStorage.indexedDB.getHITs(options);
  1836.  
  1837. setTimeout( function() { HITStorage.update_status_label("Search powered by non-amazonian script monkeys"); }, 3000);
  1838.  
  1839. HITStorage.enable_inputs();
  1840. }
  1841.  
  1842. HITStorage.show_results = function(results)
  1843. {
  1844.  
  1845. FauxFrameobj.innerHTML = "";
  1846. FauxFrameobj.style.display = 'block';
  1847.  
  1848. var html = "";
  1849. html += "<div id=\"closebutton\" align=\"right\"></div>";
  1850. html += "<h1>HITs matching your search:</h1>\n";
  1851. html += '<table style="border: 1px solid black;border-collapse:collapse;width:90%;margin-left:auto;margin-right:auto;">\n';
  1852. html += '<tr style="background-color:lightgrey"><th>Date</th><th>Requester</th><th>HIT Title</th><th>Reward</th><th>Status</th><th>Feedback</th></tr>\n';
  1853.  
  1854. var odd = true;
  1855. var sum = 0;
  1856. var sum_rejected = 0;
  1857. var sum_approved = 0;
  1858. var sum_pending = 0;
  1859.  
  1860.  
  1861. var new_day = false;
  1862.  
  1863. for (var i=0; i<results.length; i++) {
  1864. odd = !odd;
  1865. sum += results[i].reward;
  1866. if (results[i].status == 'Rejected')
  1867. sum_rejected += results[i].reward;
  1868. else if (results[i].status == 'Pending Approval')
  1869. sum_pending += results[i].reward;
  1870. else
  1871. sum_approved += results[i].reward;
  1872.  
  1873. if (i>0 && (results[i-1].date != results[i].date))
  1874. new_day = true;
  1875. else
  1876. new_day = false;
  1877. html += HITStorage.format_hit_line(results[i], odd, HITStorage.status_color(results[i].status), new_day );
  1878. }
  1879.  
  1880. html += '<tr style="background-color:lightgrey"><th></th><th></th><th></th><th>$' + sum.toFixed(2) + '</th><th></th><th></th></tr>\n';
  1881. html += "</table>";
  1882. html += "<p>Found " + results.length + " matching HITs. $" + sum_approved.toFixed(2) + " approved, " +
  1883. "$" + sum_rejected.toFixed(2) + " rejected and $" + sum_pending.toFixed(2) + " pending.</p>";
  1884.  
  1885. FauxFrameobj.innerHTML = html;
  1886.  
  1887. //close button
  1888. var Close_button = document.createElement('button');
  1889. Close_button.setAttribute('id', "close_button");
  1890. var CloseDiv =document.getElementById('closebutton');
  1891. CloseDiv.appendChild(Close_button);
  1892.  
  1893. Close_button.title = "Close Faux Frame";
  1894. Close_button.textContent = "Close Frame";
  1895. Close_button.style.color = 'black';
  1896. Close_button.style.margin = '5px 5px 5px 5x';
  1897. Close_button.addEventListener("click", HITStorage.CloseFaux , false);
  1898. //close button
  1899.  
  1900. }
  1901.  
  1902. HITStorage.status_color = function(status)
  1903. {
  1904. var color = "green";
  1905.  
  1906. if (status.match("Pending Approval"))
  1907. color = "orange";
  1908. else if (status.match("Rejected"))
  1909. color = "red";
  1910.  
  1911. return color;
  1912. }
  1913.  
  1914. HITStorage.format_hit_line = function(hit, odd, status_color, new_day)
  1915. {
  1916. var line = '<tr style="background-color:';
  1917. if (odd)
  1918. line += '#f1f3eb;';
  1919. else
  1920. line += 'white;';
  1921. line += ' valign=top;';
  1922. if (new_day)
  1923. line += ' border: 0px dotted #000000; border-width: 2px 0px 0px 0px">';
  1924. else
  1925. line += '">';
  1926.  
  1927. line += '<td>' + hit.date + '</td>';
  1928. if (hit.requesterLink != null)
  1929. line += '<td style="width:165px"><a href="' + hit.requesterLink + '" title="Contact this Requester">' + hit.requesterName + '</a></td>';
  1930. else
  1931. line += '<td style="width:165px">' + hit.requesterName + '</td>';
  1932. line += '<td style="width:213px">' + hit.title + '</td>';
  1933. line += '<td style="width:45px">$' + hit.reward.toFixed(2) + '</td>';
  1934. line += '<td style="color:' + status_color + '; width:55px">' + hit.status + '</td>';
  1935. line += '<td><div style="width:225px; overflow:hidden">' + hit.feedback + '</div></td>';
  1936. line += '</tr>\n';
  1937. return line;
  1938. }
  1939.  
  1940. HITStorage.show_pending_overview = function(results)
  1941. {
  1942. FauxFrameobj.innerHTML = "";
  1943.  
  1944. FauxFrameobj.style.display = 'block';
  1945.  
  1946. var html = "";
  1947. html += "<div id=\"closebutton\" align=\"right\"></div>";
  1948. html +="<h1>Summary of Pending HITs</h1>\n";
  1949. html +='<table style="border: 1px solid black;border-collapse:collapse;width:90%;margin-left:auto;margin-right:auto;">\n';
  1950. html +='<tr style="background-color:lightgrey"><th>requesterId</th><th>Requester</th><th></th><th>Pending</th><th>Rewards</th>\n';
  1951.  
  1952. // 'requesterId,requesterName,pending,reward';
  1953. var odd = false;
  1954. var sum = 0;
  1955. var pending = 0;
  1956.  
  1957. for (var i=0; i<results.length; i++) {
  1958. odd = !odd;
  1959. sum += results[i][3];
  1960. pending += results[i][2];
  1961. html +=HITStorage.format_pending_line(results[i], odd, i);
  1962. }
  1963.  
  1964. html +='<tr style="background-color:lightgrey"><th>' + results.length + ' different requesterIds</th><th></th><th></th><th style="text-align: right">' + pending +
  1965.  
  1966. '</th><th style="text-align: right">$' + sum.toFixed(2) + '</th>\n';
  1967. html +="</table>";
  1968.  
  1969. FauxFrameobj.innerHTML = html;
  1970.  
  1971. for (var i=0; i<results.length; i++)
  1972. {
  1973. document.getElementById('id-' + i).addEventListener("click", search_func(results[i][0], 'requesterId'), false);
  1974. document.getElementById('id2-' + i).addEventListener("click", show_requester_func(results[i][0]) , false);
  1975. }
  1976.  
  1977. //close button
  1978. var Close_button = document.createElement('button');
  1979. Close_button.setAttribute('id', "close_button");
  1980. var CloseDiv =document.getElementById('closebutton');
  1981. CloseDiv.appendChild(Close_button);
  1982.  
  1983. Close_button.title = "Close Faux Frame";
  1984. Close_button.textContent = "Close Frame";
  1985. Close_button.style.color = 'black';
  1986. Close_button.style.margin = '5px 5px 5px 5x';
  1987. Close_button.addEventListener("click", HITStorage.CloseFaux , false);
  1988. //close button
  1989. }
  1990.  
  1991. HITStorage.CloseFaux = function(){
  1992. FauxFrameobj.innerHTML = "";
  1993. FauxFrameobj.style.display = 'none';
  1994. }
  1995.  
  1996. HITStorage.show_status_overview = function(results, date)
  1997. {
  1998. FauxFrameobj.innerHTML = "";
  1999. FauxFrameobj.style.display = 'block';
  2000.  
  2001. var html = "";
  2002. html += "<div id=\"closebutton\" align=\"right\"></div>";
  2003. if (date)
  2004. html +="<h1>Daily HIT stats</h1>\n";
  2005. else
  2006. html +="<h1>Daily HIT stats (' + date + ')</h1>\n";
  2007. html +='<table style="border: 1px solid black;border-collapse:collapse;width:90%;margin-left:auto;margin-right:auto;">\n';
  2008. html +='<tr style="background-color:lightgrey"><th>Date</th><th>Submitted</th><th>Approved</th><th>Rejected</th><th>Pending</th><th>Earnings</th>\n';
  2009.  
  2010. var odd = false;
  2011. var sum = 0;
  2012. var submitted = 0;
  2013. var approved = 0;
  2014. var rejected = 0;
  2015. var pending = 0;
  2016. var new_month = false;
  2017.  
  2018. for (var i=results.length-1; i>=0; i--) {
  2019. odd = !odd;
  2020. sum += results[i].earnings;
  2021. submitted += results[i].submitted;
  2022. approved += results[i].approved;
  2023. rejected += results[i].rejected;
  2024. pending += results[i].pending;
  2025. if (i<results.length-1)
  2026. new_month = (results[i].date.substr(0,7) != results[i+1].date.substr(0,7));
  2027. html += HITStorage.format_status_line(results[i], odd, new_month);
  2028. }
  2029.  
  2030. html +='<tr style="background-color:lightgrey"><th>' + results.length + ' days</th><th style="text-align: left">' + submitted +
  2031. '</th><th style="text-align: left">' + approved +
  2032. '</th><th style="text-align: left">' + rejected +
  2033. '</th><th style="text-align: left">' + pending +
  2034. '</th><th style="text-align: left">$' + sum.toFixed(2) + '</th>\n';
  2035. html +="</table>";
  2036.  
  2037. FauxFrameobj.innerHTML = html;
  2038. for (var i=0; i<results.length; i++)
  2039. document.getElementById(results[i].date).addEventListener("click", search_func('', 'date', results[i].date, results[i].date), false);
  2040.  
  2041. //close button
  2042. var Close_button = document.createElement('button');
  2043. Close_button.setAttribute('id', "close_button");
  2044. var CloseDiv =document.getElementById('closebutton');
  2045. CloseDiv.appendChild(Close_button);
  2046.  
  2047. Close_button.title = "Close Faux Frame";
  2048. Close_button.textContent = "Close Frame";
  2049. Close_button.style.color = 'black';
  2050. Close_button.style.margin = '5px 5px 5px 5x';
  2051. Close_button.addEventListener("click", HITStorage.CloseFaux , false);
  2052. //close button
  2053.  
  2054. }
  2055.  
  2056. HITStorage.show_requester_overview = function(results, date)
  2057. {
  2058. FauxFrameobj.innerHTML = "";
  2059.  
  2060. FauxFrameobj.style.display = 'block';
  2061.  
  2062. var html = "";
  2063. html += "<div id=\"closebutton\" align=\"right\"></div>";
  2064. if (date)
  2065. html += "<h1>Requester Overview " + date + "</h1>\n";
  2066. else
  2067. html += "<h1>Requester Overview</h1>\n";
  2068. html += '<table style="border: 1px solid black;border-collapse:collapse;width:90%;margin-left:auto;margin-right:auto;">\n';
  2069. html += '<tr style="background-color:lightgrey"><th>requesterId</th><th>Requester</th><th></th><th>HITs</th><th>Pending</th><th>Rewards</th><th colspan="2">Rejected</th></tr>\n';
  2070.  
  2071. // 'requesterId,requesterName,hits,pending,reward,rejected';
  2072. var odd = false;
  2073. var sum = 0;
  2074. var hits = 0;
  2075. var rejected = 0;
  2076. var pending = 0;
  2077. var new_day = false;
  2078. var top = true;
  2079. var dot_line;
  2080.  
  2081. for (var i=0; i<results.length; i++) {
  2082. odd = !odd;
  2083. sum += results[i][3];
  2084. hits += results[i][2];
  2085. rejected += results[i][4];
  2086. pending += results[i][5];
  2087. dot_line = false;
  2088. if (i==10)
  2089. {
  2090. dot_line = true;
  2091. top = false;
  2092. }
  2093. if (i>10 && results[i][3] == 0 && results[i-1][3] != 0)
  2094. dot_line = true;
  2095.  
  2096. html += HITStorage.format_overview_line(results[i], odd, dot_line, top, i);
  2097. }
  2098.  
  2099. html += '<tr style="background-color:lightgrey"><th>' + results.length + ' different requesterIds</th>' +
  2100. '<th></th><th></th><th style="text-align: right">' + hits + '<th style="text-align: right">' + pending +
  2101. '</th><th style="text-align: right">$' + sum.toFixed(2) + '</th><th style="text-align: right">' + rejected + '</th>' +
  2102. '<th style="text-align: right">' +
  2103. (rejected/hits*100).toFixed(2) + '%</th></tr>\n';
  2104. html += "</table>";
  2105. html += "<p>Reward includes all 'Paid' and 'Approved - Pending Payment' HITs. " +
  2106. "Reward does not include any bonuses.</p>";
  2107.  
  2108. FauxFrameobj.innerHTML = html;
  2109.  
  2110. for (var i=0; i<results.length; i++)
  2111. {
  2112. document.getElementById('id-' + i).addEventListener("click", search_func(results[i][0], 'requesterId'), false);
  2113. document.getElementById('id2-' + i).addEventListener("click", show_requester_func(results[i][0]) , false);
  2114. }
  2115.  
  2116.  
  2117.  
  2118. //close button
  2119. var Close_button = document.createElement('button');
  2120. Close_button.setAttribute('id', "close_button");
  2121. var CloseDiv =document.getElementById('closebutton');
  2122. CloseDiv.appendChild(Close_button);
  2123.  
  2124. Close_button.title = "Close Faux Frame";
  2125. Close_button.textContent = "Close Frame";
  2126. Close_button.style.color = 'black';
  2127. Close_button.style.margin = '5px 5px 5px 5x';
  2128. Close_button.addEventListener("click", HITStorage.CloseFaux , false);
  2129. //close button
  2130. }
  2131.  
  2132. HITStorage.show_requester = function(results)
  2133. {
  2134. FauxFrameobj.innerHTML = "";
  2135.  
  2136. FauxFrameobj.style.display = 'block';
  2137.  
  2138. var html = "";
  2139. html += "<div id=\"closebutton\" align=\"right\"></div>";
  2140. html +='<h1>' + results[0].requesterName + ' (' + results[0].requesterId + ')</h1>\n';
  2141.  
  2142. html +='You have submitted ' + results.length + ' HITs for this requester. Earliest ' + results[results.length-1].date +
  2143. ', latest ' + results[0].date;
  2144.  
  2145. html +='<p><a href="https://www.mturk.com/mturk/searchbar?selectedSearchType=hitgroups&requesterId=' + results[0].requesterId + '">' +
  2146. 'Search HITs created by this requester</a></p>';
  2147.  
  2148.  
  2149. html +='<p><a href="https://turkopticon.differenceengines.com/' + results[0].requesterId + '">' +
  2150. 'See reviews about this requester on Turkopticon</a> or ';
  2151. '<a href="' + TO_report_link(results[0].requesterId,results[0].requesterName) + '">' +
  2152. 'review this requester on Turkopticon</a></p>';
  2153.  
  2154. var reward = 0;
  2155. var hits = 0;
  2156. var sum = 0;
  2157. var rejected = 0;
  2158. var approved = 0;
  2159. var pending = 0;
  2160. var all_rejected = 0;
  2161. var all_approved = 0;
  2162. var all_pending = 0;
  2163.  
  2164. html +='<table style="border: 1px solid black;border-collapse:collapse;margin-left:10px;margin-right:auto;">\n';
  2165. html +='<tr style="background-color:lightgrey"><th>Month' +
  2166. '</th><th>Submitted' +
  2167. '</th><th>Approved' +
  2168. '</th><th>Rejected' +
  2169. '</th><th>Pending' +
  2170. '</th><th>Earnings</th></tr>\n';
  2171.  
  2172. for (var i=0; i<results.length; i++) {
  2173. hits++;
  2174. if (results[i].status == 'Rejected')
  2175. {
  2176. all_rejected++;
  2177. rejected++;
  2178. }
  2179. else if (results[i].status == 'Pending Approval')
  2180. {
  2181. all_pending++;
  2182. pending++;
  2183. }
  2184. else
  2185. {
  2186. all_approved++;
  2187. approved++;
  2188. sum += results[i].reward;
  2189. reward += results[i].reward;
  2190. }
  2191.  
  2192. if (i==results.length-1 || (i<results.length-1 && (results[i].date.substr(0,7) != results[i+1].date.substr(0,7))))
  2193. {
  2194. html +='<tr><td style="text-align: right">' + results[i].date.substr(0,7) +
  2195. '</td><td style="text-align: right">' + hits +
  2196. '</td><td style="text-align: right">' + approved +
  2197. '</td><td style="text-align: right">' + rejected +
  2198. '</td><td style="text-align: right">' + pending +
  2199. '</td><td style="text-align: right">$' + reward.toFixed(2) + '</td></tr>\n';
  2200. reward = 0;
  2201. hits = 0;
  2202. approved = 0;
  2203. rejected = 0;
  2204. pending = 0;
  2205. }
  2206. }
  2207. html +='<tr style="background-color:lightgrey"><th>' +
  2208. '</th><th style="text-align: right">' + results.length +
  2209. '</th><th style="text-align: right">' + all_approved +
  2210. '</th><th style="text-align: right">' + all_rejected +
  2211. '</th><th style="text-align: right">' + all_pending +
  2212. '</th><th style="text-align: right">$' + sum.toFixed(2) + '</th></tr>\n';
  2213. html +='</table>';
  2214.  
  2215. html +='<p>Rewards do not include any bonuses</p>';
  2216.  
  2217. FauxFrameobj.innerHTML = html;
  2218.  
  2219. //close button
  2220. var Close_button = document.createElement('button');
  2221. Close_button.setAttribute('id', "close_button");
  2222. var CloseDiv =document.getElementById('closebutton');
  2223. CloseDiv.appendChild(Close_button);
  2224.  
  2225. Close_button.title = "Close Faux Frame";
  2226. Close_button.textContent = "Close Frame";
  2227. Close_button.style.color = 'black';
  2228. Close_button.style.margin = '5px 5px 5px 5x';
  2229. Close_button.addEventListener("click", HITStorage.CloseFaux , false);
  2230. //close button
  2231.  
  2232. //find this
  2233.  
  2234.  
  2235. }
  2236.  
  2237. function TO_report_link(requesterId, requesterName)
  2238. {
  2239. return 'https://turkopticon.differenceengines.com/report?requester[amzn_id]=' + requesterId +
  2240. '&requester[amzn_name]=' + encodeURI(requesterName.trim());
  2241. }
  2242.  
  2243. HITStorage.format_overview_line = function(req, odd, dot_line, top, i)
  2244. {
  2245. var color;
  2246. if (top)
  2247. color = (odd)? 'ffffe0;' : '#eee8aa;';
  2248. else
  2249. color = (odd)? 'white;' : '#f1f3eb;';
  2250. var line = '<tr style="background-color:' + color;
  2251. if (dot_line)
  2252. line += ' border: 0px dotted #000000; border-width: 2px 0px 0px 0px';
  2253. line += '">';
  2254. line += '<td><button type="button" title="Show all HITs" style="height: 16px;font-size: 8px; padding: 0px;" id="id-' +
  2255. i + '">&gt;&gt;</button>' +
  2256. '<button type="button" title="Show details about requester" style="height: 16px;font-size: 8px; padding: 0px;" id="id2-' +
  2257. i + '">+</button> ' + req[0].trim() +
  2258. '</td>';
  2259. line += '<td><a title="Requesters Turkopticon page" target="_blank" href="https://turkopticon.differenceengines.com/' + req[0].trim() + '">[TO]</a> ';
  2260. line += req[1].trim() + '</td>';
  2261. line += '<td style="width: 50px"><a title="Report requester to Turkopticon" target="_blank" href="' + TO_report_link(req[0], req[1]) + '">[report]</a></td>';
  2262. line += '<td style="text-align: right">' + req[2] + '</td>';
  2263. line += '<td style="text-align: right">' + req[5] + '</td>';
  2264. line += '<td style="text-align: right">$' + req[3].toFixed(2) + '</td>';
  2265. var p = (req[4]/req[2]*100).toFixed(1);
  2266. var pc = (p>0)? 'red' : 'green';
  2267. line += '<td style="text-align: right; color:' + pc + ';">' + req[4] + '</td>';
  2268. line += '<td style="text-align: right; color:' + pc + ';">' + p + '%</td>';
  2269. line += '</tr>\n';
  2270. return line;
  2271. }
  2272.  
  2273. HITStorage.format_pending_line = function(req, odd, i)
  2274. {
  2275. var color = (odd)? 'white;' : '#f1f3eb;';
  2276. var line = '<tr style="background-color:' + color;
  2277. line += '">';
  2278. line += '<td style="white-space: nowrap; width: 150px; margin-right: 10px;"><button type="button" title="Show all HITs" style="height: 16px;font-size: 8px; padding: 0px;" id="id-' +
  2279. i + '">&gt;&gt;&gt;</button>' +
  2280. '<button type="button" title="Show details about requester" style="height: 16px;font-size: 8px; padding: 0px;" id="id2-' +
  2281. i + '">+</button> ' + req[0].trim() + '</td>';
  2282. line += '<td><a title="Requesters Turkopticon page" target="_blank" href="https://turkopticon.differenceengines.com/' + req[0].trim() + '">[TO]</a> ';
  2283. line += req[1].trim() + '</td>';
  2284. line += '<td style="width: 50px"><a title="Report requester to Turkopticon" target="_blank" href="' + TO_report_link(req[0], req[1]) + '">[report]</a></td>';
  2285. line += '<td style="text-align: right">' + req[2] + '</td>';
  2286. line += '<td style="text-align: right">$' + req[3].toFixed(2) + '</td>';
  2287. line += '</tr>\n';
  2288. return line;
  2289. }
  2290.  
  2291. HITStorage.format_status_line = function(d, odd, new_month)
  2292. {
  2293. var color = (odd)? 'white;' : '#f1f3eb;';
  2294. var line = '<tr style="background-color:' + color;
  2295. if (new_month)
  2296. line += ' border: 0px dotted #000000; border-width: 2px 0px 0px 0px">';
  2297. else
  2298. line += '">';
  2299. line += '<td><button type="button" title="Show all HITs" style="height: 16px;font-size: 8px; padding: 0px;" id="' +
  2300. d.date + '">&gt;&gt;&gt;</button> ' + d.date + '</td>';
  2301. line += '<td>' + d.submitted + '</td>';
  2302. line += '<td>' + d.approved + '</td>';
  2303. line += '<td>' + d.rejected + '</td>';
  2304. line += '<td>' + d.pending + '</td>';
  2305. line += '<td>$' + d.earnings.toFixed(2) + '</td>';
  2306. line += '</tr>\n';
  2307. return line;
  2308. }
  2309.  
  2310. HITStorage.show_pending_overview_csv = function(results)
  2311. {
  2312. var csvData = 'requesterId,requesterName,pending,reward\n';
  2313. for (var i=0; i<results.length; i++) {
  2314. csvData += HITStorage.format_pending_line_csv(results[i]);
  2315. }
  2316. location.href='data:text/csv;charset=utf8,' + encodeURIComponent(csvData);
  2317. }
  2318.  
  2319. HITStorage.format_pending_line_csv = function(req)
  2320. {
  2321. var line = '';
  2322. line += req[0].trim() + ',';
  2323. line += '"' + req[1].trim() + '",';
  2324. line += req[2] + ',';
  2325. line += req[3].toFixed(2);
  2326. line += '\n';
  2327. return line;
  2328. }
  2329.  
  2330.  
  2331. HITStorage.show_requester_overview_csv = function(results)
  2332. {
  2333. var csvData = 'requesterId,requesterName,hits,reward,rejected,pending\n';
  2334. for (var i=0; i<results.length; i++) {
  2335. csvData += HITStorage.format_overview_line_csv(results[i]);
  2336. }
  2337. location.href='data:text/csv;charset=utf8,' + encodeURIComponent(csvData);
  2338. }
  2339.  
  2340. HITStorage.format_overview_line_csv = function(req)
  2341. {
  2342. var line = '';
  2343. line += req[0].trim() + ',';
  2344. line += '"' + req[1].trim() + '",';
  2345. line += req[2] + ',';
  2346. line += req[3].toFixed(2) + ',';
  2347. line += req[4] + ',';
  2348. line += req[5];
  2349. line += '\n';
  2350. return line;
  2351. }
  2352.  
  2353. HITStorage.show_status_overview_csv = function(results)
  2354. {
  2355. var csvData = 'Date,Submitted,Approved,Rejected,Pending,Earnings\n';
  2356. for (var i=results.length-1; i>=0; i--) {
  2357. csvData += HITStorage.format_status_line_csv(results[i]);
  2358. }
  2359. location.href='data:text/csv;charset=utf8,' + encodeURIComponent(csvData);
  2360. }
  2361.  
  2362. HITStorage.format_status_line_csv = function(d)
  2363. {
  2364. var line = '';
  2365. line += '"' + d.date + '",';
  2366. line += d.submitted + ',';
  2367. line += d.approved + ',';
  2368. line += d.rejected + ',';
  2369. line += d.pending + ',';
  2370. line += d.earnings.toFixed(2);
  2371. line += '\n';
  2372. return line;
  2373. }
  2374.  
  2375. HITStorage.export_csv = function(results)
  2376. {
  2377. var csvData = 'hitId,date,requesterName,requesterId,title,reward,status,feedback\n';
  2378. for (var i=0; i<results.length; i++) {
  2379. csvData += HITStorage.format_csv_line(results[i]);
  2380. }
  2381. location.href='data:text/csv;charset=utf8,' + encodeURIComponent(csvData);
  2382. }
  2383.  
  2384. HITStorage.format_csv_line = function(hit)
  2385. {
  2386. var line = '';
  2387. line += '"' + hit.hitId.trim() + '",';
  2388. line += '"' + hit.date.trim() + '",';
  2389. line += '"' + hit.requesterName.trim() + '",';
  2390. line += '"' + hit.requesterId.trim() + '",';
  2391. line += '"' + hit.title.trim() + '",';
  2392. line += hit.reward.toFixed(2) + ',';
  2393. line += '"' + hit.status.trim().replace(/\&nbsp;/g,' ') + '",';
  2394. line += '"' + hit.feedback.trim() + '"';
  2395. line += '\n';
  2396. return line;
  2397. }
  2398.  
  2399. HITStorage.do_update = function(days_to_update)
  2400. {
  2401. if (DAYS_TO_FETCH.length<1)
  2402. {
  2403. HITStorage.check_update();
  2404. return;
  2405. }
  2406. HITStorage.update_status_label('Please wait: ' + progress_bar(days_to_update-DAYS_TO_FETCH.length, days_to_update) +
  2407. ' (' + (days_to_update-DAYS_TO_FETCH.length) + '/' + days_to_update + ')', 'red');
  2408.  
  2409. var hits = [];
  2410. setTimeout(function(){ HITStorage.getHITData( DAYS_TO_FETCH.shift(), hits, 1, days_to_update); }, 2000);
  2411. }
  2412.  
  2413. HITStorage.update_done = function()
  2414. {
  2415. HITStorage.update_status_label('Script monkeys have updated your local database', 'green');
  2416. setTimeout( function() { HITStorage.update_status_label("Search powered by non-amazonian script monkeys"); }, 5000);
  2417.  
  2418. HITStorage.enable_inputs();
  2419.  
  2420. localStorage['HITDB UPDATED'] = new Date().toString();
  2421.  
  2422. var e = document.getElementById('user_activities.date_column_header.tooltip').parentNode.parentNode.childNodes[2].childNodes[1].childNodes[1];
  2423. if (e != null && e.textContent.trim() == 'Today') {
  2424. var today = e.href.slice(-8);
  2425. today = convert_date(today);
  2426. HITStorage.indexedDB.get_todays_projected_earnings(today);
  2427. }
  2428. HITStorage.indexedDB.get_pending_approvals();
  2429. HITStorage.indexedDB.get_pending_payments();
  2430. }
  2431.  
  2432.  
  2433. HITStorage.update_database = function()
  2434. {
  2435. HITStorage.disable_inputs();
  2436.  
  2437. if (localStorage['HITDB TRY_EXTRA_DAYS'] == 'YES') {
  2438. DAYS_TO_FETCH = HITStorage.getAllAvailableDays(20);
  2439. delete localStorage['HITDB TRY_EXTRA_DAYS'];
  2440. }
  2441. else
  2442. {
  2443. DAYS_TO_FETCH = HITStorage.getAllAvailableDays();
  2444. }
  2445. DAYS_TO_FETCH_CHECK = DAYS_TO_FETCH.slice(0);
  2446.  
  2447. // remove extra days from checklist
  2448. for (var i=0; i<DAYS_TO_FETCH_CHECK.length; i++)
  2449. {
  2450. if (DAYS_TO_FETCH_CHECK[i].submitted == -1) {
  2451. DAYS_TO_FETCH_CHECK = DAYS_TO_FETCH_CHECK.slice(0,i);
  2452. break;
  2453. }
  2454. }
  2455.  
  2456.  
  2457. HITStorage.update_status_label('Please wait: script monkeys are preparing to start working', 'red');
  2458. setTimeout(function(){ HITStorage.prepare_update_and_check_pending_payments(); }, 100);
  2459. }
  2460.  
  2461. HITStorage.show_overview = function()
  2462. {
  2463. if (HITStorage.validate_dates() == false)
  2464. return;
  2465. var options = {};
  2466. options.term = document.getElementById('search_term').value;
  2467. options.status = document.getElementById('status_select').value;
  2468. options.donut = document.getElementById('donut_select').value;
  2469. options.from_date = document.getElementById('from_date').value;
  2470. options.to_date = document.getElementById('to_date').value;
  2471. options.export_csv = document.getElementById('export_csv').checked;
  2472.  
  2473. HITStorage.update_status_label('Please wait: script monkeys are picking bananas 1', 'red');
  2474. HITStorage.disable_inputs();
  2475. HITStorage.indexedDB.requesterOverview(options);
  2476. HITStorage.update_status_label('Please wait: script monkeys are picking bananas 2', 'red');
  2477. }
  2478.  
  2479. HITStorage.show_pendings = function()
  2480. {
  2481. var options = {};
  2482. options.term = document.getElementById('search_term').value;
  2483. options.status = document.getElementById('status_select').value;
  2484. options.donut = document.getElementById('donut_select').value;
  2485. options.from_date = document.getElementById('from_date').value;
  2486. options.to_date = document.getElementById('to_date').value;
  2487. options.export_csv = document.getElementById('export_csv').checked;
  2488.  
  2489. HITStorage.update_status_label('Please wait: script monkeys are picking bananas 1', 'red');
  2490. HITStorage.disable_inputs();
  2491. HITStorage.indexedDB.pendingOverview(options);
  2492. HITStorage.update_status_label('Please wait: script monkeys are picking bananas 1', 'red');
  2493. }
  2494.  
  2495. HITStorage.show_status = function()
  2496. {
  2497. if (HITStorage.validate_dates() == false)
  2498. return;
  2499. var options = {};
  2500. options.term = document.getElementById('search_term').value;
  2501. options.status = document.getElementById('status_select').value;
  2502. options.donut = document.getElementById('donut_select').value;
  2503. options.from_date = document.getElementById('from_date').value;
  2504. options.to_date = document.getElementById('to_date').value;
  2505. options.export_csv = document.getElementById('export_csv').checked;
  2506.  
  2507. HITStorage.update_status_label('Please wait: script monkeys are picking bananas 1', 'red');
  2508. HITStorage.disable_inputs();
  2509. HITStorage.indexedDB.statusOverview(options);
  2510. HITStorage.update_status_label('Please wait: script monkeys are picking bananas 2', 'red');
  2511. }
  2512.  
  2513. var IMPORT_DIALOG = null;
  2514.  
  2515. function import_dialog()
  2516. {
  2517. if (IMPORT_DIALOG == null)
  2518. {
  2519. IMPORT_DIALOG = document.createElement('div');
  2520. IMPORT_DIALOG.style.display = 'block';
  2521.  
  2522. IMPORT_DIALOG.style.position = 'fixed';
  2523. IMPORT_DIALOG.style.width = '600px';
  2524. //IMPORT_DIALOG.style.height = '400px';
  2525. IMPORT_DIALOG.style.height = '90%';
  2526. IMPORT_DIALOG.style.left = '50%';
  2527. IMPORT_DIALOG.style.right = '50%';
  2528. IMPORT_DIALOG.style.margin = '-300px 0px 0px -300px';
  2529. //IMPORT_DIALOG.style.top = '400px';
  2530. IMPORT_DIALOG.style.bottom = '10px';
  2531. IMPORT_DIALOG.style.padding = '10px';
  2532. IMPORT_DIALOG.style.border = '2px';
  2533. IMPORT_DIALOG.style.textAlign = 'center';
  2534. IMPORT_DIALOG.style.verticalAlign = 'middle';
  2535. IMPORT_DIALOG.style.borderStyle = 'solid';
  2536. IMPORT_DIALOG.style.borderColor = 'black';
  2537. IMPORT_DIALOG.style.backgroundColor = 'white';
  2538. IMPORT_DIALOG.style.color = 'black';
  2539. IMPORT_DIALOG.style.zIndex = '100';
  2540.  
  2541. var table = document.createElement('table');
  2542. var input = document.createElement('textarea');
  2543. var input2 = document.createElement('input');
  2544. var label = document.createElement('label');
  2545. var label2 = document.createElement('label');
  2546.  
  2547. label.textContent = 'Paste CSV-file in the textarea below.';
  2548. label2.textContent = 'CVS separator: ';
  2549. input.style.width = '100%';
  2550. input.style.height = '90%';
  2551.  
  2552. input2.maxLength = '1';
  2553. input2.size = '1';
  2554. input2.defaultValue = ',';
  2555.  
  2556. var import_button = document.createElement('button');
  2557. import_button.textContent = 'Import HITs';
  2558. import_button.addEventListener("click", import_dialog_close_func(true, input, input2), false);
  2559. import_button.style.margin = '5px';
  2560. var cancel_button = document.createElement('button');
  2561. cancel_button.textContent = 'Cancel';
  2562. cancel_button.addEventListener("click", import_dialog_close_func(false, input, input2), false);
  2563. cancel_button.style.margin = '5px';
  2564.  
  2565. IMPORT_DIALOG.appendChild(label);
  2566. IMPORT_DIALOG.appendChild(document.createElement('br'));
  2567. IMPORT_DIALOG.appendChild(label2);
  2568. IMPORT_DIALOG.appendChild(input2);
  2569. IMPORT_DIALOG.appendChild(document.createElement('br'));
  2570. IMPORT_DIALOG.appendChild(input);
  2571. IMPORT_DIALOG.appendChild(document.createElement('br'));
  2572. IMPORT_DIALOG.appendChild(cancel_button);
  2573. IMPORT_DIALOG.appendChild(import_button);
  2574. document.body.appendChild(IMPORT_DIALOG);
  2575. }
  2576. else
  2577. {
  2578. IMPORT_DIALOG.style.display = 'block';
  2579. }
  2580. }
  2581.  
  2582.  
  2583. /*
  2584. * CSVToArray() function is taken from:
  2585. *
  2586. * Blog Entry:
  2587. * Ask Ben: Parsing CSV Strings With Javascript Exec() Regular Expression Command
  2588. *
  2589. * Author:
  2590. * Ben Nadel / Kinky Solutions
  2591. *
  2592. * Link:
  2593. * http://www.bennadel.com/index.cfm?event=blog.view&id=1504
  2594. *
  2595. * Date Posted:
  2596. * Feb 19, 2009 at 10:03 AM
  2597. */
  2598. // This will parse a delimited string into an array of
  2599. // arrays. The default delimiter is the comma, but this
  2600. // can be overriden in the second argument.
  2601. function CSVToArray( strData, strDelimiter ) {
  2602. // Check to see if the delimiter is defined. If not,
  2603. // then default to comma.
  2604. strDelimiter = (strDelimiter || ",");
  2605.  
  2606. // Create a regular expression to parse the CSV values.
  2607. var objPattern = new RegExp(
  2608. (
  2609. // Delimiters.
  2610. "(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +
  2611.  
  2612. // Quoted fields.
  2613. "(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +
  2614.  
  2615. // Standard fields.
  2616. "([^\"\\" + strDelimiter + "\\r\\n]*))"
  2617. ),
  2618. "gi"
  2619. );
  2620.  
  2621. // Create an array to hold our data. Give the array
  2622. // a default empty first row.
  2623. var arrData = [[]];
  2624.  
  2625. // Create an array to hold our individual pattern
  2626. // matching groups.
  2627. var arrMatches = null;
  2628.  
  2629.  
  2630. // Keep looping over the regular expression matches
  2631. // until we can no longer find a match.
  2632. while (arrMatches = objPattern.exec( strData )){
  2633.  
  2634. // Get the delimiter that was found.
  2635. var strMatchedDelimiter = arrMatches[ 1 ];
  2636.  
  2637. // Check to see if the given delimiter has a length
  2638. // (is not the start of string) and if it matches
  2639. // field delimiter. If id does not, then we know
  2640. // that this delimiter is a row delimiter.
  2641. if (
  2642. strMatchedDelimiter.length &&
  2643. (strMatchedDelimiter != strDelimiter)
  2644. ){
  2645.  
  2646. // Since we have reached a new row of data,
  2647. // add an empty row to our data array.
  2648. arrData.push( [] );
  2649.  
  2650. }
  2651.  
  2652.  
  2653. // Now that we have our delimiter out of the way,
  2654. // let's check to see which kind of value we
  2655. // captured (quoted or unquoted).
  2656. if (arrMatches[ 2 ]){
  2657.  
  2658. // We found a quoted value. When we capture
  2659. // this value, unescape any double quotes.
  2660. var strMatchedValue = arrMatches[ 2 ].replace(
  2661. new RegExp( "\"\"", "g" ),
  2662. "\""
  2663. );
  2664.  
  2665. } else {
  2666.  
  2667. // We found a non-quoted value.
  2668. var strMatchedValue = arrMatches[ 3 ];
  2669.  
  2670. }
  2671.  
  2672.  
  2673. // Now that we have our value string, let's add
  2674. // it to the data array.
  2675. arrData[ arrData.length - 1 ].push( strMatchedValue );
  2676. }
  2677.  
  2678. // Return the parsed data.
  2679. return( arrData );
  2680. }
  2681.  
  2682. function import_dialog_close_func(save, input, separator)
  2683. {
  2684. return function()
  2685. {
  2686. if (save == true)
  2687. {
  2688.  
  2689. var lines = [];
  2690. var hits = [];
  2691.  
  2692. if (input.value.length > 0)
  2693. lines = CSVToArray(input.value, separator.value);
  2694.  
  2695. var errors = 0;
  2696. for (var i = 0; i<lines.length; i++)
  2697. {
  2698. var error = false;
  2699. try {
  2700. if (lines[i][0] == null || lines[i][0] == 'hitId')
  2701. continue;
  2702.  
  2703. if(lines[i][6] == 'Approved - Pending Payment')
  2704. lines[i][6] = 'Approved&nbsp;- Pending&nbsp;Payment';
  2705.  
  2706. if (lines[i].length != 8)
  2707. error = true;
  2708.  
  2709. var hit = {
  2710. hitId : lines[i][0],
  2711. date : convert_date(lines[i][1]),
  2712. requesterName : lines[i][2],
  2713. //requesterLink : null,
  2714. requesterId : lines[i][3],
  2715. title : lines[i][4],
  2716. reward : parseFloat(lines[i][5]),
  2717. status : lines[i][6],
  2718. feedback : lines[i][7] || "" // If no feedback, put empty string
  2719. };
  2720. } catch(err) { error = true; }
  2721.  
  2722. if (error == false)
  2723. hits.push(hit);
  2724. else
  2725. errors++;
  2726. }
  2727. if (hits.length < 1)
  2728. {
  2729. alert('No HITs found!');
  2730. return;
  2731. }
  2732. else if (confirm('Found ' + hits.length + ' HITs' + (errors>0? ' and ' + errors + (errors==1? ' error' : ' errors') : '') +
  2733. '.\nDo not reload this page until import is ready.\n' +
  2734. 'Press Ok to start.') == true)
  2735. {
  2736. HITStorage.disable_inputs();
  2737. HITStorage.update_status_label('Please wait: importing HITs', 'red');
  2738. IMPORT_DIALOG.style.display = 'none';
  2739. input.value = '';
  2740. HITStorage.indexedDB.importHITs(hits);
  2741. return;
  2742. }
  2743. else { return; }
  2744. }
  2745.  
  2746. IMPORT_DIALOG.style.display = 'none';
  2747. input.value = '';
  2748. };
  2749. }
  2750.  
  2751. function get_requester_id(s) {
  2752. var idx = 12 + s.search('requesterId=');
  2753. return s.substr(idx);
  2754. }
  2755.  
  2756. function show_requester_func(requesterId)
  2757. {
  2758. return function()
  2759. {
  2760. HITStorage.indexedDB.showRequester(requesterId);
  2761. };
  2762. }
  2763.  
  2764. function search_func(key, index, d1, d2)
  2765. {
  2766. d1 = d1 || '';
  2767. d2 = d2 || d1;
  2768. return function()
  2769. {
  2770. HITStorage.indexedDB.getHITs({term: key, index: index, status: '---', from_date: d1, to_date: d2, donut: '', this_day: ''});
  2771. };
  2772. }
  2773.  
  2774. function visible_func(element, visible)
  2775. {
  2776. return function()
  2777. {
  2778. element.style.visibility = (visible)? 'visible' : 'hidden';
  2779. };
  2780. }
  2781.  
  2782. function delete_func()
  2783. {
  2784. return function()
  2785. {
  2786. if (confirm('This will remove your local HIT DataBase!\nContinue?'))
  2787. {
  2788. HITStorage.indexedDB.deleteDB();
  2789. }
  2790. };
  2791. }
  2792.  
  2793. function import_func()
  2794. {
  2795. return function()
  2796. {
  2797. import_dialog();
  2798. };
  2799. }
  2800.  
  2801. function note_func(id, label)
  2802. {
  2803. return function()
  2804. {
  2805. note = prompt('Note for requesterId \'' + id + '\':', label.textContent);
  2806.  
  2807. if (note == null)
  2808. {
  2809. return;
  2810. }
  2811.  
  2812. HITStorage.indexedDB.addNote(id, note);
  2813. label.textContent = note;
  2814.  
  2815. label.style.border = '1px dotted';
  2816. if (note.indexOf('!') >= 0)
  2817. label.style.color = 'red';
  2818. else
  2819. label.style.color = 'black';
  2820. };
  2821. }
  2822.  
  2823. function block_func(requesterId, title, hitElement)
  2824. {
  2825. return function()
  2826. {
  2827. re = prompt('Block HITs from requesterId \'' + requesterId + '\' matching:\n' +
  2828. '(default matches only exactly same HIT title, leave empty to match all HITS)', '^'
  2829. + title.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1") + '$');
  2830.  
  2831. if (re == null)
  2832. {
  2833. return;
  2834. }
  2835. re = new RegExp(re);
  2836.  
  2837. if (!re.test(title)) {
  2838. if (confirm("Your regular expression does not match current HIT title.\nSave it anyway?") == false)
  2839. return;
  2840. }
  2841.  
  2842. HITStorage.indexedDB.addBlock(requesterId, re);
  2843. };
  2844. }
  2845.  
  2846. function unblock_func(requesterId, title)
  2847. {
  2848. return function()
  2849. {
  2850. var unblock = confirm('Unblocking removes all blocks that match this HITs title and requesterId.');
  2851. if (unblock == true)
  2852. {
  2853. HITStorage.indexedDB.removeBlocks(requesterId, title);
  2854. }
  2855. };
  2856. }
  2857.  
  2858. function auto_update_func()
  2859. {
  2860. return function()
  2861. {
  2862. var button = document.getElementById('auto_button');
  2863.  
  2864. if (localStorage['HITDB AUTO UPDATE'] === undefined)
  2865. {
  2866. alert('Enable Hit DataBase Auto Update\nWhen enabled, script will fetch last ' +
  2867. 'statusdetail pages and add them to database when this page is reloaded ' +
  2868. 'and at least two minutes have passed from last update. You still need to ' +
  2869. 'do full update from dashboard every now and then.');
  2870. button.textContent = 'Auto Update is ON';
  2871. button.style.color = 'green';
  2872. localStorage['HITDB AUTO UPDATE'] = 'ON';
  2873. }
  2874. else if (localStorage['HITDB AUTO UPDATE'] == 'ON')
  2875. {
  2876. button.textContent = 'Auto Update is OFF';
  2877. button.style.color = 'red';
  2878. localStorage['HITDB AUTO UPDATE'] = 'OFF';
  2879. }
  2880. else
  2881. {
  2882. button.textContent = 'Auto Update is ON';
  2883. button.style.color = 'green';
  2884. localStorage['HITDB AUTO UPDATE'] = 'ON';
  2885. }
  2886. };
  2887. }
  2888.  
  2889. function set_target_func(date)
  2890. {
  2891. return function()
  2892. {
  2893. var target = localStorage['TODAYS TARGET'];
  2894. if (target === undefined)
  2895. target = '';
  2896. else
  2897. target = parseFloat(localStorage['TODAYS TARGET']).toFixed(2);
  2898. target = prompt('Set your target:', target);
  2899.  
  2900. if (target == null)
  2901. return;
  2902. target = parseFloat(target);
  2903.  
  2904. localStorage['TODAYS TARGET'] = target.toFixed(2);
  2905. if (date != null)
  2906. HITStorage.indexedDB.get_todays_projected_earnings(date);
  2907. };
  2908. }
  2909.  
  2910. function random_face()
  2911. {
  2912. var faces = ['??','??','??','??','??','??','??','??','??','??','??','??','??','??','??','??'];
  2913. var n = Math.floor((Math.random()*faces.length));
  2914. return '<span style="color: black; font-weight: normal;" title="Featured non-amazonian script ' + ((n>11) ? '... kitten?': 'monkey') + '">' + faces[n] + '</span>';
  2915. }
  2916.  
  2917. function progress_bar(done, max, full, empty, c1, c2)
  2918. {
  2919. max = (max<1)? 1 : max;
  2920. done = (done<0)? 0 : done;
  2921. done = (done>max)? max : done;
  2922.  
  2923. var bar = '<span style="color: ' + (c1||'green') + '">';
  2924. for (var i=0; i<done; i++)
  2925. {
  2926. bar += full || '¦';
  2927. }
  2928. bar += '</span><span style="color: ' + (c2||'black') + '">';
  2929. for (var i=done; i<max; i++)
  2930. {
  2931. bar += empty || '?';
  2932. }
  2933. bar += '</span>';
  2934. return bar;
  2935. }
  2936.  
  2937. // convert date to more practical form (MMDDYYYY => YYYY-MM-DD)
  2938. function convert_date(date)
  2939. {
  2940. if (date.indexOf('-') > 0)
  2941. return date;
  2942. var day = date.substr(2,2);
  2943. var month = date.substr(0,2);
  2944. var year = date.substr(4,4);
  2945. return (year + '-' + month + '-' + day);
  2946. }
  2947.  
  2948. // convert date from YYYY-MM-DD to MMDDYYYY if it isn't already
  2949. function convert_iso_date(date)
  2950. {
  2951. if (date.indexOf('-') < 0)
  2952. return date;
  2953. var t = date.split('-');
  2954. return t[1] + t[2] + t[0];
  2955. }
  2956.  
  2957. // Format date for display YYYY-MM-DD, DD/MM/YYYY or DD.MM.YYYY
  2958. function display_date(date, format)
  2959. {
  2960. if (format === undefined || format == null)
  2961. return date;
  2962.  
  2963. var d = date.split('-');
  2964.  
  2965. if (format == 'little')
  2966. {
  2967. return d[2] + '.' + d[1] + '.' + d[0];
  2968. }
  2969. if (format == 'middle')
  2970. {
  2971. return d[1] + '/' + d[2] + '/' + d[0];
  2972. }
  2973. }
  2974.  
  2975. HITStorage.indexedDB.create();
  2976.  
  2977. // Backup plan
  2978. //HITStorage.update_date_format(true);
  2979.  
  2980. if (document.location.href.match('https://www.mturk.com/mturk/dashboard'))
  2981. {
  2982. var footer = document.getElementsByClassName('footer_separator')[0];
  2983. if (footer == null)
  2984. return;
  2985.  
  2986. var extra_table = document.createElement('table');
  2987. extra_table.width = '700';
  2988. extra_table.style.boder = '1px solid black';
  2989. extra_table.align = 'center';
  2990. extra_table.cellSpacing = '0px';
  2991. extra_table.cellPadding = '0px';
  2992. var row1 = document.createElement('tr');
  2993. var row2 = document.createElement('tr');
  2994. var td1 = document.createElement('td');
  2995. var content_td = document.createElement('td');
  2996. var whatsthis = document.createElement('a');
  2997.  
  2998. row1.style.height = '25px';
  2999. td1.setAttribute('class', 'white_text_14_bold');
  3000. td1.style.backgroundColor = '#7fb448';//'#7fb4cf';
  3001. td1.style.paddingLeft = '10px';
  3002. td1.innerHTML = 'HIT DataBase' + random_face() + ' ';
  3003. content_td.setAttribute('class', 'container-content');
  3004.  
  3005. whatsthis.href = 'http://userscripts.org/scripts/show/149548';
  3006. whatsthis.setAttribute('class', 'whatis');
  3007. whatsthis.textContent = '(What\'s this?)';
  3008.  
  3009. extra_table.appendChild(row1);
  3010. row1.appendChild(td1);
  3011. td1.appendChild(whatsthis);
  3012. extra_table.appendChild(row2);
  3013. row2.appendChild(content_td);
  3014. footer.parentNode.insertBefore(extra_table, footer);
  3015.  
  3016. var my_bar = document.createElement('div');
  3017. var search_button = document.createElement('button');
  3018. var status_select = document.createElement('select');
  3019. var label = document.createElement('label');
  3020. var label2 = document.createElement('label');
  3021. var input = document.createElement('input');
  3022. var donut_select = document.createElement('select');
  3023. var csv_label = document.createElement('label');
  3024. var csv = document.createElement('input');
  3025.  
  3026. var update_button = document.createElement('button');
  3027. var delete_button = document.createElement('button');
  3028. var pending_button = document.createElement('button');
  3029. var overview_button = document.createElement('button');
  3030. var import_button = document.createElement('button');
  3031. var status_button = document.createElement('button');
  3032.  
  3033. var from_input = document.createElement('input');
  3034. var to_input = document.createElement('input');
  3035. var date_label1 = document.createElement('label');
  3036. var date_label2 = document.createElement('label');
  3037. date_label1.textContent = 'from date ';
  3038. date_label2.textContent = ' to ';
  3039. from_input.setAttribute('id', "from_date");
  3040. to_input.setAttribute('id', "to_date");
  3041. to_input.setAttribute('maxlength', "10");
  3042. from_input.setAttribute('maxlength', "10");
  3043. to_input.setAttribute('size', "10");
  3044. from_input.setAttribute('size', "10");
  3045. from_input.title = 'Date format YYYY-MM-DD\nOr leave empty.';
  3046. to_input.title = 'Date format YYYY-MM-DD\nOr leave empty.';
  3047.  
  3048. var donut_options = [];
  3049. donut_options[0] = document.createElement("option");
  3050. donut_options[1] = document.createElement("option");
  3051. donut_options[2] = document.createElement("option");
  3052. donut_options[0].text = "---";
  3053. donut_options[1].text = "Donut Chart HITS";
  3054. donut_options[2].text = "Donut Chart REWARDS";
  3055. donut_options[0].value = "---";
  3056. donut_options[1].value = "HITS";
  3057. donut_options[2].value = "REWARDS";
  3058.  
  3059. var status_options = [];
  3060. status_options[0] = document.createElement("option");
  3061. status_options[1] = document.createElement("option");
  3062. status_options[2] = document.createElement("option");
  3063. status_options[3] = document.createElement("option");
  3064. status_options[4] = document.createElement("option");
  3065. status_options[5] = document.createElement("option");
  3066. status_options[0].text = "Pending Approval";
  3067. status_options[0].style.color = "orange";
  3068. status_options[1].text = "Rejected";
  3069. status_options[1].style.color = "red";
  3070. status_options[2].text = "Approved - Pending Payment";
  3071. status_options[2].style.color = "green";
  3072. status_options[3].text = "Paid";
  3073. status_options[3].style.color = "green";
  3074. status_options[4].text = "Paid AND Approved";
  3075. status_options[4].style.color = "green";
  3076. status_options[5].text = "ALL";
  3077. status_options[0].value = "Pending Approval";
  3078. status_options[1].value = "Rejected";
  3079. status_options[2].value = "Approved";
  3080. status_options[3].value = "Paid";
  3081. status_options[4].value = "Paid|Approved";
  3082. status_options[5].value = "---";
  3083.  
  3084. search_button.setAttribute('id', "search_button");
  3085. input.setAttribute('id', "search_term");
  3086. status_select.setAttribute('id', "status_select");
  3087. label.setAttribute('id', "status_label");
  3088. donut_select.setAttribute('id', "donut_select");
  3089. delete_button.setAttribute('id', "delete_button");
  3090. update_button.setAttribute('id', "update_button");
  3091. overview_button.setAttribute('id', "overview_button");
  3092. import_button.setAttribute('id', "import_button");
  3093. pending_button.setAttribute('id', "pending_button");
  3094. status_button.setAttribute('id', "status_button");
  3095.  
  3096. my_bar.style.marginLeft = 'auto';
  3097. my_bar.style.marginRight = 'auto';
  3098. my_bar.style.textAlign = 'center';
  3099. label.style.marginLeft = 'auto';
  3100. label.style.marginRight = 'auto';
  3101. label.style.textAlign = 'center';
  3102.  
  3103. var donut = document.createElement('div');
  3104. donut.setAttribute('id', "container");
  3105. donut.style.display = 'none';
  3106.  
  3107. content_td.appendChild(my_bar);
  3108. my_bar.appendChild(delete_button);
  3109. my_bar.appendChild(import_button);
  3110. my_bar.appendChild(update_button);
  3111. my_bar.appendChild(document.createElement("br"));
  3112. my_bar.appendChild(pending_button);
  3113. my_bar.appendChild(overview_button);
  3114. my_bar.appendChild(status_button);
  3115. my_bar.appendChild(document.createElement("br"));
  3116. my_bar.appendChild(donut_select);
  3117. my_bar.appendChild(status_select);
  3118. my_bar.appendChild(label2);
  3119. my_bar.appendChild(input);
  3120. my_bar.appendChild(search_button);
  3121. my_bar.appendChild(document.createElement("br"));
  3122. my_bar.appendChild(date_label1);
  3123. my_bar.appendChild(from_input);
  3124. my_bar.appendChild(date_label2);
  3125. my_bar.appendChild(to_input);
  3126. my_bar.appendChild(csv_label);
  3127. my_bar.appendChild(csv);
  3128. my_bar.appendChild(document.createElement("br"));
  3129. my_bar.appendChild(label);
  3130. my_bar.appendChild(document.createElement("br"));
  3131. (footer.parentNode).insertBefore(donut, footer);
  3132.  
  3133. my_bar.style.textAlign = "float";
  3134. search_button.textContent = "Search";
  3135. search_button.title = "Search from local HIT database\nYou can set time limits and export as CSV-file";
  3136. label2.textContent = " HITs matching: ";
  3137. input.value = "";
  3138.  
  3139. label.textContent = "Search powered by non-amazonian script monkeys";
  3140.  
  3141. for (var i=0; i<status_options.length; i++)
  3142. status_select.options.add(status_options[i]);
  3143. for (var i=0; i<donut_options.length; i++)
  3144. donut_select.options.add(donut_options[i]);
  3145.  
  3146. update_button.title = "Fetch status pages and copy HITs to local indexed database.\nFirst time may take several minutes!";
  3147. update_button.textContent = "Update database";
  3148. update_button.style.color = 'green';
  3149. update_button.style.margin = '5px 5px 5px 5x';
  3150. delete_button.textContent = "Delete database";
  3151. delete_button.style.color = 'red';
  3152. delete_button.style.margin = '5px 5px 5px 5px';
  3153. delete_button.title = "Delete Local DataBase!";
  3154. import_button.textContent = "Import";
  3155. import_button.style.margin = '5px 5px 5px 5px';
  3156. import_button.title = "Import HIT data from exported CSV-file";
  3157. overview_button.textContent = "Requester Overview";
  3158. overview_button.style.margin = '0px 5px 5px 5px';
  3159. overview_button.title = "Summary of all requesters you have worked for\nYou can set time limit and export as CSV-file";
  3160. pending_button.textContent = "Pending Overview";
  3161. pending_button.style.margin = '0px 5px 5px 5px';
  3162. pending_button.title = "Summary of all pending HITs\nYou can export as CSV-file";
  3163. status_button.textContent = "Daily Overview";
  3164. status_button.style.margin = '0px 5px 5px 5px';
  3165. status_button.title = "Summary of each day you have worked on MTurk\nYou can set time limit and export as CSV-file";
  3166.  
  3167. pending_button.addEventListener("click", HITStorage.show_pendings, false);
  3168. overview_button.addEventListener("click", HITStorage.show_overview, false);
  3169. search_button.addEventListener("click", HITStorage.start_search, false);
  3170. update_button.addEventListener("click", HITStorage.update_database, false);
  3171. delete_button.addEventListener("click", delete_func(), false);
  3172. import_button.addEventListener("click", import_func(), false);
  3173. status_button.addEventListener("click", HITStorage.show_status, false);
  3174.  
  3175. csv_label.textContent = 'export CSV';
  3176. csv_label.title = 'Export results as comma-separated values';
  3177. csv_label.style.verticalAlign = 'middle';
  3178. csv_label.style.marginLeft = '50px';
  3179. csv.title = 'Export results as comma-separated values';
  3180. csv.setAttribute('type', 'checkbox');
  3181. csv.setAttribute('id', 'export_csv');
  3182. csv.style.verticalAlign = 'middle';
  3183.  
  3184. from_input.value = '';
  3185. to_input.value = '';
  3186.  
  3187. var table = document.getElementById('lnk_show_earnings_details');
  3188. if (table != null)
  3189. {
  3190. table = table.parentNode.parentNode.parentNode.parentNode;
  3191. var pending_tr = document.createElement('tr');
  3192. var pending_td1 = document.createElement('td');
  3193. var pending_td2 = document.createElement('td');
  3194. var today_tr = document.createElement('tr');
  3195. var today_td1 = document.createElement('td');
  3196. var today_td2 = document.createElement('td');
  3197.  
  3198. pending_tr.setAttribute('class', 'even');
  3199. pending_td1.setAttribute('class', 'metrics-table-first-value');
  3200. pending_td1.setAttribute('id', 'pending_earnings_header');
  3201. pending_td2.setAttribute('id', 'pending_earnings_value');
  3202. today_tr.setAttribute('class', 'odd');
  3203. today_td1.setAttribute('class', 'metrics-table-first-value');
  3204. today_td1.setAttribute('id', 'projected_earnings_header');
  3205. today_td2.setAttribute('id', 'projected_earnings_value');
  3206.  
  3207. pending_tr.appendChild(pending_td1);
  3208. pending_tr.appendChild(pending_td2);
  3209. today_tr.appendChild(today_td1);
  3210. today_tr.appendChild(today_td2);
  3211. table.appendChild(pending_tr);
  3212. table.appendChild(today_tr);
  3213.  
  3214. pending_td1.style.borderTop = '1px dotted darkgrey';
  3215. pending_td2.style.borderTop = '1px dotted darkgrey';
  3216. today_td1.style.borderBottom = '1px dotted darkgrey';
  3217. today_td2.style.borderBottom = '1px dotted darkgrey';
  3218.  
  3219. today_td1.title = 'This value can be inaccurate if HITDB has not been updated recently';
  3220. pending_td1.title = 'This value can be inaccurate if HITDB has not been updated recently';
  3221.  
  3222. if (localStorage['HITDB UPDATED'] === undefined)
  3223. pending_td1.textContent = 'Pending earnings';
  3224. else
  3225. pending_td1.textContent = 'Pending earnings (HITDB updated: ' + localStorage['HITDB UPDATED'] + ')';
  3226. today_td1.innerHTML = 'Projected earnings for today &nbsp;&nbsp;';
  3227. today_td2.textContent = '$-.--';
  3228. pending_td2.textContent = '$-.--';
  3229.  
  3230.  
  3231. var e = document.getElementById('user_activities.date_column_header.tooltip').parentNode.parentNode.childNodes[2].childNodes[1].childNodes[1];
  3232. var today = null;
  3233. if (e != null && e.textContent.trim() == 'Today') {
  3234. today = convert_date(e.href.slice(-8));
  3235. HITStorage.indexedDB.get_todays_projected_earnings(today);
  3236. }
  3237. HITStorage.indexedDB.get_pending_approvals();
  3238. HITStorage.indexedDB.get_pending_payments();
  3239.  
  3240. var target = document.createElement('span');
  3241. target.setAttribute('id', 'my_target');
  3242. target.textContent = 'click here to set your target';
  3243. target.style.fontSize = 'small';
  3244. target.style.color = 'blue';
  3245. today_td1.appendChild(target);
  3246. target.addEventListener("click", set_target_func(today), false);
  3247. }
  3248. }
  3249. else if (document.location.href.match('https://www.mturk.com/mturk/preview'))
  3250. {
  3251. var table = document.getElementById('requester.tooltip');
  3252. if (table == null)
  3253. return;
  3254. table = table.parentNode.parentNode.parentNode;
  3255. var title = table.parentNode.parentNode.parentNode.parentNode.getElementsByTagName('div')[0].textContent.trim();
  3256.  
  3257. var extra_row = document.createElement('tr');
  3258. var td_1 = document.createElement('td');
  3259. var td_2 = document.createElement('td');
  3260.  
  3261. var requesterId = document.getElementsByName('requesterId')[0].value;
  3262. var auto_approve = parseInt(document.getElementsByName('hitAutoAppDelayInSeconds')[0].value);
  3263.  
  3264. var buttons = [];
  3265. var b = ['Requester', 'HIT Title'];
  3266. for (var i=0; i<b.length; i++)
  3267. {
  3268. buttons[i] = document.createElement('button');
  3269. buttons[i].textContent = b[i];
  3270. buttons[i].id = b[i] + 'Button' + i;
  3271. buttons[i].style.fontSize = '10px';
  3272. buttons[i].style.height = '18px';
  3273. buttons[i].style.width = '80px';
  3274. buttons[i].style.border = '1px solid';
  3275. buttons[i].style.paddingLeft = '3px';
  3276. buttons[i].style.paddingRight = '3px';
  3277. buttons[i].style.backgroundColor = 'lightgrey';
  3278. buttons[i].setAttribute('form', 'NOThitForm');
  3279. td_1.appendChild(buttons[i]);
  3280. }
  3281. buttons[0].title = 'Search requester ' + requesterId + ' from HIT database';
  3282. buttons[1].title = 'Search title \'' + title + '\' from HIT database';
  3283.  
  3284. HITStorage.indexedDB.colorRequesterButton(requesterId, buttons[0]);
  3285. HITStorage.indexedDB.colorTitleButton(title, buttons[1]);
  3286. buttons[0].addEventListener("click", search_func(requesterId, 'requesterId'), false);
  3287. buttons[1].addEventListener("click", search_func(title, 'title'), false);
  3288.  
  3289. td_2.innerHTML = '<span class="capsule_field_title">Auto-Approval:</span>&nbsp&nbsp' + HITStorage.formatTime(auto_approve*1000) + '';
  3290. td_1.colSpan = '3';
  3291. td_2.colSpan = '8';
  3292.  
  3293. extra_row.appendChild(td_1);
  3294. extra_row.appendChild(td_2);
  3295. table.appendChild(extra_row);
  3296. }
  3297. else
  3298. {
  3299. for (var item=0; item<10; item++) {
  3300. var tooltip = document.getElementById('requester.tooltip--' + item);
  3301. if (tooltip == null)
  3302. break; // no need to continue
  3303. var titleElement = document.getElementById('capsule' + item + '-0');
  3304. var emptySpace = tooltip.parentNode.parentNode.parentNode.parentNode.parentNode;
  3305.  
  3306. var hitItem = tooltip.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode;//.parentNode;
  3307.  
  3308. var requesterLabel = tooltip.parentNode;
  3309. var requesterId = tooltip.parentNode.parentNode.getElementsByTagName('a');
  3310. var title = titleElement.textContent.trim();
  3311.  
  3312. requesterId = get_requester_id(requesterId[1].href);
  3313.  
  3314. var buttons = [];
  3315. var row = document.createElement('tr');
  3316. var div = document.createElement('div');
  3317. emptySpace.appendChild(row);
  3318. row.appendChild(div);
  3319.  
  3320. /* Turkopticon link next to requester name */
  3321. //to_link = document.createElement('a');
  3322. //to_link.textContent = ' TO ';
  3323. //to_link.href = 'https://turkopticon.differenceengines.com/' + requesterId;
  3324. //to_link.target = '_blank';
  3325. //to_link.title = requesterId + ' on Turkopticon';
  3326. //tooltip.parentNode.parentNode.appendChild(to_link);
  3327. /*-----------------------------------------*/
  3328.  
  3329. HITStorage.indexedDB.blockHITS(requesterId, title, hitItem, titleElement);
  3330.  
  3331. var b = ['R', 'T', 'N', 'B'];
  3332. for (var i=0; i<b.length; i++)
  3333. {
  3334. buttons[i] = document.createElement('button');
  3335. buttons[i].textContent = b[i];
  3336. buttons[i].id = b[i] + 'Button' + i;
  3337. buttons[i].style.height = '18px';
  3338. buttons[i].style.fontSize = '10px';
  3339. buttons[i].style.border = '1px solid';
  3340. buttons[i].style.paddingLeft = '3px';
  3341. buttons[i].style.paddingRight = '3px';
  3342. buttons[i].style.backgroundColor = 'lightgrey';
  3343. div.appendChild(buttons[i]);
  3344. }
  3345. buttons[0].title = 'Search requester ' + requesterId + ' from HIT database';
  3346. buttons[1].title = 'Search title \'' + title + '\' from HIT database';
  3347. buttons[2].title = 'Add a requester note';
  3348. buttons[3].title = '"Block" requester';
  3349.  
  3350. var notelabel = document.createElement('label');
  3351. notelabel.textContent = '';
  3352. notelabel.id = b[i] + 'notelabel' + item;
  3353. notelabel.style.height = '18px';
  3354. notelabel.style.fontSize = '10px';
  3355. notelabel.style.marginLeft = '10px';
  3356. notelabel.style.padding = '1px';
  3357. notelabel.style.backgroundColor = 'transparent';
  3358. HITStorage.indexedDB.updateNoteButton(requesterId, notelabel);
  3359. div.appendChild(notelabel);
  3360.  
  3361. HITStorage.indexedDB.colorRequesterButton(requesterId, buttons[0]);
  3362. HITStorage.indexedDB.colorTitleButton(title, buttons[1]);
  3363. buttons[0].addEventListener("click", search_func(requesterId, 'requesterId'), false);
  3364. buttons[1].addEventListener("click", search_func(title, 'title'), false);
  3365. buttons[2].addEventListener("click", note_func(requesterId, notelabel), false);
  3366. buttons[3].addEventListener("click", block_func(requesterId, title, hitItem), false);
  3367.  
  3368. div.style.margin = "0px";
  3369.  
  3370. buttons[2].style.visibility = "hidden"; // "visible"
  3371. buttons[2].parentNode.addEventListener("mouseover", visible_func(buttons[2], true), false);
  3372. buttons[2].parentNode.addEventListener("mouseout", visible_func(buttons[2], false), false);
  3373. buttons[2].addEventListener("mouseout", visible_func(buttons[2], false), false);
  3374. buttons[3].style.visibility = "hidden"; // "visible"
  3375. buttons[3].parentNode.addEventListener("mouseover", visible_func(buttons[3], true), false);
  3376. buttons[3].parentNode.addEventListener("mouseout", visible_func(buttons[3], false), false);
  3377. buttons[3].addEventListener("mouseout", visible_func(buttons[3], false), false);
  3378. }
  3379.  
  3380. var auto_button = document.createElement('button');
  3381. auto_button.setAttribute('id', 'auto_button');
  3382. auto_button.title = 'HIT DataBase Auto Update\nAutomagically update newest HITs to database when reloading this page';
  3383.  
  3384. if (localStorage['HITDB AUTO UPDATE'] === undefined)
  3385. {
  3386. auto_button.textContent = 'Auto update ?';
  3387. auto_button.style.color = 'red';
  3388. }
  3389. else if (localStorage['HITDB AUTO UPDATE'] == 'ON')
  3390. {
  3391. auto_button.textContent = 'Auto Update is ON';
  3392. auto_button.style.color = 'green';
  3393. }
  3394. else
  3395. {
  3396. auto_button.textContent = 'Auto Update is OFF';
  3397. auto_button.style.color = 'red';
  3398. }
  3399.  
  3400. var element = document.body.childNodes[13].childNodes[3].childNodes[1].childNodes[0].childNodes[5];
  3401. element.insertBefore(auto_button, element.firstChild);
  3402. auto_button.addEventListener("click", auto_update_func(), false);
  3403.  
  3404. setTimeout(HITStorage.getLatestHITs, 100);
  3405. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement