UNPKG

chessgroundx

Version:
111 lines (93 loc) 3.88 kB
import { State } from './state.js'; import * as drag from './drag.js'; import * as draw from './draw.js'; import * as pocket from './pocket.js'; import { isRightButton } from './util.js'; import * as cg from './types.js'; type MouchBind = (e: cg.MouchEvent) => void; type StateMouchBind = (d: State, e: cg.MouchEvent) => void; export function bindBoard(s: State, onResize: () => void): void { const boardEl = s.dom.elements.board; // In case of zooming boards in bughouse, observing s.dom.elements.wrap // causes recursive onResize calls, so we will just observe the document.body const target = (s.dimensionsCssVarsSuffix) ? document.body : s.dom.elements.wrap; if ('ResizeObserver' in window) new ResizeObserver(onResize).observe(target); if (s.viewOnly) return; // Cannot be passive, because we prevent touch scrolling and dragging of // selected elements. const onStart = startDragOrDraw(s); boardEl.addEventListener('touchstart', onStart as EventListener, { passive: false, }); boardEl.addEventListener('mousedown', onStart as EventListener, { passive: false, }); if (s.disableContextMenu || s.drawable.enabled) { boardEl.addEventListener('contextmenu', e => e.preventDefault()); } } // returns the unbind function export function bindDocument(s: State, onResize: () => void): cg.Unbind { const unbinds: cg.Unbind[] = []; // Old versions of Edge and Safari do not support ResizeObserver. Send // chessground.resize if a user action has changed the bounds of the board. if (!('ResizeObserver' in window)) unbinds.push(unbindable(document.body, 'chessground.resize', onResize)); if (!s.viewOnly) { const onmove = dragOrDraw(s, drag.move, draw.move); const onend = dragOrDraw(s, drag.end, draw.end); for (const ev of ['touchmove', 'mousemove']) unbinds.push(unbindable(document, ev, onmove as EventListener)); for (const ev of ['touchend', 'mouseup']) unbinds.push(unbindable(document, ev, onend as EventListener)); const onScroll = () => s.dom.bounds.clear(); unbinds.push(unbindable(document, 'scroll', onScroll, { capture: true, passive: true })); unbinds.push(unbindable(window, 'resize', onScroll, { passive: true })); const pocketTop = s.dom.elements.pocketTop; const pocketBottom = s.dom.elements.pocketBottom; const pocketStart = startDragOrDrawPocket(s); [pocketTop, pocketBottom].forEach(el => { if (el) { for (const ev of ['touchstart', 'mousedown']) unbinds.push(unbindable(el, ev, pocketStart as EventListener)); if (s.disableContextMenu || s.drawable.enabled) unbinds.push(unbindable(el, 'contextmenu', e => e.preventDefault())); } }); } return () => unbinds.forEach(f => f()); } function unbindable( el: EventTarget, eventName: string, callback: EventListener, options?: AddEventListenerOptions ): cg.Unbind { el.addEventListener(eventName, callback, options); return () => el.removeEventListener(eventName, callback, options); } const startDragOrDraw = (s: State): MouchBind => e => { if (s.draggable.current) drag.cancel(s); else if (s.drawable.current) draw.cancel(s); else if (e.shiftKey || isRightButton(e)) { if (s.drawable.enabled) draw.start(s, e); } else if (!s.viewOnly) { drag.start(s, e); } }; const startDragOrDrawPocket = (s: State): MouchBind => e => { if (s.draggable.current) drag.cancel(s); else if (s.drawable.current) draw.cancel(s); else if (e.shiftKey || isRightButton(e)) { if (s.drawable.enabled) draw.start(s, e); } else if (!s.viewOnly) { pocket.drag(s, e); } }; const dragOrDraw = (s: State, withDrag: StateMouchBind, withDraw: StateMouchBind): MouchBind => e => { if (s.drawable.current) { if (s.drawable.enabled) withDraw(s, e); } else if (!s.viewOnly) withDrag(s, e); };