...

View Full Version : using getElementbyID with a popup window



rmedek
03-10-2006, 01:56 AM
I'm trying to adapt an image gallery script detailed in Jeremey Keith's book (http://domscripting.com/) to work with popup windows. The idea is a basic gallery has thumbnails and clicking on one shows a more detailed image in a new, popup window.

The HTML on the gallery page is:


<table id="popupgallery">
<tr>
<td>Description 1</td>
<td>Description 2</td>
<td>Description 3</td>
</tr>
<tr>
<td><a href="/images/image1.jpg" title="image description"><img src="/images/image1_thumb.jpg" width="150" height="100" alt="image description" /></a></td>
<td><a href="/images/image2.jpg" title="image description"><img src="/images/image2_thumb.jpg" width="150" height="100" alt="image description" /></a></td>
<td><a href="/images/image3.jpg" title="image description"><img src="/images/image3_thumb.jpg" width="150" height="100" alt="image description" /></a></td>
</tr>
</table>


The js that creates an onload event and prepares the gallery is:


function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != "function") {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}

function preparePopUp () {
if(!document.getElementsByTagName) return false;
if(!document.getElementById) return false;
if(!document.getElementById("popupgallery")) return false;
var gallery = document.getElementById("popupgallery");
var links = gallery.getElementsByTagName("a");
for (var i=0; i < links.length; i++) {
links[i].onclick = function() {
return popUp(this);
}
}
}

addLoadEvent(preparePopUp);


Now, here's where I get stuck. I'd like to create my new window, assign it a name, and replace different attributes with references to the old window. I'm not sure how that works:



function popUp (whichpic) {
if(document.getElementById) {
newWin = window.open('popup.html','mywin', 'toolbar=no, scrollbars=no, resizable=no, menubar=no, status=no, directories=no, location=no, width=400, height=300');
newWin.document.getElementById('placeholder').src = whichpic.href;
if (whichpic.title) {
newWin.document.getElementById('desc').childNodes[0].nodeValue = whichpic.title;
} else {
newWin.document.getElementById('desc').childNodes[0].nodeValue = whichpic.childNodes[0].nodeValue;
}
return false;
} else {
return true;
}
}


popup.html:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>test</title>
</head>
<body>
<p id="desc">Description goes here</p>
<img id="placeholder" src="/images/placeholder.jpg" alt="" width="350" height="250" />
</body>
</html>

Running everything as-is gives me a "newWin.document.getElementById('placeholder').src has no properties" error which I am assuming is because the js gets fired before the popup is finished loading. But I can't figure out how to run the other half of that function after the page gets loaded. Am I taking the wrong approach here? Do I need a separate function in the new window?

Kravvitz
03-10-2006, 03:11 AM
I suggest you set a global variable in the opener and then run the code the needs the document.getElementById() calls via the onload event handler for the child that checks for the global variable in the opener.

rmedek
03-10-2006, 03:37 AM
I'm sorry Kravvitz, I'm not following. (Keep in mind Javascript is essentially sorcery to me at this point:)) The part I can't wrap my head around is this:


run the code the needs the document.getElementById() calls via the onload event handler for the child that checks for the global variable in the opener

The popup function and the image display function all get called in the original page. If I understand you correctly I would need to put a global variable in the new window, and then wait to fire the script until the variable is loaded. (?) I like the sound of it but I don't know how to go about implementing it.

--RM

Kravvitz
03-10-2006, 04:18 AM
That's not what I said.

I said the global variable goes in the opener, though on second though it could go in the child -- it doesn't matter. The function needs to be called via the onload event of the child.

In popup() you would put something like

newWin.picToShow = whichpic;
newWin.onload = function() {
if(!document.getElementById) return;
document.getElementById('placeholder').src = picToShow.href;
if (picToShow.title) {
document.getElementById('desc').childNodes[0].nodeValue = picToShow.title;
} else {
document.getElementById('desc').childNodes[0].nodeValue = picToShow.childNodes[0].nodeValue;
}
}

http://www.quirksmode.org/js/croswin.html

rmedek
03-10-2006, 06:01 AM
Thanks for the link and the help, Kravvitz!

So after reading PPK's article and trying to combine everything I came up with this. It seems to me it's a bit bloated, but it lets me call everything from the parent page:



var newWin = '';

function popUp (whichpic) {
if(document.getElementById) {
function doit() {
newWin.document.getElementById('placeholder').src = whichpic.href;
if (whichpic.title) {
newWin.document.getElementById('desc').childNodes[0].nodeValue = whichpic.title;
} else {
newWin.document.getElementById('desc').childNodes[0].nodeValue = whichpic.childNodes[0].nodeValue;
}
}
if (!newWin.closed && newWin.location) {
newWin.focus();
doit();
} else {
newWin = window.open('popup.html','mywin', 'toolbar=no, scrollbars=no, resizable=no, menubar=no, status=no, directories=no, location=no, width=450, height=400');
newWin.focus();
newWin.onload = function() {
doit();
}
}
return false;
} else {
return true;
}
}

