import React from 'react';
import ReactDOM from 'react-dom';
import events from '../utils/events';

const isDescendant = (el, target) => {
  if (target !== null) {
    return el === target || isDescendant(el, target.parentNode);
  }
  return false;
};

const clickAwayEvents = ['mousedown', 'touchstart'];
const bind = (callback) => clickAwayEvents.forEach((event) => events.on(document, event, callback));
const unbind = (callback) => clickAwayEvents.forEach((event) => events.off(document, event, callback));

export default class ClickAwayListener extends React.Component {

  static propTypes = {
    children: React.PropTypes.node,
    onClickAway: React.PropTypes.any,
  };

  componentDidMount() {
    if (this.props.onClickAway) {
      bind(this.handleClickAway);
    }
  }

  componentDidUpdate(prevProps) {
    if (prevProps.onClickAway !== this.props.onClickAway) {
      unbind(this.handleClickAway);
      if (this.props.onClickAway) {
        bind(this.handleClickAway);
      }
    }
  }

  componentWillUnmount() {
    unbind(this.handleClickAway);
  }

  handleClickAway = (event) => {
    if (event.defaultPrevented) {
      return;
    }

    const el = ReactDOM.findDOMNode(this);

    if (document.documentElement.contains(event.target) && !isDescendant(el, event.target)) {
      this.props.onClickAway(event);
    }
  };

  render() {
    return this.props.children;
  }
}

import React from 'react';
import ReactDOM from 'react-dom';
import events from '../utils/events';

const isDescendant = (el, target) => {
  if (target !== null) {
    return el === target || isDescendant(el, target.parentNode);
  }
  return false;
};

const clickAwayEvents = ['mouseup', 'touchend'];
const bind = (callback) => clickAwayEvents.forEach((event) => events.on(document, event, callback));
const unbind = (callback) => clickAwayEvents.forEach((event) => events.off(document, event, callback));

export default class ClickAwayListener extends React.Component {

  static propTypes = {
    children: React.PropTypes.node,
    onClickAway: React.PropTypes.any,
  };

  componentDidMount() {
    if (this.props.onClickAway) {
      bind(this.handleClickAway);
    }
  }

  componentDidUpdate(prevProps) {
    if (prevProps.onClickAway !== this.props.onClickAway) {
      unbind(this.handleClickAway);
      if (this.props.onClickAway) {
        bind(this.handleClickAway);
      }
    }
  }

  componentWillUnmount() {
    unbind(this.handleClickAway);
  }

  handleClickAway = (event) => {
    if (event.defaultPrevented) {
      return;
    }

    const el = ReactDOM.findDOMNode(this);

    if (document.documentElement.contains(event.target) && !isDescendant(el, event.target)) {
      this.props.onClickAway(event);
    }
  };

  render() {
    return this.props.children;
  }
}

Fix nested menus that can't be clicked issue
[Menu] Fix nested menus that can't be clicked issue

This fixes a regression that was introduced in https://github.com/callemall/material-ui/pull/3360. The previous `click-awayable` mixin listened on `mouseup` and `touchend` events and the new `ClickAwayListener` was implemented to use `mousedown` and `touchstart` events. This commit changes the events to mimick the behavior from the original mixin.

Resolves #3818
