A reader Paul wrote me and described an issue he was having with the jQuery UI date picker. It worked in a form embedded on his page but refuses to work within a CFWINDOW. Let's look at an example of what he tried and I'll explain what went wrong and how to fix it.
To begin with, I'll create a page that uses a date picker within a form on the page. This is just to ensure a simple use case works.
<html>
<head>
<link rel="stylesheet" href="/jquery/jqueryui/css/smoothness/jquery-ui-1.7.1.custom.css" type="text/css" media="screen" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="/jquery/jqueryui/js/jquery-ui-1.7.1.custom.min.js"></script>
<script>
$(document).ready(function() {
$("#dob").datepicker()
})
</script>
</head>
<body>
<h1>Foo</h1>
<form>
<input type="text" name="dob" id="dob"><br/>
</form>
</body>
</html>
I've blogged about jQuery UI before (although I don't think I've blogged on just the date picker) so I won't explain each and every line. The basic gist is - load in jQuery, load in the jQuery UI library, and load in the jQuery UI CSS. Next, use the selector for the input field we want to turn into a datepicker and run the .datepicker function on it. I love how simple that is!
Alright - now let's add a CFWINDOW to the picture:
<cfajaximport tags="cfwindow" />
<html>
<head>
<link rel="stylesheet" href="/jquery/jqueryui/css/smoothness/jquery-ui-1.7.1.custom.css" type="text/css" media="screen" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="/jquery/jqueryui/js/jquery-ui-1.7.1.custom.min.js"></script>
<script>
function showDateWindow() {
ColdFusion.Window.create('dateWin','Title', '/test5.cfm',{x:100,y:100,height:300,width:350,modal:true,closable:false, draggable:true,resizable:false,center:true,initshow:false,refreshOnShow:true});
ColdFusion.Window.show('dateWin')
}
$(document).ready(function() {
$("#dob").datepicker()
console.log('ran')
$("#showWin").click(showDateWindow)
})
</script>
</head>
<body>
<h1>Foo</h1>
<form>
<input type="text" name="dob" id="dob"><br/>
<input type="button" id="showWin" title="Show Window" value="Show Window">
</form>
</body>
</html>
Going from top to bottom - the first change I made was to use cfajaximport to let ColdFusion know I'd need JavaScript support for cfwindow. I added a new function, showDateWindow(), which defines the window I'll create. jQuery's document.ready function is told to listen for a click event on the showWin button, and finally, I add that button to the form.
Now for the interesting part. Let's look at test5.cfm, where my cfwindow content is loaded.
<h1>Inner Form</h1>
<form>
<input type="text" name="innerdob" id="innerdob"><br/>
</form>
I've got a super simple form with one field - innerdob. So what happens if I add datepicker support for this to document.ready?
$(document).ready(function() {
$("#dob").datepicker()
$("#innerdob").datepicker()
console.log('ran')
$("#showWin").click(showDateWindow)
})
This is exactly what Paul tried first and it failed completely. Why? Remember that $(document).ready is the same as: "Listen for the page to load and then do this..." When the page loaded, our cfwindow didn't actually exist yet.
The first suggestion I made to Paul was to look at the CFML Reference for the Ajax functions and see if there was a function you could run to add an event listener to the cfwindow loading. There was - ColdFusion.Window.onShow. We modified the code to create the window to the following:
function showDateWindow() {
ColdFusion.Window.create('dateWin','Title', '/test5.cfm',{x:100,y:100,height:300,width:350,modal:true,closable:false, draggable:true,resizable:false,center:true,initshow:false,refreshOnShow:true});
ColdFusion.Window.onShow('dateWin',doShow)
ColdFusion.Window.show('dateWin')
}
function doShow() {
$("#innerdob").datepicker()
console.log('doShow()')
}
Did that work? Nope! And it's kind of obvious if you get picky about the names. I didn't really see why though till I added:
<cfset sleep(5000)>
to my page loaded in via cfwindow. What you see when clicking the button to create the window is that as soon as the window is shown, doShow is run, but the content still isn't loaded yet. What we need is something like ColdFusion.Window.onPageLoaded or somesuch. While we don't have that - we have something else - ajaxOnLoad. I modified test5.cfm like so:
<cfset ajaxOnLoad("winLoaded")>
<h1>Inner Form</h1>
<form>
<input type="text" name="innerdob" id="innerdob"><br/>
</form>
and in my main window added winLoaded:
function winLoaded() {
console.log('winLoaded()')
$("#innerdob").datepicker()
console.log('made the date')
}
By the way, please remove the console.log statements if you make use of my code. I'm a huge believer in using logging everywhere during testing. So this finally worked... kinda. When it ran, the date picker ended up being behind the window. -sigh- So close! A quick Google search turned up posts from other people having the same problem. Not with cfwindow per se, but with the jQuery Dialog UI, which is pretty similar to cfwindow. The solution then is to add CSS to set the date picker UI to be above anything else in the DOM:
<style>
#ui-datepicker-div {
z-index:10000;
}
</style>
And with that - it worked. The complete template is listed below.
<cfajaximport tags="cfwindow" />
<html>
<head>
<link rel="stylesheet" href="/jquery/jqueryui/css/smoothness/jquery-ui-1.7.1.custom.css" type="text/css" media="screen" />
<style>
#ui-datepicker-div {
z-index:10000;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="/jquery/jqueryui/js/jquery-ui-1.7.1.custom.min.js"></script>
<script>
function showDateWindow() {
ColdFusion.Window.create('dateWin','Title', '/test5.cfm',{x:100,y:100,height:300,width:350,modal:true,closable:false, draggable:true,resizable:false,center:true,initshow:false,refreshOnShow:true});
ColdFusion.Window.onShow('dateWin',doShow)
ColdFusion.Window.show('dateWin')
}
function doShow() {
console.log('doShow()')
}
function winLoaded() {
console.log('winLoaded()')
$("#innerdob").datepicker()
console.log('made the date')
}
$(document).ready(function() {
$("#dob").datepicker()
console.log('ran')
$("#showWin").click(showDateWindow)
})
</script>
</head>
<body>
<h1>Foo</h1>
<form>
<input type="text" name="dob" id="dob"><br/>
<input type="button" id="showWin" title="Show Window" value="Show Window">
</form>
</body>
</html>
Archived Comments
This is untested, but you may also be able to attach an event listener to the window's 'update' event, which is triggered after it is loaded/reloaded with remote content:
function showDateWindow() {
ColdFusion.Window.create('dateWin','Title', '/test5.cfm',{x:100,y:100,height:300,width:350,modal:true,closable:false, draggable:true,resizable:false,center:true,initshow:false,refreshOnShow:true});
ColdFusion.Window.onShow('dateWin',doShow);
ColdFusion.Window.getWindowObject('dateWin').getUpdater().on('update',function(){// now set the datepicker});
ColdFusion.Window.show('dateWin');
}
Something like that.
I hate to be the voice of reason and the dullard who still likes tags over about everything but what is wrong with using ColdFusion's datefield? Is there some reason that we don't know about as to why it couldn't be used in this form? Not trying to criticize but that would be the simplest solution.
The heathen has profaned against the One True Way. The heathen shall be smited!
This is what I typically tell people. The built in Ajax UI controls in CF are VERY nice. If you want to do _more_ with them, and are an experienced Ajax developer, I think it makes more sense to roll your own - simply to ensure you have the control necessary over the final result. CF goes a long way to giving you hooks to stuff (see Cutter's use of getWindowObject), but at the end of the day, I'd rather do it myself.
Using the datefield option requires the form type to be flash, correct? That is one reason I can think of to use JQuery UI over the datefield especially when developing for possible use on Railo or Blue Dragon.
Yeah, the built in datefield uses flash, and it also looks really out of place compared a modern JS date picker. I was very sad when I saw that despite using ExtJS for layouts and things like that, CF was still using the old flash date picker...
BTW, my current LylaCaptch phrase is a word that would probably be filtered out if I put it in the comment :)
I tried to run this as is and get an error in IE, fireFox gives no error but neither will display the window when button is clicked on.
See it here (and its code): http://searisen.com/test/te...
@John: No. It CAN use Flash, but there is an Ajax/HTML version as well.
@Jon: Your wrong - kinda. ;) You can do Flash based datefields, but since CF8 we have had a pure Ext/JS one.
@Chuck: When I view source on your page I see nothing. Are you sure you used the code exactly as I had it?
@Ray
You've pretty much gone from trusted adviser status to MCP. I'm also convinced that if Adobe included a control called cfTurd and then a year later the people at jQuery came up with one called jTurd you would recommend jTurd over cfTurd hands down. Your next tat should depict SARK and the MCP standing over a defenseless CFBot beating it with a virtual jHammer.
And by the way, I'm just kidding, I'm really starting to dig jQuery. However, I've noticed that a lot of people are quick to pull out the nuke when a simple pistol will do the job. If the reader was so damn intent on using the jQuery datepicker then he should've made his form in a jQuery dialog window instead of using cfwindow. Anyway, this has kept me from falling asleep at my desk as well as allowed me to work TRON references into your blog's search engine forever; and for that - I'm grateful.
That is easily one of the best comments I've seen on my blog - and for the record - the MCP was the best computer villain ever. That stupid "Architect" in the Matrix was a wuss.
So to be clear - I have - and have said publicly - a HUGE amount of respect for the Ajax UI components in CF8+. I think they are wonderful. But at the same time I think they are meant more for people who are new, or not familiar with, Ajax frameworks. (And I speak specifically about the UI stuff. The plumbing stuff is great for all use cases.)
That being said, Andy, I think you make a great point. I'm not sure I'd advocate the "mix" that the developer did here. I'd either go CFAjaxUI all the way or jQuery all the way.
Personally I feel like I'm still a newbie Ajax developer. I've only been doing it for about 2.5 years now and it still feels very fresh to me. That's my way of saying I may totally disagree with this comment next year. :)
Aww shucks, that's a decent point. I guess I'll get up and remove the darts from your photo.
@Ray,
My site was down for apparently for a bit, not sure why HMS had it down as it checked into a problem I was having with a tag I was using to display the code. It's up now.
@Chuck: If you look at your error console, you see:
Error: $("#dob").datepicker is not a function
Source File: http://searisen.com/test/te...
Line: 50
Which means datepicker may not exist in your copy of jquery ui. Remember that you can customize the download. You may want to reget the JS and ensure you get the complete package.
Woah - no - your link to jqueryui isn't valid. You either used the wrong url or didn't download the file at all. :) FYI, Firebug showed me this in two seconds - just use the Net tab, All.
In a few projects we tried going with the built in datepicker that uses the yui library but it has issues with hiding under form fields in IE so we ended up switching it out with a jQuery one or a home built one. And there was issues with having the datepicker initializing correctly in modal windows in IE
I don't know this one is good option or not but I am generally using this method in such case.
function showDateWindow() {
ColdFusion.Window.create('dateWin','Title', 'test5.cfm');
ColdFusion.navigate("test5.cfm",'dateWin',winLoaded);
}
I am using ColdFusion.navigate method which allow us to configure callbackhandler function which will automatically call when test5.cfm is loaded in cfwindow and it doesn't require any ajaxonload function call on test5.cfm page. This will useful when test5.cfm is called from different pages.
@Ray: Really? I could swear that the last time I tried to do a <cfform/> for HTML with a date field, it still came up as a flash based date picker. I guess I'll have to look at that one again.
Make sure you specify format=html in the form tag. Or type=html. Whatever - you get the idea. :)
I have a question
I have a feature on my site that loads a Youtube video VIA CFWINDOW. The only problem that I am facing is the video continues to play even thou the window is closed. Is there anyway to clear the CFWINDOW once the window is closed?
Thanks a million
You may want to use ColdFusion.Window.destroy. This function is documented in the 801 release notes PDF, but unfortunately missing from the CF9 reference manual.
Thank's Raymond for this tip.
For me (in CF9) it worked only if I used
div.ui-datepicker {
z-index: 9999 !important;
font-size:10px;
}
But there's still a problem and I can't figured out how to deal with it. In IE 9, if I use datepicker like this:
$("#innerdob").datepicker({
dateFormat: 'dd/mm/yy'
, changeMonth: true
, changeYear: true
, yearRange: '1950:2012'
, minDate: new Date(1950, 01, 01)
, maxDate: new Date(2012, 12, 31)
});
the changeMonth and changeYear does not appear. Is there a way to make this fixed?
Thank you.
Best thing I can recommend is filing a bug report on it. Since IE9 wasn't out when CF9 came out, it probably wasn't tested.
hi, a demo page might be too much to ask but can you please at least include a downloadable working templates?
I don't know where the original source files are - this post is now four years old - but if you use "View Plain" you can copy and paste.