Vomnibar = vomnibarUI: null # the dialog instance for this window completers: {} getCompleter: (name) -> if (!(name of @completers)) @completers[name] = new BackgroundCompleter(name) @completers[name] # # Activate the Vomnibox. # activateWithCompleter: (completerName, refreshInterval, initialQueryValue, selectFirstResult, forceNewTab) -> completer = @getCompleter(completerName) @vomnibarUI = new VomnibarUI() unless @vomnibarUI completer.refresh() @vomnibarUI.setInitialSelectionValue(if selectFirstResult then 0 else -1) @vomnibarUI.setCompleter(completer) @vomnibarUI.setRefreshInterval(refreshInterval) @vomnibarUI.setForceNewTab(forceNewTab) @vomnibarUI.show() if (initialQueryValue) @vomnibarUI.setQuery(initialQueryValue) @vomnibarUI.update() activate: -> @activateWithCompleter("omni", 100) activateInNewTab: -> @activateWithCompleter("omni", 100, null, true, true) activateTabSelection: -> @activateWithCompleter("tabs", 0, null, true) activateBookmarks: -> @activateWithCompleter("bookmarks", 0, null, true) activateBookmarksInNewTab: -> @activateWithCompleter("bookmarks", 0, null, true, true) getUI: -> @vomnibarUI class VomnibarUI constructor: -> @refreshInterval = 0 @initDom() setQuery: (query) -> @input.value = query setInitialSelectionValue: (initialSelectionValue) -> @initialSelectionValue = initialSelectionValue setCompleter: (completer) -> @completer = completer @reset() setRefreshInterval: (refreshInterval) -> @refreshInterval = refreshInterval setForceNewTab: (forceNewTab) -> @forceNewTab = forceNewTab show: -> @box.style.display = "block" @input.focus() handlerStack.push({ keydown: @onKeydown.bind(this) }) hide: -> @box.style.display = "none" @completionList.style.display = "none" @input.blur() handlerStack.pop() reset: -> @input.value = "" @updateTimer = null @completions = [] @selection = @initialSelectionValue @update(true) updateSelection: -> if (@completions.length > 0) @selection = Math.min(@selection, @completions.length - 1) 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. # actionFromKeyEvent: (event) -> key = KeyboardUtils.getKeyChar(event) if (KeyboardUtils.isEscape(event)) return "dismiss" else if (key == "up" || (event.shiftKey && event.keyCode == keyCodes.tab) || (event.ctrlKey && (key == "k" || key == "p"))) return "up" 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" onKeydown: (event) -> action = @actionFromKeyEvent(event) return true unless action # pass through openInNewTab = @forceNewTab || (event.shiftKey || KeyboardUtils.isPrimaryModifierKey(event)) if (action == "dismiss") @hide() 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) query = @input.value.trim() @hide() chrome.extension.sendRequest({ handler: if openInNewTab then "openUrlInNewTab" else "openUrlInCurrentTab" url: query }) else @update true, => # Shift+Enter will open the result in a new tab instead of the current tab. @completions[@selection].performAction(openInNewTab) @hide() # It seems like we have to manually supress the event here and still return true. event.stopPropagation() 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) -> "