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.
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.
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.
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.
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.
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
#1 by Gabe on 3/10/08 - 7:23 AM
cfwindow needs to close itself and refresh a div on the main page via innerHTML. I can get the js to work perfectly with a popup but I am
constantly getting "error processing javascript in markup for element winName_body". Can you offer any help?
#2 by Dave Ferguson on 3/10/08 - 8:14 AM
#3 by Gabe on 3/10/08 - 9:14 AM
that will allow me to close the cfwindow automatically via js?
This issue has been driving me crazy :)
#4 by Dave Ferguson on 3/10/08 - 9:26 AM
#5 by Gabe on 3/10/08 - 12:16 PM
access a div within the main document but [opener.document.getElementByID("divName")] or [parent.getElementByID("divName")] doesn't seem to work.
Also when I try to use ColdFusion.Window.Close(name of window that conatins the iframe), I get a js error that says "coldfusion is undefined"
#6 by Mark on 7/23/08 - 1:11 PM
window using js. Was already doing the unique window creation using a random nub
om number but I like the counter idea better. I am having issues however
when I try to access form variables from the window in the parent page, only
on subsequent windows the first window always works fine. It is as if js gets
confused somehow... I have had to resort to forcing a reload of the parent
which is not ideal. Have you tried working with cfforms in your cfwindow?
The form works consistantly and pulls data in from a query (based on a js var
I pass as I have my grid bound using the proxy) it is just the issue with the
parent page not recognizing the form vars except for the initial cfwindow.
Hope that all makes sense! All in all really happy with CF8 and the Ext js lib.
Thanks again for the great post and any ideas regarding my issue are
welcome.
js control from the parent that I am struggling with
#7 by Andy on 1/25/12 - 10:47 AM