Changing search bar

Watch the video, i want to know if it’s possible. And if it is, is there a way to do it without coding? Just wondering.

Yeah, it is possible to do it. But you are going to need coding.

I made this:

const searchList = ["call of duty", "battlefield", "zelda", "full throttle", "pokemon", "naruto"]

const searchList = ["call of duty", "battlefield", "zelda", "full throttle", "pokemon", "naruto"]

$w.onReady(async () => {
    setInterval(async () => {
        changeText()
        await $w("#iptText").show("slide", showOptions("top", 0))
        await $w("#iptText").hide("slide", showOptions("bottom", 1600))
    }, 2000)
})

function randomIntFromInterval(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min)
}
function changeText() {
    let index = randomIntFromInterval(0, 5)
    $w("#iptText").text = searchList[index]
}
function showOptions(dir, del) {
    return {
        delay: del,
        duration: 200,
        direction: dir
    }
}
https://bwprado.wixsite.com/my-site-1 

Thanks, but here’s the problem…

Also sometimes it shows the same thing 6 times.

It doesn’t give search results either so it’s hard to know what you are searching for…
But thanks!

@w11 it is not a complete solution, it was just to show the animation. A complete solution would be WAY longer and require WAY more time to be done.

@bwprado Okay! I’ll look up some tutorials on how to finish it. Thanks so much!

Look at the size it got:

const searchList = [
    { name: "call of duty", _id: "aihauiah" },
    { name: "battlefield", _id: "aiuhauiah" },
    { name: "zelda", _id: "987128u" },
    { name: "full throttle", _id: "192871987" },
    { name:"pokemon", _id: "128937198273" },
    { name: "naruto", _id: "019247ujq" },
]

let interval = setInterval(() => showAnimation(), 2000)
$w.onReady(() => {
    $w("#inputSearch").onFocus(() => stopAnimation())
    $w("#iptText").onClick(event => {
        let search = event.target.text
        $w("#inputSearch").placeholder = search
        stopAnimation()
    })
    $w("#inputSearch").onInput(({ target }) => {
        stopAnimation()
        let search = target.value
        if (search.length > 0) {
            let timeout = setTimeout(() => {
                let results = filterArray(search)
                if (results.length > 0) {
                    fillRepeater(results)
                    $w('#boxResults').expand()
                }
            }, 100)
        } else {
            $w('#boxResults').collapse()
        }
    })
})

function stopAnimation() {
    clearInterval(interval)
    $w("#iptText").hide()
}
async function showAnimation() {
    changeText()
    await $w("#iptText").show("slide", showOptions("top", 0))
    await $w("#iptText").hide("slide", showOptions("bottom", 1600))
}

function randomIntFromInterval(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min)
}

function changeText() {
    let index = randomIntFromInterval(0, 5)
    $w("#iptText").text = searchList[index].name
}
function showOptions(dir, del) {
    return {
        direction: dir,
        delay: del,
        duration: 200,
    }
}
function filterArray(search) {
    console.log(search)
    let result = searchList.filter(item => item.name.includes(search))
    return result
}
function fillRepeater(data) {
    $w("#repeater").data = data
    $w("#repeater").onItemReady(($item, iData) => {
        $item('#textRpt').text = iData.name
    })
}

Check it out!
Work In Progress

Hi All! So I built a little custom search for my colection. It’s a site I built to work on my skills for such things, the page is here: https://bluntchbuilders.wixsite.com/seaapts/sea-apts-apartments

The search that is there works. The problem I am having now is that I want it to be better. From my collections I want a visitor to be able to select one of the locations (city) and then they can either see all of the returns OR select bedrooms and filter down just from the returned cities. Right now and for some time each filed return it own results and they are not working together in a drill down fashion.

An answer would be ok, pointing me to the right resource to learn how to do this not only for my test but as a coding skill would be much better. I suck at JS, just saying.

Here is my code. I’ve been plunking away at this on and off for about a year, that includes teaching myself enough python to build some bots to scrape the data up for me.

I would also like to have the text search include the stations data column in the future.

Thanks in advance.

// start search features ===================================================
import wixData from ‘wix-data’ ;
import wixWindow from ‘wix-window’ ;
$w . onReady ( function () {
});

