...

View Full Version : Cloned selectbox will not refresh content



jmol
01-19-2006, 10:47 AM
I have two selectboxes containing several option.
I am able to move options from one selectbox to the other selectbox (by .insertBefore for example).

However, when I clone those selectboxes, the cloned selectboxes behave incorrect. I am able to move options from one to the other, but they won't show correctly. Only after a browser resize or minimize/maximize window will the selectboxes be 'refreshed' to reflect their real content.

See the following code example. Bottom selectboxes are clones of the top ones.

<HTML>
<HEAD>
<style>
select
{
width: expression(document.body.clientWidth / 3);
height: expression(document.body.clientHeight / 3);
}
</style>
<SCRIPT>
// move selected options from source to destination selectbox
function SwapSelected(oSrc, oDest)
{
var oDestOption = null;
if(oSrc.length > 0)
for(var i=oSrc.length-1; i>=0; i--)
if(oSrc.options[i].selected)
{
oDest.insertBefore(oSrc.options[i]); // object will be moved
}
}

// clone selectboxes to bottom table
function cloneTopSelectboxesToBottom()
{
var oCloneL = oSelBxLeftOne.cloneNode(true); // clone
var oCloneR = oSelBxRightOne.cloneNode(true);

oCloneL.id = "oSelBxLeftTwo"; // mage unique
oCloneR.id = "oSelBxRightTwo";

leftTd.insertBefore(oCloneL); // insert
rightTd.insertBefore(oCloneR);
}
</SCRIPT>
</HEAD>

<BODY onload="cloneTopSelectboxesToBottom();">
Hard coded select/options:
<TABLE>
<TR>
<TD>
<select id="oSelBxLeftOne" multiple="multiple">
<option value='1'>one
<option value="2">two
<option value="3">three
<option value="4">four
</select>
</TD>
<TD>
<INPUT TYPE="button" onclick="SwapSelected(oSelBxLeftOne,oSelBxRightOne);" value="move right"><br>
<INPUT TYPE="button" onclick="SwapSelected(oSelBxRightOne,oSelBxLeftOne);" value="move left">
</TD>
<TD>
<select id="oSelBxRightOne" multiple="multiple">
<option value='5'>five
<option value="6">six
<option value="7">seven
<option value="8">eight
</select>
</TD>
</TR>
</TABLE>
<hr>
Cloned select/options (clones of the top hard coded ones):
<TABLE>
<TR>
<TD id="leftTd" />
<TD>
<INPUT TYPE="button" onclick="SwapSelected(oSelBxLeftTwo,oSelBxRightTwo);" value="move right"><br>
<INPUT TYPE="button" onclick="SwapSelected(oSelBxRightTwo,oSelBxLeftTwo);" value="move left">
</TD>
<TD id="rightTd" />
</TR>
</TABLE>
</BODY>
</HTML>

Only work-around I can think of getting them 'refreshed' by code, is by doing a clone-delete-insert after every move action, like calling the following function at the end of function SwapSelected().

function reFreshClones()
{
var oTmpL = oSelBxLeftTwo.cloneNode(true);
var oTmpR = oSelBxRightTwo.cloneNode(true);
oSelBxLeftTwo.removeNode(true);
oSelBxRightTwo.removeNode(true);
leftTd.insertBefore(oTmpL);
rightTd.insertBefore(oTmpR);
}

As you'll understand, this work-around does not really please me...
Anybody knows how to fix (work-around) this weird behaviour?

Kor
01-19-2006, 04:23 PM
At a first glance you have coded incorrectly the elements. Elements are always appended to the document and, if you wanna catch them by their id, use getElementById() method.

for instance:

var oCloneL = oSelBxLeftOne.cloneNode(true)
should be
var oCloneL = document.getElementById('oSelBxLeftOne').cloneNode(true)

jmol
01-20-2006, 03:19 PM
Ah, I was only testing this in IE and most things work without the getElementById. Bad habbit...
I've changed the script so document.getElementById() is used everywhere, but it's still not working.
I created another smaller testpage that is more 'direct' so it's easier to see what it's doing. Problem is the same though.

The script will clone a selectbox including options. so far so good.
Inserting a new option in the 'original' selectbox works fine.
Inserting a new option in the 'cloned' selectbox does not! Only after resizing the window all new options are shown...

