Aurimas
Aurimas

Reputation: 2717

Listen on event between some parent and some child element

I have a modal that covers whole window, but only because there is a need for a darkening background to the modal that is set on .open.modal. HTML looks like this:

<div class="modals">
  <div class="open modal">
    <div class="modal_inner">
      <div class="white">
        <div class="x"><img src="/assets/meeting/close.png"></div>
        <div class="all">
            <!-- ALL CONTENT HERE -->
        </div>
      </div>
    </div>
  </div>
  <div class="open modal">
    <!-- OTHER MODAL CAN BE OPEN ON TOP -->
  </div>
</div>

When user clicks outside .white (.open.modal or above) I want to close the modal.

How do I register a Javascript event that will fire if clicked between the parent (in this case body or bellow) and the child (in this case .white)?

I have this in React.

Upvotes: 0

Views: 579

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074435

There are two standard ways to approach it:

Multiple handlers

  1. Hook click on .open.modal and do the real work there

  2. Hook click on .white and prevent bubbling, so clicks on .white don't reach .open.modal, and thus don't trigger its handler

So for instance:

handleOpenModalClick(event) {
    // Do the work
}
handleWhiteClick(event) {
    event.stopPropagation();
}

Example:

class Example extends React.Component {
  handleOpenModalClick(event) {
    // Do the work
    console.log("Do it");
  }
  handleWhiteClick(event) {
      event.stopPropagation();
  }
  render() {
    return (
      <div>
        <div className="open modal" onClick={this.handleOpenModalClick}>
          <div className="white" onClick={this.handleWhiteClick}>
            xxx
          </div>
        </div>
      </div>
    );
  }
}

ReactDOM.render(
  <Example />,
  document.getElementById("react")
);
.open.modal {
  background: #ccc;
  padding: 20px;
}
.white {
  background: white;
}
<div id="react"</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Filtering the event once received

Hook click on .open.modal, and when received, check the elements between event.target and .open.modal and check if .white is there. If so, don't do the work.

handleClick(event) {
    let node = event.target;
    while (node && node !== event.currentTarget) {
        if (node.classList.contains("white")) {
            return; // Skip it
        }
    }
    // Do the work
}

Example:

class Example extends React.Component {
  handleClick(event) {
    let node = event.target;
    while (node && node !== event.currentTarget) {
      if (node.classList.contains("white")) {
        return; // Skip it
      }
    }
    // Do the work
    console.log("Do it!");
  }
  render() {
    return (
      <div>
        <div className="open modal" onClick={this.handleClick}>
          <div className="white">
            xxx
          </div>
        </div>
      </div>
    );
  }
}

ReactDOM.render(
  <Example />,
  document.getElementById("react")
);
.open.modal {
  background: #ccc;
  padding: 20px;
}
.white {
  background: white;
}
<div id="react"</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Upvotes: 1

Related Questions