Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name EyeWire – Clickable Cube Player Names
- // @namespace eyewire-clickable-player-names
- // @version 0.4.0
- // @description Opens profiles from the Cube Players panel and keeps the logged-in profile compact.
- // @match https://eyewire.org/*
- // @run-at document-idle
- // @grant none
- // ==/UserScript==
- (() => {
- 'use strict';
- const PLAYER_SELECTOR = '.panel.player > li';
- function getUsername(element) {
- return String(element?.textContent ?? '')
- .replace(/\s+/g, ' ')
- .trim();
- }
- function getJQuery() {
- return window.jQuery || window.$;
- }
- function isVisible(element) {
- if (!(element instanceof Element)) {
- return false;
- }
- const rect = element.getBoundingClientRect();
- const style = getComputedStyle(element);
- return (
- rect.width > 0 &&
- rect.height > 0 &&
- style.display !== 'none' &&
- style.visibility !== 'hidden'
- );
- }
- function findLeaderboardRow() {
- const rows = [...document.querySelectorAll('.leaderRow')];
- return (
- rows.find(isVisible) ??
- rows[0] ??
- null
- );
- }
- function replaceUsernameFields(value, username, depth = 0) {
- if (
- !value ||
- typeof value !== 'object' ||
- depth > 5
- ) {
- return;
- }
- for (const key of Object.keys(value)) {
- const item = value[key];
- if (
- typeof item === 'string' &&
- /^(username|user_name|name)$/i.test(key)
- ) {
- value[key] = username;
- } else if (item && typeof item === 'object') {
- replaceUsernameFields(item, username, depth + 1);
- }
- }
- }
- function cloneData(value, seen = new WeakMap()) {
- if (!value || typeof value !== 'object') {
- return value;
- }
- if (seen.has(value)) {
- return seen.get(value);
- }
- const copy = Array.isArray(value) ? [] : {};
- seen.set(value, copy);
- for (const key of Object.keys(value)) {
- copy[key] = cloneData(value[key], seen);
- }
- return copy;
- }
- function restoreObject(target, backup) {
- for (const key of Object.keys(target)) {
- if (!(key in backup)) {
- delete target[key];
- }
- }
- for (const key of Object.keys(backup)) {
- target[key] = backup[key];
- }
- }
- function findUsernameElement(row) {
- const selectors = [
- '.username',
- '.userName',
- '[class*="username"]',
- '[class*="userName"]',
- 'span'
- ];
- for (const selector of selectors) {
- const element = row.querySelector(selector);
- if (element) {
- return element;
- }
- }
- return null;
- }
- function openProfile(username) {
- const $ = getJQuery();
- if (!$ || typeof $.data !== 'function') {
- console.error(
- '[EyeWire clickable names] EyeWire jQuery was not found.'
- );
- return false;
- }
- const row = findLeaderboardRow();
- if (!row) {
- console.error(
- '[EyeWire clickable names] No leaderboard row was found.'
- );
- return false;
- }
- const rowData = $.data(row);
- if (!rowData || typeof rowData !== 'object') {
- console.error(
- '[EyeWire clickable names] The leaderboard row contains no player data.'
- );
- return false;
- }
- const dataBackup = cloneData(rowData);
- const usernameElement = findUsernameElement(row);
- const originalVisibleName = usernameElement?.textContent ?? null;
- try {
- replaceUsernameFields(rowData, username);
- // Fields confirmed by EyeWire's leaderboard data.
- rowData.username = username;
- if (rowData.user && typeof rowData.user === 'object') {
- rowData.user.username = username;
- if ('name' in rowData.user) {
- rowData.user.name = username;
- }
- }
- // Some versions of EyeWire may read the visible text.
- if (usernameElement) {
- usernameElement.textContent = username;
- }
- /*
- * Invoke EyeWire's existing profile-opening handler.
- * triggerHandler avoids simulating an unrelated browser action.
- */
- $(row).triggerHandler('click');
- return true;
- } catch (error) {
- console.error(
- `[EyeWire clickable names] Could not open "${username}".`,
- error
- );
- return false;
- } finally {
- restoreObject(rowData, dataBackup);
- if (usernameElement && originalVisibleName !== null) {
- usernameElement.textContent = originalVisibleName;
- }
- }
- }
- function showError(username, element) {
- document
- .querySelectorAll('.ew-profile-click-error')
- .forEach(message => message.remove());
- const message = document.createElement('div');
- message.className = 'ew-profile-click-error';
- message.textContent = `Could not open ${username}'s profile.`;
- const rect = element.getBoundingClientRect();
- Object.assign(message.style, {
- position: 'fixed',
- left: `${Math.max(
- 8,
- Math.min(rect.left, window.innerWidth - 260)
- )}px`,
- top: `${Math.max(8, rect.top - 38)}px`,
- zIndex: '2147483647',
- padding: '7px 10px',
- border: '1px solid #555',
- borderRadius: '4px',
- background: 'rgba(25, 25, 28, 0.96)',
- color: '#ddd',
- font: '12px/1.4 sans-serif',
- pointerEvents: 'none'
- });
- document.body.appendChild(message);
- setTimeout(() => message.remove(), 2500);
- }
- /*
- * EyeWire gives the logged-in user's own profile a much larger layout.
- * Detect the Settings tab and scale only that version down.
- */
- function updateOwnProfileSize() {
- const profile = document.querySelector('#profileContainer');
- if (!profile) {
- return;
- }
- const hasSettingsTab = [...profile.querySelectorAll(
- 'a, button, li, span, div'
- )].some(element => (
- element.children.length === 0 &&
- element.textContent.trim() === 'Settings'
- ));
- profile.classList.toggle(
- 'ew-compact-own-profile',
- hasSettingsTab
- );
- }
- const style = document.createElement('style');
- style.textContent = `
- ${PLAYER_SELECTOR} {
- cursor: pointer;
- }
- #profileContainer.ew-compact-own-profile {
- zoom: 0.98 !important;
- }
- `;
- document.head.appendChild(style);
- document.addEventListener(
- 'click',
- event => {
- if (event.button !== 0) {
- return;
- }
- const nameElement = event.target.closest(PLAYER_SELECTOR);
- if (!nameElement) {
- return;
- }
- const username = getUsername(nameElement);
- if (!username) {
- return;
- }
- event.preventDefault();
- event.stopPropagation();
- event.stopImmediatePropagation();
- if (!openProfile(username)) {
- showError(username, nameElement);
- }
- },
- true
- );
- const observer = new MutationObserver(updateOwnProfileSize);
- observer.observe(document.body, {
- childList: true,
- subtree: true,
- characterData: true
- });
- updateOwnProfileSize();
- console.info(
- '[EyeWire clickable names] Version 0.4.0 loaded.'
- );
- })();
Advertisement
Add Comment
Please, Sign In to add comment