Is it possible to stuff an Ajax text search with characters from a link

I have an Ajax search box that drills down and rapidly reduces books found and it works quite well:

I would like to change the “For review add:” 534103" into a link and replace the search box or add to the search string like this:

john burdett 561446

The result would be a unique book found in the table:

When you create a review link, you can use encodeURI to encode the text including spaces and suchlike, so that they properly work when added to the url.
A a link would look something like this: index.html?q=john%20burdett%20561446

On page load you can check if the URL has a query string, and use a decoded version of that with decodeURI to place in the search field, and trigger a search.

I was hoping to stuff the string into the Ajax text search box to eliminate refreshing the page and display the new Ajax search result.

1 Like

Without your code it’ll be difficult to give an exact answer, but the answer is generally something like:

<a class='addtosearch' href='' data-pad='580586'>580586</a>
//Inside AJAX loader... addstuff = the link you're rendering for this result.
addstuff.addEventListener('click',stuffsearch)

//Back in the global scope.
function stuffsearch(e) {
    document.getElementById("mysearchbox").value = document.getElementById("mysearchbox").value + " " + this.target.dataset.pad;
}

(Spitballing, untested)

1 Like

Many thanks, it is now quite late here and hope to try tomorrow.

Many thanks.

Including the link was the easy part but unfortunately unable to modify the current Ajax script. I do not understand the Ajax script because of my very limited JavaScript knowledge:

This works and afraid to touch it :slight_smile:

<script>

var liveSearch = function(inputID) {
	this.input = document.getElementById(inputID);
	if (this.input) {
		this.initialise();
	}
}
liveSearch.prototype = {
	initialise: function()
	{
		this.previousSearch = null;
		this.canSearch = 1;
		this.input.addEventListener("keyup", this.onKeyUp.bind(this));
	},
	onKeyUp : function()
	{
		if (this.canSearch) {
			this.canSearch = 0;
			setTimeout(function(){
				var value = this.input.value.toLowerCase();
				if (value != this.previousSearch) {
					this.doSearch(value);
				}
				this.previousSearch = value;
				this.canSearch = 1;
			}.bind(this), 500);
		}
	},
	doSearch : function(str)
	{
		// START: do your ajax call here ========
	    if (str.length==0)
	    {
	      document.getElementById("livesearch").innerHTML="";
	      return;
	    }
	    if (window.XMLHttpRequest)
	    {
	      // code for IE7+, Firefox, Chrome, Opera, Safari
	      xmlhttp=new XMLHttpRequest();
	    }else{  // code for IE6, IE5
	      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	    }
	    xmlhttp.onreadystatechange=function() {
	      if (xmlhttp.readyState==4 && xmlhttp.status==200)
	      {
	        document.getElementById("livesearch").innerHTML=xmlhttp.responseText;
	      }
	    }
	    xmlhttp.open("GET","incs/_dbResults-GBOOKS.php?q="+str,true);
	    xmlhttp.send();
		// END: do your ajax call here ==============
	}
}

var myLiveSearch = new liveSearch("bufferedInput");

</script>

I modified the link and instead of sending the database table id I added the author and book title to the link then used the following to call the relevant Google Books function:

PHP Stuff

  $getref = '';
  if(isset($_GET['getref'])) :
    define('SHOP', 'd'); // hardcoded SHOP - needs to check URL/domain
    $row['author']  = $_GET['getref'];
    $row['memo']    = $_GET['title'];
    $getref = $gb->fnGetGbooks($gb, (object) $row);
  endif;  

HTML stuff

  <div id="livesearch" class="w88 mga">
      <?php if($getref) : echo $getref; else: ?>
        <p> &nbsp; </p>
        <?php 
            echo '<div class="w88 mga bd1 bgd fg3 p42">';
              echo $gb->Blurb();
              $aTypes = $gb->groupByType($table);
              echo $gb->groupByTypesDisplay($aTypes);
            echo '</div>';  
          endif;  
        ?>
    </div><!-- div id="livesearch" class="w88 mga" -->

It works quite well and pleased to say the page refresh is not noticeable.

