1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-15 09:04:04 +02:00
joplin/packages/renderer/MdToHtml/createEventHandlingAttrs.ts
2023-10-02 15:15:51 +01:00

101 lines
3.2 KiB
TypeScript

import utils from '../utils';
export interface Options {
enableLongPress: boolean;
postMessageSyntax: string;
enableEditPopup: boolean;
createEditPopupSyntax?: string;
destroyEditPopupSyntax?: string;
}
// longPressTouchStart and clearLongPressTimeout are turned into strings before being called.
// Thus, they should not reference any other non-builtin functions.
const longPressTouchStartFnString = `(onLongPress, longPressDelay) => {
// if touchTimeout is set when ontouchstart is called it means the user has already touched
// the screen once and this is the 2nd touch in this case we assume the user is trying
// to zoom and we don't want to show the menu
if (!!window.touchTimeout) {
clearTimeout(window.touchTimeout);
window.touchTimeout = null;
} else {
window.touchTimeout = setTimeout(() => {
window.touchTimeout = null;
onLongPress();
}, longPressDelay);
}
}`;
const clearLongPressTimeoutFnString = `() => {
if (window.touchTimeout) {
clearTimeout(window.touchTimeout);
window.touchTimeout = null;
}
}`;
// Helper for createEventHandlingAttrs. Exported to facilitate testing.
export const createEventHandlingListeners = (resourceId: string, options: Options, onClickAction: string|null) => {
const eventHandlers = {
ontouchstart: '',
ontouchmove: '',
ontouchend: '',
ontouchcancel: '',
onmouseenter: '',
onmouseleave: '',
onclick: '',
};
if (options.enableLongPress) {
const longPressHandler = `(() => ${options.postMessageSyntax}('longclick:${resourceId}'))`;
const touchStart = `(${longPressTouchStartFnString})(${longPressHandler}, ${utils.longPressDelay}); `;
const callClearLongPressTimeout = `(${clearLongPressTimeoutFnString})(); `;
const touchCancel = callClearLongPressTimeout;
const touchEnd = callClearLongPressTimeout;
eventHandlers.ontouchstart += touchStart;
eventHandlers.ontouchcancel += touchCancel;
eventHandlers.ontouchmove += touchCancel;
eventHandlers.ontouchend += touchEnd;
}
if (options.enableEditPopup) {
const editPopupClick = `(() => ${options.postMessageSyntax}('edit:${resourceId}'))`;
const createEditPopup = ` (${options.createEditPopupSyntax})(this, ${JSON.stringify(resourceId)}, ${editPopupClick}); `;
eventHandlers.ontouchstart += createEditPopup;
eventHandlers.onclick += createEditPopup;
}
if (onClickAction) {
eventHandlers.onclick += onClickAction;
}
return eventHandlers;
};
// Adds event-handling (e.g. long press) code to images and links.
// resourceId is the ID of the image resource or link.
const createEventHandlingAttrs = (resourceId: string, options: Options, onClickAction: string|null) => {
const eventHandlers = createEventHandlingListeners(resourceId, options, onClickAction);
// Build onfoo="listener" strings and add them to the result.
let result = '';
for (const listenerType in eventHandlers) {
const eventHandlersDict = eventHandlers as Record<string, string>;
// Only create code for non-empty listeners.
if (eventHandlersDict[listenerType].length > 0) {
const listener = eventHandlersDict[listenerType].replace(/["]/g, '&quot;');
result += ` ${listenerType}="${listener}" `;
}
}
return result;
};
export default createEventHandlingAttrs;