您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds some visitor-related features to PlanetRomeo.
当前为
// ==UserScript== // @name Romeo Additions // @namespace https://greasyfork.org/en/users/723211-ray/ // @version 1.0 // @description Adds some visitor-related features to PlanetRomeo. // @description:de Fügt Besucher-bezogene Funktionen zu PlanetRomeo hinzu. // @author -Ray- // @include https://*.planetromeo.com/* // @grant GM_addStyle // @require https://code.jquery.com/jquery-3.5.1.slim.min.js // ==/UserScript== // ==== Dependencies ==== /*! waitForKeyElements | https://gist.github.com/BrockA/2625891 */ /*--- waitForKeyElements(): A utility function, for Greasemonkey scripts, that detects and handles AJAXed content. Usage example: waitForKeyElements ( "div.comments" , commentCallbackFunction ); //--- Page-specific function to do what we want when the node is found. function commentCallbackFunction (jNode) { jNode.text ("This comment changed by waitForKeyElements()."); } IMPORTANT: This function requires your script to have loaded jQuery. */ function waitForKeyElements ( selectorTxt, /* Required: The jQuery selector string that specifies the desired element(s). */ actionFunction, /* Required: The code to run when elements are found. It is passed a jNode to the matched element. */ bWaitOnce, /* Optional: If false, will continue to scan for new elements even after the first match is found. */ iframeSelector /* Optional: If set, identifies the iframe to search. */ ) { var targetNodes, btargetsFound; if (typeof iframeSelector == "undefined") targetNodes = $(selectorTxt); else targetNodes = $(iframeSelector).contents () .find (selectorTxt); if (targetNodes && targetNodes.length > 0) { btargetsFound = true; /*--- Found target node(s). Go through each and act if they are new. */ targetNodes.each ( function () { var jThis = $(this); var alreadyFound = jThis.data ('alreadyFound') || false; if (!alreadyFound) { //--- Call the payload function. var cancelFound = actionFunction (jThis); if (cancelFound) btargetsFound = false; else jThis.data ('alreadyFound', true); } } ); } else { btargetsFound = false; } //--- Get the timer-control variable for this selector. var controlObj = waitForKeyElements.controlObj || {}; var controlKey = selectorTxt.replace (/[^\w]/g, "_"); var timeControl = controlObj [controlKey]; //--- Now set or clear the timer as appropriate. if (btargetsFound && bWaitOnce && timeControl) { //--- The only condition where we need to clear the timer. clearInterval (timeControl); delete controlObj [controlKey] } else { //--- Set a timer, if needed. if ( ! timeControl) { timeControl = setInterval ( function () { waitForKeyElements ( selectorTxt, actionFunction, bWaitOnce, iframeSelector ); }, 300 ); controlObj [controlKey] = timeControl; } } waitForKeyElements.controlObj = controlObj; } // ==== CSS ==== GM_addStyle( // Overrides "#visits > .layer__container--wider { width:unset; max-width:1227px; }" + "div[class*='tile--loading--'] .tile__image { background-image:url(/assets/ef3ab4c55a3a9e7a717bcfdb95c3d58f.svg); border-radius:3px; }" + // Custom styles ".tile:active { transform:unset; }" + ".tile__bar { position:absolute; bottom:0; right:0; visibility:hidden; }" + ".tile__bar_action { background:rgba(0,0,0,0.4); display: inline-block; border-radius:3px; color:white; margin:0 3px 3px 0; padding:0.25rem 0.4rem; }" + ".tile__bar_action:hover { background-color:#00A3E4; }" + ".tile__bar_action:active { background-color:#06648B; }" + ".tile__link:hover .tile__bar { visibility:visible; }" ); // ==== Script ==== const settingNs = "RA_SETTINGS:"; // ---- Language ---- const _strings = { "hiddenUsers": { "de": "Versteckte Benutzer", "en": "Hidden users" }, "hideUser": { "de": "Benutzer verstecken", "en": "Hide user" }, "viewFullSizeImage": { "de": "Bild in voller Größe anzeigen", "en": "View full-size image" } } function getString(key) { const lang = document.documentElement.getAttribute("lang") || "en"; const translations = _strings[key]; if (translations) return translations[lang] || translations["en"] || "%" + key + "%"; return "%" + key + "%"; } // ---- Actions for user tiles ---- var _hiddenUsers = JSON.parse(localStorage.getItem(settingNs + "hiddenUsers")) || []; waitForKeyElements( "a.tile__link, " + "div.js-profiles a.listresult, " + "div.js-wrapper a.tile__link > div.tile__image, " + "#visits a.listresult", handleTile); function handleTile(jNode) { const tile = jNode.parent(".tile"); const tileLink = tile.children(".tile__link").first(); if (!tileLink) return; // handle only real profile tiles, ignore placeholders const tileImage = tileLink.children(".tile__image").first(); const username = tileImage.attr("aria-label"); // Remove if hidden. if (_hiddenUsers.includes(username)) { tile.remove(); return; } // Unblur oldest visitors and restore their profile link and display name. if (tile.hasClass("tile--blurred")) { tile.removeClass("tile--blurred"); tileLink.attr("href", "/profile/" + username); tileLink.append( "<div class='bg-raise tile__info'>" + " <div class='info info--middle txt-raise'>" + " <div class='txt-truncate layout-item--consume'>" + " <div class='lh-heading txt-truncate'>" + " <div class='info__main-data'>" + " <div class='info__username' title='" + username + "' lang>" + username + "</div>" + " </div>" + " </div>" + " </div>" + " </div>" + "</div>" + "<div class='tile__footprint'>" + " <div class='tile__visit '> >1d </div>" + "</div>"); } // Add actions. const tileBar = $("<div class='tile__bar'></div>").appendTo(tileLink); handleTile_addShowImage(tile, tileBar, tileImage); handleTile_addHideUser(tile, tileBar, username); } function handleTile_addShowImage(tile, tileBar, tileImage) { const style = tileImage.attr("style"); if (!style) return; const url = style.substring(style.lastIndexOf("/") + 1, style.lastIndexOf(")")); if (url.endsWith(".svg")) return; // ignore "no photo" placeholders const origUrl = "/img/usr/original/0x0/" + url; $("<a class='tile__bar_action' href='" + origUrl + "' title='" + getString("viewFullSizeImage") + "'><span class='icon icon-profile-picture'></a>") .on("click", function(e) { e.preventDefault(); window.open(origUrl, "_blank"); }) .appendTo(tileBar); } function handleTile_addHideUser(tile, tileBar, username) { $("<a class='tile__bar_action' href='#' title='" + getString("hideUser") + "'><span class='icon icon-remove-tag'></a>") .on("click", function(e) { if (!_hiddenUsers.includes(username)) { _hiddenUsers.push(username); _hiddenUsers.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); }); localStorage.setItem(settingNs + "hiddenUsers", JSON.stringify(_hiddenUsers)); } e.preventDefault(); $(e.target).closest(".tile").css("display", "none"); }) .appendTo(tileBar); } // ---- Settings ---- waitForKeyElements("li.js-settings > div.accordion > ul", handleSettings); function handleSettings(jNode) { var itemClass = jNode.find("a").attr("class"); $("<li><div><a class='" + itemClass + "'>" + getString("hiddenUsers") + "</a></div></li>") .on("click", function (e) { // Force open the setting pane and clear any existing contents. $("#offcanvas-nav > .js-layer-content").addClass("is-open"); const pane = $(".js-side-content"); pane.empty(); // Add item for each user. pane.append( "<div class='layout layout--vertical layout--consume'>" + " <div class='layout-item layout-item--consume layout layout--vertical'>" + " <div class='layout-item settings__navigation p l-hidden-sm'>" + " <div class='js-title typo-section-navigation'>" + getString("hiddenUsers") + "</div>" + " </div>" + " <div class='layout-item layout-item--consume'>" + " <div class='js-content js-scrollable fit scrollable'>" + " <div class='js-grid-stats-selector'>" + " <div id='ra_hiddenusers'>" + " <ul class='js-list tags-list tags-list--centered'/>" + " </div>" + " </div>" + " </div>" + " </div>" + " </div>" + "</div>"); const ul = $("#ra_hiddenusers > ul"); _hiddenUsers.forEach(function (item, index) { const li = $("<li class='tags-list__item'/>").appendTo(ul); $("<a class='js-tag ui-tag ui-tag--removable ui-tag--selected' href='#'><span class='ui-tag__label'>" + item + "</span></a>") .on("click", function (e) { _hiddenUsers = _hiddenUsers.filter(function (ele) { return ele != e.target.innerHTML; }); localStorage.setItem(settingNs + "hiddenUsers", JSON.stringify(_hiddenUsers)); $(e.target).closest(".tags-list__item").css("display", "none"); }) .appendTo(li); }); }) .appendTo(jNode); }