Interesting ColdFusion Ajax Issue(Bug?)

Yesterday a reader wrote me with an interesting question. He was using ColdFusion’s Ajax controls to load content into a cfdiv. Within the content loaded via Ajax, he had a simple form with some checkboxes. He wanted to use jQuery to support a “Check All” button. For some reason though the event handler he used never worked. Let’s take a look at his initial code. First - here is the root page:

<cflayout type="border" name="layoutborder" height="200"> <cflayoutarea name="Center" position="center"> <a href="javascript:ColdFusion.navigate('test2a.cfm','catz')">Click Here</a> </cflayoutarea> </cflayout> <cfdiv id="catz"></cfdiv>

As you can see, he uses a simple border style layout with a link that makes use of ColdFusion.navigate. Now let’s look at test2a.cfm:

<script> $(document).ready(function() { console.log("Confirm I ran...") $("#checkboxall").click(function() { console.log("Ran the checkbox") var checked_status = this.checked; $("input[name=mapid]").each(function() { this.checked = checked_status; });

})

}) </script>

<input id=”checkboxall” type=”checkbox” />Check all below<br/> <FORM> <input name=”mapid” type=”checkbox” /><BR> <input name=”mapid” type=”checkbox” /><BR> <input name=”mapid” type=”checkbox” /><BR> </form> </code>

Pardon the tabbing above - these scripts went through some adjustments. Anyway - nothing too special here. You can see the main form with the special checkbox above it. The jQuery code has an event listener for the special checkbox. When run it simply gets the other checkboxes and either checks or de-checks (is that a word?) the boxes.

So again - this should work. On a whim, I made a tweak. I switched from using a click listener to the live() feature. I’ve blogged on this before. jQuery’s live() feature allows you to use event listener for DOM items that don’t exist yet. So if you want to always bind to links, and you load content that may contain links, you need to use live(). From what I knew though, this shouldn’t be required. The event listener was run when the content was loaded. However, when I switched the code to:

$("#checkboxall").live("click",function() {

It worked! So that was last night. This morning I tried to dig a bit deeper into this. As I said, this change should not have been required, but it obviously worked (the reader confirmed it). So I did an interesting test. I wrote a new front end page that made use of both ColdFusion.navigate and jQuery:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> <script>

$(document).ready(function() {

$("#loadIt").click(function() {
	$("#content").load("test2a.cfm")
})

})

</script>

<input type=”button” value=”Load Content” id=”loadIt”>

<div id=”content”></div>

<cflayout type=”border” name=”layoutborder” height=”200”> <cflayoutarea name=”Center” position=”center”> <a href=”javascript:ColdFusion.navigate(‘test2a.cfm’,’catz’)”>Click Here</a> </cflayoutarea> </cflayout> <cfdiv id=”catz”></cfdiv> </code>

And here is where things get crazy. As you can see, I’ve got the original code on the bottom. Above it I have a simple button that runs the jQuery load() function. Basically though both should be doing the same thing: Request test2a.cfm and load it into a thing.

I was shocked to see though that the jQuery loaded content worked as I expected! At this point I was truly lost. I opened up Firefox (I’ve pretty much given up on Firefox except for Firebug) and looked at the XHR requests. In general, I saw two things different.

First - ColdFusion’s navigate function adds a bunch of junk to the URL. I knew this of course. It handles suppressing debugging, preventing caching, and other stuff. As an example, here is the jQuery URL versus ColdFusion’s:

http://localhost/test2a.cfm
http://localhost/test2a.cfm_cf_containerId=catz&_cf_nodebug=true&_cf_nocache=true&_cf_clientid=730C445ABFA5719A14A7DBC87B0E5259&_cf_rc=0

As I said - I expected that. The second change was surprising. In a previous blog post I talked about how you can check for a HTTP header, X-Requested-With, to sniff an Ajax request. This is set by jQuery and other Ajax frameworks. It isn’t (as far as I know) an actual part of the low level HTTP implementation in JavaScript. ColdFusion’s code, however, does not send this header. While I don’t believe this is the issue, it is surprising. I’m going to file an ER for this and I’m going to see if I can tweak the core ColdFusion JavaScript code to add this header in. Maybe it will make a difference.

Raymond Camden's Picture

About Raymond Camden

Raymond is a developer advocate looking for his next gig. He focuses on JavaScript, serverless and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support.

Lafayette, LA https://www.raymondcamden.com

Comments