Jump to content

Archived

This topic is now archived and is closed to further replies.

billy_111

AJAX, JS, PHP Predictive Text

Recommended Posts

Hi,

 

I was wondering if anyone can please assist me. I am trying to find an example of a method which uses a predictive text/suggestions technique on input text boxes.. I want to pull data out of a database and show the results in the form of predictive text..

 

Can i do this? Please can someone offer some guidance..

 

Thanks

Regards

Billy

Share this post


Link to post
Share on other sites

Yes it's possible. I'm assuming you mean something like with Google or on Facebook. There are a bunch of tutorials out there, most making use of a JavaScript Framework such as jQuery.

 

Here's a couple:

Using jQuery

http://papermashup.com/jquery-php-ajax-autosuggest/

 

Using script.aculo.us

http://www.talkphp.com/advanced-php-programming/1588-auto-suggest-using-php-mysql-ajax.html

Share this post


Link to post
Share on other sites

Hey,

 

I am trying to follow the first link you sent, seemed quite easy but it seems like it's not working for me, maybe because i'm doing something wrong?

 

This is the page:

 

http://www.prima.cse.salford.ac.uk:8080/~ibrarhussain/view/test.php

 

If you start typing in the big search box the suggestions box appears in the wrong place, and it should be returning some results but it's not.

 

This is my autoSuggest.php file:

 

   $db = new mysqli('***', '***' ,'****', '****');

if(!$db) {

	echo 'Could not connect to the database.';
} else {

	if(isset($_POST['queryString'])) {
		$queryString = $db->real_escape_string($_POST['queryString']);

		if(strlen($queryString) >0) {

			$query = $db->query("SELECT CPtitle FROM ConfPaper WHERE CPtitle LIKE '$queryString%' LIMIT 10");
			if($query) {
			echo '<ul>';
				while ($result = $query ->fetch_object()) {
         			echo '<li onClick="fill(\''.addslashes($result->CPtitle).'\');">'.$result->CPtitle.'</li>';
         		}
			echo '</ul>';

			} else {
				echo 'OOPS we had a problem ';
			}
		} else {
			// do nothing
		}
	} else {
		echo 'There should be no direct access to this script!';
	}
}

 

Can you see a problem with what i am doing?

 

Thanks

Share this post


Link to post
Share on other sites

With the positioning, not sure, would need to see your CSS. I'm guessing its because you're using absolute positioning on it without having a container div that is relative positioned. Perhaps place your suggestion div inside another, and have this containers div position set to relative. As for no results...

 

Make your LIKE in your query like this:

LIKE '%$queryString%'

Share this post


Link to post
Share on other sites

hmm have had a play around with the css, but i can fix that later..

 

I don't think the predictive is working however as it should..

 

It's just always returning blank but there are fields in the database that match the search criteria..

 

 

Share this post


Link to post
Share on other sites

Do some general debugging, use die in a place where you think the script is getting to. Then if it shows whatever you echo in die, move it further down until you can safely see where the script is failing.

Share this post


Link to post
Share on other sites

School boy error!  ;D

 

I spelt a variable wrong!

 

Thanks again, the die() method worked.

 

By the way, where is this set:

 

