Skip to content
This repository has been archived by the owner on May 27, 2019. It is now read-only.

Commit

Permalink
Implement as-you-type filtering, make Enter submit the first entry (#220
Browse files Browse the repository at this point in the history
, fixes #40, fixes #211)
  • Loading branch information
erayd authored and maximbaz committed Mar 19, 2018
1 parent e1aa4b7 commit 49bbfd5
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 29 deletions.
131 changes: 104 additions & 27 deletions chrome/script.browserify.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
"use strict";

var m = require("mithril");
var FuzzySort = require("fuzzysort");
var app = "com.dannyvankooten.browserpass";
var activeTab;
var searching = false;
var logins;
var resultLogins = [];
var logins = [];
var fillOnSubmit = false;
var error;
var domain, urlDuringSearch;

Expand All @@ -24,10 +27,10 @@ function view() {
results = m("div.status-text", "Error: " + error);
error = undefined;
} else if (logins) {
if (logins.length === 0) {
if (logins.length === 0 && domain && domain.length > 0) {
results = m(
"div.status-text",
m.trust(`No passwords found for <strong>${domain}</strong>.`)
m.trust(`No matching passwords found for <strong>${domain}</strong>.`)
);
} else if (logins.length > 0) {
results = logins.map(function(login) {
Expand Down Expand Up @@ -61,22 +64,29 @@ function view() {
m(
"form",
{
onsubmit: submitSearchForm
onsubmit: submitSearchForm,
onkeydown: searchKeyHandler
},
[
m("input", {
type: "text",
id: "search-field",
name: "s",
placeholder: "Search password..",
autocomplete: "off",
autofocus: "on"
m("div", {
"id": "filter-search"
}),
m("input", {
type: "submit",
value: "Search",
style: "display: none;"
})
m("div", [
m("input", {
type: "text",
id: "search-field",
name: "s",
placeholder: "Search passwords..",
autocomplete: "off",
autofocus: "on",
oninput: filterLogins
}),
m("input", {
type: "submit",
value: "Search",
style: "display: none;"
})
])
]
)
]),
Expand All @@ -86,15 +96,73 @@ function view() {
]);
}

function filterLogins(e) {
// use fuzzy search to filter results
var filter = e.target.value.trim().split(/[\s\/]+/);
if (filter.length > 0) {
logins = resultLogins.slice(0);
filter.forEach(function(word) {
if (word.length > 0) {
var refine = [];
FuzzySort.go(word, logins, {allowTypo: false}).forEach(function(result) {
refine.push(result.target);
});
logins = refine.slice(0);
}
});

// fill login forms on submit rather than initiating a search
fillOnSubmit = logins.length > 0;
} else {
// reset the result list if the filter is empty
logins = resultLogins.slice(0);
}

// redraw the list
m.redraw();

// show / hide the filter hint
showFilterHint(logins.length);
}

function searchKeyHandler(e) {
// switch to search mode if backspace is pressed and no filter text has been entered
if (e.code == "Backspace" && logins.length > 0 && e.target.value.length == 0) {
e.preventDefault();
logins = resultLogins = [];
e.target.value = fillOnSubmit ? '' : domain;
domain = '';
showFilterHint(false);
}
}

function showFilterHint(show=true) {
var filterHint = document.getElementById("filter-search");
var searchField = document.getElementById("search-field");
if (show) {
filterHint.style.display = "block";
searchField.setAttribute("placeholder", "Refine search...");
} else {
filterHint.style.display = "none";
searchField.setAttribute("placeholder", "Search passwords...");
}
}

function submitSearchForm(e) {
e.preventDefault();

// don't search without input.
if (!this.s.value.length) {
return;
}
if (fillOnSubmit && logins.length > 0) {
// fill using the first result
getLoginData.bind(logins[0])();
} else {
// don't search without input.
if (!this.s.value.length) {
return;
}

searchPassword(this.s.value);
// search for matching entries
searchPassword(this.s.value, "search", false);
}
}

function init(tab) {
Expand All @@ -108,9 +176,9 @@ function init(tab) {
searchPassword(activeDomain, "match_domain");
}

function searchPassword(_domain, action="search") {
function searchPassword(_domain, action="search", useFillOnSubmit=true) {
searching = true;
logins = null;
logins = resultLogins = [];
domain = _domain;
urlDuringSearch = activeTab.url;
m.redraw();
Expand All @@ -132,7 +200,13 @@ function searchPassword(_domain, action="search") {
}

searching = false;
logins = response;
logins = resultLogins = response ? response : [];
document.getElementById("filter-search").textContent = domain;
fillOnSubmit = useFillOnSubmit && logins.length > 0;
if (logins.length > 0) {
showFilterHint(true);
document.getElementById("search-field").value = '';
}
m.redraw();
}
);
Expand Down Expand Up @@ -160,13 +234,14 @@ function getFaviconUrl(domain) {

function getLoginData() {
searching = true;
logins = null;
logins = resultLogins = [];
m.redraw();

chrome.runtime.sendMessage(
{ action: "login", entry: this, urlDuringSearch: urlDuringSearch },
function(response) {
searching = false;
fillOnSubmit = false;

if (response.error) {
error = response.error;
Expand Down Expand Up @@ -222,14 +297,16 @@ function keyHandler(e) {
switchFocus("div.entry:first-child > .login", "nextElementSibling");
break;
case "c":
if (e.ctrlKey) {
if (e.target.id != "search-field" && e.ctrlKey) {
document.activeElement["nextElementSibling"][
"nextElementSibling"
].click();
}
break;
case "C":
document.activeElement["nextElementSibling"].click();
if (e.target.id != "search-field") {
document.activeElement["nextElementSibling"].click();
}
break;
}
}
Expand Down
20 changes: 19 additions & 1 deletion chrome/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,37 @@ body {
font-size: 14px;
}

.search > form {
border-bottom: 1px solid #bbb;
display: flex;
flex-wrap: nowrap;
}

.search > form :last-child {
width: 100%;
}

.search input {
box-sizing: border-box;
width: 100%;
padding: 6px;
border: 0;
border-bottom: 1px solid #bbb;
background: url("icon-search.svg") center right 6px no-repeat;
background-size: 16px 16px;
background-color: white;
color: black;
padding-right: 20px;
}

#filter-search {
background: #eee;
border: 0;
box-sizing: border-box;
display: none;
padding: 6px;
padding-top: 5px;
}

.search input:focus {
outline: 0;
}
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"dependencies": {
"browserify": "^14.4.0",
"mithril": "^1.1.4"
"mithril": "^1.1.4",
"fuzzysort": "^1.1.0"
}
}
4 changes: 4 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,10 @@ function-bind@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"

fuzzysort@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/fuzzysort/-/fuzzysort-1.1.1.tgz#bf128f1a4cc6e6b7188665ac5676de46a3d81768"

glob@^7.1.0:
version "7.1.1"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
Expand Down

0 comments on commit 49bbfd5

Please sign in to comment.