2

I have an eventHandler on the entire document, targeting the element with a specific id. That targeted element is a div with some content in it. The eventHandler checks for the 'click'-action. However, whenever I click one of the elements inside the div, it does not activate. Therefore I have to click on the edge of the div for the eventHandler to activate.

Any way to fix this? I was tempted to add an a-element with height/width = 100%, but cannot find a nice way to have it execute a JS function and not just redirect to a link.

Edit 1: here is what's going on:

var inner = createDiv(['page-content', 'small-page-content', 'hover']);

document.addEventListener('click', function (e) {
  if (hasId(e.target, index.toString())) {
    makeLarge(index);
  }
}, false);

function hasId(elem, id) {
    return elem.id == id;
}

function createDiv(classes=[]) {
  var div = document.createElement('div');
  for (var i = 0; i<classes.length; i++) {
    div.classList.add(classes[i]);
  }
  return div;
}

index.toSring() is the id of the div. The div contains: 1 img element, 1 h1 element and 2 sub-divs which each contain a h3 element and an ol. I want the WHOLE div with id index.toString() to be clickable. Right now, only the edges is clickable. Clicking the image etc. does not work.

Edit 2: https://jsfiddle.net/1j3rrtqg/2/ Notice that the text is not clickable, but the edge of the div it (where the div is not covered by another element).

Plain JS please. No jQuery.

Bugs
  • 4,491
  • 9
  • 32
  • 41
vegarab
  • 309
  • 1
  • 10
  • 2
    Don't be so rough for yourself. Anyways - some code example would be helpful. – kind user Nov 08 '17 at 15:17
  • @Kinduser Added some code now. – vegarab Nov 08 '17 at 15:22
  • By default, any click inside the div should bubble up to it and hit your listener. Have you checked if any of the inner elements have listeners that deliberately stop the event from propagating? – Max Nov 08 '17 at 15:27
  • @Max They don't have any listeners. – vegarab Nov 08 '17 at 15:29
  • @VegarAndreasBergum it's a hack, but have you tried setting the last arg of `addEventListener` to `true`? That way your listener should trigger before anything inside the div sees the click at all. – Max Nov 08 '17 at 15:30
  • @Max Had no effect sadly. – vegarab Nov 08 '17 at 15:33
  • 1
    What's the `makeLarge()` function? Can you post a runnable snippet in your answer (https://meta.stackoverflow.com/q/358992/82548) to illustrate your problem, showing the "*[mcve]*" code? – David Thomas Nov 08 '17 at 15:46
  • https://jsfiddle.net/1j3rrtqg/2/ Notice that the text is not clickable, but the edges of the div is. – vegarab Nov 08 '17 at 19:10
  • Please don't add _solved_ into the title. By accepting an answer you're telling others that this has been solved. Thank you. – Bugs Nov 09 '17 at 12:52

3 Answers3

1

This solution does not make the div clickable in itself. Take this as a different approach to achieving what you're after by altering your logic a bit. When you check whether e.target equals #target you could also check whether e.target is a descendant of #target.

Slightly modifying this answer we can do this using the following function:

function isDescendant(parentId, child) {
     var node = child.parentNode;
     var parent = document.getElementById(parentId);
     while (node != null) {
         if (node == parent) {
             return true;
         }
         node = node.parentNode;
     }
     return false;
}

You can then change your condition to if (hasId(e.target, 'target') || isDescendant('target', e.target)).

See the result in this updated JSFiddle

agrm
  • 3,735
  • 4
  • 26
  • 36
0

I would probably add a div with the class "overlay", give this div a z-index of 100 and a width and hight of 100%. If in the div#index something need to be clicked you can add an style attr that will make the z-index: 0 or the give it a pointer-events:none.

this would look something like this:

var indexOverlay = document.querySelector('.overlay');

indexOverlay.addEventListener('click', function(e){
   //Do what you want to do
   e.target.style.zIndex = "-1";
   e.target.style.pointerEvents = "none";
)};
jasper
  • 937
  • 1
  • 9
  • 22
0

The reason that only the edges of your div are clickable is that the child elements do not share the id of the div (nor should they).

You coud, as @jasper suggests, overlay a div on top of your existing div to catch the clicks but that solution is likely to introduce a new set of problems (i.e., what if the user wants to select text in that div, or needs to fill out an input in that div?)

The solution I would go with instead in this situation is to use event delegation.

Updated fiddle or inline example:

(function () {
    "use strict";
    var target = document.getElementById('target'),
        sayHeyo = function (elem) {
            alert('heyo from ' + elem);
        };
    target.addEventListener('click', function (e) {
      console.log(e.target.tagName + ' was clicked');
      sayHeyo(e.target.tagName);
    }, false);
}());
#target {
  border: 1px solid;
  background-color: red;
}
<div id="outer">
  <div id="target">
  <h1>
  I'm a clickable H1 element! <span>I'm a clickable SPAN element inside the H1 element!</span>
  </h1>
  </div>
  <div id="not-target">
  <h1>
  I'm another H1, not inside #target and therefore not clickable. <span>This is a SPAN (also not inside #target and therefore not clickable either)!</span>
  </h1>
  </div>
</div>
pete
  • 24,141
  • 4
  • 37
  • 51