element attribute affectation behaves like a move instead of a copy

M

Mounir

Hi,

Assume that right and left are multiple select elements. It's about the
following line :

right.options=left.options[j];

It copies the content of left.options[j] into right.options, but
*removes* the content of the first one !

It's hard to google with relevant keywords. Do you know if it's a
normal behaviour of Javascript ?

Tested on Firefox 1.5.x/Windows.

Regards,
 
P

Paul

Mounir said:
Hi,

Assume that right and left are multiple select elements. It's about the
following line :

right.options=left.options[j];

It copies the content of left.options[j] into right.options, but
*removes* the content of the first one !

It's hard to google with relevant keywords. Do you know if it's a
normal behaviour of Javascript ?


Not really a matter of JavaScript but, of the particular DOM being
manipulated by the javascript. I see the behavior you described in
Firefox but, in IE6 it simply removes from the right list.
Tested on Firefox 1.5.x/Windows.

Regards,
What is it that you are actually trying to do ?
 
M

Mounir

right.options=left.options[j];

First, I apologize not have given an HTML sample with my message.

Paul wrote :
Not really a matter of JavaScript but, of the particular DOM being
manipulated by the javascript. I see the behavior you described in
Firefox but, in IE6 it simply removes from the right list.

What ? You mean it doesn't even perform the affectation ?
What is it that you are actually trying to do ?

You know, two multiple selection lists, with "Add", "Add All",
"Remove", "Remove All" buttons, respectively to add from the first list
to the second, to add all from the first list to the second, to remove
one and remove all with same ways.

The behavior of Firefox allows me to not create options instances
(javascript command new Option()), so I wondered if it was indeed a
normal behavior and not some bug in my source code. And as the target
browser is Firefox, that's cool :)

Thank you and regards,
 
P

Paul

Mounir said:
right.options=left.options[j];


First, I apologize not have given an HTML sample with my message.

Paul wrote :
Not really a matter of JavaScript but, of the particular DOM being
manipulated by the javascript. I see the behavior you described in
Firefox but, in IE6 it simply removes from the right list.

What ? You mean it doesn't even perform the affectation ?
What is it that you are actually trying to do ?

You know, two multiple selection lists, with "Add", "Add All",
"Remove", "Remove All" buttons, respectively to add from the first list
to the second, to add all from the first list to the second, to remove
one and remove all with same ways.

The behavior of Firefox allows me to not create options instances
(javascript command new Option()), so I wondered if it was indeed a
normal behavior and not some bug in my source code. And as the target
browser is Firefox, that's cool :)

Thank you and regards,

Ah, that is something I can work with :)
See if this will work for you.

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Select test</title>

<style type="text/css">
#selSwap fieldset{
width: 30em;
height: 10em;
}
#selSwap fieldset div{
display:block;
width: 30%;
float:left;
}
#selSwap fieldset div input, select{
margin-left: 1em;
width: 90%;
font-family: monospace;
}

#selSwap fieldset div input{
height: 1.5em;
margin-top: 0.5em;
}
#selSwap fieldset div select{
height: 10em;
}
</style>


<script type="text/javascript">
function copy(selSrc,selDest){
var opts = selSrc.options;
for(var i=opts.length-1; i>=0; i--){
if(opts.selected){
selDest.appendChild(opts);
}
}
}

function copyAll(selSrc,selDest){
var opts = selSrc.options;
for(var i=opts.length-1; i>=0; i--){
selDest.appendChild(opts);
}
}
</script>

</head>

<body>

<form action="#" id="selSwap">
<fieldset>
<legend>Swaping multiselect fun</legend>
<div>
<select multiple="multiple" name="left" id="left">
<option value="1">Apple</option>
<option value="2">Orange</option>
<option value="3">Banana</option>
<option value="4">Grape</option>
</select>
</div>
<div>
<input type="button" value="Add"
onclick="copy(this.form.left,this.form.right)" />
<input type="button" value="Add All"
onclick="copyAll(this.form.left,this.form.right)" />
<input type="button" value="Remove"
onclick="copy(this.form.right,this.form.left)" />
<input type="button" value="Remove All"
onclick="copyAll(this.form.right,this.form.left)" />
</div>
<div>
<select multiple="multiple" name="right" id="right">
<option value="a">red</option>
<option value="b">orange</option>
<option value="c">yellow</option>
<option value="d">purple</option>
</select>
</div>
</fieldset>
</form>

</body>

</html>
 
R

Richard Cornford

Paul wrote:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<input type="button" value="Add"
onclick="copy(this.form.left,this.form.right)" />
<snip>

You realise that the common HTML shortcut of referencing named and IDed
elements as named properties of the FORM element is non-standard and
should not be expected to be available in XHTML DOMs?

You should probably be suing DOM standard - this.form.elments.left -
(and similar) if you want to script XHTML DOMs.

Richard.
 
P

Paul

Richard said:
Paul wrote:


<snip>

You realise that the common HTML shortcut of referencing named and IDed
elements as named properties of the FORM element is non-standard and
should not be expected to be available in XHTML DOMs?

You should probably be suing DOM standard - this.form.elments.left -
(and similar) if you want to script XHTML DOMs.

Richard.
True
 
R

RobG

Paul said:
Mounir said:
Hi,

Assume that right and left are multiple select elements. It's about the
following line :

right.options=left.options[j];

It copies the content of left.options[j] into right.options, but
*removes* the content of the first one !


The "=" character is an assignment operator, it assigns the value of
the right hand side to the value of the left hand side - it isn't a
"copy" operator.

I guess your quandry is to work out what should happen when a reference
to a DOM element is assigned to the value of another DOM element
reference. To take much of the guesswork out of the equation, use DOM
methods (preferably W3C) when DOM elements are involved.