wixData . query ( “SampleApts” )
. count ()
. then (( num ) => {
$w ( ‘#TextCount’ ). text = ‘’ + num ;
$w ( “#dataset1” ). next ();
})

let debounceTimer ;
export function searchBar_keyPress ( event ) {
$w ( “#loadingGif” ). show ();
if ( debounceTimer ) {
clearTimeout ( debounceTimer );
debounceTimer = undefined ;
}

debounceTimer = setTimeout (() => {
$w ( “#dataset1” ). setFilter ( wixData . filter (). contains ( “title” , $w ( ‘#searchBar’ ). value )
. or ( wixData . filter (). contains ( “location” , $w ( ‘#searchBar’ ). value )
. or ( wixData . filter (). contains ( “price” , $w ( ‘#searchBar’ ). value )
. or ( wixData . filter (). contains ( “nearByStation” , $w ( ‘#searchBar’ ). value )))))
//.or(wixData.filter().eq(“nearByStation”, $w(‘#searchBar’).value)))))

. then (() => { 
    count (); 

})

}, 200 );
}

$w . onReady ( function () {
}) ;

export function searchRoomsDD_change ( event ) {
$w ( “#loadingGif” ). show ();
if ( debounceTimer ) {
clearTimeout ( debounceTimer );
debounceTimer = undefined ;
}

let searchRooms = $w ( “#searchRoomsDD” ). value ;
$w ( “#dataset1” ). setFilter ( wixData . filter (). contains ( “title” , searchRooms ))
. then (() => {
count ();
})
}

$w . onReady ( function () {
}) ;

export function searchLocationsDD_change ( event ) {
$w ( “#loadingGif” ). show ();
if ( debounceTimer ) {
clearTimeout ( debounceTimer );
debounceTimer = undefined ;
}

let searchLocations = $w ( “#searchLocationsDD” ). value ;
$w ( “#dataset1” ). setFilter ( wixData . filter (). contains ( “location” , searchLocations ))
. then (() => {
count ();
})
}

function count () {

let  total  =  $w ( '#dataset1' ). getTotalCount (); 

if  ( total  >  1 ) {    
$w ( '#textResults' ). text  =  ` ${ total }  results were found.` ;  $w ( "#loadingGif" ). hide (); 
$w ( '#textResults' ). show ();    
}    

if  ( total  ===  1 ) { 
$w ( '#textResults' ). text  =  ` ${ total }  result was found.` ;  $w ( "#loadingGif" ). hide (); 
$w ( '#textResults' ). show (); 
}    

if  ( total  ===  0 ) { 
$w ( '#textResults' ). text  =  "No result found!" ;  $w ( "#loadingGif" ). hide (); 
$w ( '#textResults' ). show ();    
}  

}

Hello @greenhomeboy99 , there are some things that you need to do to clean up your code.

First remove all but one $w.onReady() method, you just need a single one to be called upon the page is loaded.

Second you need to define what kind of search you want, because if you want all input fields to filter using .or() as you defined, than you will need ONE function to deal with this side effect.

For example, this would be a function that filters based on pairs (field and value) and every argument is a new .or() method being applied.

async function filterDataset(...args) { //You need to feed this with arrays of pairs
    let arrayOfFunctions = []
    args.forEach(([field, value]) => arrayOfFunctions.push(wixData.filter().contains(field, value)))
    const filter = await arrayOfFunctions.reduceRight((result, f) => f.or(result))
    $w('#dataset1').setFilter(filter) //Change to your Dataset ID
}

Example of usage would be:

$w.onReady(() => {
    $w('#dataset1').onReady(() => {
        $w('#btnFilter').onClick(async () => {
            await filterDataset(['rooms', '1 Bedroom']) //You can put any number or pairs in here.
        })
    })
})

And you can optimize you code in the count() function, for example using a variable to change the verb. Something like this:

function count() {
    let total = $w('#dataset1').getTotalCount()
    $w('#loadingGif').hide()
    $w('#textResults').show()
    if (total === 0) return $w('#textResults').text = 'No result found!'
    let verb = total > 1 ? 'were' : 'was'
    $w('#textResults').text = `${total} results ${verb} found.`
}

Let me know if this helps you and anyway?

@bwprado Thank you. I will be going over this tonight and I’ll get back to you. From my skimming over it it makes sense. My skill level with JS is really poor, thank you for your help. I’m learning one nugget at a time.

@greenhomeboy99 That’s the way to go. Take your time and let me know if it worked!

Hey! So I went through it and removed the extra onReady and did a couple of other small things and that really sped up the page loads including using your optimized count code block. I’m struggling with the .or() call, partially because Room Type is just pulled from the title, there is no dedicated arg and value pairs in the db at this time.

I’m going to keep working on it over the next couple of evenings and get back to you with another progress update.

Thanks you

@greenhomeboy99 So, the pairs I mentioned are described as dataset field key and the search value .

Maybe I wasn’t that clear. So let’s illustrate an example. Let’s suppose you want to find a “Studio” in “Bangkok” .

First you have to define the first pair, that relates to “Studio” . This “Studio” value is stored in a column that has a field key as the name, I think yours is “title” , so you just use the pair as:

['title','Studio']

So the search will try to find inside the “title” column, the value “Studio”.

The second pair would be the location pair. “Bangkok” must be stored in a column (field key) inside your dataset, that if I’m not wrong is called “location”. So the second pair would be:

['location','Bangkok']

Ok, so you just need to fill the function that I created with the defined pairs. Like this:

await filterDataset(['title','Studio'], ['location','Bangkok'])

This function starts from right to left, and it will try to find an item in the “location” field that contains the value “Bangkok” or an item in the “title” field that contains the value “Studio”.

Remember that the value can be retrieved from your inputs (dropdowns or inputs), just store the values in a variable and feed the function. Like this:

['location', dropdownValue]

I hope I was a little bit clearer.