Essentially it first checks to see if the new window has opened. If it has, it gives the new window focus and runs the rest of the function. If it hasn't, it creates the new window, gives it focus, then waits until it has loaded until it runs the function.

Is this a sane approach? I'm trying to learn this sort of thing the right way from the beginning so if anyone has any tips please let me know...

Beagle
03-10-2006, 02:47 PM
One thing I would recommend is making sure "whichpic" is actually what you think it is.

What if I pass in null, or 5 as the argument? whichpic.title will kill the script.

Before accessing members of whichpic, either check for each individual one's existence:

if (whichpic.title && whichpic.title = "title")

OR, check for the type that whichpic is right at the beginning:

if (typeof whichpic == 'Whatever type you want')

That will make it more fault tolerant.

rmedek
03-10-2006, 08:17 PM
One thing I would recommend is making sure "whichpic" is actually what you think it is.

Do I actually need the other arguments? I get "whichpic" from the function above:


function preparePopUp () {
if(!document.getElementsByTagName) return false;
if(!document.getElementById) return false;
if(!document.getElementById("popupgallery")) return false;
var gallery = document.getElementById("popupgallery");
var links = gallery.getElementsByTagName("a");
for (var i=0; i < links.length; i++) {
links[i].onclick = function() {
return popUp(this);
}
}
}


So I'm not sure how it's possible to get another value other than the link for "whichpic"; of course, this is why I ask these questions. :D

rmedek
03-10-2006, 09:13 PM
So... on testing the script it seems it doesn't work in IE or Safari. The popup page gets loaded but the script never fires past the "newWin.onload" part. If I click on another thumbnail without closing the popup window first, the script does as it's supposed to.

Any ideas on what I am doing wrong?

Kravvitz
03-10-2006, 09:21 PM
Try changing

newWin.onload = function() {
doit();
}
to

newWin.onload = function() {
window.opener.doit();
}
and

function doit() {
to

window.doit = function () {

rmedek
03-10-2006, 09:57 PM
That isn't working…I get a "window.opener' has no properties error.

If I understand you correctly, this approach attempts to prevent the function from running from the child window, but I don't think that would be an issue as the function runs correctly when the window is already opened.

Kravvitz
03-10-2006, 10:22 PM
I thought it might have been a scope problem -- I was wrong.

It looks like window.onload is being triggered after you set it.

I suggest you use setTimeout() instead.
Change:

newWin.onload = function() {
doit();
}
to

setTimeout("doit();",500);

Kor
03-10-2006, 11:07 PM
I dare to suggest you another kind of approach. What if, instead of a popup, you would use a "layer", an element by default displayed 'none', but brought to 'block' with the proper function? Or an iframe?

rmedek
03-10-2006, 11:23 PM
Well, this is a client/designer request for the popup, not mine. The site is essentially a shopping cart; other pages within the site use the technique you mention(actually, the new image is targeted into an existing "placeholder" image)—implemented by a slightly different version of this script—and it's working fine. Only one page has the popup functionality requested.

BTW, the timeout method gives me a "doit is not defined" error. Plus, using timeout seems to be sort of a hack—what if a visitor is on a slow/lagging connection?

Kravvitz
03-10-2006, 11:32 PM
Oops. It's not working because the doIt() was local to the other function. setTimeout() always executes from a global scope.

I suggest you put the contents of the doIt() function in an event handler for window.onload in the popup file itself.

Kor
03-11-2006, 06:20 AM
Well, this is a client/designer request for the popup, not mine. The site is essentially a shopping cart; other pages within the site use the technique you mention(actually, the new image is targeted into an existing "placeholder" image)—implemented by a slightly different version of this script—and it's working fine. Only one page has the popup functionality requested.

BTW, the timeout method gives me a "doit is not defined" error. Plus, using timeout seems to be sort of a hack—what if a visitor is on a slow/lagging connection?

If well graphic designed, a layer might look exactly as a pop-up. Further more, I had a client which asked me exactly the same. I have build for him an iframe (whose content was mainly controlled by a server-side application) which looks exactly like a pop-up... :D ... I have told him about that only about after an year latter, when he was very happy about the fact that his business was extremely efficient due to its web pages... :D :D

rmedek
03-12-2006, 08:26 PM
If well graphic designed, a layer might look exactly as a pop-up. Further more, I had a client which asked me exactly the same. I have build for him an iframe (whose content was mainly controlled by a server-side application) which looks exactly like a pop-up... :D
Funny, although I do find most popup windows annoying (even non-ad ones) I find popup layers even more annoying. :D



I suggest you put the contents of the doIt() function in an event handler for window.onload in the popup file itself
That's most likely what I'm going to end up doing, but out of desparation, not preference.

I find it hard to believe that this sort of thing isn't achievable, or bad practice… :confused:



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum