skip to Main Content

I made web component like below.

Webtest.js

class Webtest extends HTMLElement {
    constructor() {
        super();
    }

    connectedCallback() {
        this.attachShadow({mode: 'open'});
        this.shadowRoot.innerHTML = `
            <style>
                .special {
                    color: green; /* Active link styling */
                    font-weight: bold;
                }
            </style>

            <a id="testId" href="/mypath/index.html">textA</a>
            <a id="testId" href="/mypath/subfolderA/subfolderA.html">textB</a>
            <a id="testId" href="/mypath/subfolderB/subfolderB.html">textC</a>
            <a id="testId" href="/mypath/subfolderC/subfolderC.html">textD</a>
        `;

        const links = this.shadowRoot.querySelectorAll("#testId");
        
        links.forEach(link => {
            link.addEventListener('click', () => {
                this.shadowRoot.querySelector('.special')?.classList.remove('special');
                link.classList.add('special');
            });
        });
    }
}
customElements.define('webtest-component', Webtest);

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="color-scheme" content="dark">
    <script src="./Webtest.js"></script>
</head>

<body>
    <webtest-component></webtest-component>    
</body>

</html>

I have 4 hyperlinks on top of page like this.
enter image description here

I want to highlight the text of last clicked link (one of textA, textB, textC, textD) by inserting special class to last clicked link. But it does not work.

What I tried:
Use ‘addEventListener’ to get the click effect.
click effect:

  1. Remove ‘special’ class from last clicked one.
  2. Add ‘speical’ class to last clicked one.
  3. Since ‘special’ class is defined in style section, it should be highlighted.

Expecting result:
After clicking each text, each text should be highlighted as green color and bold.

Thank you for your help!


According to Nick and Bravo’s help, this is what’s happening. (Thank you very much!)

After clicking page, class properly gets updated but the page redirects to another page and gets refreshed.

So the updated class by the JS only lasts momentarily before the page refreshes.

I want to navigate to each page AND highlight the text of last clicked link.
I want to keep my format as it is.
Any suggestions would be really appriciated!
If you think it is not possible, kindly share as well!
Thank you.

2

Answers


  1. To highlight the link whose href matches the document.referrer, you can modify the Webtest.js component to compare the referrer with each link’s href. If they match, apply the special class to that link.

     class Webtest extends HTMLElement {
         constructor() {
         super();
         }. 
        connectedCallback() {
        this.attachShadow({ mode: "open" });
        this.shadowRoot.innerHTML = `
                <style>
                    .special {
                        color: green; /* Active link styling */
                        font-weight: bold;
                    }
                </style>
    
                <p id="referrer-message"></p>
                <a class="test-link" href="/mypath/index.html">textA</a>
                <a class="test-link" href="/mypath/subfolderA/subfolderA.html">textB</a>
                <a class="test-link" href="/mypath/subfolderB/subfolderB.html">textC</a>
                <a class="test-link" href="/subfolderC.html">textD</a>
            `;
    
        const referrer = document.referrer;
        const referrerMessage = this.shadowRoot.querySelector("#referrer-message");
    
        if (referrer) {
          referrerMessage.textContent = `You navigated here from: ${referrer}`;
        } else {
          referrerMessage.textContent = "No referrer information available.";
        }
    
        const links = this.shadowRoot.querySelectorAll(".test-link");
    
        links.forEach((link) => {
          const href = new URL(link.href, window.location.origin).href;
          if (referrer && referrer === href) {
            link.classList.add("special");
          }
    
          link.addEventListener("click", (event) => {
            history.pushState(null, "", link.getAttribute("href"));
    
            this.shadowRoot.querySelector(".special")?.classList.remove("special");
            link.classList.add("special");
          });
        });
      }
    }
    
    customElements.define("webtest-component", Webtest);
    
    Login or Signup to reply.
  2. You are navigating to another www-page. And that page has no clue what happened in the previous www-page.

    That is how the web works.

    You can store what happened in a page:

    • in the URI as Query Parameters,
    • or save it in localStorage or sessionStorage
    • or on the backend server in cookies, or whatever servercode can do for your

    (duplicate) IDs

    Note: the duplicate ID is indeed invalid X-HTML (when checked with a strict parser), but is valid HTML.

    <div id="foo">ONE</div>
    <div id="foo">TWO</div>
    <div id="foo">THREE</div>
    
    <script>
      console.log( "foo:", foo );
      console.log( "foos", document.querySelectorAll("#foo") );
    </script>

    a bonus Global variable foo was created by the Browser

    Every HTML id="X" creates a Global JavaScript variable X
    This IS part of the official standard, when there are multiple equal IDs the first is returned, says the standard. But that is not what all Browsers do:

    This behavior goes back to the previous century, when Microsoft Internet Explorer implemented it. And because IE had 80+% marketshare all later browsers copied its behavior.

    FireFox, since 2016, no longer returns an HTMLCollection for multiple foo, only the first foo
    So technically only FireFox does what the W3C Standard says:

    Disclaimer; use this knowlegde in test-code, you type less
    Do not use it in production code, only old geezers will understand what is going on

    Note! HTML inside shadowDOM does NOT create (Global) variables

    shadowRoot.querySelectorAll("#testId") gets you a valid Nodelist in all Browsers. Because it queries the DOM live.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search