Gossamer Forum
Home : Products : DBMan : Customization :

Using AJAX with DBMan

Quote Reply
Using AJAX with DBMan
I was hacking around with AJAX and got it to work with the sign up form in DBMan. It will check usernames against the password file as your new users type and notify them if a name is already taken *before* they submit the form. (AJAX can take the place of form submission for some functions such as math, checking usernames, email validation, postal address validation, etc.)

Here is the code if anyone wants to play with it...

1. Edit the html.pl file (sub html_signup_form) as follows:

a. add
<SCRIPT LANGUAGE="JavaScript" SRC="ajax.js"></SCRIPT>
in between the <head></head> tags
b. modify the username <INPUT> tag as follows:
<input type="TEXT" name="userid" ID="userid" value="$in{'userid'}" onkeyup="checkUsername(event)">
(adding the "onkeyup" part)
c. add
<DIV ID="targetDiv">&nbsp;</DIV>
after the closing </table> just above the submit buttons.

2. Copy the following into a file called ajax.js and upload it into the same directory as your dbman script (I didn't have to change any permissions on this one):
Code:
var XMLHttpRequestObject = false;

if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP");
}

function getData(dataSource) {

if (XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", dataSource);
XMLHttpRequestObject.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

XMLHttpRequestObject.onreadystatechange = function() {

if (XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status == 200) {

if (XMLHttpRequestObject.responseText) {
var targetDiv = document.getElementById("targetDiv");
targetDiv.innerHTML = XMLHttpRequestObject.responseText;
}

}
}
XMLHttpRequestObject.send(null);
}
}


function checkUsername(keyEvent) {

keyEvent = (keyEvent) ? keyEvent: window.event;
input = (keyEvent.target) ? keyEvent.target : keyEvent.srcElement;

if (keyEvent.type == "keyup") {
var targetDiv = document.getElementById("targetDiv");
targetDiv.innerHTML = "<div></div>";

if (input.value) {
getData("checkuser.cgi?uname=" + input.value);
}

}
}

3. Copy the following into a file called checkuser.cgi and upload to the same directory as your dbman script. Change permissions to 755 (rwx-rx-rx) - you'll need to change default.pass to whatever your password file is called:
Code:
#!/usr/local/bin/perl

my $message;

#takes the info passed along in "GET" and splits the single pair into values
#if using POST use $ENV{"CONTENT_LENGTH"}
$pair = $ENV{"QUERY_STRING"};
local($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ s/<!--(.|\n)*-->//g;
$FORM{$name} = $value;


#open & read the password file - change default.pass to whatever you named your password file
open (PASS, "<default.pass") or die ("unable to open: password file.\nReason: $!");
if ($db_use_flock) { flock(PASS, 1); }
while (<PASS>) {

#code borrowed from GT - if you find a match then $message will contain what you type below
/^\Q$FORM{'uname'}\E:/ and ($message = "The Username <U>$FORM{'uname'}</U> already exists. Please try another.");

}

print "Content-type: text/html\n\n";
print "<font color=red>$message</font>";
close PASS;


Caveats: I got this to work using GET, but would really like to use POST - however it is not a simple as just changing the words, so I'm using GET for now.

The script "fires" on the "onkeyup" "call" or "event" - which means it runs on each keystroke in the username field. I'd like to use "onChange" which means it'd run only after the user had tabbed or clicked out of the field, but once again it won't work if I simply replace "onkeyup" with "onchange". Also, I'm an upper/lower case kind of guy but the script wouldn't work if I used onKeyUp (instead of onkeyup) - not sure why...

This script works based on JavaScript and if the user has their browser set to ignore JavaScript then it won't work.

.........................

The purpose of this excercise was to get it to work. I'd plan on adapting the script to use when users type in their mailing address so it will check the address against the US Post Office's database and warn them if they've entered a bad address.

Feel free to play with this and improve upon it. Any pointers or suggestions are welcome.