Simple question about cross-window dropdown list loading

J

Joseph Barron

Here is a SIMPLE problem that I'm trying to solve.
It works in Netscape 6.2, but IE6 gives ""No such interface
supported."

Below are page1.htm and page2.htm .

In page1.htm, there are two dropdown lists. If you change the
selection of the left one (e.g. choose parentoption2), it
should open up page2.htm in a popup window.

page2.htm has its own dropdown list. When this page finishes loading,
the onload() its <BODY> will call copyback() which copies the
contents of that dropdown list to the rightmost dropdown list on
page1.htm. In the blink of an eye, the page2.htm popup window
then closes itself.

So, the end result should be that the right dropdown list in
page1.htm, instead of having "What?","What?","What?" as options
as it does originally, it should end up having childoption1,
childoption2, and childoption3.

*Should* be. I thought the best way to do this "replace one node
with another" is to use replaceChild (in page2.htm).
(Is there a better way of doing it? There is removeChild but it's
not part of W3C, I don't believe.)

(What I'm trying to get out of all this is to have the first
dropdown list hold, say, a list of people. When a person is selected,
the Javascript opens up a second page which will be something
like a Perl or PHP script that connects to a SQL database,
grabs all the phone numbers for that person, puts them in a
temporary dropdown list on that page, then copies that list
to the rightmost dropdown list of the first page.

I know that this must be a very common requirement, but I haven't
yet found any web site that shows code to do exactly this, and
I certainly don't mind being told how I'm doing it all wrong!
)

It works in Netscape 6.2, but not in IE6! At the replaceChild
step in page2.htm, IE6 gives the fatal error
"No such interface supported.", usually followed by the browser
completely terminating (nice).

I don't think the problem is replaceChild per se, as I got the
same error when trying other DHTML stuff like mergeAttributes(),
etc, in the same environment, i.e. I think *possibly* the problem
is that it's not designed to handle this kind of cross-window
copying??

I saw Microsoft KB support article Q237831 which kind of implies
that you can't create stuff in one context (window or frame) and
try to use it in another window or frame.
This is at (note that it's all one line!) :
support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/s
upport/kb/articles/Q237/8/31.ASP&NoWebContent=1

Unfortunately, I tried the example in the article, which the article
says won't work for IE5, but it DOES work for IE6 - at least, it
worked for me. So it's not helping in solving my problem.

What DOES work is if I comment out the
parentnode.replaceChild(newnode,oldnode);
return;
lines in page2.htm, so that it continues and gets to the code
which copies the select list option by option. Unfortunately,
it is far too slow - in certain situations there are going to be
thousands of options in the dropdown list.

----page1.htm----
<html>
<head>
</head>
<body>
<select onchange='window.open("page2.htm","popup","toolbar=no, width=500,
height=250, left=0, top=0")'
name="selectlistparent1" >
<option value="30">parentoption1</option>
<option value="31">parentoption2</option>
</select>
<select
name="selectlistparent2" >
<option value="4">What?</option><option
value="5">What?</option><option value="6">What?</option>
</select>
</body>
</html>
----page2.htm----
<html>
<head>
<script>
<!--
function copyback() {
newnodes=document.getElementsByName('selectlistchild');
newnode=newnodes[0];

oldnodes=opener.document.getElementsByName('selectlistparent2') ;
oldnode=oldnodes[0];
//echodebug('oldnode.nodeName: '+oldnode.nodeName,1);

parentnode = oldnode.parentNode;
// IE6 can't handle this: "No such interface supported."
parentnode.replaceChild(newnode,oldnode);
return;

// -------
// Instead of using replaceChild above, can copy the options
// one by one:

// Empty the recepient dropdown list in the parent window,
// by making a non-deep clone of it, then replacing itself
// with the clone. Then assign 'oldnode' variable to once
// again point to it.
oldnodeclone = oldnode.cloneNode(false);
oldnode.parentNode.replaceChild(oldnodeclone,oldnode);

oldnodes=opener.document.getElementsByName('selectlistparent2') ;
oldnode=oldnodes[0];

// Copy the options from the dropdown list in the child window, to
the
// recepient dropdown list in the parent window.
for (i=0;i<newnode.options.length;i++) {
// This does work to copy them individually. But it's way too
slow.
oldnode.options.length++;
oldnode.options.text = newnode.options.text;
oldnode.options.value = newnode.options.value;
}

window.close();

}

// -->
</script>
</head>
<body onload="copyback()">
<select name="selectlistchild" >
<option value="1">childoption1</option>
<option value="2">childoption2</option>
<option value="3">childoption3</option>
</select>
</body>
</html>
 
Y

Yep

In the blink of an eye, the page2.htm popup window
then closes itself.

What about using a hidden (i)frame? Logic remains the same, and you
avoid blinking (moreover window.open may is not safe in an Internet
env). If you're sure of your env you could also use XmlHttpRequest I
think.
It works in Netscape 6.2, but not in IE6! At the replaceChild
step in page2.htm, IE6 gives the fatal error
"No such interface supported.", usually followed by the browser
completely terminating (nice).

Well, I've got IE5.5 and get the same results, as you note here...
I saw Microsoft KB support article Q237831 which kind of implies
that you can't create stuff in one context (window or frame) and
try to use it in another window or frame.

.... this is a normal behavior, the real pain is that IE doesn't
currently support advanced DOM2 features (also note that DOM2 offers
an importNode method and DOM3 adoptNode method for the Document
interface, which would please you if supported).
What DOES work is if I comment out the
parentnode.replaceChild(newnode,oldnode);
return;
lines in page2.htm, so that it continues and gets to the code
which copies the select list option by option.

That's unfortunately the generally accepted solution, regarding your
code I'd just recommend not to use window.open in the onchange handler
(you'll prevent any keyboard navigation for the select, such as arrows
and letters) and use getElementById over getElementsByName.
Unfortunately,
it is far too slow - in certain situations there are going to be
thousands of options in the dropdown list.

Maybe re-think your process then (functional solution), do some
intermediate layer, select boxes with thousands entries aren't
generally appreciated; or just have the server sends a parseable
string and have innerHTML write it (technical solution). This could be
much faster than DOM manipulation, and (probably) more cross-browser.
The result is impressive in IE (7 times faster), correct in Mozilla
(1.5 times faster) and not worth it in Opera 7 (DOM manipulation a bit
faster, innerHTML doesn't seem to communicate directly with the
parser):

<script type="text/javascript">
function f(){
var d=document;
var s=d.createElement("select");
for(var ii=0; ii<1000; ii++){
var opt=d.createElement("option");
opt.value="v"+ii;
opt.text="t"+ii;
s.appendChild(opt);
}
document.getElementById("test").appendChild(s);
}
function g(){
var s="<select>";
for(var ii=0; ii<1000; ii++)
s+="<option value='v"+ii+"'>t"+ii+"<\/option>";
document.getElementById("test").innerHTML=s+"<\/select>";
}
function runTest(){
var d1=new Date();
f();
var d2=new Date();
g();
var d3=new Date();
alert("f:"+(d2-d1)+"\n"+"g:"+(d3-d2));
}
</script>
<div id="test"></div>
<input type="button" onclick="runTest()" value="test!">


A quick script follows as illustration (if you happen to go for this
conception or something similar, I'd however suggest that you adopt a
more structured approach defining clearly the interface and message
objects):


page1.htm
<script type="text/javascript">
function generate(where, what){
switch (where) {
case "csel" :
var parts=what.split(":"), buf=["<select>"];
for(var ii=0; ii<parts.length; ii+=2){
buf.push(
"<option value='"+parts[ii]+"'>"+
parts[ii+1]+
"<\/option>"
);
}
document.getElementById("csel").innerHTML=buf.join("");
break;
}
}
function test(){
//document.getElementById("csel").innerHTML="Loading...";
frames.buffer.location.href='page2.htm';
}
</script>

<input type="button" value="load!" onclick="test()">
<div id="csel">
<select>
<option value="4">What?</option>
<option value="5">What?</option>
<option value="6">What?</option>
</select>
</div>
<iframe width="0" height="0"
style="visibility:hidden" name="buffer"></iframe>



page2.htm (server's response):
<html>
<head>
<title></title>
<script type="text/javascript">
window.onload=function(){
var db=document.body;
if(top.generate && db)
top.generate("csel",db.innerHTML);
}
</script>
</head>
<body>
value 1:child 1:value 2:child 2:value 3:child 3
</body>
</html>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top