您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Searches the games table for settable game names and highlights them.
// ==UserScript== // @name Game Highlighter // @author Timo Gebauer // @namespace [email protected] // @version 0.2.4 // @grant none // @include http://makemehost.com/games.php* // @description Searches the games table for settable game names and highlights them. // ==/UserScript== /******************************************************************************/ // use MakeMeHosts jQuery version $ = unsafeWindow.jQuery; // option, to restrict search on games column (only mmh table) var searchGamesOnly = false; var highlights = []; var sounds = { solemn: 'http://www.oringz.com/oringz-uploads/sounds-882-solemn.mp3', comm: 'http://www.oringz.com/oringz-uploads/sounds-917-communication-channel.mp3' }; /******************************************************************************/ /* * Ajax Request "hijacken" nach jeder erfolgreichen Übertragung die Funktion highlightArray() ausführen * Das Ergebnis des Requests kann hier nicht abgefangen werden, da der Eventlistener erst aufgerufen wird, * nachdem der eigentliche Aufrufer das Ergebnis bereits verarbeitet hat */ // backup original "send" function reference XMLHttpRequest.prototype.oldSend = XMLHttpRequest.prototype.send; var newSend = function(a) { var xhr = this; var onload = function() { highlightArray(); }; xhr.addEventListener("load", onload, false); this.oldSend(a); }; XMLHttpRequest.prototype.send = newSend; /*******************************************************************************/ /* * TODO: * - color-picker ? * - mute sound checkbox * - "mute" elements * - Rückgangig button * - erst beim schließen vollständig anwenden * - sound-fenster (neu, entfernen, etc..) * - lag verringern * - input dialog verschönern */ function initGui() { $('.refreshMe').next().after('<div align="center"><a class="changelink-unactive" id="btn_options" title="Open highlight settings dialog."> Highlight Settings</a></div>'); document.getElementById('btn_options').addEventListener('click', showGui, true); $("body").append('<div id="popup_overlay" class="overlay"></div>'); $("body").append('<div id="popup" class="popup"></div>'); document.getElementById('popup_overlay').addEventListener('click', hideGui, true); // popup window var html = '<div align="center"><a class="changelink-active"><span>Highlighting Rules</span></a></div><br><p>' + 'Enter one or more keywords, insert a color value (blue, red, #fff, #ff00ff, ...) ' + 'and select a sound if you want one.' + '<br>All table fields are searched. Searching is case-insensitive.' + '<br>Lower indexed rules are applied first.' + '<br>Highlights that trigger a sound will be intensively highlighted for a short duration.</p>' + '<div id="buttons_top">' + '<a id="btn_add"class="changelink-unactive" title="Inserts a new highlighting rule.">New Highlight</a>' + '<a id="btn_load" class="changelink-unactive" title="Load rules from a previously saved JSON formated string.">Load (JSON)</a>' + '</div><div id="buttons_bottom">' + '<a id="btn_save" class="changelink-unactive" title="Save your current rules as JSON formated string.">Save (JSON)</a>' + '<a id="btn_remove_all" class="changelink-unactive" title="Delete all rules. Backup before?">Remove all</a>' + '</div><div id="highlight_container">Something is not working correctly.</div>'; $("#popup").append(html); // load / save $("#btn_load").click(function() { showInputDialog("", function() { highlights = JSON.parse($("#inputDialogInput").attr("value")); updateGui(); }); }); $("#btn_save").click(function() { alert("Save this stringified options somewhere \n\n" + JSON.stringify(highlights)); }); // add a new highlight $("#btn_add").click(function() { highlights.splice(0,0,{search:[]}); updateGui(); }); // remove all $("#btn_remove_all").click(function() { highlights = []; updateGui(); }); updateGui(); // append custom stylesheet $("head").append('<style type="text/css"><!--\n' + "#btn_options {" + "cursor: pointer;" + "font-size: 20px;" + "}" + ".overlay {" + "left: 0;" + "top: 0;" + "bottom: 0;" + "right: 0;" + "z-index: 100;" + "position: fixed;" + "background-color: #000;" + "filter: alpha(opacity=20);" + "opacity: 0.2;" + "cursor: pointer;" + "display: none;" + "}" + ".popup {" + "display: none;" + "background: #fff;" + "padding: 1%;" + "width: 50%;" + "position: fixed;" + "top: 10%;" + "left: 50%;" + "margin: 0 0 0 -20%;" /* add negative left margin for half the width to center the div */ + "cursor: default;" + "z-index: 200;" + "box-shadow: 0 0 5px rgba(0,0,0,0.9);" + "max-height: 80%;" + "overflow: auto;" + "}" + ".highlight_wrapper {" + "width: 550px;" + "margin: 20px;" + "margin-left: auto;" + "margin-right: auto;" + "clear: both;" // + "border: 1px solid grey;" + "overflow: hidden;" + "}" + ".index {" + "width: 20px;" + "margin-right: 30px;" + "float:left;" + "font-family: helvetica neue, helvetica, arial, sans-serif;" + "font-size: 14px;" + "text-shadow: 1px 1px 1px #000;" + "}" + ".btn_hl {" + "font-family: helvetica neue, helvetica, arial, sans-serif;" + "width: 22px;" + "height: 22px;" + "margin-right: 5px;" + "margin-left: 5px;" + "border: 1px solid grey;" + "text-decoration: none;" + "font-weight: bold;" + "cursor:pointer;" + "float:left;" + "}" + ".btn_color {" + "margin-right: 20px;" + "margin-left: 20px;" +"}" + ".btn_remove {" + "background-color: #f5f5f5;" + "}" + ".highlight_search {" + "width: 200px;" + "resize: none;" + "float: left;" + "font-family: helvetica neue, helvetica, arial, sans-serif;" + "white-space: nowrap;" + "word-wrap: normal;" + "border: none;" + "border-left: 2px solid grey;" + "padding-left: 10px;" + "overflow: hidden;" + "}" + ".sound_select {" + "width: 100px;" + "border: 1px solid grey;" + "float: left;" + "}" + ".end_wrapper {" + "clear:both;" + "}" + "#inputDialog {" + "display: none;" + "position: fixed;" + "top: 20%;" + "left: 50%;" + "margin-left: -10%;" + "z-index: 300;" + "}" + "#inputDialogOverlay {" + "z-index: 250;" + "}" + "#btn_save {" + "float:right;" + "font-size: 18px;" + "cursor: pointer;" + "}" + "#btn_load {" + "float:right;" + "font-size: 18px;" + "cursor: pointer;" + "}" + "#btn_add {" + "font-size: 18px;" + "cursor: pointer;" + "}" + "#btn_remove_all {" + "font-size: 18px;" + "cursor: pointer;" + "}" + '\n--></style>'); // input dialog var html = '<div id="inputDialogOverlay" class="overlay"></div>' + '<div id="inputDialog">' + '<input id="inputDialogInput" type="text"></input>' + '<button id="inputDialogButton">Ok</button>' + '</div>'; $("body").append(html); $("#inputDialog").hide(); $("#inputDialogOverlay").click(function() { $("#inputDialog").hide(); $("#inputDialogOverlay").hide(); }); $("#inputDialogInput").focus(function(){ var that = this; setTimeout(function(){$(that).select();}, 10); }); $("#inputDialogInput").keypress(function(event){ if(event.keyCode == 13){ $("#inputDialogButton").click(); } }); } function updateGui() { // save changes saveLocalData(); // reset all previous highlights resetHighlights(); // apply new highlights highlightArray(); $("#highlight_container").empty(); $.each(highlights, function(index, elem) { var html = '<div class="highlight_wrapper" align="center">' + '<span class="index">' + index + '</span>' + ''; // make sure, elem.search is an array elem.search = elem.search instanceof Array ? elem.search : [elem.search]; var text = ""; $.each(elem.search, function(index, search_value) { if(index != 0) text += "\n"; text += search_value; }); html += '<textarea class="highlight_search" title="Search keywords. One per line." index="'+index+'" rows="' + elem.search.length + '">' + text + '</textarea>'; html += '<button class="btn_hl btn_color" value="' + index + '" style="background-color:' + elem.color + ';"> </button>'; html += '<select class="sound_select" title="Notification sound.\nNew games will not only trigger the sound, but also be especially highlighted for a short duration." index="'+index+'">'; var afterOption = ""; var foundSound = false; $.each(sounds, function(sound, url) { afterOption += '<option'; if(elem.sound === sound) { afterOption += ' selected=selected'; foundSound = true; } afterOption += '>' + sound + '</option>'; }); html += '<option' if(!foundSound) html += ' selected=selected'; html += '></option>'; html += afterOption; html += '</select>'; html += '<button class="btn_hl btn_up" title="Move up" index="' + index + '">▲</button>'; html += '<button class="btn_hl btn_down" title="Move down" index="' + index + '">▼</button>'; html += '<button class="btn_hl btn_remove" title="Delete" index="' + index + '">X</button>'; html += '</div>'; $("#highlight_container").append(html); }); // register events $(".highlight_search").change(function() { highlights[$(this).attr("index")].search = cleanArray($(this).val().split("\n")) ; saveLocalData(); resetHighlights(); highlightArray(); }); $(".highlight_search").keyup(function(event) { $(this).attr("rows", $(this).val().split("\n").length); }); $(".btn_color").click(function() { var index = $(this).attr("value"); showInputDialog(highlights[index].color, function() { var color = $("#inputDialogInput").attr("value"); highlights[index].color = color; updateGui(); $('.btn_color[value="'+index+'"]').focus(); }); }); $(".sound_select").change(function(){ highlights[$(this).attr("index")].sound = $(this).val(); // no need to update the gui here, only save the changes saveLocalData(); }); $(".btn_remove").click(function() { highlights.splice($(this).attr("index"),1); updateGui(); }); $(".btn_up").click(function() { var index = parseInt($(this).attr("index")); if(index == 0) return; var temp = highlights.splice(index, 1); highlights.splice(index-1, 0, temp[0]); updateGui(); }); $(".btn_down").click(function() { var index = parseInt($(this).attr("index")); if(index == highlights.length-1) return; var temp = highlights.splice(index, 1); highlights.splice(index+1, 0, temp[0]); updateGui(); }); } function showInputDialog(text, okFunction) { $("#inputDialogInput").attr("value", text); $("#inputDialogInput").focus(); $("#inputDialog").show(); $("#inputDialogOverlay").show(); $("#inputDialogButton").unbind("click") $("#inputDialogButton").click(function() { $("#inputDialog").hide(); $("#inputDialogOverlay").hide(); }); $("#inputDialogButton").click(okFunction); } function showGui() { $("#popup_overlay").show(); $("#popup").show(); $("body").css("overflow", "hidden"); } function hideGui() { $("#popup_overlay").css("display", "none"); $("#popup").css("display", "none"); $("body").css("overflow", "auto"); // reset all previous highlights resetHighlights(); // apply new highlights highlightArray(); } /******************************************************************************/ function saveLocalData() { localStorage.setItem("highlights", JSON.stringify(highlights)); } function loadLocalData() { highlights = JSON.parse(localStorage.getItem("highlights")); if(highlights === null) { highlights = []; } } /******************************************************************************/ $(document).ready(function () { // Riesigen Header entfernen $('#rt-header-overlay').remove(); // Sounds vorladen $.each(sounds, function(name, url) { $("body").append("<audio id='sound_"+name+"' src='"+url+"' hidden=true preload=auto></audio>"); }); // Einstellungen laden loadLocalData(); // eigenes GUI einfügen initGui(); }); /******************************************************************************/ // enthalten die Namen der gefundenen Spiele var knownGames = {}; var foundGames = {}; function resetHighlights() { $("#mmh td").css({ backgroundColor: "transparent", color: "black" }); } function highlightArray() { foundGames = {}; $.each(highlights, function(index, elem) { if (elem === null) return; var arr = elem.search instanceof Array ? elem.search : [elem.search]; if(!(arr.length == 1 && arr[0] === "")) $.each(arr, function(index, text) { highlight(text, elem.color, elem.sound); }); }); knownGames = foundGames; } function highlight(search, color, sound) { getNodes(search).each(function(){ // Schrift färben? if(color && !$(this).attr("hl")) { $(this).css("color", color); } // Spiel unbekannt? if(!($(this).text() in knownGames)) { // Sound abspielen? if(sound in sounds) { // neu gefundene Spiele kurzzeitig hervorheben $(this).css("background-color", color); $(this).css("color", "white"); // mark this element as highlighted $(this).attr("hl", "true"); document.getElementById("sound_" + sound).play(); } } foundGames[$(this).text()] = $(this).text(); }); } function getNodes(text) { // Nur in Games Spalten suchen? if (searchGamesOnly) { var tds = $('#mmh table:first-child td:nth-child(4)') .add('#mmh table:last-child td:nth-child(2)'); } else { var tds = $('td'); } return tds.filter(':Contains(' + text + ')'); } /******************************************************************************/ /* * removes every "falsy" value: undefined, null, 0, false, NaN and '': */ function cleanArray(actual){ var newArray = new Array(); for(var i = 0; i<actual.length; i++){ if (actual[i]){ newArray.push(actual[i]); } } return newArray; } /******************************************************************************/ // jQuery :contains Case-Insensitive // http://css-tricks.com/snippets/jquery/make-jquery-contains-case-insensitive/ jQuery.expr[':'].Contains = function(a, i, m) { return jQuery(a).text().toUpperCase() .indexOf(m[3].toUpperCase()) >= 0; };