import { Fun, Obj } from '@ephox/katamari'; import { type SugarElement, SugarLocation, SugarNode, SugarPosition, Traverse } from '@ephox/sugar'; // The 'button' field of the mouse event - which button was pressed to create the event. Pick only one value. Not defined for mouseenter, // mouseleave, mouseover, mouseout or mousemove. const leftClickButton = 0; const middleClickButton = 1; const rightClickButton = 2; // The 'buttons' field of the mouse event - which buttons *were already pressed* at the time the event fired. Forms a bitfield. const leftClickButtons = 1; const rightClickButtons = 2; const middleClickButtons = 4; // Settings for mouse events interface Settings { // used to tweak the location before firing the event dx?: number; dy?: number; // settings for the event itself button?: number; buttons?: number; ctrlKey?: boolean; shiftKey?: boolean; altKey?: boolean; metaKey?: boolean; bubbles?: boolean; cancelable?: boolean; detail?: number; } // Types of events type EventType = 'click' | 'mousedown' | 'mouseup' | 'mousemove' | 'mouseover' | 'mouseout' | 'contextmenu' | 'dblclick'; // Fire an event const event = (type: EventType, { dx, dy, ...settings }: Settings) => (element: SugarElement): void => { const location = (SugarNode.isElement(element) ? SugarLocation.absolute(element) : SugarPosition(0, 0)).translate(dx || 0, dy || 0); const event = new MouseEvent(type, { screenX: location.left, screenY: location.top, clientX: location.left, clientY: location.top, bubbles: true, cancelable: true, ...settings }); element.dom.dispatchEvent(event); }; const click = (settings: Settings) => (element: SugarElement): void => { const dom = element.dom; Obj.get(dom as any, 'click').fold(() => event('click', settings)(element), Fun.call); }; const mouseDown = Fun.curry(event, 'mousedown'); const mouseUp = Fun.curry(event, 'mouseup'); const mouseMove = Fun.curry(event, 'mousemove'); const mouseOver = Fun.curry(event, 'mouseover'); const mouseOut = Fun.curry(event, 'mouseout'); const contextMenu = (settings: Settings): (element: SugarElement) => void => event('contextmenu', { button: rightClickButton, ...settings }); const dblclick = Fun.curry(event, 'dblclick'); // Note: This can be used for phantomjs. const trigger = (element: SugarElement): void => { const ele = element.dom; if (ele.click !== undefined) { return ele.click(); } // Adapted from: http://stackoverflow.com/questions/17468611/triggering-click-event-phantomjs point('click', leftClickButton, element, 0, 0); return; }; const point = (type: string, button: number, element: SugarElement, x: number, y: number): void => { // Adapted from: http://stackoverflow.com/questions/17468611/triggering-click-event-phantomjs const ev: MouseEvent = Traverse.owner(element).dom.createEvent('MouseEvents'); ev.initMouseEvent( type, true /* bubble */, true /* cancelable */, window, null, x, y, x, y, /* coordinates */ false, false, false, false, /* modifier keys */ button, null ); element.dom.dispatchEvent(ev); }; export type { Settings, EventType }; export { event, leftClickButton, middleClickButton, rightClickButton, leftClickButtons, rightClickButtons, middleClickButtons, click, mouseDown, mouseUp, mouseMove, mouseOver, mouseOut, contextMenu, point, trigger, dblclick };