Skip to content

Commit

Permalink
Fixed some ownerDocument/contentWindow edge cases
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Vaughn committed Dec 17, 2019
1 parent 0e1ef7c commit be9046a
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import {DataContext, RegistryContext} from './Contexts';
import styles from './ContextMenu.css';

function respositionToFit(element, pageX, pageY) {
const ownerWindow = element.ownerDocument.defaultView;
if (element !== null) {
if (pageY + element.offsetHeight >= window.innerHeight) {
if (pageY + element.offsetHeight >= ownerWindow.innerHeight) {
if (pageY - element.offsetHeight > 0) {
element.style.top = `${pageY - element.offsetHeight}px`;
} else {
Expand All @@ -22,7 +23,7 @@ function respositionToFit(element, pageX, pageY) {
element.style.top = `${pageY}px`;
}

if (pageX + element.offsetWidth >= window.innerWidth) {
if (pageX + element.offsetWidth >= ownerWindow.innerWidth) {
if (pageX - element.offsetWidth > 0) {
element.style.left = `${pageX - element.offsetWidth}px`;
} else {
Expand Down Expand Up @@ -51,14 +52,16 @@ export default function ContextMenu({children, id}: Props) {

const [state, setState] = useState(HIDDEN_STATE);

const bodyAccessorRef = useRef(null);
const containerRef = useRef(null);
const menuRef = useRef(null);

useEffect(() => {
containerRef.current = document.createElement('div');
document.body.appendChild(containerRef.current);
const ownerDocument = bodyAccessorRef.current.ownerDocument;
containerRef.current = ownerDocument.createElement('div');
ownerDocument.body.appendChild(containerRef.current);
return () => {
document.body.removeChild(containerRef.current);
ownerDocument.body.removeChild(containerRef.current);
};
}, []);

Expand All @@ -81,33 +84,39 @@ export default function ContextMenu({children, id}: Props) {

const menu = menuRef.current;

const hide = event => {
const hideUnlessContains = event => {
if (!menu.contains(event.target)) {
setState(HIDDEN_STATE);
}
};

document.addEventListener('mousedown', hide);
document.addEventListener('touchstart', hide);
document.addEventListener('keydown', hide);
const hide = event => {
setState(HIDDEN_STATE);
};

const ownerDocument = containerRef.current.ownerDocument;
ownerDocument.addEventListener('mousedown', hideUnlessContains);
ownerDocument.addEventListener('touchstart', hideUnlessContains);
ownerDocument.addEventListener('keydown', hideUnlessContains);

window.addEventListener('resize', hide);
const ownerWindow = ownerDocument.defaultView;
ownerWindow.addEventListener('resize', hide);

respositionToFit(menu, state.pageX, state.pageY);

return () => {
document.removeEventListener('mousedown', hide);
document.removeEventListener('touchstart', hide);
document.removeEventListener('keydown', hide);
ownerDocument.removeEventListener('mousedown', hideUnlessContains);
ownerDocument.removeEventListener('touchstart', hideUnlessContains);
ownerDocument.removeEventListener('keydown', hideUnlessContains);

window.removeEventListener('resize', hide);
ownerWindow.removeEventListener('resize', hide);
};
},
[state],
);

if (!state.isVisible) {
return null;
return <div ref={bodyAccessorRef} />;
} else {
return createPortal(
<div ref={menuRef} className={styles.ContextMenu}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ export default function useContextMenu({data, id, ref}) {
event.stopPropagation();

const pageX =
event.clientX || (event.touches && event.touches[0].pageX);
event.pageX || (event.touches && event.touches[0].pageX);
const pageY =
event.clientY || (event.touches && event.touches[0].pageY);
event.pageY || (event.touches && event.touches[0].pageY);

showMenu({data, id, pageX, pageY});
};
Expand Down

0 comments on commit be9046a

Please sign in to comment.