1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
# NOTE(smblott). Ultimately, all of the FindMode-related code should be moved to this file.
# When we use find mode, the selection/focus can land in a focusable/editable element. In this situation,
# special considerations apply. We implement three special cases:
# 1. Disable keyboard events in insert mode, because the user hasn't asked to enter insert mode.
# 2. Prevent printable keyboard events from propagating to the page; see #1415.
# 3. If the very-next keystroke is Escape, then drop immediately into insert mode.
#
class PostFindMode extends InputController
constructor: (findModeAnchorNode) ->
# Locate the element we need to protect. In most cases, it's just the active element.
element =
if document.activeElement and DomUtils.isEditable document.activeElement
document.activeElement
else
# For contentEditable elements, chrome does not focus them, although they are activated by keystrokes.
# We need to find the element ourselves.
element = findModeAnchorNode
element = element.parentElement while element.parentElement?.isContentEditable
if element.isContentEditable
if DomUtils.isDOMDescendant element, findModeAnchorNode
# TODO(smblott). We shouldn't really need to focus the element, here. Need to look into why this
# is necessary.
element.focus()
element
return unless element
super
name: "post-find"
exitOnBlur: element
exitOnClick: true
keydown: (event) -> InsertMode.suppressEvent event # Truthy.
keypress: (event) -> InsertMode.suppressEvent event # Truthy.
keyup: (event) =>
@alwaysContinueBubbling =>
if document.getSelection().type != "Range"
# If the selection is no longer a range, then the user is interacting with the element, so get out
# of the way. See Option 5c from #1415.
@exit()
else
InsertMode.suppressEvent event
# If the very-next keydown is Esc, drop immediately into insert mode.
self = @
@push
_name: "mode-#{@id}/handle-escape"
keydown: (event) ->
if KeyboardUtils.isEscape event
DomUtils.suppressKeyupAfterEscape handlerStack
self.exit()
false # Suppress event.
else
@remove()
true # Continue bubbling.
# Prevent printable keyboard events from propagating to the page; see #1415.
do =>
handler = (event) =>
if event.srcElement == element and KeyboardUtils.isPrintable event
@suppressEvent
else
@continueBubbling
# Note. We use unshift here, instead of push. We see events *after* normal mode, so we only see
# unmapped keys.
@unshift
_name: "mode-#{@id}/suppressPrintableEvents"
keydown: handler
keypress: handler
keyup: handler
chooseBadge: (badge) ->
# If PostFindMode is active, then we don't want the "I" badge from insert mode.
InsertMode.suppressEvent badge
root = exports ? window
root.PostFindMode = PostFindMode
|