Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #8171 > unrolled thread

newbie Javascript checked is null or not an object

Started byshall@uaex.edu
First post2011-11-09 08:10 -0800
Last post2011-11-10 06:36 -0800
Articles 7 — 5 participants

Back to article view | Back to comp.lang.javascript


Contents

  newbie Javascript checked is null or not an object shall@uaex.edu - 2011-11-09 08:10 -0800
    Re: newbie Javascript checked is null or not an object Elegie <elegie@anonymous.invalid> - 2011-11-09 17:59 +0100
      Re: newbie Javascript checked is null or not an object Denis McMahon <denismfmcmahon@gmail.com> - 2011-11-09 23:20 +0000
        Re: newbie Javascript checked is null or not an object Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2011-11-10 14:30 +0100
          Re: newbie Javascript checked is null or not an object Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2011-11-12 13:32 +0100
        Re: newbie Javascript checked is null or not an object shall@uaex.edu - 2011-11-10 05:30 -0800
        Re: newbie Javascript checked is null or not an object David Mark <dmark.cinsoft@gmail.com> - 2011-11-10 06:36 -0800

#8171 — newbie Javascript checked is null or not an object

Fromshall@uaex.edu
Date2011-11-09 08:10 -0800
Subjectnewbie Javascript checked is null or not an object
Message-ID<7a88bf5f-7821-49ca-85a8-bca655c28a36@u9g2000vbx.googlegroups.com>
I have a web page I click on a link which calls AJAX routine to list 3
checkboxes.
I'm trying to use Javascript for a SELECT ALL to select all of the
checkboxes.

The check boxes MUST be in a AJAX routine. My select all function
would work if
the checkboxes were on the same page.
Here is sample code :
======== Below AJAX section ======
<%
        response.write "<table border=""1"" width=""80%""
align=""center"">"
        response.write "<tr><td colspan=""3"" class=""normalem""
align=""center"">"
		 response.write "<a href='javascript:selectall(""3"")'>Select all
names</a>"
 		 response.write "</td></tr>"
         Response.write "<tr><td align=""center"">"
		   Response.write "<input type=""checkbox"" id=""oneemp1"" "
		   Response.write " name=""oneemp"" value=""123"">Chevy<br>"
		   Response.write "<input type=""checkbox"" id=""oneemp2"" "
		   Response.write " name=""oneemp"" value=""456"">Ford<br>"
		   Response.write "<input type=""checkbox"" id=""oneemp3"" "
		   Response.write " name=""oneemp"" value=""789"">Honda<br>"
           Response.write "</td></tr></table>"
  %>

======  Below page calling AJAX ==============
<HTML Lang="en">
<HEAD>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<TITLE>Test Ajax</TITLE>
<script language="JavaScript">
function killenter() {
   return false;
}
function selectall(myCode) {
   intCode=parseInt(myCode);
   intMaxLength=document.form1.length;
	   for( elemnum=0; elemnum<intMaxLength; elemnum++){
       var gg=document.form1.elements[elemnum].name;
	   var strTmp = gg.substring(0,6);
	   if( strTmp=="oneemp"){
	        var ff=document.form1.elements[gg][elemnum];
        	   if ( !ff.checked) {
  	              ff.checked=!ff.checked;
	           }
	           else{
  	              ff.checked=false;
	           }
       }
       }
}

function dView(AA){
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHttp");
  }
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
 
document.getElementById("listCars").innerHTML=xmlhttp.responseText;
    }
  }
xmlhttp.open("GET","TestAjaxCars.asp",true);
xmlhttp.send();
}
</script>
</HEAD>
<body bgcolor="#FFFFFF" text="#000000" link="#800000" vlink="#800000"
alink="#800000">

<div align="center">
		</select>&nbsp;&nbsp;<a href='javascript:dView("123")'>Show Cars</a>
</div>
    <form name="form1" action="dosomething.asp"
 	  method="post" onSubmit="return killenter()">
 	<input type="hidden" name="Fyear" value="2012">

<div id="listCars"></div>
</form>

