Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name EyeWire II - UI Guard
- // @namespace local.eyewire.ui
- // @version 1.0.0
- // @description Fixed segment legend and persistent manual-only Selection Details.
- // @match https://eyewire-ii-community-dot-brain-wire-dot-seung-lab.ue.r.appspot.com/*
- // @run-at document-start
- // @grant none
- // ==/UserScript==
- (() => {
- 'use strict';
- const LEGEND = '.nge-seg-legend';
- const PANEL =
- '.neuroglancer-side-panel.neuroglancer-selection-details';
- const CLOSE =
- '.neuroglancer-icon[title="Close panel"]';
- const SETTINGS =
- 'button.nge-settings-advanced-btn';
- const STORAGE_KEY = 'ew-ui-guard-selection-closed';
- let legend = null;
- let legendPosition = null;
- // Restore the user's previous choice after refresh.
- // If Selection was manually closed, keep it locked.
- let selectionLocked = false;
- try {
- selectionLocked =
- localStorage.getItem(STORAGE_KEY) === 'true';
- } catch (error) {
- console.warn('[EW Guard] Storage unavailable:', error);
- }
- // Manual Settings opening remains allowed.
- let manualOpenUntil = 0;
- function saveSelectionLock(locked) {
- selectionLocked = locked;
- try {
- localStorage.setItem(
- STORAGE_KEY,
- locked ? 'true' : 'false'
- );
- } catch (error) {
- console.warn('[EW Guard] Could not save preference:', error);
- }
- }
- // =========================================================
- // 1. SEGMENT LEGEND — unchanged from working version
- // =========================================================
- function editingActive() {
- return !!document.querySelector(
- '.nge-split-merge-overlay, ' +
- '.graphene-merge-segments, ' +
- '.graphene-multicut'
- );
- }
- function findLegend() {
- const found = document.querySelector(LEGEND);
- if (!found || found === legend) return;
- legend = found;
- legendPosition = null;
- }
- function captureLegendPosition() {
- if (!legend || legendPosition || editingActive()) return;
- const rect = legend.getBoundingClientRect();
- if (rect.width < 10 || rect.height < 5) return;
- legendPosition = {
- left: rect.left,
- top: rect.top,
- width: rect.width
- };
- console.info('[EW Guard] Legend baseline:', legendPosition);
- }
- function anchorLegend() {
- if (!legend || !legendPosition) return;
- const p = legendPosition;
- legend.style.setProperty('position', 'fixed', 'important');
- legend.style.setProperty('left', `${p.left}px`, 'important');
- legend.style.setProperty('top', `${p.top}px`, 'important');
- legend.style.setProperty('bottom', 'auto', 'important');
- legend.style.setProperty('right', 'auto', 'important');
- legend.style.setProperty('width', `${p.width}px`, 'important');
- legend.style.setProperty('margin', '0', 'important');
- legend.style.setProperty('transform', 'none', 'important');
- legend.style.setProperty('transition', 'none', 'important');
- legend.style.setProperty('z-index', '1000', 'important');
- }
- // =========================================================
- // 2. MANUAL SELECTION OPEN / CLOSE
- // =========================================================
- function settingsButtonFrom(target) {
- if (!(target instanceof Element)) return null;
- const button = target.closest(SETTINGS);
- if (!button) return null;
- return /selection\s*details/i.test(
- button.textContent || ''
- ) ? button : null;
- }
- function closeButtonFrom(target) {
- if (!(target instanceof Element)) return null;
- return target.closest(`${PANEL} ${CLOSE}`);
- }
- function authorizeManualOpen() {
- // Allow the user to open Selection through Settings.
- // Do not erase the saved "keep closed" preference:
- // it should still apply after the next refresh.
- selectionLocked = false;
- manualOpenUntil = performance.now() + 2000;
- }
- function recordManualClose() {
- saveSelectionLock(true);
- manualOpenUntil = 0;
- }
- // Capture events before Neuroglancer's own handlers.
- document.addEventListener('pointerdown', event => {
- if (!event.isTrusted) return;
- if (settingsButtonFrom(event.target)) {
- authorizeManualOpen();
- } else if (closeButtonFrom(event.target)) {
- recordManualClose();
- }
- }, true);
- document.addEventListener('click', event => {
- if (!event.isTrusted) return;
- if (settingsButtonFrom(event.target)) {
- authorizeManualOpen();
- } else if (closeButtonFrom(event.target)) {
- recordManualClose();
- }
- }, true);
- document.addEventListener('keydown', event => {
- if (!event.isTrusted) return;
- if (event.key !== 'Enter' && event.key !== ' ') return;
- if (settingsButtonFrom(event.target)) {
- authorizeManualOpen();
- } else if (closeButtonFrom(event.target)) {
- recordManualClose();
- }
- }, true);
- // =========================================================
- // 3. BLOCK UNWANTED SELECTION PANEL INSERTION
- // =========================================================
- function containsSelectionPanel(node) {
- if (!(node instanceof Element)) return false;
- return (
- node.matches(PANEL) ||
- !!node.querySelector(PANEL)
- );
- }
- function shouldBlock(node, receiver) {
- if (!selectionLocked) return false;
- if (performance.now() < manualOpenUntil) {
- return false;
- }
- if (!containsSelectionPanel(node)) {
- return false;
- }
- const parent =
- receiver instanceof Element
- ? receiver
- : null;
- if (!parent) return false;
- return (
- parent.matches('.neuroglancer-side-panel-column') ||
- !!parent.closest('.neuroglancer-side-panel-column')
- );
- }
- const originalInsertBefore = Node.prototype.insertBefore;
- Node.prototype.insertBefore = function(node, reference) {
- if (shouldBlock(node, this)) {
- return node;
- }
- return originalInsertBefore.call(this, node, reference);
- };
- const originalAppendChild = Node.prototype.appendChild;
- Node.prototype.appendChild = function(node) {
- if (shouldBlock(node, this)) {
- return node;
- }
- return originalAppendChild.call(this, node);
- };
- // =========================================================
- // 4. LEGEND WATCHER
- // =========================================================
- let updatePending = false;
- function update() {
- if (updatePending) return;
- updatePending = true;
- requestAnimationFrame(() => {
- updatePending = false;
- findLegend();
- captureLegendPosition();
- anchorLegend();
- });
- }
- function start() {
- const observer = new MutationObserver(update);
- observer.observe(document.documentElement, {
- childList: true,
- subtree: true
- });
- update();
- setInterval(update, 500);
- }
- if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', start, {
- once: true
- });
- } else {
- start();
- }
- })();
Advertisement
Add Comment
Please, Sign In to add comment