diff options
Diffstat (limited to 'pages')
| -rw-r--r-- | pages/help_dialog.html | 4 | ||||
| -rw-r--r-- | pages/hud.coffee | 15 | ||||
| -rw-r--r-- | pages/hud.html | 11 | ||||
| -rw-r--r-- | pages/options.coffee | 25 | ||||
| -rw-r--r-- | pages/options.css | 5 | ||||
| -rw-r--r-- | pages/options.html | 36 | ||||
| -rw-r--r-- | pages/popup.html | 2 | ||||
| -rw-r--r-- | pages/vomnibar.coffee | 369 | ||||
| -rw-r--r-- | pages/vomnibar.css | 19 | ||||
| -rw-r--r-- | pages/vomnibar.html | 2 |
10 files changed, 341 insertions, 147 deletions
diff --git a/pages/help_dialog.html b/pages/help_dialog.html index 0884f2cd..5c09c0ab 100644 --- a/pages/help_dialog.html +++ b/pages/help_dialog.html @@ -7,6 +7,7 @@ page with the up-to-date key bindings when the dialog is shown. --> <div id="vimiumHelpDialog" class="vimiumReset"> <a class="vimiumReset optionsPage" href="#">Options</a> + <a class="vimiumReset wikiPage" href="https://github.com/philc/vimium/wiki" target="_blank">Wiki</a> <a class="vimiumReset closeButton" href="#">×</a> <div id="vimiumTitle" class="vimiumReset"><span class="vimiumReset" style="color:#2f508e">Vim</span>ium {{title}}</div> <div class="vimiumReset vimiumColumn"> @@ -20,6 +21,8 @@ <div class="vimiumReset vimiumColumn"> <table class="vimiumReset" > <tbody class="vimiumReset"> + <tr class="vimiumReset" ><td class="vimiumReset" ></td><td class="vimiumReset" ></td><td class="vimiumReset vimiumHelpSectionTitle">Using the vomnibar</td></tr> + {{vomnibarCommands}} <tr class="vimiumReset" ><td class="vimiumReset" ></td><td class="vimiumReset" ></td><td class="vimiumReset vimiumHelpSectionTitle">Using find</td></tr> {{findCommands}} <tr class="vimiumReset" ><td class="vimiumReset" ></td><td class="vimiumReset" ></td><td class="vimiumReset vimiumHelpSectionTitle">Navigating history</td></tr> @@ -46,6 +49,7 @@ </div> <div class="vimiumReset vimiumColumn" style="text-align:right"> <span class="vimiumReset">Version {{version}}</span><br/> + <a href="https://github.com/philc/vimium#release-notes" class="vimiumReset">What's new?</a> </div> </div> </div> diff --git a/pages/hud.coffee b/pages/hud.coffee new file mode 100644 index 00000000..68283451 --- /dev/null +++ b/pages/hud.coffee @@ -0,0 +1,15 @@ +handlers = + show: (data) -> + document.getElementById("hud").innerText = data.text + document.getElementById("hud").classList.add "vimiumUIComponentVisible" + document.getElementById("hud").classList.remove "vimiumUIComponentHidden" + hide: -> + # We get a flicker when the HUD later becomes visible again (with new text) unless we reset its contents + # here. + document.getElementById("hud").innerText = "" + document.getElementById("hud").classList.add "vimiumUIComponentHidden" + document.getElementById("hud").classList.remove "vimiumUIComponentVisible" + +UIComponentServer.registerHandler (event) -> + {data} = event + handlers[data.name]? data diff --git a/pages/hud.html b/pages/hud.html new file mode 100644 index 00000000..bcb38e04 --- /dev/null +++ b/pages/hud.html @@ -0,0 +1,11 @@ +<html> + <head> + <title>HUD</title> + <link rel="stylesheet" type="text/css" href="../content_scripts/vimium.css" /> + <script type="text/javascript" src="ui_component_server.js"></script> + <script type="text/javascript" src="hud.js"></script> + </head> + <body> + <div class="vimiumReset vimiumHUD" id="hud"></div> + </body> +</html> diff --git a/pages/options.coffee b/pages/options.coffee index 5a4a93ab..c8c21850 100644 --- a/pages/options.coffee +++ b/pages/options.coffee @@ -1,7 +1,6 @@ $ = (id) -> document.getElementById id -bgUtils = chrome.extension.getBackgroundPage().Utils -bgSettings = chrome.extension.getBackgroundPage().Settings +Settings.init() bgExclusions = chrome.extension.getBackgroundPage().Exclusions # @@ -22,21 +21,20 @@ class Option # Fetch a setting from localStorage, remember the @previous value and populate the DOM element. # Return the fetched value. fetch: -> - @populateElement @previous = bgSettings.get @field + @populateElement @previous = Settings.get @field @previous # Write this option's new value back to localStorage, if necessary. save: -> value = @readValueFromElement() if not @areEqual value, @previous - bgSettings.set @field, @previous = value - bgSettings.performPostUpdateHook @field, value + Settings.set @field, @previous = value # Compare values; this is overridden by sub-classes. areEqual: (a,b) -> a == b restoreToDefault: -> - bgSettings.clear @field + Settings.clear @field @fetch() # Static method. @@ -118,8 +116,8 @@ class ExclusionRulesOption extends Option readValueFromElement: -> rules = for element in @element.getElementsByClassName "exclusionRuleTemplateInstance" - pattern: @getPattern(element).value.split(/\s+/).join "" - passKeys: @getPassKeys(element).value.split(/\s+/).join "" + pattern: @getPattern(element).value.trim() + passKeys: @getPassKeys(element).value.trim() rules.filter (rule) -> rule.pattern areEqual: (a,b) -> @@ -260,6 +258,7 @@ initOptionsPage = -> searchEngines: TextOption searchUrl: NonEmptyTextOption userDefinedLinkHintCss: TextOption + omniSearchWeight: NumberOption # Populate options. The constructor adds each new object to "Option.all". for name, type of options @@ -270,8 +269,12 @@ initPopupPage = -> exclusions = null document.getElementById("optionsLink").setAttribute "href", chrome.runtime.getURL("pages/options.html") + # As the active URL, we choose the most recently registered URL from a frame in the tab, or the tab's own + # URL. + url = chrome.extension.getBackgroundPage().urlForTab[tab.id] || tab.url + updateState = -> - rule = bgExclusions.getRule tab.url, exclusions.readValueFromElement() + rule = bgExclusions.getRule url, exclusions.readValueFromElement() $("state").innerHTML = "Vimium will " + if rule and rule.passKeys "exclude <span class='code'>#{rule.passKeys}</span>" @@ -290,8 +293,6 @@ initPopupPage = -> Option.saveOptions() $("saveOptions").innerHTML = "Saved" $("saveOptions").disabled = true - chrome.tabs.query { windowId: chrome.windows.WINDOW_ID_CURRENT, active: true }, (tabs) -> - chrome.extension.getBackgroundPage().updateActiveState(tabs[0].id) $("saveOptions").addEventListener "click", saveOptions @@ -301,7 +302,7 @@ initPopupPage = -> window.close() # Populate options. Just one, here. - exclusions = new ExclusionRulesOnPopupOption(tab.url, "exclusionRules", onUpdated) + exclusions = new ExclusionRulesOnPopupOption url, "exclusionRules", onUpdated updateState() document.addEventListener "keyup", updateState diff --git a/pages/options.css b/pages/options.css index 8d1014dc..ffb348c6 100644 --- a/pages/options.css +++ b/pages/options.css @@ -107,9 +107,10 @@ input#linkHintNumbers { input#linkHintCharacters { width: 100%; } -input#scrollStepSize { - width: 40px; +input#scrollStepSize, input#omniSearchWeight { + width: 50px; margin-right: 3px; + padding-left: 3px; } textarea#userDefinedLinkHintCss, textarea#keyMappings, textarea#searchEngines { width: 100%;; diff --git a/pages/options.html b/pages/options.html index 777d514a..b14c454f 100644 --- a/pages/options.html +++ b/pages/options.html @@ -3,6 +3,7 @@ <title>Vimium Options</title> <link rel="stylesheet" type="text/css" href="options.css"> <script src="content_script_loader.js"></script> + <script type="text/javascript" src="../lib/settings.js"></script> <script type="text/javascript" src="options.js"></script> </head> @@ -68,6 +69,9 @@ b: http://b.com/?q=%s description </tr> <tbody id='advancedOptions'> <tr> + <td colspan="2"><header>Advanced Options</header></td> + </tr> + <tr> <td class="caption">Scroll step size</td> <td> <div class="help"> @@ -197,7 +201,7 @@ b: http://b.com/?q=%s description <div class="help"> <div class="example"> The page to open with the "create new tab" command. - Set this to "<tt>pages/blank.html</tt>" for a blank page.<br /> + Set this to "<tt>pages/blank.html</tt>" for a blank page (except incognito mode).<br /> </div> </div> <input id="newTabUrl" type="text" /> @@ -230,6 +234,36 @@ b: http://b.com/?q=%s description <div class="nonEmptyTextOption"> </td> </tr> + + <!-- Vimium Labs --> + <!-- + Disabled. But we leave this code here as a template for the next time we need to introduce "Vimium Labs". + <tr> + <td colspan="2"><header>Vimium Labs</header></td> + </tr> + <tr> + <td class="caption"></td> + <td> + <div class="help"> + <div class="example"> + </div> + </div> + These features are experimental and may be changed or removed in future releases. + </td> + </tr> + <tr> + <td class="caption">Search weighting</td> + <td> + <div class="help"> + <div class="example"> + How prominent should suggestions be in the vomnibar? + <tt>0</tt> disables suggestions altogether. + </div> + </div> + <input id="omniSearchWeight" type="number" min="0.0" max="1.0" step="0.05" />(0 to 1) + </td> + </tr> + --> </tbody> </table> </div> diff --git a/pages/popup.html b/pages/popup.html index c7e2fd6f..fdf116e5 100644 --- a/pages/popup.html +++ b/pages/popup.html @@ -48,6 +48,8 @@ } </style> + <script src="../lib/utils.js"></script> + <script src="../lib/settings.js"></script> <script src="options.js"></script> </head> <body> diff --git a/pages/vomnibar.coffee b/pages/vomnibar.coffee index 18a72a37..d5659fdc 100644 --- a/pages/vomnibar.coffee +++ b/pages/vomnibar.coffee @@ -9,79 +9,97 @@ Vomnibar = completers: {} getCompleter: (name) -> - if (!(name of @completers)) - @completers[name] = new BackgroundCompleter(name) - @completers[name] + @completers[name] ?= new BackgroundCompleter name - # - # Activate the Vomnibox. - # activate: (userOptions) -> options = completer: "omni" query: "" newTab: false selectFirst: false + keyword: null extend options, userOptions + extend options, refreshInterval: if options.completer == "omni" then 150 else 0 - options.refreshInterval = switch options.completer - when "omni" then 100 - else 0 - - completer = @getCompleter(options.completer) + completer = @getCompleter options.completer @vomnibarUI ?= new VomnibarUI() - completer.refresh() - @vomnibarUI.setInitialSelectionValue(if options.selectFirst then 0 else -1) - @vomnibarUI.setCompleter(completer) - @vomnibarUI.setRefreshInterval(options.refreshInterval) - @vomnibarUI.setForceNewTab(options.newTab) - @vomnibarUI.setQuery(options.query) - @vomnibarUI.update() + completer.refresh @vomnibarUI + @vomnibarUI.setInitialSelectionValue if options.selectFirst then 0 else -1 + @vomnibarUI.setCompleter completer + @vomnibarUI.setRefreshInterval options.refreshInterval + @vomnibarUI.setForceNewTab options.newTab + @vomnibarUI.setQuery options.query + @vomnibarUI.setKeyword options.keyword + @vomnibarUI.update true + + hide: -> @vomnibarUI?.hide() + onHidden: -> @vomnibarUI?.onHidden() class VomnibarUI constructor: -> @refreshInterval = 0 + @postHideCallback = null @initDom() setQuery: (query) -> @input.value = query - - setInitialSelectionValue: (initialSelectionValue) -> - @initialSelectionValue = initialSelectionValue - - setCompleter: (completer) -> - @completer = completer - @reset() - @update(true) - - setRefreshInterval: (refreshInterval) -> @refreshInterval = refreshInterval - - setForceNewTab: (forceNewTab) -> @forceNewTab = forceNewTab - - hide: -> + setKeyword: (keyword) -> @customSearchMode = keyword + setInitialSelectionValue: (@initialSelectionValue) -> + setRefreshInterval: (@refreshInterval) -> + setForceNewTab: (@forceNewTab) -> + setCompleter: (@completer) -> @reset() + setKeywords: (@keywords) -> + + # The sequence of events when the vomnibar is hidden is as follows: + # 1. Post a "hide" message to the host page. + # 2. The host page hides the vomnibar. + # 3. When that page receives the focus, and it posts back a "hidden" message. + # 3. Only once the "hidden" message is received here is any required action invoked (in onHidden). + # This ensures that the vomnibar is actually hidden before any new tab is created, and avoids flicker after + # opening a link in a new tab then returning to the original tab (see #1485). + hide: (@postHideCallback = null) -> UIComponentServer.postMessage "hide" @reset() + @completer?.reset() + + onHidden: -> + @postHideCallback?() + @postHideCallback = null reset: -> + @clearUpdateTimer() @completionList.style.display = "" @input.value = "" - @updateTimer = null @completions = [] + @previousInputValue = null + @customSearchMode = null @selection = @initialSelectionValue + @keywords = [] + @seenTabToOpenCompletionList = false updateSelection: -> - # We retain global state here (previousAutoSelect) to tell if a search item (for which autoSelect is set) - # has just appeared or disappeared. If that happens, we set @selection to 0 or -1. - if @completions[0] - @selection = 0 if @completions[0].autoSelect and not @previousAutoSelect - @selection = -1 if @previousAutoSelect and not @completions[0].autoSelect - @previousAutoSelect = @completions[0].autoSelect + # For custom search engines, we suppress the leading term (e.g. the "w" of "w query terms") within the + # vomnibar input. + if @lastReponse.isCustomSearch and not @customSearchMode? + queryTerms = @input.value.trim().split /\s+/ + @customSearchMode = queryTerms[0] + @input.value = queryTerms[1..].join " " + + # For suggestions for custom search engines, we copy the suggested text into the input when the item is + # selected, and revert when it is not. This allows the user to select a suggestion and then continue + # typing. + if 0 <= @selection and @completions[@selection].insertText? + @previousInputValue ?= @input.value + @input.value = @completions[@selection].insertText + else if @previousInputValue? + @input.value = @previousInputValue + @previousInputValue = null + + # Highlight the selected entry, and only the selected entry. for i in [0...@completionList.children.length] @completionList.children[i].className = (if i == @selection then "vomnibarSelected" else "") - # - # Returns the user's action ("up", "down", "enter", "dismiss" or null) based on their keypress. - # We support the arrow keys and other shortcuts for moving, so this method hides that complexity. - # + # Returns the user's action ("up", "down", "tab", etc, or null) based on their keypress. We support the + # arrow keys and various other shortcuts, and this function hides the event-decoding complexity. actionFromKeyEvent: (event) -> key = KeyboardUtils.getKeyChar(event) if (KeyboardUtils.isEscape(event)) @@ -90,83 +108,139 @@ class VomnibarUI (event.shiftKey && event.keyCode == keyCodes.tab) || (event.ctrlKey && (key == "k" || key == "p"))) return "up" + else if (event.keyCode == keyCodes.tab && !event.shiftKey) + return "tab" else if (key == "down" || - (event.keyCode == keyCodes.tab && !event.shiftKey) || (event.ctrlKey && (key == "j" || key == "n"))) return "down" else if (event.keyCode == keyCodes.enter) return "enter" + else if event.keyCode == keyCodes.backspace || event.keyCode == keyCodes.deleteKey + return "delete" + + null onKeydown: (event) => - action = @actionFromKeyEvent(event) + @lastAction = action = @actionFromKeyEvent event return true unless action # pass through openInNewTab = @forceNewTab || (event.shiftKey || event.ctrlKey || KeyboardUtils.isPrimaryModifierKey(event)) if (action == "dismiss") @hide() + else if action in [ "tab", "down" ] + if action == "tab" and + @completer.name == "omni" and + not @seenTabToOpenCompletionList and + @input.value.trim().length == 0 + @seenTabToOpenCompletionList = true + @update true + else + @selection += 1 + @selection = @initialSelectionValue if @selection == @completions.length + @updateSelection() else if (action == "up") @selection -= 1 @selection = @completions.length - 1 if @selection < @initialSelectionValue @updateSelection() - else if (action == "down") - @selection += 1 - @selection = @initialSelectionValue if @selection == @completions.length - @updateSelection() else if (action == "enter") - # If they type something and hit enter without selecting a completion from our list of suggestions, - # try to open their query as a URL directly. If it doesn't look like a URL, we will search using - # google. - if (@selection == -1) + isCustomSearchPrimarySuggestion = @completions[@selection]?.isPrimarySuggestion and @lastReponse.engine?.searchUrl? + if @selection == -1 or isCustomSearchPrimarySuggestion query = @input.value.trim() - # <Enter> on an empty vomnibar is a no-op. + # <Enter> on an empty query is a no-op. return unless 0 < query.length - @hide() - chrome.runtime.sendMessage({ - handler: if openInNewTab then "openUrlInNewTab" else "openUrlInCurrentTab" - url: query }) + # First case (@selection == -1). + # If the user types something and hits enter without selecting a completion from the list, then: + # - If a search URL has been provided, then use it. This is custom search engine request. + # - Otherwise, send the query to the background page, which will open it as a URL or create a + # default search, as appropriate. + # + # Second case (isCustomSearchPrimarySuggestion). + # Alternatively, the selected completion could be the primary selection for a custom search engine. + # Because the the suggestions are updated asynchronously in omni mode, the user may have typed more + # text than that which is included in the URL associated with the primary suggestion. Therefore, to + # avoid a race condition, we construct the query from the actual contents of the input (query). + query = Utils.createSearchUrl query, @lastReponse.engine.searchUrl if isCustomSearchPrimarySuggestion + @hide -> + chrome.runtime.sendMessage + handler: if openInNewTab then "openUrlInNewTab" else "openUrlInCurrentTab" + url: query + else + completion = @completions[@selection] + @hide -> completion.performAction openInNewTab + else if action == "delete" + inputIsEmpty = @input.value.length == 0 + if inputIsEmpty and @customSearchMode? + # Normally, with custom search engines, the keyword (e,g, the "w" of "w query terms") is suppressed. + # If the input is empty, then reinstate the keyword (the "w"). + @input.value = @customSearchMode + @customSearchMode = null + @update true + else if inputIsEmpty and @seenTabToOpenCompletionList + @seenTabToOpenCompletionList = false + @update true else - @update true, => - # Shift+Enter will open the result in a new tab instead of the current tab. - @completions[@selection].performAction(openInNewTab) - @hide() + return true # Do not suppress event. # It seems like we have to manually suppress the event here and still return true. event.stopImmediatePropagation() event.preventDefault() true - updateCompletions: (callback) -> - query = @input.value.trim() - - @completer.filter query, (completions) => - @completions = completions - @populateUiWithCompletions(completions) - callback() if callback - - populateUiWithCompletions: (completions) -> - # update completion list with the new data - @completionList.innerHTML = completions.map((completion) -> "<li>#{completion.html}</li>").join("") - @completionList.style.display = if completions.length > 0 then "block" else "" - @selection = Math.min(Math.max(@initialSelectionValue, @selection), @completions.length - 1) - @updateSelection() - - update: (updateSynchronously, callback) => - if (updateSynchronously) - # cancel scheduled update - if (@updateTimer != null) - window.clearTimeout(@updateTimer) - @updateCompletions(callback) - else if (@updateTimer != null) - # an update is already scheduled, don't do anything - return - else - # always update asynchronously for better user experience and to take some load off the CPU - # (not every keystroke will cause a dedicated update) - @updateTimer = setTimeout(=> - @updateCompletions(callback) + # Return the background-page query corresponding to the current input state. In other words, reinstate any + # search engine keyword which is currently being suppressed, and strip any prompted text. + getInputValueAsQuery: -> + (if @customSearchMode? then @customSearchMode + " " else "") + @input.value + + updateCompletions: (callback = null) -> + @completer.filter + query: @getInputValueAsQuery() + seenTabToOpenCompletionList: @seenTabToOpenCompletionList + callback: (@lastReponse) => + { results } = @lastReponse + @completions = results + @selection = if @completions[0]?.autoSelect then 0 else @initialSelectionValue + # Update completion list with the new suggestions. + @completionList.innerHTML = @completions.map((completion) -> "<li>#{completion.html}</li>").join("") + @completionList.style.display = if @completions.length > 0 then "block" else "" + @selection = Math.min @completions.length - 1, Math.max @initialSelectionValue, @selection + @updateSelection() + callback?() + + onInput: => + @seenTabToOpenCompletionList = false + @completer.cancel() + if 0 <= @selection and @completions[@selection].customSearchMode and not @customSearchMode + @customSearchMode = @completions[@selection].customSearchMode + updateSynchronously = true + # If the user types, then don't reset any previous text, and reset the selection. + if @previousInputValue? + @previousInputValue = null + @selection = -1 + @update updateSynchronously + + clearUpdateTimer: -> + if @updateTimer? + window.clearTimeout @updateTimer + @updateTimer = null + + shouldActivateCustomSearchMode: -> + queryTerms = @input.value.ltrim().split /\s+/ + 1 < queryTerms.length and queryTerms[0] in @keywords and not @customSearchMode + + update: (updateSynchronously = false, callback = null) => + # If the query text becomes a custom search (the user enters a search keyword), then we need to force a + # synchronous update (so that the state is updated immediately). + updateSynchronously ||= @shouldActivateCustomSearchMode() + if updateSynchronously + @clearUpdateTimer() + @updateCompletions callback + else if not @updateTimer? + # Update asynchronously for a better user experience, and to take some load off the CPU (not every + # keystroke will cause a dedicated update). + @updateTimer = Utils.setTimeout @refreshInterval, => @updateTimer = null - @refreshInterval) + @updateCompletions callback @input.focus() @@ -174,58 +248,93 @@ class VomnibarUI @box = document.getElementById("vomnibar") @input = @box.querySelector("input") - @input.addEventListener "input", @update + @input.addEventListener "input", @onInput @input.addEventListener "keydown", @onKeydown @completionList = @box.querySelector("ul") @completionList.style.display = "" window.addEventListener "focus", => @input.focus() + # A click in the vomnibar itself refocuses the input. + @box.addEventListener "click", (event) => + @input.focus() + event.stopImmediatePropagation() + # A click anywhere else hides the vomnibar. + document.body.addEventListener "click", => @hide() # -# Sends filter and refresh requests to a Vomnibox completer on the background page. +# Sends requests to a Vomnibox completer on the background page. # class BackgroundCompleter - # - name: The background page completer that you want to interface with. Either "omni", "tabs", or - # "bookmarks". */ + # The "name" is the background-page completer to connect to: "omni", "tabs", or "bookmarks". constructor: (@name) -> - @filterPort = chrome.runtime.connect({ name: "filterCompleter" }) - - refresh: -> chrome.runtime.sendMessage({ handler: "refreshCompleter", name: @name }) - - filter: (query, callback) -> - id = Utils.createUniqueId() - @filterPort.onMessage.addListener (msg) => - @filterPort.onMessage.removeListener(arguments.callee) - # The result objects coming from the background page will be of the form: - # { html: "", type: "", url: "" } - # type will be one of [tab, bookmark, history, domain]. - results = msg.results.map (result) -> - functionToCall = if (result.type == "tab") - BackgroundCompleter.completionActions.switchToTab.curry(result.tabId) - else - BackgroundCompleter.completionActions.navigateToUrl.curry(result.url) - result.performAction = functionToCall - result - callback(results) - - @filterPort.postMessage({ id: id, name: @name, query: query }) - -extend BackgroundCompleter, - # - # These are the actions we can perform when the user selects a result in the Vomnibox. - # + @port = chrome.runtime.connect name: "completions" + @messageId = null + @reset() + + @port.onMessage.addListener (msg) => + switch msg.handler + when "keywords" + @keywords = msg.keywords + @lastUI.setKeywords @keywords + when "completions" + if msg.id == @messageId + # The result objects coming from the background page will be of the form: + # { html: "", type: "", url: "", ... } + # Type will be one of [tab, bookmark, history, domain, search], or a custom search engine description. + for result in msg.results + extend result, + performAction: + if result.type == "tab" + @completionActions.switchToTab result.tabId + else + @completionActions.navigateToUrl result.url + + # Handle the message, but only if it hasn't arrived too late. + @mostRecentCallback msg + + filter: (request) -> + { query, callback } = request + @mostRecentCallback = callback + + @port.postMessage extend request, + handler: "filter" + name: @name + id: @messageId = Utils.createUniqueId() + queryTerms: query.trim().split(/\s+/).filter (s) -> 0 < s.length + # We don't send these keys. + callback: null + + reset: -> + @keywords = [] + + refresh: (@lastUI) -> + @reset() + @port.postMessage name: @name, handler: "refresh" + + cancel: -> + # Inform the background completer that it may (should it choose to do so) abandon any pending query + # (because the user is typing, and there will be another query along soon). + @port.postMessage name: @name, handler: "cancel" + + # These are the actions we can perform when the user selects a result. completionActions: - navigateToUrl: (url, openInNewTab) -> - # If the URL is a bookmarklet prefixed with javascript:, we shouldn't open that in a new tab. - openInNewTab = false if url.startsWith("javascript:") - chrome.runtime.sendMessage( + navigateToUrl: (url) -> (openInNewTab) -> + # If the URL is a bookmarklet (so, prefixed with "javascript:"), then we always open it in the current + # tab. + openInNewTab &&= not Utils.hasJavascriptPrefix url + chrome.runtime.sendMessage handler: if openInNewTab then "openUrlInNewTab" else "openUrlInCurrentTab" - url: url, - selected: openInNewTab) + url: url + selected: openInNewTab - switchToTab: (tabId) -> chrome.runtime.sendMessage({ handler: "selectSpecificTab", id: tabId }) + switchToTab: (tabId) -> -> + chrome.runtime.sendMessage handler: "selectSpecificTab", id: tabId -UIComponentServer.registerHandler (event) -> Vomnibar.activate event.data +UIComponentServer.registerHandler (event) -> + switch event.data + when "hide" then Vomnibar.hide() + when "hidden" then Vomnibar.onHidden() + else Vomnibar.activate event.data root = exports ? window root.Vomnibar = Vomnibar diff --git a/pages/vomnibar.css b/pages/vomnibar.css index 2042a6c4..1b19daad 100644 --- a/pages/vomnibar.css +++ b/pages/vomnibar.css @@ -126,7 +126,6 @@ #vomnibar li em { font-style: italic; } #vomnibar li em .vomnibarMatch, #vomnibar li .vomnibarTitle .vomnibarMatch { color: #333; - text-decoration: underline; } #vomnibar li.vomnibarSelected { @@ -134,3 +133,21 @@ font-weight: normal; } +#vomnibarInput::selection { + /* This is the light grey color of the vomnibar border. */ + /* background-color: #F1F1F1; */ + + /* This is the light blue color of the vomnibar selected item. */ + /* background-color: #BBCEE9; */ + + /* This is a considerably lighter blue than Vimium blue, which seems softer + * on the eye for this purpose. */ + background-color: #E6EEFB; +} + +.vomnibarInsertText { +} + +.vomnibarNoInsertText { + visibility: hidden; +} diff --git a/pages/vomnibar.html b/pages/vomnibar.html index 2ca463d0..87acc081 100644 --- a/pages/vomnibar.html +++ b/pages/vomnibar.html @@ -14,7 +14,7 @@ <body> <div id="vomnibar" class="vimiumReset"> <div class="vimiumReset vomnibarSearchArea"> - <input type="text" class="vimiumReset"> + <input id="vomnibarInput" type="text" class="vimiumReset"> </div> <ul class="vimiumReset"></ul> </div> |