Of course you still need to test widely to ensure browsers are
compliant with whatever standard you have used.

Not really a matter of JavaScript but, of the particular DOM being
manipulated by the javascript. I see the behavior you described in
Firefox but, in IE6 it simply removes from the right list.

In IE, option elements and DOM just don't like each other, hence the
use of new Option() when creating options rather than createElement. A
DOM version of the above (i.e. to move an option from one select to
another) would be:

right.appendChild(left.options);


Which works fine in Firefox & Safari at least, but not IE.
 
M

Mounir

The "=" character is an assignment operator, it assigns the value of
the right hand side to the value of the left hand side - it isn't a
"copy" operator.

Sure, actually i meant "it copies the reference" by "copies the
content", so an assignment.
I guess your quandry is to work out what should happen when a reference
to a DOM element is assigned to the value of another DOM element
reference.

Yes. But, please, do you have an explanation for this behavior ?
To take much of the guesswork out of the equation, use DOM
methods (preferably W3C) when DOM elements are involved.

Thanks. http://www.w3.org/TR/REC-DOM-Level-1/ seems to be a good
starting point.
Of course you still need to test widely to ensure browsers are
compliant with whatever standard you have used.

Yeah, in first time, I will code for firefox (this is an intrant
applications, which assumes that the browser client will be FF).
In IE, option elements and DOM just don't like each other, hence the
use of new Option() when creating options rather than createElement. A
DOM version of the above (i.e. to move an option from one select to
another) would be:
right.appendChild(left.options);

Which works fine in Firefox & Safari at least, but not IE.


I've just seen in the previous link a pretty method, in
chapter 2: Document Object Model (HTML) Level 1 :

void add(in HTMLElement element, in HTMLElement before)

It seems to be from a set of specific HTML DOM methods. No problem to
use it, right ?

Regards,
 
M

Mounir

Ah, that is something I can work with :)
See if this will work for you.

Thank you :)
I hope you haven't passed much time to do.

Interesting line :
selDest.appendChild(opts);


So appendChild() *removes* the refererence of child from the previous
parent node.

Thanks !

Regards,
 
M

Mounir

I wrote :
Yes. But, please, do you have an explanation for this behavior ?

Err... in Paul's reply (xhtmI file) I think I got the answer... The
assignment behaves like a DOM child moving (i.e. appendChild()). Right
?

Regards,
 
R

RobG

Mounir said:
I wrote :

Err... in Paul's reply (xhtmI file) I think I got the answer... The
assignment behaves like a DOM child moving (i.e. appendChild()). Right

I think the issue is that DOM objects are host objects, you can't
presume their behaviour will be consistent with ECMAScript native or
built-in objects.

Consider:

var objA = new Object();
objA.firstChild = new Object();

var objB = new Object();
objB.firstChild = objA.firstChild;

Outcome: objA.firstChild and objB.firstChild reference the same object.
Now consider something similar in DOM:

<div id="divA><div id="divC"></div></div>
<div id="divB"><div id="divD"></div></div>

<script type="text/javascript">
var divA = document.getElementById('divA');
var divB = document.getElementById('divB');

divB.firstChild = divA.firstChild;

</script>

Outcome: ?

In a pure ECMAScript context, divB.firstChild and divA.firstChild
should both reference divC, the firstChild of divA. However, since a
DOM element can only have one parent, we are left to guess whether[1]:

1. divC replaces divD
2. divD is moved down the DOM tree to make room for divC
3. an error.

If the intention was that divC is inserted as divB's first child, then:

divB.insertBefore(divA.firstChild, divB.firstChild);


is specified in the W3C DOM HTML spec as doing exactly that, no
guesswork. If we'd wanted divC to replace divB's firstChild:

divB.replaceChild(divA.firstChild, divB.firstChild);


The lesson is that where you want a specific DOM behaviour, use DOM
methods to achieve it. That principle can be applied to any host
object - use the host provided methods to manipulate them.

1. Determining the correct behaviour assumes whoever is reading the
code knows that DOM objects/elements are involved, so naming
conventions become very important. Using DOM methods makes it pretty
clear that DOM objects are being manipulated (though if silliness was
the order of the day, someone may have created their own native
ECMAScript objects and methods with the same names as well known host
objects/methods).
 
R

Richard Cornford

RobG wrote:
... . Using DOM methods makes it pretty clear that DOM
objects are being manipulated (though if silliness was
the order of the day, someone may have created their own
native ECMAScript objects and methods with the same names
as well known host objects/methods).

I don't know if that would necessarily be silliness. If the object was a
flexible tree structure properties such as a - childNodes - array,
first/lastChild -, - previous/nextSibling -, - parentNode -, and methods
such as - appendChild -, - removeChild - and - insertBefore -, would be
just the sorts of things it would need. One would hope that the
Identifier to the left of the dots for these methods was named in a way
that made it clear what type of object was being acted upon.

Richard.
 
R

RobG

Richard said:
RobG wrote:


I don't know if that would necessarily be silliness. If the object was a
flexible tree structure properties such as a - childNodes - array,
first/lastChild -, - previous/nextSibling -, - parentNode -, and methods
such as - appendChild -, - removeChild - and - insertBefore -, would be
just the sorts of things it would need. One would hope that the
Identifier to the left of the dots for these methods was named in a way
that made it clear what type of object was being acted upon.

Yes, quite right. I was thinking 'and gave them different behaviours'
but didn't write it. If the intention is to emulate host objects, then
using the same naming scheme is probably good idea (adding a
'getElementById' method to the document object in (old) browsers that
don't natively support it springs to mind).
 

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

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top