I'm working on a web site that allows people to enter RSS urls. These urls get parsed (via CFFEED) and displayed on a custom page. While I have support for handling bad RSS feeds, I wanted to create a quick demo where I'd use jQuery and ColdFusion to handle checking the RSS feeds while the user is working on the form. Here is what I came up with.
First - let's look at the form. The first two fields aren't really relevant. I added them to show that the RSS parsing was part of a greater form. The last three fields, the RSS labeled ones, are the fields we will care about.
<style>
.rssfield { width: 500px; }
.rssstatus {
font-style: italic;
}
</style>
<form>
name: <input type="text" name="name"><br/>
max num of entries: <input type="text" name="maxentries"><br/>
rss feed: <input type="text" name="rssfeed1" class="rssfield"><br/>
rss feed: <input type="text" name="rssfeed2" class="rssfield"><br/>
rss feed: <input type="text" name="rssfeed3" class="rssfield"><br/>
<input type="submit">
</form>
Note that I've made use of a class, "rssfield", that is common to all the fields. This is going to come into play within our jQuery. And speaking of that - let's take a look at the JavaScript.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$(".rssfield").blur(function() {
var value = $(this).val()
var name = $(this).attr("name")
console.log('current value is '+value+' for field '+name)
value = $.trim(value)
//If blank, just quit - but clear any previous status
if(value == '') {
if($("#status"+name).length == 1) $("#status"+name).text("")
return
}
//create a response span - if we don't have one
if($("#status"+name).length == 0) $(this).next().before('<span class="rssstatus" id="status'+name+'">Checking RSS validity...</span>')
else $("#status"+name).text("Checking RSS validity...")
//call the server to check the field
$.get('checkrss.cfm', { "rssurl":value}, function(data,status,eq) {
if(data.verified == 0) {
console.log('bad')
$("#status"+name).html("RSS value not valid: "+data.message)
} else {
console.log('good')
$("#status"+name).html("RSS value valid!")
}
console.log(data)
})
})
})
</script>
So as you can see - the bulk of the code here revolves around a blur handler for any field with the rssfield class. (I should probably have filtered it INPUT tags as well.) I begin by getting the value and name. Once I have the value, I do a quick trim on it. Now the first thing I want to do is ensure the user actually typed something in. If they didn't, I might as well leave. For now ignore that first line in the clause. It will make more sense in a second.
If the user did type something, I begin by creating a new span to handle a status message. Why did I do this? My thinking was - it would be kind of nice if I didn't add stuff to my form that was distracting. Not that a empty span would even register to a user, but I thought it would be nice if jQuery handled that as well. So essentially - I try to get a span for my particular field. If it doesn't exist, I create it. If it does exist, I set the text. I'm way open to being argued about this way of doing this.
Finally we get to the AJAX call. I pass the value to a ColdFusion script and then wait around the result. I'm going to expect a structure back. That structure will have two fields: verified and message. The message field will only be used for errors. So that's it really for the client side code, now let's take a look at checkrss.cfm:
<cfparam name="url.rssurl" default="">
<cfif url.rssurl is "">
<cfabort>
</cfif>
<!---
Return a structure:
verified: 0/1 (true/false)
message: Only useful on bad results
--->
<cfset result = {}>
<cfif not isValid("url", url.rssurl)>
<cfset result["verified"] = 0>
<cfset result["message"] = "Value was not a valid URL.">
<cfelse>
<cftry>
<cffeed source="#url.rssurl#" query="foo">
<cfset result["verified"] = 1>
<cfset result["message"] = "">
<cfcatch>
<cfif cfcatch.message is "Unable to parse the feed: Either source specified is invalid or feed is malformed.">
<cfset result["verified"] = 0>
<cfset result["message"] = "URL was not a valid RSS feed.">
<cfelse>
<cfset result["verified"] = 0>
<cfset result["message"] = "Unable to verify RSS feed. Gremlins.">
</cfif>
</cfcatch>
</cftry>
</cfif>
<cfcontent type="application/json" reset="true"><cfoutput>#serializeJSON(result)#</cfoutput>
Stepping through - we being with a quick param for url.rssurl. If it is blank, we abort the request. Then we first check to see if the URL is valid. If not, we return a struct with a message saying that it was not. Now unfortunately, cffeed does not support a way to see if a URL is a valid RSS feed. So because of that, I perform the request and simply try/catch it. I've got one catch set up for a bad feed, and another set up for "everything else". Finally I serialize the response.
All in all - a pretty simple example. I do want to point out something. The jQuery form validation plugin (when I say "the" I obviously mean, to me, the best one) actually supports operations like this. You can easily set up validation rules that include hitting server side stuff for complex logic. I chose not to use it in this example because I'm not quite sure I'll be using the plugin for the site in question. And I wanted to write it myself for fun.
I've got a demo set up (see big ole button below), but unfortunately, I had to hobble it a bit. Any valid URL will be converted to http://feeds.feedburner.com/RaymondCamdensColdfusionBlog, which means it will always come back as true. I will explain why later today. (Possible new bad bug in cffeed unfortunately.)
Archived Comments
demo is busted.. .. tisk tisk
Fixed.
Have you checked out the jQuery Validation plugin? It's has a baked-in "url" method.
http://docs.jquery.com/Plug...
I don't use CFForm anymore since using this library as it allows me to change validation rules on-the-fly and integrate dependencies that CFForm is unable to do on the client-side.
http://bassistance.de/jquer...
James - did you read the second to last paragraph? :)
Sorry... I didn't read the full article. (I need to slow down... too much coffee this morning.) I just realized that you already mentioned the validation plugin. Using this plugin will automatically add error messages to the form when information is invalid or required.
You were additionally verifying the URL. To do this with jQuery Validation, you'd use the "remote" method:
http://docs.jquery.com/Plug...
I mentioned that too. :) I even blogged about it before. As I said though - I wanted to do it "by hand". I probably _will_ end up going the validate route cuz it would be handier.