innerHTML works, but DOM doesn't - Please Help

Discussion in 'Javascript' started by dan, Oct 28, 2007.

  1. dan

    dan Guest

    Hi

    I'm creating a very basic Ajax "Suggest" type script. I have the
    server side OK, and the response gets back OK. I've had to use
    responseText, as for some reason xmlResponse doesn't seem to work if
    more than one <message> element is present. But that isn't the point
    of this post, so I'd better get to that.

    Once I have the list of values that match the user's search term, I
    display them as a list in a <div>. When the user clicks on one of the
    list, that value is placed into the textfield.

    Here are three ways I attempted this, but the only one that allows
    anything other than the last element to accept any kind of focus is
    the one that uses innerHTML for the entire thing.

    Can anyone tell me why the other two don't work? They all display
    pretty much the same, until you move the cursor over the list. The
    last two automatically move the focus to the last item on the list. I
    should add that I've only tested these in IE 6, and Firefox 2 (both
    for Windows).

    Any pointers with this very much appreciated.

    Cheers

    Dan

    Assume all of the following are performed within a for loop

    // This is the one that works
    ss.innerHTML += "<div class='norm' onmouseover=
    \"javascript:this.className='over'\" onmouseout=
    \"javascript:this.className='norm'\" " +
    "onclick='SetSearch(this.innerHTML)'>" + text + "</div>";

    // This doesn't work
    var d = document.createElement('div');
    ss.appendChild(d);
    d.innerHTML = text;
    d.className = 'norm';
    d.onmouseover = function() { d.className = 'over'; };
    d.onmouseout = function() { d.className = 'norm'; };
    d.onclick = function() { SetSearch(text); };

    // This doesn't work
    var li = document.createElement('li');
    li.style.marginBottom = '3px';
    var a = document.createElement('a');
    var content = document.createTextNode(text);
    a.appendChild(content);
    a.setAttribute('title', text);
    a.setAttribute('href', text);
    li.appendChild(a);
    u.appendChild(li);
    a.onclick=function() { SetSearch(a.getAttribute('href')); return
    false;};
    dan, Oct 28, 2007
    #1
    1. Advertising

  2. dan

    Evertjan. Guest

    dan wrote on 28 okt 2007 in comp.lang.javascript:

    > d.onmouseover = function() { d.className = 'over'; };
    > d.onmouseout = function() { d.className = 'norm'; };
    > d.onclick = function() { SetSearch(text); };
    >


    This works:

    <div
    onmouseover ='alert("hi")'>
    test</div>

    This does not:

    <div
    onmouseover = function(){alert("hi")}>
    test</div>

    The on.. eventhandlers are not part of javascript,
    so they need a string sctipt, meseems.




    --
    Evertjan.
    The Netherlands.
    (Please change the x'es to dots in my emailaddress)
    Evertjan., Oct 28, 2007
    #2
    1. Advertising

  3. dan

    dan Guest

    On Oct 28, 8:07 pm, "Evertjan." <> wrote:
    > dan wrote on 28 okt 2007 in comp.lang.javascript:
    >
    > > d.onmouseover = function() { d.className = 'over'; };
    > > d.onmouseout = function() { d.className = 'norm'; };
    > > d.onclick = function() { SetSearch(text); };

    >
    > This works:
    >
    > <div
    > onmouseover ='alert("hi")'>
    > test</div>
    >
    > This does not:
    >
    > <div
    > onmouseover = function(){alert("hi")}>
    > test</div>
    >
    > The on.. eventhandlers are not part of javascript,
    > so they need a string sctipt, meseems.
    >
    > --
    > Evertjan.
    > The Netherlands.
    > (Please change the x'es to dots in my emailaddress)


    Thanks for your response, but I'm not applying the anonymous function
    to the events within the actual HTML.

    The two non-working snippets I provided, do work to a degree. All the
    items appear in the page, but it's as if all the event handler info is
    only being applied to the last item added to the list.

    It's more than that, though, because the last item actually hogs the
    focus. If I put my cursor over the first item in a 20 item list, the
    20th item changes its class attribute. If I click on the first item,
    the 20th element submits its information.

    I guess what I would really like to know is how to make it work using
    DOM, rather than innerHTML. What would I need to change?
    d.onmouseover = 'javascript:this.className = "over"'; doesn't do the
    trick.

    Cheers

    Dan
    dan, Oct 28, 2007
    #3
  4. dan

    David Mark Guest

    On Oct 28, 5:57 am, dan <> wrote:
    > On Oct 28, 8:07 pm, "Evertjan." <> wrote:
    >
    >
    >
    >
    >
    > > dan wrote on 28 okt 2007 in comp.lang.javascript:

    >
    > > > d.onmouseover = function() { d.className = 'over'; };
    > > > d.onmouseout = function() { d.className = 'norm'; };
    > > > d.onclick = function() { SetSearch(text); };

    >
    > > This works:

    >
    > > <div
    > > onmouseover ='alert("hi")'>
    > > test</div>

    >
    > > This does not:

    >
    > > <div
    > > onmouseover = function(){alert("hi")}>
    > > test</div>

    >
    > > The on.. eventhandlers are not part of javascript,
    > > so they need a string sctipt, meseems.

    >
    > > --
    > > Evertjan.
    > > The Netherlands.
    > > (Please change the x'es to dots in my emailaddress)

    >
    > Thanks for your response, but I'm not applying the anonymous function
    > to the events within the actual HTML.
    >


    Right.

    > The two non-working snippets I provided, do work to a degree. All the
    > items appear in the page, but it's as if all the event handler info is
    > only being applied to the last item added to the list.


    Right. The problem is a misunderstanding of how closures work.

    You mentioned these were in a loop.

    d.onmouseover = function() { d.className = 'over'; };
    d.onmouseout = function() { d.className = 'norm'; };
    d.onclick = function() { SetSearch(text); };

    When you exit the function containing the loop, d is equal to the last
    item. Try them like this:

    // First two don't need to reference anything in the outer function
    d.onmouseover = function() { this.className = 'over'; };
    d.onmouseout = function() { this.className = 'norm'; };
    // Can't reference text as it will change on the next iteration
    d.onclick = (function(t) { return function() { SetSearch(t); }; })
    (text);

    And at the end of the loop:

    d = null; // Avoid memory leaks in IE
    David Mark, Oct 28, 2007
    #4
  5. dan

    dan Guest

    On Oct 28, 9:26 pm, David Mark <> wrote:
    > On Oct 28, 5:57 am, dan <> wrote:
    >
    >
    >
    > > On Oct 28, 8:07 pm, "Evertjan." <> wrote:

    >
    > > > dan wrote on 28 okt 2007 in comp.lang.javascript:

    >
    > > > > d.onmouseover = function() { d.className = 'over'; };
    > > > > d.onmouseout = function() { d.className = 'norm'; };
    > > > > d.onclick = function() { SetSearch(text); };

    >
    > > > This works:

    >
    > > > <div
    > > > onmouseover ='alert("hi")'>
    > > > test</div>

    >
    > > > This does not:

    >
    > > > <div
    > > > onmouseover = function(){alert("hi")}>
    > > > test</div>

    >
    > > > The on.. eventhandlers are not part of javascript,
    > > > so they need a string sctipt, meseems.

    >
    > > > --
    > > > Evertjan.
    > > > The Netherlands.
    > > > (Please change the x'es to dots in my emailaddress)

    >
    > > Thanks for your response, but I'm not applying the anonymous function
    > > to the events within the actual HTML.

    >
    > Right.
    >
    > > The two non-working snippets I provided, do work to a degree. All the
    > > items appear in the page, but it's as if all the event handler info is
    > > only being applied to the last item added to the list.

    >
    > Right. The problem is a misunderstanding of how closures work.
    >
    > You mentioned these were in a loop.
    >
    > d.onmouseover = function() { d.className = 'over'; };
    > d.onmouseout = function() { d.className = 'norm'; };
    > d.onclick = function() { SetSearch(text); };
    >
    > When you exit the function containing the loop, d is equal to the last
    > item. Try them like this:
    >
    > // First two don't need to reference anything in the outer function
    > d.onmouseover = function() { this.className = 'over'; };
    > d.onmouseout = function() { this.className = 'norm'; };
    > // Can't reference text as it will change on the next iteration
    > d.onclick = (function(t) { return function() { SetSearch(t); }; })
    > (text);
    >
    > And at the end of the loop:
    >
    > d = null; // Avoid memory leaks in IE


    Wow, thanks so much. That does the trick alright. The way JavaScript
    handles scoping really throws me sometimes.

    I've actually never seen that syntax for the onclick thing before, but
    then I've hardly got to first base with it yet :)

    Cheers

    Dan
    dan, Oct 28, 2007
    #5
  6. dan

    David Mark Guest

    On Oct 28, 6:41 am, dan <> wrote:
    > On Oct 28, 9:26 pm, David Mark <> wrote:
    >
    >
    >
    >
    >
    > > On Oct 28, 5:57 am, dan <> wrote:

    >
    > > > On Oct 28, 8:07 pm, "Evertjan." <> wrote:

    >
    > > > > dan wrote on 28 okt 2007 in comp.lang.javascript:

    >
    > > > > > d.onmouseover = function() { d.className = 'over'; };
    > > > > > d.onmouseout = function() { d.className = 'norm'; };
    > > > > > d.onclick = function() { SetSearch(text); };

    >
    > > > > This works:

    >
    > > > > <div
    > > > > onmouseover ='alert("hi")'>
    > > > > test</div>

    >
    > > > > This does not:

    >
    > > > > <div
    > > > > onmouseover = function(){alert("hi")}>
    > > > > test</div>

    >
    > > > > The on.. eventhandlers are not part of javascript,
    > > > > so they need a string sctipt, meseems.

    >
    > > > > --
    > > > > Evertjan.
    > > > > The Netherlands.
    > > > > (Please change the x'es to dots in my emailaddress)

    >
    > > > Thanks for your response, but I'm not applying the anonymous function
    > > > to the events within the actual HTML.

    >
    > > Right.

    >
    > > > The two non-working snippets I provided, do work to a degree. All the
    > > > items appear in the page, but it's as if all the event handler info is
    > > > only being applied to the last item added to the list.

    >
    > > Right. The problem is a misunderstanding of how closures work.

    >
    > > You mentioned these were in a loop.

    >
    > > d.onmouseover = function() { d.className = 'over'; };
    > > d.onmouseout = function() { d.className = 'norm'; };
    > > d.onclick = function() { SetSearch(text); };

    >
    > > When you exit the function containing the loop, d is equal to the last
    > > item. Try them like this:

    >
    > > // First two don't need to reference anything in the outer function
    > > d.onmouseover = function() { this.className = 'over'; };
    > > d.onmouseout = function() { this.className = 'norm'; };
    > > // Can't reference text as it will change on the next iteration
    > > d.onclick = (function(t) { return function() { SetSearch(t); }; })
    > > (text);

    >
    > > And at the end of the loop:

    >
    > > d = null; // Avoid memory leaks in IE

    >
    > Wow, thanks so much. That does the trick alright. The way JavaScript
    > handles scoping really throws me sometimes.


    Follow this link for more information on closures:

    http://www.jibbering.com/faq/faq_notes/closures.html

    >
    > I've actually never seen that syntax for the onclick thing before, but


    It just creates a closure for each handler, each with its own local t
    variable. If you use the text variable from the outer function, every
    handler will share a reference to a single variable.

    > then I've hardly got to first base with it yet :)


    It is a common mistake. The lesson is that you shouldn't use closures
    until you understand how they work.
    David Mark, Oct 28, 2007
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. pjar09
    Replies:
    0
    Views:
    762
    pjar09
    Aug 11, 2010
  2. necromonger

    help with DOM row/cell with innerHTML

    necromonger, Oct 11, 2004, in forum: Javascript
    Replies:
    22
    Views:
    324
    Michael Winter
    Oct 14, 2004
  3. Andrew Poulos

    Command works as html but not as DOM

    Andrew Poulos, Dec 21, 2004, in forum: Javascript
    Replies:
    10
    Views:
    149
    Andrew Poulos
    Dec 22, 2004
  4. Replies:
    3
    Views:
    80
    Thomas 'PointedEars' Lahn
    Dec 17, 2005
  5. sonic
    Replies:
    5
    Views:
    271
    Randy Webb
    Jul 11, 2006
Loading...

Share This Page