'Get element inside "block" relative of user click without IDs
I'm not entirely sure if this is possible, but here is my idea:
I have multiple blocks in my page, all of them are built the same and they have the same classes. Only the content in the blocks is different.
I can't / don't want to assign IDs because these blocks get generated by the backend and it's just not suitable to give each an individual ID.
I want to get relative (in the HTML) to where the user clicks the button another element near the button and store that in a variable.
So if my HTML looks like this:
<div class="this-is-a-block">
<h3>My first Element 1</h3>
<p>Some text</p>
<p>Some text</p>
<div>
<div>
<button class="classButton">Button 1</button>
</div>
</div>
</div>
<div class="this-is-a-block">
<h3>My second Element 2</h3>
<p>Some other text</p>
<p>Some other tex</p>
<div>
<div>
<button class="classButton">Button 2</button>
</div>
</div>
</div>
I want to get the h3 in a variable, but only in the scope of the block.
So when the user clicks Button 2 the variable would be My second Element 2 but when the user clicks Button 1 the variable would be My first Element 1
I think you get the point.
Is that possible to do without IDs? I assume for JS both blocks look the same. Is there any way to stay in the scope of where the user clicks?
When I select the button with querySelectorAll and loop through the output then I get multiple results for my h3 (so a result for any button on the page).
This is an example with a single block with an ID to show how my other code would work.
document.getElementById("button").addEventListener("click", myScript);
function myScript() {
let result = document.getElementById("button").parentElement.parentElement.parentElement.firstElementChild.innerHTML.trim();
console.log(result)
}
<div>
<h3>My first Element 1</h3>
<p>Some text</p>
<p>Some text</p>
<div>
<div>
<button id="button" class="classButton">Button 1</button>
</div>
</div>
</div>
The only part missing is to only select the button that get's actually clicked and get relative to that the h3, and only a single h3 inside the block and not every h3 on the page.
This is my simplified code of the actual thing without IDs and multiple blocks:
let result;
let button = document.querySelectorAll(".classButton");
button.forEach(click => {
click.addEventListener("click", myScript);
})
function myScript() {
button.forEach(i => {
result = i.parentElement.parentElement.parentElement.firstElementChild.innerHTML.trim();
})
console.log(result)
}
<div class="this-is-a-block">
<h3>My first Element 1</h3>
<p>Some text</p>
<p>Some text</p>
<div>
<div>
<button class="classButton">Button 1</button>
</div>
</div>
</div>
<div class="this-is-a-block">
<h3>My second Element 2</h3>
<p>Some other text</p>
<p>Some other tex</p>
<div>
<div>
<button class="classButton">Button 2</button>
</div>
</div>
</div>
I either only get the last element or if I put the console.log inside the forEach both.
Any way of doing that?
Thanks!
I know the way of getting the content of the h3 might not be the best way, but that's another problem I can work on as soon as the other part works.
Solution 1:[1]
When you specify a function to handle an event inside a loop then you have access to event and element both so you don't have to loop again
let result;
let button = document.querySelectorAll(".classButton");
button.forEach(click => {
click.addEventListener("click", getH1);
})
function getH1(e){
let textValue = e.target.parentNode.parentNode.parentNode.children[0].innerText
console.log(textValue)
}
<div class="this-is-a-block">
<h3>My first Element 1</h3>
<p>Some text</p>
<p>Some text</p>
<div>
<div>
<button class="classButton">Button 1</button>
</div>
</div>
</div>
<div class="this-is-a-block">
<h3>My second Element 2</h3>
<p>Some other text</p>
<p>Some other tex</p>
<div>
<div>
<button class="classButton">Button 2</button>
</div>
</div>
</div>
<div class="this-is-a-block">
<h3>My second Element 3</h3>
<p>Some other text</p>
<p>Some other tex</p>
<div>
<div>
<button class="classButton">Button 3</button>
</div>
</div>
</div>
<div class="this-is-a-block">
<h3>My second Element 4</h3>
<p>Some other text</p>
<p>Some other tex</p>
<div>
<div>
<button class="classButton">Button 4</button>
</div>
</div>
</div>
Solution 2:[2]
Thanks to @CBroe's comment I got this solution:
let result;
let buttonEvent = document.querySelectorAll(".classButton");
let button = document.querySelector(".classButton");
buttonEvent.forEach(click => {
click.addEventListener("click", myScript);
})
function myScript() {
result = this.parentElement.parentElement.parentElement.firstElementChild.innerHTML.trim()
console.log(result)
}
<div class="this-is-a-block">
<h3>My first Element 1</h3>
<p>Some text</p>
<p>Some text</p>
<div>
<div>
<button class="classButton">Button 1</button>
</div>
</div>
</div>
<div class="this-is-a-block">
<h3>My second Element 2</h3>
<p>Some other text</p>
<p>Some other tex</p>
<div>
<div>
<button class="classButton">Button 2</button>
</div>
</div>
</div>
I'm not sure if this is the 100% best way, but it's working.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Ankit Tiwari |
| Solution 2 | jona |
