External link to a specific section of site

Hi there!
How can I create an external link that navigates to a specific section of a single-page site?
For example, similar to how a standard anchor works.
It is necessary for this link to work when connected to a QR code.

Thank you, but I have the opposite situation: I need an external link that leads to a specific anchor on my page.

For example, as it is done with a standard anchor (see the attachment).

While solving this issue, two problems were identified:

  1. The problem is that when the page loads, the hash site.com/#Schoolyard is reset, and the full URL of the page is lost, so the anchor cannot work.
  2. The anchor needs to be created by a script after the page has fully loaded. The script must be executed at the very last stage of loading, after all others.

Script that restores the hash (URL):

Place this at the beginning inside the <head> tag:

<head>
    <script>
        (function() {
            // Save the original hash
            var originalHash = window.location.hash;

            // Function to restore the hash
            function restoreHash() {
                if (window.location.hash !== originalHash) {
                    //console.log('Restoring hash:', originalHash);
                    window.location.hash = originalHash;
                }
            }

            // Override the history API methods
            var originalPushState = history.pushState;
            history.pushState = function(state, title, url) {
                var result = originalPushState.apply(this, arguments);
                restoreHash();
                return result;
            };

            var originalReplaceState = history.replaceState;
            history.replaceState = function(state, title, url) {
                var result = originalReplaceState.apply(this, arguments);
                restoreHash();
                return result;
            };

            // Monitor hash changes
            window.addEventListener('hashchange', function() {
                //console.log('Hash changed to:', window.location.hash);
                restoreHash();
            });

            // Restore the hash after the page loads
            window.addEventListener('load', function() {
                setTimeout(restoreHash, 0);
            });
        })();
    </script>
</head>

Script that performs substitution based on aria-label:

This uses the ALT-TEXT of an element; for example, I placed an image outside the visible area located above the desired place on the page.

Now, in the script, it’s sufficient to place an array of aria-label correspondences to the final link.

The script smoothly moves focus to the anchor. But since the site’s content doesn’t load immediately, there’s a slight delay. If there’s animation on the page, there will be jerking during scrolling, so it’s better to replace 'smooth' with 'auto'.

To disable logging, simply comment out all lines starting with console.log using //.

Place this at the end, before </body>:

<body>
    <!-- Your page content -->

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const replacements = {
                'aria-label1': 'aria-label1',
                'aria-label2': 'aria-label2',
                'aria-label3': 'aria-label3',
                // Add additional correspondences as needed
            };

            function updateElements() {
                //console.log("Starting to update elements with aria-label...");
                const elements = document.querySelectorAll('[aria-label]');
                //console.log(`Found elements with aria-label attribute: ${elements.length}`);

                elements.forEach(element => {
                    const dataIdValue = element.getAttribute('aria-label');

                    // Check if there is a replacement for this aria-label
                    if (replacements[dataIdValue]) {
                        element.id = replacements[dataIdValue];
                        //console.log(`Element with aria-label="${dataIdValue}" received id="${element.id}"`);
                    }
                });
            }

            function scrollToAnchor() {
                const hash = window.location.hash;
                if (hash) {
                    const targetId = hash.substring(1); // Remove the '#' symbol
                    const targetElement = document.getElementById(targetId);
                    if (targetElement) {
                        //console.log(`Scrolling to element with id="${targetId}"`);
                        targetElement.scrollIntoView({ behavior: 'smooth' });
                    } else {
                        //console.log(`Element with id="${targetId}" not found`);
                    }
                } else {
                    //console.log("No anchor present in the URL");
                }
            }

            // Initially update elements and try to scroll to anchor
            updateElements();
            scrollToAnchor();

            // Create a MutationObserver to track changes in the DOM
            const observer = new MutationObserver((mutationsList) => {
                mutationsList.forEach(mutation => {
                    if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                        //console.log("New nodes detected in DOM, updating elements...");
                        updateElements();
                        scrollToAnchor();
                    }
                });
            });

            // Start observing the entire document
            observer.observe(document.body, { childList: true, subtree: true });
            //console.log("Started observing changes in the DOM");
        });
    </script>
</body>

Notes:

  • To enable logging, uncomment all lines starting with console.log by delete // at the beginning of each line.
  • Regarding smooth scrolling: If you experience jerky scrolling due to animations or delayed content loading, you might want to replace { behavior: 'smooth' } with { behavior: 'auto' } in the scrollIntoView method:
targetElement.scrollIntoView({ behavior: 'auto' });
  • About the replacements object: This object maps aria-label values to id values. You can add as many correspondences as you need.
  • Placement of scripts:
    • Hash restoration script: Place it inside the <head> tag at the beginning of your HTML document.
    • Main script: Place it just before the closing </body> tag to ensure it runs after all content has been loaded.

By implementing these scripts, you address both problems:

  1. Hash Preservation: The first script ensures that the hash in the URL is preserved throughout page loads and navigation, allowing anchor links to function correctly.
  2. Anchor Creation After Page Load: The second script assigns id attributes to elements based on their aria-label after the DOM content is fully loaded. It then attempts to scroll to the anchor specified in the URL.

Example Usage:

In your replacements object, you can define:

const replacements = {
    'section1': 'section1',
    'section2': 'section2',
    // Add more as needed
};

This script will assign the id attribute to each element based on its aria-label, allowing you to use anchor links like yourpage.html#section1.

Remember:

  • The MutationObserver ensures that any new elements added to the DOM after initial load are also processed.
  • Make sure that the elements you want to scroll to are available in the DOM and have the appropriate aria-label attributes.
  • Test the scripts thoroughly in your environment to ensure they work as expected.