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.
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.
Share Improve this question edited Mar 21, 2010 at 19:46 Patrick asked Mar 16, 2010 at 18:17 PatrickPatrick 5,60210 gold badges55 silver badges107 bronze badges 04 Answers
Reset to default 5 +100Your code appears to be 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 es 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.
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.
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./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
}
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.