[Tutorial] Google Suggest Search

TFlan

I could change this in my User CP.
Reaction score
64
Ever wonder how Google's Suggest Search worked? Well here's a small tutorial on how to implement their code to your website!

Examples:
- Facebook's Message Composer
- Google's Suggest Search

Image Example:
suggestions_img.bmp


The Codes:
For this tutorial I will be using this code for a PM system, much like Facebook's Message Composer. You can easily customize this code for your own personal use.

suggestions_php.php
PHP:
<?php
$db_user = "*****";
$db_pass = "*****";
$db_serv = "*****";
$db_data = "*****";
$db_conn = mysql_connect($db_serv, $db_user, $db_pass);
mysql_select_db($db_data);

$sql = "SELECT username FROM users";
$result = mysql_query($sql);
$num = mysql_num_rows($result);
for($i=0;$i<$num;$i++):
	$username = mysql_result($result, $i, 'username');
	$members .= $username."|";
endfor;

$string = $members;
$rawkeywords = preg_split('/\s*[\s+\.|\?|,|(|)|\-+|\'|\"|=|;|×|\$|\/|:|{|}]\s*/i', $string);
$keywords = array_unique ( $rawkeywords );
sort($keywords);
echo 'var customarray = new Array( ';
foreach($keywords as $value):
	echo "'$value', ";
endforeach;
echo "'' );";
mysql_close($db_conn);
?>

The info on suggestions_php.php:
The first section, lines 1 - 7, are used to connect to a mysql database. I stared out the information for security reasons.
$db_user = MySQL login Username
$db_pass = MySQL login Password
$db_serv = MySQL server path
$db_data = MySQL Database name

The second section, lines 8 - 15, is used to grab the suggestions.
PHP:
$sql = "SELECT username FROM users";
Selects all usernames from the table 'users'.
PHP:
$result = mysql_query($sql);
$num = mysql_num_rows($result);
Submits the query, and gets the amount of rows that is in the result.
PHP:
for($i=0;$i<$num;$i++):
	$username = mysql_result($result, $i, 'username');
	$members .= $username."|";
endfor;
Starts a loop to grab each and every username and saves in the variable $members with a delimiter of '|'

The third section, lines 16 and up, makes the variable $members into an array by using '|', the delimiter, to separate the members names into separate fields, with this code here:
PHP:
$string = $members;
$rawkeywords = preg_split('/\s*[\s+\.|\?|,|(|)|\-+|\'|\"|=|;|×|\$|\/|:|{|}]\s*/i', $string);
It then checks to see if their are a duplicate with this line of code:
PHP:
$keywords = array_unique ($rawkeywords);
Now it echos the php array into a javascript array with this code here:
PHP:
echo 'var customarray = new Array( ';
foreach($keywords as $value):
	echo "'$value', ";
endforeach;
echo "'' );";
Then closes the mysql connection with "mysql_close($db_conn);"

