Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions js/navbar/tabEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,9 @@ const tabEditor = {

tabEditor.input.addEventListener('keypress', function (e) {
if (e.keyCode === 13) { // return key pressed; update the url
if (this.getAttribute('data-autocomplete') && this.getAttribute('data-autocomplete').toLowerCase() === this.value.toLowerCase()) {
// special case: if the typed input is capitalized differently from the actual URL that was autocompleted (but is otherwise the same), then we want to open the actual URL instead of what was typed.
// see https://github.com/minbrowser/min/issues/314#issuecomment-276678613
searchbar.openURL(this.getAttribute('data-autocomplete'), e)
if (this.getAttribute('data-autocomplete-text') && this.getAttribute('data-autocomplete-text').toLowerCase() === this.value.toLowerCase()) {
// The original autocompletion can contain additional information, such as a protocol or different capitalization than what was typed
searchbar.openURL(this.getAttribute('data-autocomplete-ref') || this.getAttribute('data-autocomplete-text'), e)
} else {
searchbar.openURL(this.value, e)
}
Expand Down
2 changes: 1 addition & 1 deletion js/searchbar/bangsPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ function getBangSearchResults (text, input, inputFlags) {
showBangSearchResults(text, results, input, inputFlags)

if (results[0] && !inputFlags.isDeletion) {
searchbarAutocomplete.autocomplete(input, [results[0].phrase])
searchbarAutocomplete.autocomplete(input, [[results[0].phrase]])
}
}
})
Expand Down
2 changes: 1 addition & 1 deletion js/searchbar/bookmarkEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ const bookmarkEditor = {
newTagInput.addEventListener('keypress', function (e) {
if (e.keyCode !== 8 && e.keyCode !== 13) {
places.getAllTagsRanked(bookmarkEditor.currentInstance.bookmark.url).then(function (results) {
autocomplete.autocomplete(newTagInput, results.map(r => r.tag))
autocomplete.autocomplete(newTagInput, results.map(r => [r.tag]))
})
}
})
Expand Down
2 changes: 1 addition & 1 deletion js/searchbar/placesPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ async function showSearchbarPlaceResults (text, input, inputFlags, pluginName =
if (canAutocomplete) {
// if the query is autocompleted, pressing enter will search for the result using the current search engine, so only pages from the current engine should be autocompleted
if (searchQuery && searchQuery.engine === searchEngine.getCurrent().name && index === 0) {
var acResult = searchbarAutocomplete.autocomplete(input, [searchQuery.search])
var acResult = searchbarAutocomplete.autocomplete(input, [[searchQuery.search]])
if (acResult.valid) {
canAutocomplete = false
didAutocompleteResult = true
Expand Down
60 changes: 47 additions & 13 deletions js/util/autocomplete.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
var urlParser = require('util/urlParser.js')

function autocomplete (input, strings) {
function autocomplete(input, completions) {
// if there is text after the selection, we can never autocomplete
if (input.selectionEnd !== input.value.length) {
return {
Expand All @@ -10,44 +10,78 @@ function autocomplete (input, strings) {

var text = input.value.substring(0, input.selectionStart)

for (var i = 0; i < strings.length; i++) {
for (var i = 0; i < completions.length; i++) {
// check if the item can be autocompleted
if (strings[i].toLowerCase().indexOf(text.toLowerCase()) === 0) {
input.value = text + strings[i].substring(input.selectionStart)
input.setSelectionRange(text.length, strings[i].length)
input.setAttribute('data-autocomplete', strings[i])
if (completions[i][0].toLowerCase().indexOf(text.toLowerCase()) === 0) {
input.value = text + completions[i][0].substring(input.selectionStart)
input.setSelectionRange(text.length, completions[i][0].length)
input.setAttribute('data-autocomplete-text', completions[i][0])
if (completions[i][1]) {
input.setAttribute('data-autocomplete-ref', completions[i][1])
} else {
input.removeAttribute('data-autocomplete-ref')
}

return {
valid: true,
matchIndex: i
}
}
}
input.removeAttribute('data-autocomplete')
input.removeAttribute('data-autocomplete-text')
input.removeAttribute('data-autocomplete-ref')
return {
valid: false
}
}

// autocompletes based on a result item
// returns: 1 - the exact URL was autocompleted, 0 - the domain was autocompleted, -1: nothing was autocompleted
function autocompleteURL (input, url) {
function autocompleteURL(input, url) {
var urlObj = new URL(url)
var hostname = urlObj.hostname

// the different variations of the URL we can autocomplete
var possibleAutocompletions = [
// we start with the domain, including any non-standard ports (such as localhost:8080)
hostname + (urlObj.port ? ':' + urlObj.port : ''),
[
hostname + (urlObj.port ? ':' + urlObj.port : ''),
new URL(urlObj.protocol + '//' + hostname + (urlObj.port ? ':' + urlObj.port : ''))
],
// if that doesn't match, try the hostname without the www instead. The regex requires a slash at the end, so we add one, run the regex, and then remove it
(hostname + '/').replace(urlParser.startingWWWRegex, '$1').replace('/', ''),
[
(hostname + '/').replace(urlParser.startingWWWRegex, '$1').replace('/', ''),
new URL(urlObj.protocol + '//' + (hostname + '/').replace(urlParser.startingWWWRegex, '$1').replace('/', ''))
],
// then try the whole URL
urlParser.prettyURL(url),
[
urlParser.prettyURL(url),
(() => {
try {
return new URL(urlParser.prettyURL(url))
} catch (e) { return null }
})()
],
// then try the URL with querystring
urlParser.basicURL(url),
[
urlParser.basicURL(url),
(() => {
try {
return new URL(urlParser.basicURL(url))
} catch (e) { return null }
})()
],
// then just try the URL with protocol
url
[
url,
(() => {
try {
return new URL(url)
} catch (e) { return null }
})()
]
]
.map(completion => [completion[0], completion[1] ? completion[1].toString() : null])

var autocompleteResult = autocomplete(input, possibleAutocompletions)

Expand Down