HTML OnMissingImage - With Dynamic Content

This morning Rob Gonda blogged about using the 'onerror' attribute of the <img> tag to display an alternate image if your image does not load. I tried this solution within a dynamic Spry region, and it didn't seem to work. I'm guessing that the onerror is fired once and only once, and since the image src is dynamic (within my Spry region) it is not firing the onerror again so the initial replacement image is loaded.

Thanks to some good discussion in the comments I devised a method to get this to work with my Spry region. It's pretty simple really, just register an observer on the region, and once the region is updated loop over the dataset, checking to see if the image is loaded. If not, replace it with your 'oops' image. Here's some code:

observer = function(type,notifier,data){
   if(type == 'onPostStateChange'){
      var ds = dsName.getData();
      
      for(var i = 0; i<ds.length; i++){
         //assumes you've named your image {ID}_img          
         var id = ds[i].ID + '_img';
         
         //check to see if the image was loaded          
         if(!document.images[id].complete){
             document.getElementById(id).src = 'oops.jpg';
         }
      }
   }
}
Spry.Data.Region.addObserver('regionName', observer);

That's it!

Managing Sessions In CF Ajax Applications

Everyone is likely familiar with standard application logic for managing authenticated sessions with ColdFusion. Typically you do some sort of check inside your Application.cfc file (usually in onRequestStart()) and if the current user is not authenticated (or there session has timed out) you redirect them to a login screen. Nothing new there, but when you think of the nature of an Ajax application you realize that there is a fundamental issue with that concept. What happens if a cfdiv were to be refreshed and the users session has timed out? Well, likely your cfdiv would then contain the results of the redirection (maybe a login.cfm template), but that may not be the 'prettiest' solution depending on your application.

