aboutsummaryrefslogtreecommitdiffstats
path: root/content_scripts/mode_insert.coffee
diff options
context:
space:
mode:
Diffstat (limited to 'content_scripts/mode_insert.coffee')
-rw-r--r--content_scripts/mode_insert.coffee80
1 files changed, 37 insertions, 43 deletions
diff --git a/content_scripts/mode_insert.coffee b/content_scripts/mode_insert.coffee
index 41d82add..5280aada 100644
--- a/content_scripts/mode_insert.coffee
+++ b/content_scripts/mode_insert.coffee
@@ -17,75 +17,69 @@ isEmbed =(element) ->
isFocusable =(element) ->
isEditable(element) or isEmbed element
+# This mode is installed when insert mode is active.
+class InsertMode extends Mode
+ constructor: (@insertModeLock = null) ->
+ super
+ name: "insert"
+ badge: "I"
+ singleton: InsertMode
+ keydown: (event) => @stopBubblingAndTrue
+ keypress: (event) => @stopBubblingAndTrue
+ keyup: (event) => @stopBubblingAndTrue
+ exitOnEscape: true
+ exitOnBlur: @insertModeLock
+
+ exit: (event = null) ->
+ super()
+ element = event?.srcElement
+ if element and isFocusable element
+ # Remove the focus so the user can't just get himself back into insert mode by typing in the same
+ # input box.
+ # NOTE(smblott, 2014/12/22) Including embeds for .blur() here is experimental. It appears to be the
+ # right thing to do for most common use cases. However, it could also cripple flash-based sites and
+ # games. See discussion in #1211 and #1194.
+ element.blur()
+
# Automatically trigger insert mode:
# - On a keydown event in a contentEditable element.
# - When a focusable element receives the focus.
#
+# The trigger can be suppressed via triggerSuppressor; see InsertModeBlocker, below.
# This mode is permanently installed fairly low down on the handler stack.
class InsertModeTrigger extends Mode
constructor: ->
super
name: "insert-trigger"
keydown: (event) =>
- return @continueBubbling if InsertModeTrigger.isSuppressed()
- # Some sites (e.g. inbox.google.com) change the contentEditable attribute on the fly (see #1245);
- # and unfortunately, the focus event happens *before* the change is made. Therefore, we need to
- # check again whether the active element is contentEditable.
- return @continueBubbling unless document.activeElement?.isContentEditable
- new InsertMode document.activeElement
- @stopBubblingAndTrue
+ triggerSuppressor.unlessSuppressed =>
+ # Some sites (e.g. inbox.google.com) change the contentEditable attribute on the fly (see #1245);
+ # and unfortunately, the focus event happens *before* the change is made. Therefore, we need to
+ # check again whether the active element is contentEditable.
+ return @continueBubbling unless document.activeElement?.isContentEditable
+ new InsertMode document.activeElement
+ @stopBubblingAndTrue
@push
focus: (event) =>
- @alwaysContinueBubbling =>
- return @continueBubbling if InsertModeTrigger.isSuppressed()
+ triggerSuppressor.unlessSuppressed =>
return if not isFocusable event.target
new InsertMode event.target
# We may already have focussed an input, so check.
new InsertMode document.activeElement if document.activeElement and isEditable document.activeElement
- # Allow other modes (notably InsertModeBlocker, below) to suppress this trigger. All static.
- @suppressors: 0
- @isSuppressed: -> 0 < @suppressors
- @suppress: -> @suppressors += 1
- @unsuppress: -> @suppressors -= 1
+# Used by InsertModeBlocker to suppress InsertModeTrigger; see below.
+triggerSuppressor = new Utils.Suppressor true
# Suppresses InsertModeTrigger. This is used by various modes (usually by inheritance) to prevent
# unintentionally dropping into insert mode on focusable elements.
class InsertModeBlocker extends Mode
constructor: (options = {}) ->
- InsertModeTrigger.suppress()
+ triggerSuppressor.suppress()
options.name ||= "insert-blocker"
super options
-
- exit: ->
- super()
- InsertModeTrigger.unsuppress()
-
-# This mode is installed when insert mode is active.
-class InsertMode extends Mode
- constructor: (@insertModeLock = null) ->
- super
- name: "insert"
- badge: "I"
- singleton: InsertMode
- keydown: (event) => @stopBubblingAndTrue
- keypress: (event) => @stopBubblingAndTrue
- keyup: (event) => @stopBubblingAndTrue
- exitOnEscape: true
- exitOnBlur: @insertModeLock
-
- exit: (event = null) ->
- super()
- element = event?.srcElement
- if element and isFocusable element
- # Remove the focus so the user can't just get himself back into insert mode by typing in the same
- # input box.
- # NOTE(smblott, 2014/12/22) Including embeds for .blur() here is experimental. It appears to be the
- # right thing to do for most common use cases. However, it could also cripple flash-based sites and
- # games. See discussion in #1211 and #1194.
- element.blur()
+ @onExit -> triggerSuppressor.unsuppress()
root = exports ? window
root.InsertMode = InsertMode