Show me incs/_dbResults-GBOOKS.php instead?

I’m surprised this file is required.

File: incs/_dbResults-GBOOKS.php

<?php DECLARE(STRICT_TYPES=1);
  # error_reporting(-1);
  # ini_set('display_errors', '1');

  defined('LOCALHOST')
      ?: 
  define('LOCALHOST', 'localhost'===$_SERVER['SERVER_NAME']);
  define('SHOP', LOCALHOST ? 'g' : substr($_SERVER['SERVER_NAME'], 0,1));
  defined('jj') ?: define('jj', "<br>\n");
  define('SHOWSQL',  FALSE);
  define('LIMITRECS', 22);
  
  $table  = 'booksGekko'; // GOOD
  $table  = 'booksDasa';  // GOOD

  require '../../PASSWORD-LOGIN.php';
  require '../../incs/Class_gbooks.php';
  $gb  = new GB;

  # STANDARDIZE
    $dCOLREF  = 'ref';   
    $dCOLAUTH = 'author';
    $dCOLMEMO = 'memo';
    $dCOLTYPE = 'type';
    $dCOLBAHT = 'baht';
    $dCOLQQQ  = 'qqq';

    $cols = "`$dCOLAUTH`,`$dCOLREF`,`$dCOLMEMO`,`$dCOLBAHT`,`$dCOLTYPE`";

//==========================================================
//   Display Search Results
//==========================================================
  $search  = $_GET['q'] ?? '';
  if( empty($search) ):
    # do nothing
  else:
    $aParams = getParams($search);

    # GET/BUILD QUERY
      $where   = getSqlWhere($aParams, $cols);
      $sqlCnt  = getCombinedCount($table, $where, $cols);
      $sqlRows = getCombinedRows( $table, $where, $cols, LIMITRECS);

    # GET RECORDS
    $link = new mysqli("localhost", uNAME, pWORD, dBASE);

    if(SHOWSQL): 
      echo showSql($sqlCnt); 
    endif;

    $resultCnt  = mysqli_query($link, $sqlCnt);
    if( $resultCnt ) :
      $recNos = $resultCnt->fetch_object();      
      $recNos = intval($recNos -> recNo);
    else:
      $recNos = '';
    endif;

    if(SHOWSQL): 
      echo showSql($sqlRows); 
    endif;
      $resultRows = mysqli_query($link, $sqlRows);

    # RENDER RESULTS
      $maybeShowing = '';
      if($recNos > LIMITRECS):
        $maybeShowing = ' (showing: ' .LIMITRECS .')';
      endif;  
      echo '<p class="fwb fga">'
          .   number_format((float)$recNos)
          .   ' Books found: '
          .     $maybeShowing
          .'</p>'
          ;

        $lines = '';
        $i2    = 1;
        if($resultRows) :
          while($row = $resultRows->fetch_object()) :
            $togBg = ++$i2 % 2 ? 'bgc' : 'bge';
            $gbook = '<i class="tac fsl fg0"> Reviews: </i>';
                   
           # SINGLE                       
            if( 1===$recNos ) :
              $gbook = $gb->fnGetGbooks($gb, $row);
            endif; 
            $lines .= $gb->render($row, $togBg, $search, $gbook) ;
          endwhile; 
        endif;  
        echo $lines;
  endif; # if( empty($search) ):


/* =================================
#  Validate and clean input text
================================== */
function getParams( $params=NULL)
:array
{
  $result = NULL;

  # REMOVE DOUBLE SPACES
    while (strpos($params, '  ') ) {
      $params = str_replace('  ',  ' ', $params);
    }

  # CONVERT TO ARRAY
    $result = explode(' ', $params);
    if( empty($result) ):
      $result[] = $params;
    endif;

  return $result;
}//


/* ============================================
#  Parse User's input input into a string
============================================== */
function getSqlWhere
(
  string $aParams, 
  string $cols
)
:string
{
  $result = '';

  foreach($aParams as $i2 => $param):
    if($i2 > 0):
      $result .= ' AND ';
    endif;
    $result .= "
               CONCAT($cols) 
               LIKE '%$param%'
              ";
  endforeach;

  return $result;
}

