Search code examples
javascriptanalyticsgoogle-tag-manager

How to store some data on a click event in JS?


I am making an Analytics app in js. I need to get the text from an element that is clicked. I am using this function to get the data at present.

clickfunc = function(link) {
var t = link.innerText || link.textContent;
console.log(t);
}

I call this function on a link as-

<a href="#work" onclick='clickfunc(this)'>

The problem is that, I need to get the data from the element without calling the function in the code, just like in GTM.

Any help is appreciated.


Solution

  • Here as I have called the function in <a href="#work" onclick='clickfunc(this)'>, I need to make a function that does not have to be called like this.

    It sounds like you're asking how to use modern event handling, which is a good idea.

    You do it by:

    1. Removing the onclick from that tag, and either:
      1. Adding script that runs after that element has been created and hooks up a handler for it; or
      2. Adding script that hooks click on an ancestor element and then checks, when the click bubbles to that ancestor, whether it passed through that element. (This is called event delegation.)

    Here's an example of #1:

    <a href="#work">this is the #work element</a>
    <a href="#life">this is something else</a>
    <script>
    document.querySelector("a[href='#work']").addEventListener("click", function() {
        console.log(this.textContent || this.innerText);
    });
    </script>

    Note that that code must be evaluated after the element exists. There are several ways to do that on modern browsers:

    1. Put it in a script tag at the end of the document, just before the closing </body> tag. This works on modern and older and obsolete browsers.
    2. Or put the defer attribute on the script tag (this assumes you're using an external script with a src; it doesn't work on inline script). Works on modern browsers.
    3. Or wrap the code in a handler for the DOMContentLoaded event. Works on modern and older browsers.

    Here's an example of #2 (event delegation):

    <script>
    document.addEventListener("click", function(e) {
        var a = e.target.closest("a[href='#work']");
        if (a) {
            // The event passed through the element on its way to the document
            console.log(a.textContent || a.innerText);
        }
    });
    </script>
    <a href="#work">this is the #work element</a>
    <a href="#life">this is something else</a>

    That closest method exists on modern and slightly older browsers but not IE11. If you need to use IE11-compatible code:

    document.addEventListener("click", function(e) {
        var a = e.target;
        while (a && a.nodeType === 1) {
            if (a.tagName === "A" && a.getAttribute("href") === "#work") {
                // The event passed through the element on its way to the document
                console.log(a.textContent || a.innerText);
                break;
            }
            a = a.parentNode;
        }
    });
    

    In a comment you asked:

    Can I do it like var a = e.target.closest("a[href]") to reference all the tags having href?

    Yes, that's it exactly. e.target.closest("a[href]") will match the first a element that has an href attribute starting from e.target and moving up through its ancestors. e.target.closest("a[href^='#']") will do that only for a elements whose href starts with #. For instance, here's the example above with two href="#xyz" elements that log their text and a the third href="http://example.com" that doesn't because it doesn't match:

    <script>
    document.addEventListener("click", function(e) {
        var a = e.target.closest("a[href^='#']");
        if (a) {
            // The event passed through the element on its way to the document
            console.log(a.textContent || a.innerText);
        }
    });
    </script>
    <div><a href="#work">this is the #work element</a></div>
    <div><a href="#life">this is the #life element</a></div>
    <div><a href="http://example.com">this is the http://example.com element</a></div>