newbie Javascript checked is null or not an object

Discussion in 'Javascript' started by shall, Nov 9, 2011.

  1. shall

    shall Guest

    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
     
    shall, Nov 9, 2011
    #1
    1. Advertisements

  2. shall

    Elegie Guest

    On 09/11/2011 17:10, wrote :

    Hi,

    "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
    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;
    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.
     
    Elegie, Nov 9, 2011
    #2
    1. Advertisements

  3. 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.type == "checkbox") inputsInListcarsDiv.checked
    = !inputsInListcarsDiv.checked;

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

    Rgds

    Denis McMahon
     
    Denis McMahon, Nov 9, 2011
    #3
  4. 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.
    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.
    It is bad,
    because it is comparably inefficient, incompatible, and unnecessary.
    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
     
    Thomas 'PointedEars' Lahn, Nov 10, 2011
    #4
  5. shall

    shall Guest

    Thanks a million!!!
     
    shall, Nov 10, 2011
    #5
  6. shall

    David Mark Guest

    Sensing some frustration here. :(


    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. ;)
     
    David Mark, Nov 10, 2011
    #6
  7. 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.type == "checkbox")
    {
    inputsInListcarsDiv.checked = !inputsInListcarsDiv.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
    P: inputsInListcarsDiv.type
    O: inputsInListcarsDiv.type == "checkbox"

    inputsInListcarsDiv.length times (worst case):

    P: inputsInListcarsDiv
    P: inputsInListcarsDiv
    P: inputsInListcarsDiv.checked
    O: !inputsInListcarsDiv.checked
    P: inputsInListcarsDiv
    P: inputsInListcarsDiv
    P: inputsInListcarsDiv.checked
    O: inputsInListcarsDiv.checked = !inputsInListcarsDiv.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;
    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
    P: elem
    O: elem = inputsInListcarsDiv
    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.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
    P: checked
    O: checkboxes = 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.

    [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>
     
    Thomas 'PointedEars' Lahn, Nov 12, 2011
    #7
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.