A while ago I built and released ColdFusionBloggers.org as a way to demonstrate and learn about new ColdFusion 8 Ajax technologies. Since then I've wanted to come back to the site and rebuild it using Spry or JQuery. Not because I wasn't happy with the CF8 Ajax stuff, but because a) it's fun to totally rebuild your own sites and b) I wanted to learn more about jQuery.
I also know that the site had a big footprint. YSlow was reporting around 600k of stuff which is a bit much. I was curious to see what a change to jQuery would be like.
I had looked at jQuery a few weeks back. I sat in a good presentation on jQuery (one that focused on the UI stuff) and it seemed like something that wouldn't be too hard to play with.
I began by working on the main guts of the site - the content div. This is the list of blog entries with pagination. Previously this was done with cfdiv. In general this was a super simple implementation outside of the support I had to do for restoring a page based on URL.
This was mainly done using ColdFusion.navigate. In jQuery there is a similar function - load. So I replaced:
ColdFusion.navigate(someurl,somediv)
with
$("#content").load(baseurl);
Simple enough - but not really too much different from the ColdFusion 8 method.
The next issue I ran into was the contact form. This created two problems for me. First off - it seems as if jQuery's built in UI stuff is still in development. While there are ten billion jQuery plugins, as a new user this is actually more of a bad thing then a good thing. I mean as a new user I had no idea what to use. Scott Stroz pointed me to jqModal, which worked easily enough, although my contact form now is a bit uglier compared to what it used to be.
The second problem was how to handle submitting the form. Once again - ColdFusion had a simple way of doing this - ColdFusion.Ajax.submitForm(formid,url,etc). In jQuery I converted this to $.post("url", { data and callback here}). I was a bit surprised that I had to specify the form values. I'm not sure I really need to. The docs say it's optional. But they don't say if it will send the entire form to the URL. I assumed it wouldn't and typed it all out:
$.post("sendcontact.cfm",{dname:$("#dname").val(),demail:$("#demail").val(),comments:$("#comments").val()},formDone);
If I'm right and it is required that you specify the data, then ColdFusion definitely wins here.
Other changes I made were to remove the autosuggest and make the stats pod stop reloading. That was a bit silly in retrospect.
I'm pretty impressed with jQuery. It's not quite as friendly as Spry, but it does seem pretty darn powerful. I hope the UI project continues to evolve as I think it makes sense for jQuery to provide a "best of breed" UI selection for it's users.
Oh - and does size matter? Well, my unscientific testing seems to show the new site reacting just as quickly as it used to. YSlow says the size is now down to 200k or so, which is incredible, but I didn't get the "wow" I thought I would with the switch.
A few quick final notes. The entire site has not been converted to jQuery. The feeds for example still use CF8 UI stuff. The code zip you can download is also out of date now obviously.
Any comments on my use of jQuery are appreciated, but be gentle as I have a grand total of 2-3 hours experience with it!
p.s. I'd especially appreciate a suggestion on how to handle the "loading" status that I lost when I left cfdiv. Right now it's not immediately apparent that you've begun an AJAX request to load new data.
Archived Comments
Hi Raymond,
As a jQuery fan, it's great to see someone with your standing in the CF community using it because I've been considering working more with Spry and EXT2 instead as they now ship with CF8 and I didn't want to get stuck in the "familiarity" trap of sticking with jQuery when the rest of the CF community has moved on :)
Since Rey Bengo is busy with new a new baby - I'll say it for him - "Go jQuery!"
If you aren't already on the jQuery mailing list - I'd hop on - it's a bit heavy traffic wise but there are lots of CF folks on there as well as lots of people willing to offer advice.
You may want to try the 'min' version instead of the packed version of jQuery. I know there have been discussions on the list about which is better/faster (also depends how your server is setup).
When I tried the first link on the jquery site, which is labeled as minified and 15kb, the link led to a file that was 50ish k, not 15. That's why I switched to the packed one. If you can tell me what I did wrong, I'll replace it.
jQuery rulez.
I'd set a 'loading' message when the load is initiated (before the call to .load) and then hide it in a callback function. Looks like the third argument for .load is a callback handler (http://docs.jquery.com/Ajax....
The 'min' version is a bit bigger - BUT - if your web server doesn't have to spend time unpacking it it's a bit faster, esp. since it gets cached on the browser after the first load.
http://groups.google.com/gr...
So if I get the min version, save it over my JS, it willb e quicker. Magically? (I guess I should read the link.)
@ToddS - would you mind doing a quick demo? :)
@JP - So I don't get it. Do I just get the min version or do I have to get it and zip it?
Grab the jquery.min.js version and just replace the .pack. version you have now...
/js/jquery.min.js
It may be slower on the first load but subsequent loads should be faster as the server won't have to unpack it each time... (read the link) :)
@Raymond:
You want the "Form Plug-in"--that plug-in will allow you to automatically post a form via AJAX (it'll serialize the entire form for you automatically.)
The Form Plug-in will also handle file uploads--which I don't think CF currently does (but I could be wrong.)
Ray,
I am glad you are trying Jquery.
For forms ajax submit try this plugin:
http://www.malsup.com/jquer...
I have a custom tag that can be interested for you on my website for ajax forms using jquery.
Andrea
@DS - I did read it, but didn't quite get it. But it is done. Using the min version now.
@Andrea - trying to avoid plugins for now. So if it isn't built in, I'll stick with my code as is.
Well here is some pseudo code:
Imagine a div where you want to display your 'loading message':
<div id="loadMsg" style="display:none;">Loading...</div>
In your script you'd have:
//i don't know jquery...so use jquery to get the element:
document.getElementById('loadMsg').style.display = 'normal';
$("#content").load(baseurl, "", cbFunc);
cbFunc = function(){
document.getElementById('loadMsg').style.display = 'none';
}
You get the idea (I hope).
But as I said, I'm not a jQuery expert (or even a regular user)...so anyone can feel free to propose a different (better) way.
jQuery has a hide() function built-in, so where Todd used:
document.getElementById("loadMsg").style.display= 'none';
...you could do...
$("#loadMsg").hide();
Personally, I tend to create a CSS class called "hideElement" with the "display:none" style setting, then add or remove that class as needed:
$("#loadMsg").addClass("hideElement");
Nice Brian! Thanks. As a side note for the accessibility crowd - Sandra Clark told me at cf.objective that display:none is not 'accessible' - I forget why (hey I had a few beers at that point) - but I suppose that is a discussion for another day.
Further to Todd's example (which is the way I would do it), you can show and hide the loadMsg div using:
$("#loadMsg").hide();
$("#loadMsg").show();
We just finished a simple e-commerce site using ColdFusion and jQuery for one of our clients: http://www.smallworldbaby.com
Aaaaand... Brian beat me to it :)
I'm going to give this a try. I'll steal a graphic from that ajax-load site and see if I can make this work.
As we all know - it isn't a Web 2.0 site w/o the loading indicator.
Also - I don't think I've seen anyone comment - is the site faster for you guys?
Define 'faster' - no, don't do that...I'm kidding.
It never seemed 'slow' to me...
OMG!!!! Camden is using jQuery! Hell has frozen over!!!! Everyone, take a screencap of this blog post. It's like a bigfoot sighting! ;)
Welcome to jQuery Ray. Let me know if you need some help. Be sure to sign up to the list as well as @jquery & @jqueryui Twitter accounts.
@Jim: Thx for stepping in while I was tending to my new addition :)
Hi Ray,
If/when you get around to using plugins, you'll like the Form plugin that others have mentioned. It's the de facto standard for doing ajax form submits.
It's cool because it's totally unobtrusive. All you have to do is this:
$("#myformid").ajaxForm({ success: callbackfunction });
This binds the ajax submit to the form, picks up the action attribute of the form as the submission url, packs up the form data for you, and returns whatever your server response is to the callback function.
Welcome to jQuery!!!
Oh yeah, also in regards to the "loading" message, there is another plugin called "BlockUI" that handles that sort of thing very nicely - it's by the same author as the Form plugin.
To block a certain element you might do:
$("#mydivtoblock").block();
Then in your callback:
$("#mydivtoblock").unblock();
Guys - reload and comment.
I don't like how the loader is place. But the code was rather simple to do.
Any suggestions on how to place my loader?
@Todd: I believe "display:none;" causes accessibility problems because screen readers will never load any content affected by the style, even when you do display it. I tend to put most of my DHTML in the administrative/internal pages of my applications where accessibility isn't really an issue, but I probably should find a better alternative.
@ Mike Hodgson
Easier to use toggle(), rather than show() and hide().
That way you let jQuery maintain the state of the object for you.
Regarding the loader...maybe you could make it bigger and make it appear in the left side of the banner div (under the Home and Feeds tabs) with a "float:left;" That might look cool.
@Andy: Isn't the toggle() function designed primarily for user-generated events like mouse clicks? I'm not sure it would be appropriate in this case.
I've used it in some of my apps, but there are certain situations you can get into where the current state of the toggle gets out of sync with the state of the object manipulated by the toggle.
@Brian: You can use toggle() to change the display status at anytime, not just user-generated events. In fact, it's best practice to do that since it minimizes the amount of code you write and it actually keeps an internal cache of the last status of the specific element you're toggling
@BS - I made it bigger - and used the float.
If you want to do client side validation try the validation plugin by bassistance, it's the best out there IMO.
Something I didn't see here yet - you can serialize a form without the jQuery form plug-in. Just do this:
$.ajax(url, $("#myForm").serialize(), callback);
Check my favorite reference, visual jQuery: http://visualjquery.com/ - It's under Ajax functions.
@Nathan: Nice code.
@everyone: Please use the API docs on the jQuery site or here (http://remysharp.com/jquery... as they're current.
Shameless Promotional Spot for CFUnited...
http://cfunited.com/go/topi...
That is the session but if you guys want a full load I suggest arriving a day early and attending Hal Helms class.
http://teratech.com/go/trai...
:) Hope to meet other jQuery enthusiasts there also.
@Rey: So how do you invoke the toggle() event without a mouse click? Via the trigger() or triggerHandler() function?
First, it's awesome to see people like you using jQuery, but then many have said that already.
Now, I think you can do better on the 'loading' indicator for the home page - it is still not as 'pretty' as it can be...
I tend to do something like this for ajax links:
$(".mylink").click(function() {
$("#contentdiv").html("<img src='images/ajax-loader.gif' class='loadergif' alt='Loading content...' /> Loading content. Please wait...");
$.get(url, function(data) {
$("#contentdiv").html(data);
}
}
This way you can show the 'loading' image with any text you want. But that is just my way of doing it...
The Feeds page is rather slow, but I think it is not jQuery-based yet, is it? Or maybe it is my Internet connection - it is not really exceptionally fast here in Laos...
As for 'popup' windows - have a look at Thickbox and Impromptu plug-ins. I know you said 'no plugins', but then you did use jqModal...
One other thing is: the site is rather useless with js turned off... Sure, it is a Web 2.0 site, but... still better if it works no matter what the user setting are... At least a 'js turned off!' warning can be helpful.
I know, not many users have js disabled, but nonetheless - even a web2.0 site should be friendly to users who are not quiet web2.0'd yet...
But a great site overall and extremely useful! It has replaced pretty much all the other feeds I used to peruse. Have kept your cfjedi separate, though - I like to get full feed from it, not just 3 first lines :)
@Azadi - I'll try your code out. That's what I wanted really - to make the main div show the loading, and _then_ the real content.
Yes - the feeds page is still cfdiv, but it's more slow due to some bad SQL I haven't gotten around to optimizing yet.
I tend to hide my elements using the jQuery hide method instead of using an inline display:none or setting it in the stylesheet, so that screen readers etc (which don't have js) will read all elements - this should make it accessible.
Good to know that you are exploring JQuery. I am developing stuff using CF for many many years now, but will not opt for CF8 Ajax; just look at the JS includes and JS code you will get.
And why to use JModal (save a http request) you will have flash problems - looking through your form - as you see in your contact form; you can very easily hide the main content and in a seperate div show the form and once submitted display the main content back again.
www.ranglapunjab.net - I have developed it entirely in CF and jQuery
I was really stoked about the cf8 ajax features until I used Firebug and saw all the extra files that were being loaded. That immediately made me changed directions. Right now I'm saving around 300k by going with jQuery/Thickbox instead of cfwindow.
It would be awesome if ajax ui features in future coldfusion releases were more lightweight.
Thanks for posting that Ray. I've been reading up on JavaScript Toolkits/Frameworks for awhile now. I've been highly interested to see someone give Spry & jQuery a thorough usage.
I've dabbled with Spry, and read up on jQuery.
One area that matters a lot to me is documentation. I've found is Spry's documentation is simple, straightforward, and answers what I'm trying to do quickly.
jQuery - I just did a double check... looks like they've come a ways in this area. When I first looked at it, the documentation was just a collection of disparate blog postings. Nice to see the improvements. And they have at least 2 books on the subject available.
In playing around with Spry I found it CRAZY EASY to get into, and like how they support data binding - which I don't think is a feature jQuery supports...?
@Tariq - Agreed. I think the way Spry handles getting and displaying structured data is the best. Period. Afaik, in Jquery, you would need to do some looping and string parsing yourself. Not that it would be impossible of course.
Ray,
Will this mean there will be a new sect of Jedi?
JQJedi's?