From a938c55e0a08d82abbd200a8e7609ceaa8ee539a Mon Sep 17 00:00:00 2001
From: Stephen Blott
Date: Sun, 18 Jan 2015 13:07:39 +0000
Subject: Give focusInput a memory.
- Track the most recently-focused input.
- When focusInput is launched (with a count of 1) start with the most
recently focused input.
This does two things:
- If the user is editing an element then comes back, they end up back
where they started.
- It gives focusInput a memory.
---
content_scripts/vimium_frontend.coffee | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 35d92f3c..c49c27e2 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -331,6 +331,17 @@ 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
+
+ (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.
@@ -345,7 +356,11 @@ extend window,
return if visibleInputs.length == 0
- selectedInputIndex = Math.min(count - 1, visibleInputs.length - 1)
+ 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")
--
cgit v1.2.3
From 13592dc5016eff6bf84384a8cef62d1ada1ac80d Mon Sep 17 00:00:00 2001
From: Stephen Blott
Date: Sun, 18 Jan 2015 13:21:49 +0000
Subject: Give focusInput a memory; add tests.
---
content_scripts/vimium_frontend.coffee | 6 +++++-
tests/dom_tests/dom_tests.coffee | 17 +++++++++++++++++
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index c49c27e2..abcf2b36 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -338,7 +338,11 @@ getFocusedElementIndexByRecency = do ->
installListener window, "focus", (event) ->
focusedElement = event.target if DomUtils.isEditable event.target
- (elements) ->
+ # Only for tests.
+ window.resetFocusInputFocusedElement = ->
+ focusedElement = null
+
+ (elements = null) ->
Math.max 0, elements.indexOf focusedElement
extend window,
diff --git a/tests/dom_tests/dom_tests.coffee b/tests/dom_tests/dom_tests.coffee
index c73e0885..8cb0c41a 100644
--- a/tests/dom_tests/dom_tests.coffee
+++ b/tests/dom_tests/dom_tests.coffee
@@ -184,10 +184,12 @@ context "Input focus",
"
document.getElementById("test-div").innerHTML = testContent
backupStackState()
+ resetFocusInputFocusedElement()
tearDown ->
document.getElementById("test-div").innerHTML = ""
restoreStackState()
+ resetFocusInputFocusedElement()
should "focus the right element", ->
focusInput 1
@@ -204,10 +206,25 @@ 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")
+
+ 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
--
cgit v1.2.3
From d8f2446261887cb9affc50caf27b5793f0339edc Mon Sep 17 00:00:00 2001
From: Stephen Blott
Date: Sun, 18 Jan 2015 15:10:49 +0000
Subject: Give focusInput a memory (fix typo).
---
content_scripts/vimium_frontend.coffee | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index abcf2b36..8b73c766 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -342,7 +342,7 @@ getFocusedElementIndexByRecency = do ->
window.resetFocusInputFocusedElement = ->
focusedElement = null
- (elements = null) ->
+ (elements) ->
Math.max 0, elements.indexOf focusedElement
extend window,
--
cgit v1.2.3
From 9d7185b78b366abafe52faeb18ec039b242e02b9 Mon Sep 17 00:00:00 2001
From: Stephen Blott
Date: Sun, 18 Jan 2015 21:39:00 +0000
Subject: Give focusInput a memory (fix typo).
---
content_scripts/vimium_frontend.coffee | 145 ++++++++++++++++-----------------
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",
"
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
--
cgit v1.2.3
From 7450e1cfc57231457c894d372774c391bf13ac68 Mon Sep 17 00:00:00 2001
From: Stephen Blott
Date: Sun, 18 Jan 2015 21:43:28 +0000
Subject: Give focusInput a memory (refactor).
This makes the diff look big, but that's mainly due to a change in
the indentation.
---
content_scripts/vimium_frontend.coffee | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 6cc686d2..725d8a53 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -332,21 +332,23 @@ extend window,
new VisualMode()
focusInput: do ->
- # Track the most-recently focused input element.
- focusedElement = null
+ # Track the most recently focused input element.
+ recentlyFocusedElement = null
handlerStack.push
+ _name: "focus-input-tracker"
focus: (event) ->
- focusedElement = event.target if DomUtils.isEditable event.target
+ recentlyFocusedElement = event.target if DomUtils.isEditable event.target
+ true
(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)
+ 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)
+ element = resultSet.snapshotItem i
+ rect = DomUtils.getVisibleClientRect element
continue if rect == null
{ element: element, rect: rect }
@@ -354,13 +356,14 @@ extend window,
selectedInputIndex =
if count == 1
+ # As the starting index, we pick that of the most recently focused input element (or 0).
elements = visibleInputs.map (visibleInput) -> visibleInput.element
- Math.max 0, elements.indexOf focusedElement
+ Math.max 0, elements.indexOf recentlyFocusedElement
else
Math.min(count, visibleInputs.length) - 1
hints = for tuple in visibleInputs
- hint = document.createElement("div")
+ hint = document.createElement "div"
hint.className = "vimiumReset internalVimiumInputHint vimiumInputHint"
# minus 1 for the border
--
cgit v1.2.3