innerHTML works, but DOM doesn't - Please Help

D

dan

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;};
 
E

Evertjan.

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.
 
D

dan

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


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.

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
 
D

David Mark

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
 
D

dan

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
 
D

David Mark

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.
 

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

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,817
Latest member
AdalbertoT

Latest Threads

Top