/* ===========================================
# Combine two SQL Statements - ORDER IMPORTANT
=========================================== */
function getCombinedCount
(
  string $table, 
  string $sWhere, 
  string $cols
)
:string
{
  $LIMITRECS = LIMITRECS;
  $result = <<< ____TMP
    SELECT COUNT(*) AS `recNo` 
    FROM  `$table` 
    WHERE  $sWhere 
    ;
____TMP;

  return $result;
}

/* ===========================================
# Conbine two SQL Statements - ORDER IMPORTANT
=========================================== */
function getCombinedRows
(
  $table, 
  $sWhere, 
  $cols,
  $limitrecs
)
:string
{
  $result = <<< ____TMP
    SELECT $cols  
    FROM   `$table`  
    WHERE  $sWhere  
    LIMIT  0, $limitrecs;
____TMP;

  return $result;
}

//================================
function showSql($sql)
:string
{
  $result = '';

  $from = [
    'SELECT', 
    'FROM', 
    'WHERE', 
    'LIKE', 
    'AND', 
    'CONCAT(', 
    'LIMIT', 
  ];
  $to   = [
    '<b>SELECT </b> ', 
    '<br><b>FROM </b> ', 
    '<br><b>WHERE </b> ', 
    '<br><b>LIKE </b>', 
    '<br><b>AND </b>', 
    '<br><b>CONCAT<br>(</b> ', 
    '<br><b>LIMIT </b>', 
  ];
  $str  = str_replace($from, $to, $sql);

  $result = ''
        .'<dl class="bgy fg0 fss XXXbgr">'
        .   '<dt class="ooo">SQL:</dt>'
        .   '<dd>' .$str .'</dd>'
        .   '<dd>&nbsp;</dd>'
        .'</dl>';

  return $result;
  }

Well it’s more about ‘where is the easiest place to put this’ rather than required.

the PHP constructs the HTML, and hands a fully formed HTML result to your javascript; all the javascript does is slap it into place. So if we wanted to make changes to the HTML, we’d actually need to be doing it in the PHP.

Looks like the rendering of the result is actually stored in the class… but i think at that point we’re diving too deep into the rabbit hole, so we’ll go around it with Javascript instead.

What does the resulting HTML look like (as in the HTML code, not the screenshot :wink: ) after you’ve put in “john burdett” to the search?

I have the Google Book Reviews working locally using PHP and this is the source when “John Burdett” is entered in the search box locally.

