Forum Moderators: open
Seems pretty cool, but I'm wondering what other uses AJAX could be put to. There are a number of examples on the web, but they are pretty academic/theoretical so far.
Implementing AJAX is actually quite straight forward, if you are already using some Javascript on your site and PHP/ASP on your server.
The intended use is for web applications, but ,traditionally, it's most commonly use is for tracking and spying.
Another example is list filtering. Users can filter long lists based on keyword and we highlight the filter matches. This could be done inline, but we also allow for the user filtering on a RegEx!
This is a very powerful tool for web applications as Bernard Marx has said.
Having mastered the basics, I am now trying to do something a bit more complicated.
I want to add a input text box on a form, for example, "city name", and when the user types in a few letters, the form shows a drop-down list (populated from the database) from which to select possible cities. Like Google Suggest.
I can do the database bit, and I can do the XMLHTTPRequest part.
But I am puzzled how to populate and display the drop-down list with the returned database data.
Could anyone offer any tips/ideas?
Many thanks.
A perfect match. What form does the response come back in?
XML? - How is it structured?
Presumeably you are using an asynchronous request, so we could start from the callback function.
1) Send the user input (i.e. first few letters of the city name) to the server as a XMLHttpRequest.send
2) The server queries the database, and returns as a string, say 10 most likely cities in the form "LondonXXXNew YorkXXXParisXXXSydneyXXXBeijingXXXTokyoXXXChicago" (this is just an example!)
3) The client receives this as .responseText, and explodes the string into an array around "XXX"
4) That array is used to populate the drop-down box, which presumably was css-hidden initially and then made visible when there is data available.
Is this sensible / is there a better way?
If I get this working, hopefully I'll reduce the number of mis-spellings of names, cities etc. users make when entering data into the database.
is there a better way? There always is.
This might be easier using the "create new script element" technique.
It wouldn't involve ActiveX in IE, but there may be other problems.
So I'm considering the XMLHTTP approach. I'll knock something together over coffee.
BTW. If possible, how about using \n as a delimiter?
London\nNew York\nParis
1) With CSS, you make a hidden DIV under the text input box in question, and assign them the same widths.
2) In the XMLHTTPRequest callback function,
document.getElementById("hiddenDIV").style.visibility="visible";
document.getElementById("hiddenDIV").innerHTML=xhr.responseText;
3) Server-side, format the return string as a <SELECT>, with each item as an <OPTION>.
So when the server passes the result back, it is displayed as a drop-down box which can be selected.
But the problem is that I cannot seem to generate any events for the SELECT. If the "onclick" or "onchange" could trigger an update of the original input box with a OPTION value, the job would be complete!
Maybe this is why you said it would need the "create new script element" technique?
There are probably some kinks in this approach, not least the asynchronicity - without a built-in callback mechanism. So forget I mentioned it for now.
I hadn't thought of formatting, server-side, the whole markup for the SELECT. Right now, I can't see why it wouldn't work. It might be fine, with a little tweak. I always prefer a pure DOM approach - without using innerHTML. Each time innerHTML is changed the select is a 'new object'. There is also, at the back of my mind, the fact that strict XHTML 1.1 mode doesn't allow innerHTML as a setter.
...
--- relevant HTML ---
<select id="selCountries">
<option value="">select country..</option>
</select>
--- SCRIPT ---
function ID(id){ return document.getElementById(id);}var responseCities = "Chicago\nLos Angeles\nNew York\nWashington";
window.onload = function()
{
HTTPResponse(responseCities);
ID('selCountries').onchange = onCitySelection;}
function HTTPResponse(text)
{
var select = ID('selCountries');
var vals = text.split('\n');
var option, D = document;
for(var k=-1, val;val=vals[++k];)
{
option = D.createElement('option');
option.setAttribute('value',val);
option.appendChild(D.createTextNode(val));
select.appendChild(option);
}
}function onCitySelection()
{
alert(this.options[this.selectedIndex].value);
}
1) This is the main HTML file that brings it all together.
<html>
<head><style>
#form1{position:relative;z-index:0;border:1px solid black}
#city{width:250px;}.leftcolumn{width:250px;}
.hiddenselect{width:250px;position:absolute;z-index:1;visibility:hidden;top:30px;left:260px;}
</style><script type='text/javascript' src="js_dynamic.js">
</script>
</head>
<body>
<form action="action.php" method="post" name="form1" id="form1"><table>
<tr>
<td class="leftcolumn">
<p>Your city of residence:
</td>
<td>
<input type="text" name="city" id="city" onkeyup="return populate(this.value, 'selCities', 'city');"><select id="selCities" class="hiddenselect" multiple size=10 onblur="this.style.visibility='hidden';">
<option value="">select city..</option>
</select></td></tr></table>
</form></body>
</html>
2)This is the JS file called js_dynamic.js
function ID(id){return document.getElementById(id);}window.onload = function()
{
ID('selCities').onchange = function () {ID('city').value=this.options[this.selectedIndex].value;}
}function HTTPResponse(text, control)
{
var select = ID(control);
var vals = text.split('\n'), val;
var options = select.getElementsByTagName('option'), option;
var k, D = document;/* empty all options but first */
while(options.length>1)
select.removeChild(options[options.length-1]);/* (re)fill */
for(k=-1;val=vals[++k];)
{
option = D.createElement('option');
option.setAttribute('value',val);
option.appendChild(D.createTextNode(val));
select.appendChild(option);
}
}function populate(typed, control, type)
{
if (window.XMLHttpRequest) {xhr = new XMLHttpRequest();}
else if (window.ActiveXObject) {xhr = new ActiveXObject("Microsoft.XMLHTTP");}address="http://www.example.com/prefetch.html?type="+type;
xhr.open("POST",address, true);
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');
xhr.send(typed);
xhr.onreadystatechange=function()
{
if (xhr.readyState==4)
{
if (xhr.responseText!="")
{
HTTPResponse(xhr.responseText, control);
ID(control).style.visibility="visible";
}
else
{
ID(control).style.visibility="hidden";
}
}
}
}
3) This is the PHP server script prefetch.html
<?
include("config.html");
$incoming = urldecode(implode(file('php://input')));if ($type=="city" and $incoming!="" and $incoming!=" ")
{
$incoming.="%";
$SQL = "SELECT city, count(city) as CityCount FROM profiles WHERE city like '$incoming' GROUP by city ORDER by CityCount desc LIMIT 10";
$result = mysql_query("$SQL",$cid);
while($row = mysql_fetch_array($result))
{
$city .= trim(ucwords(strtolower($row["city"]))) . "XXXisorgXXX";
}$citya= explode("XXXisorgXXX", $city);
$cityb= array_unique($citya);
$city= implode("\n", $cityb);
echo $city;
exit;
}
?>
This is the first time I have ever posted so much code in a message on WW, and I apologise in advance for my crude programming style (needless to say, I am not a programmer by trade... :) ) But I thought it may help others to know how I got this working, and to thank those who have helped along the way.
[isorg.pastebin.com...] is the HTML file
[isorg.pastebin.com...] is the JS file
[isorg.pastebin.com...] is the PHP script.
It's probably a better practice anyway to use XML rather than just returning Text or HTML.
The information, which after all is quite simple in structure, would have to be wrapped in tags, adding an overhead, and strenously checked for validity, with dodgy characters turned into entities.
Getting the information takes a little more time & effort on the client side too.
While it's not such a big deal, I can't really see any 'big deal' benefits either.
There are some that see JSON [crockford.com] as a better, lightweight alternative (easy on the client, possibly fiddly on the server).
Thinking aloud, while XML might leave some room for flexibility and further development, JSON serialised objects can include their own methods, so there's room for encapsulation and polymorphism. Possibly more options are open that way.
At the moment, the only realistic option for this is XML, although something like JSON would make more sense in the long run (interesting link).
IMHO what we need is for some of the 'authorities' in this area to very quickly provide more C&P examples for generating and reading XML data using XMLHttpRequest so that beginners can get off on the right foot.
"balkanized":
Yes. I know what you mean.
Using basic strings...,
while XML has the capacity to...
<Warning: switching metaphorically from geopolitical to natural>
However XML documents can be snowflakes instead. In the end, one still needs some 'contract' and central central authority. XHTML, dtds etc.
XML docs support an interface, DOM, but it would be nice to arrange a subinterface that enables the "information package" to tell you about itself. This could funnel the multiplicity of tags into something maneagable. Actually this is doubtless possible in XML already (see my first statement).
Anyway, I'll express it as Javascript because that I can get my head around.
{
getOptions:function(){return ['London','Birmingham','Leicester']}
country: 'UK',
init: function(){ alert('Mum: Time for dinner')}
}
The options array is encapsulated, so its getter could be changed at the server so as to choose its output in some other way (don't quite know what for the specific example).
country: Make sure we get what we asked for.
init: Perhaps the only necessary interface component. This could do anything if the client chooses to execute it.
-------------------------------------
The dark cloud for XMLHTTP is ActiveX blocking in IE. Hopefully that will be sorted out soon in one way or another .
One thing I have learnt is that you should not rely on XMLHTTPRequest for your site's functionality. It may not work at all, for a number of reasons, including Javascript being turned off. So only use it to enhance something that is already there.
Case in point - I came to work this morning and tried to play with the scripts I made yesterday, but it doesn't work. I thought my entire day would be ruined because the script had crashed but then realised - my work computer runs IE5.0 and this is the reason it doesn't work!
In fact, "if Javascript is disabled" is definitely the most commonly appearing 25-character string on Javascript forums.
my work computer runs IE5.0 and this is the reason it doesn't work!
IE5 does support XMLHTTP (I have 5.01 elsewhere and that does). The solution is probably a try..catch block like the one at Jibbering [jibbering.com] - although someone posted a better one here once (lost link).
I'm just wondering whether IE's in-built download behavior [msdn.microsoft.com] will work at higher security settings than XMLHTTP. It could be a fallback.
Perhaps (?) IE5 would prefer us to use the old style, Option constructor.
So I'm saying what I said here:
[webmasterworld.com ]
..only the complete opposite.
Now that's a great idea, I will see what happens.
I've been looking at my webalizer stats, and only 1.67% of my visitors were using IE5.0. So maybe it's better left alone - Google Suggest doesn't work on that computer either (gives same error), so I'm in good company :)