Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Reference to an object in IE

0 views
Skip to first unread message

Christoph Boget

unread,
May 12, 2008, 3:24:32 PM5/12/08
to
Consider the following script:

var SearchWidgetWhat = {
aWhatCheckboxes : {},
iNumCheckboxes : 0, /* Need to do this because JS can't get the length
of an object. Stupid @#(*&(*$&@# JS */

getWhatCheckboxes : function()
{
var retval = {};
var sKeyName = '';

/**
* The checkboxes are never going to change so we may as well cache
them
* for later use
**/
if( SearchWidgetWhat.iNumCheckboxes == 0 )
{
aInputs = document.getElementsByTagName( 'input' );
if(( aInputs ) && ( aInputs.length > 0 ))
{
for( i = 0; i < aInputs.length; i++ )
{
if( aInputs[i].id.indexOf( 'SearchWidget_What_' ) != -1 )
{
sKeyName = aInputs[i].id.replace( 'SearchWidget_What_', '' );
SearchWidgetWhat.aWhatCheckboxes[sKeyName] = aInputs[i];
SearchWidgetWhat.iNumCheckboxes++;
}
}
retval = SearchWidgetWhat.aWhatCheckboxes;
}
}
else
{
retval = SearchWidgetWhat.aWhatCheckboxes;
}
return retval;

}
}

The above works fine in FF. However, in IE, the following line

SearchWidgetWhat.aWhatCheckboxes[sKeyName] = aInputs[i];

creates a copy of the input object and does not store a reference to that
object. Consequently, if I want to change attributes and/or values of those
objects,

(e.g. SearchWidgetWhat.aWhatCheckboxes[sKeyName].checked = false;
SearchWidgetWhat.aWhatCheckboxes[sKeyName].value =1; etc)

I cannot because what is being altered is not the original element. Is
there any way I can get IE to save references to the original input objects?
Or am I just SOL and I need to use document.getElementById() every time,
even though it shouldn't otherwise be necessary? I mean, it's not as if the
form input elements are going to change all the time so I don't understand
why I can't just cache those few (checkboxes in this case) that I need to
work with.

thnx,
Christoph

Anthony Jones

unread,
May 13, 2008, 6:03:55 AM5/13/08
to
"Christoph Boget" <jcb...@yahoo.com> wrote in message
news:404F82AE-7814-49DC...@microsoft.com...

First of all this code:-

SearchWidgetWhat.aWhatCheckboxes[sKeyName] = aInputs[i];

is not creating a copy of the element. I've tested it in IE7 and IE6 using
getElementsByTagName, something else is going wrong with the code.