if(isset($_POST['queryString'])) {

 

Where do we get the $_POST['queryString' from? I can't see it in the form, yet the code still works? This is the form:

 

                     <form id="form" action="#">
                        <div id="suggest">
                          <input type="text" size="25" value="" id="documents" onkeyup="suggest(this.value);" onblur="fill();" class="searchtext"/>
                          <div class="suggestionsBox" id="suggestions" style="display: none;"> <img src="<?=VIEW?>/images/arrow.png" style="position: relative; top: -12px; left: 2px;" alt="upArrow" />
                            <div class="suggestionList" id="suggestionsList">   </div>
                          </div>
                          <input type="submit" name="searchsubmit" class="searchbutton" value=""/>
                       </div>
                    </form>

 

:D

Share this post


Link to post
Share on other sites

You'll have some jQuery code, and the jQuery code will run an AJAX request.

 

If you look at your jQuery code and the AJAX request, you should see queryString there somewhere.

Share this post


Link to post
Share on other sites

Hmm well that's where i'm confused.. This m my jQuery in doctype:

 

    <script type="text/javascript">
    function suggest(inputString){
                    if(inputString.length == 0) {
                            $('#suggestions').fadeOut();
                    } else {
                    $('#documents').addClass('load');
                            [b]$.post("includes/autosuggest.php", {queryString: ""+inputString+""}, function(data){[/b]
                                    if(data.length >0) {
                                            $('#suggestions').fadeIn();
                                            $('#suggestionsList').html(data);
                                            $('#documents').removeClass('load');
                                    }
                            });
                    }
            }

            function fill(thisValue) {
                    $('#documents').val(thisValue);
                    setTimeout("$('#suggestions').fadeOut();", 600);
            }
    </script>

 

See bold line. Quick question, if i wanted to add a different method to a different page, i know how i'd change the php code i can add another IF statement, but how can i add another method within the javascript at the top that also checks for lets say "QuerystringAuthor"..

 

Share this post


Link to post
Share on other sites

Not sure if this is correct, but would i need to add another instance of this:

 

[b]                          $.post("includes/autosuggest.php", {queryStringAuthor: ""+inputString+""}, function(data){[/b]
                                    if(data.length >0) {
                                            $('#suggestions').fadeIn();
                                            $('#suggestionsList').html(data);
                                            $('#documents').removeClass('load');
                                    }
                            });

Share this post


Link to post
Share on other sites

See, there is queryString.

 

No, I take it on your input box you have an onkeyup event handler or something of the sort. Now, what you can do is in that handler you'll be calling the JavaScript function 'suggest' which you have created. The first parameter is probably set to this.value. Give it a second parameter, and make it something like default. So it might look like this:

 

<input type="text" name="search" onkeyup="javascript: suggest(this.value, 'default');" />

 

Then your suggest function needs to accept the second parameter.

 

function suggest(inputString, inputFor){

 

I've called it inputFor, you can name it something else though. Then further down, in your $.post AJAX request, you set another post parameter:

 

$.post("includes/autosuggest.php",
   {
      queryString: inputString,
      queryFor: inputFor
   }, function(data){

 

Now, in your PHP script, you can use $_POST['queryFor'] to see what they are querying for. You can then use the same suggest function on other things, except instead of passing in default pass in author. Then in your PHP script you'd just use an if statement to see what they are querying for, like so:

 

if($_POST['queryFor'] == "author"){
   // do a mysql query to search for authors
}else{
   // this is the default, you could add more elseifs though.
}

 

I hope that makes some sense.

Share this post


Link to post
Share on other sites

Ok thanks,

 

I have only got around to doing this now, this is what i have:

 

autosuggest.php

   $db = new mysqli('localhost', '****' ,'****', '****');
if(!$db) {
	echo 'Could not connect to the database.';
} else {
	if($_POST['queryFor'] == "author"){
		$queryString = $db->real_escape_string($_POST['queryString']);

		if(strlen($queryString) >0) {
			$query = $db->query("SELECT CPtitle FROM ConfPaper WHERE CPtitle LIKE '%$queryString%' LIMIT 10");
			if($query) {
			echo '<ul>';
				while ($result = $query ->fetch_object()) {
         			echo '<li onClick="fill(\''.addslashes($result->CPtitle).'\');">'.$result->CPtitle.'</li>';
         		}
			echo '</ul>';

			} else {
                                    echo '<ul><li>Sorry no results found.</li></ul>';
			}
		} else {
			// do nothing
		}
	} else {
		echo 'There should be no direct access to this script!';
	}
}

 

And then i have this in my JavaScript:

 

    <script type="text/javascript">
    function suggest(inputString, inputFor){
                    if(inputString.length == 0) {
                            $('#suggestions').fadeOut();
                    } else {
                    $('#documents').addClass('load');
                            $.post("includes/autosuggest.php", {queryString: ""+inputString+"", queryFor: inputFor}, function(data){
                                    if(data.length >0) {
                                            $('#suggestions').fadeIn();
                                            $('#suggestionsList').html(data);
                                            $('#documents').removeClass('load');
                                    }
                            });
                    }
            }

            function fill(thisValue) {
                    $('#documents').val(thisValue);
                    setTimeout("$('#suggestions').fadeOut();", 600);
            }
    </script>

 

But i keep getting this:

 

There should be no direct access to this script!

 

So it does not recognize: if($_POST['queryFor'] == "author"){...

 

Any ideas why it doesn't work, where is author set? This is my input text box:

 

<input type="text" size="25" value="" id="documents" onkeyup="suggest(this.value, 'default');" onblur="fill();" class="searchtext" name="documents"/>

 

 

Share this post


Link to post
Share on other sites

Because in your input text box, your using default instead of author as the second parameter for suggest(). In your PHP you should have and elseif and see if the queryFor is default, if it is then search for whatever.

 

So basically, you have one input box where you want to search for general things, which we shall call default. So in this box you call the suggest() function and set the second parameter to default. Then somewhere else you want to get suggestions for authors, so you set the second parameter to author.

 

Then your PHP Script needs to handle MySQL searches for both these, or more if you add more.

 

if($_POST['queryFor'] == "author"){
// do mysql search query for your author
} elseif($_POST['queryFor'] == "default") {
// do mysql search query for default
} else {
// bad call or direct access
echo 'There should be no direct access to this script!';
}

Share this post


Link to post
Share on other sites

Thanks, It's actually quite simple to call the method on different pages..

 

I have got it working thanks to your assistance.. However i have one problem.

 

On this page:

 

http://www.prima.cse.salford.ac.uk:8080/~ibrarhussain/admin/testing.php

 

I have made this so you can see what i am trying to do.. If you start typing, you will see the predictive text working perfectly on the first textbox. However now click on "add author" and start typing in the second box, if you select an option from the suggestions it fills the first textbox always. Is there way i can have the suggestions specific to each textbox?

 

Regards

Billy

 

Thanks again

Share this post


Link to post
Share on other sites

Yeah, in your input boxes instead of passing this.value as the parameter, just pass this.

 

Then, in your JavaScript where you pass in the queryString to the PHP script and queryFor, change queryFor to:

 

queryFor: inputFor.value

 

Now, when you retrieve the data you can use inputFor.id in your jQuery, like so:

 

$('#suggestions').fadeIn();
$('#suggestionsList').html(data);

// Use our inputFor.id because that's the ID of our input box
$('#' + inputFor.id).removeClass('load');

 

I also noticed you used #documents further up as well, remember to replace that with what I've done above.

 

Then your fill() function needs to something similar, so that it fills the correct input box.

Share this post


Link to post
Share on other sites

Hi,

 

Thanks, i tried that but had no luck!  :-\ Sorry i tried taking you to a page before which required login access. If you visit this page:

 

http://www.prima.cse.salford.ac.uk:8080/~ibrarhussain/admin/testing.php

 

you can see a textbox, with the ability to add more textboxes by the "add author" link. If you view the doctype you will see i have tried making some changes, but the predictive suggestions does not work..

 

Any ideas what i have missed out?

 

Thanks

Share this post


Link to post
Share on other sites

This is my JavaScript at the top:

 

    <script type="text/javascript">
    function suggest(inputString, inputFor){
                    if(inputString.length == 0) {
                            $('#Adminsuggestions').fadeOut();
                    } else {
                    $('#' + inputFor.id).addClass('load');
                            $.post("../view/includes/autosuggest.php", {queryString: ""+inputString+"", queryFor: inputFor.value}, function(data){
                                    if(data.length >0) {
                                            $('#AdminSuggestions').fadeIn();
                                            $('#AdminSuggestionsList').html(data);
                                            $('#' + inputFor.id).removeClass('load');
                                    }
                            });
                    }
            }

            function fill(thisValue) {
                    $('#' + inputFor.id).val(thisValue);
                    setTimeout("$('#AdminSuggestions').fadeOut();", 600);
            }
    </script>

 

And then this is my textbox:

 

            <div id="AdminSuggest">
            <label for="Author">Author:</label>
                <input type="text" name="author[]" id="authors" value="" onkeyup="suggest(this, 'admin');" onblur="fill();" style="margin-left:-1px"/>
                    <div class="right" style="margin: 0 360px 0 0"><a href="#" id="add-line" onclick="addTextBox()">Add author</a></div>
                    <div class="AdminSuggestionsBox" id="AdminSuggestions" style="display: none;"> <img src="../view/images/arrow.png" style="position: relative; top: 0px; left: 0px;" alt="upArrow" />
                    <div class="AdminSuggestionList" id="AdminSuggestionsList">   </div>
                    </div>
            </div>

 

Just thought i'd show you so you can see what i might be doing wrong?

Share this post


Link to post
Share on other sites

Okay, you're going to have to mix things up a little here. When you are adding new input boxes they all have the same ID, this is bad. In your textbox.js file, you have this line:

 

var htcontents = "<div id=\"authors-list\"><div id=\"AdminSuggest\"><label for='Author'>Author:</label><input type='text' name='author[]' id='authors' value='' onkeyup=\"suggest(this, 'admin');\" onblur=\"fill();\"/><div class=\"AdminSuggestionsBox\" id=\"AdminSuggestions\" style=\"display: none;\"> <img src=\"../view/images/arrow.png\" style=\"position: relative; top: 0px; left: 0px;\" alt=\"upArrow\" /><div class=\"AdminSuggestionList\" id=\"AdminSuggestionsList\">   </div></div></div></div>"; 

 

Change it to this:

 

var htcontents = "<div id=\"authors-list-" + inival + "\"><div id=\"AdminSuggest" + inival + "\"><label for='Author'>Author:</label><input type='text' name='author[]' id='authors" + inival + "' value='' onkeyup=\"suggest(this, inival, 'admin');\" onblur=\"fill(this, inival);\"/><div class=\"AdminSuggestionsBox\" id=\"AdminSuggestions" + inival + "\" style=\"display: none;\"> <img src=\"../view/images/arrow.png\" style=\"position: relative; top: 0px; left: 0px;\" alt=\"upArrow\" /><div class=\"AdminSuggestionList\" id=\"AdminSuggestionsList" + inival + "\">   </div></div></div></div>";

 

What I've changed is all attributes that have the same ID now have inival appended to them, like the containing div in the other function. The parameters for the suggest() and fill() functions have also changed. (I've used 'admin' as the inputFor in the dynamically added input boxes).

 

I also changed how the suggest and fill functions will work. This is what you should change them too:

 

<script type="text/javascript">
    function suggest(elm, num, inputFor){
                    if(elm.length == 0) {
                            $('#AdminSuggestions' + num).fadeOut();
                    } else {
                    $('#' + elm.id).addClass('load');
                            $.post("../view/includes/autosuggest.php", {queryString: ""+elm.value+"", queryFor: inputFor}, function(data){
                                    if(data.length >0) {
                                            $('#AdminSuggestions' + num).fadeIn();
                                            $('#AdminSuggestionsList' + num).html(data);
                                            $('#' + elm.id).removeClass('load');
                                    }
                            });
                    }
            }

            function fill(elm, num) {
                    $('#' + elm.id).val(elm.value);
                    setTimeout("$('#AdminSuggestions' + num).fadeOut();", 600);
            }
    </script>

 

Now your default input box should look like this:

 

<div id="AdminSuggest">
            <label for="Author">Author:</label>
                <input type="text" name="author[]" id="authors" value="" onkeyup="suggest(this, '', 'admin');" onblur="fill(this, '');" style="margin-left:-1px"/>
                    <div class="right" style="margin: 0 360px 0 0"><a href="#" id="add-line" onclick="addTextBox()">Add author</a></div>
                    <div class="AdminSuggestionsBox" id="AdminSuggestions" style="display: none;"> <img src="../view/images/arrow.png" style="position: relative; top: 0px; left: 0px;" alt="upArrow" />
                    <div class="AdminSuggestionList" id="AdminSuggestionsList">   </div>
                    </div>
            </div>

 

That should just about do it, note that none of this was tested. So it may or may not work. Hopefully you can see how it's all being done.

Share this post


Link to post
Share on other sites

Ok again thanks for your response, i appreciate your help immensely  :D

 

That nearly worked, however what is happening now is that the predictive text is still only showing for one textbox, and also, you cannot select an option from the dropdown, so it's not clickable thus does not fill the textbox.

 

I understand what you are suggesting, having input with different ID's so that the suggestions list is specific to each text box..

 

In regards to the fill method:

 

            function fill(elm, num) {
                    setTimeout("$('#AdminSuggestions' + num).fadeOut();", 600);
            }

 

I get a grey line under 'elm' and 'num', saying "unused".. Could it be this?

Share this post


Link to post
Share on other sites

Okay, it seems I haven't looked at all the code properly. Let's change up a few things... again.

 

What I didn't notice is that fill() is being called from the PHP page, which makes sense. Let's change our suggest() function first. We want to send a few more POST variables to our PHP page, the number of the input box.

 

Change this line:

$.post("../view/includes/autosuggest.php", {queryString: ""+elm.value+"", queryFor: inputFor}, function(data){

 

To this:

$.post("../view/includes/autosuggest.php", {queryString: elm.value, queryFor: inputFor, queryNum: num, queryId: elm.id}, function(data){

 

Now, your PHP code needs to change so that fill accepts the num parameter for fill:

echo '<li onClick="fill(\'' . $_POST['queryId'] . '\', \''.addslashes($result->CPtitle).'\', \'' . $_POST['queryNum'] . '\');">'.$result->CPtitle.'</li>';

Now the fill() function should look like this:

function fill(elm, value, num) {
                    $('#' + elm).val(value);
                    $('#AdminSuggestions' + num).fadeOut();
            }

Share this post


Link to post
Share on other sites

Ok thats perfect, take a look  :D

 

http://www.prima.cse.salford.ac.uk:8080/~ibrarhussain/admin/testing.php

 

I can't thank you enough! Ok i'm not sure if this is a css issue, but when you get to the page, add about 8 textboxes and then start typing in the 8th box, try with name "Peter.."

 

You will see that the drop down appears under the first text box, BUT fills the 8th textbox  ::)

 

Is this done in the JavaScript? The reason why i'm asking is the CSS is has already been made to sit underneath the textbox.. so i assumed when more are added it would simply just dropdown under each one separately?

 

Thanks again for your help..

 

 

Share this post


Link to post
Share on other sites

You didn't change the textbox.js file to what I gave you above. Your not setting all the suggestion div box ids correctly.

Share this post


Link to post
Share on other sites

Woops! Silly me..

 

That works now, there are some css fixes as the drop down appears way over to the left, so i will get on with these  ::)

 

Thanks for all your help, really appreciate it.

 

Regards

Billy

Share this post


Link to post
Share on other sites

There are actually a few bugs with it, try this instead:

 

var htcontents = "<div id=\"authors-list-" + inival + "\"><div id=\"AdminSuggest" + inival + "\"><label for='Author'>Author:</label><input type='text' name='author[]' id='authors" + inival + "' value='' onkeyup=\"suggest(this, '" + inival + "', 'admin');\" onblur=\"fill(this, '" + inival + "');\"/><div class=\"AdminSuggestionsBox\" id=\"AdminSuggestions" + inival + "\" style=\"display: none;\"> <img src=\"../view/images/arrow.png\" style=\"position: relative; top: 0px; left: 0px;\" alt=\"upArrow\" /><div class=\"AdminSuggestionList\" id=\"AdminSuggestionsList" + inival + "\">   </div></div></div></div>";

 

The inival variable wasn't being set properly in there.

Share this post


Link to post
Share on other sites

Thanks,

 

I was actually going to post back about something else. Basically when there is no text in the textbox the dropdown suggestions should fade out..

 

So i looked at this function:

 

                    if(elm.length == 0) {
                            $('#AdminSuggestions' + num).fadeOut();
                    }

 

Which i thought should fade the dropdown suggestion out when there is no text. But it does not seem to work. so i tried adding this:

 

alert(elm.length);

 

And i got "undefined"..

 

Any ideas what the problem is?

 

 

Share this post


Link to post
Share on other sites

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.