suggestions_js.js
Code:
function getCaretEnd(obj){
if(typeof obj.selectionEnd!="undefined"){
return obj.selectionEnd;
}else if(document.selection&&document.selection.createRange){
var M=document.selection.createRange();
var Lp=obj.createTextRange();
Lp.setEndPoint("EndToEnd",M);
var rb=Lp.text.length;
if(rb>obj.value.length){
return-1;
}
return rb;
}
}
function getCaretStart(obj){
if(typeof obj.selectionStart!="undefined"){
return obj.selectionStart;
}else if(document.selection&&document.selection.createRange){
var M=document.selection.createRange();
var Lp=obj.createTextRange();
Lp.setEndPoint("EndToStart",M);
var rb=Lp.text.length;
if(rb>obj.value.length){
return-1;
}
return rb;
}
}
function setCaret(obj,l){
obj.focus();
if(obj.setSelectionRange){
obj.setSelectionRange(l,l);
}else if(obj.createTextRange){
m=obj.createTextRange();
m.moveStart('character',l);
m.collapse();
m.select();
}
}
String.prototype.addslashes=function(){
return this.replace(/(["\\\.\|\[\]\^\*\+\?\$\(\)])/g,'\\$1');
}
String.prototype.trim=function(){
return this.replace(/^\s*(\S*(\s+\S+)*)\s*$/,"$1");
};
function actb(obj,evt,ca){
var actb_timeOut=10000;
var actb_lim=15;
var actb_firstText=false;
var actb_mouse=true;
var actb_delimiter=new Array(';',' ');
var actb_bgColor='#f9f4e6';
var actb_textColor='#342a1f';
var actb_hColor='#ecc076';
var actb_fFamily='Georgia';
var actb_fSize='0.9em';
var actb_hStyle='text-decoration:underline;font-weight:bold;';
var actb_delimwords=new Array();
var actb_cdelimword=0;
var actb_delimchar=new Array();
var actb_keywords=new Array();
var actb_display=false;
var actb_pos=0;
var actb_total=0;
var actb_curr=null;
var actb_rangeu=0;
var actb_ranged=0;
var actb_bool=new Array();
var actb_pre=0;
var actb_toid;
var actb_tomake=false;
var actb_getpre="";
var actb_mouse_on_list=true;
var actb_kwcount=0;
var actb_caretmove=false;
actb_keywords=ca;
actb_curr=obj;
var oldkeydownhandler=document.onkeydown;
var oldblurhandler=obj.onblur;
var oldkeypresshandler=obj.onkeypress;
document.onkeydown=actb_checkkey;
obj.onblur=actb_clear;
obj.onkeypress=actb_keypress;
function actb_clear(evt){
if(!evt)evt=event;
document.onkeydown=oldkeydownhandler;
actb_curr.onblur=oldblurhandler;
actb_curr.onkeypress=oldkeypresshandler;
actb_removedisp();
}
function actb_parse(n){
if(actb_delimiter.length>0){
var t=actb_delimwords[actb_cdelimword].trim().addslashes();
var plen=actb_delimwords[actb_cdelimword].trim().length;
}else{
var t=actb_curr.value.addslashes();
var plen=actb_curr.value.length;
}
var tobuild='';
var i;
if(actb_firstText){
var re=new RegExp("^"+t,"i");
}else{
var re=new RegExp(t,"i");
}
var p=n.search(re);
for(i=0;i<p;i++){
tobuild+=n.substr(i,1);
}
tobuild+="<font style='"+(actb_hStyle)+"'>"
for(i=p;i<plen+p;i++){
tobuild+=n.substr(i,1);
}
tobuild+="</font>";
for(i=plen+p;i<n.length;i++){
tobuild+=n.substr(i,1);
}
return tobuild;
}
function curTop(){
actb_toreturn=0;
obj=actb_curr;
while(obj){
actb_toreturn+=obj.offsetTop;
obj=obj.offsetParent;
}
return actb_toreturn;
}
function curLeft(){
actb_toreturn=0;
obj=actb_curr;
while(obj){
actb_toreturn+=obj.offsetLeft;
obj=obj.offsetParent;
}
return actb_toreturn;
}
function actb_generate(){
if(document.getElementById('tat_table')){actb_display=false;document.body.removeChild(document.getElementById('tat_table'));}
if(actb_kwcount==0){
actb_display=false;
return;
}
a=document.createElement('table');
a.cellSpacing='1px';
a.cellPadding='2px';
a.style.position='absolute';
a.style.top=eval(curTop(actb_curr) + actb_curr.offsetHeight + 20) + "px";
a.style.left=curLeft(actb_curr) + "px";
a.style.backgroundColor=actb_bgColor;
a.style.border='1px solid #342a1f';
a.id='tat_table';
document.body.appendChild(a);
var i;
var first=true;
var j=1;
if(actb_mouse){
a.onmouseout=actb_table_unfocus;
a.onmouseover=actb_table_focus;
}
var counter=0;
for(i=0;i<actb_keywords.length;i++){
if(actb_bool[i]){
counter++;
r=a.insertRow(-1);
if(first&&!actb_tomake){
r.style.backgroundColor=actb_hColor;
first=false;
actb_pos=counter;
}else if(actb_pre==i){
r.style.backgroundColor=actb_hColor;
first=false;
actb_pos=counter;
}else{
r.style.backgroundColor=actb_bgColor;
}
r.id='tat_tr'+(j);
c=r.insertCell(-1);
c.style.color=actb_textColor;
c.style.fontFamily=actb_fFamily;
c.style.fontSize=actb_fSize;
c.innerHTML=actb_parse(actb_keywords[i]);
c.id='tat_td'+(j);
c.setAttribute('pos',j);
if(actb_mouse){
c.onclick=actb_mouseclick;
c.onmouseover=actb_table_highlight;
}
j++;
}
if(j-1==actb_lim&&j<actb_total){
r=a.insertRow(-1);
r.style.backgroundColor=actb_bgColor;
c=r.insertCell(-1);
c.style.color=actb_textColor;
c.style.fontFamily='arial narrow';
c.style.fontSize=actb_fSize;
c.align='center';
c.innerHTML='\\/';
if(actb_mouse){
c.onclick=actb_mouse_down;
}
break;
}
}
actb_rangeu=1;
actb_ranged=j-1;
actb_display=true;
if(actb_pos<=0)actb_pos=1;
}
function actb_remake(){
document.body.removeChild(document.getElementById('tat_table'));
a=document.createElement('table');
a.cellSpacing='1px';
a.cellPadding='2px';
a.style.position='absolute';
a.style.top=eval(curTop()+actb_curr.offsetHeight)+"px";
a.style.left=curLeft()+"px";
a.style.backgroundColor=actb_bgColor;
a.id='tat_table';
if(actb_mouse){
a.onmouseout=actb_table_unfocus;
a.onmouseover=actb_table_focus;
}
document.body.appendChild(a);
var i;
var first=true;
var j=1;
if(actb_rangeu>1){
r=a.insertRow(-1);
r.style.backgroundColor=actb_bgColor;
c=r.insertCell(-1);
c.style.color=actb_textColor;
c.style.fontFamily='arial narrow';
c.style.fontSize=actb_fSize;
c.align='center';
c.innerHTML='/\\';
if(actb_mouse){
c.onclick=actb_mouse_up;
}
}
for(i=0;i<actb_keywords.length;i++){
if(actb_bool[i]){
if(j>=actb_rangeu&&j<=actb_ranged){
r=a.insertRow(-1);
r.style.backgroundColor=actb_bgColor;
r.id='tat_tr'+(j);
c=r.insertCell(-1);
c.style.color=actb_textColor;
c.style.fontFamily=actb_fFamily;
c.style.fontSize=actb_fSize;
c.innerHTML=actb_parse(actb_keywords[i]);
c.id='tat_td'+(j);
c.setAttribute('pos',j);
if(actb_mouse){
c.onclick=actb_mouseclick;
c.onmouseover=actb_table_highlight;
}
j++;
}else{
j++;
}
}
if(j>actb_ranged)break;
}
if(j-1<actb_total){
r=a.insertRow(-1);
r.style.backgroundColor=actb_bgColor;
c=r.insertCell(-1);
c.style.color=actb_textColor;
c.style.fontFamily='arial narrow';
c.style.fontSize=actb_fSize;
c.align='center';
c.innerHTML='\\/';
if(actb_mouse){
c.onclick=actb_mouse_down;
}
}
}
function actb_goup(){
if(!actb_display)return;
if(actb_pos==1)return;
document.getElementById('tat_tr'+actb_pos).style.backgroundColor=actb_bgColor;
actb_pos--;
if(actb_pos<actb_rangeu)actb_moveup();
document.getElementById('tat_tr'+actb_pos).style.backgroundColor=actb_hColor;
if(actb_toid)clearTimeout(actb_toid);
if(actb_timeOut>0)actb_toid=setTimeout(function(){actb_mouse_on_list=0;actb_removedisp();},actb_timeOut);
}
function actb_godown(){
if(!actb_display)return;
if(actb_pos==actb_total)return;
document.getElementById('tat_tr'+actb_pos).style.backgroundColor=actb_bgColor;
actb_pos++;
if(actb_pos>actb_ranged)actb_movedown();
document.getElementById('tat_tr'+actb_pos).style.backgroundColor=actb_hColor;
if(actb_toid)clearTimeout(actb_toid);
if(actb_timeOut>0)actb_toid=setTimeout(function(){actb_mouse_on_list=0;actb_removedisp();},actb_timeOut);
}
function actb_movedown(){
actb_rangeu++;
actb_ranged++;
actb_remake();
}
function actb_moveup(){
actb_rangeu--;
actb_ranged--;
actb_remake();
}
function actb_mouse_down(){
document.getElementById('tat_tr'+actb_pos).style.backgroundColor=actb_bgColor;
actb_pos++;
actb_movedown();
document.getElementById('tat_tr'+actb_pos).style.backgroundColor=actb_hColor;
actb_curr.focus();
actb_moue_on_list=0;
if(actb_toid)clearTimeout(actb_toid);
if(actb_timeOut>0)actb_toid=setTimeout(function(){actb_mouse_on_list=0;actb_removedisp();},actb_timeOut);
}
function actb_mouse_up(evt){
if(!evt)evt=event;
if(evt.stopPropagation){
evt.stopPropagation();
}else{
evt.cancelBubble=true;
}
document.getElementById('tat_tr'+actb_pos).style.backgroundColor=actb_bgColor;
actb_pos--;
actb_moveup();
document.getElementById('tat_tr'+actb_pos).style.backgroundColor=actb_hColor;
actb_curr.focus();
actb_moue_on_list=0;
if(actb_toid)clearTimeout(actb_toid);
if(actb_timeOut>0)actb_toid=setTimeout(function(){actb_mouse_on_list=0;actb_removedisp();},actb_timeOut);
}
function actb_mouseclick(evt){
if(!evt)evt=event;
if(!actb_display)return;
actb_mouse_on_list=0;
actb_pos=this.getAttribute('pos');
actb_penter();
}
function actb_table_focus(){
actb_mouse_on_list=1;
}
function actb_table_unfocus(){
actb_mouse_on_list=0;
if(actb_toid)clearTimeout(actb_toid);
if(actb_timeOut>0)actb_toid=setTimeout(function(){actb_mouse_on_list=0;actb_removedisp();},actb_timeOut);
}
function actb_table_highlight(){
actb_mouse_on_list=1;
document.getElementById('tat_tr'+actb_pos).style.backgroundColor=actb_bgColor;
actb_pos=this.getAttribute('pos');
while(actb_pos<actb_rangeu)actb_moveup();
while(actb_pos>actb_ranged)actb_mousedown();
document.getElementById('tat_tr'+actb_pos).style.backgroundColor=actb_hColor;
if(actb_toid)clearTimeout(actb_toid);
if(actb_timeOut>0)actb_toid=setTimeout(function(){actb_mouse_on_list=0;actb_removedisp();},actb_timeOut);
}
function actb_insertword(a){
if(actb_delimiter.length>0){
str='';
l=0;
for(i=0;i<actb_delimwords.length;i++){
if(actb_cdelimword==i){
str+=a;
l=str.length;
}else{
str+=actb_delimwords[i];
}
if(i!=actb_delimwords.length-1){
str+=actb_delimchar[i];
}
}
actb_curr.value=str;
setCaret(actb_curr,l);
}else{
actb_curr.value=a;
}
actb_mouse_on_list=0;
actb_removedisp();
}
function actb_penter(){
if(!actb_display)return;
actb_display=false;
var word='';
var c=0;
for(var i=0;i<=actb_keywords.length;i++){
if(actb_bool[i])c++;
if(c==actb_pos){
word=actb_keywords[i];
break;
}
}
actb_insertword(word);
}
function actb_removedisp(){
if(!actb_mouse_on_list){
actb_display=false;
if(document.getElementById('tat_table')){document.body.removeChild(document.getElementById('tat_table'));}
if(actb_toid)clearTimeout(actb_toid);
}
}
function actb_keypress(){
return!actb_caretmove;
}
function actb_checkkey(evt){
if(!evt)evt=event;
a=evt.keyCode;
caret_pos_start=getCaretStart(actb_curr);
actb_caretmove=0;
switch(a){
case 38:
actb_goup();
actb_caretmove=1;
return false;
break;
case 40:
actb_godown();
actb_caretmove=1;
return false;
break;
case 13:case 9:
actb_penter();
actb_caretmove=1;
return false;
break;
default:
setTimeout(function(){actb_tocomplete(a)},50);
break;
}
}
function actb_tocomplete(kc){
if(kc==38||kc==40||kc==13)return;
var i;
if(actb_display){
var word=0;
var c=0;
for(var i=0;i<=actb_keywords.length;i++){
if(actb_bool[i])c++;
if(c==actb_pos){
word=i;
break;
}
}
actb_pre=word;
}else{actb_pre=-1};
if(actb_curr.value==''){
actb_mouse_on_list=0;
actb_removedisp();
return;
}
if(actb_delimiter.length>0){
caret_pos_start=getCaretStart(actb_curr);
caret_pos_end=getCaretEnd(actb_curr);
delim_split='';
for(i=0;i<actb_delimiter.length;i++){
delim_split+=actb_delimiter[i];
}
delim_split=delim_split.addslashes();
delim_split_rx=new RegExp("(["+delim_split+"])");
c=0;
actb_delimwords=new Array();
actb_delimwords[0]='';
for(i=0,j=actb_curr.value.length;i<actb_curr.value.length;i++,j--){
if(actb_curr.value.substr(i,j).search(delim_split_rx)==0){
ma=actb_curr.value.substr(i,j).match(delim_split_rx);
actb_delimchar[c]=ma[1];
c++;
actb_delimwords[c]='';
}else{
actb_delimwords[c]+=actb_curr.value.charAt(i);
}
}
var l=0;
actb_cdelimword=-1;
for(i=0;i<actb_delimwords.length;i++){
if(caret_pos_end>=l&&caret_pos_end<=l+actb_delimwords[i].length){
actb_cdelimword=i;
}
l+=actb_delimwords[i].length+1;
}
var t=actb_delimwords[actb_cdelimword].addslashes().trim();
}else{
var t=actb_curr.value.addslashes();
}
if(actb_firstText){
var re=new RegExp("^"+t,"i");
}else{
var re=new RegExp(t,"i");
}
actb_total=0;
actb_tomake=false;
actb_kwcount=0;
for(i=0;i<actb_keywords.length;i++){
actb_bool[i]=false;
if(re.test(actb_keywords[i])){
actb_total++;
actb_bool[i]=true;
actb_kwcount++;
if(actb_pre==i)actb_tomake=true;
}
}
if(actb_toid)clearTimeout(actb_toid);
if(actb_timeOut>0)actb_toid=setTimeout(function(){actb_mouse_on_list=0;actb_removedisp();},actb_timeOut);
actb_generate();
}
}

In this file are the styles. From lines 47 (var actb_timeOut=10000; ) down to line 75 (var actb_caretmove=false; ) are variables that you can set which will change font family, font size, bgcolor, font color, and one variable where you can put any CSS in (var actb_hStyle='text-decoration:underline;font-weight:bold;'; ).

The Installation:
Step 1) Use suggestions_js.js from above.
Step 2) Create suggestions_php.php from the code above. Customize it to your liking.
Step 3) Upload those 2 files to your server.
Step 4) Add this code to the page where you want to put your suggestions box:

