Take a look at the two call back handlers, OnMethod1() and OnMethod2(). The first one uses explicit jQuery code to update the DOM. The second one doesn't care what is returned, it just evaluates the value using the eval() method.
Ok, now let's look at the ajax.cfm page that is being called:
<!--- Param the method. ---> <cfparam name="URL.method" type="numeric" default="1" /> <!--- Check to see which method we are using. ---> <cfif (URL.method EQ 1)> <!--- In method one, all we want to do is return the simple value to the client. ---> <cfset strReturn = "Yeah, just like that!" /> <cfelse> <!--- In method two, we don't want to just return the value, we also want to return the Javscript that tells the client what to do with the return value. ---> <cfsavecontent variable="strReturn"> $( "#output" ).html( "Oh baby, that felt good" ); </cfsavecontent> </cfif> <!--- Trim the return value. ---> <cfset strReturn = Trim( strReturn ) /> <!--- Return AJAX value length. ---> <cfheader name="content-length" value="#Len( strReturn )#" /> <!--- Stream result to the client (this will reset the content buffer to make sure no additional data is returned). ---> <cfcontent type="text/plain" variable="#ToBinary( ToBase64( strReturn ) )#" />
Both of these methods work just as expected. I really like the second method. I am not sure if like it because it is new and unfamiliar, or if I like it because the logic is on the server which is where I am more used to playing. I have no recommendations at this point - I am just enjoying this new idea. I am letting it make the evaluation rounds in my mind. I am gonna see if I can get Rob Gonda to drop in here and make sure I really had any clue what he was talking about (I don't want to be misinforming anyone).
Want to use code from this post? Check out the license.
Does $.get("ajax.cfm", actually work?
Oh you better believe it works. It's just a relative URL to the current page (which was in the same directory for my test). But, I think when the rest executes, it actually changes the to a full URL for you. For example, none of my linked files (CSS / JS) have full URLs, only relative ones; however, if you look in FireBug, you will see that the request is all fully qualified URLs.
The browser takes care of all that goodness for you.
jQuery is just too awesome :)
Yeah, I drank the jQuery kool-aid already, I use it. Just don't use the full benefit of it.
jQuery is definitely awesome. I spend almost as much time doing cool UI things with jQuery as I do writing server-side code these days.
That's an interesting technique, having the server essentially issue commands to the client. I wonder if it could be used to completely bridge the events on both the client side and the server side together, letting event-driven frameworks essentially broadcast their events to the client, causing an event on the client side. Maybe you could even set off a chain of back-and-forth events between the client and server (though I can't think of a use case for this off the top of my head).
The biggest reason I am not a fan of method #2 (which is how I have done in the past) is due to the fact that now that the updating of information in the view is being generated in the business logic side of things, forcing high coupling.
Typically it is a good practice to reduce the knowledge that the business logic has of the view, and instead letting the server side of things maniplate data based on business rules, and sending this along back to your view. At this point the only coupling is what the view expects back from the server, as far as data goes.
Did I make any sense at all? lol
That was my concern as well. It may be that I only want the Touch Me return only ever on this one page, in which case it's fine for me to return the full DOM call and do a client-side eval(). If, however, I have another page or some other control elsewhere in my app that wants to play with the same Touch value generation but has a different DOM (maybe I'll use the value on a different page to change a fieldset legend or something), now I would need different return methods. If I return the simple string (or complex HTML, as Ben noted), then I can leave it to the view to go ahead and decide how the dispaly is relevant to it's context.
Something like that :D
A spoonful of jQuery helps the JS medicine go down. ;)
And that's cool. In the end it is simply a matter of what accomplishes the job, with a healthy balance of cost of development, future maintenance cost, and delivery time. Like I said, I've done the same before. :)
@Adam, what do you think about an ajax call building html on the server and then sending it back to the DOM? The classic example is generating options for a select menu, or rows for a table. I just find this to be cleaner than sending back a bunch of JSON and then building the DOM elements in the client, because you can just use CFOUTPUT and some html. Building up DOM elements from JSON is ugly, even with jQuery. I see what you're saying about coupling though.
If you aren't using that kind of thing though, returning HTML is certainly a viable solution. The only point where that really breaks down is when you need to reuse that data in a different fashion... something different than the HTML for a combo box. This is why I typically prefer allowing my model to handle the retrieval of the data, and then pass that through components to transform this data in the desired format (i.e. JSON, XML). If I need to populate a combo box, I simply call the model components to get the data, and construct the combo box in the view. If I needed a JSON data set for some other reason, I can use the same model component, filtered through a transform component, to get the data in the desired format.
You make good points. Perhaps if the AJAX call went to some kind of proxy that then turned around and got the appropriate JSON data, you would't run into these use issues. For example, let's say for every page that has the use of AJAX, it has a server-side controller page like PAGE.ajax.cfm (just thinking out load here). Then, this page, just as the front controller, would take care of the request, pull in the right data, and then package it and send it back.
Of course, this might hurt the Don't Repeat Yourself concept. But then again, you are just moving variation from one file to another, so I don't think that's a concern.
I am not saying that his is an excuse - again, I am new to this and just thinking out loud mostly.