Converting ColdFusion data for jQuery Plugins - An example
Kerrie asks:
A couple of weeks ago, I read a post you wrote on jQuery and form validation... really peaked my interest so I've been taking a look at not only the validation plugin, but many of the other great jQuery plugins... I found this one last night, and its perfect for an app I'm working on, but I cannot figure out how to return the output of a query to populate the list. In the demo they are returning the results of tvshows.php. I noticed a number of other folks were having the same problem but no solution. Might you have a few spare moments to take a look??
Kerrie, don't feel alone. I've noticed this in a few other jQuery plugins. The author will give you an example of the JSON they want, but they don't describe the JSON in pure data forms. So for example, if the JSON string is an array of strings, they don't say that. They just show it and assume you know that is how arrays are represented in JSON. JSON may be easy, but I definitely can't parse it in my head quite yet. Lets take a look at what the plugin wants:
Ask a Jedi: CFAJAXPROXY and Managing Callbacks
Yaron asks:
I'd like to know what your preference is for using cfajaxproxy. In JavaScript, do you create one global proxy object and reuse it throughout your script? Or do you create a new proxy object within every function that generates a proxy call?
The reason I'm asking is I had multiple concurrent proxy calls that had their callback functions mixed up. Meaning, one functions makes 2 async calls with two separately defined callback functions. Unfortunately, one callback function received the input from another. Weird.
Ah, asynchronous network calls. Life would be a heck of a lot easier if everything was synchronous. Let's dig a bit into what Yaron found in case it doesn't make sense.
My waste of time this weekend - playing with Yahoo Maps and jQuery
Last week I blogged on jQuery UI tabs and Google Maps. That led me to take another look at Yahoo's Maps API. I had worked with this sometime ago when I created my CFYahoo project. The code I wrote for the wrapper though only interfaced with their REST API. This let you get maps as images and save them to your server. This weekend I took a look at the AJAX API.
jQuery Tabs and Google Maps
A reader wrote in earlier this week about an issue with Google Maps and jQuery tabs. He was trying to use a Google Map in one tab but the map wasn't rendering correctly. Here is a quick example showing what went wrong.
Links
Just a quick recap of external blog posts. My last entry for this was back on April 26th.
- Sports Tournament Style Brackets with jQuery and jQuery UI (3)
- Sports Tournament Style Brackets with jQuery and jQuery UI (2)
- jQuery FTW (May 16)
- Sports Tournament Style Brackets with jQuery and jQuery UI
- Open Question: When not to RIA?
- jQuery FTW (May 2)
- Detecting an End of Session Event with jQuery
User Submitted Tip: Refreshing a CFDIV bound to a CFC
I swear this is something I may have covered before, but I'm not finding it in my archives. Either way, it's a good tip and I wanted to share it. Markus Wollny was working with a CFDIV tag that was bound to a CFC:
<cfdiv id="ivactid" bind="cfc:article.getCuriVactid()"></cfdiv>
The problem he ran into was refreshing the data in the grid. Normally a bound CFDIV (or other UI item) would 'listen' in to a particular form field and notice when it changed. In his case, there was no form field included in the bind.
To get around this, he simply used ColdFusion.navigate on the DIV and switched to a URL version of his CFC:
ColdFusion.navigate('article.cfc?method=getCuriVactid','ivactid')
In order for this to work the CFC has to return a string as a result, and unless the cffunction tag declares it explicitly, you will need to use a returnFormat of plain:
ColdFusion.navigate('article.cfc?method=getCuriVactid&returnFormat=plain','ivactid')
Thanks for sharing this, Markus.
Preventing resizes in CFGRID Columns
Ever want to stop the ability to resize columns in a CFGRID? There isn't a way to do this via tags, but as with other CFGRID hacks, you can do it once you get access to the underlying grid object. Let's look at an example.
Simple CFCHART/jQuery Demo
I had some time to kill today and I decide to mix cfchart up with some jQuery love. You can see the demo of this here. When the chart loads, click on the bars, and you will see a detail load beneath the graph.