Code:
<script language="javascript" type="text/javascript" src="PATH HERE/suggestions_js"></script>
<script language="javascript" type="text/javascript" src="PATH HERE/suggestions_php.php"></script>

Step 5) Replace your input box with this html code:

Code:
<input id="search" name="search" size="20" onfocus="actb(this,event,customarray);" autocomplete="off" />

Step 6) Your done!

Original Coder
 

mase

____ ___ ____ __
Reaction score
154
Very nice. I'm gonna try and learn AJAX soon.
 

TFlan

I could change this in my User CP.
Reaction score
64
Ajax isn't really a 'language', its just an extension of Javascript. Very simple to understand and code.

Here is a nice tutorial of it, simple and down to the point.
 

mase

____ ___ ____ __
Reaction score
154
Well I already know a tiny amount of AJAX. It is the same as loadVars in Flash. I just don't fully understand AJAX or loadVars yet.
 

TFlan

I could change this in my User CP.
Reaction score
64
bump for the masses to see.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    Actually I was just playing with having some kind of mention of the food forum and recipes on the main page to test and see if it would engage some of those people to post something. It is just weird to get so much traffic and no engagement
  • The Helper The Helper:
    So what it really is me trying to implement some kind of better site navigation not change the whole theme of the site
  • Varine Varine:
    How can you tell the difference between real traffic and indexing or AI generation bots?
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top