Copying javascript objects (select.option[x] really)

JavaScript and client side scripting.

Moderator: General Moderators

Post Reply
User avatar
Heavy
Forum Contributor
Posts: 478
Joined: Sun Sep 22, 2002 7:36 am
Location: Viksjöfors, Hälsingland, Sweden
Contact:

Copying javascript objects (select.option[x] really)

Post by Heavy »

I have options in an HTML-form select that I create with specific styles:

Code: Select all

function SpecialOption(obj, text, val, bold, multiple){
		obj.value = val
		obj.text = text
		obj.className =  (bold ? 'optIsGroup' : '') + ' ' +  (multiple ? 'optIsMultiple' : '')
		obj.selected = false
		return obj
	}
	
	function populateItemsLeft(){
		var leftSel = element('selItemsLeft')
	
	<tpl tpl="foreach(identities_varsets:arrAvailableVarGroups as rowVarGroup)">
		leftSel.options[leftSel.length] = SpecialOption(new Option(), 
			'{rowVarGroup:strName jsencode}', 
			{rowVarGroup:ID}, 
			{rowVarGroup:Explicit},
			{rowVarGroup:isMultiple}
			)
	</tpl>
	}
The <tpl> stuff has to do with my templating engine. I suggest you don't care about it. It's off topic anyway.
the SpecialOption() sets style to the options informting the user about certain meanings of that option.

Then (and here comes the problem) I want to move options up and down in the "multiple select box". I use a copy approach like this:

Code: Select all

function moveDn(){
		var sel = element('selItemsIncluded');
		var c = sel.length
		var options = sel.options
		for (var a = c - 1; a > 0 ; a--){
			if(options[a-1].selected && !options[a].selected){
				var opt = new Option();
				optionCopy(opt, options[a-1])
				optionCopy(options[a-1], options[a])
				optionCopy(options[a], opt)
			}
		}
	}
Since the default assignment behaviour in JavaScript it to create a reference to the right hand object, simply options[a-1] = options[a] won't do.
So I google for copying objects in JavaScript and any hit I get is very similar to this one, quoted below:

Code: Select all

Example 9.5: The assign() Method

// This is the function we'll use for the assign() method.
function myassign(rhs) {
    var i;
    for (i in rhs) this[i] = rhs[i];
}
myobject = new Object;       // create an object
myobject.assign = myassign;  // set the custom assign() method on it
// Now, when an object is assigned to "myobject", the properties
// of that object are copied, rather than overwriting the "myobject"
// variable with a reference to the other object.
myobject = my_other_object;
      
// After the above assignment, myobject and my_other_object still refer
// to two separate objects, but myobject has a copy of each of the 
// properties of my_other_object.
or anything else based on

Code: Select all

for (i in rhs) this[i] = rhs[i];
However, firefox complains that this method is not allowed. "Trying to set a property that only is a getter".

Which is the best way to copy objects without having to (like I do now) copy the properties explicitly, see below?

Code: Select all

// OK, I consider this a BAD way. But it works at least:
function optionCopy(to, from){
		to.text = from.text
		to.value = from.value
		to.defaultSelected = from.defaultSelected
		to.selected = from.selected
		to.style.fontWeight = from.style.fontWeight
		to.style.color = from.style.color
}
Any suggestions?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

as far as I know, the for .. in loop is the most efficient. Something you could do is give the function an optional second argument that is an array or string. So you can exclude the property names listed inside it. I'd then create a function that would be have the array of properties to exclude already stored inside it, as an interface caller to the actual copy function.
User avatar
Heavy
Forum Contributor
Posts: 478
Joined: Sun Sep 22, 2002 7:36 am
Location: Viksjöfors, Hälsingland, Sweden
Contact:

Post by Heavy »

Okay...
This is just me playing:

Code: Select all

function optionCopy(to, from){
		var cell
		for(cell in from){
			alert(cell + ", " + typeof(to[cell]))
			if (!readonly(to[cell])){
			to[cell] = from[cell]
			}
		}
	}
I would be perfectly happy if I could determine if to[cell] is setable.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

yeah, I haven't seen anything that'd tell if a property is read only though.. :? I don't see anything on copy constructors or anything remotely related. Even the documentation on copying an object is vague at best.. :(
User avatar
Heavy
Forum Contributor
Posts: 478
Joined: Sun Sep 22, 2002 7:36 am
Location: Viksjöfors, Hälsingland, Sweden
Contact:

Post by Heavy »

yeah, I wish JavaScript could be as forgiving and flexible as PHP.
Post Reply