@@ -79,6 +79,14 @@ const alphabetsContainingSpaces = new RegExp(
79
79
')$' ,
80
80
) ;
81
81
82
+ /**
83
+ * Spell-checking on mobile devices does not stop at inline tags like b, i, u
84
+ * but it hits a barrier on different nodes like div for example. The code
85
+ * below constructs a crude selector to match if the node is such a barrier.
86
+ */
87
+ const spellCheckingIgnoredTags = [ 'a' , 'b' , 'i' , 'u' , 'span' , 'font' , 'superscript' , 'subscript' ] ;
88
+ const spellCheckingBarrier = spellCheckingIgnoredTags . map ( t => `:not(${ t } )` ) . join ( '' ) ;
89
+
82
90
/**
83
91
* These javascript event types might, in case of safari or spell-checking
84
92
* keyboard, trigger dom events in multiple javascript stacks. They will require
@@ -941,8 +949,11 @@ export class EventNormalizer {
941
949
| DeleteWordAction
942
950
| DeleteHardLineAction
943
951
| DeleteContentAction {
944
- const isInsertOrRemoveAction = hasMutatedElements && ! inputTypeCommands . has ( inputType ) ;
945
- if ( isInsertOrRemoveAction ) {
952
+ const isMutationAction = hasMutatedElements && ! inputTypeCommands . has ( inputType ) ;
953
+ // These two particular keys might have been defaultPrevented to avoid
954
+ // flickering and thus trigger no mutation but still need to be handled.
955
+ const isRemoveAction = key === 'Backspace' || key === 'Delete' ;
956
+ if ( isMutationAction || isRemoveAction ) {
946
957
if ( key === 'Backspace' || key === 'Delete' ) {
947
958
return this . _getRemoveAction ( key , inputType ) ;
948
959
} else if ( key === 'Enter' ) {
@@ -1599,6 +1610,26 @@ export class EventNormalizer {
1599
1610
const selection = this . _getSelection ( ) ;
1600
1611
const [ offsetNode , offset ] = targetDeepest ( selection . anchorNode , selection . anchorOffset ) ;
1601
1612
this . _initialCaretPosition = { offsetNode, offset } ;
1613
+
1614
+ // Backspace cannot always be prevented as preventing a backspace in a
1615
+ // text node would throw off spell-checking on mobile for example.
1616
+ if ( ev . key === 'Backspace' ) {
1617
+ const forward = selection . direction === Direction . FORWARD ;
1618
+ const start = forward ? selection . anchorNode : selection . focusNode ;
1619
+ const startOffset = forward ? selection . anchorOffset : selection . focusOffset ;
1620
+ if (
1621
+ ( startOffset === 0 && ! start . previousSibling ) ||
1622
+ selection . anchorNode . parentElement . closest ( spellCheckingBarrier ) !==
1623
+ selection . focusNode . parentElement . closest ( spellCheckingBarrier )
1624
+ ) {
1625
+ // Allowed cases for preventing is:
1626
+ // 1. At the start of the node
1627
+ // 2. When the anchor and focus of the selection are set in
1628
+ // nodes that are separated of each other by a node that is
1629
+ // considered to be a barrier for spell-checking purposes.
1630
+ ev . preventDefault ( ) ;
1631
+ }
1632
+ }
1602
1633
}
1603
1634
/**
1604
1635
* Set internal properties of the pointer down event to retrieve them later
0 commit comments