Banner of None

Creating A Real Website with PHP object oriented - part 7 - a search input and autocomplete


Category: php

Date: September 2020
Views: 1.62K


in this 7th part of this tutorial series about PHP object oriented programming, we will add a very important part of any website, an input field to search the website, in this particular website the input search field will help us search the wallpapers and we will add an autocomplete component using jquery-ui

Viewing one wallpaper:

First we add these 3 lines of code to allow us to be able to view a single wallpaper as we have mentiend in the previews articles , the one() method from our ViewWallpapers class will be like this:


protected function one(){
    $w = $this->db->one($this->id);
    echo '<div class="row">';
    echo '<img style="max-width:100%;height:auto;" src="/images/Wallpapers/'.$w["url"].'" >';
    echo '</div>';
}


We will create another method to handle viewing the items, this method will be called once in the all() method and once again in the search() method. I should note that I changed the css class "row" to "wrow" so that it dose not interfere with the bootstrap class "row" so change it in the css code from the previous article



private function __viewitems($items){
    echo '<div class="wrow">';
	foreach ($items as $item) {
	    echo '<div class="item">';
		echo '    <a href="/Wallpapers/Full/'.$item["id"].'" >';
		echo '        <img src="/images/Thumbnails/'.$item["url"].'" >';
		echo '        <div class="content">';
		echo '            <p>'.$item["x"].'x'.$item["y"].'</p>';
		echo '        </Div>';
		echo '    </a>';
		echo '</div>';
	}
    echo '</div>';
}


Now the one() and search() methods in our ViewWallpapers class will be like:


protected function all(){
    $items = $this->db->all($this->first,$this->perPage);
	$this->__viewitems($items);
}
protected function search(){
    $items = $this->db->search($this->searchquery,$this->first,$this->perPage);
	$this->__viewitems($items);
}


Getting Bootstrap, jquery and jquery-ui:

First we get the bootstrap css and js files from https://www.bootstrapcdn.com/. At the time of writing this article it was on version v4.5.2 and the files were the following :



<-- jQuery cdn : -->

<script
      src="https://code.jquery.com/jquery-3.5.1.min.js"
      integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
      crossorigin="anonymous"></script>

<-- bootstrap cdn : -->
<link rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
      integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"
      crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"
	   integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV"
	   crossorigin="anonymous"></script>


In order to use the autocomplete, we need to download this jquery-ui zip file , extract it and use the minified versions in both jquery-ui.min.js and jquery-ui.min.css files. add them to our website project folders and include them in the index.php file.


Creating the input search element:



<div class="globalsearch">
    <input class="form-control" type="text" placeholder="search wallpapers" >
    <div id="tagsuggestions"></div>
</div>


The javascript autocomplete code:


$(document).ready(function() {
    $( ".globalsearch" ).on('click','input',function() {
	$(this).autocomplete({
	  appendTo: "#tagsuggestions",
	  source: function( request, response ) {
	    $.ajax( {
	      type: "POST",
	      url: "/sources/includes/autcomplete.inc.php",
	      dataType: "json",
	      data: {
		term: request.term
	      },
	      success: function( data ) {
		response( data );
	      },
	      error: function(xhr){
		  alert(xhr.responseText);
	      }
	    } );
	  },
	  minLength: 3,
	  select: function( event, ui ) {
	      window.location.href = "/Wallpapers/" + encodeURIComponent(ui.item.value).replace('%20','+') + "/1" ;
	  }
	} );
    } );
});


The javascript code above is triggered when we click on an input child of the container with class "globalsearch" that we created with the 4 html lines above. it then performs an ajax request with the method "POST" to a php file that we called autocomplete.inc.php. when the data is received from this php file, and upon a selection by the user. the webpage is redirected to a URL with the selected value. of course our website is prepared to handle that search value and serve the Wallpapers in question.


The autcomplete.inc.php file:


<?php
spl_autoload_register('myautoloader');
function myautoloader($classname){
    $fname = "../../sources/classes/$classname.class.php";
    if(file_exists($fname)){
	include_once $fname;
	return true;
    }
    return false;
}

$w = new Wallpapers();
$tags = $w->autocomplete($_POST["term"]);
$data = array();
foreach ($tags as $t) {
    $data[] = $t['tagname'];
}
echo json_encode($data);
?>


The first function is an autoloader for our classes. the second part is a call to autocomplete() method from our Wallpapers class. then we format the recieved data from the database in order to convert it to json data for the jquery-ui script. and this method is:



public function autocomplete($tag){
    $query = "select tagname from $this->tagtable where tagname like :t or text like :t limit 50";
    $sql = $this->pdo->prepare($query);
    $sql->bindValue(':t',(string) "%$tag%",PDO::PARAM_STR);
    $sql->execute();
    return $sql->fetchAll();
}


Finally the css for our input and jquery-ui elements:


.globalsearch {
  justify-content: center;
  vertical-align: middle;
  width:70%;
  margin:  0 auto;
  margin-bottom: 5px;
}

.globalsearch input {
    width: 100%;
    height: 40px;
    background:#205041;
    padding-left: 20px;
    border:1px solid white;
    border-radius: 25px;
    font-size: 1.2em;
}

#tagsuggestions {
    position: relative;
}

.ui-autocomplete {
    position: absolute;
	max-width: 100%;
    max-height: 200px;
	overflow-y: scroll;
	overflow-x: hidden;
    text-align: left;
}

.ui-autocomplete a {
    font-size: 14px;
    padding-left: 7px;
}


The following video shows all this in details:



1.62K views

Previous Article

0 Comments, latest

No comments.