views:

368

answers:

4

I have run into a strange problem, i am creating a lot of dynamically divs. And i recently found out that some of my divs doesn't fire the onclick event? All the divs are created using the same template, so why are some not working? Most of the time, its the 4-5 from the bottom. If you click on one of the others and then try again, you might get one of those to trigger. But only sporadically.

Code to create the divs:

// Code to loop thru the number of players and create the divs accordingly
for (fieldNumber = 0; fieldNumber < 18; fieldNumber++) {
        var holderDiv = CreateDiv('gameCellLarge', '');
        holderDiv.style.width = 150 + extraCellWidth + 'px'; // Ändra storleken beroende på antalet spelare

        if (fieldNumber == 0 || fieldNumber == 6 || fieldNumber == 8 || fieldNumber == 17)
            newField = CreateDiv('gameCellMedium borderFull gameText', gameText[fieldNumber]);
        else
            newField = CreateDiv('gameCellMedium borderWithoutTop gameText', gameText[fieldNumber]);
        holderDiv.appendChild(newField);

        for (playerNumber = 0; playerNumber < players.length; playerNumber++) {            
            holderDiv.appendChild(players[playerNumber].InitField(fieldNumber));
        }
        gameFieldDiv.appendChild(holderDiv);
    }




GameField.prototype.InitField = function(fieldNumber) {
var newField = document.createElement("div");
if (fieldNumber == 0 || fieldNumber == 6 || fieldNumber == 8 || fieldNumber == 17)
    newField.className = 'gameCellSmall borderFull gameText gameTextAlign';
else
    newField.className = 'gameCellSmall borderWithoutTop gameText gameTextAlign';

var instance = this;
if (fieldNumber == 6 || fieldNumber == 7 || fieldNumber == 17) { }
else
    newField.onclick = function() { instance.DivClick(fieldNumber); return false; }

this.fields[fieldNumber] = newField;
this.score[fieldNumber] = 0;
return newField;
}

I added the return false to the click function, but it still behaves strangely. Why are some not triggering? I create around 18 divs / player. But it happens even if i just create one player.

Do i perhaps need to cancel the event once i am done with it? (Like the return false; is trying to do) Works sometimes but not always...

I have run out of ideas, here is a link to the script. Maybe i have just missed something. The script I have changed it a bit, so just press the button and click on the lower end of the game field (yatzy, kåk etc). It should popup alerts when clicked. Sometimes they work sometimes they don't.

A: 

At least three of them are not triggering any events, because they have no onClick handler:

if (fieldNumber == 6 || fieldNumber == 7 || fieldNumber == 17) { }

I'm not sure that that's what you're talking about, though, if you say that the bottom 4 or 5 divs do nothing.

Ian Clelland
They are lined up from 0 - 17. But from around 12-13, they stop triggering. They only sporadically triggers.I have gone through the code and the fieldNumbers are correct, it goes from 0 to 17 and skips giving onclick to the number 6, 7 and 17
Patrick
+2  A: 

Well, first of all, I'm going to assume that the ones that are not working are NOT being created with a fieldNumber of 6, 7, or 17.

That aside... If the problem happens to be in stopping event propagation, you might try something like the following:

newField.onclick = function(e) {
     if (!e) var e = window.event;
     instance.DivClick(fieldNumber);
     if (e.preventDefault) e.preventDefault();
     else e.returnValue=false;
     return false;
}

Other than that, I can't really test anything to figure out the issue.

Chibu
The if-statement produces the following, " 'preventDefault' is null or not an object" when i try to run it.
Patrick
Oh right, I missed a line of code (apparently you're using Internet Explorer :P)Updated.
Chibu
+2  A: 

Your code appears to fine, it looks like the CSS is messing things up.

The problem is that the 'gameCellLarge' divs are getting out of phase with the 'gameCellMedium' and 'gameCellSmall' divs that they enclose. This is because they have a 'position:relative;' style attribute which allows them to wander from where they should be. (You can visually see what's happening by using the debugger that comes with most browsers, e.g. Firebug with Firefox, or the Developer Tools with Chrome.)

Only the portion of a 'gameCellSmall' box that overlaps with its enclosing 'gameCellLarge' box is clickable. You'll find that all the boxes have a clickable region, but that the region shrinks as you get to the bottom of the table. That's because the large cells get more and more out of phase with the small cells as you go down the table. But if you click toward the top of a box it will work, although if you don't realize this it will seem that the response is random and sporadic.

Anyways, you can fix this problem by removing 'position:relative' from the .gameCellLarge style. This doesn't seem to make a difference to the layout, so it should be OK to do this. You could also specify 'border:1px solid black;' in the .gameCellLarge style.

Hope this helps.

brainjam
+1. You are right.
Chetan Sastry
Thanks a lot for the help and the explanation.
Patrick
+1  A: 

This is not a direct answer to your problem, but a situation like this is a good candidate for event delegation. Just google for it and you will find plenty of sources. Here is a good one - http://www.sitepoint.com/blogs/2008/07/23/javascript-event-delegation-is-easier-than-you-think/

The way it works is by attaching an event handler to the parent container and catch the events that bubble up. You can then obtain the source of the event (event.srcElement in IE and event.target in firefox) and do stuff based on it. In your case, if you attach an unique id to each of your clickable divs, you can check against it and call the appropriate event handler.

It is a much more cleaner way of doing things rather than attaching many event handlers.

[Edit]: Found your problem. Basically, your gamecellLarge divs have no heights because they contain only floated elements. You have tried to remediate that by adding height: 30px but that causes the div to overlap the next set of divs. If you have Firebug, highlight the elements and see the problem. You click always works if you click the top 1/3rd of the box.

Change the style to something like this and it should work.

.gameCellLarge {
    clear: both;
    overflow: hidden;
    width: 200px;
    zoom: 1
}
Chetan Sastry
Thanks a lot for the help and the explanation.
Patrick