So I put together a quick application to demo one possible solution. The basic concept this:

  • Log a timestamp of the last 'hit' by a given user in their session
  • Create a simple facade that looks at the time difference between the last hit and the current time
  • Create a ajax proxy to query that session facade
  • Make sure the proxy request does not update the 'last hit' - otherwise your session will never time out
  • Run a call to the session facade (via the ajax proxy) on a set interval
  • Evaluate the inactivity period, if in a 'warning' period (say between 15-19 minutes) display a modal window warning the user.
  • If the user chooses to extend the session, ping the session facade which will update the 'last hit' variable.
  • If the inactivity is beyond the session timeout (I usually go with >= 19 minutes display a modal (non-closable) window telling them the session has timed out

I have a demo online here. If you open the demo and wait longer then a minute you'll be warned. Longer then 2 minutes and you're logged out. Full source is attached to this entry. As always, feel free to post questions/comments.

CFGrid Date Picker Editor

A few weeks ago Dan Vega blogged about creating a comboxbox (drop down) cell editor for the editable <cfgrid> before he realized that cfgrid supports in cell drop downs. I commented that I'd like to see something like a date picker cell editor and after using Dan's orginal code as inspiration and some hints from this post by Scott Bennett I finally got the thing working. Yes, I do realize that sometimes it'd just be easier to roll your own Ajax widget from scratch, but sometimes hacking it is more fun.

I'll leave it to Dan and Scott's original posts to explain the details, but here is what you'll end up with:

And here's the code:

<cfsetting showdebugoutput="false">

<cfajaximport tags="cfinput-datefield" />

<html>
<head>
<title>Edit Artist Grid</title>
<link href="/CFIDE/scripts/ajax/ext/resources/css/ytheme-aero.css" rel="stylesheet" type="text/css">

<style>
.x-menu-list{
margin: 0px; padding: 0px;
}
</style>

<script type="text/javascript" src="/CFIDE/scripts/ajax/ext/ext-all.js"></script>

<script type="text/javascript">
function init(){
//grid object
grid = ColdFusion.Grid.getGridObject("ArtistGrid");

//column model
cm = grid.getColumnModel();

//we need to know the column id
stIndex = cm.findColumnIndex("LASTMODIFIED");

var df = new Ext.grid.GridEditor(
   new Ext.form.DateField(
      {
         format: 'm/d/Y',
         minValue: '04/01/08',
      }
   )
);


cm.setEditor(stIndex, df);
cm.setRenderer(stIndex, Ext.util.Format.dateRenderer('m/d/Y'));

grid.reconfigure(grid.getDataSource(),cm);
}
</script>
</head>

<body>



<cfquery name="getArtists" datasource="cfartgallery">
SELECT artistId, firstname, lastname, address, city, state,
postalcode, email, '04/01/2008' as lastModified
FROM Artists
</cfquery>

<cfset args = structNew()>
<cfset args.name = "ArtistGrid">

<cfset args.format = "html">
<cfset args.query = "getArtists">
<cfset args.stripeRows = true>
<cfset args.selectColor = "##D9E8FB">
<cfset args.selectmode = "edit">
<cfset args.onchange = "cfc:artists.editArtist({cfgridaction},{cfgridrow},{cfgridchanged})">

<cfform>
<cfgrid attributeCollection="#args#">
<cfgridcolumn name="artistid" display="false">
<cfgridcolumn name="firstname" header="First Name">
<cfgridcolumn name="lastname" header="Last Name">
<cfgridcolumn name="address" header="Address">
<cfgridcolumn name="city" header="City">
<cfgridcolumn name="state" header="State">
<cfgridcolumn name="postalcode" header="Zip">
<cfgridcolumn name="lastModified" header="Last Modified">
</cfgrid>
</cfform>

<cfset ajaxOnLoad("init")>
</body>
</html>

Progressive Enhancement With ColdFusion 8 Ajax

I've been heavy into some research lately, trying to become more familiar with some advanced concepts. Part of such research has been to learn more about Progressive Enhancement. I wouldn't exactly call myself an expert on the topic, but essentially it's a shift in mindsight from what I've gotten used to with Ajax development over the last year.

[More]

Speaking At April CFUG Meeting

I will be presenting a preview of my cf.objective() presentation 'Integrating ColdFusion 8 Ajax with Model-Glue Applications' at the Cleveland ColdFusion User Group meeting on April 10.

I've been trying to attend more meetings in person but things often come up for me. Brian Meloche and Dan Vega do a great job with the group, so if you're in the area you should try to attend. I believe Brian is also presenting at the April meeting and I think Dan is presenting in May.

Sexy ColdFusion 8 Ajax

Many folks have asked recently how I worked around the - umm - 'plain' look of the ColdFusion 8 Ajax controls. I originally planned on that being a part of my cf.Objective() Ajax presentation, but what the heck, I may as well show it now.

It's actually quite simple. Ext ships with several 'themes'. To use these with your Ajax controls, just include them on your page.

For the 'aero' theme:

<link href="/CFIDE/scripts/ajax/ext/resources/css/xtheme-aero.css" rel="stylesheet" type="text/css">

How 'bout a Vista theme?

<link href="/CFIDE/scripts/ajax/ext/resources/css/xtheme-vista.css" rel="stylesheet" type="text/css">

A few words of caution though. The first caution is to make sure you have all of the latest hot fixes applied for CF 8. There is a fix in one of them that makes sure your user included stylesheets are included after the CF added ones. This is important! (A workaround is to write your stylesheet to the <head> with <cfhtmlhead> - that should put your sheet after the CF stuff). The other thing to watch out for is to make sure the path to the necessary images is not altered (if you move the theme to your project directory instead of pointing at /CFIDE). If you don't maintain the image path, then you will need to change the path in the local stylesheet (and move the images local to your project).

Adding A Minimize Button To Your CFWindow

Here's a quick example of how to add a functional minimize button to your CFWindow.

<script>
createWin = function(){
ColdFusion.Window.create('Window1', 'This is a CF window','win.cfm',{x:100,y:100,height:300,width:400,modal:false,closable:true,collapsible:true,draggable:true,resizable:true,center:true,initshow:true})
//get the Ext window object
var w = ColdFusion.Window.getWindowObject('Window1');
//add the class for the collapse button
w.collapseBtn = w.toolbox.createChild({cls:"x-dlg-collapse"});
//add a listener for the collapse click
w.collapseBtn.on("click", w.collapseClick, w);
//add the class to swap the image on mouse over
w.collapseBtn.addClassOnOver("x-dlg-collapse-over");
}

</script>

<cfset ajaxOnLoad('createWin') />

Demo

Thoughts On Ajax Frameworks And ColdFusion/Adobe

A reader (ironically named Todd) commented on my post yesterday:

I'd also like to see some discussion about Ext vs. Spry.

Dreamweaver CS3 seems to have settled on Spry while CF8 has settled on Ext (1.0). Apparently, Adobe divisions do not talk to each other.

I can't decide between them. I find Ext (at least teh 1.0 version used in CF) to be difficult and frustrating to use. Prototype.js was easy. I haven't yet tried Spry.

[More]

ColdFusion 8 Ajax Feed Reader

If you've ever checked out Ext you've probably seen the feed viewer sample application.

A while back I decided to see how quickly I could recreate that viewer using ColdFusion 8 Ajax. I ended up using some Spry bits for listeners - but overall much of the code is pretty simple. I'm not going to bother posting the code unless someone really wants to see it - I just wanted to get this out there as a cool demo of the power/simplicity of ColdFusion 8 Ajax.

Here it is

Oh - I almost forgot - if you try to view a post from a BlogCFC blog it will bust out of the application and take over your window. This is not a bug but an intentional feature of BlogCFC to keep folks from harvesting your content. If you add a non-BlogCFC feed and try to view a post in a new tab you'll see the feature.

CFDiv - Something To Watch Out For

Was just trying to create a super simple dynamic region on a page when I repeatedly received the following error when I loaded the page:

error:http: Error replacing HTML, element not found: comments

I double check everything and my bind statement looks good. View Source however told me something different. CF correctly included the Ajax 'plumbing' bits to create the div and register it, but my div itself was not in the source. Turns out the template I was working with had the following on line 1:

<cfsetting enablecfoutputonly=true>

So since cfdiv actually is creating a div behind the scenes it did not get output to the page because it wasn't surrounded in a <cfoutput>. Seems strange though because none of the other CF tags that generate HTML (IE cfinput) share this behavior. Unless I'm mistaken?

More Entries

cfunited08

cfunited08

Calendar

Sun Mon Tue Wed Thu Fri Sat
    123
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

Subscribe

Enter your email address to subscribe to this blog.

Tags

actionscript ajax blogging cfsnippets coldfusion flash forms flex misc model-glue off topic personal project learn sql

Recent Comments

Anyone Have A Copy Of Rebar?
369 said: Theres something similar on riaforge, maybe it meets some of what you're looking for? <a href=h... [More]

Applying Effects To CF Ajax Controls Revisited
Calvin said: Very Nice! How would one put cfwindow's name as a variable in to showWin and hideWin functions? T... [More]

Hosting Advice Needed
todd sharp said: Must have been on a box that I'm not on. Thank goodness too, because all of my sites (this blog, cf... [More]

Hosting Advice Needed
Oğuz Demirkapı said: No. And the tickets are still open in support system. :) I think they had a big outage and still ... [More]

Hosting Advice Needed
todd sharp said: Did they say what caused such a long outage? [More]

RSS


coldfusionbloggers

FullAsAGoog MXNA

Consumed By Feed-Squirrel.com