<!DOCTYPE HTML><html lang="en">
<head>
<title> DasaBookCafe Online Search </title>
<meta name="viewport"	    content="width=device-width, initial-scale=1.0">
<meta name="description"  content="DasaBookCafe Live Book Search | books source from XLS spreadsheets">
<meta name="author"       content="John_Betong john.betong@gmail.com">
<link type="image/x-icon" href="/favicon.ico" rel="icon" />
<link type="image/x-icon" href="/favicon.ico" rel="shortcut icon" />
<style>
.btn {}
.fsl {font-size: large;}
.fg0 {color: #000;}
.mh3 {min-height:260px;}
</style>
<link type="text/css" href="https://dasabookcafe.tk/assets/css/style.min.css" media="screen" rel="stylesheet"/>
<style> 
body {background-color: #042;} 
</style>
</head><div class="ooo tac">
	<div class="hhh fll dib jbs"> 
		\$SVG2
	</div>	
	<i class="flr ooo"> Friday, 1st May 2020 </i>

	<h1 class="fll ooo dib">
		<a href="index.php">
  		<span class="fga fgy"> DasaBookCafe Online Search </span>
		</a>
	</h1>
	<br class="clb">
	<b class="flr fss"> ver:042 </b>
	<hr class="clb fg7">
</div><i class="flr">18,332 books,  last checked: 2020-05-01 </i><h4 class="ooo"><a href="?check7update=john_betong"> 
                <i class="fgy">UPDATE</i> 
              </a> 
              &nbsp; &nbsp;
              
<a href="info.php"> 
                <i class="fgy">Info</i> 
              </a> 
              &nbsp; &nbsp;
              
<a href="//jonathanmh.com/searching-google-books-api-php-quickstart/"> 
                <i class="fgy">Tutorial</i> 
              </a> 
              &nbsp; &nbsp;
              
</h4>  <div class="w88 mga">
    <form action="?" method="get">
      <div>
        <br><br>
        <label>Search: &nbsp; </label>
        <input
          id    = "bufferedInput"
          type  = "text"
          size  = "42"
          name  = "search"
          class = "fsn"
          value = ""
        >  
        <br>localhost ONLY ==> booksDasa      </div>
    </form>
  </div><!-- div class="w88 mga" -->
  
    <div id="livesearch" class="w88 mga">
              <p> &nbsp; </p>
        <div class="hhh w42 mga tac bgy fgr p42">
            ¯\_(ツ)_/¯
        </div>  
        <div class="w88 mga bd1 bgd fg3 p42">		<h2 class="ooo">
			A simple and rapid search routine. 
		</h2>

		<ul class="ulv mg1 lh2">
			<li> Ideal for both mobiles and desktops </li>
			<li> Books are now found instantly </li>
      <li> Automatically updated </li>
      <li> Spreadsheet download not required </li>
      <li> Spreadsheet reader not required </li>
		</ul>	
		<hr class="w42 mga">    <dl>
      <dt class="fs2 bd1 p42">
      	Search may contain any or all of the following:
      </dt>
      <dd>
        <dl class="bd1">
  	      <dt class="fwb fg0">
  	      	Title, Author, Reference or one of the following Types: 
  	      </dt>
  	      <dd class="w88 mga p42">
  	      	<i>&nbsp; </i><b>Animals&nbsp; </b><i>Art&nbsp; </i><b>Art/Fashion&nbsp; </b><i>Asia&nbsp; </i><b>Biography&nbsp; </b><i>Buddhism&nbsp; </i><b>Business&nbsp; </b><i>CD&nbsp; </i><b>Children&nbsp; </b><i>Dutch&nbsp; </i><b>Fiction&nbsp; </b><i>Film&nbsp; </i><b>Food&nbsp; </b><i>French&nbsp; </i><b>Gardening&nbsp; </b><i>German&nbsp; </i><b>Graphic Novel&nbsp; </b><i>Health&nbsp; </i><b>History&nbsp; </b><i>Horror&nbsp; </i><b>Humor&nbsp; </b><i>Hungarian&nbsp; </i><b>Indonesian&nbsp; </b><i>Italian&nbsp; </i><b>Language&nbsp; </b><i>Memoir&nbsp; </i><b>Music&nbsp; </b><i>Mystery&nbsp; </i><b>Nature/Environment&nbsp; </b><i>Non-Fiction&nbsp; </i><b>Parenting&nbsp; </b><i>Philosophy&nbsp; </i><b>Photography&nbsp; </b><i>Plays&nbsp; </i><b>Poetry&nbsp; </b><i>Polish&nbsp; </i><b>Politics/Current Affairs&nbsp; </b><i>Portuguese&nbsp; </i><b>Psychology&nbsp; </b><i>Religion&nbsp; </i><b>Romance&nbsp; </b><i>Russian&nbsp; </i><b>Scandinavian&nbsp; </b><i>Sci-Fi/Fantasy&nbsp; </i><b>Science&nbsp; </b><i>Self Help&nbsp; </i><b>Sexuality&nbsp; </b><i>Spanish&nbsp; </i><b>Spirituality&nbsp; </b><i>Sports&nbsp; </i><b>Spy&nbsp; </b><i>Thailand&nbsp; </i><b>Travel&nbsp; </b><i>True Crime&nbsp; </i> &nbsp;
  	      </dd>
  	    </dl>  
      <dd>
    </dl>
 		<h3 class="hhh">
			Also searching for <mark>qqq</mark> returns the latest arrivals.
		</h3></div>    </div><!-- div id="livesearch" class="w88 mga" -->

<p><br></p>
  <p> <br> </p>
  <div class='fix BOT w99 tac bd1 bge fg3'>
    Contact:&nbsp;&nbsp; 
    <a href="http://www.dasabookcafe.com/16467726/mail-order">
      Mail Order
    </a>
  </div>
<script>

var liveSearch = function(inputID) {
	this.input = document.getElementById(inputID);
	if (this.input) {
		this.initialise();
	}
}
liveSearch.prototype = {
	initialise: function()
	{
		this.previousSearch = null;
		this.canSearch = 1;
		this.input.addEventListener("keyup", this.onKeyUp.bind(this));
	},
	onKeyUp : function()
	{
		if (this.canSearch) {
			this.canSearch = 0;
			setTimeout(function(){
				var value = this.input.value.toLowerCase();
				if (value != this.previousSearch) {
					this.doSearch(value);
				}
				this.previousSearch = value;
				this.canSearch = 1;
			}.bind(this), 500);
		}
	},
	doSearch : function(str)
	{
		// START: do your ajax call here ============================================
	    if (str.length==0)
	    {
	      document.getElementById("livesearch").innerHTML="";
	      // document.getElementById("livesearch").style.border="0px";
	      return;
	    }
	    if (window.XMLHttpRequest)
	    {
	      // code for IE7+, Firefox, Chrome, Opera, Safari
	      xmlhttp=new XMLHttpRequest();
	    }else{  // code for IE6, IE5
	      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	    }
	    xmlhttp.onreadystatechange=function() {
	      if (xmlhttp.readyState==4 && xmlhttp.status==200)
	      {
	        document.getElementById("livesearch").innerHTML=xmlhttp.responseText;
	        // document.getElementById("livesearch").style.border="1px solid #A5ACB2";
	      }
	    }
	    xmlhttp.open("GET","incs/_dbResults-GBOOKS.php?q="+str,true);
	    xmlhttp.send();
		// END: do your ajax call here ============================================
	}
}

var myLiveSearch = new liveSearch("bufferedInput");

</script>
</body></html>

Edit:

Please note that there is no reference to “John Burdett” in the script above because the search uses Ajax to find the relevant books in the database table and insert the results into the page.

The old online search routine can be found here:

https://dasabookcafe.tk/

[Off Topic]
I have recently changed to a DigitalOcean Singapore based server and curious to know how quickly the results appear. I would be grateful for feedback and the testing location.
[/off topic]

Right, so here’s what one of your results looks like, for the record, in Chrome:

<dl class="bge rad p42 fss bdr">
        <dd class="flr ooo">
          <i class="fgb fgr fwb"> &nbsp;.&nbsp; </i>
        </dd>

        <dt>
          Title: <b class="fg0"> Bangkok 8 </b>
        </dt>
        <dd>
          by: <i class="fg0"> <b>Burdett, John  </b></i>
        </dd>

        <dt class="tac">
          <span class="fll"> Baht: <b> 120 </b> </span>
          <span class="hhh flr fg0"> Ref: <b>534103 </b></span>
          
          <span class="flr">
            Type: <b class="fgr0"> Mystery </b>
          </span>
        </dt>
        <dd class="clb bd1 tac fwb"> 
          <i class="tac p42 fsl fg0"> 
                        For review add: 
                      </i> :
          <b class="fsl fg0"> 534103 </b> 
        </dd>
      </dl>

So, assuming you can’t/don’t want to control the search results, I would instead phrase it thusly:

//Here is your key line to find where to insert this code.
	        document.getElementById("livesearch").innerHTML=xmlhttp.responseText;
            for (let e of document.getElementsByClassName("clb"))  {
                e.addEventListener('click', function () { stuffsearch(e.getElementsByTagName("b")[0].innerText); });
            }

and then in your global scope:

function stuffsearch(addition) {
  document.getElementById("bufferedInput").value += " "+addition;
}

(as usual, all of this is spitball code, may need refinement.)

[off-topic]Coming from Atlanta, GA, the results were quick enough that they were reactive to my typing, so your server’s response times are certainly adequate. The image below may be informative to you, as I typed the name into your field:

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.