How to create a searchbar for my website

Responder
Avatar de Usuario
ricardo arraes
Mensajes: 87
Registered for: 3 years 5 months
Brazil

How to create a searchbar for my website

Mensaje por ricardo arraes »

Hey everybody!

a searchban is probably one of the most important widgets for a website, that's where the user will search for all the information it wants...

So it's important to learn how to create a good searchbar as well...

But what I mean with "good searchbar"? what does a searchbar requires to be a good one?

1- the simplest as possible. All the user gotta do is type some information and get what he is looking for...
2- the less freezing, the better. Async requests are the way to avoid freezing the UI, so I suggest you to take a look at this topic I created, it will be extremely worth it:
viewtopic.php?f=5&p=831#p831
3- the less requests, the better. We gotta prevent the application to search for EVERY SINGLE THING the user types... if the user typing a word, there's no need to send a request for every single letter of that word.

Before we start to create a simple example...
I suggest you, once again, to take a look at this topic:
viewtopic.php?f=5&p=831#p831

It will help you to understand the async requests that are crucial to get where we want in this example.
So let's go...

STEP 1: create our searchbar

let's create our searchbar inside our navbar.

this is a very basic searchbar, I'm using some custom-made classes to style it but basically you can create it the way you desire...

But I want you to pay attention at:

1- the #searchbar input element. that's where the user will insert the some data
2- the #ModalSearch element. that's where the result of our async search (async request) will be displayed.

Código: Seleccionar todo


    <nav class="navbar navbar-expand-lg navbar-light bg-white p-2">
      <div class="container">

        <a class="navbar-brand" href="{{Route('root')}}">
          <img src="/vfatec/img/logo/icone_medio.png">
        </a>

      </div>      
    </nav>
    
    <div class="navbar navbar-boxed navbar-expand-md navbar-dark mb-3 navbar-fixed-top">
      <div class="container">
        
        
        <div class="dropdown flex-grow-1 flex-md-grow-0">
		<div class="flex-grow-1 position-relative">          
                       <form class="navbar-form" action="{{ Route( 'pesquisa' ) }}" method="get">
                              <div class="input-group">              
                                	<input type="search" class="form-control form-control-lg" name="param" placeholder="Search" id="searchbar">         
                                	<div class="input-group-append">
		                                  <button class="btn btn-outline-border btn-lg">
                                    			<i class="fe fe-search"></i>
                                  		</button>
                                	</div>                  
                             </div>
                      </form>
                      <div class="dropdown-menu dropdown-menu-lg w-100" id="ModalSearch" data-parent="#searchbar">                              
                              <div class="card card-lg shadow-border dropdown-item" data-toggle="collapse">                
                                    <div class="col-12" id="searchResult">
                                        <div class="loader mx-auto"></div>
                                    </div>                                
                              </div>
                      </div>
	      </div>  
    	</div>
     </div>  
  </div>

STEP 2: creating our routes

now, let's create the routes of our application...

the root route, basically is the one that will redirect us to the home page

the search route is the one that will act as a webservice processing and retrieving data

Código: Seleccionar todo


	DEFINE APP oApp TITLE 'vfatec';
		ON INIT Config() ;
		CREDENTIALS 'teste' COOKIE 'teste'

		DEFINE ROUTE 'root'  			URL '/' 	 		 	CONTROLLER 'home@controller.prg' 			METHOD 'GET'  OF oApp

		DEFINE ROUTE 'search'		URL 'search'		CONTROLLER 'search@ws.prg'			METHOD 'GET' OF oApp

	//Inicialização da aplicação
	INIT APP oApp 
	
	
STEP 3: creating the controller.prg (navigation)

this controller is responsible for the navigation

Código: Seleccionar todo

CLASS controller

    METHOD New(oController) CONSTRUCTOR

    
    METHOD home(oController)  
        

ENDCLASS

METHOD New(oController) CLASS controller

RETURN Self

METHOD home(oController) CLASS controller
    oController:View("/home.view")
RETURN NIL

STEP 4: creating the ws.prg (webservice)

this controller will act as a webservice, it will recieve the async requests that we are about to send, process e retrieve data right back to the application

Código: Seleccionar todo

CLASS WS

    METHOD New(oController) CONSTRUCTOR
    
    METHOD search(oController)

    
ENDCLASS

METHOD New(oController) CLASS WS


RETURN Self

METHOD search(oController) CLASS WS

    LOCAL oTable,hResponse:={=>},aParam:={},hData:={=>}

    hData:=oController:oRequest:GetAll()
    
    Aadd(aParam,hData['param'])
    
    cQuery := "SELECT * FROM content WHERE field1 LIKE '%PARAM01%' "
       
    oTable  :=  App():oBD:QueryJson(cQuery,aParam)
    
	oController:oResponse:SendJson(oTable)

RETURN NIL

STEP 5: creating the script

now, let's get back to our view from the step one and add this script.

the first event listener inside this script is responsible for closing the modal (where the results from the search will be located) when we cancel the searching process.

the keyup function is responsible for identifying when the user is typing. In this case, if the user takes more than 0,5secs to type, the application will send a request to search for the application that the user typed.

notice that there are two variables that are extremely important for the whole process to work properly: pesqseq and pesqsend.
these variables are in charge of granting that the results from the right sequence of requests will be displayed to the user. We are talking about async requests, so it's important to understand that if these variables didn't exist, the results from a previous request could be displayed as the final result to the user...


Código: Seleccionar todo


<script>

      var npag=0

      var pesqseq=0

        document.getElementById("searchbar").addEventListener("search", function(event) {
          var div = document.querySelector('#searchResult');
          $("#ModalSearch").hide()
          div.innerHTML='<div class="loader mx-auto"></div>';

        });

        

        $("#searchbar").keyup(function(e){
                    
          var div = document.querySelector('#searchResult');
          var pesqsend;

          pesqseq++;
          pesqsend=pesqseq;
          
          if($("#searchbar").val().length >= 1 )
          {
            $("#ModalSearch").show()
          }
          else
          {
            if($("#searchbar").val().length==0)
            {
              $("#ModalSearch").hide()
            }
            
          }  
          
          div.innerHTML='<div class="loader mx-auto"></div>';
          
          setTimeout(function(){ 

            if(pesqseq==pesqsend && $("#searchbar").val().length > 0)            
            {
          
              $.ajax({
          
                  type: "GET",
                  url: "http://localhost/teste/search?param="+$("#searchbar").val(),              

              }).done(function(data,status) {
                                        
                if(pesqseq==pesqsend)
                {
                  var prodhtml='<div class="card">'+
                                  '<div class="card-body">'+
                                    '<div class="form-group-overflow">'

                  for(var i = 0; i < data.length; i++) 
                  {
                      var obj = data[i];                                  
                      
                      prodhtml+=  '<div class="custom-control custom-control-text m-2">'+                                      
                                      '<a class="custom-control-label" href="#">'+obj.field1+'</a>'+
                                  '</div>'
                          
                          
                      
                  }
                  prodhtml+='</div>'+
                        '</div>'+
                      '</div>'
                  
                  div.innerHTML=prodhtml
                }

              }).fail(function(xhr, status, error) {


              });

            }
            
          },500);

        });
    </script>

*There are some security improvements to be made, but I tried to make this example as simple as possible for you guys to understand the whole idea :)

Hope it helps you!

Video of an example:

The work always comes before the belief

Responder