jQuery ajax with coldfusion
Ray Camden blogged about this recently and I thought I'd take time out to do some of this jQuery/Ajaxy stuff myself.
I was in the midst of trying to figure out how to to a simple login authentication process with CF8 and jQuery.
I've done this in the past with Prototype and this wonderful ajax library JSMX. Simple library to use..just love it! But, with the times, I figured I should try this "jQuery" thing. Seems to be alot of momentum behind it and there's been a lot of raves. So I dove in.
So let's begin...
First build your form:
<form name="frmLogin" id="frmLogin" method="post">
<fieldset>
<legend>Login here</legend>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td><label for="email">Email:</label></td>
<td> <input type="text" size="25" name="email" id="email" /></td>
</tr>
<tr>
<td><label for="password">Password:</label></td>
<td> <input type="password" name="password" id="password" size="25" /></td>
</tr>
<tr>
<td colspan="2"><div id="loginResponse" style="height: 20px;text-align: center;margin-top:10px;"></div></td>
<tr>
<td><br /><input type="submit" name="Submit" id="submitButton" value="Log In"> </td>
</tr>
</table>
</fieldset>
</form>
Nothing new here, just a simple form.
Now, begin adding your customized jQuery script:
$(document).ready(function() {
// attach a submit handler to the form
$("form#frmLogin").submit(function(){
}); // .submit()
});
$("#frmLogin").submit()
Next up, add your ajax handler:
$.ajax({
type: "",
url: "",
data: ,
success: function(){}
});
TYPE= "GET,POST"
URL = url of the calling script to process the data you'll be passing in
DATA= the data you'll be passing in the form of key value pairs
SUCCESS: the function to call when a successful request is made
ERROR: the function to call when a failed request is made (not used in this example)
Next up, figure out what data you'll be passing from your form. Since we only need to pass in the username and password to process through your validation script this works just fine:
var email = $('#email').val();
var password = $('#password').val();
var datastring = "email=" + email + "&password="+password;
$.ajax({
type: "POST",
url: "ajaxtest.cfc?method=loginCheck&returnformat=plain",
data: datastring,
success: function(){}
});
var datastring= $('form#frmLogin').serialize();
Since I'm calling a CFC to process my credentials, I have to remember to add the ever important RETURNFORMAT=PLAIN parameter to the URL. If I don't, I will get the information passed back to me in CF's native WDDX format. WDDX won't work for me in this instance. I just want to know if the credentials pass...TRUE or FALSE.
So jQuery will now call this behind the scenes: ajaxtest.cfc?method=loginCheck&returnformat=plain&email=
The response back from the server will either be TRUE or FALSE. I need to do something with either one of these 2 results.
$.ajax({
type: "POST",
url: "ajaxtest.cfc?method=loginCheck&returnformat=plain",
data: datastring,
success: function(response){
var resp = jQuery.trim(response);//getting alot of whitespace in my return CFC method
if (resp == 'true'){
$('#loginResponse').html("<span style='color: green;font-weight: bold; font-size: 15px;'>Success!!</span>");
// you'll want to put your code here to move onto the next page. I would simply do a page refresh
// and continue with using the session's login data
}else{
$('#loginResponse').html("<span style='color: red;font-weight: bold; font-size: 15px;'>Failed!!</span>");
}
}
});
Next up I trim my response. Not sure this is necessary, but my CFC was returning alot of whitespace. Probably unnecessary for everyone else.
Next, I decided to do an IF/ELSE based on the return value.
If resp is TRUE then add to the loginResponse div, the word "Success!!" that's styled within a span tag.
I do the same for a FALSE response.
I hard coded the styling for this example, but you're going to want to add a class to this field.
ajaxtest.cfc:
<cffunction name="loginCheck" access="remote" returntype="string" displayname="validates login">
<cfargument name="email" type="string" required="yes">
<cfargument name="password" type="string" required="yes">
<cfset valid = "">
<cfquery name="validate" datasource="#variables.dsn#">
select username,password from employees_login
where username = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.email#">
and password = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.password#">
</cfquery>
<cfif validate.recordcount>
<cfset valid ="true">
<cfelse>
<cfset valid="false">
</cfif>
<cfreturn valid>
</cffunction>
jQuery ajax with CF

I've been playing around with all the return codes.
(function($) {
$().ajaxStart(function() { // Learning jQuery pg. 129
$('#busy').slideDown();
});
$().ajaxSend(function(myEvent, request, settings) {
$('#debug').append(myEvent.type+'<br />');
$('#debug').append('readyState:'+request.readyState+'<br />');
$('#debug').append('multipart:'+request.multipart+'<br />');
$('#debug').append('type:'+settings.type+'<br />');
$('#debug').append('url:'+settings.url+'<br />');
});
$().ajaxSuccess(function(myEvent, request, settings) {
$('#debug').append(myEvent.type+'<br />');
$('#debug').append('readyState:'+request.readyState+'<br />');
$('#debug').append('status:'+request.status+'<br />');
$('#debug').append('responseText:'+request.responseText+'<br />');
$('#debug').append('type:'+settings.type+'<br />');
$('#debug').append('url:'+settings.url+'<br />');
});
$().ajaxComplete(function(myEvent, request, settings) {
$('#debug').append(myEvent.type+'<br />');
$('#debug').append('readyState:'+request.readyState+'<br />');
$('#debug').append('multipart:'+request.multipart+'<br />');
$('#debug').append('status:'+request.status+'<br />');
$('#debug').append('type:'+settings.type+'<br />');
$('#debug').append('url:'+settings.url+'<br />');
});
$().ajaxStop(function() {
$('#busy').slideUp("slow");
});
$().ajaxError(function(myEvent, request, settings, thrownError) {
$('#debug').append(myEvent.type+'<br />');
$('#debug').append('readyState:'+request.readyState+'<br />');
$('#debug').append('multipart:'+request.multipart+'<br />');
$('#debug').append('status:'+request.status+'<br />');
$('#debug').append('type:'+settings.type+'<br />');
$('#debug').append('url:'+settings.url+'<br />');
});
})(jQuery);
ANYWHERE in your variable. For some reason the serializer doesn't escape them properly. Also, because JQuery appears to pass the variables in some
kind of query string format you need to make sure your variables are URL safe as well.
Here is the code I used that seemed to work: (assuming MyStructure is a CF structure object containing strings, numbers, and a query object)
<cfloop collection="#MyStructure #" item="i">
<cftry>
<cfset MyStructure [i] = XMLFormat(MyStructure [i])>
<cfset MyStructure [i] = URLEncodedFormat(MyStructure [i])>
<cfcatch type="any"></cfcatch>
</cftry>
</cfloop>
<script type="text/javascript">
<!--- Convert the object into a javascript variable object--->
<cfwddx action="cfml2js" input="#MyStructure #" toplevelvariable="tempParams">
wddxSerializer = new WddxSerializer();
tableParams = wddxSerializer.serialize(tempParams);
... etc... to Jquery stuff...
Hopefully this will help anyone else having problems with passing special characters. :)
A great run through of passing values directly through to a CFC. I never considered the returnformat value, turns out it was causing me grief.
Also clarified a few points on the AJAX request method for me, now I don't need to use a remote_processor file as a handler.
Thanks
Shaun
HTH