Search results while typing

Hello,

is there a way to get search results while typing ? Following this tutorial: “https://getkirby.com/docs/solutions/search” you only get result after submitting the form.

Thanks in adavnce

To accomplished that you would have to implement an AJAX-based solution.

do you maybe have more information on how to achieve this or a hint or a tutorial ? i found this video but it did not work to connect this with the kirby search (https://youtu.be/AofECml9pQU). THX

You can use a route that takes the search query and returns a JSON object with the results.

This route can then be called by your frontend code.

Thank you i will look into that and let you know if that worked :slight_smile:

This will not work. The get() method in the controller code fetches the query from the URL as soon as the search form has been submitted stands here: https://getkirby.com/docs/solutions/search. So the url of the route’s pattern cannot match before it was submitted.

No, you just call the URL in your Javascript, which listens for a keyup event.

Edit:

Basically, it works like this:

  1. You create the search form without the submit button.
  2. The user types in the search field and your client-side script listens for key events in the input field
  3. The ajax call in your script calls the route for the search query
  4. The route handles the query and returns the results as JSON object
  5. The script takes the JSON objects and shows the result in the browser
1 Like

Hello again,

i think i have a problem on part 3 and 4 of your list. Maybe my thinking is too complicated. i followed the search tutorial and then i tried to follow your list. now i have this script:

`

` ` `

and this in my config:

c::set('routes', array( array( 'pattern' => array('search'), 'action' => function() { return response::json(array( get('q') )); } ) ));

So what happens is that the site now redirects to the json file and i get whatever i put as a search in the url (e.g. if url is: “localhost/kirby_cms/search?q=example” I get the the json “[example]”). That’s how it is supposed to be right?

But how do i save the json into another url that does not overwrite my site so the script can read the json from the url?

thx a lot for the support

The url in your ajax call must point to the url in your route, i.e. ‘search’.

Then in your route, all you do is to return the search string as json, which does not make sense; your route needs to return the search results, that is, you need the logic here from the search controller.

If you’re searching a large site, you can also index the searchable fields and their respective URLs, and put these (as JSON) in a cached file, which can be loaded with the page or when the user starts using the search field. This way, the server doesn’t need to handle repetitive requests, and results will show up immediately.

The downside to this is that you need to know when to re-index the site - you could create a cron job, or, have the pages re-indexed after pages are updated in the panel. The latter, depending on the amount of content or how complex your indexing function is, may make the panel feel sluggish.

Or you could use an external search service, which will even correct typos in the search query for you. There’s something coming to Kirby soon, just saying. :wink:

1 Like

Until we have the option to use a external search service :wink: , I’ve tested the following very basic setup and this works:

The route

My route listens to a string added to search/ {{ search string }}

array(
        'pattern' => 'search/(:all)',
        'action' => function ($uri) {
            $query   = $uri;
            $results = site()->search($query)->toJson();

            return response::json(array(
                $results
            ));
        }
    )

It returns the results from the query as a JSON Object so I can deal with it within my client-side script later.

My javascript (jQuery, in my case)

The javascript handles the input from the user and displays the results from the query in the html. I’ve commented it, so I hope it’s useful :slight_smile:


var input                       = jQuery('.js-search');
var searchResultsContainer      = jQuery('.ajax-container');

    input.on('keyup', function(e) {

        // I check if the length in the input is more than 3 characters
        if(input.val().length > 3) {
            $.ajax({
                // build the url
                url: "/search/"+input.val()+"",
                context: jQuery('.ajax-container')
            }).done(function(data) {

                // convert the data to objects, console.log this to see 
                // how the object is build and which keys you can use
                var results = JSON.parse(data);

                // Flush the container
                searchResultsContainer.html('');

                // loop trough the objects in results and display them
                jQuery.each(results, function(index, object) {

                    var string = '
                        <div class="content-box">
                            <a href="'+object.url+'" class="full-link"></a>
                            <time class="content-box__datetime">'+object.content.date+'</time>
                            <h2 class="content-box__title">'+object.content.title+'</h2>
                            <p>'+object.content.intro+'</p>
                        </div>
                    ';   

                    // Append the results to the container
                    searchResultsContainer.append(string);        
                });
            });
        }else {
            // If there are less than 3 or 0 characters in the input, flush the container
            searchResultsContainer.html('');
        }
    });

Hope it helps! You can even alter the search() method to search within specific pages or fields: https://getkirby.com/docs/solutions/search

2 Likes

Hi again,

i had time now to your solution, but i could not get it to work. I put your route in the config file and put your javascript my search.php. Unfortunately I get an error on the $.ajax line. I am not that fit in ajax, maybe I just act a little bit too stupid.

but thx for helping everyone !

What does your config file look like with the route? It looks like it is not properly registered.

Hi that is my config file:

i am running kirby on a localhost, but that can’t be the problem right ?

thx

Could you please post your code as code blocks (withing three backticks at the beginning and the end of a block on a separate line) in the future? Makes it a lot easier to test bits of code and to correct it where necessary than with images. Thanks a lot.

Hello, just thought @lukasbestle only needs a quick look on this. But you are of course right, thx for reminding:

c::set('routes', array(
	array(
        'pattern' => 'search/(:all)',
        'action' => function ($uri) {
            $query   = $uri;
            $results = site()->search($query)->toJson();
            return response::json(array(
                $results
            ));
        }
    )
));

The route looks all right to me, you can easily test that by entering something into the browser’s address bar.

…meaning: What do you get when you go to http://localhost/search/mysearchrequest in the browser?

1 Like

wow, thx a lot. it works. I work with a subpage ( localhost/kirby_cms/ ) and forgot to put “kirby_cms/” before “search” in the directory of the ajax and the config. I realized this because of @lukasbestle post of my url. Thx a lot.

1 Like