1

Here's the challenge:

Code Excerpt

We have an image and text that describes it all nested in the same div. When somebody clicks on that image, we want Google Tag Manager to return that text.

Basically, we need to:

  1. Go up 3 parent nodes
  2. Go down to the child node with the class "right-section"
  3. Go down to the child node with the class "is-title"
  4. Go down to the child node with the tag "a"
  5. Extract the text

Using my crude, self-taught Javascript knowledge, I came up with this monstrosity of a function:

function(){
  return el.parentNode.parentNode.parentNode.getElementsByClassName("right-section")[0].getElementsByClassName("is-title")[0].getElementsByTagName("a")[0].innerText;
}

... which does not work at all.

Any suggestions?

isherwood
  • 58,414
  • 16
  • 114
  • 157
MOliver
  • 87
  • 6
  • imgur is blocked in our country thats why it dosent show up btw are you allowed to use dom functions like querySelector ? its very easy if you use dom functions – Amir Rahman Apr 29 '22 at 13:41
  • I see, thanks. Here's the relevant code: – MOliver Apr 29 '22 at 13:51
  • Never post code or errors as images, and it belongs in your question, not down here. See [ask]. – isherwood Apr 29 '22 at 13:53
  • This is one of many results in a listing using the same classes, so while document.querySelector(".is-title").innerText returns text, it does not return the text connected to the specific image the user clicked on. – MOliver Apr 29 '22 at 13:54
  • When you run your functions what errors are there on the browser's dev tools console, and how/where is el defined? – A Haworth Apr 29 '22 at 14:00
  • el = {{Click Element}} as defined by Google Tag Manager. There are no errors in the console, but this returns undefined. – MOliver Apr 29 '22 at 14:09

4 Answers4

1

this is an example markup basically the idea is use closest function to go up to dom tree and then use 'querySelector' with that result to go down to any element inside it

const img = document.querySelector(".item_image")
img.onclick = e=>{
    const root = e.target.closest(".card") // goind back to root element
    const text = root.querySelector(".text") // going down to text element
    console.log(text.innerText)
}
<div class="card" style="width:400px;">
    <div class="sections">
        <img class="item_image" style="width:200px;" src="https://2.img-dpreview.com/files/p/E~C1000x0S4000x4000T1200x1200~articles/3925134721/0266554465.jpeg" alt="">
    </div>
    <div class="another-seci">
        <div class="text">
            Despite its modest MSRP, Fujifilm's entry-level X-A3 has dual control dials, a tilting touchscreen, and the same 24MP sensor from the company's flagship models - but with a traditional Bayer color filter array instead of X-Trans. We're pushing through our full 
        </div>
    </div>
</div>
Amir Rahman
  • 1,076
  • 1
  • 6
  • 15
  • Thanks, but I'm afraid this isn't quite there yet. Some of these functions aren't possible in GTM. I can get it running like this: function() { var el = {{Click Element}} var root = el.target.closest(".is-search-sections") // goind back to root element var text = root.querySelector(".is-title") // going down to text element return text.innerText } But it returns the text for the first item in the list regardless of where the user clicks. – MOliver Apr 29 '22 at 14:07
  • obviously i just showed the basic with single element and it is working as required now you can make your own functions with them however you wanted to and if possible use this functions and avoid full custom code for going to parentNode one by one it will break with any future change in dom – Amir Rahman Apr 29 '22 at 18:36
1

ok, Here is an example of what you need to do. If you need an exact answer that would work by just copy pasting it, show the block of HTML exactly how Amir did. I used Amir's HTML example to do the trick. Also, if you see that it takes the same text when you click on different images, include in your html snippet the code from other images, so that we could see how they relate to the parents and could refine the selectors.

Here's your CJS code:

function(){
  return {{Click Element}}.parentElement.parentElement.querySelector(".text").innerText
}

There's completely no need to hop from node to node once you got to the bottom. From the bottom parentElement, just do the query selector once and you're in good hands.

You could also use .closest, but it seems like its complexity is way over just a few parentElements. I know it's insignificant, but hey.

Here is how I debug it right on this page (in Amir's answer): enter image description here

BNazaruk
  • 6,300
  • 3
  • 19
  • 33
0

document.querySelectorAll('.item_image').forEach(item => {
  item.addEventListener('click', event => {
        const root = event.target.closest(".card") // goind back to root element
    const text = root.querySelector(".text") // going down to text element
    console.log(text.innerText)
  })
})
<div class="card" style="width:400px;">
    <div class="sections">
        <img class="item_image" style="width:200px;" src="https://2.img-dpreview.com/files/p/E~C1000x0S4000x4000T1200x1200~articles/3925134721/0266554465.jpeg" alt="">
    </div>
    <div class="another-seci">
        <div class="text">
            Despite its modest MSRP, Fujifilm's entry-level X-A3 has dual control dials, a tilting touchscreen, and the same 24MP sensor from the company's flagship models - but with a traditional Bayer color filter array instead of X-Trans. We're pushing through our full 
        </div>
    </div>
</div>
<div class="card" style="width:400px;">
    <div class="sections">
        <img class="item_image" style="width:200px;" src="https://2.img-dpreview.com/files/p/E~C1000x0S4000x4000T1200x1200~articles/3925134721/0266554465.jpeg" alt="">
    </div>
    <div class="another-section">
        <div class="text">
            BlaDespite its modest MSRP, Fujifilm's entry-level X-A3 has dual control dials, a tilting touchscreen, and the same 24MP sensor from the company's flagship models - but with a traditional Bayer color filter array instead of X-Trans. We're pushing through our full 
        </div>
    </div>
</div>
Olivier
  • 104
  • 3
0

Here's what ultimately worked, for anyone Googling this:

function (){
     el = {{Click Element}};
     var item = el.parentElement.parentElement.nextElementSibling.getElementsByTagName('a')[0].innerText;
     return item;
}
MOliver
  • 87
  • 6