Hi
I realized my input text #autocomplete menu, but it miss something.
I would like to #highlight an item of a #repeater, for example changing the color of the text.
I found some way, like here, the Dan's solution : https://www.wix.com/corvid/forum/community-discussion/highlight-repeater-row-onclick
but you have to click an item!
I would like to choose an item via keyboard, that's using #arrowUp and #arrowDown keys.
But the handlers of the containers don't provide onFocus method, only onClick. There's a way ? thanks in advance
Mauro
Hey guys - nice work on this! I hope you don't mind, but I started out with your ideas, had a few beers, and voila! Here's an example of a Repeater Dropdown with Keyboard Navigation. I had been meaning to do something like this for a while, and this forum thread provided the necessary inspiration. Thanks! 🍻
Hi guys, I love the implementation that you have made here! I really would love it if you could help me adopt the code a little to my particular situation - I would like to have the autocomplete but that it would read it from multiple columns of the database - for example I have a columns with Title, Location, Description and when someone starts typing then it will search all three fields and provide suggestions... Thus far i have tried the following:
in the onReady section i added:
case "Enter": $w('#searchBarLB').value = $w('#rptDropdown').data[currIndex].location; $w('#searchBarLB').value = $w('#rptDropdown').data[currIndex].title; $w('#searchBarLB').value = $w('#rptDropdown').data[currIndex].description;
then in the functions:
export function rptDropdown_itemReady($item, itemData, index) { $item('#name').text = itemData.location; $item('#name1').text = itemData.description; $item('#name2').text = itemData.title; if (index === currIndex) { $item("#rptBox").style.backgroundColor = HL_COLOR; } else { $item("#rptBox").style.backgroundColor = REG_COLOR; } $item('#container1').onClick(() => { $w('#searchBarLB').value = itemData.location; $w('#searchBarLB').value = itemData.description; $w('#searchBarLB').value = itemData.title; $w('#rptDropdown').collapse(); }); } function refresh_repeater() { $w("#rptDropdown").forEachItem(($item, itemData, index) => { $item('#name').text = itemData.location; $item('#name1').text = itemData.description; $item('#name2').text = itemData.title; if (index === currIndex) { $item("#rptBox").style.backgroundColor = HL_COLOR; } else { $item("#rptBox").style.backgroundColor = REG_COLOR; } $item('#container1').onClick(() => { $w('#searchBarLB').value = itemData.location $w('#searchBarLB').value = itemData.description $w('#searchBarLB').value = itemData.title; $w('#rptDropdown').collapse(); }); });
so it only searches by locations and I am not sure what I am doing wrong. Also I would like to know if the the autocomplete output from searching three different columns in the database can go into the same one field ('name') or I have to have 3 fields ("name" "name1" "name2")...
all help would be so much appreciated..
CANCEL:
«...the problem is in the end of code: // the variable: container = '#container3'...»
neither this, the results are random! It works only in preview mode, not on published site. MISTERY !!
the problem is in the end of code:
// the variable: container = '#container3' $item('#container3').onClick(() => { //works! input.value = itemData[campo]; repeater.collapse(); }); $item(container).onClick(() => { //doesn't work input.value = itemData[campo]; repeater.collapse(); });
So the keyboard works, the click mouse not works, the touch id on iPhone works.
Hi @Yisrael (Wix)
unbelievable, let's tray to connect to:
https://costieraslow.wixsite.com/testquery/autocomplete3
via PC and then via smartphone :O
In the first case all work fine,
in the 2d case when you click a name, you get the _id value in the input_box in despite of the name.
What's happen ?
Hi guys,
I just set up the routine for you, in order to have a simple way to manage more and more repeater and using collections or array of elements without datasets and invoking the same function like the following:
menu_input (input1,repeater1,container1,voce1,sfondo1,collezione1,campo1)
where you can set the repeater and the collections or the array.
Collezione1 could be the name of the collection you pass and campo1 the name of the field, or can be the name of the simple array of elements, or the name of a array of records and campo is the name of the property.
The eg:
https://costieraslow.wixsite.com/testquery/autocomplete3
Here the code in the home page where you use the three types of data:
import {menu_input} from 'public/menu_input.js' $w.onReady( function () { // set three repeaters let input1 =$w('#input1') let repeater1 =$w('#repeater1') let container1 = '#container1' let voce1 = '#text1' let sfondo1 = '#box1' let input2 =$w('#input2') let repeater2 =$w('#repeater2') let container2 = '#container2' let voce2 = '#text2' let sfondo2 = '#box2' let input3 =$w('#input3') let repeater3 =$w('#repeater3') let container3 = '#container3' let voce3 = '#text3' let sfondo3 = '#box3' // set the input collections let collezione1 = 'Producers' let campo1 = 'nominativo' let collezione2 = ["Giulio Dubbioso", "Francesco Genatiempo", "Mauro Avino", "Alfonso Tortora", "Mario Persico", "Alessandra Balduccini", "Elena De Marco", "Giuseppe Russo"] let collezione3 = [ {"_id":"01","valore":"Giulio Dubbioso"}, {"_id":"02","valore":"Alfonso Tortora"}, {"_id":"03","valore":"Mauro Avino"} ] let campo3 = "valore" // invoke the same function for the different repeaters menu_input (input1,repeater1,container1,voce1,sfondo1,collezione1,campo1) menu_input (input2,repeater2,container2,voce2,sfondo2,collezione2) menu_input (input3,repeater3,container3,voce3,sfondo3,collezione3,campo3) });
Here the function in menu_input.js in Public:
import wixData from 'wix-data'; /************************************************** */ /******* FUNZIONE MENU SEARCH & NAVIGATOR ARRAY ****/ /************************************************** */ // This project was inspired by a recent forum discussion, Highlight an item Repeater - autocomplete menu, // between amazing users: Mauro Vento Avyno and David - skeptisch.net // and the principal contributor the Master Yisrael(Wix) export async function menu_input (input,repeater,container,voce,sfondo,collezione, campo) { let options={suppressAuth:true,suppressHokks:true} const HL_COLOR = "rgba(190,190,250)"; const REG_COLOR = "rgba(222,222,222)"; let listSize; let currIndex = -1; // verifica se 'collezione' è il riferimento a un dbase e se esiste if (typeof(collezione)==="string" && wixData.query(collezione)) { console.log("Esiste la collezione nel database2: ",collezione) await wixData.query(collezione,campo,options) .find() .then( (res) => { ArraY = res.items}) } else if // se 'collezione' invece è un Array semplice, crea ArraY del tipo (_id, valore) (Array.isArray(collezione) && typeof(collezione[0])==="string") { var ArraY=[], i=0, ARRAY=[]; // predispone ArraY collezione.forEach( (el) => { ArraY.push( { [campo]:el,"_id":String(i) }); ++i }) console.log("'collezione' è un array semplice di valori",collezione) } else if ( Array.isArray(collezione) && typeof(collezione[0])==="object" ) { console.log("È un oggetto: ", collezione) var ArraY = collezione, i=0, ARRAY=[]; } else {console.log("'collezione' non è ne un riferimento ad un database, ne un array semplice, ne una collezione di record/items")} // chiude il menu al passaggio del mouse input.onMouseIn(() => {repeater.collapse()}) // chiude il menu all'uscita da input input.onBlur( () => {repeater.collapse()}) // controlla ogni singolo input da tastiera e popola il menu input.onKeyPress((event) => { console.log(event.key) setTimeout(() => { if (input.value.length === 0) { currIndex = -1; repeater.collapse() } else { switch (event.key) { case "Tab": repeater.collapse() break; case "ArrowLeft": case "ArrowUp": if (currIndex > 0) { currIndex -= 1; repeater.forEachItem(($item, itemData, index) => { if (index === currIndex) { $item(sfondo).style.backgroundColor = HL_COLOR; } else { $item(sfondo).style.backgroundColor = REG_COLOR; } }); } break; case "ArrowRight": case "ArrowDown": if (currIndex < listSize - 1) { currIndex += 1; repeater.forEachItem(($item, itemData, index) => { if (index === currIndex) { $item(sfondo).style.backgroundColor = HL_COLOR; } else { $item(sfondo).style.backgroundColor = REG_COLOR; } }); } break; case "Escape": //input.value = ''; //currIndex = -1; repeater.collapse() break; // case "Enter": try { console.log(repeater.data) if (currIndex === -1) {input.value = repeater.data[0][campo];} else {input.value = repeater.data[currIndex][campo];} console.log("IL dato esiste") repeater.collapse() } catch (err) { console.log("Il dato non esiste", err)} break; // popola il repeater con i risultati della ricerca default: ARRAY=[]; currIndex = -1; // passa in rassegna gli elementi 'valore' dell'Array // e seleziona quelli contenenti una parte di stringa da 'input' ArraY.forEach( (el) => { if( el[campo].toLowerCase().includes(input.value.toLowerCase()) ) {ARRAY.push(el) } } ) console.log("ARRAY = ",ARRAY) repeater.data = []; repeater.data = ARRAY; listSize = ARRAY.length; repeater.expand(); break; } } }, 50) // chiude SetTimeOut }); // chiude onKeyPress event // popola le voci del menu e ne controlla l'aspetto repeater.onItemReady( ($item, itemData, index) => { $item(voce).text = itemData[campo]; console.log(itemData[campo], index) if (index === currIndex) { $item(sfondo).style.backgroundColor = HL_COLOR; } else { $item(sfondo).style.backgroundColor = REG_COLOR; } $item(container).onClick(() => { input.value = itemData[campo]; repeater.collapse(); }); }) }
Hi @Yisrael (Wix) and @David - skeptisch.net ,
an unexpected issue, a Chrome's menu overlap our repeater and disable the arrow keys !
Here really I don't know which Saint to invoke, have you some advices ? Thx in advance
Mauro
Thanks again guys. Someday we'll get together, and WD-40 our brains.
PS: @Yisrael (Wix) could you add a simple example about in the repeater item reference API please ? thxXX :)
Nooooway @Yisrael (Wix) it'snt fair, you want win easy. You have to leave something to solve to us 😃😁 Thanks so much, a artisanal lemon beer for you, and @David - skeptisch.net of course, the next time you'll be in Sorrento in Italy 🤝🤗
I'll see if I can get it working, because it would be a cool feature.
Up
Here we need an help, please :)
Haven't tried or tested this myself, so it might need some tweaking but this is what comes to mind:
(might need to await default in arrowDown case)
import wixData from 'wix-data'; let totalRes; let currIndex = 0; export function repeater1_itemReady($item, itemData, index) { //MOUSE $item('#container1').onClick(()=>{ $w('#input1').value = itemData.nominativo; $w('#repeater1').collapse() } ); //KEYBOARD let con = $item('#container1'); $w('#input1').onKeyPress(()=>{ $w('#repeater1').show(); $w('#repeater1').expand(); setTimeout(() => { if ($w('#input1').value === "") {$w('#repeater1').collapse();} switch (event.key) { case "Enter": $w('#input1').value = $w('#repeater1').data[0].nominativo; $w('#repeater1').collapse(); break; case "arrowUp": currIndex -= 1; //not sure if repeater index starts at 0 or 1, so you should console.log() it to be sure if (index > 0) { index !== currIndex ? con.style.backgroundColor = '#414141' : con.style.backgroundColor = 'white'; } break; case "arrowDown": currIndex += 1; if (index < totalRes) { index !== currIndex ? con.style.backgroundColor = '#414141' : con.style.backgroundColor = 'white'; } break; case "Escape": $w('#repeater1').collapse(); break; default: wixData.query("Producers") .contains("nominativo", $w('#input1').value) .ascending("nominativo") .find() .then( (res) => { $w('#repeater1').data = res.items; totalRes = res.items.length; $w('#repeater1').show(); } ); break; } }, 500) } ); }
Up
This is the test site, you can use Enter to autocomplete or use click mouse: https://costieraslow.wixsite.com/testquery/autocomplete then follow what I set up and the code:
database
- a 'Producers' collection
in the main page - a 'input1' text input box - a 'dataset1' linked to the collection - a 'repeater1' linked to the dataset and hide on load
code
// HOME PAGE import wixData from 'wix-data'; $w.onReady(function () { }); export function input1_keyPress_1(event) { $w('#repeater1').show(); $w('#repeater1').expand(); // let $item = $w.at(event.context) // console.log($item("#box1")) setTimeout(() => { if ($w('#input1').value === "") {$w('#repeater1').collapse()} switch (event.key) { case "Enter": $w('#input1').value = $w('#repeater1').data[0].nominativo $w('#repeater1').collapse() break; case "arrowUp": //........ break; case "arrowDown": //........ break; case "Escape": $w('#repeater1').collapse() break; default: wixData.query("Producers") .contains("nominativo", $w('#input1').value ) .ascending("nominativo") .find() .then( (res) => { $w('#repeater1').data = res.items; $w('#repeater1').show(); }) break; } }, 500) } //_____________________________________________ // MOUSE export function container1_click(event) { let $item = $w.at(event.context); let clickedItemData = $item("#dataset1").getCurrentItem(); $w('#input1').value=clickedItemData.nominativo; $w('#repeater1').collapse() ; }