diff options
| author | Stephen Blott | 2015-01-18 21:39:00 +0000 |
|---|---|---|
| committer | Stephen Blott | 2015-01-18 21:39:00 +0000 |
| commit | 9d7185b78b366abafe52faeb18ec039b242e02b9 (patch) | |
| tree | 374318338309ee4de62e3e0ce1e49f5f4eabcc4a | |
| parent | 7ed25b7a757a0b3d8d8cf14c60fd8e0e0d237835 (diff) | |
| download | vimium-9d7185b78b366abafe52faeb18ec039b242e02b9.tar.bz2 | |
Give focusInput a memory (fix typo).
| -rw-r--r-- | content_scripts/vimium_frontend.coffee | 145 | ||||
| -rw-r--r-- | tests/dom_tests/dom_tests.coffee | 13 |
2 files changed, 70 insertions, 88 deletions
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 27e813c9..6cc686d2 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -331,84 +331,77 @@ extend window, enterVisualMode: => new VisualMode() -# Track the most-recently focused input element. This is used by focusInput to decide which input to initially -# highlight. -getFocusedElementIndexByRecency = do -> - focusedElement = null - installListener window, "focus", (event) -> - focusedElement = event.target if DomUtils.isEditable event.target - - # Only for tests. - window.resetFocusInputFocusedElement = -> + focusInput: do -> + # Track the most-recently focused input element. focusedElement = null - - (elements) -> - Math.max 0, elements.indexOf focusedElement - -extend window, - focusInput: (count) -> - # Focus the first input element on the page, and create overlays to highlight all the input elements, with - # the currently-focused element highlighted specially. Tabbing will shift focus to the next input element. - # Pressing any other key will remove the overlays and the special tab behavior. - resultSet = DomUtils.evaluateXPath(textInputXPath, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE) - visibleInputs = - for i in [0...resultSet.snapshotLength] by 1 - element = resultSet.snapshotItem(i) - rect = DomUtils.getVisibleClientRect(element) - continue if rect == null - { element: element, rect: rect } - - return if visibleInputs.length == 0 - - selectedInputIndex = - if count == 1 - getFocusedElementIndexByRecency visibleInputs.map (visibleInput) -> visibleInput.element - else - Math.min(count, visibleInputs.length) - 1 - - hints = for tuple in visibleInputs - hint = document.createElement("div") - hint.className = "vimiumReset internalVimiumInputHint vimiumInputHint" - - # minus 1 for the border - hint.style.left = (tuple.rect.left - 1) + window.scrollX + "px" - hint.style.top = (tuple.rect.top - 1) + window.scrollY + "px" - hint.style.width = tuple.rect.width + "px" - hint.style.height = tuple.rect.height + "px" - - hint - - new class FocusSelector extends Mode - constructor: -> - super - name: "focus-selector" - badge: "?" - # We share a singleton with PostFindMode. That way, a new FocusSelector displaces any existing - # PostFindMode. - singleton: PostFindMode - exitOnClick: true - keydown: (event) => - if event.keyCode == KeyboardUtils.keyCodes.tab - hints[selectedInputIndex].classList.remove 'internalVimiumSelectedInputHint' - selectedInputIndex += hints.length + (if event.shiftKey then -1 else 1) - selectedInputIndex %= hints.length - hints[selectedInputIndex].classList.add 'internalVimiumSelectedInputHint' - visibleInputs[selectedInputIndex].element.focus() - @suppressEvent - else unless event.keyCode == KeyboardUtils.keyCodes.shiftKey - @exit() - @continueBubbling - - @onExit -> DomUtils.removeElement hintContainingDiv - hintContainingDiv = DomUtils.addElementList hints, - id: "vimiumInputMarkerContainer" - className: "vimiumReset" - - visibleInputs[selectedInputIndex].element.focus() - if visibleInputs.length == 1 - @exit() + handlerStack.push + focus: (event) -> + focusedElement = event.target if DomUtils.isEditable event.target + + (count) -> + # Focus the first input element on the page, and create overlays to highlight all the input elements, with + # the currently-focused element highlighted specially. Tabbing will shift focus to the next input element. + # Pressing any other key will remove the overlays and the special tab behavior. + resultSet = DomUtils.evaluateXPath(textInputXPath, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE) + visibleInputs = + for i in [0...resultSet.snapshotLength] by 1 + element = resultSet.snapshotItem(i) + rect = DomUtils.getVisibleClientRect(element) + continue if rect == null + { element: element, rect: rect } + + return if visibleInputs.length == 0 + + selectedInputIndex = + if count == 1 + elements = visibleInputs.map (visibleInput) -> visibleInput.element + Math.max 0, elements.indexOf focusedElement else - hints[selectedInputIndex].classList.add 'internalVimiumSelectedInputHint' + Math.min(count, visibleInputs.length) - 1 + + hints = for tuple in visibleInputs + hint = document.createElement("div") + hint.className = "vimiumReset internalVimiumInputHint vimiumInputHint" + + # minus 1 for the border + hint.style.left = (tuple.rect.left - 1) + window.scrollX + "px" + hint.style.top = (tuple.rect.top - 1) + window.scrollY + "px" + hint.style.width = tuple.rect.width + "px" + hint.style.height = tuple.rect.height + "px" + + hint + + new class FocusSelector extends Mode + constructor: -> + super + name: "focus-selector" + badge: "?" + # We share a singleton with PostFindMode. That way, a new FocusSelector displaces any existing + # PostFindMode. + singleton: PostFindMode + exitOnClick: true + keydown: (event) => + if event.keyCode == KeyboardUtils.keyCodes.tab + hints[selectedInputIndex].classList.remove 'internalVimiumSelectedInputHint' + selectedInputIndex += hints.length + (if event.shiftKey then -1 else 1) + selectedInputIndex %= hints.length + hints[selectedInputIndex].classList.add 'internalVimiumSelectedInputHint' + visibleInputs[selectedInputIndex].element.focus() + @suppressEvent + else unless event.keyCode == KeyboardUtils.keyCodes.shiftKey + @exit() + @continueBubbling + + @onExit -> DomUtils.removeElement hintContainingDiv + hintContainingDiv = DomUtils.addElementList hints, + id: "vimiumInputMarkerContainer" + className: "vimiumReset" + + visibleInputs[selectedInputIndex].element.focus() + if visibleInputs.length == 1 + @exit() + else + hints[selectedInputIndex].classList.add 'internalVimiumSelectedInputHint' # Decide whether this keyChar should be passed to the underlying page. # Keystrokes are *never* considered passKeys if the keyQueue is not empty. So, for example, if 't' is a diff --git a/tests/dom_tests/dom_tests.coffee b/tests/dom_tests/dom_tests.coffee index f67ebc88..a4713a72 100644 --- a/tests/dom_tests/dom_tests.coffee +++ b/tests/dom_tests/dom_tests.coffee @@ -184,12 +184,10 @@ context "Input focus", <input type='password' id='third' value='some value'/>" document.getElementById("test-div").innerHTML = testContent backupStackState() - resetFocusInputFocusedElement() tearDown -> document.getElementById("test-div").innerHTML = "" restoreStackState() - resetFocusInputFocusedElement() should "focus the right element", -> focusInput 1 @@ -204,25 +202,16 @@ context "Input focus", focusInput 1 handlerStack.bubbleEvent 'focus', target: document.activeElement assert.isTrue InsertMode.permanentInstance.isActive() - # deactivate the tabbing mode and its overlays - handlerStack.bubbleEvent 'keydown', mockKeyboardEvent("A") focusInput 100 handlerStack.bubbleEvent 'focus', target: document. activeElement assert.isTrue InsertMode.permanentInstance.isActive() - # deactivate the tabbing mode and its overlays - handlerStack.bubbleEvent 'keydown', mockKeyboardEvent("A") should "select the previously-focused input when count is 1", -> focusInput 100 - assert.equal "third", document.activeElement.id - # deactivate the tabbing mode and its overlays - handlerStack.bubbleEvent 'keydown', mockKeyboardEvent("A") - + handlerStack.bubbleEvent 'focus', target: document. activeElement focusInput 1 assert.equal "third", document.activeElement.id - # deactivate the tabbing mode and its overlays - handlerStack.bubbleEvent 'keydown', mockKeyboardEvent("A") # TODO: these find prev/next link tests could be refactored into unit tests which invoke a function which has # a tighter contract than goNext(), since they test minor aspects of goNext()'s link matching behavior, and we |
