Forum Moderators: open

Message Too Old, No Replies

Listener not working

Loop sets listeners, but click doesn't respond

         

DS_Cole

10:49 pm on Oct 23, 2010 (gmt 0)

10+ Year Member



This script loops through the elements in the document to get ids, listMe(). It then runs a function with a forloop, setMe(), to set listeners for those divs. This part "seems" to be working.

The next part is the listener event responder function clickDisplay(). No event seems to be fired to trigger the function. (HTML 5.) Alerts say everything is working, except clickDisplay. It adds 1 to the id and displays another element with that id. (clickDisplay works fine if I alter setMe() to send it an id, so I think clickDisplay is fine.) There is no problem indicated on "Lint." No console errors.

I need help identifying why no event is fired to start clickDisplay when the div text is clicked. Thanks in advance. Following is the relevant code.

<script type="text/javascript"> 
var ids = [];

// Function to list all ids in document
function listMe() {
var allTags = document.body.getElementsByTagName('*');
for (var tg = 0; tg< allTags.length; tg++) {
var tag = allTags[tg];
if (tag.id) {
ids.push(tag.id);
var el = tag.id;
}
}
setMe();
}

// Function to respond to click events
function clikDisplay() {
var ab = ab +"1";
alert(ab);
ab = document.getElementById(ab);
ab.style.display = "block";
}

// Function to set listeners for all ids in document
function setMe() {
var i;
for (i=0; i<ids.length; i++) {
var evalue = ids[i];
var elistener = document.getElementById(evalue);
alert(evalue);
if (evalue.addEventListener){
elistener.addEventListener('click', clikDisplay, false);
} // For IE
else if (elistener.attachEvent){
elistener.attachEvent('onclick', clikDisplay);
}
}
}
</script>
</head>

<body onload = listMe();>

<div id="alac">Listener text. id = alac
</div>
<div class="menu_tab" id="alac1" style="display:none;">
<span style="color:#000000;">Displays this text.</span>
</div>

daveVk

11:38 pm on Oct 23, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



function clikDisplay() {
var ab = ab +"1";
alert(ab);
ab = document.getElementById(ab);
ab.style.display = "block";
}

If ab is intended to be local, then ab on RHS is undefined.

If ab is intended to be global, then var is misplaced

It is confusing to to use ab as both the id of the element, and the element itself

DS_Cole

1:03 am on Oct 24, 2010 (gmt 0)

10+ Year Member



Thanks Dave. I made a quick try rewriting, but it didn't work:

Let var el be the var passed from the listener click event. Tried this rewrite:

function clikDisplay(el) { 
alert("This is clickDisplay fired.");
var ab = el +"1";
alert(ab);
ab = document.getElementById(ab);
ab.style.display = "block";
}

No alerts, no display.

Full page of code:

<!DOCTYPE html>
<head>
<meta charset="utf-8" />

<script type="text/javascript">
var ids = [];

// Function to list all ids in document
function listMe() {
var allTags = document.body.getElementsByTagName('*');
for (var tg = 0; tg< allTags.length; tg++) {
var tag = allTags[tg];
if (tag.id) {
ids.push(tag.id);
var el = tag.id;
}
}
setMe();
}

// Function to respond to click events
function clikDisplay(el) {
alert("This is clickDisplay fired.");
var ab = el +"1";
alert(ab);
ab = document.getElementById(ab);
ab.style.display = "block";
}

// Function to set listeners for all ids in document
function setMe() {
var i;
for (i=0; i<ids.length; i++) {
var evalue = ids[i];
var elistener = document.getElementById(evalue);
alert(evalue);
if (evalue.addEventListener){
elistener.addEventListener('click', clikDisplay, false);
} // For IE
else if (elistener.attachEvent){
elistener.attachEvent('onclick', clikDisplay);
}
}
}
</script>


</head>

<body onload = listMe();>

<div id="alac" >Div alac Listener text.
</div>
<div class="menu_tab" id="alac1" style="display:none;">
<span style="color:#000000;">On alac click, displays this div/text.</span>
</div>

</body>
</html>

daveVk

2:09 am on Oct 24, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



if (evalue.addEventListener)

should this be ?

if (elistener.addEventListener)

also

var ab = el +"1";

should this be ?

var ab = el.id + "1";

DS_Cole

4:37 am on Oct 24, 2010 (gmt 0)

10+ Year Member



Apologies for the evalue/elistener mistake - too many coding changes trying to find the problem. I get an undefined for el.id. That rings a bell. I'll look into it tomorrow. Appreciate the help a bunch.

rocknbil