</BODY>
</HTML>

The error message I currently get is :
checked is null or not an object

Suggestions?
TIA
Steve

[toc] | [next] | [standalone]


#8173

FromElegie <elegie@anonymous.invalid>
Date2011-11-09 17:59 +0100
Message-ID<4ebab172$0$14430$426a34cc@news.free.fr>
In reply to#8171
On 09/11/2011 17:10, shall@uaex.edu wrote :

Hi,

<snip>

> function selectall(myCode) {
>     intCode=parseInt(myCode);
>     intMaxLength=document.form1.length;
> 	   for( elemnum=0; elemnum<intMaxLength; elemnum++){
>         var gg=document.form1.elements[elemnum].name;
> 	   var strTmp = gg.substring(0,6);
> 	   if( strTmp=="oneemp"){
> 	        var ff=document.form1.elements[gg][elemnum];

"elemNum" is an iterator over all elements of the FORM, not an iterator 
over the elements of the checkbox group. Try and replace the line above by:

    var ff=document.form1.elements[elemnum]; // untested

>          	   if ( !ff.checked) {
>    	              ff.checked=!ff.checked;
> 	           }
> 	           else{
>    	              ff.checked=false;
> 	           }

This conditional hurts, because the conditions display different logic. 
Why not simply write (if this really is what you want):

   ff.checked = !ff.checked;

or (as your title suggests)

   ff.checked = true;

> Suggestions?

Yes. I'll be blunt here, but your code really needs cleaning up. The 
HTML is not validated (there's a "</select>" somewhere), your javascript 
is not properly indented, has undeclared variables and so on... Remember 
that there's no compiler to help you, so if you start working with 
messed up code, then debugging will be increasingly difficult (as you 
have experienced).

HTH,
Elegie.

[toc] | [prev] | [next] | [standalone]


#8185

FromDenis McMahon <denismfmcmahon@gmail.com>
Date2011-11-09 23:20 +0000
Message-ID<4ebb0ac7$0$28592$a8266bb1@newsreader.readnews.com>
In reply to#8173
On Wed, 09 Nov 2011 17:59:28 +0100, Elegie wrote:

var ff=document.form1.elements[elemnum]; // untested

/* then wrap the tests so that it only looks for the checked property on 
actual checkboxes */

if (ff.type == "checkbox") ff.checked = !ff.checked; // untested

/* or it will barf when you test an element that doesn't have the checked 
property. */

(I assume that the OPs intent was to toggle the checkbox state, as that's 
what his code was actually doing.)

You could even (and I'm sure someone will shortly post saying why this is 
bad, but probably not actually explaining (a) why or (b) the 'proper' way 
of doing it) use something like (not tested either):

var inputsInListcarsDiv = document.getElementById
("listcars").getElementsByTagName("input");
for (var i = 0; i < inputsInListcarsDiv.length; i++) if 
(inputsInListcarsDiv[i].type == "checkbox") inputsInListcarsDiv[i].checked 
= !inputsInListcarsDiv[i].checked;

You could drop the 'if (inputsInListcarsDiv[i].type == "checkbox")' if 
you know for an absolute certainty that all the inputs in that div will 
only ever be checkboxes.

Rgds

Denis McMahon

[toc] | [prev] | [next] | [standalone]


#8194

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2011-11-10 14:30 +0100
Message-ID<1675485.FNyZMGkNft@PointedEars.de>
In reply to#8185
Denis McMahon wrote:

> On Wed, 09 Nov 2011 17:59:28 +0100, Elegie wrote:
> 
> var ff=document.form1.elements[elemnum]; // untested
> 
> /* then wrap the tests so that it only looks for the checked property on
> actual checkboxes */
> 
> if (ff.type == "checkbox") ff.checked = !ff.checked; // untested

A more reliable test would be 

  if (typeof ff.checked != "undefined")
  {
    ff.checked = !ff.checked;
  }

That is, you should test the property that you intent to access.  But if 
this is for checkboxes only, your way should suffice.

> /* or it will barf when you test an element that doesn't have the checked
> property. */

That is not likely.  While host objects do have a reputation for being 
unreliable, many of them will allow the addition of new properties, and will 
yield the standard `undefined' value when accessing non-existent properties 
(and !undefined === true).  It is still unreliable, though.

However, this code should never be applied to objects that do not have a 
`checked' property in the first place, which renders the question moot and 
the test unnecessary.

> You could even (and I'm sure someone will shortly post saying why this is
> bad,

It is bad,

> but probably not actually explaining (a) why

because it is comparably inefficient, incompatible, and unnecessary.

> or (b) the 'proper' way of doing it)

The proper way of doing it is described in the FAQ of this newsgroup and 
involves the standard backwards-compatible `forms' and `elements' 
collections.

Put politely, you would be well-advised to read the FAQ and listen to the 
people who very obviously have a lot more experience in this field than you 
have.


PointedEars
-- 
Danny Goodman's books are out of date and teach practices that are
positively harmful for cross-browser scripting.
 -- Richard Cornford, cljs, <cife6q$253$1$8300dec7@news.demon.co.uk> (2004)

[toc] | [prev] | [next] | [standalone]


#8254

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2011-11-12 13:32 +0100
Message-ID<3002143.SPkdTlGXAF@PointedEars.de>
In reply to#8194
Thomas 'PointedEars' Lahn wrote:

> Denis McMahon wrote:
>> var ff=document.form1.elements[elemnum]; // untested
>> 
>> /* then wrap the tests so that it only looks for the checked property on
>> actual checkboxes */
>> 
>> if (ff.type == "checkbox") ff.checked = !ff.checked; // untested
> 
> […]
> However, this code should never be applied to objects that do not have a
> `checked' property in the first place, which renders the question moot and
> the test unnecessary.
> 
>> You could even (and I'm sure someone will shortly post saying why this is
>> bad,
> 
> It is bad,
> 
>> but probably not actually explaining (a) why
> 
> because it is comparably inefficient, incompatible, and unnecessary.

Now as to the why.  Remember, the suggested alternative was (formatted):

  var inputsInListcarsDiv =
    document.getElementById("listcars").getElementsByTagName("input");

  for (var i = 0; i < inputsInListcarsDiv.length; i++)
  {
    if (inputsInListcarsDiv[i].type == "checkbox")
    {
      inputsInListcarsDiv[i].checked = !inputsInListcarsDiv[i].checked;
    }
  }

Efficience
-----------

The suggested alternative is comparably inefficient because it requires a 
lot more property lookups (P), calls (C) and operations (O).  In order of 
execution:

  P: document
  P: document.getElementById
  C: document.getElementById("listcars")
  P: document.getElementById("listcars").getElementsByTagName
  C: document.getElementById("listcars").getElementsByTagName("input");
  P: inputsInListcarsDiv
  O: inputsInListcarsDiv =
       document.getElementById("listcars").getElementsByTagName("input")

  `for' statement:

    P: i
    O: i = 0

    inputsInListcarsDiv.length times (any case):

      P: i
      P: inputsInListcarsDiv
      P: inputsInListcarsDiv.length
      O: ToBoolean(i < inputsInListcarsDiv.length)
      P: inputsInListcarsDiv
      P: inputsInListcarsDiv[i]
      P: inputsInListcarsDiv[i].type
      O: inputsInListcarsDiv[i].type == "checkbox"

    inputsInListcarsDiv.length times (worst case):

      P: inputsInListcarsDiv
      P: inputsInListcarsDiv[i]
      P: inputsInListcarsDiv[i].checked
      O: !inputsInListcarsDiv[i].checked
      P: inputsInListcarsDiv
      P: inputsInListcarsDiv[i]
      P: inputsInListcarsDiv[i].checked
      O: inputsInListcarsDiv[i].checked = !inputsInListcarsDiv[i].checked

    inputsInListcarsDiv.length times (any case):

      P: i
      O: i++

It is a lot more efficient when written as follows:

  var inputsInListcarsDiv =
     document.getElementById("listcars").getElementsByTagName("input");

  for (var i = inputsInListcarsDiv.length; i--;)
  {
    var elem = inputsInListcarsDiv[i];
    if (elem.type == "checkbox")
    {
      elem.checked = !elem.checked;
    }
  }

Then the following property lookups (P), calls (C) and operations (O) would 
take place, in order of execution:

  P: document
  P: document.getElementById
  C: document.getElementById("listcars")
  P: document.getElementById("listcars").getElementsByTagName
  C: document.getElementById("listcars").getElementsByTagName("input")
  P: inputsInListcarsDiv
  O: inputsInListcarsDiv =
       document.getElementById("listcars").getElementsByTagName("input")

  `for' statement:

    P: i
    P: inputsInListcarsDiv
    P: inputsInListcarsDiv.length
    O: i = inputsInListcarsDiv.length

    inputsInListcarsDiv.length times (any case):

      P: i
      O: ToBoolean(i--)
      P: inputsInListcarsDiv
      P: inputsInListcarsDiv[i]
      P: elem
      O: elem = inputsInListcarsDiv[i]
      P: elem.type
      O: elem.type == "checkbox"

    inputsInListcarsDiv.length times (worst case):

      P: elem
      P: elem.checked
      P: elem
      P: elem.checked
      O: !elem.checked
      O: elem.checked = !elem.checked

It is still very inefficient by comparison because it involves

- document.getElementById(), i.e. searching the entire document tree for one
  element (best case), and returning the reference to the corresponding
  element object,

and

- getElementsByTagName(), i.e. searching that element's subtree for
  descendant elements of a certain type (), building a live collection
  containing the corresponding element objects, and returning that
  collection.

The `document.forms' collection, by comparison, is already a live collection 
of objects representing `form' elements, and its `elements' collection is 
already a live collection representing form controls of that particular 
`form' element.  Therefore, the first approach requires only the following, 
in order of execution:

  P: document
  P: document.forms
  P: document.forms["form1"]
  P: document.forms["form1"].elements
  P: elemnum
  P: document.forms["form1"].elements[elemnum]

  [a lot more P's, and O's, and one C]

However, it should be noted that none of those property accesses are 
necessary here.  One can pass `this' from an event handler attribute of a 
control:

  function toggleAll(ctrl, name)
  {
    var checked = ctrl.checked;
    var checkboxes = ctrl.form.elements[name];

    for (var i = checkboxes.length; i--;)
    {
      checkboxes[i].checked = checked;
    }
  }

  <input type="checkbox" … onclick="toggleAll(this, 'foo')">

Which requires the following:

  C: toggleAll(this, 'foo')
  P: checked
  P: ctrl
  P: ctrl.checked
  O: checked = ctrl.checked
  P: ctrl
  P: ctrl.form
  P: ctrl.form.elements
  P: name
  P: ctrl.form.elements[name]
  O: checkboxes = ctrl.form.elements[name]

  `for' statement:

    P: i
    P: checkboxes
    P: checkboxes.length
    O: i = checkboxes.length

    checkboxes.length times:

      P: i
      O: ToBoolean(i--)
      P: checkboxes
      P: i
      P: checkboxes[i]
      P: checked
      O: checkboxes[i] = checked

In any case, one can easily see from this that this kind of element object 
access must be more efficient (and cannot be less standards-compliant or 
less compatible, see below) than the suggested alternative.

Compatibility
--------------

The suggested alternative is comparably incompatible, because not only it 
relies on the availability of the document.getElementById() method, but also 
on that element objects have a getElementsByTagName() method.

The document.getElementById(…) method was introduced with W3C DOM (HTML) 
Level 1 [1].  But in that Specification, the HTMLElement interface has no 
getElementsByTagName() method [2].  It was only introduced there with W3C 
DOM Level 2 Core [3].

By contrast, the `forms' and `elements' collections [4,5] date back to the 
so-called "DOM Level 0" [6] introduced by Netscape Navigator 3.0 [7,8] and 
Internet Explorer 3.0 [9,10].  As a consequence of that, they can be 
expected to be supported by any script-enabled HTML user agent.
 
Unnecessary
------------

Because we already have the `forms' and `elements' live collections in 
either proprietary and standards-compliant implementation, it is not 
necessary to search the entire document tree for suitable elements.

[x] done.

>> or (b) the 'proper' way of doing it)

[x] done.


PointedEars
_________
 [1] <http://www.w3.org/TR/REC-DOM-Level-1/level-one-html.html#ID-26809268>
 [2] <http://www.w3.org/TR/REC-DOM-Level-1/level-one-html.html#ID-011100101>
 [3] <http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-745549614>
 [4] <http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268>
 [5] <http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-40002357>
 [6] <http://www.w3.org/TR/DOM-Level-2-HTML/glossary.html>
 [7] <http://devedge-
temp.mozilla.org/library/manuals/2000/javascript/1.3/reference/document.html>
 [8] <http://devedge-
temp.mozilla.org/library/manuals/2000/javascript/1.3/reference/form.html>
 [9] <http://msdn.microsoft.com/en-us/library/ms531073(VS.85).aspx>
[10] <http://msdn.microsoft.com/en-us/library/ms535249(VS.85).aspx>
-- 
When all you know is jQuery, every problem looks $(olvable).

[toc] | [prev] | [next] | [standalone]


#8195

Fromshall@uaex.edu
Date2011-11-10 05:30 -0800
Message-ID<cc922569-1bdf-47ac-813d-d21ab10546c7@d17g2000yql.googlegroups.com>
In reply to#8185
Thanks a million!!!


On Nov 9, 5:20 pm, Denis McMahon <denismfmcma...@gmail.com> wrote:
> On Wed, 09 Nov 2011 17:59:28 +0100, Elegie wrote:
>
> var ff=document.form1.elements[elemnum]; // untested
>
> /* then wrap the tests so that it only looks for the checked property on
> actual checkboxes */
>
> if (ff.type == "checkbox") ff.checked = !ff.checked; // untested
>
> /* or it will barf when you test an element that doesn't have the checked
> property. */
>
> (I assume that the OPs intent was to toggle the checkbox state, as that's
> what his code was actually doing.)
>
> You could even (and I'm sure someone will shortly post saying why this is
> bad, but probably not actually explaining (a) why or (b) the 'proper' way
> of doing it) use something like (not tested either):
>
> var inputsInListcarsDiv = document.getElementById
> ("listcars").getElementsByTagName("input");
> for (var i = 0; i < inputsInListcarsDiv.length; i++) if
> (inputsInListcarsDiv[i].type == "checkbox") inputsInListcarsDiv[i].checked
> = !inputsInListcarsDiv[i].checked;
>
> You could drop the 'if (inputsInListcarsDiv[i].type == "checkbox")' if
> you know for an absolute certainty that all the inputs in that div will
> only ever be checkboxes.
>
> Rgds
>
> Denis McMahon

[toc] | [prev] | [next] | [standalone]


#8200

FromDavid Mark <dmark.cinsoft@gmail.com>
Date2011-11-10 06:36 -0800
Message-ID<4291148e-545d-4f6a-97f8-c84b5cdc5767@x8g2000yql.googlegroups.com>
In reply to#8185
On Nov 9, 6:20 pm, Denis McMahon <denismfmcma...@gmail.com> wrote:

>
> You could even (and I'm sure someone will shortly post saying why this is
> bad, but probably not actually explaining (a) why or (b) the 'proper' way
> of doing it) use something like (not tested either):

Sensing some frustration here. :(

>
> var inputsInListcarsDiv = document.getElementById
> ("listcars").getElementsByTagName("input");
> for (var i = 0; i < inputsInListcarsDiv.length; i++) if
> (inputsInListcarsDiv[i].type == "checkbox") inputsInListcarsDiv[i].checked
> = !inputsInListcarsDiv[i].checked;

For reasons already mentioned (and others), this is bad.  I'll add
that this is *really* bad.

You get out of it what you put into it. ;)

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web