openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

drop_events.js (4701B)


      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     let loadFile = (file, i) => {
     33       if (cm.options.allowDropFileTypes &&
     34           indexOf(cm.options.allowDropFileTypes, file.type) == -1)
     35         return
     36 
     37       let reader = new FileReader
     38       reader.onload = operation(cm, () => {
     39         let content = reader.result
     40         if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) content = ""
     41         text[i] = content
     42         if (++read == n) {
     43           pos = clipPos(cm.doc, pos)
     44           let change = {from: pos, to: pos,
     45                         text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())),
     46                         origin: "paste"}
     47           makeChange(cm.doc, change)
     48           setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)))
     49         }
     50       })
     51       reader.readAsText(file)
     52     }
     53     for (let i = 0; i < n; ++i) loadFile(files[i], i)
     54   } else { // Normal drop
     55     // Don't do a replace if the drop happened inside of the selected text.
     56     if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
     57       cm.state.draggingText(e)
     58       // Ensure the editor is re-focused
     59       setTimeout(() => cm.display.input.focus(), 20)
     60       return
     61     }
     62     try {
     63       let text = e.dataTransfer.getData("Text")
     64       if (text) {
     65         let selected
     66         if (cm.state.draggingText && !cm.state.draggingText.copy)
     67           selected = cm.listSelections()
     68         setSelectionNoUndo(cm.doc, simpleSelection(pos, pos))
     69         if (selected) for (let i = 0; i < selected.length; ++i)
     70           replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag")
     71         cm.replaceSelection(text, "around", "paste")
     72         cm.display.input.focus()
     73       }
     74     }
     75     catch(e){}
     76   }
     77 }
     78 
     79 export function onDragStart(cm, e) {
     80   if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return }
     81   if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return
     82 
     83   e.dataTransfer.setData("Text", cm.getSelection())
     84   e.dataTransfer.effectAllowed = "copyMove"
     85 
     86   // Use dummy image instead of default browsers image.
     87   // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
     88   if (e.dataTransfer.setDragImage && !safari) {
     89     let img = elt("img", null, null, "position: fixed; left: 0; top: 0;")
     90     img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
     91     if (presto) {
     92       img.width = img.height = 1
     93       cm.display.wrapper.appendChild(img)
     94       // Force a relayout, or Opera won't use our image for some obscure reason
     95       img._top = img.offsetTop
     96     }
     97     e.dataTransfer.setDragImage(img, 0, 0)
     98     if (presto) img.parentNode.removeChild(img)
     99   }
    100 }
    101 
    102 export function onDragOver(cm, e) {
    103   let pos = posFromMouse(cm, e)
    104   if (!pos) return
    105   let frag = document.createDocumentFragment()
    106   drawSelectionCursor(cm, pos, frag)
    107   if (!cm.display.dragCursor) {
    108     cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors")
    109     cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv)
    110   }
    111   removeChildrenAndAdd(cm.display.dragCursor, frag)
    112 }
    113 
    114 export function clearDragCursor(cm) {
    115   if (cm.display.dragCursor) {
    116     cm.display.lineSpace.removeChild(cm.display.dragCursor)
    117     cm.display.dragCursor = null
    118   }
    119 }