diff options
| author | Stephen Blott | 2015-01-14 07:57:09 +0000 |
|---|---|---|
| committer | Stephen Blott | 2015-01-14 09:46:00 +0000 |
| commit | 9b0a48955c61c262cc4428b2360938d4b54d2d41 (patch) | |
| tree | 3abda5d154e96ad019eb9aa67ff59a362775fa23 /content_scripts/mode_insert.coffee | |
| parent | 7e1c3475ed9241a5e1fbf78b8134e6ed669ea906 (diff) | |
| download | vimium-9b0a48955c61c262cc4428b2360938d4b54d2d41.tar.bz2 | |
Modes; substantial reworking of insert mode (and friends).
Diffstat (limited to 'content_scripts/mode_insert.coffee')
| -rw-r--r-- | content_scripts/mode_insert.coffee | 69 |
1 files changed, 52 insertions, 17 deletions
diff --git a/content_scripts/mode_insert.coffee b/content_scripts/mode_insert.coffee index 678e35cc..4be9c589 100644 --- a/content_scripts/mode_insert.coffee +++ b/content_scripts/mode_insert.coffee @@ -3,32 +3,67 @@ class InsertMode extends Mode constructor: (options = {}) -> defaults = name: "insert" - exitOnEscape: true - keydown: (event) => @handler event - keypress: (event) => @handler event - keyup: (event) => @handler event + keydown: (event) => @handleKeydownEvent event + keypress: (event) => @handleKeyEvent event + keyup: (event) => @handleKeyEvent event super extend defaults, options + @insertModeLock = if options.targetElement? then options.targetElement else null @push - "blur": => @exit() + "blur": => @alwaysContinueBubbling => + if DomUtils.isFocusable event.target + @exit event.target + Mode.updateBadge() + "focus": (event) => @alwaysContinueBubbling => + @insertModeLock = event.target if DomUtils.isFocusable event.target - active: -> - document.activeElement and DomUtils.isFocusable document.activeElement + if @insertModeLock == null + # We may already have focused an input element, so check. + @insertModeLock = event.target if document.activeElement and DomUtils.isFocusable document.activeElement - handler: (event) -> - if @active() then @stopBubblingAndTrue else @continueBubbling + isActive: -> + return true if @insertModeLock != null + # Some sites (e.g. inbox.google.com) change the contentEditable property on the fly (see #1245); and + # unfortunately, the focus event fires *before* the change. Therefore, we need to re-check whether the + # active element is contentEditable. + @insertModeLock = document.activeElement if document.activeElement?.isContentEditable + @insertModeLock != null - exit: () -> - document.activeElement.blur() if @active() - if @options.permanentInsertMode - # We don't really exit if we're permanently installed. - Mode.updateBadge() - else - super() + handleKeydownEvent: (event) -> + return @continueBubbling if event == InsertMode.suppressedEvent or not @isActive() + return @stopBubblingAndTrue unless KeyboardUtils.isEscape event + DomUtils.suppressKeyupAfterEscape handlerStack + if DomUtils.isFocusable event.srcElement + # Remove 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() etc. 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. + event.srcElement.blur() + @exit() + Mode.updateBadge() + @suppressEvent + + # Handles keypress and keyup events. + handleKeyEvent: (event) -> + if @isActive() and event != InsertMode.suppressedEvent then @stopBubblingAndTrue else @continueBubbling + + exit: (target) -> + if target == undefined or target == @insertModeLock + if @options.targetElement? + super() + else + # If @options.targetElement isn't set, then this is the permanently-installed instance from the front + # end. So, we don't actually exit; instead, we just reset ourselves. + @insertModeLock = null chooseBadge: (badge) -> - badge.badge ||= "I" if @active() + badge.badge ||= "I" if @isActive() + + # Static stuff to allow PostFindMode to suppress insert mode. + @suppressedEvent: null + @suppressEvent: (event) -> @suppressedEvent = event root = exports ? window root.InsertMode = InsertMode |