Checking the innerHTML of the page after the insert shows correct html. Seems that after inserting a clone of the select object, the clone object is missing some internal refresh event or something like that?

<HTML>
<HEAD>
<style>
select
{
width: expression(document.body.clientWidth / 3);
height: expression(document.body.clientHeight / 3);
}
</style>
<SCRIPT>
<!--
// clone selectbox
function cloneSelectbox()
{
var oOriginal = document.getElementById('original');
var oClone = oOriginal.cloneNode(true);
oClone.id = "clone";
oOriginal.insertAdjacentElement('afterEnd',oClone);
}

// insert a new option
function insertNewOption(where)
{
var sNewOptionText = document.getElementById('textInput').value;
var oNewOpt = document.createElement('OPTION');
oNewOpt.innerText = sNewOptionText;
oNewOpt.value = sNewOptionText;
document.getElementById(where).insertBefore(oNewOpt);
}
//-->
</SCRIPT>
</HEAD>

<BODY onload="cloneSelectbox();">

<FORM METHOD=POST ACTION="">
<select id="original" multiple="multiple">
<option value='1'>one
<option value="2">two
<option value="3">three
</select>
<br>
<input type='text' id='textInput' />
<input type='button' value='add option original (left)' onclick='insertNewOption("original");' />
<input type='button' value='add option clone (right)' onclick='insertNewOption("clone");' />
</FORM>
</BODY>
</HTML>

Kor
01-20-2006, 03:43 PM
Seems that after inserting a clone of the select object, the clone object is missing

Exactly. You may use the clone only once. To use a clone multiple times you may try:

1. clone the original onload. Don't do any changes yet (except id, in some cases)
2. whenever use the clone, first append it to the root and afterwards clone it again (clone the now-appended-clone). Now change whichever on the appended-clone.

This way you will have a "genuine" clone each time.

Kor
01-20-2006, 04:07 PM
Here's an example of this method:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<script type="text/javascript">
var myclone;
function cloneTab(){
myclone=document.getElementById('tab').cloneNode(true);
}
function insertRow(){
var root = document.getElementById('tab').getElementsByTagName('tr')[0].parentNode;
var row = document.createElement('tr');
var cell = document.createElement('td');
cell.appendChild(document.createTextNode('New Text'))
row.appendChild(cell);root.appendChild(row);
}
function resetTab(){
var tabRoot = document.getElementById('tab').parentNode;
tabRoot.replaceChild(myclone,document.getElementById('tab'))
cloneTab();
}
onload=function(){
cloneTab();
}
</script>
</head>
<body>
<table id="tab" width="200" border="0" cellspacing="2" cellpadding="2">
<tr>
<td bgcolor="#CCCCCC">Text orig</td>
</tr>
<tr>
<td bgcolor="#CCCCCC">Text orig</td>
</tr>
</table>
<br>
<input type="button" value="Insert new row" onclick="insertRow()">
<br>
<input type="button" value="Reset (use clone)" onclick="resetTab()">
</body>
</html>

jmol
01-25-2006, 12:46 PM
Thanks for your reaction Kor, but I have the feeling that we're not talking about the same...

Your example is showing (genuine) cloning of a table.
Cloning tables (or any other objects) is not a problem.
The problem is a cloned selectbox.

In my previous example I tried to give a simple example of the problem. In that example I'm cloning only once (in the onload), so I'm using a genuine clone am I not?
If I create a new selectbox with document.createElement('SELECT'), it's working fine. If I clone an original selectbox, it's not working 'like it should'.

ps
What I need this for is the following: I retrieve an array containing items that are inserted as options of a ('hidden prototype') selectbox. This array can contain a couple of thousand items. (I know, maybe not the kind of data for a selectbox, but for now I need this...) Building the options for this selectbox takes a long time. The user can perform several actions on the selectbox like removing/adding options. To prevent having to build the whole selectbox again (which takes quite some time) when the user wants to revert all actions and start all over again, I keep the selectbox as 'hidden prototype' that I clone when needed. Problem is that the clone is not working like a genuine selectbox...

Jaap

Kor
01-25-2006, 01:43 PM
maybe this article will be of some help... Yes, there might be some problems on cloning select boxes...
http://www.bobbyvandersluis.com/articles/unobtrusivedynamicselect.php



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum