UNPKG

fabric

Version:

Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.

1 lines 22.1 kB
{"version":3,"file":"DraggableTextDelegate.min.mjs","sources":["../../../../src/shapes/IText/DraggableTextDelegate.ts"],"sourcesContent":["import type {\n DragEventData,\n DropEventData,\n TPointerEvent,\n} from '../../EventTypeDefs';\nimport { Point } from '../../Point';\nimport type { IText } from './IText';\nimport { setStyle } from '../../util/dom_style';\nimport { cloneStyles } from '../../util/internals/cloneStyles';\nimport type { TextStyleDeclaration } from '../Text/StyledText';\nimport { getDocumentFromElement } from '../../util/dom_misc';\nimport { CHANGED, NONE } from '../../constants';\n\n/**\n * #### Dragging IText/Textbox Lifecycle\n * - {@link start} is called from `mousedown` {@link IText#_mouseDownHandler} and determines if dragging should start by testing {@link isPointerOverSelection}\n * - if true `mousedown` {@link IText#_mouseDownHandler} is blocked to keep selection\n * - if the pointer moves, canvas fires numerous mousemove {@link Canvas#_onMouseMove} that we make sure **aren't** prevented ({@link IText#shouldStartDragging}) in order for the window to start a drag session\n * - once/if the session starts canvas calls {@link onDragStart} on the active object to determine if dragging should occur\n * - canvas fires relevant drag events that are handled by the handlers defined in this scope\n * - {@link end} is called from `mouseup` {@link IText#mouseUpHandler}, blocking IText default click behavior\n * - in case the drag session didn't occur, {@link end} handles a click, since logic to do so was blocked during `mousedown`\n */\nexport class DraggableTextDelegate {\n readonly target: IText;\n private __mouseDownInPlace = false;\n private __dragStartFired = false;\n private __isDraggingOver = false;\n private __dragStartSelection?: {\n selectionStart: number;\n selectionEnd: number;\n };\n private __dragImageDisposer?: VoidFunction;\n private _dispose?: () => void;\n\n constructor(target: IText) {\n this.target = target;\n const disposers = [\n this.target.on('dragenter', this.dragEnterHandler.bind(this)),\n this.target.on('dragover', this.dragOverHandler.bind(this)),\n this.target.on('dragleave', this.dragLeaveHandler.bind(this)),\n this.target.on('dragend', this.dragEndHandler.bind(this)),\n this.target.on('drop', this.dropHandler.bind(this)),\n ];\n this._dispose = () => {\n disposers.forEach((d) => d());\n this._dispose = undefined;\n };\n }\n\n isPointerOverSelection(e: TPointerEvent) {\n const target = this.target;\n const newSelection = target.getSelectionStartFromPointer(e);\n return (\n target.isEditing &&\n newSelection >= target.selectionStart &&\n newSelection <= target.selectionEnd &&\n target.selectionStart < target.selectionEnd\n );\n }\n\n /**\n * @public override this method to disable dragging and default to mousedown logic\n */\n start(e: TPointerEvent) {\n return (this.__mouseDownInPlace = this.isPointerOverSelection(e));\n }\n\n /**\n * @public override this method to disable dragging without discarding selection\n */\n isActive() {\n return this.__mouseDownInPlace;\n }\n\n /**\n * Ends interaction and sets cursor in case of a click\n * @returns true if was active\n */\n end(e: TPointerEvent) {\n const active = this.isActive();\n if (active && !this.__dragStartFired) {\n // mousedown has been blocked since `active` is true => cursor has not been set.\n // `__dragStartFired` is false => dragging didn't occur, pointer didn't move and is over selection.\n // meaning this is actually a click, `active` is a false positive.\n this.target.setCursorByClick(e);\n this.target.initDelayedCursor(true);\n }\n this.__mouseDownInPlace = false;\n this.__dragStartFired = false;\n this.__isDraggingOver = false;\n return active;\n }\n\n getDragStartSelection() {\n return this.__dragStartSelection;\n }\n\n /**\n * Override to customize the drag image\n * https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage\n */\n setDragImage(\n e: DragEvent,\n {\n selectionStart,\n selectionEnd,\n }: {\n selectionStart: number;\n selectionEnd: number;\n },\n ) {\n const target = this.target;\n const canvas = target.canvas!;\n const flipFactor = new Point(target.flipX ? -1 : 1, target.flipY ? -1 : 1);\n const boundaries = target._getCursorBoundaries(selectionStart);\n const selectionPosition = new Point(\n boundaries.left + boundaries.leftOffset,\n boundaries.top + boundaries.topOffset,\n ).multiply(flipFactor);\n const pos = selectionPosition.transform(target.calcTransformMatrix());\n const pointer = canvas.getScenePoint(e);\n const diff = pointer.subtract(pos);\n const retinaScaling = target.getCanvasRetinaScaling();\n const bbox = target.getBoundingRect();\n const correction = pos.subtract(new Point(bbox.left, bbox.top));\n const vpt = canvas.viewportTransform;\n const offset = correction.add(diff).transform(vpt, true);\n // prepare instance for drag image snapshot by making all non selected text invisible\n const bgc = target.backgroundColor;\n const styles = cloneStyles(target.styles);\n target.backgroundColor = '';\n const styleOverride = {\n stroke: 'transparent',\n fill: 'transparent',\n textBackgroundColor: 'transparent',\n };\n target.setSelectionStyles(styleOverride, 0, selectionStart);\n target.setSelectionStyles(styleOverride, selectionEnd, target.text.length);\n target.dirty = true;\n const dragImage = target.toCanvasElement({\n enableRetinaScaling: canvas.enableRetinaScaling,\n viewportTransform: true,\n });\n // restore values\n target.backgroundColor = bgc;\n target.styles = styles;\n target.dirty = true;\n // position drag image offscreen\n setStyle(dragImage, {\n position: 'fixed',\n left: `${-dragImage.width}px`,\n border: NONE,\n width: `${dragImage.width / retinaScaling}px`,\n height: `${dragImage.height / retinaScaling}px`,\n });\n this.__dragImageDisposer && this.__dragImageDisposer();\n this.__dragImageDisposer = () => {\n dragImage.remove();\n };\n getDocumentFromElement(\n (e.target || this.target.hiddenTextarea)! as HTMLElement,\n ).body.appendChild(dragImage);\n e.dataTransfer?.setDragImage(dragImage, offset.x, offset.y);\n }\n\n /**\n * @returns {boolean} determines whether {@link target} should/shouldn't become a drag source\n */\n onDragStart(e: DragEvent): boolean {\n this.__dragStartFired = true;\n const target = this.target;\n const active = this.isActive();\n if (active && e.dataTransfer) {\n const selection = (this.__dragStartSelection = {\n selectionStart: target.selectionStart,\n selectionEnd: target.selectionEnd,\n });\n const value = target._text\n .slice(selection.selectionStart, selection.selectionEnd)\n .join('');\n const data = { text: target.text, value, ...selection };\n e.dataTransfer.setData('text/plain', value);\n e.dataTransfer.setData(\n 'application/fabric',\n JSON.stringify({\n value: value,\n styles: target.getSelectionStyles(\n selection.selectionStart,\n selection.selectionEnd,\n true,\n ),\n }),\n );\n e.dataTransfer.effectAllowed = 'copyMove';\n this.setDragImage(e, data);\n }\n target.abortCursorAnimation();\n return active;\n }\n\n /**\n * use {@link targetCanDrop} to respect overriding\n * @returns {boolean} determines whether {@link target} should/shouldn't become a drop target\n */\n canDrop(e: DragEvent): boolean {\n if (\n this.target.editable &&\n !this.target.getActiveControl() &&\n !e.defaultPrevented\n ) {\n if (this.isActive() && this.__dragStartSelection) {\n // drag source trying to drop over itself\n // allow dropping only outside of drag start selection\n const index = this.target.getSelectionStartFromPointer(e);\n const dragStartSelection = this.__dragStartSelection;\n return (\n index < dragStartSelection.selectionStart ||\n index > dragStartSelection.selectionEnd\n );\n }\n return true;\n }\n return false;\n }\n\n /**\n * in order to respect overriding {@link IText#canDrop} we call that instead of calling {@link canDrop} directly\n */\n protected targetCanDrop(e: DragEvent) {\n return this.target.canDrop(e);\n }\n\n dragEnterHandler({ e }: DragEventData) {\n const canDrop = this.targetCanDrop(e);\n if (!this.__isDraggingOver && canDrop) {\n this.__isDraggingOver = true;\n }\n }\n\n dragOverHandler(ev: DragEventData) {\n const { e } = ev;\n const canDrop = this.targetCanDrop(e);\n if (!this.__isDraggingOver && canDrop) {\n this.__isDraggingOver = true;\n } else if (this.__isDraggingOver && !canDrop) {\n // drop state has changed\n this.__isDraggingOver = false;\n }\n if (this.__isDraggingOver) {\n // can be dropped, inform browser\n e.preventDefault();\n // inform event subscribers\n ev.canDrop = true;\n ev.dropTarget = this.target;\n }\n }\n\n dragLeaveHandler() {\n if (this.__isDraggingOver || this.isActive()) {\n this.__isDraggingOver = false;\n }\n }\n\n /**\n * Override the `text/plain | application/fabric` types of {@link DragEvent#dataTransfer}\n * in order to change the drop value or to customize styling respectively, by listening to the `drop:before` event\n * https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#performing_a_drop\n */\n dropHandler(ev: DropEventData) {\n const { e } = ev;\n const didDrop = e.defaultPrevented;\n this.__isDraggingOver = false;\n // inform browser that the drop has been accepted\n e.preventDefault();\n let insert = e.dataTransfer?.getData('text/plain');\n if (insert && !didDrop) {\n const target = this.target;\n const canvas = target.canvas!;\n let insertAt = target.getSelectionStartFromPointer(e);\n const { styles } = (\n e.dataTransfer!.types.includes('application/fabric')\n ? JSON.parse(e.dataTransfer!.getData('application/fabric'))\n : {}\n ) as { styles: TextStyleDeclaration[] };\n const trailing = insert[Math.max(0, insert.length - 1)];\n const selectionStartOffset = 0;\n // drag and drop in same instance\n if (this.__dragStartSelection) {\n const selectionStart = this.__dragStartSelection.selectionStart;\n const selectionEnd = this.__dragStartSelection.selectionEnd;\n if (insertAt > selectionStart && insertAt <= selectionEnd) {\n insertAt = selectionStart;\n } else if (insertAt > selectionEnd) {\n insertAt -= selectionEnd - selectionStart;\n }\n target.removeChars(selectionStart, selectionEnd);\n // prevent `dragend` from handling event\n delete this.__dragStartSelection;\n }\n // remove redundant line break\n if (\n target._reNewline.test(trailing) &&\n (target._reNewline.test(target._text[insertAt]) ||\n insertAt === target._text.length)\n ) {\n insert = insert.trimEnd();\n }\n // inform subscribers\n ev.didDrop = true;\n ev.dropTarget = target;\n // finalize\n target.insertChars(insert, styles, insertAt);\n // can this part be moved in an outside event? andrea to check.\n canvas.setActiveObject(target);\n target.enterEditing(e);\n target.selectionStart = Math.min(\n insertAt + selectionStartOffset,\n target._text.length,\n );\n target.selectionEnd = Math.min(\n target.selectionStart + insert.length,\n target._text.length,\n );\n target.hiddenTextarea!.value = target.text;\n target._updateTextarea();\n target.hiddenTextarea!.focus();\n target.fire(CHANGED, {\n index: insertAt + selectionStartOffset,\n action: 'drop',\n });\n canvas.fire('text:changed', { target });\n canvas.contextTopDirty = true;\n canvas.requestRenderAll();\n }\n }\n\n /**\n * fired only on the drag source after drop (if occurred)\n * handle changes to the drag source in case of a drop on another object or a cancellation\n * https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#finishing_a_drag\n */\n dragEndHandler({ e }: DragEventData) {\n if (this.isActive() && this.__dragStartFired) {\n // once the drop event finishes we check if we need to change the drag source\n // if the drag source received the drop we bail out since the drop handler has already handled logic\n if (this.__dragStartSelection) {\n const target = this.target;\n const canvas = this.target.canvas!;\n const { selectionStart, selectionEnd } = this.__dragStartSelection;\n const dropEffect = e.dataTransfer?.dropEffect || NONE;\n if (dropEffect === NONE) {\n // pointer is back over selection\n target.selectionStart = selectionStart;\n target.selectionEnd = selectionEnd;\n target._updateTextarea();\n target.hiddenTextarea!.focus();\n } else {\n target.clearContextTop();\n if (dropEffect === 'move') {\n target.removeChars(selectionStart, selectionEnd);\n target.selectionStart = target.selectionEnd = selectionStart;\n target.hiddenTextarea &&\n (target.hiddenTextarea.value = target.text);\n target._updateTextarea();\n target.fire(CHANGED, {\n index: selectionStart,\n action: 'dragend',\n });\n canvas.fire('text:changed', { target });\n canvas.requestRenderAll();\n }\n target.exitEditing();\n }\n }\n }\n\n this.__dragImageDisposer && this.__dragImageDisposer();\n delete this.__dragImageDisposer;\n delete this.__dragStartSelection;\n this.__isDraggingOver = false;\n }\n\n dispose() {\n this._dispose && this._dispose();\n }\n}\n"],"names":["DraggableTextDelegate","constructor","target","_defineProperty","this","disposers","on","dragEnterHandler","bind","dragOverHandler","dragLeaveHandler","dragEndHandler","dropHandler","_dispose","forEach","d","undefined","isPointerOverSelection","e","newSelection","getSelectionStartFromPointer","isEditing","selectionStart","selectionEnd","start","__mouseDownInPlace","isActive","end","active","__dragStartFired","setCursorByClick","initDelayedCursor","__isDraggingOver","getDragStartSelection","__dragStartSelection","setDragImage","_ref","_e$dataTransfer","canvas","flipFactor","Point","flipX","flipY","boundaries","_getCursorBoundaries","pos","left","leftOffset","top","topOffset","multiply","transform","calcTransformMatrix","diff","getScenePoint","subtract","retinaScaling","getCanvasRetinaScaling","bbox","getBoundingRect","correction","vpt","viewportTransform","offset","add","bgc","backgroundColor","styles","cloneStyles","styleOverride","stroke","fill","textBackgroundColor","setSelectionStyles","text","length","dirty","dragImage","toCanvasElement","enableRetinaScaling","setStyle","position","concat","width","border","NONE","height","__dragImageDisposer","remove","getDocumentFromElement","hiddenTextarea","body","appendChild","dataTransfer","x","y","onDragStart","selection","value","_text","slice","join","data","_objectSpread","setData","JSON","stringify","getSelectionStyles","effectAllowed","abortCursorAnimation","canDrop","editable","getActiveControl","defaultPrevented","index","dragStartSelection","targetCanDrop","_ref2","ev","preventDefault","dropTarget","_e$dataTransfer2","didDrop","insert","getData","insertAt","types","includes","parse","trailing","Math","max","selectionStartOffset","removeChars","_reNewline","test","trimEnd","insertChars","setActiveObject","enterEditing","min","_updateTextarea","focus","fire","CHANGED","action","contextTopDirty","requestRenderAll","_ref3","_e$dataTransfer3","dropEffect","clearContextTop","exitEditing","dispose"],"mappings":"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"}