Forum Moderators: open

Message Too Old, No Replies

How to close a window if user clicks anything but an <INPUT>?

Works in Safari, not in IE6

         

MichaelBluejay

8:22 am on Jan 19, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I have a little popup window (generated by a click, not auto-spawned, thank you very much). I'd like this window to close if the user clicks anything in the window besides an <INPUT> element. This does the trick nicely, in Safari:

function closer(e) { 
var targ;
if (!e) var e = window.event;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;

targ = targ+'';
if (targ.indexOf('INPUT') <0) window.close();
}
<BODY onclick="closer()">

But in IE6, when I click the link that pops up the window, the text in the original window is replaced by the word [OBJECT], and the popup window closes when I click *anywhere*, including on an <INPUT> object.

The first part of the script is straight out of QuirksMode.org. I added only the last two lines myself.

Any idears? Thankie-doodle, -MBJ-

MichaelBluejay

8:51 am on Jan 19, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Okay, I solved half of my problem and I have a clue about the other one. My main page is no longer replaced by the word [OBJECT] if I call my popup window this way:

 [b]<A href="#" onclick="popathon()">[/b]

instead of this way:

 [b]<A href=javascript:popathon()>[/b]

But I still have that pesky problem of the window closing even when I click an INPUT element. It occurred to me to output the name of the object I'm clicking on with an alert(). (Duh.) When I do that I see the object name is always [object], no matter what I click on. It's not returning the actual name of the object. Well, that explains why the window is closing when I click an INPUT object: IE6 doesn't think I've clicked on an INPUT object. So the question becomes, how can I get the name of the object that was clicked in IE6?

Rambo Tribble

3:20 pm on Jan 19, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Try:

targ = e.srcElement.tagName;

Be aware the returned string is in uppercase.

Rambo Tribble

4:18 pm on Jan 19, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



By the way, given the parameters you expressed, you might try this:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Untitled</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<style type="text/css">
html,body{height:100%}
</style>
<script type="text/javascript">
window.onload=function(){
var bd=document.getElementsByTagName("body");
bd[0].onclick=function(){
var targ=this.tagName;
alert(targ);
}
var inpt=document.getElementsByTagName("input");
inpt[0].onclick=function(){
var targ=this.tagName;
alert(targ);
}
}
</script>
</head>
<body>
<form action="">
<input type="text" value="Click here . . ." />
</form>
<p style="text-align:center;">
. . . and compare it to clicking here.
</p>
</body>
</html>

Rambo Tribble

6:20 pm on Jan 19, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



In case the last post was too cryptic, here's the full solution:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Untitled</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<style type="text/css">
html,body{height:100%}
</style>
<script type="text/javascript">
var tag_flag=false;
function isInp(){
if(this.tagName.toUpperCase().indexOf("INPUT")==-1){
tag_flag==true? tag_flag=false : alert("close this window");
}else{
tag_flag=true;
alert("hands off this window");
}
}
window.onload=function(){
var bd=document.getElementsByTagName("body");
bd[0].onclick=isInp;
var inpt=document.getElementsByTagName("input");
for(var i=0;i<inpt.length;i++){
inpt[i].onclick=isInp;
}
}
</script>
</head>
<body>
<form action="">
<input type="text" value="Click here . . ." /><br />
<input type="text" value="Click here . . ." /><br />
<input type="text" value="Click here . . ." /><br />
</form>
<p style="text-align:center;">
. . . and compare it to clicking here.
</p>
</body>
</html>

Rambo Tribble

11:31 pm on Jan 19, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Actually, you can shorten the isInp() function to (make sure the ternary appears all on one line in your code):


function isInp(evt){
if(!evt)var evt=window.event;
this.tagName.toUpperCase().indexOf("INPUT")!=-1? evt.cancelBubble=true : alert("close this window");
}

Of course, the tag_flag variable becomes unnecessary with this modification.

MichaelBluejay

8:57 am on Jan 20, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Thanks for your help. The multiple posts and the lengthy code really confused me. I think I've distilled it down to the essentials:

function isInput(evt){
if (!evt) var evt=window.event;
this.tagName.toUpperCase().indexOf("INPUT")!=-1? evt.cancelBubble=true : alert("close this window");
}

window.onload=function(){
var theBody=document.getElementsByTagName("body");
theBody[0].onclick=isInput;
var inputTags=document.getElementsByTagName("input");
for (var i=0;i <inputTags.length; i++) {
inpt[i].onclick=isInput;
}
}

