Skip to content
Permalink
Browse files

Delay cursor wrapper creation on IE until mouse is up again

To avoid aborting selection dragging when the drag starts at a
position that needs a cursor wrapper.

FIX: Fix mouse-selecting (in IE and Edge) from the end of links and
other positions that cause a cursor wrapper.

See https://discuss.prosemirror.net/t/drag-select-cursor-at-the-end-of-link-not-working-properly-on-ms-edge-ie11/1301
  • Loading branch information...
marijnh committed Apr 24, 2018
1 parent 64f7958 commit 9174b1c5b9fd6e51433cf6df848bd2ed8394475a
Showing with 24 additions and 12 deletions.
  1. +7 −11 src/index.js
  2. +3 −1 src/input.js
  3. +14 −0 src/selection.js
@@ -4,8 +4,9 @@ import {NodeSelection} from "prosemirror-state"
import {scrollRectIntoView, posAtCoords, coordsAtPos, endOfTextblock, storeScrollPos, resetScrollPos} from "./domcoords"
import {docViewDesc} from "./viewdesc"
import {initInput, destroyInput, dispatchEvent, ensureListeners} from "./input"
import {SelectionReader, selectionToDOM} from "./selection"
import {SelectionReader, selectionToDOM, needsCursorWrapper} from "./selection"
import {Decoration, viewDecorations} from "./decoration"
import browser from "./browser"

export {Decoration, DecorationSet} from "./decoration"

@@ -319,10 +320,6 @@ function computeDocDeco(view) {
return [Decoration.node(0, view.state.doc.content.size, attrs)]
}

function nonInclusiveMark(mark) {
return mark.type.spec.inclusive === false
}

function cursorWrapperDOM(visible) {
let span = document.createElement("span")
span.textContent = "\ufeff" // zero-width non-breaking space
@@ -334,12 +331,11 @@ function cursorWrapperDOM(visible) {
}

function updateCursorWrapper(view) {
let {$head, $anchor, visible} = view.state.selection
let $pos = $head.pos == $anchor.pos && (!visible || $head.parent.inlineContent) ? $head : null
if ($pos && (!visible ||
view.state.storedMarks ||
$pos.parent.content.length == 0 ||
$pos.parentOffset && !$pos.textOffset && $pos.nodeBefore.marks.some(nonInclusiveMark))) {
let $pos = needsCursorWrapper(view.state)
// On IE/Edge, moving the DOM selection will abort a mouse drag, so
// there we delay the creation of the wrapper when the mouse is down.
if ($pos && !(browser.ie && view.mouseDown)) {
let visible = view.state.selection.visible
// Needs a cursor wrapper
let marks = view.state.storedMarks || $pos.marks()
let spec = {isCursorWrapper: true, marks, raw: true, visible}
@@ -5,7 +5,7 @@ import {captureKeyDown} from "./capturekeys"
import {DOMChange} from "./domchange"
import {parseFromClipboard, serializeForClipboard} from "./clipboard"
import {DOMObserver} from "./domobserver"
import {selectionBetween} from "./selection"
import {selectionBetween, needsCursorWrapper} from "./selection"

// A collection of DOM events that occur within the editor, and callback functions
// to invoke when the event fires.
@@ -294,6 +294,8 @@ class MouseDown {
return

if (this.allowDefault) {
// Force a cursor wrapper redraw if this was suppressed (to avoid an issue with IE drag-selection)
if (browser.ie && needsCursorWrapper(this.view.state)) this.view.updateState(this.view.state)
this.view.selectionReader.poll("pointer")
} else if (handleSingleClick(this.view, this.pos.pos, this.pos.inside, event, this.selectNode)) {
event.preventDefault()
@@ -309,3 +309,17 @@ function hasSelection(view) {
return false
}
}

function nonInclusiveMark(mark) {
return mark.type.spec.inclusive === false
}

export function needsCursorWrapper(state) {
let {$head, $anchor, visible} = state.selection
let $pos = $head.pos == $anchor.pos && (!visible || $head.parent.inlineContent) ? $head : null
if ($pos && (!visible || state.storedMarks || $pos.parent.content.length == 0 ||
$pos.parentOffset && !$pos.textOffset && $pos.nodeBefore.marks.some(nonInclusiveMark)))
return $pos
else
return null
}

0 comments on commit 9174b1c

Please sign in to comment.
You can’t perform that action at this time.