added search suggestions and autocomplete
This commit is contained in:
sairaj mote 2020-05-24 22:49:25 +05:30
parent 776f05a318
commit 5a66a46d7d
4 changed files with 187 additions and 148 deletions

View File

@ -1,5 +1,4 @@
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700;900&display=swap"); @import url("https://fonts.googleapis.com/css2?family=Barlow:wght@500;600;700&family=Roboto:wght@400;500;700&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Quicksand:wght@500&display=swap");
*, *,
::before, ::before,
::after { ::after {
@ -15,7 +14,7 @@ body {
--text: 17, 17, 17; --text: 17, 17, 17;
--text-light: 100, 100, 100; --text-light: 100, 100, 100;
--foreground: 255, 255, 255; --foreground: 255, 255, 255;
--background: #efefef; --background: #e8e8e8;
--dark-shade: #dadada; --dark-shade: #dadada;
font-size: 16px; font-size: 16px;
color: rgba(var(--text), 1); color: rgba(var(--text), 1);
@ -28,7 +27,7 @@ body[data-theme='dark'] {
--text: 218, 218, 218; --text: 218, 218, 218;
--text-light: 170, 170, 170; --text-light: 170, 170, 170;
--foreground: 20, 20, 20; --foreground: 20, 20, 20;
--background: #111; --background: #0a0a0a;
--dark-shade: #1a1a1a; --dark-shade: #1a1a1a;
} }
@ -125,8 +124,7 @@ h3 {
} }
.other-font { .other-font {
font-family: 'Quicksand', sans-serif; font-family: 'Barlow', sans-serif;
font-weight: 500;
} }
.uppercase { .uppercase {
@ -320,19 +318,18 @@ ul .balance:last-of-type {
-webkit-box-direction: normal; -webkit-box-direction: normal;
-ms-flex-direction: column; -ms-flex-direction: column;
flex-direction: column; flex-direction: column;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
} }
#main_search h1 { #main_search h2 {
margin-top: 2rem;
-ms-flex-item-align: start; -ms-flex-item-align: start;
align-self: flex-start; align-self: flex-start;
margin-top: 2rem; font-size: 4rem;
font-weight: 500; letter-spacing: 0.1em;
font-weight: 600;
} }
#main_search h3 { #main_search h4 {
line-height: 1.4em; line-height: 1.4em;
margin: 1rem 0 2rem 0; margin: 1rem 0 2rem 0;
font-weight: 400; font-weight: 400;
@ -343,6 +340,51 @@ ul .balance:last-of-type {
border-radius: 0.5rem; border-radius: 0.5rem;
} }
#main_search .input input:valid ~ #suggestions {
opacity: 1;
pointer-events: all;
-webkit-transform: none;
transform: none;
}
#main_search label {
position: relative;
}
#main_search #suggestions {
opacity: 0;
pointer-events: none;
-webkit-transform: translateY(-0.5rem);
transform: translateY(-0.5rem);
-webkit-transition: opacity 0.3s, -webkit-transform 0.3s;
transition: opacity 0.3s, -webkit-transform 0.3s;
transition: transform 0.3s, opacity 0.3s;
transition: transform 0.3s, opacity 0.3s, -webkit-transform 0.3s;
position: absolute;
top: 100%;
width: 100%;
background: var(--background);
border-radius: 0.5rem;
padding: 0.5rem 0;
max-height: 20vh;
overflow-y: auto;
margin-top: 0.5rem;
}
#main_search #suggestions:empty {
padding: 0;
}
#main_search .suggestion {
padding: 0.6rem 1.5rem 0.6rem 3rem;
opacity: 0.8;
cursor: pointer;
}
#main_search .suggestion:hover, #main_search .suggestion:focus {
opacity: 1;
}
.input { .input {
position: relative; position: relative;
display: -ms-grid; display: -ms-grid;
@ -357,7 +399,7 @@ ul .balance:last-of-type {
align-items: center; align-items: center;
padding: 0.8rem; padding: 0.8rem;
gap: 1em; gap: 1em;
background: rgba(var(--text), 0.1); background: var(--background);
} }
.input input { .input input {
@ -370,9 +412,9 @@ ul .balance:last-of-type {
} }
.icon { .icon {
height: 1.2em; height: 1.2rem;
overflow: visible; overflow: visible;
width: 1.5em; width: 1.2rem;
fill: none; fill: none;
stroke: rgba(var(--text), 1); stroke: rgba(var(--text), 1);
stroke-linecap: round; stroke-linecap: round;
@ -615,8 +657,6 @@ ul .balance:last-of-type {
.page { .page {
padding: 0 0 1rem 0; padding: 0 0 1rem 0;
-webkit-animation: fade 0.3s;
animation: fade 0.3s;
} }
.page h3.heading { .page h3.heading {

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,4 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700;900&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Barlow:wght@500;600;700&family=Roboto:wght@400;500;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@500&display=swap');
*, *,
::before, ::before,
::after{ ::after{
@ -13,7 +12,7 @@ body{
--text: 17, 17, 17; --text: 17, 17, 17;
--text-light: 100, 100, 100; --text-light: 100, 100, 100;
--foreground: 255, 255, 255; --foreground: 255, 255, 255;
--background: #efefef; --background: #e8e8e8;
--dark-shade: #dadada; --dark-shade: #dadada;
font-size: 16px; font-size: 16px;
color: rgba(var(--text), 1); color: rgba(var(--text), 1);
@ -25,7 +24,7 @@ body[data-theme='dark']{
--text: 218, 218, 218; --text: 218, 218, 218;
--text-light: 170, 170, 170; --text-light: 170, 170, 170;
--foreground: 20, 20, 20; --foreground: 20, 20, 20;
--background: #111; --background: #0a0a0a;
--dark-shade: #1a1a1a; --dark-shade: #1a1a1a;
} }
input[type=text]::-ms-clear { display: none; width : 0; height: 0; } input[type=text]::-ms-clear { display: none; width : 0; height: 0; }
@ -88,8 +87,7 @@ h3{
letter-spacing: 0.06em; letter-spacing: 0.06em;
} }
.other-font{ .other-font{
font-family: 'Quicksand', sans-serif; font-family: 'Barlow', sans-serif;
font-weight: 500;
} }
.uppercase{ .uppercase{
text-transform: uppercase !important; text-transform: uppercase !important;
@ -230,14 +228,14 @@ ul{
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; h2{
//text-align: center;
h1{
align-self: flex-start;
margin-top: 2rem; margin-top: 2rem;
font-weight: 500; align-self: flex-start;
font-size: 4rem;
letter-spacing: 0.1em;
font-weight: 600;
} }
h3{ h4{
line-height: 1.4em; line-height: 1.4em;
margin: 1rem 0 2rem 0; margin: 1rem 0 2rem 0;
font-weight: 400; font-weight: 400;
@ -245,6 +243,40 @@ ul{
} }
.input{ .input{
border-radius: 0.5rem; border-radius: 0.5rem;
input:valid ~ #suggestions{
opacity: 1;
pointer-events: all;
transform: none;
}
}
label{
position: relative;
}
#suggestions{
opacity: 0;
pointer-events: none;
transform: translateY(-0.5rem);
transition: transform 0.3s, opacity 0.3s;
position: absolute;
top: 100%;
width: 100%;
background: var(--background);
border-radius: 0.5rem;
padding: 0.5rem 0;
max-height: 20vh;
overflow-y: auto;
&:empty{
padding: 0;
}
margin-top: 0.5rem;
}
.suggestion{
padding: 0.6rem 1.5rem 0.6rem 3rem;
opacity: 0.8;
cursor: pointer;
&:hover, &:focus{
opacity: 1;
}
} }
} }
.input{ .input{
@ -257,7 +289,7 @@ ul{
align-items: center; align-items: center;
padding: 0.8rem; padding: 0.8rem;
gap: 1em; gap: 1em;
background: rgba(var(--text), 0.1); background: var(--background);
input{ input{
border: none; border: none;
width: 100%; width: 100%;
@ -268,9 +300,9 @@ ul{
} }
} }
.icon{ .icon{
height: 1.2em; height: 1.2rem;
overflow: visible; overflow: visible;
width: 1.5em; width: 1.2rem;
fill: none; fill: none;
stroke: rgba(var(--text), 1); stroke: rgba(var(--text), 1);
stroke-linecap: round; stroke-linecap: round;
@ -405,7 +437,6 @@ ul{
} }
.page{ .page{
padding: 0 0 1rem 0; padding: 0 0 1rem 0;
animation: fade 0.3s;
h3.heading{ h3.heading{
text-transform: capitalize; text-transform: capitalize;
font-weight: 500; font-weight: 500;

View File

@ -86,17 +86,17 @@
</label> </label>
</header> </header>
<div id="main_search"> <div id="main_search">
<h1 class="other-font">FLO SCOUT</h1> <h2 class="other-font">FLO SCOUT</h2>
<h3>Search for<br>block, transaction, address,<br>token and contract</h3> <h4>Search for<br>block, transaction, address,<br>token and contract</h4>
<label id="primary_search" class="input"> <label id="primary_search" class="input">
<svg class="icon" viewBox="0 0 64 64"> <svg class="icon" viewBox="0 0 64 64">
<title>search icon</title> <title>search icon</title>
<circle cx="25.34" cy="25.34" r="24.84"/> <circle cx="25.34" cy="25.34" r="24.84"/>
<line x1="63.65" y1="63.65" x2="42.91" y2="42.91"/> <line x1="63.65" y1="63.65" x2="42.91" y2="42.91"/>
</svg> </svg>
<input id='main-search-text' type="search" placeholder="Search"> <input id='main_search_field' autocomplete="off" type="search" placeholder="Search" required>
<ul id="suggestions"></ul>
</label> </label>
<div id="suggetions"></div>
</div> </div>
<div id="highlights"> <div id="highlights">
<div class="highlight-item"> <div class="highlight-item">
@ -279,7 +279,7 @@
page.id = "contract_page"; page.id = "contract_page";
page.innerHTML = ` page.innerHTML = `
<div class="status closed">Closed</div> <div class="status closed">Closed</div>
<h2 class="uppercase">${contract}</h2> <h3 class="uppercase">${contract}</h3>
<div class="card"> <div class="card">
<h5 class="label">Contract Type</h5> <h5 class="label">Contract Type</h5>
<h4>${contractType}</h4> <h4>${contractType}</h4>
@ -500,7 +500,7 @@
let addressTxs = await getAddressTxs(field);*/ let addressTxs = await getAddressTxs(field);*/
let [addressInfo, addressBalance, addressTxs] = await Promise.all([getAddressInfo(field), getAddressBalance(field), getAddressTxs(field)]) let [addressInfo, addressBalance, addressTxs] = await Promise.all([getAddressInfo(field), getAddressBalance(field), getAddressTxs(field)])
console.log(addressInfo, addressBalance, addressTxs) console.log(addressInfo, addressBalance, addressTxs)
pageContainer.append(create.addressPage({balance: addressBalance, address: field})) pageContainer.append(create.addressPage({balance: addressBalance, address: -field}))
pageTitle.textContent = 'Address' pageTitle.textContent = 'Address'
loading() loading()
} }
@ -565,7 +565,7 @@
loading(); loading();
// add event listener to input dialog box // add event listener to input dialog box
document.getElementById("main-search-text").addEventListener("keydown", function (e) { document.getElementById("main_search_field").addEventListener("keydown", function (e) {
if (e.key === 'Enter') { //checks whether the pressed key is "Enter" if (e.key === 'Enter') { //checks whether the pressed key is "Enter"
processNavbarSearch(); processNavbarSearch();
} }
@ -596,6 +596,8 @@
} }
}); });
getAllSuggestions()
latestTxs.forEach(tx => { latestTxs.forEach(tx => {
if (tx["type"] == "tokentransfer") if (tx["type"] == "tokentransfer")
frag.append(create.tokenTransferCard(tx)) frag.append(create.tokenTransferCard(tx))
@ -636,7 +638,7 @@
render("homepage"); render("homepage");
history.pushState(appState, null, null); history.pushState(appState, null, null);
document.querySelector("main").addEventListener("click", (e) => { this.addEventListener("click", (e) => {
if (e.target.closest(".address") && prevField !== e.target.textContent) { if (e.target.closest(".address") && prevField !== e.target.textContent) {
render("address_page", e.target.textContent) render("address_page", e.target.textContent)
appState = { appState = {
@ -674,13 +676,43 @@
if (e.target.closest(".tab")) { if (e.target.closest(".tab")) {
showTab(e.target.closest(".tab")); showTab(e.target.closest(".tab"));
} }
if (e.target.closest("#secondary_search")) { if (e.target.closest("#secondary_search_btn")) {
render("homepage"); render("homepage")
document.getElementById("primary_search").click(); //document.getElementById("primary_search").click();
}
if(e.target.closest('.suggestion')){
let searchBox = document.getElementById('main_search_field');
searchBox.value = e.target.textContent;
processNavbarSearch()
} }
}); });
}); });
window.addEventListener('keyup', e => {
if(e.target.closest('.suggestion') && e.key === 'Enter'){
processNavbarSearch()
}
if(e.target.closest('.suggestion') && e.key === 'Tab'){
let searchBox = document.getElementById('main_search_field');
searchBox.value = e.target.textContent;
}
if(e.target.closest('#main_search_field')){
let results = index.search(e.target.value, 25),
entry, childs = suggestions.childNodes,
i = 0, len = results.length;
for (; i < len; i++) {
entry = childs[i];
if (!entry && data[results[i]]) {
suggestions.append(suggestion(data[results[i]]))
}
}
while (childs.length > len) {
suggestions.removeChild(childs[i])
}
suggestions.append(frag)
}
})
let tabMounted = false; let tabMounted = false;
function showTab(tab) { function showTab(tab) {
let targetTab = tab.getAttribute('data-target'), let targetTab = tab.getAttribute('data-target'),
@ -1552,53 +1584,50 @@
//console.log('data entered is noise') //console.log('data entered is noise')
} }
//document.getElementById('main-search-text').value = '';
} }
} }
function processNavbarSearch() { function processNavbarSearch() {
userinput = document.getElementById('main-search-text'); userinput = document.getElementById('main_search_field');
console.log(userinput.value);
if (userinput.value != '') { if (userinput.value != '') {
categoriseText(userinput.value, userinput); categoriseText(userinput.value, userinput);
} }
} }
function runScriptJs() { // function runScriptJs() {
var $cell = $('.card'); // var $cell = $('.card');
//open and close card when clicked on card // //open and close card when clicked on card
$cell.find('.js-expander').click(function () { // $cell.find('.js-expander').click(function () {
var $thisCell = $(this).closest('.card'); // var $thisCell = $(this).closest('.card');
if ($thisCell.hasClass('is-collapsed')) { // if ($thisCell.hasClass('is-collapsed')) {
$cell.not($thisCell).removeClass('is-expanded').addClass('is-collapsed').addClass('is-inactive'); // $cell.not($thisCell).removeClass('is-expanded').addClass('is-collapsed').addClass('is-inactive');
$thisCell.removeClass('is-collapsed').addClass('is-expanded'); // $thisCell.removeClass('is-collapsed').addClass('is-expanded');
if ($cell.not($thisCell).hasClass('is-inactive')) { // if ($cell.not($thisCell).hasClass('is-inactive')) {
//do nothing // //do nothing
} else { // } else {
$cell.not($thisCell).addClass('is-inactive'); // $cell.not($thisCell).addClass('is-inactive');
} // }
} else { // } else {
$thisCell.removeClass('is-expanded').addClass('is-collapsed'); // $thisCell.removeClass('is-expanded').addClass('is-collapsed');
$cell.not($thisCell).removeClass('is-inactive'); // $cell.not($thisCell).removeClass('is-inactive');
} // }
}); // });
//close card when click on cross // //close card when click on cross
$cell.find('.js-collapser').click(function () { // $cell.find('.js-collapser').click(function () {
var $thisCell = $(this).closest('.card'); // var $thisCell = $(this).closest('.card');
$thisCell.removeClass('is-expanded').addClass('is-collapsed'); // $thisCell.removeClass('is-expanded').addClass('is-collapsed');
$cell.not($thisCell).removeClass('is-inactive'); // $cell.not($thisCell).removeClass('is-inactive');
}); // });
} // }
// First load // First load
@ -1606,8 +1635,9 @@
// loading of global variables which contains name of all tokens and smart contracts // loading of global variables which contains name of all tokens and smart contracts
var data = []; function getAllSuggestions(){
fetch(`${window.tokenapiUrl}/api/v1.0/getTokenSmartContractList`) window.data = [];
fetch(`${window.tokenapiUrl}/api/v1.0/getTokenSmartContractList`)
.then(function (response) { .then(function (response) {
return response.json(); return response.json();
}) })
@ -1626,7 +1656,6 @@
data.push(ranchimallflo.smartcontractlist[i]['contractName']); data.push(ranchimallflo.smartcontractlist[i]['contractName']);
ranchimallflo.smartcontractnamelist.push(ranchimallflo.smartcontractlist[i]['contractName']); ranchimallflo.smartcontractnamelist.push(ranchimallflo.smartcontractlist[i]['contractName']);
ranchimallflo.smartcontractnameaddresslist.push(ranchimallflo.smartcontractlist[i]['contractName'] + '-' + ranchimallflo.smartcontractlist[i]['contractAddress']); ranchimallflo.smartcontractnameaddresslist.push(ranchimallflo.smartcontractlist[i]['contractName'] + '-' + ranchimallflo.smartcontractlist[i]['contractAddress']);
} }
for (var i = 0; i < ranchimallflo.tokenlist.length; i++) { for (var i = 0; i < ranchimallflo.tokenlist.length; i++) {
@ -1634,8 +1663,7 @@
data.push(ranchimallflo.tokenlist[i]); data.push(ranchimallflo.tokenlist[i]);
} }
var index = new FlexSearch({ window.index = new FlexSearch({
encode: "advanced", encode: "advanced",
tokenize: "reverse", tokenize: "reverse",
suggest: true suggest: true
@ -1645,76 +1673,16 @@
index.add(i, data[i]); index.add(i, data[i]);
} }
window.suggestion = function(str){
let li = document.createElement('li')
var suggestions = document.getElementById("suggestions"); li.textContent = str
var autocomplete = document.getElementById("autocomplete"); li.tabIndex = 0
var userinput = document.getElementById("userinput"); li.classList.add('suggestion')
return li;
//userinput.addEventListener("input", show_results, true);
//userinput.addEventListener("keyup", accept_autocomplete, true);
//suggestions.addEventListener("click", accept_suggestion, true);
function show_results() {
var value = this.value;
var results = index.search(value, 25);
var entry, childs = suggestions.childNodes;
var i = 0, len = results.length;
for (; i < len; i++) {
entry = childs[i];
if (!entry) {
entry = document.createElement("div");
suggestions.appendChild(entry);
}
entry.textContent = data[results[i]];
}
while (childs.length > len) {
suggestions.removeChild(childs[i])
}
var first_result = data[results[0]];
var match = first_result && first_result.toLowerCase().indexOf(value.toLowerCase());
if (first_result && (match !== -1)) {
autocomplete.value = value + first_result.substring(match + value.length);
autocomplete.current = first_result;
}
else {
autocomplete.value = autocomplete.current = value;
}
}
function accept_autocomplete(event) {
if ((event || window.event).keyCode === 13) {
this.value = autocomplete.value = autocomplete.current;
}
}
function accept_suggestion(event) {
var target = (event || window.event).target;
userinput.value = autocomplete.value = target.textContent;
while (suggestions.lastChild) {
suggestions.removeChild(suggestions.lastChild);
}
return false;
} }
}); });
}
</script> </script>
</body> </body>