How to allow the click event to be ignored by clicking inside an element?

Asked

Viewed 52 times

6

I have a div which contains some child elements. I would like you to click on the window, that one div be removed.

The code below served, however, by clicking on the content inside the div, she disappears the same way. How to prevent it from happening so much to div as for their child elements?

I managed to get div was not removed when clicking on it, but the removal is still done if you click on one of your children, which is not what is expected.

const div = document.body.firstElementChild;

function ocult(event) {
  if (event.target != div) {
    div.remove();
  }
}

window.addEventListener("click", ocult, true);
div {
  background: #333333;
  margin: 20px;
}
p {
  background: #181818;
  color: white;
  padding: 20px;
  margin: 20px;
}
<div>
  <p>Paragrafo</p>
  <p>Paragrafo</p>
  <p>Paragrafo</p>
  <p>Paragrafo</p>
  <p>Paragrafo</p>
</div>

2 answers

4

The estate event.target refers, in the case of click events, to the element that issued the event in question.

Knowing this, you can use the property target to verify that the element that activated the event meets a certain condition and, depending on its outcome, allow or discard the event.

Trivially, you can do something like this:

const div = document.querySelector('div#my-div');

window.addEventListener('click', function(event) {
  if (event.target.tagName === 'DIV') {
    console.log('Evento descartado.');
    return;
  }
  
  div.remove();
});
#my-div, #my-div * {
  border: solid 1px black;
  background-color: rgba(0, 0, 0, .05);
}
<div id="my-div">
  <p>Paragrafo</p>
  <p>Paragrafo</p>
  <p>Paragrafo</p>
  <p>Paragrafo</p>
  <p>Paragrafo</p>
</div>

Notice now that if you click on div (area marked in light gray), it is no longer removed. However, the effect is not discarded if we click on an element intern à div, as one of its elements p, since the verification we are doing does not encompass them.

Therefore, we need to ensure that the target of the event is not the div in question or one of their children. For this, one can use a while and check the relatives of target, thus.

We will then:

const div = document.querySelector('div#my-div');

window.addEventListener('click', function(event) {
  // Se o alvo do evento for a div ou um de seus filhos, descarte o evento.
  if (event.target === div || isChildrenOf(event.target, div)) {
    console.log('Evento descartado.');
    return;
  }
  
  div.remove();
});

// Função que verifica se `child` é filho de `parent` na hierarquia do DOM.
function isChildrenOf(child, parent) {
  let current = child;
  while (current = current.parentElement) {
    if (current === parent) {
      return true;
    }
  }
  return false;
}
#my-div, #my-div * {
  border: solid 1px black;
  background-color: rgba(0, 0, 0, .05);
}
<div id="my-div">
  <p>Paragrafo</p>
  <p>Paragrafo</p>
  <p>Paragrafo</p>
  <p>Paragrafo</p>
  <p>Paragrafo</p>
</div>

  • Bigger back, 100% explanatory and functional, I imagined that there was something with a little less code just imagined but thank you, if this is the only way will serve

  • Obs I’m not judging or belittling the code, it’s perfect, I just figured there was like a command that did this

  • @Adriano, although there is no native API equivalent to the function isChildrenOf, the code can be reduced with the approach demonstrated in another answer.

4


One option is you add one Event Listener in div to stop the spread of click event with stopPropagation. To div will listen for clicks in any region that is rendered, then you can click on the children that will work as expected.

For this to work, however, you need to remove the , true of window.addEventListener. That’s because when that argument is true, means that the event will be received first by this Thinker and then by the others. Therefore, with the true, It wouldn’t do any good to put a Istener in div.

Heed: If you put the true for some specific reason of your application, you either need to treat it in a better way in order to withdraw it, or you should not adopt this response.

const div = document.body.firstElementChild;

// Adicionei o listener, apenas para parar a propagação
div.addEventListener('click', (event) => event.stopPropagation());

function ocult(event) {
  div.remove();
}

// Removi o terceiro argumento
window.addEventListener("click", ocult);
div {
  background: #333333;
  margin: 20px;
}
p {
  background: #181818;
  color: white;
  padding: 20px;
  margin: 20px;
}
<div>
  <p>Paragrafo</p>
  <p>Paragrafo</p>
  <p>Paragrafo</p>
  <p>Paragrafo</p>
  <p>Paragrafo</p>
</div>

  • 1

    Excellent answer, I had forgotten it. This should be the accepted. :-)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.