1

Help would be really appreciated, I’ve been trying to figure this out for hours now.

So this was the solution to an exercise I was doing:

<!doctype html>
<tab-panel>
<div data-tabname="one">Tab one</div>
<div data-tabname="two">Tab two</div>
<div data-tabname="three">Tab three</div>
</tab-panel>
<script>
function asTabs(node) {
let tabs = Array.from(node.children).map(node => {
  let button = document.createElement("button");
  button.textContent = node.getAttribute("data-tabname");
  let tab = {node, button};
  button.addEventListener("click", () => selectTab(tab));
  return tab;
});
let tabList = document.createElement("div");
for (let {button} of tabs) tabList.appendChild(button);
node.insertBefore(tabList, node.firstChild);

function selectTab(selectedTab) {
  for (let tab of tabs) {
    let selected = tab == selectedTab;
    console.log(selected)
    tab.node.style.display = selected ? "" : "none";
    tab.button.style.color = selected ? "red" : "";
  }
}
selectTab(tabs[0]);
}
asTabs(document.querySelector("tab-panel"));
</script>

the part that confused me is on line 13:

button.addEventListener("click", () => selectTab(tab));

Normally when adding event listeners, you wouldnt need to place a function call inside another function - it would be sufficient to say something like this:

button.addEventListener("click", selectTab(tab));

However when I do, an error comes up saying:

ReferenceError: tabs is not defined (line 15 in function selectTab)
called from line 7 in function Array.from.map.node
called from line 3 in function asTabs
called from line 25

and that’s where I’m lost. Thanks for your time as always

ahmedg94
  • 186
  • 2
  • 6

1 Answers1

2

Normally when adding event listeners, you wouldnt need to place a function call inside another function - it would be sufficient to say something like this:

button.addEventListener("click", selectTab(tab));

That isn't true.

The second argument to addEventListener needs to be a function. That function will be called when the event happens.

selectTab(tab) calls the selectTab function immediately (passing it the value of the tab variable). You can only do that if that function's return value it another function.


However when I do, an error comes up saying:

ReferenceError: tabs is not defined (line 15 in function selectTab)

tabs is defined then the Array.from call finished evaluating. The event listener is added as part of the evaluation of that. i.e. before the value has been assigned to tabs.

Quentin
  • 800,325
  • 104
  • 1,079
  • 1,205
  • im not sure what you mean by "You can only do that if that function's return value it another function." – ahmedg94 Mar 08 '18 at 00:12
  • If the return value of `selectTab()` is, for example, `3`, then it would be a number, not a function, and you can't use a number as an event listener. You can only use a function. – Quentin Mar 08 '18 at 00:15