Reddit Floating Back Button

Keep Reddit's post back button visible while scrolling

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         Reddit Floating Back Button
// @namespace    https://reddit.com/
// @version      1.0
// @description  Keep Reddit's post back button visible while scrolling
// @match        https://www.reddit.com/*
// @match        https://reddit.com/*
// @grant        none
// @run-at       document-idle
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    var BUTTON_SELECTOR = 'pdp-back-button[post-id]';
    var HEADER_SELECTOR = '#pdp-credit-bar';
    var TITLE_SELECTOR = 'h1[slot="title"]';

    var currentButton = null;
    var rafId = null;
    var observer = null;

    function isPostPage() {
        return /\/comments\//i.test(location.pathname);
    }

    function getBackButton() {
        return document.querySelector(BUTTON_SELECTOR);
    }

    function getAnchorElement(button) {
        if (!button) {
            return null;
        }

        var header = document.querySelector(HEADER_SELECTOR);
        if (header) {
            return header;
        }

        var title = document.querySelector(TITLE_SELECTOR);
        if (title) {
            return title;
        }

        return button.parentElement || button;
    }

    function applyFloatingStyle(button) {
        if (!button) {
            return;
        }

        var anchor = getAnchorElement(button);
        var left = 16;
        var top = 76;

        if (anchor) {
            var rect = anchor.getBoundingClientRect();
            left = Math.max(12, Math.round(rect.left - 52));
        }

        button.style.setProperty('position', 'fixed', 'important');
        button.style.setProperty('top', top + 'px', 'important');
        button.style.setProperty('left', left + 'px', 'important');
        button.style.setProperty('right', 'auto', 'important');
        button.style.setProperty('bottom', 'auto', 'important');
        button.style.setProperty('z-index', '9999', 'important');
        button.style.setProperty('display', 'block', 'important');
        button.style.setProperty('visibility', 'visible', 'important');
        button.style.setProperty('opacity', '1', 'important');
        button.style.setProperty('transform', 'none', 'important');
        button.style.setProperty('margin', '0', 'important');
        button.style.setProperty('pointer-events', 'auto', 'important');
    }

    function clearFloatingStyle(button) {
        if (!button) {
            return;
        }

        button.style.removeProperty('position');
        button.style.removeProperty('top');
        button.style.removeProperty('left');
        button.style.removeProperty('right');
        button.style.removeProperty('bottom');
        button.style.removeProperty('z-index');
        button.style.removeProperty('display');
        button.style.removeProperty('visibility');
        button.style.removeProperty('opacity');
        button.style.removeProperty('transform');
        button.style.removeProperty('margin');
        button.style.removeProperty('pointer-events');
    }

    function updateButton() {
        var button = getBackButton();

        if (!isPostPage()) {
            if (currentButton) {
                clearFloatingStyle(currentButton);
            }
            currentButton = null;
            return;
        }

        if (!button) {
            currentButton = null;
            return;
        }

        currentButton = button;
        applyFloatingStyle(button);
    }

    function requestUpdate() {
        if (rafId !== null) {
            return;
        }

        rafId = window.requestAnimationFrame(function () {
            rafId = null;
            updateButton();
        });
    }

    function installObserver() {
        if (observer) {
            observer.disconnect();
        }

        observer = new MutationObserver(function () {
            requestUpdate();
        });

        observer.observe(document.documentElement, {
            childList: true,
            subtree: true
        });
    }

    function installHistoryHooks() {
        var originalPushState = history.pushState;
        var originalReplaceState = history.replaceState;

        history.pushState = function () {
            var result = originalPushState.apply(this, arguments);
            setTimeout(requestUpdate, 0);
            setTimeout(requestUpdate, 300);
            setTimeout(requestUpdate, 1000);
            return result;
        };

        history.replaceState = function () {
            var result = originalReplaceState.apply(this, arguments);
            setTimeout(requestUpdate, 0);
            setTimeout(requestUpdate, 300);
            setTimeout(requestUpdate, 1000);
            return result;
        };

        window.addEventListener('popstate', requestUpdate, true);
    }

    function installListeners() {
        window.addEventListener('scroll', requestUpdate, { passive: true });
        window.addEventListener('resize', requestUpdate, true);
    }

    function init() {
        installObserver();
        installHistoryHooks();
        installListeners();

        requestUpdate();
        setTimeout(requestUpdate, 500);
        setTimeout(requestUpdate, 1500);
    }

    init();
})();