Skip to content
Permalink
Browse files

Work around IE11 corrupting the DOM selection after backspacing

When you press backspace after the first character in a textblock,
it'd force-move the selection after applying that change, sometimes to
the end of the textblock, sometimes to the end of the document.

This ignores such selection changes and forces the selection back to
where it should be.

FIX: Fix an issue where backspacing out the first character in a
textblock would cause IE11 to move the selection to some incorrect
position.

See https://discuss.prosemirror.net/t/backspace-or-canc-on-ie11/2053
  • Loading branch information...
marijnh committed Jul 3, 2019
1 parent a607dc7 commit d69eb94dac043243292f818831a7abcee8769f7f
Showing with 16 additions and 7 deletions.
  1. +8 −5 src/domchange.js
  2. +8 −2 src/domobserver.js
@@ -1,7 +1,7 @@
import {Fragment, DOMParser} from "prosemirror-model"
import {Selection, TextSelection} from "prosemirror-state"

import {selectionBetween, selectionFromDOM} from "./selection"
import {selectionBetween, selectionFromDOM, selectionToDOM} from "./selection"
import {selectionCollapsed, keyEvent} from "./dom"
import browser from "./browser"

@@ -143,10 +143,7 @@ export function readDOMChange(view, from, to, typeOver) {
if (view.state.selection.anchor > change.start &&
looksLikeJoin(doc, change.start, change.endA, $from, $to) &&
view.someProp("handleKeyDown", f => f(view, keyEvent(8, "Backspace")))) {
if (browser.android && browser.chrome) { // #820
view.domObserver.suppressSelectionUpdates = true
setTimeout(() => view.domObserver.suppressSelectionUpdates = false, 50)
}
if (browser.android && browser.chrome) view.domObserver.suppressSelectionUpdates() // #820
return
}

@@ -155,6 +152,12 @@ export function readDOMChange(view, from, to, typeOver) {
let tr, storedMarks, markChange, $from1
if ($from.sameParent($to) && $from.parent.inlineContent) {
if ($from.pos == $to.pos) { // Deletion
// IE11 sometimes weirdly moves the DOM selection around after
// backspacing out the first element in a textblock
if (browser.ie && browser.ie_version <= 11 && $from.parentOffset == 0) {
view.domObserver.suppressSelectionUpdates()
setTimeout(() => selectionToDOM(view), 20)
}
tr = view.state.tr.delete(chFrom, chTo)
storedMarks = doc.resolve(change.start).marksAcross(doc.resolve(change.endA))
} else if ( // Adding or removing a mark
@@ -37,6 +37,7 @@ export class DOMObserver {
}
}
this.onSelectionChange = this.onSelectionChange.bind(this)
this.suppressingSelectionUpdates = false
}

start() {
@@ -66,9 +67,14 @@ export class DOMObserver {
this.view.dom.ownerDocument.removeEventListener("selectionchange", this.onSelectionChange)
}

suppressSelectionUpdates() {
this.suppressingSelectionUpdates = true
setTimeout(() => this.suppressingSelectionUpdates = false, 50)
}

onSelectionChange() {
if (!hasFocusAndSelection(this.view)) return
if (this.suppressSelectionUpdates) return selectionToDOM(this.view)
if (this.suppressingSelectionUpdates) return selectionToDOM(this.view)
this.flush()
}

@@ -85,7 +91,7 @@ export class DOMObserver {
}

let sel = this.view.root.getSelection()
let newSel = !this.currentSelection.eq(sel) && hasSelection(this.view)
let newSel = !this.suppressingSelectionUpdates && !this.currentSelection.eq(sel) && hasSelection(this.view)

let from = -1, to = -1, typeOver = false
if (this.view.editable) {

0 comments on commit d69eb94

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