Serval Takealot price tracker - Link Helper

Press Alt + S to open Serval Tracker for the current product on Takealot. Also adds a link with icon to the sidebar above the current price.

// ==UserScript==
// @name         Serval Takealot price tracker - Link Helper
// @namespace    your-namespace-here
// @version      1.6
// @description  Press Alt + S to open Serval Tracker for the current product on Takealot. Also adds a link with icon to the sidebar above the current price.
// @match        https://www.takealot.com/*
// @icon         https://www.takealot.com/favicon.ico
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const SERVAL_ICON_URL = 'https://www.servaltracker.com/static/images/favicons/serval_favicon_48x48.png';

    function getServalTrackerUrl() {
        const canonicalLink = document.querySelector('link[rel="canonical"]');
        if (!canonicalLink) {
            const currentUrl = window.location.href;
            const urlParts = currentUrl.split('/');
            const lastPart = urlParts[urlParts.length - 1].split('?')[0];
            return `https://www.servaltracker.com/products/${lastPart}`;
        }
        const hrefParts = canonicalLink.href.split('/');
        const lastPart = hrefParts[hrefParts.length - 1];
        return `https://www.servaltracker.com/products/${lastPart}`;
    }

    function createServalTrackerLink() {
        const servalTrackerUrl = getServalTrackerUrl();
        const linkElement = document.createElement('a');
        linkElement.href = servalTrackerUrl;
        linkElement.target = '_blank';
        linkElement.style.display = 'flex';
        linkElement.style.alignItems = 'center';
        linkElement.style.marginBottom = '10px';
        linkElement.style.textDecoration = 'none';
        linkElement.style.color = 'inherit';

        const iconElement = document.createElement('img');
        iconElement.src = SERVAL_ICON_URL;
        iconElement.width = 24;
        iconElement.height = 24;
        iconElement.style.marginRight = '8px';

        const textElement = document.createElement('span');
        textElement.textContent = 'Track price';
        textElement.style.color = '#0b79bf';

        textElement.addEventListener('mouseover', function() {
            textElement.style.textDecoration = 'underline';
        });

        textElement.addEventListener('mouseout', function() {
            textElement.style.textDecoration = 'none';
        });

        linkElement.appendChild(iconElement);
        linkElement.appendChild(textElement);

        return linkElement;
    }

    function prependServalTrackerLink() {
        const sidebar = document.querySelector('aside[class*="pdp-module_side-bar_"]');
        if (sidebar) {
            let existingLink = sidebar.querySelector('a[href*="servaltracker.com"]');
            if (existingLink) {
                existingLink.href = getServalTrackerUrl();
            } else {
                const linkElement = createServalTrackerLink();
                sidebar.insertBefore(linkElement, sidebar.firstChild);
            }
        }
    }

    function observeCanonicalLink() {
        const observer = new MutationObserver(() => {
            if (document.querySelector('link[rel="canonical"]')) {
                prependServalTrackerLink();
            }
        });
        observer.observe(document.head, { childList: true, subtree: true });
    }

    function observeSidebar() {
        const observer = new MutationObserver((mutations) => {
            for (const mutation of mutations) {
                if (mutation.type === 'childList') {
                    const sidebar = document.querySelector('aside[class*="pdp-module_side-bar_"]');
                    if (sidebar) {
                        prependServalTrackerLink();
                    }
                }
            }
        });
        observer.observe(document.body, { childList: true, subtree: true });
    }

    function openServalTrackerTab() {
        const servalTrackerUrl = getServalTrackerUrl();
        window.open(servalTrackerUrl, '_blank');
    }

    document.addEventListener('keydown', (event) => {
        if (event.altKey && event.code === 'KeyS') {
            openServalTrackerTab();
        }
    });

    observeSidebar();
    observeCanonicalLink();
})();