Warning: fopen(/www/sites/update.greasyfork.icu/index/store/temp/02deeb3e0b47a5edcbcb73d0c4ab8b6f.js): failed to open stream: No space left on device in /www/sites/update.greasyfork.icu/index/scriptControl.php on line 65
// ==UserScript==
// @name Turkmaster (Mturk)
// @namespace https://greasyfork.org/users/12875
// @author DonovanM
// @description A fork of DonovanM's Turkmaster, now with watcher groups and other new features. A page-monitoring web app for Mturk (Mechanical Turk) designed to make turking more efficient. Easily monitor mturk search pages and requesters and Auto-Accept the HITs you missed.
// @include https://www.mturk.com/mturk/*
// @version 1.3.4e
// @require https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
// @require https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js
// @grant GM_getValue
// @grant GM_setValue
// @downloadURL https://update.greasyfork.icu/scripts/11373/Turkmaster%20%28Mturk%29.user.js
// @updateURL https://update.greasyfork.icu/scripts/11373/Turkmaster%20%28Mturk%29.meta.js
// ==/UserScript==
// Incorporates additions by Kevin Schumacher (tubedogg on MTG/GreasyFork):
// - Basic support for groups
// - Stop group if one PANDA catches
// - Start with group (click on any member of the group to start them all)
// - "Last Found" date (hover over last checked time at bottom-right of each watcher)
// - Tracks date watcher was added (for watchers added from this point forward - also found by hovering over last checked time)
// - Deselect all (from gear/settings menu)
// - New option: "Show other page" - load something else where the dashboard normally is (specify URL in gear/settings menu)
// - New option: Force TurkMaster URL: only load if ?turkmaster is added to dashboard URL e.g. if you go to http://www.mturk.com/mturk/dashboard it would not load, but if you go to http://www.mturk.com/mturk/dashboard?turkmaster it would do so. Useful if you normally keep the dashboard open in another tab/window/browser so it can auto-refresh, and especially so when paired with the "Show other page" setting
var settings = (function() {
var LOCAL_STORAGE = "turkmaster_settings";
var pub = {
sound : true,
animation : true,
preloadHits : false,
volume : 50,
notifications : true,
alertOnly : false,
fontSize : 10,
typeface : "Oxygen",
desktopNotifications : false,
canHide : false,
customURL : '',
forceUniqueURL: false
};
_load();
function _setfontSize(val) {
if (val >= 5 && val <= 20) {
pub.fontSize = val;
$("#dispatcher div").css("font-size", val + "pt");
$(".notification_panel p").css("font-size", val + "pt");
$("#settingsDialog, #settingsDialog div, #settingsDialog li, #settingsDialog input, #settingsDialog button").css("font-size", val + "pt");
_save();
}
}
function _setDesktopNotifications(val, callback) {
if (val) {
requestDesktopNotifications(function(isPermitted) {
callback(isPermitted);
pub.desktopNotifications = isPermitted;
_save();
});
pub.desktopNotifications = false;
} else {
pub.desktopNotifications = false;
}
_save();
}
function _setVolume(val) {
if (val >= 0 && val <= 100) {
Sound.setVolume(val);
pub.volume = val;
_save();
}
}
function _setCustomFrameURL(val) {
var urlregex = new RegExp(
"^(http|https)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$");
if (urlregex.test(val) && $("#externalFrame").length) {
$("#externalFrame").src = val;
pub.customURL = val;
_save();
} else if (urlregex.test(val) || (val === '' && pub.customURL !== '')) {
// save settings with the new URL (blank or otherwise) and reload the page to add/remove the iframe
pub.customURL = val;
_save();
location.reload();
} else if (!urlregex.test(val)) {
alert('The URL entered is not valid. Please try again. If you are trying to revert to showing the MTurk dashboard, please empty the URL box.');
}
}
function _save() {
// localStorage.setItem(LOCAL_STORAGE, JSON.stringify(pub));
GM_setValue(LOCAL_STORAGE, JSON.stringify(pub));
}
function _load() {
var values = GM_getValue(LOCAL_STORAGE);
if (typeof values === 'undefined')
values = localStorage.getItem(LOCAL_STORAGE);
if (values) {
values = JSON.parse(values);
for (i in values)
pub[i] = values[i];
}
}
pub.setfontSize = _setfontSize;
pub.setVolume = _setVolume;
pub.setDesktopNotifications = _setDesktopNotifications;
pub.setCustomFrameURL = _setCustomFrameURL;
pub.save = _save;
return pub;
}());
var pageType = {
MAIN : true, // This is so remote watcher requests don't add new watchers to multiple pages and cause mturk errors.
DASHBOARD : false,
HIT : false,
REQUESTER : false,
SEARCH : false
};
var loadError = false;
var wasViewed = false;
var dispatch;
var notificationPanel;
if(!('contains' in String.prototype)) {
String.prototype.contains = function(str, startIndex) {
return -1 !== String.prototype.indexOf.call(this, str, startIndex);
};
}
$(document).ready(function(){
console.log('Ready');
checkPageType();
loadFonts();
if (pageType.DASHBOARD) {
dispatch = new Dispatch();
DispatchUI.create(dispatch);
createDetailsPanel();
IgnoreList.init();
if (settings.preloadHits)
loadDefaultWatchers();
else
dispatch.load();
requestMain();
preloadImages();
addFormStyle();
}
if (pageType.HIT || pageType.REQUESTER || pageType.SEARCH)
addWatchButton();
notificationPanel = new NotificationPanel();
// Listen to messages
window.addEventListener('storage', onStorageEvent, false);
});
$(window).on('beforeunload', function() {
if (pageType.DASHBOARD && pageType.MAIN) {
dispatch.save();
}
});
function loadFonts() {
WebFont.load({
google: { families: [ 'Oxygen:400,700:latin', 'Droid Sans Mono' ] }
});
}
function onStorageEvent(event) {
if (event.key.substring(0,13) === "notifier_msg_")
onMessageReceived(event.key.substring(13), JSON.parse(event.newValue).content);
}
function checkPageType() {
// Dashboard, hit, requester, search
if (document.URL.search("https://www.mturk.com/mturk/dashboard") > -1 && ((document.URL.search("turkmaster") > -1 && settings.forceUniqueURL) || !settings.forceUniqueURL)) {
pageType.DASHBOARD = true;
}
else if (document.URL.match(/https:\/\/www.mturk.com\/mturk\/(preview|accept).+groupId=.*/) !== null)
{
pageType.HIT = true;
}
else if (document.URL.match(/requesterId=([A-Z0-9]+)/) !== null)
{
pageType.REQUESTER = true;
}
else if (document.URL.match(/(searchbar|findhits)/) !== null)
{
pageType.SEARCH = true;
}
}
function requestMain() {
sendMessage({ header: "request_main" });
}
function preloadImages() {
var images = [
'https://i.imgur.com/guRzYEL.png',
'https://i.imgur.com/5snaSxU.png',
'https://i.imgur.com/VTHXHI4.png',
'https://i.imgur.com/peEhuHZ.png'
];
$(images).each(function(){
$('')[0].src = this;
});
}
var SettingsDialog = function() {
var DOMElement,
TOGGLE = '';
function _show() {
if (!DOMElement)
_createDOMElement()
_getSettings();
DOMElement.show();
$(window).on('click', _handleWindowClick);
}
function _isVisible() {
if (DOMElement)
return DOMElement.is(":visible");
else
return false;
}
function _getSettings() {
if (settings.sound) DOMElement.find("#soundSettings > .on_off").addClass("on");
DOMElement.find("#volume input").val(settings.volume);
if (settings.notifications) DOMElement.find("#notificationSettings > .on_off").addClass("on");
if (settings.desktopNotifications) DOMElement.find("#desktopNotifications .on_off").addClass("on");
if (settings.alertOnly) DOMElement.find("#alertOnly .on_off").addClass("on");
if (settings.canHide) DOMElement.find("#hideable .on_off").addClass("on");
DOMElement.find("#fontSize input").val(settings.fontSize);
DOMElement.find("#typeface input").val(settings.typeface);
if (settings.customURL) DOMElement.find("#customURL input").val(settings.customURL);
if (settings.forceUniqueURL) DOMElement.find("#forceUniqueURL .on_off").addClass("on");
if (settings.stopCaptcha) DOMElement.find("#stopCaptcha .on_off").addClass("on");
}
function _save() {
}
function _cancel() {
DOMElement.hide();
}
function _createDOMElement() {
_addStyle();
DOMElement = $('
Settings
').append(
$('
General
\
\
' + TOGGLE + 'Stop upon encountering captcha
\
Start all non-HIT (PANDA) watchers
\
Stop all non-HIT (PANDA) watchers
\
\
'),
$('
' + TOGGLE + '
Sound
\
Volume (0 - 100)
\
'),
$('
' + TOGGLE + '
Notifications
\
\
' + TOGGLE + 'Desktop Notifications
\
\
\
'),
$('
Font
\
\
Size (pt)
\
\
\
'),
$('
User Interface
\
\
' + TOGGLE + 'Hideable
\
' + TOGGLE + 'Only load when ?turkmaster is appended to URL
\
Enter custom URL for right side of page
\
\
'),
$('
Backup
\
\
Export
\
Import
\
\
'),
$('
Deselect All
\
\
Deselect All
\
\
')
);
_addHandlers();
$("body").append(DOMElement);
}
function _addHandlers() {
DOMElement.on('click', function(e) {
if (e.target.tagName === "BUTTON" || e.target.parentNode.tagName === "BUTTON")
_handleButtonToggle(e);
});
DOMElement.on('change', _handleInputChange);
}
function _handleWindowClick(e) {
var target = e.target;
if (!DOMElement.is(target) && DOMElement.has(target).length === 0 && $("#settings img").get(0) !== target) {
_cancel();
$(window).off('click', _handleWindowClick);
}
}
function _handleInputChange(e) {
var target = $(e.target),
value = target.val(),
id = target.parent().attr('id');
if (id === "volume")
settings.setVolume(value);
else if (id === "fontSize")
settings.setfontSize(value);
else if (id === "typeface")
settings.typeface = value;
else if (id === "customURL")
settings.setCustomFrameURL(value);
}
function _handleButtonToggle(e) {
e.preventDefault();
// Chrome returns the span as the target while FF returns the button
var target = (e.target.tagName === "BUTTON") ? $(e.target) : $(e.target).parent(),
value = target.hasClass("on"),
id = target.parent().attr('id');
if (id !== "desktopNotifications") {
if (target.hasClass("on")) {
target.removeClass("on");
value = false;
} else {
target.addClass("on");
value = true;
}
}
if (id === "soundSettings") {
settings.sound = value;
} else if (id === "notificationSettings") {
settings.notifications = value;
} else if (id === "desktopNotifications") {
if (value)
target.removeClass("on");
// Desktop notification requests require user action so we need a callback
// for when the user responds.
settings.setDesktopNotifications(!value, function(isPermitted) {
if (isPermitted) {
target.addClass("on");
} else {
target.removeClass("on");
console.error("Desktop notifications are blocked.");
}
});
} else if (id === "alertOnly") {
settings.alertOnly = value;
} else if (id === "hideable") {
settings.canHide = value;
setTimeout(function () { DispatchUI.setHide() }, 50);
} else if (id === "forceUniqueURL") {
settings.forceUniqueURL = value;
} else if (id === "stopCaptcha") {
settings.stopCaptcha = value;
}
settings.save();
if (id === "export") {
_showExport();
} else if (id === "import") {
_showImport();
}
if (id === "deselect_all") {
_deselectAll();
}
if (id === "startNonHitWatchers") {
_startNonHitWatchers();
}
if (id === "stopNonHitWatchers") {
_stopNonHitWatchers();
}
}
function _showExport() {
var div = $('
Export Watchers
Copy the text below. (Triple-click to highlight all)
' + dispatch.exportWatchers() + '
');
$('')
.click(function() { div.remove(); })
.appendTo(div);
div.appendTo($("body"));
}
function _showImport() {
var div = $('
")
.attr('rowspan', '2')
.attr('align', 'center')
);
location.append(newCell);
location.parents("td table").eq(0).attr('width', '350');
location = location.children('td').eq(1);
}
var nextRowUp = location.parents("table").eq(0).children().eq(0).children().eq(0).children().eq(1);
nextRowUp.remove("img");
nextRowUp.text('Want to watch this HIT?').attr('align', 'center').attr('width', '250');
}
else if ($("body > form:nth-child(7) > table:nth-child(9) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(2) > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(1)").length)
{
location = $("body > form:nth-child(7) > table:nth-child(9) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(2) > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(1)");
}
} else if (pageType.REQUESTER || pageType.SEARCH) {
if ($(".title_orange_text_bold").length)
location = $(".title_orange_text_bold");
else
location = $(".error_title");
}
location.append(button);
addFormStyle();
}
function addFormStyle() {
addStyle("\
#add_watcher_form {\
position: fixed;\
width: 600px;\
top: 50px;\
left: 50%;\
margin: 50px -300px;\
background-color: #fcfcfe;\
border: 1px solid #aaa;\
border-radius: 1px;\
text-align: center;\
}\
#add_watcher_form h3 {\
font: 12pt Verdana;\
margin: 0 0 15px;\
background-color: #def;\
background-color: rgba(230, 230, 230, 1);\
padding: 3px;\
color: #111;\
}\
#add_watcher_form input[type='text'] {\
font: 10pt Verdana;\
margin: 10px 20px 0 0;\
}\
#add_watcher_form input[type='button'] {\
margin-top: 20px;\
font: 9pt Verdana;\
color: #444;\
background-color: #eee;\
border: 1px solid #999;\
}\
#add_watcher_form input[type='button']:hover {\
background-color: #9df;\
}\
#add_watcher_form p {\
margin: 10px;\
font: 11pt Verdana;\
}\
#add_watcher_form .form_buttons input {\
margin: 5px;\
}\
.watcher_button { display: inline; }\
.watcher_button a {\
text-decoration: none;\
font-weight: normal;\
background-color: #CECECE;\
color: white;\
padding: 3px 10px;\
border-radius: 8px;\
font-family: 'Oxygen', verdana, sans-serif;\
transition: background-color 0.4s;\
}\
.watcher_button a:hover { background-color: #55B8EA }\
.error_title .watcher_button { display: block; margin: 15px }\
");
}
function addStyle(styleText) {
var style = '';
$("head").append(style);
}
function loadDefaultWatchers() {
// Add a few watchers. Won't be done like this in the future
dispatch.isLoading = true;
dispatch.add(new Watcher({
id: "https://www.mturk.com/mturk/searchbar?selectedSearchType=hitgroups&searchWords=survey&minReward=0.25&qualifiedFor=on&x=13&y=10",
time: 60000,
type: 'url',
name: "Surveys $0.25 and up"})); //$.25 surveys
dispatch.add(new Watcher({
id: "https://www.mturk.com/mturk/searchbar?selectedSearchType=hitgroups&searchWords=survey&minReward=0.75&qualifiedFor=on&x=13&y=10",
time: 60000,
type: 'url',
name: "Surveys $0.75 and up"})); //$.75 surveys
dispatch.add(new Watcher({
id: "A11L036EBWKONR",
time: 120000,
type: 'requester',
name: "Project Endor",
option: {alert:true}})); // Endor
dispatch.add(new Watcher({
id: "A6YG5FKV2TAVC",
time: 300000,
type: 'requester',
name: "Agent Agent",
option: {alert:true}})); // Agent Agent
dispatch.add(new Watcher({
id: "A2SUM2D7EOAK1T",
time: 120000,
type: 'requester',
name: 'Crowdsource'}));
dispatch.add(new Watcher({
id: "AKEBQYX32KM19",
time: 120000,
type: 'requester',
name: 'Crowdsurf Support'}));
dispatch.add(new Watcher({
id: "https://www.mturk.com/mturk/searchbar?selectedSearchType=hitgroups&searchWords=transcri&minReward=0.00&qualifiedFor=on&x=0&y=0",
time: 60000,
type: 'url',
name: "Transcription HITs"})); // Transcription HITs
dispatch.isLoading = false;
dispatch.save();
}
function onMessageReceived(header, message) {
if (pageType.DASHBOARD && pageType.MAIN) {
switch(header) {
case 'notification_viewed' :
wasViewed = true;
break;
case 'add_watcher' :
var msg = message;
dispatch.add(new Watcher({
id : msg.id,
time : msg.duration,
type : msg.type,
groupid: msg.groupid,
name : msg.name,
option : {
auto: msg.auto,
stopOnCatch: msg.stopOnCatch,
stopGroup: msg.stopGroup,
startGroup: msg.startGroup,
alert: msg.alert
}
}, true)).start();
break;
case 'ignore_requester' :
console.log("Ignore requester", message);
IgnoreList.add(IgnoreList.REQUESTER, message.id);
break;
case 'mute_hit' :
var id = message.id;
IgnoreList.add(IgnoreList.HIT, id);
break;
case 'unmute_hit' :
var id = message.id;
IgnoreList.remove(IgnoreList.HIT, id);
break;
case 'request_main' :
sendMessage({ header: "request_denied" });
break;
case 'request_denied' :
dispatch.onRequestMainDenied();
break;
case 'show_main' :
alert("Showing the main dashboard. (Close this Mturk page to establish a notifier in a different tab or window)");
break;
}
} else if (!pageType.DASHBOARD || (pageType.DASHBOARD && !pageType.MAIN)) {
switch(header) {
case 'new_hits' :
var hits = message.hits;
// Re-create the hits so their methods can be used
for(var i = hits.length; i--;) hits[i] = new Hit(hits[i]);
// Show the hits and let the dashboard know it was seen
if (document.hasFocus())
sendMessage({ header: "notification_viewed" });
notificationPanel.add(new NotificationGroup({ title: message.title, hits: hits, url: message.url }));
break;
case 'captcha' :
if (document.hasFocus())
alert("Captcha Alert!");
break;
case 'turkopticon' :
// This needs a more elegant solution. If the servers start lagging we might be
// using addTO() for the wrong group. It won't show the TO for the wrong requester,
// though, so it's safe to use for now. It's just that some ratings could be missing.
notificationPanel.notifications[notificationPanel.notifications.length - 1].addTO(message);
break;
}
}
}
function sendMessage(message) {
var header = message.header;
var content = message.content || new Date().getTime(); // Make the content a timestamp when there's no actual content
var timestamp = message.timestamp && new Date().getTime(); // If wanted, adds a timestamp to the content so messages with the same content will still trigger the event consecutively
localStorage.setItem('notifier_msg_' + header, JSON.stringify({ content: content, timestamp: timestamp}));
}
function sendDesktopNotification(hits, watcher) {
// Let's check if the user is okay to get some notification
if (Notification.permission === "granted" && settings.desktopNotifications) {
// If the user isn't on a mturk page to receive a rich notification, then send a web notification
if (!wasViewed) {
var bodyText = "";
for (var i = 0, len = hits.length; i < len; i++)
bodyText += "\n" + hits[i].title.substring(0, 40) + ((hits[i].title.length > 40) ? "..." : "") + "\n" + hits[i].reward + "\n";
var notification = new Notification(
watcher.name,
{
body: bodyText,
icon: "http://halfelf.org/wp-content/uploads/sites/2/2012/06/amazon_icon.png"
}
);
notification.onclick = function() {
window.focus(); // Focus this window (dashboard)
this.close(); // Closes the notification
showDetailsPanel(watcher); // Opens the details panel for whatever watcher the notification was for
};
notification.onshow = function() { setTimeout(function() { notification.close() }, 5000) }; // Need to set a close time for Chrome
}
}
}
function requestDesktopNotifications(callback) {
// Let's check if the browser supports notifications
if (!("Notification" in window)) {
alert("This browser does not support desktop notification");
} else {
window.Notification.requestPermission(function (permission) {
// Whatever the user answers, we make sure Chrome stores the information
if(!('permission' in Notification))
window.Notification.permission = permission;
// If the user is okay, let's create a notification
if (permission === "granted") {
var notification = new window.Notification("Desktop notifications enabled.");
notification.onshow = function() { setTimeout(function() { notification.close() }, 5000) };
callback(true);
} else {
callback(false);
}
});
}
}
function Hit(attrs) {
attrs = attrs || {};
this.id = attrs.id;
this.uid = attrs.uid;
this.isAutoAccept = attrs.isAutoAccept || false;
this.requester = attrs.requester;
this.requesterID = attrs.requesterID;
this.url = attrs.url;
this.title = attrs.title;
this.reward = attrs.reward;
this.description = attrs.description;
this.available = attrs.available;
this.time = attrs.time;
this.isQualified = (typeof attrs.isQualified !== 'undefined') ? attrs.isQualified : true;
this.canPreview = (typeof attrs.canPreview !== 'undefined') ? attrs.canPreview : true;
}
Hit.prototype.getURL = function(type) {
switch(type) {
case 'preview':
return "https://www.mturk.com/mturk/preview?groupId=" + this.id;
case 'accept' :
return (this.isQualified) ? "https://www.mturk.com/mturk/previewandaccept?groupId=" + this.id : null;
case 'auto' :
return "https://www.mturk.com/mturk/previewandaccept?groupId=" + this.id + "&autoAcceptEnabled=true";
case 'view' :
return "https://www.mturk.com/mturk/continue?hitId=" + this.uid;
case 'return' :
// This will need to be changed. It's the same as 'view' until more testing is done on AMT's return functionality
return "https://www.mturk.com/mturk/preview?hitId=" + this.uid;
default:
return "";
}
};
// Returns the position of a hit in a hit array by its ID
Hit.indexOf = function(hitId, hits) {
for (var i = 0, len = hits.length; i < len; i++) {
if (hitId === hits[i].id)
return i;
}
return -1;
};
// Returns true if there are multiple hits in the array and all of the hits are from the same requester
Hit.isSameRequester = function(hits) {
if (hits.length > 1) {
var compareRequester = hits[0].requester;
for (var i = 1, len = hits.length; i < len; i++) {
if (compareRequester !== hits[i].requester)
return false;
}
return true;
} else {
return false;
}
};
// Returns a list of unique requester IDs from an array of hits
Hit.getUniqueReqeusters = function(hits) {
var ids = [];
for (var i = 0, len = hits.length; i < len; ++i) {
var id = hits[i].requesterID;
if (ids.indexOf(id) === -1)
ids.push(id);
}
return ids;
};
// Message object (Not used)
function Message() {
/* Status (changed): Unchanged, Added, Removed, Count
We should mark each Hit in the message with what has changed. The count change should be sent with this.
The message will also tell the client whether or not to pop-up the notification. */
}
// The details panel for each watcher
function createDetailsPanel() {
var div = $('
').attr('id', 'details_panel').addClass('notification_panel');
addStyle("#details_panel {\
background-color: #fff;\
position: absolute;\
top: 0px;\
margin-left: 1px;\
left: 270px;\
width: 500px;\
border: 1px solid #e3e3e3;\
border-radius: 0 0 3px 0;\
border-width: 0 1px 1px 0;\
transition: left 0.5s ease;\
display: none }\
#details_panel h4 { display: none }\
#details_panel.left { left: 30px }");
$(div).mouseleave(function() { $(this).hide() });
$("body").append(div);
}
var lastWatcher = "";
function showDetailsPanel(watcher) {
var panel = $("#details_panel");
var group;
// Only change the panel contents if it's a different watcher or the same one, but updated
if (watcher !== lastWatcher || (watcher === lastWatcher && watcher.isUpdated)) {
$("*", panel).remove();
if (watcher.lastHits.length > 0) {
group = new NotificationGroup({ hits: watcher.lastHits, isSticky: false, watcher: watcher });
$(panel).append((group).getDOMElement());
// This doesn't need a callback since the data will already be cached at this point
group.addTO(TO.get(Hit.getUniqueReqeusters(watcher.lastHits), _handleTOReceived));
} else {
$(panel).append($('
').append('
').css('text-align', 'center').html(" There are no HITs available.
"));
}
}
$(panel).show();
function _handleTOReceived(data) {
group.addTO(data);
}
lastWatcher = watcher;
}
var IgnoreList = (function() {
var _time = 60000,
_hits = [];
_requesters = [],
_HIT = 0,
_REQUESTER = 1;
function _init() {
// _clear();
_load();
_addListeners();
}
function _addListeners() {
$(window).on('unload', function() { _save(); });
}
function _save() {
localStorage.setItem('notifier_ignore', JSON.stringify(_hits));
localStorage.setItem('notifier_ignore_requesters', JSON.stringify(_requesters));
// console.log("Saving ignore list", _hits, _requesters);
}
function _load() {
var storedHits = localStorage.getItem('notifier_ignore');
var storedRequesters = localStorage.getItem('notifier_ignore_requesters');
if (storedHits !== null) {
try {
_hits = JSON.parse(storedHits);
} catch (e) {
_clear();
_save();
console.log("Ignored hits couldn't be loaded correctly.");
}
} else {
console.log("No ignored hits found");
}
if (storedRequesters !== null) {
try {
_requesters = JSON.parse(storedRequesters);
} catch (e) {
_clear();
_save();
console.log("Ignored requesters couldn't be loaded correctly.");
}
} else {
console.log("No ignored requesters found");
}
// console.log("Ignored requesters", _requesters);
}
function _clear() {
_hits = [];
_requesters = [];
localStorage.removeItem('notifier_ignore');
localStorage.removeItem('notifier_ignore_requesters');
}
function _contains(type, item) {
if (type === _HIT)
return (_hits.indexOf(item) !== -1);
else
return (_requesters.indexOf(item) !== -1);
}
function _isIgnored(requester) {
return (_requesters.indexOf(requester) !== -1);
}
function _isMuted(item) {
return (_hits.indexOf(item) !== -1);
}
function _filter(hits) {
var filteredHits = [];
for (var i = 0, len = hits.length; i < len; i++) {
var hit = hits[i];
if ((_hits.indexOf(hit.id) === -1) && (_requesters.indexOf(hit.requester) === -1))
filteredHits.push(hit);
}
return filteredHits;
}
function _add(type, id) {
if (type === _HIT) {
if (_hits.indexOf(id) === -1)
_hits.push(id);
} else if (type === _REQUESTER) {
if (_requesters.indexOf(id) === -1)
_requesters.push(id);
}
_save();
}
function _remove(type, id) {
if (type === _HIT) {
var index = _hits.indexOf(id);
if (index !== -1)
_hits.splice(index, 1);
} else if (type === _REQUESTER) {
var index = _requesters.indexOf(id);
if (index !== -1)
_requesters.splice(index, 1);
}
_save();
}
return {
init: _init,
add: _add,
remove: _remove,
filter: _filter,
isMuted: _isMuted,
isIgnored: _isIgnored,
HIT: _HIT,
REQUESTER: _REQUESTER
}
})();
function Evt() { /* Nothing */ };
Evt.ADD = 1;
Evt.REMOVE = 2;
Evt.START = 3;
Evt.STOP = 4;
Evt.CHANGE = 5;
Evt.UPDATE = 6;
Evt.HITS_CHANGE = 7;
Evt.DELETE = 8;
Evt.VIEW_DETAILS = 9;
Evt.prototype.addListener = function(type, callback) {
switch(type) {
case Evt.ADD:
this.listener.onadd.push(callback);
break;
case Evt.REMOVE:
this.listener.onremove.push(callback);
break;
case Evt.START:
this.listener.onstart.push(callback);
break;
case Evt.STOP:
this.listener.onstop.push(callback);
break;
case Evt.CHANGE:
this.listener.onchange.push(callback);
break;
case Evt.UPDATE:
this.listener.onupdate.push(callback);
break;
case Evt.HITS_CHANGE:
this.listener.onhitschange.push(callback);
break;
case Evt.DELETE:
this.listener.ondelete.push(callback);
break;
case Evt.VIEW_DETAILS:
this.listener.onviewdetails.push(callback);
break;
default:
console.error("Invalid Event type in addListener()");
}
}
Evt.prototype.notify = function(type, data) {
switch(type) {
case Evt.ADD:
this.callFunctionArray(this.listener.onadd, data);
break;
case Evt.REMOVE:
this.callFunctionArray(this.listener.onremove, data);
break;
case Evt.START:
this.callFunctionArray(this.listener.onstart, data);
break;
case Evt.STOP:
this.callFunctionArray(this.listener.onstop, data);
break;
case Evt.CHANGE:
this.callFunctionArray(this.listener.onchange, data);
break;
case Evt.UPDATE:
this.callFunctionArray(this.listener.onupdate, data);
break;
case Evt.HITS_CHANGE:
this.callFunctionArray(this.listener.onhitschange, data);
break;
case Evt.DELETE:
this.callFunctionArray(this.listener.ondelete, data);
break;
case Evt.VIEW_DETAILS:
this.callFunctionArray(this.listener.onviewdetails, data);
break;
default:
console.error("Unknown event type:", type);
}
}
Evt.prototype.callFunctionArray = function(functions, data) {
if (functions.length > 0)
for (var i = 0, len = functions.length; i < len; i++)
functions[i](data);
}
var DispatchUI = {
create: function(dispatch) {
DispatchUI.dispatch = dispatch;
DispatchUI.init();
DispatchUI.addStyle();
DispatchUI.addActions();
DispatchUI.addListeners();
DispatchUI.addDragAndDrop();
return DispatchUI.div;
},
init: function() {
var div = DispatchUI.div = $("
").attr('id', "dispatcher")
.append($("
").attr('id', "controller"))
.append($("
").attr('id', "watcher_container"));
DispatchUI.watchers = [];
// Move dashboard contents to the right and put the dispatch panel on the left
var pageElements = $("body > *");
$("body").html("");
$("body").append(
$("