comparison .cms/lib/codemirror/src/edit/drop_events.js @ 0:78edf6b517a0 draft

24.10
author Coffee CMS <info@coffee-cms.ru>
date Fri, 11 Oct 2024 22:40:23 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:78edf6b517a0
1 import { drawSelectionCursor } from "../display/selection.js"
2 import { operation } from "../display/operations.js"
3 import { clipPos } from "../line/pos.js"
4 import { posFromMouse } from "../measurement/position_measurement.js"
5 import { eventInWidget } from "../measurement/widgets.js"
6 import { makeChange, replaceRange } from "../model/changes.js"
7 import { changeEnd } from "../model/change_measurement.js"
8 import { simpleSelection } from "../model/selection.js"
9 import { setSelectionNoUndo, setSelectionReplaceHistory } from "../model/selection_updates.js"
10 import { ie, presto, safari } from "../util/browser.js"
11 import { elt, removeChildrenAndAdd } from "../util/dom.js"
12 import { e_preventDefault, e_stop, signalDOMEvent } from "../util/event.js"
13 import { indexOf } from "../util/misc.js"
14
15 // Kludge to work around strange IE behavior where it'll sometimes
16 // re-fire a series of drag-related events right after the drop (#1551)
17 let lastDrop = 0
18
19 export function onDrop(e) {
20 let cm = this
21 clearDragCursor(cm)
22 if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
23 return
24 e_preventDefault(e)
25 if (ie) lastDrop = +new Date
26 let pos = posFromMouse(cm, e, true), files = e.dataTransfer.files
27 if (!pos || cm.isReadOnly()) return
28 // Might be a file drop, in which case we simply extract the text
29 // and insert it.
30 if (files && files.length && window.FileReader && window.File) {
31 let n = files.length, text = Array(n), read = 0
32 const markAsReadAndPasteIfAllFilesAreRead = () => {
33 if (++read == n) {
34 operation(cm, () => {
35 pos = clipPos(cm.doc, pos)
36 let change = {from: pos, to: pos,
37 text: cm.doc.splitLines(
38 text.filter(t => t != null).join(cm.doc.lineSeparator())),
39 origin: "paste"}
40 makeChange(cm.doc, change)
41 setSelectionReplaceHistory(cm.doc, simpleSelection(clipPos(cm.doc, pos), clipPos(cm.doc, changeEnd(change))))
42 })()
43 }
44 }
45 const readTextFromFile = (file, i) => {
46 if (cm.options.allowDropFileTypes &&
47 indexOf(cm.options.allowDropFileTypes, file.type) == -1) {
48 markAsReadAndPasteIfAllFilesAreRead()
49 return
50 }
51 let reader = new FileReader
52 reader.onerror = () => markAsReadAndPasteIfAllFilesAreRead()
53 reader.onload = () => {
54 let content = reader.result
55 if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) {
56 markAsReadAndPasteIfAllFilesAreRead()
57 return
58 }
59 text[i] = content
60 markAsReadAndPasteIfAllFilesAreRead()
61 }
62 reader.readAsText(file)
63 }
64 for (let i = 0; i < files.length; i++) readTextFromFile(files[i], i)
65 } else { // Normal drop
66 // Don't do a replace if the drop happened inside of the selected text.
67 if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
68 cm.state.draggingText(e)
69 // Ensure the editor is re-focused
70 setTimeout(() => cm.display.input.focus(), 20)
71 return
72 }
73 try {
74 let text = e.dataTransfer.getData("Text")
75 if (text) {
76 let selected
77 if (cm.state.draggingText && !cm.state.draggingText.copy)
78 selected = cm.listSelections()
79 setSelectionNoUndo(cm.doc, simpleSelection(pos, pos))
80 if (selected) for (let i = 0; i < selected.length; ++i)
81 replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag")
82 cm.replaceSelection(text, "around", "paste")
83 cm.display.input.focus()
84 }
85 }
86 catch(e){}
87 }
88 }
89
90 export function onDragStart(cm, e) {
91 if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return }
92 if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return
93
94 e.dataTransfer.setData("Text", cm.getSelection())
95 e.dataTransfer.effectAllowed = "copyMove"
96
97 // Use dummy image instead of default browsers image.
98 // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
99 if (e.dataTransfer.setDragImage && !safari) {
100 let img = elt("img", null, null, "position: fixed; left: 0; top: 0;")
101 img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
102 if (presto) {
103 img.width = img.height = 1
104 cm.display.wrapper.appendChild(img)
105 // Force a relayout, or Opera won't use our image for some obscure reason
106 img._top = img.offsetTop
107 }
108 e.dataTransfer.setDragImage(img, 0, 0)
109 if (presto) img.parentNode.removeChild(img)
110 }
111 }
112
113 export function onDragOver(cm, e) {
114 let pos = posFromMouse(cm, e)
115 if (!pos) return
116 let frag = document.createDocumentFragment()
117 drawSelectionCursor(cm, pos, frag)
118 if (!cm.display.dragCursor) {
119 cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors")
120 cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv)
121 }
122 removeChildrenAndAdd(cm.display.dragCursor, frag)
123 }
124
125 export function clearDragCursor(cm) {
126 if (cm.display.dragCursor) {
127 cm.display.lineSpace.removeChild(cm.display.dragCursor)
128 cm.display.dragCursor = null
129 }
130 }