5:37 pm on Oct 24, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Don't re-invent the wheel. You're forcing yourself to a specific naming convention (selector+integer) and it always leads to difficult maintenance. This should lead you in the right direction. :-)


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01
Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Use Jquery.</title>
<style type="text/css">
/*Just so you can see where things are*/
p,h1,li { border: 1px solid #d6d6d6; }
</style>
<!-- later versions give a "sizzle" error in FF (?) -->
<script type="text/javascript" src="jquery-1.2.6.min.js"></script>
<script type="text/javascript">
// move me externally
$(document).ready(function(){
// api.jquery.com/has-attribute-selector/
// api.jquery.com/css/
// api.jquery.com/bind/
$('*[id]').css('cursor','pointer'); // for unnatural click objects
$('*[id]').bind('click', function() {
identify_me(this);
});
});
//
function identify_me(obj) {
alert(obj.id);
return false;
}
//
</script>
</head>
<body>
<h1>Attach Click Event to All ID's</h1>
<p id="some-id">Some id'ed 'graph</p>
<p class="whatever">No ID, no click event</p>
<ul>
<li id="list-1">Click</li>
<li>No Click</li>
<li id="list-2">Click</li>
<li id="list-3">Click</li>
<li id="list-4">Click</li>
</ul>
<p><a href="#" id="some-link">Also returns false</a></p>
</body>
</html>


If you need to access the elements individually and assign different functions to them, you can loop through them like so;

// create an object that is not an array but acts
// like an associative array.
var functions = {
'some-id':'some_function',
// etc.
};


var elements = $('*[id]');
for (j=0;j<elements.length;j++) {
$('#'+elements[j].id).bind('click', function() {
functions[this.id](this);
});
}


The last bit is probably syntactically incorrect and needs playing with but can be done.

DS_Cole

3:59 pm on Oct 25, 2010 (gmt 0)

10+ Year Member



rocknbil: Excellent advice. After a couple more hours of looking at the DOM API and wondering why they don't tell you what the dispatchEvent method parameters are, I looked at jquery - lightweight footprint with a small learning curve. Looks easily adaptable. I've been writing my own code since 1996. I think I'll switch. It's guaranteed, right? : )

rocknbil

5:14 pm on Oct 25, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Nothing is guaranteed, and there *are* a few bugs [bugs.jquery.com] with jQuery, but overall, I'd say yes. I haven't encountered any except for the "sizzle" error for later versions in my comment above, but it's probably something I'm doing wrong.

I too have been swimming upstream for far too long. LOL . . . however it's always good to explore the specifics of what's going on - if you have the time. That's what it gets down to, I think . . .

DS_Cole

12:22 am on Oct 26, 2010 (gmt 0)

10+ Year Member



The problem with the original script was, the DOM event handler sends an object that is accessed by
this
, which I wasn't using. The id of the element that had the mouse event is accessed by
this.id
. The basic code is for a simple menu system so when a menu element (div, p, ol... with an id) is clicked, it displays another element with the same id incremented by 1. You could also use class, or even the title. Additional handlers can be added for mouseover, and other mouse events.

Advantages: unobtrusive HTML (no scripting in the html), automatically gathers the page element ids and sets event handlers (no scripting associations required). Simplicity of naming. More of the work can be done with jquery.

Disadvantages: It has the extensibility limitation mentioned previously in that it only adds "1" to the div id to get the div id to display.

If it doesn't work for you, just reply to this post and I'll provide a link to a working example. (The HTML for this is in a previous post.) Thanks for everyone's help, and other's examples. The working code, which I need to convert all to jquery is:

<script type="text/javascript" src="../js/jquery-1.4.3.min.js">
</script>

<script type="text/javascript" > //<![CDATA[
// When the page is ready
$(document).ready(function(){
listMe();
});
//]]>

var ids = [];

// Function to list all ids - this works in both ie and FF. ("push" adds elements to the ids array and returns length.)
function listMe() {
var allTags = document.body.getElementsByTagName('*');
for (var tg = 0; tg< allTags.length; tg++) {
var tag = allTags[tg];
if (tag.id) {
ids.push(tag.id);
var el = tag.id;
}
}
setMe();
}

// This function displays the element on click.
function clikDisplay(el) {
alert("This is clickDisplay fired.");
alert(this.id);
var ab = this.id +"1";
alert(ab);
ab = document.getElementById(ab);
ab.style.display = "block";
}

/* This function sets the event listeners. It needs another else/alert for older browsers (pre-IE6 and NS4)*/
function setMe() {
var i;
for (i=0; i<ids.length; i++) {
//alert(ids[i]);
var evalue = ids[i];
var elistener = document.getElementById(evalue);
if (elistener.addEventListener){
elistener.addEventListener('click', clikDisplay, false);
}
else if (elistener.attachEvent){
elistener.attachEvent('onclick', clikDisplay);
}
}
}
</script>