aboutsummaryrefslogtreecommitdiffstats
path: root/background_scripts/completion_search.coffee
diff options
context:
space:
mode:
Diffstat (limited to 'background_scripts/completion_search.coffee')
-rw-r--r--background_scripts/completion_search.coffee66
1 files changed, 47 insertions, 19 deletions
diff --git a/background_scripts/completion_search.coffee b/background_scripts/completion_search.coffee
index b3ae88d4..09261ff6 100644
--- a/background_scripts/completion_search.coffee
+++ b/background_scripts/completion_search.coffee
@@ -1,12 +1,38 @@
-class EngineWrapper
+# This is a wrapper class for completion engines. It handles the case where a custom search engine includes a
+# prefix query term (or terms). For example:
+#
+# http://www.google.com/search?q=javascript+%s
+#
+# In this case, we get better suggestions if we include the term "javascript" in queries sent to the
+# completion engine. This wrapper handles adding such prefixes to completion-engine queries and removing them
+# from the resulting suggestions.
+class EnginePrefixWrapper
constructor: (@searchUrl, @engine) ->
getUrl: (queryTerms) ->
+ # This tests whether @searchUrl contains something of the form "...=abc+def+%s...", from which we extract
+ # a prefix of the form "abc def ".
+ if /\=.+\+%s/.test @searchUrl
+ terms = @searchUrl.replace /\+%s.*/, ""
+ terms = terms.replace /.*=/, ""
+ terms = terms.replace /\+/g, " "
+
+ queryTerms = [ terms.split(" ")..., queryTerms... ]
+ prefix = "#{terms} "
+
+ @postprocessSuggestions =
+ (suggestions) ->
+ for suggestion in suggestions
+ continue unless suggestion.startsWith prefix
+ suggestion[prefix.length..]
+
@engine.getUrl queryTerms
parse: (xhr) ->
- @engine.parse xhr
+ @postprocessSuggestions @engine.parse xhr
+
+ postprocessSuggestions: (suggestions) -> suggestions
CompletionSearch =
debug: false
@@ -74,22 +100,23 @@ CompletionSearch =
# If the user appears to be typing a continuation of the characters of the most recent query, then we can
# sometimes re-use the previous suggestions.
- if @mostRecentQuery? and @mostRecentSuggestions?
- reusePreviousSuggestions = do =>
- # Verify that the previous query is a prefix of the current query.
- return false unless 0 == query.indexOf @mostRecentQuery.toLowerCase()
- # Verify that every previous suggestion contains the text of the new query.
- # Note: @mostRecentSuggestions may also be empty, in which case we drop though. The effect is that
- # previous queries with no suggestions suppress subsequent no-hope HTTP requests as the user continues
- # to type.
- for suggestion in @mostRecentSuggestions
- return false unless 0 <= suggestion.indexOf query
- # Ok. Re-use the suggestion.
- true
-
- if reusePreviousSuggestions
- console.log "reuse previous query:", @mostRecentQuery, @mostRecentSuggestions.length if @debug
- return callback @completionCache.set completionCacheKey, @mostRecentSuggestions
+ if @mostRecentQuery? and @mostRecentSuggestions? and @mostRecentSearchUrl?
+ if searchUrl == @mostRecentSearchUrl
+ reusePreviousSuggestions = do =>
+ # Verify that the previous query is a prefix of the current query.
+ return false unless 0 == query.indexOf @mostRecentQuery.toLowerCase()
+ # Verify that every previous suggestion contains the text of the new query.
+ # Note: @mostRecentSuggestions may also be empty, in which case we drop though. The effect is that
+ # previous queries with no suggestions suppress subsequent no-hope HTTP requests as the user continues
+ # to type.
+ for suggestion in @mostRecentSuggestions
+ return false unless 0 <= suggestion.indexOf query
+ # Ok. Re-use the suggestion.
+ true
+
+ if reusePreviousSuggestions
+ console.log "reuse previous query:", @mostRecentQuery, @mostRecentSuggestions.length if @debug
+ return callback @completionCache.set completionCacheKey, @mostRecentSuggestions
# That's all of the caches we can try. Bail if the caller is only requesting synchronous results. We
# signal that we haven't found a match by returning null.
@@ -102,7 +129,7 @@ CompletionSearch =
# Elide duplicate requests. First fetch the suggestions...
@inTransit[completionCacheKey] ?= new AsyncDataFetcher (callback) =>
- engine = new EngineWrapper searchUrl, @lookupEngine searchUrl
+ engine = new EnginePrefixWrapper searchUrl, @lookupEngine searchUrl
url = engine.getUrl queryTerms
@get searchUrl, url, (xhr = null) =>
@@ -128,6 +155,7 @@ CompletionSearch =
# ... then use the suggestions.
@inTransit[completionCacheKey].use (suggestions) =>
+ @mostRecentSearchUrl = searchUrl
@mostRecentQuery = query
@mostRecentSuggestions = suggestions
callback @completionCache.set completionCacheKey, suggestions