Posted in jQuery, ColdFusion | Posted on 11-10-2009 | 6,321 views
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.
2
3<head>
4<link rel="stylesheet" href="/jquery/jqueryui/css/smoothness/jquery-ui-1.7.1.custom.css" type="text/css" media="screen" />
5<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
6<script src="/jquery/jqueryui/js/jquery-ui-1.7.1.custom.min.js"></script>
7<script>
8
9$(document).ready(function() {
10 $("#dob").datepicker()
11})
12</script>
13</head>
14
15<body>
16
17<h1>Foo</h1>
18<form>
19<input type="text" name="dob" id="dob"><br/>
20</form>
21
22</body>
23</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:
2<html>
3
4<head>
5<link rel="stylesheet" href="/jquery/jqueryui/css/smoothness/jquery-ui-1.7.1.custom.css" type="text/css" media="screen" />
6<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
7<script src="/jquery/jqueryui/js/jquery-ui-1.7.1.custom.min.js"></script>
8<script>
9function showDateWindow() {
10 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});
11 ColdFusion.Window.show('dateWin')
12}
13
14
15$(document).ready(function() {
16 $("#dob").datepicker()
17 console.log('ran')
18 $("#showWin").click(showDateWindow)
19})
20</script>
21</head>
22
23<body>
24
25<h1>Foo</h1>
26<form>
27<input type="text" name="dob" id="dob"><br/>
28<input type="button" id="showWin" title="Show Window" value="Show Window">
29</form>
30
31</body>
32</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.
2<form>
3<input type="text" name="innerdob" id="innerdob"><br/>
4</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?
2 $("#dob").datepicker()
3 $("#innerdob").datepicker()
4 console.log('ran')
5
6 $("#showWin").click(showDateWindow)
7})
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:
2 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});
3 ColdFusion.Window.onShow('dateWin',doShow)
4 ColdFusion.Window.show('dateWin')
5}
6
7function doShow() {
8 $("#innerdob").datepicker()
9 console.log('doShow()')
10}
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:
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:
2
3<h1>Inner Form</h1>
4<form>
5<input type="text" name="innerdob" id="innerdob"><br/>
6</form>
and in my main window added winLoaded:
2 console.log('winLoaded()')
3 $("#innerdob").datepicker()
4 console.log('made the date')
5}
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:
2#ui-datepicker-div {
3 z-index:10000;
4}
5</style>
And with that - it worked. The complete template is listed below.
2<html>
3
4<head>
5<link rel="stylesheet" href="/jquery/jqueryui/css/smoothness/jquery-ui-1.7.1.custom.css" type="text/css" media="screen" />
6<style>
7#ui-datepicker-div {
8 z-index:10000;
9}
10</style>
11<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
12<script src="/jquery/jqueryui/js/jquery-ui-1.7.1.custom.min.js"></script>
13<script>
14function showDateWindow() {
15 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});
16 ColdFusion.Window.onShow('dateWin',doShow)
17 ColdFusion.Window.show('dateWin')
18}
19
20function doShow() {
21 console.log('doShow()')
22}
23
24function winLoaded() {
25 console.log('winLoaded()')
26 $("#innerdob").datepicker()
27 console.log('made the date')
28}
29
30$(document).ready(function() {
31 $("#dob").datepicker()
32 console.log('ran')
33
34 $("#showWin").click(showDateWindow)
35})
36</script>
37</head>
38
39<body>
40
41<h1>Foo</h1>
42<form>
43<input type="text" name="dob" id="dob"><br/>
44<input type="button" id="showWin" title="Show Window" value="Show Window">
45</form>
46
47</body>
48</html>


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.
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.
BTW, my current LylaCaptch phrase is a word that would probably be filtered out if I put it in the comment :)
See it here (and its code): http://searisen.com/test/testCFWindow.cfm
@Jon: Your wrong - kinda. ;) You can do Flash based datefields, but since CF8 we have had a pure Ext/JS one.
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.
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. :)
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.
Error: $("#dob").datepicker is not a function
Source File: http://searisen.com/test/testCFWindow.cfm
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.
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.
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
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.
[Add Comment] [Subscribe to Comments]