The code behind this is fairly trivial. I've got a file I include to generate my chart data. Normally this would be a proper database query. The main template's code consists of:
<cfinclude template="data.cfm">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
function loadData(l) {
$("#detail").load('detail.cfm?name='+escape(l)).hide().fadeIn('slow')
}
</script>
<cfchart chartWidth="500" chartHeight="250" format="flash" url="javascript:loadData('$ITEMLABEL$')">
<cfchartseries type="bar" query="data" itemcolumn="name" valuecolumn="sales" />
</cfchart>
<div id="detail" style="width:500"></div>
The cfchart makes use of the url attribute to specify what should happen when you click. In this case, I'm simply calling a function, loadData(). This then uses jQuery to make a remote call to detail.cfm. Note that I pass the name. Normally you would pass a primary key, but we don't have (easy) access to that (see this entry for more info) value so we have to work with the name instead. That's it. All detail.cfm does is look up the detail information:
<cfinclude template="data.cfm">
<cfparam name="url.name" default="">
<!--- get detail based on label --->
<cfquery name="detail" dbtype="query">
select *
from data
where name = <cfqueryparam cfsqltype="cf_sql_varchar" value="#url.name#">
</cfquery>
<cfif detail.recordCount is 1>
<cfoutput>
<h2>#url.name#</h2>
<p>
Founded: #detail.yearfounded#<br/>
Sales: #dollarFormat(detail.sales)#<br/>
#paragraphFormat(detail.bio)#
</cfoutput>
</cfif>
Not terribly useful I guess, but fun.
CFAJAXPROXY and Extended CFCs
Well here is something I didn't expect. Thanks go to a forum poster for bringing this to my attention. When you use cfajaxproxy to proxy a CFC, and that CFC extends another CFC, you don't get access to the remote methods defined in the base CFC. Consider the following example.
Using a Remote JSONP ColdFusion Service to Send Mail
A user had an interesting question regarding jQuery and JSONP. He wanted to know if a file on one server (a server without ColdFusion) could use jQuery and JSONP to run CFML code on another server and send email. The problem with using JSONP in this scenario is that JSONP is a GET request. Emails are - typically - a bit long and could fail to execute if the message was too large. He still wanted to see an example anyway so I whipped up the following demo. The code is based on the blog entry I wrote two months ago on JSONP services in ColdFusion.
The front end is incredibly simple. One text area and a button:
<form id="theform">
<textarea name="msg" id="msg"></textarea>
<input type="submit">
</form>
I then whipped up some quick jQuery code to process the form:
<script>
$(document).ready(function() {
$("#theform").submit(function() {
var message = $("#msg").val()
$.getJSON('http://127.0.0.1/test.cfc?method=sendmail&callback=?', {message:message}, function(d,t) {
$("#result").html('Mail Sent')
})
return false
})
})
</script>
I begin by grabbing the textarea value. Then I run the JSONP request. A JSONP request is no different than a normal JSON request, but you have to include the ? parameter at the end of the URL. This tips off jQuery that we are doing a JSONP request instead of a simple HTTP request to an item on the same server.
The CFC is a bit simpler than the one I wrote for my previous blog entry. Instead of writing two methods to nicely abstract the service, I just wrote a method to send the mail and return the properly formatted result:
<cffunction name="sendmail" access="remote" returntype="any" output="false" returnformat="plain">
<cfargument name="message" type="string" required="true">
<cfargument name="callback" type="string" required="true">
<cfset var data = "">
<cflog file="application" text="Going to send this in email: #arguments.message#">
<cfset data = serializeJSON(true)>
<!--- wrap --->
<cfset data = arguments.callback & "(" & data & ")">
<cfreturn data>
</cffunction>
The cflog line is standing in for my cfmail command. I don't really care about the result so I just return true. Note the use of the callback wrapper which fits into the JSONP requirements.
Once setup, you could put the HTML on any server and then use the form to send your text to the remote CFC.
Is this a good idea? Probably not. Again, you have to worry about the GET size limits, but you could probably add a size limit to the textarea easily enough.
