1

In my html I have

<div id="map"></div>

#map {
    width: 100%;
    height: 100%;
    background-color: #CCC;
}

that gets dynamically filled with several divs like the following

<div class="basicTiles1" style="left: 8128px; top: 8128px;"></div>

.basictiles1 {
    position: absolute;
    width: 64px;
    height: 64px;
    background-image: url(<snip urlToPng>);
    background-position: 0px 0px;
}

Then an onmousedown event is added to #map like so

$('#map').on('mousedown', function(){console.log("mousedown");});

The event is never triggered. If I don't add the tiles to the map, it works.

I tried doing it with jquery's 'on', 'onmousedown', javascripts 'addEventListener'. The script doesn't have any compilation errors. The event just doesn't seem to trickle down.

Is it because the tiles are position absolute? Is it because they are added dynamically?

Boris Callens
  • 90,659
  • 85
  • 207
  • 305
  • Would be much easier with a jsfiddle to illustrate the problem – mash Jan 27 '13 at 16:11
  • Problem is that in your case all is good before you add tiles, because, after you add tile then map div is behind tile and mousedown will not get trough upper element to lower. – Aivar Jan 27 '13 at 16:18
  • @AivarLuist, indeed. But how to resolve this? They are linked as childs in the dom, so I would think the events would trickle to the parent – Boris Callens Jan 27 '13 at 16:21
  • 1
    If tiles do not need click option itself then you could try to use CSS property pointer-events. Example usage http://stackoverflow.com/questions/3680429/click-through-a-div-to-underlying-elements – Aivar Jan 28 '13 at 09:56
  • @AivarLuist, cool. Can't use it right now, but will become handy in the (near future). Thanks :D – Boris Callens Jan 29 '13 at 12:21
  • You can allso put transparent div above all tiles and add listener to that, and if it is somekind of game map or something like that then you can allways calculate cordinates to determin witch tile you really clicked. All depends what is your final goal. – Aivar Jan 29 '13 at 19:05
  • That too is a good idea! Currently my performance issue is not with the click event (yet), so I'm not going to optimize that until it does pose problems. But you have given me good ideas for the future :) – Boris Callens Jan 31 '13 at 12:29

1 Answers1

3

I understand that when you bind the event, the DIV's are not there yet. Try using delegate instead, like this:

$("#map").delegate("div", "mousedown", function() {
    console.log("mousedown");
});

EDIT: Elaborating The jQuery .on() reference states: "Attach an event handler function for one or more events to the selected elements."

Moreover, when you bind the event directly to your #map it will work as long as you don't cover it with something else (you have to mousedown ON the actual #map element).

The jQuery .delegate() reference states instead: "Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements."

Since you will be adding inner div's -after- binding the event, this exactly fits what you want to do. Specifying the "div" selector actually binds mousedown to any (current or future) div inside #map. You could actually use div.basictiles1 if you have other, non-clickable divs there.

istepaniuk
  • 4,016
  • 2
  • 32
  • 60
  • Thanks, this works, but I don't understand why. Can you elaborate? – Boris Callens Jan 27 '13 at 16:21
  • does it bind the event to all div's under the #map? Because there will be thousands of tiles. Don't know if this is a good idea then – Boris Callens Jan 27 '13 at 16:26
  • 1
    AFAIK, It is indeed a good idea to use `.delegate()` in your case. Take a look at http://www.alfajango.com/blog/the-difference-between-jquerys-bind-live-and-delegate/ – istepaniuk Jan 27 '13 at 16:31