BTW, (re: 'JS can't get the length of an object'), whilst a Javascript
object can be used as an associative array its not designed as such. No
object in any language anywhere have I seen that carries a property
specifing the total number of properties and methods it exposes.

A better solution to that problem would be to not define the aWhatCheckboxes
member at all until the first call to getWhatCheckboxes. In that function
use:-

if (!this.aWhatCheckBoxes)
{
this.aWhatCheckBoxes = {}

//Rest of code to add members to aWhatCheckBoxes

}

Now unless you have another use iNumCheckboxes it is superflous.

Note you should use the accessor getWhatCheckBoxes each time you need the
'array', treat the aWhatCheckBoxes member as private and therefore only to
be accessed by code inside the object.

Note the use of 'this' instead of the 'SearchWidgetWhat' variable. Using
the 'this' keyword makes the code more transportable.

Having said all that I would ditch the whole thing and use this instead:-

function putSearchWidgetWhatChecked(sKeyName, value)
{
var elem = document.getElementById('SearchWidget_What_' + sKeyName);
elem.checked = value;
}


The statement 'The best solution is the simplest' is nearly always true.
The most common reason we ignore it is because often the simplest solution
is not the most efficient solution. What we lose sight of is the
inefficiency rarely causes any problems at all whereas complexity will most
of the time cause some problems.


--
Anthony Jones - MVP ASP/ASP.NET


Christoph Boget

unread,
May 13, 2008, 8:15:29 AM5/13/08
to
> First of all this code:-
> SearchWidgetWhat.aWhatCheckboxes[sKeyName] = aInputs[i];
> is not creating a copy of the element. I've tested it in IE7 and IE6
> using
> getElementsByTagName, something else is going wrong with the code.

Try running the following code:

var oTmp = SearchWidgetWhat.getWhatCheckboxes();
for( sKey in oTmp )
{
oTmp[sKey].checked = false;
}

Either

SearchWidgetWhat.aWhatCheckboxes[sKeyName] = aInputs[i];

or

oTmp[sKey].checked = false;

must be working with a cloned object. Sadly, because JS is almost
impossible to debug in IE, it's very difficult for me to tell which. But
because I've tried alert()ing various messages at various stages, the
alerted data led me to believe it was the initial assignment.

> BTW, (re: 'JS can't get the length of an object'), whilst a Javascript
> object can be used as an associative array its not designed as such. No
> object in any language anywhere have I seen that carries a property
> specifing the total number of properties and methods it exposes.

Fair enough. And that is a point I do understand. It just would be really
nice if JS supported hashes or associative arrays.

> A better solution to that problem would be to not define the
> aWhatCheckboxes
> member at all until the first call to getWhatCheckboxes. In that function
> use:-

> Now unless you have another use iNumCheckboxes it is superflous.

I do have other uses for it. And the reason I define it early is because
the code I posted is just a small part of a larger object; the only part I
is causing problems for me.

> Note the use of 'this' instead of the 'SearchWidgetWhat' variable. Using
> the 'this' keyword makes the code more transportable.

True, but I don't need an object that can be instantiated. I'm using it
mostly as a namespace.

> The statement 'The best solution is the simplest' is nearly always true.
> The most common reason we ignore it is because often the simplest solution
> is not the most efficient solution. What we lose sight of is the
> inefficiency rarely causes any problems at all whereas complexity will
> most
> of the time cause some problems.

Also a fair point. But as I pointed out above, there is more to the object
than what I originally posted. In retrospect, I should have also included
how I was accessing the aWhatCheckboxes property, which I've now posted in
this message.

thnx,
Christoph

Anthony Jones

unread,
May 13, 2008, 9:55:15 AM5/13/08
to

--
Anthony Jones - MVP ASP/ASP.NET

"Christoph Boget" <jcb...@yahoo.com> wrote in message

news:DC18DDB4-D50B-448E...@microsoft.com...

Try this super simple test page:-

<html>
<head>
<style type="text/css">

</style>
<script type="text/javascript">

var chkBoxes = {}

function body_onload()
{
var arr = document.getElementsByTagName("input");
for (var i = 0, length = arr.length; i < length; i++)
{
chkBoxes[arr[i].id] = arr[i];
}
}

function toggle(name)
{
chkBoxes[name].checked = !chkBoxes[name].checked;
}

</script>
</head>
<body onload="body_onload()">
<input type="checkbox" id="chkTest1" /><br/>
<input type="checkbox" id="chkTest2" /><br/>
<input id="cmdToggle" type="button" value="Toggle"
onclick="toggle('chkTest1')" />
</body>
</html>

When you click the toggle button does the first check box toggle?


Anthony Jones

unread,
May 13, 2008, 10:10:30 AM5/13/08
to

"Christoph Boget" <jcb...@yahoo.com> wrote in message
news:DC18DDB4-D50B-448E...@microsoft.com...

In fact here is an alternative test page based on your code:-

<html>
<head>
<script type="text/javascript">

var SearchWidgetWhat = {
aWhatCheckboxes : {},

iNumCheckboxes : 0, /* Need to do this because JS can't get the length


of an object. Stupid @#(*&(*$&@# JS */

getWhatCheckboxes : function()
{
var retval = {};
var sKeyName = '';

if( SearchWidgetWhat.iNumCheckboxes == 0 )


{
aInputs = document.getElementsByTagName( 'input' );
if(( aInputs ) && ( aInputs.length > 0 ))
{
for( i = 0; i < aInputs.length; i++ )
{

if( aInputs[i].id.indexOf( 'chk' ) != -1 )
{
sKeyName = aInputs[i].id.replace( 'chk', '' );


SearchWidgetWhat.aWhatCheckboxes[sKeyName] = aInputs[i];

SearchWidgetWhat.iNumCheckboxes++;
}
}
retval = SearchWidgetWhat.aWhatCheckboxes;
}
}
else
{
retval = SearchWidgetWhat.aWhatCheckboxes;
}
return retval;

}
}

function toggle()
{

var oTmp = SearchWidgetWhat.getWhatCheckboxes();
for( sKey in oTmp )
{

oTmp[sKey].checked = !oTmp[sKey].checked;
}
}

</script>
</head>
<body>


<input type="checkbox" id="chkTest1" /><br/>
<input type="checkbox" id="chkTest2" /><br/>

<input id="cmdToggle" type="button" value="toggle" onclick="toggle()" />
</body>
</html>

works fine on IE6 and IE7

0 new messages