One of the new features in CF8 is the ability to create windows. These are great alternative to using pop-ups as they can't blocked buy a pop-up blocker. They also have a modality option so users cant interact with anything but the window content. They do have some drawbacks though. For example, their shadow effect does not look right in IE6. This is because IE6 does not handle PNG transparency. Other issues are that you can't truly destroy a window. You can run a destroy command on it but it just destroys the reference to it. You can actually still reference the non existent window's content by using getElementById.

One of the things that always bugged me was the close action on the window. I loved the fact that the window had a standard close on the top right and I did not have to code my own close function. However, as I got into more complex items I found it necessary to want to override the windows close action. I wanted a way to trap the fact that the user was closing the window and not just close it.

So, after many hours of trial and error. Then doing a dump of the window object into the cfajaxdebugger I was able to figure it out. BTW... I would not suggest dumping the window object into the cfajaxdebugger. It took almost 15 minutes for it to render the content in the debugger. That was after it crashed my browser twice while trying to do it.

So, let me first show you all the code then I'll walk you through what it does.

view plain print about
1<CFAJAXIMPORT TAGS="CFWINDOW">
2
3<SCRIPT>
4
5    winCounter = 1;
6    winName = "window"+winCounter;
7    
8    function loadWindow(width, height, url, winTitle, closeFunc){
9    
10        winH = height;
11        winW = width;
12        winURL = url;    
13    
14        try{
15            ColdFusion.Window.getWindowObject(winName).destroy();
16        } catch (err) {}
17    
18    
19        winName = "window"+winCounter;
20        winCounter = winCounter+1;
21        ColdFusion.Window.create(winName, winTitle, winURL, {refreshOnShow:true,height:winH,width:winW,modal:true,closable:true, draggable:false,resizable:false,center:true,initshow:true});
22        
23        //document.getElementById(ColdFusion.Window.getWindowObject(winName).header.id).className = "windowHdr";
24        ColdFusion.Window.getWindowObject(winName).close.removeAllListeners();
25        document.getElementById(ColdFusion.Window.getWindowObject(winName).close.id).innerHTML='<SPAN style="width=16px; height:16px" onclick="JAVASCRIPT: ' + closeFunc + '();" class="" id="winCloseReplace"></SPAN>';
26        document.getElementById("winCloseReplace").className = document.getElementById(ColdFusion.Window.getWindowObject(winName).close.id).className;
27        document.getElementById(ColdFusion.Window.getWindowObject(winName).close.id).className = "";    
28    }
29    
30    
31    function closeWin(){
32        try{
33        ColdFusion.Window.getWindowObject(winName).destroy();
34        } catch (err) {}    
35    }
36
37    function doShowWindow(){
38        var title = "Window Title";
39        var path = "/blank.htm";
40        loadWindow(800, 500, path, title, 'trapClose');    
41    }
42    
43    function trapClose(){
44        if (confirm("You sure you want to close this window?")){
45            closeWin();
46        }
47    }
48    
49</SCRIPT>
50
51
52
53<SPAN onClick="doShowWindow();" STYLE="cursor:pointer;">OPEN WINDOW</SPAN>

The first thing we do is use cfajaximport to import the cfwindow code. As you will see I am using javascript to create the windows so using cfajaximport is required.

After that we have a javascript function to create the window. This is a unique way to do it in my opinion. This allows me to generate multiple windows of different sizes and content without dealing with the caching issues of cfwindow.

view plain print about
1function loadWindow(width, height, url, winTitle, closeFunc){}

Next I set some vars then try and destroy the previous window. Since the window naming is sequential this will delete the previously created window. I also allows me to overcome some weird caching and resizing issues with cfwindow.

view plain print about
1try{
2ColdFusion.Window.getWindowObject(winName).destroy();
3        } catch (err) {}

The next step is to create the window name and then create the window. Again, I am using dynamic window naming so each window create is unique.

view plain print about
1winName = "window"+winCounter;
2        winCounter = winCounter+1;
3        ColdFusion.Window.create(winName, winTitle, winURL, {refreshOnShow:true,height:winH,width:winW,modal:true,closable:true, draggable:false,resizable:false,center:true,initshow:true});

Now this next chunk of code is to override the close action of the window. I still show the close in the top right but I replace the existing close function with my own. There may be an easier or more elegant way to do this but I found that this seems to work. What I am doing is removing the existing listeners on the close div. Inserting my own span inside the close div and setting an onclick to my function. I then set the class of the span to the class of the close div then remove the class on the close div. I discovered that the listener is listening for a click on close div with a specific class. Since I have placed an span into the div it gets the click first and the click action does not make it to the parent div. Thus overriding the close action of the window. I have experimented removing parts of this code but it appears that they all need to be there for it work as expected.

view plain print about
1ColdFusion.Window.getWindowObject(winName).close.removeAllListeners();
2        document.getElementById(ColdFusion.Window.getWindowObject(winName).close.id).innerHTML='<SPAN style="width=16px; height:16px" onclick="JAVASCRIPT: ' + closeFunc + '();" class="" id="winCloseReplace"></SPAN>';
3        document.getElementById("winCloseReplace").className = document.getElementById(ColdFusion.Window.getWindowObject(winName).close.id).className;
4        document.getElementById(ColdFusion.Window.getWindowObject(winName).close.id).className = "";

Then I just have a function to close the window, function to call the function to create the window, and the function that replaced the window's close action.

So there you have it. Dynamic window creation and a way to override the close action. There may be other or better ways to do this. If you have discovered a better way to do any of this please let me know.

Till next time,

--Dave