But this doesn't work. Even when I click on an INPUT object, the script still fires the "Close the window" alert.
Did I mess up the code somehow?

Rambo Tribble

2:09 pm on Jan 20, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Here's the entire file in its finished form. It works for me on Win XP with IE 6, Moz 1.7.5 and Opera 7.54; the only test it failed was on NN 4 (no surprise, there). Clicking on an input results in no action, clicking anywhere else displays the alert.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Untitled</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<style type="text/css">
html,body{height:100%;}
</style>
<script type="text/javascript">
function isInp(evt){
if(!evt)var evt=window.event;
this.tagName.toUpperCase().indexOf("INPUT")!=-1? evt.cancelBubble=true : alert("close this window");
}
window.onload=function(){
var bd=document.getElementsByTagName("body");
bd[0].onclick=isInp;
var inpt=document.getElementsByTagName("input");
for(var i=0;i<inpt.length;i++){
inpt[i].onclick=isInp;
}
}
</script>
</head>
<body>
<form action="">
<input type="text" value="Click here . . ." /><br /><br />
<input type="text" value="Click here . . ." /><br /><br />
<input type="text" value="Click here . . ." />
</form>
<p style="text-align:center;">
. . . and compare it to clicking here.
</p>
</body>
</html>

MichaelBluejay

10:32 am on Jan 21, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Thanks, this works. Once again, for anyone trying to follow this thread, here is the abbreviated, formatted, and slightly less cryptic JS code:
function isInput(theEvent) { 
if(!theEvent) theEvent=window.event;
this.tagName.toUpperCase().indexOf("INPUT")!=-1? theEvent.cancelBubble=true : alert("close this window");
}

window.onload=function() {
theBody=document.getElementsByTagName("body");
theBody[0].onclick=isInput;
inputFields=document.getElementsByTagName("input");
for(var i=0;i<inputFields.length;i++) {
inputFields[i].onclick=isInput;
}
}

Although it works I can't really follow it at all. I'd prefer to use the original code I posted, if I could just easily discover the name of the clicked object in IE6 so I could test for it. Surely there's an easier way to find the name of a clicked object than all of this? Thanks, -MBJ

Rambo Tribble

1:53 pm on Jan 21, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Actually, the isInput() function is what replaces your original code; the function assigned to the window.onload event is to put event handlers on the body and input elements, a more efficient technique than manually placing onclick tags on each element, but one that shouldn't be strictly necessary. You should still be able to call the isInput() function using onclick attributes on individual elements.

The first line of the isInput() function tests for the event model being used and sets the value of the evt variable accordingly. In the ternary operator's expression, first a test is performed to determine if the target element of the event is an input element. If it is, the event is cancelled (evt.cancelBubble=true) instead of being allowed to bubble up to the body's event handler, otherwise the alert is triggered (naturally, in place of the alert you would put your window closing code).

So, you see, it's really pretty simple, just two lines of code to do the test.

Bernard Marx

12:26 am on Jan 22, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'll butt-in (it's been a while).

document.onclick = function(eMoz)
{
var src = eMoz? eMoz.target : event.srcElement;
if( (src.tagName¦¦"").toUpperCase()!= "INPUT")
alert("CLOSE WINDOW");
}

Howzat?

Put the event handler on the document. This is immediately available, so no need to wait till the page loads. Event bubbling is over by this stage, so we don't need to (

cancelBubble / stopPropagation
).

The W3C interface's

<eventObj>.target
property can sometimes return a text node. These don't have a
tagName
property, so this little parenthesised construction is thrown in..

(src.tagName¦¦"")

..to make sure that we don't cause an error by calling the

toUpperCase
method on
undefined
- we have at least an empty string to call it on.

*!* Replace ¦¦ with unbroken pipe symbols, as usual.

(In fact, all browsers should return the tagName in upper case, but why tempt fate?)

Rambo Tribble

2:56 am on Jan 22, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Quite elegant, Mr. Marx. I might consider actually putting something in the empty string, just so some obscure interpreter somewhere doesn't get flummoxed capitalizing nothingness (sounds a bit like my social life).

MichaelBluejay

8:29 am on Jan 22, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



That is elegant in its beautiticiousness. Thanks!

Rambo Tribble

5:41 pm on Jan 22, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Yes, Mr. Marx, keep this up and I'll be inviting you to all my events.