From 51fa63a5e97167b015acf7b80d673d081c2b91da Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 24 Oct 2017 18:36:23 +0100 Subject: Move NormalMode to its own content script --- content_scripts/mode_normal.coffee | 38 ++++++++++++++++++++++++++++++++++ content_scripts/vimium_frontend.coffee | 35 ------------------------------- 2 files changed, 38 insertions(+), 35 deletions(-) create mode 100644 content_scripts/mode_normal.coffee (limited to 'content_scripts') diff --git a/content_scripts/mode_normal.coffee b/content_scripts/mode_normal.coffee new file mode 100644 index 00000000..3e1b1ee3 --- /dev/null +++ b/content_scripts/mode_normal.coffee @@ -0,0 +1,38 @@ +class NormalMode extends KeyHandlerMode + constructor: (options = {}) -> + defaults = + name: "normal" + indicator: false # There is normally no mode indicator in normal mode. + commandHandler: @commandHandler.bind this + + super extend defaults, options + + chrome.storage.local.get "normalModeKeyStateMapping", (items) => + @setKeyMapping items.normalModeKeyStateMapping + + chrome.storage.onChanged.addListener (changes, area) => + if area == "local" and changes.normalModeKeyStateMapping?.newValue + @setKeyMapping changes.normalModeKeyStateMapping.newValue + + commandHandler: ({command: registryEntry, count}) -> + count *= registryEntry.options.count ? 1 + count = 1 if registryEntry.noRepeat + + if registryEntry.repeatLimit? and registryEntry.repeatLimit < count + return unless confirm """ + You have asked Vimium to perform #{count} repetitions of the command: #{registryEntry.description}.\n + Are you sure you want to continue?""" + + if registryEntry.topFrame + # We never return to a UI-component frame (e.g. the help dialog), it might have lost the focus. + sourceFrameId = if window.isVimiumUIComponent then 0 else frameId + chrome.runtime.sendMessage + handler: "sendMessageToFrames", message: {name: "runInTopFrame", sourceFrameId, registryEntry} + else if registryEntry.background + chrome.runtime.sendMessage {handler: "runBackgroundCommand", registryEntry, count} + else + Utils.invokeCommandString registryEntry.command, count, {registryEntry} + +root = exports ? (window.root ?= {}) +root.NormalMode = NormalMode +extend window, root unless exports? diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 86e3b682..add7b7f4 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -117,41 +117,6 @@ handlerStack.push target = target.parentElement true -class NormalMode extends KeyHandlerMode - constructor: (options = {}) -> - defaults = - name: "normal" - indicator: false # There is normally no mode indicator in normal mode. - commandHandler: @commandHandler.bind this - - super extend defaults, options - - chrome.storage.local.get "normalModeKeyStateMapping", (items) => - @setKeyMapping items.normalModeKeyStateMapping - - chrome.storage.onChanged.addListener (changes, area) => - if area == "local" and changes.normalModeKeyStateMapping?.newValue - @setKeyMapping changes.normalModeKeyStateMapping.newValue - - commandHandler: ({command: registryEntry, count}) -> - count *= registryEntry.options.count ? 1 - count = 1 if registryEntry.noRepeat - - if registryEntry.repeatLimit? and registryEntry.repeatLimit < count - return unless confirm """ - You have asked Vimium to perform #{count} repetitions of the command: #{registryEntry.description}.\n - Are you sure you want to continue?""" - - if registryEntry.topFrame - # We never return to a UI-component frame (e.g. the help dialog), it might have lost the focus. - sourceFrameId = if window.isVimiumUIComponent then 0 else frameId - chrome.runtime.sendMessage - handler: "sendMessageToFrames", message: {name: "runInTopFrame", sourceFrameId, registryEntry} - else if registryEntry.background - chrome.runtime.sendMessage {handler: "runBackgroundCommand", registryEntry, count} - else - Utils.invokeCommandString registryEntry.command, count, {registryEntry} - installModes = -> # Install the permanent modes. The permanently-installed insert mode tracks focus/blur events, and # activates/deactivates itself accordingly. -- cgit v1.2.3 From 0b24e966c6a64864204c7f489063b29e05b2ca34 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 24 Oct 2017 19:03:38 +0100 Subject: Move self-contained normal mode commands to normal mode file --- content_scripts/mode_normal.coffee | 69 ++++++++++++++++++++++++++++++++++ content_scripts/vimium_frontend.coffee | 66 -------------------------------- 2 files changed, 69 insertions(+), 66 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_normal.coffee b/content_scripts/mode_normal.coffee index 3e1b1ee3..a7a8a8b6 100644 --- a/content_scripts/mode_normal.coffee +++ b/content_scripts/mode_normal.coffee @@ -33,6 +33,75 @@ class NormalMode extends KeyHandlerMode else Utils.invokeCommandString registryEntry.command, count, {registryEntry} +NormalModeCommands = + # Scrolling. + scrollToBottom: -> + Marks.setPreviousPosition() + Scroller.scrollTo "y", "max" + scrollToTop: (count) -> + Marks.setPreviousPosition() + Scroller.scrollTo "y", (count - 1) * Settings.get("scrollStepSize") + scrollToLeft: -> Scroller.scrollTo "x", 0 + scrollToRight: -> Scroller.scrollTo "x", "max" + scrollUp: (count) -> Scroller.scrollBy "y", -1 * Settings.get("scrollStepSize") * count + scrollDown: (count) -> Scroller.scrollBy "y", Settings.get("scrollStepSize") * count + scrollPageUp: (count) -> Scroller.scrollBy "y", "viewSize", -1/2 * count + scrollPageDown: (count) -> Scroller.scrollBy "y", "viewSize", 1/2 * count + scrollFullPageUp: (count) -> Scroller.scrollBy "y", "viewSize", -1 * count + scrollFullPageDown: (count) -> Scroller.scrollBy "y", "viewSize", 1 * count + scrollLeft: (count) -> Scroller.scrollBy "x", -1 * Settings.get("scrollStepSize") * count + scrollRight: (count) -> Scroller.scrollBy "x", Settings.get("scrollStepSize") * count + + # Page state. + reload: (count, options) -> + hard = options.registryEntry.options.hard ? false + window.location.reload(hard) + goBack: (count) -> history.go(-count) + goForward: (count) -> history.go(count) + + # Url manipulation. + goUp: (count) -> + url = window.location.href + if (url[url.length - 1] == "/") + url = url.substring(0, url.length - 1) + + urlsplit = url.split("/") + # make sure we haven't hit the base domain yet + if (urlsplit.length > 3) + urlsplit = urlsplit.slice(0, Math.max(3, urlsplit.length - count)) + window.location.href = urlsplit.join('/') + + goToRoot: -> + window.location.href = window.location.origin + + toggleViewSource: -> + chrome.runtime.sendMessage { handler: "getCurrentTabUrl" }, (url) -> + if (url.substr(0, 12) == "view-source:") + url = url.substr(12, url.length - 12) + else + url = "view-source:" + url + chrome.runtime.sendMessage {handler: "openUrlInNewTab", url} + + copyCurrentUrl: -> + chrome.runtime.sendMessage { handler: "getCurrentTabUrl" }, (url) -> + chrome.runtime.sendMessage { handler: "copyToClipboard", data: url } + url = url[0..25] + "...." if 28 < url.length + HUD.showForDuration("Yanked #{url}", 2000) + + # Mode changes. + enterInsertMode: -> + # If a focusable element receives the focus, then we exit and leave the permanently-installed insert-mode + # instance to take over. + new InsertMode global: true, exitOnFocus: true + + enterVisualMode: -> + new VisualMode userLaunchedMode: true + + enterVisualLineMode: -> + new VisualLineMode userLaunchedMode: true + root = exports ? (window.root ?= {}) root.NormalMode = NormalMode +root.NormalModeCommands = NormalModeCommands +extend root, NormalModeCommands extend window, root unless exports? diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index add7b7f4..530e96c3 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -299,74 +299,8 @@ focusThisFrame = (request) -> flashFrame() if request.highlight extend root, - scrollToBottom: -> - Marks.setPreviousPosition() - Scroller.scrollTo "y", "max" - scrollToTop: (count) -> - Marks.setPreviousPosition() - Scroller.scrollTo "y", (count - 1) * Settings.get("scrollStepSize") - scrollToLeft: -> Scroller.scrollTo "x", 0 - scrollToRight: -> Scroller.scrollTo "x", "max" - scrollUp: (count) -> Scroller.scrollBy "y", -1 * Settings.get("scrollStepSize") * count - scrollDown: (count) -> Scroller.scrollBy "y", Settings.get("scrollStepSize") * count - scrollPageUp: (count) -> Scroller.scrollBy "y", "viewSize", -1/2 * count - scrollPageDown: (count) -> Scroller.scrollBy "y", "viewSize", 1/2 * count - scrollFullPageUp: (count) -> Scroller.scrollBy "y", "viewSize", -1 * count - scrollFullPageDown: (count) -> Scroller.scrollBy "y", "viewSize", 1 * count - scrollLeft: (count) -> Scroller.scrollBy "x", -1 * Settings.get("scrollStepSize") * count - scrollRight: (count) -> Scroller.scrollBy "x", Settings.get("scrollStepSize") * count - -extend root, - reload: (count, options) -> - hard = options.registryEntry.options.hard ? false - window.location.reload(hard) - goBack: (count) -> history.go(-count) - goForward: (count) -> history.go(count) - - goUp: (count) -> - url = window.location.href - if (url[url.length - 1] == "/") - url = url.substring(0, url.length - 1) - - urlsplit = url.split("/") - # make sure we haven't hit the base domain yet - if (urlsplit.length > 3) - urlsplit = urlsplit.slice(0, Math.max(3, urlsplit.length - count)) - window.location.href = urlsplit.join('/') - - goToRoot: -> - window.location.href = window.location.origin - mainFrame: -> focusThisFrame highlight: true, forceFocusThisFrame: true - toggleViewSource: -> - chrome.runtime.sendMessage { handler: "getCurrentTabUrl" }, (url) -> - if (url.substr(0, 12) == "view-source:") - url = url.substr(12, url.length - 12) - else - url = "view-source:" + url - chrome.runtime.sendMessage {handler: "openUrlInNewTab", url} - - copyCurrentUrl: -> - # TODO(ilya): When the following bug is fixed, revisit this approach of sending back to the background - # page to copy. - # http://code.google.com/p/chromium/issues/detail?id=55188 - chrome.runtime.sendMessage { handler: "getCurrentTabUrl" }, (url) -> - chrome.runtime.sendMessage { handler: "copyToClipboard", data: url } - url = url[0..25] + "...." if 28 < url.length - HUD.showForDuration("Yanked #{url}", 2000) - - enterInsertMode: -> - # If a focusable element receives the focus, then we exit and leave the permanently-installed insert-mode - # instance to take over. - new InsertMode global: true, exitOnFocus: true - - enterVisualMode: -> - new VisualMode userLaunchedMode: true - - enterVisualLineMode: -> - new VisualLineMode userLaunchedMode: true - passNextKey: (count, options) -> if options.registryEntry.options.normal enterNormalMode count -- cgit v1.2.3 From ca9aa228f1999540063063e6cb86a7baeba9da93 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 24 Oct 2017 19:22:20 +0100 Subject: Move FindMode exit functions into FindMode --- content_scripts/hud.coffee | 6 +++--- content_scripts/mode_find.coffee | 20 +++++++++++++++++++- content_scripts/vimium_frontend.coffee | 23 ++--------------------- 3 files changed, 24 insertions(+), 25 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/hud.coffee b/content_scripts/hud.coffee index 6185d786..7c983cfa 100644 --- a/content_scripts/hud.coffee +++ b/content_scripts/hud.coffee @@ -71,13 +71,13 @@ HUD = focusNode?.focus?() if exitEventIsEnter - handleEnterForFindMode() + FindMode.handleEnter() if FindMode.query.hasResults postExit = -> new PostFindMode else if exitEventIsEscape - # We don't want FindMode to handle the click events that handleEscapeForFindMode can generate, so we + # We don't want FindMode to handle the click events that FindMode.handleEscape can generate, so we # wait until the mode is closed before running it. - postExit = handleEscapeForFindMode + postExit = FindMode.handleEscape @findMode.exit() postExit?() diff --git a/content_scripts/mode_find.coffee b/content_scripts/mode_find.coffee index 5238ab34..8dc3bdcc 100644 --- a/content_scripts/mode_find.coffee +++ b/content_scripts/mode_find.coffee @@ -79,7 +79,7 @@ class FindMode extends Mode exit: (event) -> super() - handleEscapeForFindMode() if event + FindMode.handleEscape() if event restoreSelection: -> range = @initialRange @@ -201,6 +201,24 @@ class FindMode extends Mode @restoreDefaultSelectionHighlight: forTrusted -> document.body.classList.remove("vimiumFindMode") + # The user has found what they're looking for and is finished searching. We enter insert mode, if possible. + @handleEscape: -> + document.body.classList.remove("vimiumFindMode") + # Removing the class does not re-color existing selections. we recreate the current selection so it reverts + # back to the default color. + selection = window.getSelection() + unless selection.isCollapsed + range = window.getSelection().getRangeAt(0) + window.getSelection().removeAllRanges() + window.getSelection().addRange(range) + focusFoundLink() || selectFoundInputElement() + + # Save the query so the user can do further searches with it. + @handleEnter: -> + focusFoundLink() + document.body.classList.add("vimiumFindMode") + FindMode.saveQuery() + checkReturnToViewPort: -> window.scrollTo @scrollX, @scrollY if @options.returnToViewport diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 530e96c3..a01551a8 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -423,25 +423,6 @@ checkIfEnabledForUrl = do -> checkEnabledAfterURLChange = forTrusted -> checkIfEnabledForUrl() if windowIsFocused() -handleEscapeForFindMode = -> - document.body.classList.remove("vimiumFindMode") - # removing the class does not re-color existing selections. we recreate the current selection so it reverts - # back to the default color. - selection = window.getSelection() - unless selection.isCollapsed - range = window.getSelection().getRangeAt(0) - window.getSelection().removeAllRanges() - window.getSelection().addRange(range) - focusFoundLink() || selectFoundInputElement() - -# sends us into insert mode if possible, but does not. -# corresponds approximately to 'nevermind, I have found it already' while means 'I want to save -# this query and do more searches with it' -handleEnterForFindMode = -> - focusFoundLink() - document.body.classList.add("vimiumFindMode") - FindMode.saveQuery() - focusFoundLink = -> if (FindMode.query.hasResults) link = getLinkFromSelection() @@ -604,8 +585,8 @@ root.Frame = Frame root.windowIsFocused = windowIsFocused root.bgLog = bgLog # These are exported for find mode and link-hints mode. -extend root, {handleEscapeForFindMode, handleEnterForFindMode, performFind, performBackwardsFind, - enterFindMode, focusThisFrame} +extend root, {focusFoundLink, selectFoundInputElement, performFind, performBackwardsFind, enterFindMode, + focusThisFrame} # These are exported only for the tests. extend root, {installModes} extend window, root unless exports? -- cgit v1.2.3 From d330ebd648914802453fa1e818ef9dc52de739c8 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 24 Oct 2017 19:25:53 +0100 Subject: Move findAndFocus into FindMode, rename to findNext --- content_scripts/mode_find.coffee | 10 ++++++++++ content_scripts/vimium_frontend.coffee | 14 ++------------ 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_find.coffee b/content_scripts/mode_find.coffee index 8dc3bdcc..d361d4be 100644 --- a/content_scripts/mode_find.coffee +++ b/content_scripts/mode_find.coffee @@ -219,6 +219,16 @@ class FindMode extends Mode document.body.classList.add("vimiumFindMode") FindMode.saveQuery() + @findNext: (backwards) -> + Marks.setPreviousPosition() + FindMode.query.hasResults = FindMode.execute null, {backwards} + + if FindMode.query.hasResults + focusFoundLink() + new PostFindMode() + else + HUD.showForDuration("No matches for '#{FindMode.query.rawQuery}'", 1000) + checkReturnToViewPort: -> window.scrollTo @scrollX, @scrollY if @options.returnToViewport diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index a01551a8..11c952ca 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -438,18 +438,8 @@ selectFoundInputElement = -> DomUtils.isDOMDescendant(findModeAnchorNode, document.activeElement)) DomUtils.simulateSelect(document.activeElement) -findAndFocus = (backwards) -> - Marks.setPreviousPosition() - FindMode.query.hasResults = FindMode.execute null, {backwards} - - if FindMode.query.hasResults - focusFoundLink() - new PostFindMode() - else - HUD.showForDuration("No matches for '#{FindMode.query.rawQuery}'", 1000) - -performFind = (count) -> findAndFocus false for [0...count] by 1 -performBackwardsFind = (count) -> findAndFocus true for [0...count] by 1 +performFind = (count) -> FindMode.findNext false for [0...count] by 1 +performBackwardsFind = (count) -> FindMode.findNext true for [0...count] by 1 getLinkFromSelection = -> node = window.getSelection().anchorNode -- cgit v1.2.3 From 6fcfde0b561e43955ef35ea3a91ed483cedfff4f Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 24 Oct 2017 19:30:02 +0100 Subject: Move normal mode find commands into normal mode file --- content_scripts/mode_normal.coffee | 8 ++++++++ content_scripts/vimium_frontend.coffee | 11 +---------- 2 files changed, 9 insertions(+), 10 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_normal.coffee b/content_scripts/mode_normal.coffee index a7a8a8b6..652adc3c 100644 --- a/content_scripts/mode_normal.coffee +++ b/content_scripts/mode_normal.coffee @@ -100,6 +100,14 @@ NormalModeCommands = enterVisualLineMode: -> new VisualLineMode userLaunchedMode: true + enterFindMode: -> + Marks.setPreviousPosition() + new FindMode() + + # Find. + performFind: (count) -> FindMode.findNext false for [0...count] by 1 + performBackwardsFind: (count) -> FindMode.findNext true for [0...count] by 1 + root = exports ? (window.root ?= {}) root.NormalMode = NormalMode root.NormalModeCommands = NormalModeCommands diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 11c952ca..e5de01a3 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -438,9 +438,6 @@ selectFoundInputElement = -> DomUtils.isDOMDescendant(findModeAnchorNode, document.activeElement)) DomUtils.simulateSelect(document.activeElement) -performFind = (count) -> FindMode.findNext false for [0...count] by 1 -performBackwardsFind = (count) -> FindMode.findNext true for [0...count] by 1 - getLinkFromSelection = -> node = window.getSelection().anchorNode while (node && node != document.body) @@ -543,11 +540,6 @@ root.goNext = -> nextStrings = nextPatterns.split(",").filter( (s) -> s.trim().length ) findAndFollowRel("next") || findAndFollowLink(nextStrings) -# Enters find mode. Returns the new find-mode instance. -enterFindMode = -> - Marks.setPreviousPosition() - new FindMode() - root.showHelp = (sourceFrameId) -> HelpDialog.toggle {sourceFrameId, showAllCommandDetails: false} @@ -575,8 +567,7 @@ root.Frame = Frame root.windowIsFocused = windowIsFocused root.bgLog = bgLog # These are exported for find mode and link-hints mode. -extend root, {focusFoundLink, selectFoundInputElement, performFind, performBackwardsFind, enterFindMode, - focusThisFrame} +extend root, {focusFoundLink, selectFoundInputElement, focusThisFrame} # These are exported only for the tests. extend root, {installModes} extend window, root unless exports? -- cgit v1.2.3 From ee95cb38bbd24fec444e0af3f593f470cce60d22 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 24 Oct 2017 19:34:20 +0100 Subject: Move mainFrame and showHelp to normal mode file --- content_scripts/mode_normal.coffee | 4 ++++ content_scripts/vimium_frontend.coffee | 5 ----- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_normal.coffee b/content_scripts/mode_normal.coffee index 652adc3c..6ae82fe6 100644 --- a/content_scripts/mode_normal.coffee +++ b/content_scripts/mode_normal.coffee @@ -108,6 +108,10 @@ NormalModeCommands = performFind: (count) -> FindMode.findNext false for [0...count] by 1 performBackwardsFind: (count) -> FindMode.findNext true for [0...count] by 1 + # Misc. + mainFrame: -> focusThisFrame highlight: true, forceFocusThisFrame: true + showHelp: (sourceFrameId) -> HelpDialog.toggle {sourceFrameId, showAllCommandDetails: false} + root = exports ? (window.root ?= {}) root.NormalMode = NormalMode root.NormalModeCommands = NormalModeCommands diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index e5de01a3..0cc9e15f 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -299,8 +299,6 @@ focusThisFrame = (request) -> flashFrame() if request.highlight extend root, - mainFrame: -> focusThisFrame highlight: true, forceFocusThisFrame: true - passNextKey: (count, options) -> if options.registryEntry.options.normal enterNormalMode count @@ -540,9 +538,6 @@ root.goNext = -> nextStrings = nextPatterns.split(",").filter( (s) -> s.trim().length ) findAndFollowRel("next") || findAndFollowLink(nextStrings) -root.showHelp = (sourceFrameId) -> - HelpDialog.toggle {sourceFrameId, showAllCommandDetails: false} - # If we are in the help dialog iframe, then HelpDialog is already defined with the necessary functions. root.HelpDialog ?= helpUI: null -- cgit v1.2.3 From fe2255f4de5e17d6ab1a9168191bfbfaa488d62d Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 24 Oct 2017 19:51:25 +0100 Subject: Move passNextKey to normal mode file --- content_scripts/mode_normal.coffee | 13 +++++++++++++ content_scripts/vimium_frontend.coffee | 13 ------------- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_normal.coffee b/content_scripts/mode_normal.coffee index 6ae82fe6..9a53ce76 100644 --- a/content_scripts/mode_normal.coffee +++ b/content_scripts/mode_normal.coffee @@ -33,6 +33,13 @@ class NormalMode extends KeyHandlerMode else Utils.invokeCommandString registryEntry.command, count, {registryEntry} +enterNormalMode = (count) -> + new NormalMode + indicator: "Normal mode (pass keys disabled)" + exitOnEscape: true + singleton: "enterNormalMode" + count: count + NormalModeCommands = # Scrolling. scrollToBottom: -> @@ -112,6 +119,12 @@ NormalModeCommands = mainFrame: -> focusThisFrame highlight: true, forceFocusThisFrame: true showHelp: (sourceFrameId) -> HelpDialog.toggle {sourceFrameId, showAllCommandDetails: false} + passNextKey: (count, options) -> + if options.registryEntry.options.normal + enterNormalMode count + else + new PassNextKeyMode count + root = exports ? (window.root ?= {}) root.NormalMode = NormalMode root.NormalModeCommands = NormalModeCommands diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 0cc9e15f..10eb197b 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -299,19 +299,6 @@ focusThisFrame = (request) -> flashFrame() if request.highlight extend root, - passNextKey: (count, options) -> - if options.registryEntry.options.normal - enterNormalMode count - else - new PassNextKeyMode count - - enterNormalMode: (count) -> - new NormalMode - indicator: "Normal mode (pass keys disabled)" - exitOnEscape: true - singleton: "enterNormalMode" - count: count - focusInput: do -> # Track the most recently focused input element. recentlyFocusedElement = null -- cgit v1.2.3 From d8f8015f4cd71cf3681506a5ec16f00f8ab46f46 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Wed, 25 Oct 2017 00:34:43 +0100 Subject: Split focusInput, move the main part into the normal mode file --- content_scripts/mode_normal.coffee | 57 ++++++++++++++ content_scripts/vimium_frontend.coffee | 133 ++++++++++----------------------- 2 files changed, 96 insertions(+), 94 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_normal.coffee b/content_scripts/mode_normal.coffee index 9a53ce76..2408e4aa 100644 --- a/content_scripts/mode_normal.coffee +++ b/content_scripts/mode_normal.coffee @@ -125,6 +125,63 @@ NormalModeCommands = else new PassNextKeyMode count + 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 + continue unless DomUtils.getVisibleClientRect element, true + { element, rect: Rect.copy element.getBoundingClientRect() } + + if visibleInputs.length == 0 + HUD.showForDuration("There are no inputs to focus.", 1000) + return + + # This is a hack to improve usability on the Vimium options page. We prime the recently-focused input + # to be the key-mappings input. Arguably, this is the input that the user is most likely to use. + recentlyFocusedElement = lastFocusedInput() + recentlyFocusedElement ?= document.getElementById "keyMappings" if window.isVimiumOptionsPage + + 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 recentlyFocusedElement + else + Math.min(count, visibleInputs.length) - 1 + + hints = for tuple in visibleInputs + hint = DomUtils.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 FocusSelector hints, visibleInputs, selectedInputIndex + +# The types in that we consider for focusInput command. Right now this is recalculated in +# each content script. Alternatively we could calculate it once in the background page and use a request to +# fetch it each time. +# Should we include the HTML5 date pickers here? + +# The corresponding XPath for such elements. +textInputXPath = (-> + textInputTypes = [ "text", "search", "email", "url", "number", "password", "date", "tel" ] + inputElements = ["input[" + + "(" + textInputTypes.map((type) -> '@type="' + type + '"').join(" or ") + "or not(@type))" + + " and not(@disabled or @readonly)]", + "textarea", "*[@contenteditable='' or translate(@contenteditable, 'TRUE', 'true')='true']"] + DomUtils.makeXPath(inputElements) +)() + root = exports ? (window.root ?= {}) root.NormalMode = NormalMode root.NormalModeCommands = NormalModeCommands diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 10eb197b..2cdaa6c5 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -22,21 +22,6 @@ windowIsFocused = do -> windowHasFocus = false if event.target == window; true -> windowHasFocus -# The types in that we consider for focusInput command. Right now this is recalculated in -# each content script. Alternatively we could calculate it once in the background page and use a request to -# fetch it each time. -# Should we include the HTML5 date pickers here? - -# The corresponding XPath for such elements. -textInputXPath = (-> - textInputTypes = [ "text", "search", "email", "url", "number", "password", "date", "tel" ] - inputElements = ["input[" + - "(" + textInputTypes.map((type) -> '@type="' + type + '"').join(" or ") + "or not(@type))" + - " and not(@disabled or @readonly)]", - "textarea", "*[@contenteditable='' or translate(@contenteditable, 'TRUE', 'true')='true']"] - DomUtils.makeXPath(inputElements) -)() - # This is set by Frame.registerFrameId(). A frameId of 0 indicates that this is the top frame in the tab. frameId = null @@ -299,7 +284,7 @@ focusThisFrame = (request) -> flashFrame() if request.highlight extend root, - focusInput: do -> + lastFocusedInput: do -> # Track the most recently focused input element. recentlyFocusedElement = null window.addEventListener "focus", @@ -308,85 +293,45 @@ extend root, if DomUtils.isEditable event.target recentlyFocusedElement = event.target , true + -> recentlyFocusedElement - (count) -> - mode = InsertMode - # 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. - # The mode argument is the mode to enter once an input is selected. - resultSet = DomUtils.evaluateXPath textInputXPath, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE - visibleInputs = - for i in [0...resultSet.snapshotLength] by 1 - element = resultSet.snapshotItem i - continue unless DomUtils.getVisibleClientRect element, true - { element, rect: Rect.copy element.getBoundingClientRect() } - - if visibleInputs.length == 0 - HUD.showForDuration("There are no inputs to focus.", 1000) - return - - # This is a hack to improve usability on the Vimium options page. We prime the recently-focused input - # to be the key-mappings input. Arguably, this is the input that the user is most likely to use. - recentlyFocusedElement ?= document.getElementById "keyMappings" if window.isVimiumOptionsPage - - 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 recentlyFocusedElement - else - Math.min(count, visibleInputs.length) - 1 - - hints = for tuple in visibleInputs - hint = DomUtils.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" - exitOnClick: true - keydown: (event) => - if event.key == "Tab" - hints[selectedInputIndex].classList.remove 'internalVimiumSelectedInputHint' - selectedInputIndex += hints.length + (if event.shiftKey then -1 else 1) - selectedInputIndex %= hints.length - hints[selectedInputIndex].classList.add 'internalVimiumSelectedInputHint' - DomUtils.simulateSelect visibleInputs[selectedInputIndex].element - @suppressEvent - else unless event.key == "Shift" - @exit() - # Give the new mode the opportunity to handle the event. - @restartBubbling - - @hintContainingDiv = DomUtils.addElementList hints, - id: "vimiumInputMarkerContainer" - className: "vimiumReset" - +class FocusSelector extends Mode + constructor: (hints, visibleInputs, selectedInputIndex) -> + super + name: "focus-selector" + exitOnClick: true + keydown: (event) => + if event.key == "Tab" + hints[selectedInputIndex].classList.remove 'internalVimiumSelectedInputHint' + selectedInputIndex += hints.length + (if event.shiftKey then -1 else 1) + selectedInputIndex %= hints.length + hints[selectedInputIndex].classList.add 'internalVimiumSelectedInputHint' DomUtils.simulateSelect visibleInputs[selectedInputIndex].element - if visibleInputs.length == 1 - @exit() - return - else - hints[selectedInputIndex].classList.add 'internalVimiumSelectedInputHint' - - exit: -> - super() - DomUtils.removeElement @hintContainingDiv - if mode and document.activeElement and DomUtils.isEditable document.activeElement - new mode - singleton: "post-find-mode/focus-input" - targetElement: document.activeElement - indicator: false + @suppressEvent + else unless event.key == "Shift" + @exit() + # Give the new mode the opportunity to handle the event. + @restartBubbling + + @hintContainingDiv = DomUtils.addElementList hints, + id: "vimiumInputMarkerContainer" + className: "vimiumReset" + + DomUtils.simulateSelect visibleInputs[selectedInputIndex].element + if visibleInputs.length == 1 + @exit() + return + else + hints[selectedInputIndex].classList.add 'internalVimiumSelectedInputHint' + + exit: -> + super() + DomUtils.removeElement @hintContainingDiv + if document.activeElement and DomUtils.isEditable document.activeElement + new InsertMode + singleton: "post-find-mode/focus-input" + targetElement: document.activeElement + indicator: false # Checks if Vimium should be enabled or not in this frame. As a side effect, it also informs the background # page whether this frame has the focus, allowing the background page to track the active frame's URL and set @@ -549,7 +494,7 @@ root.Frame = Frame root.windowIsFocused = windowIsFocused root.bgLog = bgLog # These are exported for find mode and link-hints mode. -extend root, {focusFoundLink, selectFoundInputElement, focusThisFrame} +extend root, {focusFoundLink, selectFoundInputElement, focusThisFrame, FocusSelector} # These are exported only for the tests. extend root, {installModes} extend window, root unless exports? -- cgit v1.2.3 From b06ed7bd5cc82ec3307aeee945bcf6bf8f9264ce Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Wed, 25 Oct 2017 01:00:18 +0100 Subject: Include LinkHints, Vomnibar and Marks commands in normal mode file --- content_scripts/mode_normal.coffee | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'content_scripts') diff --git a/content_scripts/mode_normal.coffee b/content_scripts/mode_normal.coffee index 2408e4aa..3ddbf294 100644 --- a/content_scripts/mode_normal.coffee +++ b/content_scripts/mode_normal.coffee @@ -167,6 +167,31 @@ NormalModeCommands = new FocusSelector hints, visibleInputs, selectedInputIndex +if LinkHints? + extend NormalModeCommands, + "LinkHints.activateMode": LinkHints.activateMode + "LinkHints.activateModeToOpenInNewTab": LinkHints.activateModeToOpenInNewTab + "LinkHints.activateModeToOpenInNewForegroundTab": LinkHints.activateModeToOpenInNewForegroundTab + "LinkHints.activateModeWithQueue": LinkHints.activateModeWithQueue + "LinkHints.activateModeToOpenIncognito": LinkHints.activateModeToOpenIncognito + "LinkHints.activateModeToDownloadLink": LinkHints.activateModeToDownloadLink + "LinkHints.activateModeToCopyLinkUrl": LinkHints.activateModeToCopyLinkUrl + +if Vomnibar? + extend NormalModeCommands, + "Vomnibar.activate": Vomnibar.activate + "Vomnibar.activateInNewTab": Vomnibar.activateInNewTab + "Vomnibar.activateTabSelection": Vomnibar.activateTabSelection + "Vomnibar.activateBookmarks": Vomnibar.activateBookmarks + "Vomnibar.activateBookmarksInNewTab": Vomnibar.activateBookmarksInNewTab + "Vomnibar.activateEditUrl": Vomnibar.activateEditUrl + "Vomnibar.activateEditUrlInNewTab": Vomnibar.activateEditUrlInNewTab + +if Marks? + extend NormalModeCommands, + "Marks.activateCreateMode": Marks.activateCreateMode + "Marks.activateGotoMode": Marks.activateGotoMode + # The types in that we consider for focusInput command. Right now this is recalculated in # each content script. Alternatively we could calculate it once in the background page and use a request to # fetch it each time. -- cgit v1.2.3 From 6cb8a82b7cf7d6930b669fae74e1751a1e87567d Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Wed, 25 Oct 2017 01:04:58 +0100 Subject: Move goPrevious and goNext to normal mode file --- content_scripts/mode_normal.coffee | 10 ++++++++++ content_scripts/vimium_frontend.coffee | 13 ++----------- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_normal.coffee b/content_scripts/mode_normal.coffee index 3ddbf294..8547c9e5 100644 --- a/content_scripts/mode_normal.coffee +++ b/content_scripts/mode_normal.coffee @@ -125,6 +125,16 @@ NormalModeCommands = else new PassNextKeyMode count + goPrevious: -> + previousPatterns = Settings.get("previousPatterns") || "" + previousStrings = previousPatterns.split(",").filter( (s) -> s.trim().length ) + findAndFollowRel("prev") || findAndFollowLink(previousStrings) + + goNext: -> + nextPatterns = Settings.get("nextPatterns") || "" + nextStrings = nextPatterns.split(",").filter( (s) -> s.trim().length ) + findAndFollowRel("next") || findAndFollowLink(nextStrings) + 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. diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 2cdaa6c5..5549664e 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -460,16 +460,6 @@ findAndFollowRel = (value) -> followLink(element) return true -root.goPrevious = -> - previousPatterns = Settings.get("previousPatterns") || "" - previousStrings = previousPatterns.split(",").filter( (s) -> s.trim().length ) - findAndFollowRel("prev") || findAndFollowLink(previousStrings) - -root.goNext = -> - nextPatterns = Settings.get("nextPatterns") || "" - nextStrings = nextPatterns.split(",").filter( (s) -> s.trim().length ) - findAndFollowRel("next") || findAndFollowLink(nextStrings) - # If we are in the help dialog iframe, then HelpDialog is already defined with the necessary functions. root.HelpDialog ?= helpUI: null @@ -494,7 +484,8 @@ root.Frame = Frame root.windowIsFocused = windowIsFocused root.bgLog = bgLog # These are exported for find mode and link-hints mode. -extend root, {focusFoundLink, selectFoundInputElement, focusThisFrame, FocusSelector} +extend root, {focusFoundLink, selectFoundInputElement, focusThisFrame, FocusSelector, + findAndFollowRel, findAndFollowLink} # These are exported only for the tests. extend root, {installModes} extend window, root unless exports? -- cgit v1.2.3 From 5c4aab3d4488e5d8d64aba122791f86fc9766b99 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sat, 28 Oct 2017 17:02:12 +0100 Subject: Bind LinkHints, Vomnibar and Marks commands appropriately --- content_scripts/mode_normal.coffee | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_normal.coffee b/content_scripts/mode_normal.coffee index 8547c9e5..6db42948 100644 --- a/content_scripts/mode_normal.coffee +++ b/content_scripts/mode_normal.coffee @@ -179,28 +179,28 @@ NormalModeCommands = if LinkHints? extend NormalModeCommands, - "LinkHints.activateMode": LinkHints.activateMode - "LinkHints.activateModeToOpenInNewTab": LinkHints.activateModeToOpenInNewTab - "LinkHints.activateModeToOpenInNewForegroundTab": LinkHints.activateModeToOpenInNewForegroundTab - "LinkHints.activateModeWithQueue": LinkHints.activateModeWithQueue - "LinkHints.activateModeToOpenIncognito": LinkHints.activateModeToOpenIncognito - "LinkHints.activateModeToDownloadLink": LinkHints.activateModeToDownloadLink - "LinkHints.activateModeToCopyLinkUrl": LinkHints.activateModeToCopyLinkUrl + "LinkHints.activateMode": LinkHints.activateMode.bind LinkHints + "LinkHints.activateModeToOpenInNewTab": LinkHints.activateModeToOpenInNewTab.bind LinkHints + "LinkHints.activateModeToOpenInNewForegroundTab": LinkHints.activateModeToOpenInNewForegroundTab.bind LinkHints + "LinkHints.activateModeWithQueue": LinkHints.activateModeWithQueue.bind LinkHints + "LinkHints.activateModeToOpenIncognito": LinkHints.activateModeToOpenIncognito.bind LinkHints + "LinkHints.activateModeToDownloadLink": LinkHints.activateModeToDownloadLink.bind LinkHints + "LinkHints.activateModeToCopyLinkUrl": LinkHints.activateModeToCopyLinkUrl.bind LinkHints if Vomnibar? extend NormalModeCommands, - "Vomnibar.activate": Vomnibar.activate - "Vomnibar.activateInNewTab": Vomnibar.activateInNewTab - "Vomnibar.activateTabSelection": Vomnibar.activateTabSelection - "Vomnibar.activateBookmarks": Vomnibar.activateBookmarks - "Vomnibar.activateBookmarksInNewTab": Vomnibar.activateBookmarksInNewTab - "Vomnibar.activateEditUrl": Vomnibar.activateEditUrl - "Vomnibar.activateEditUrlInNewTab": Vomnibar.activateEditUrlInNewTab + "Vomnibar.activate": Vomnibar.activate.bind Vomnibar + "Vomnibar.activateInNewTab": Vomnibar.activateInNewTab.bind Vomnibar + "Vomnibar.activateTabSelection": Vomnibar.activateTabSelection.bind Vomnibar + "Vomnibar.activateBookmarks": Vomnibar.activateBookmarks.bind Vomnibar + "Vomnibar.activateBookmarksInNewTab": Vomnibar.activateBookmarksInNewTab.bind Vomnibar + "Vomnibar.activateEditUrl": Vomnibar.activateEditUrl.bind Vomnibar + "Vomnibar.activateEditUrlInNewTab": Vomnibar.activateEditUrlInNewTab.bind Vomnibar if Marks? extend NormalModeCommands, - "Marks.activateCreateMode": Marks.activateCreateMode - "Marks.activateGotoMode": Marks.activateGotoMode + "Marks.activateCreateMode": Marks.activateCreateMode.bind Marks + "Marks.activateGotoMode": Marks.activateGotoMode.bind Marks # The types in that we consider for focusInput command. Right now this is recalculated in # each content script. Alternatively we could calculate it once in the background page and use a request to -- cgit v1.2.3 From f65720e58e31a0218e0c176a9140520451e5dd7d Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sat, 28 Oct 2017 17:04:37 +0100 Subject: Remove invokeCommandString, call NormalModeCommands directly --- content_scripts/mode_normal.coffee | 2 +- content_scripts/vimium_frontend.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_normal.coffee b/content_scripts/mode_normal.coffee index 6db42948..d6f2934e 100644 --- a/content_scripts/mode_normal.coffee +++ b/content_scripts/mode_normal.coffee @@ -31,7 +31,7 @@ class NormalMode extends KeyHandlerMode else if registryEntry.background chrome.runtime.sendMessage {handler: "runBackgroundCommand", registryEntry, count} else - Utils.invokeCommandString registryEntry.command, count, {registryEntry} + NormalModeCommands[registryEntry.command] count, {registryEntry} enterNormalMode = (count) -> new NormalMode diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 5549664e..b936fe04 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -142,7 +142,7 @@ initializePreDomReady = -> frameFocused: -> # A frame has received the focus; we don't care here (UI components handle this). checkEnabledAfterURLChange: checkEnabledAfterURLChange runInTopFrame: ({sourceFrameId, registryEntry}) -> - Utils.invokeCommandString registryEntry.command, sourceFrameId, registryEntry if DomUtils.isTopFrame() + NormalModeCommands[registryEntry.command] sourceFrameId, registryEntry if DomUtils.isTopFrame() linkHintsMessage: (request) -> HintCoordinator[request.messageType] request chrome.runtime.onMessage.addListener (request, sender, sendResponse) -> -- cgit v1.2.3 From 9847144f3493547af7eb419f11552ac18d7e9872 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sat, 28 Oct 2017 17:09:24 +0100 Subject: Remove normal mode commands from global scope --- content_scripts/mode_normal.coffee | 1 - 1 file changed, 1 deletion(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_normal.coffee b/content_scripts/mode_normal.coffee index d6f2934e..02681475 100644 --- a/content_scripts/mode_normal.coffee +++ b/content_scripts/mode_normal.coffee @@ -220,5 +220,4 @@ textInputXPath = (-> root = exports ? (window.root ?= {}) root.NormalMode = NormalMode root.NormalModeCommands = NormalModeCommands -extend root, NormalModeCommands extend window, root unless exports? -- cgit v1.2.3 From 0b9287696825cb7df2301d97a54c7666d9094521 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sun, 29 Oct 2017 10:18:42 +0000 Subject: Move focusFoundLink into mode_find, don't expose it as global --- content_scripts/mode_find.coffee | 12 ++++++++++++ content_scripts/vimium_frontend.coffee | 15 +-------------- 2 files changed, 13 insertions(+), 14 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_find.coffee b/content_scripts/mode_find.coffee index d361d4be..e02f61c9 100644 --- a/content_scripts/mode_find.coffee +++ b/content_scripts/mode_find.coffee @@ -243,6 +243,18 @@ getCurrentRange = -> selection.collapseToStart() if selection.type == "Range" selection.getRangeAt 0 +getLinkFromSelection = -> + node = window.getSelection().anchorNode + while (node && node != document.body) + return node if (node.nodeName.toLowerCase() == "a") + node = node.parentNode + null + +focusFoundLink = -> + if (FindMode.query.hasResults) + link = getLinkFromSelection() + link.focus() if link + root = exports ? (window.root ?= {}) root.PostFindMode = PostFindMode root.FindMode = FindMode diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index b936fe04..5f6c377e 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -353,11 +353,6 @@ checkIfEnabledForUrl = do -> checkEnabledAfterURLChange = forTrusted -> checkIfEnabledForUrl() if windowIsFocused() -focusFoundLink = -> - if (FindMode.query.hasResults) - link = getLinkFromSelection() - link.focus() if link - selectFoundInputElement = -> # Since the last focused element might not be the one currently pointed to by find (e.g. the current one # might be disabled and therefore unable to receive focus), we use the approximate heuristic of checking @@ -368,13 +363,6 @@ selectFoundInputElement = -> DomUtils.isDOMDescendant(findModeAnchorNode, document.activeElement)) DomUtils.simulateSelect(document.activeElement) -getLinkFromSelection = -> - node = window.getSelection().anchorNode - while (node && node != document.body) - return node if (node.nodeName.toLowerCase() == "a") - node = node.parentNode - null - # used by the findAndFollow* functions. followLink = (linkElement) -> if (linkElement.nodeName.toLowerCase() == "link") @@ -484,8 +472,7 @@ root.Frame = Frame root.windowIsFocused = windowIsFocused root.bgLog = bgLog # These are exported for find mode and link-hints mode. -extend root, {focusFoundLink, selectFoundInputElement, focusThisFrame, FocusSelector, - findAndFollowRel, findAndFollowLink} +extend root, {selectFoundInputElement, focusThisFrame, FocusSelector, findAndFollowRel, findAndFollowLink} # These are exported only for the tests. extend root, {installModes} extend window, root unless exports? -- cgit v1.2.3 From a00bb7d2172803bc04b3543b31345879cb434b27 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sun, 29 Oct 2017 10:22:17 +0000 Subject: Move selectFoundInputElement into mode_find --- content_scripts/mode_find.coffee | 10 ++++++++++ content_scripts/vimium_frontend.coffee | 12 +----------- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_find.coffee b/content_scripts/mode_find.coffee index e02f61c9..b6c80cec 100644 --- a/content_scripts/mode_find.coffee +++ b/content_scripts/mode_find.coffee @@ -255,6 +255,16 @@ focusFoundLink = -> link = getLinkFromSelection() link.focus() if link +selectFoundInputElement = -> + # Since the last focused element might not be the one currently pointed to by find (e.g. the current one + # might be disabled and therefore unable to receive focus), we use the approximate heuristic of checking + # that the last anchor node is an ancestor of our element. + findModeAnchorNode = document.getSelection().anchorNode + if (FindMode.query.hasResults && document.activeElement && + DomUtils.isSelectable(document.activeElement) && + DomUtils.isDOMDescendant(findModeAnchorNode, document.activeElement)) + DomUtils.simulateSelect(document.activeElement) + root = exports ? (window.root ?= {}) root.PostFindMode = PostFindMode root.FindMode = FindMode diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 5f6c377e..920fb27c 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -353,16 +353,6 @@ checkIfEnabledForUrl = do -> checkEnabledAfterURLChange = forTrusted -> checkIfEnabledForUrl() if windowIsFocused() -selectFoundInputElement = -> - # Since the last focused element might not be the one currently pointed to by find (e.g. the current one - # might be disabled and therefore unable to receive focus), we use the approximate heuristic of checking - # that the last anchor node is an ancestor of our element. - findModeAnchorNode = document.getSelection().anchorNode - if (FindMode.query.hasResults && document.activeElement && - DomUtils.isSelectable(document.activeElement) && - DomUtils.isDOMDescendant(findModeAnchorNode, document.activeElement)) - DomUtils.simulateSelect(document.activeElement) - # used by the findAndFollow* functions. followLink = (linkElement) -> if (linkElement.nodeName.toLowerCase() == "link") @@ -472,7 +462,7 @@ root.Frame = Frame root.windowIsFocused = windowIsFocused root.bgLog = bgLog # These are exported for find mode and link-hints mode. -extend root, {selectFoundInputElement, focusThisFrame, FocusSelector, findAndFollowRel, findAndFollowLink} +extend root, {focusThisFrame, FocusSelector, findAndFollowRel, findAndFollowLink} # These are exported only for the tests. extend root, {installModes} extend window, root unless exports? -- cgit v1.2.3 From ad8fa8e850eaa6ca3ef4d45e1903d11aa564cafe Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sun, 29 Oct 2017 12:03:43 +0000 Subject: Move FocusSelector to mode_normal.coffee --- content_scripts/mode_normal.coffee | 38 ++++++++++++++++++++++++++++++++ content_scripts/vimium_frontend.coffee | 40 +--------------------------------- 2 files changed, 39 insertions(+), 39 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_normal.coffee b/content_scripts/mode_normal.coffee index 02681475..9a03e9d0 100644 --- a/content_scripts/mode_normal.coffee +++ b/content_scripts/mode_normal.coffee @@ -217,6 +217,44 @@ textInputXPath = (-> DomUtils.makeXPath(inputElements) )() +class FocusSelector extends Mode + constructor: (hints, visibleInputs, selectedInputIndex) -> + super + name: "focus-selector" + exitOnClick: true + keydown: (event) => + if event.key == "Tab" + hints[selectedInputIndex].classList.remove 'internalVimiumSelectedInputHint' + selectedInputIndex += hints.length + (if event.shiftKey then -1 else 1) + selectedInputIndex %= hints.length + hints[selectedInputIndex].classList.add 'internalVimiumSelectedInputHint' + DomUtils.simulateSelect visibleInputs[selectedInputIndex].element + @suppressEvent + else unless event.key == "Shift" + @exit() + # Give the new mode the opportunity to handle the event. + @restartBubbling + + @hintContainingDiv = DomUtils.addElementList hints, + id: "vimiumInputMarkerContainer" + className: "vimiumReset" + + DomUtils.simulateSelect visibleInputs[selectedInputIndex].element + if visibleInputs.length == 1 + @exit() + return + else + hints[selectedInputIndex].classList.add 'internalVimiumSelectedInputHint' + + exit: -> + super() + DomUtils.removeElement @hintContainingDiv + if document.activeElement and DomUtils.isEditable document.activeElement + new InsertMode + singleton: "post-find-mode/focus-input" + targetElement: document.activeElement + indicator: false + root = exports ? (window.root ?= {}) root.NormalMode = NormalMode root.NormalModeCommands = NormalModeCommands diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 920fb27c..5a2db5d0 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -295,44 +295,6 @@ extend root, , true -> recentlyFocusedElement -class FocusSelector extends Mode - constructor: (hints, visibleInputs, selectedInputIndex) -> - super - name: "focus-selector" - exitOnClick: true - keydown: (event) => - if event.key == "Tab" - hints[selectedInputIndex].classList.remove 'internalVimiumSelectedInputHint' - selectedInputIndex += hints.length + (if event.shiftKey then -1 else 1) - selectedInputIndex %= hints.length - hints[selectedInputIndex].classList.add 'internalVimiumSelectedInputHint' - DomUtils.simulateSelect visibleInputs[selectedInputIndex].element - @suppressEvent - else unless event.key == "Shift" - @exit() - # Give the new mode the opportunity to handle the event. - @restartBubbling - - @hintContainingDiv = DomUtils.addElementList hints, - id: "vimiumInputMarkerContainer" - className: "vimiumReset" - - DomUtils.simulateSelect visibleInputs[selectedInputIndex].element - if visibleInputs.length == 1 - @exit() - return - else - hints[selectedInputIndex].classList.add 'internalVimiumSelectedInputHint' - - exit: -> - super() - DomUtils.removeElement @hintContainingDiv - if document.activeElement and DomUtils.isEditable document.activeElement - new InsertMode - singleton: "post-find-mode/focus-input" - targetElement: document.activeElement - indicator: false - # Checks if Vimium should be enabled or not in this frame. As a side effect, it also informs the background # page whether this frame has the focus, allowing the background page to track the active frame's URL and set # the page icon. @@ -462,7 +424,7 @@ root.Frame = Frame root.windowIsFocused = windowIsFocused root.bgLog = bgLog # These are exported for find mode and link-hints mode. -extend root, {focusThisFrame, FocusSelector, findAndFollowRel, findAndFollowLink} +extend root, {focusThisFrame, findAndFollowRel, findAndFollowLink} # These are exported only for the tests. extend root, {installModes} extend window, root unless exports? -- cgit v1.2.3 From 722ba99720ed946f11e5672c7fbf0f1f34337576 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sun, 29 Oct 2017 12:05:40 +0000 Subject: Move findAndFollow* to mode_normal.coffee --- content_scripts/mode_normal.coffee | 85 +++++++++++++++++++++++++++++++++ content_scripts/vimium_frontend.coffee | 87 +--------------------------------- 2 files changed, 86 insertions(+), 86 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_normal.coffee b/content_scripts/mode_normal.coffee index 9a03e9d0..8dad4b63 100644 --- a/content_scripts/mode_normal.coffee +++ b/content_scripts/mode_normal.coffee @@ -217,6 +217,91 @@ textInputXPath = (-> DomUtils.makeXPath(inputElements) )() +# used by the findAndFollow* functions. +followLink = (linkElement) -> + if (linkElement.nodeName.toLowerCase() == "link") + window.location.href = linkElement.href + else + # if we can click on it, don't simply set location.href: some next/prev links are meant to trigger AJAX + # calls, like the 'more' button on GitHub's newsfeed. + linkElement.scrollIntoView() + DomUtils.simulateClick(linkElement) + +# +# Find and follow a link which matches any one of a list of strings. If there are multiple such links, they +# are prioritized for shortness, by their position in :linkStrings, how far down the page they are located, +# and finally by whether the match is exact. Practically speaking, this means we favor 'next page' over 'the +# next big thing', and 'more' over 'nextcompany', even if 'next' occurs before 'more' in :linkStrings. +# +findAndFollowLink = (linkStrings) -> + linksXPath = DomUtils.makeXPath(["a", "*[@onclick or @role='link' or contains(@class, 'button')]"]) + links = DomUtils.evaluateXPath(linksXPath, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE) + candidateLinks = [] + + # at the end of this loop, candidateLinks will contain all visible links that match our patterns + # links lower in the page are more likely to be the ones we want, so we loop through the snapshot backwards + for i in [(links.snapshotLength - 1)..0] by -1 + link = links.snapshotItem(i) + + # ensure link is visible (we don't mind if it is scrolled offscreen) + boundingClientRect = link.getBoundingClientRect() + if (boundingClientRect.width == 0 || boundingClientRect.height == 0) + continue + computedStyle = window.getComputedStyle(link, null) + if (computedStyle.getPropertyValue("visibility") != "visible" || + computedStyle.getPropertyValue("display") == "none") + continue + + linkMatches = false + for linkString in linkStrings + if link.innerText.toLowerCase().indexOf(linkString) != -1 || + 0 <= link.value?.indexOf? linkString + linkMatches = true + break + continue unless linkMatches + + candidateLinks.push(link) + + return if (candidateLinks.length == 0) + + for link in candidateLinks + link.wordCount = link.innerText.trim().split(/\s+/).length + + # We can use this trick to ensure that Array.sort is stable. We need this property to retain the reverse + # in-page order of the links. + + candidateLinks.forEach((a,i) -> a.originalIndex = i) + + # favor shorter links, and ignore those that are more than one word longer than the shortest link + candidateLinks = + candidateLinks + .sort((a, b) -> + if (a.wordCount == b.wordCount) then a.originalIndex - b.originalIndex else a.wordCount - b.wordCount + ) + .filter((a) -> a.wordCount <= candidateLinks[0].wordCount + 1) + + for linkString in linkStrings + exactWordRegex = + if /\b/.test(linkString[0]) or /\b/.test(linkString[linkString.length - 1]) + new RegExp "\\b" + linkString + "\\b", "i" + else + new RegExp linkString, "i" + for candidateLink in candidateLinks + if exactWordRegex.test(candidateLink.innerText) || + (candidateLink.value && exactWordRegex.test(candidateLink.value)) + followLink(candidateLink) + return true + false + +findAndFollowRel = (value) -> + relTags = ["link", "a", "area"] + for tag in relTags + elements = document.getElementsByTagName(tag) + for element in elements + if (element.hasAttribute("rel") && element.rel.toLowerCase() == value) + followLink(element) + return true + class FocusSelector extends Mode constructor: (hints, visibleInputs, selectedInputIndex) -> super diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 5a2db5d0..3beb96aa 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -315,91 +315,6 @@ checkIfEnabledForUrl = do -> checkEnabledAfterURLChange = forTrusted -> checkIfEnabledForUrl() if windowIsFocused() -# used by the findAndFollow* functions. -followLink = (linkElement) -> - if (linkElement.nodeName.toLowerCase() == "link") - window.location.href = linkElement.href - else - # if we can click on it, don't simply set location.href: some next/prev links are meant to trigger AJAX - # calls, like the 'more' button on GitHub's newsfeed. - linkElement.scrollIntoView() - DomUtils.simulateClick(linkElement) - -# -# Find and follow a link which matches any one of a list of strings. If there are multiple such links, they -# are prioritized for shortness, by their position in :linkStrings, how far down the page they are located, -# and finally by whether the match is exact. Practically speaking, this means we favor 'next page' over 'the -# next big thing', and 'more' over 'nextcompany', even if 'next' occurs before 'more' in :linkStrings. -# -findAndFollowLink = (linkStrings) -> - linksXPath = DomUtils.makeXPath(["a", "*[@onclick or @role='link' or contains(@class, 'button')]"]) - links = DomUtils.evaluateXPath(linksXPath, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE) - candidateLinks = [] - - # at the end of this loop, candidateLinks will contain all visible links that match our patterns - # links lower in the page are more likely to be the ones we want, so we loop through the snapshot backwards - for i in [(links.snapshotLength - 1)..0] by -1 - link = links.snapshotItem(i) - - # ensure link is visible (we don't mind if it is scrolled offscreen) - boundingClientRect = link.getBoundingClientRect() - if (boundingClientRect.width == 0 || boundingClientRect.height == 0) - continue - computedStyle = window.getComputedStyle(link, null) - if (computedStyle.getPropertyValue("visibility") != "visible" || - computedStyle.getPropertyValue("display") == "none") - continue - - linkMatches = false - for linkString in linkStrings - if link.innerText.toLowerCase().indexOf(linkString) != -1 || - 0 <= link.value?.indexOf? linkString - linkMatches = true - break - continue unless linkMatches - - candidateLinks.push(link) - - return if (candidateLinks.length == 0) - - for link in candidateLinks - link.wordCount = link.innerText.trim().split(/\s+/).length - - # We can use this trick to ensure that Array.sort is stable. We need this property to retain the reverse - # in-page order of the links. - - candidateLinks.forEach((a,i) -> a.originalIndex = i) - - # favor shorter links, and ignore those that are more than one word longer than the shortest link - candidateLinks = - candidateLinks - .sort((a, b) -> - if (a.wordCount == b.wordCount) then a.originalIndex - b.originalIndex else a.wordCount - b.wordCount - ) - .filter((a) -> a.wordCount <= candidateLinks[0].wordCount + 1) - - for linkString in linkStrings - exactWordRegex = - if /\b/.test(linkString[0]) or /\b/.test(linkString[linkString.length - 1]) - new RegExp "\\b" + linkString + "\\b", "i" - else - new RegExp linkString, "i" - for candidateLink in candidateLinks - if exactWordRegex.test(candidateLink.innerText) || - (candidateLink.value && exactWordRegex.test(candidateLink.value)) - followLink(candidateLink) - return true - false - -findAndFollowRel = (value) -> - relTags = ["link", "a", "area"] - for tag in relTags - elements = document.getElementsByTagName(tag) - for element in elements - if (element.hasAttribute("rel") && element.rel.toLowerCase() == value) - followLink(element) - return true - # If we are in the help dialog iframe, then HelpDialog is already defined with the necessary functions. root.HelpDialog ?= helpUI: null @@ -424,7 +339,7 @@ root.Frame = Frame root.windowIsFocused = windowIsFocused root.bgLog = bgLog # These are exported for find mode and link-hints mode. -extend root, {focusThisFrame, findAndFollowRel, findAndFollowLink} +extend root, {focusThisFrame} # These are exported only for the tests. extend root, {installModes} extend window, root unless exports? -- cgit v1.2.3 From 3abee4d80699c1fade78af951efd23c1297d0be3 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sun, 29 Oct 2017 12:08:23 +0000 Subject: Tidy up exports in vimium_frontend --- content_scripts/vimium_frontend.coffee | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'content_scripts') diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 3beb96aa..bbc3e4f1 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -283,17 +283,17 @@ focusThisFrame = (request) -> document.activeElement.blur() if document.activeElement.tagName.toLowerCase() == "iframe" flashFrame() if request.highlight -extend root, - lastFocusedInput: do -> - # Track the most recently focused input element. - recentlyFocusedElement = null - window.addEventListener "focus", - forTrusted (event) -> - DomUtils = window.DomUtils ? root.DomUtils # Workaround FF bug 1408996. - if DomUtils.isEditable event.target - recentlyFocusedElement = event.target - , true - -> recentlyFocusedElement +# Used by focusInput command. +root.lastFocusedInput = do -> + # Track the most recently focused input element. + recentlyFocusedElement = null + window.addEventListener "focus", + forTrusted (event) -> + DomUtils = window.DomUtils ? root.DomUtils # Workaround FF bug 1408996. + if DomUtils.isEditable event.target + recentlyFocusedElement = event.target + , true + -> recentlyFocusedElement # Checks if Vimium should be enabled or not in this frame. As a side effect, it also informs the background # page whether this frame has the focus, allowing the background page to track the active frame's URL and set @@ -338,7 +338,7 @@ root.frameId = frameId root.Frame = Frame root.windowIsFocused = windowIsFocused root.bgLog = bgLog -# These are exported for find mode and link-hints mode. +# These are exported for normal mode and link-hints mode. extend root, {focusThisFrame} # These are exported only for the tests. extend root, {installModes} -- cgit v1.2.3 From 24148c709806d1631f35cd8efd3fdec4f2376f92 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Sun, 29 Oct 2017 12:51:53 +0000 Subject: Guard against undefined DomUtils, instead of stubbing in tests --- content_scripts/mode_normal.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'content_scripts') diff --git a/content_scripts/mode_normal.coffee b/content_scripts/mode_normal.coffee index 8dad4b63..ee05f4b0 100644 --- a/content_scripts/mode_normal.coffee +++ b/content_scripts/mode_normal.coffee @@ -214,7 +214,7 @@ textInputXPath = (-> "(" + textInputTypes.map((type) -> '@type="' + type + '"').join(" or ") + "or not(@type))" + " and not(@disabled or @readonly)]", "textarea", "*[@contenteditable='' or translate(@contenteditable, 'TRUE', 'true')='true']"] - DomUtils.makeXPath(inputElements) + DomUtils?.makeXPath(inputElements) )() # used by the findAndFollow* functions. -- cgit v1.2.3