简体   繁体   中英

How to make an entire div clickable except a deep level child div?

I want to make an entire div clickable except a child div. This child div is not an immediate child of the div, rather it is in a few level deeper. I would like to dynamically exclude this child div by just passing div id or class name.

I tried to solve it with jQuery ".not()" and ".children()" methods, which works. But its static in a sense that I need to know in which level the div is and need to align the methods accordingly. However, I want something dynamic which will take only the div's class name or id, and find it from the DOM tree and exclude it from the new DOM object chain so that the jQuery ".click" and ".hover" function can be applied on the entire div except that particular div.

I have created a dummy example of my problem. In the example, I want to make the entire div (ie, id = main1) hyperlinked except the "#d3" div.

Here is my JSFiddle: JSFiddle

Example Code:

HTML:

<!DOCTYPE HTML>
<html>
    <head>
        <meta charset="utf-8">
            <title>
                Untitled Document
            </title>

        </meta>
    </head>
    <body>
        <div class="center border divmain1" id="main1">
            <a href="https://www.google.ca" style="display: block">
                link
            </a>
            <p>
                Main
            </p>
            <div class="border-thin divd1" id="d1">
                <p>
                    d1
                </p>
            </div>
            <div class="border-thin divd2" id="d2">
                <p>
                    d2
                </p>
                <div class="border-thin divd3" id="d3">
                    <p>
                        d3
                    </p>
                    <div class="border-thin divd4" id="d4">
                        d4
                    </div>
                    <div class="border-thin divd5" id="d5">
                        d5
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>

CSS:

.border {
  border: 5px solid RosyBrown;
}
.border-thin {
  border: 2px solid RosyBrown;
}
.divmain1 {
  width: 90%;
  margin: 0 auto 0 auto;
  overflow: hidden;
}
.divd1 {
  width: 30%;
  float: left;
}
.divd2 {
  width: 60%;
  float: right;
  margin: 0 0 0 3.5%;
}
.divd3 {
  margin: auto;
  width: 90%;
}
.divd4 {
  width: 30%;
}
.divd5 {
  width: 30%;
}

jQuery:

// find elements
var main1 = $("#main1")
var d3 = $("#d3")

// handle click and hover pointer
main1.on("click", function(){
  window.open('https://www.google.ca');
});

main1.hover(function(){
  $(this).css("cursor", "pointer");
});

Could anyone please help me on how to make an entire div clickable and dynamically exclude a child div?

In your jQuery you can run

event.stopPropagation();

within a click event for the div child you don't want to trigger the initial function.

use cancelBubble

for example, to disable your root event on "#d5" div

$('#d5').on('click', function(e){
    // stop the event from bubbling.
    e.cancelBubble=true
});

I am not much of a fan of jQuery but I can tell you that this can be done with pure JavaScript. All you have to do is to implement an event listener to the top level div and see if the clicked element or it's parent has the targeted class.

Let's take this HTML markup for an example where we will trigger an alert " Target Locked " when someone clicked anything inside divd4 else " General Action "

 function HasSelfClassOrParent(element, classname) { if (element.classList && element.classList.contains(classname)) return true; return element.parentNode && HasSelfClassOrParent(element.parentNode, classname); } let divd2 = document.querySelector(".divd2") let target = 'divd4' divd2.addEventListener("click", function(event) { let isTargetOrChild = HasSelfClassOrParent(event.target, target) if (isTargetOrChild) { alert("Target Locked") } else { alert("General Action") } }) 
 .border { border: 5px solid RosyBrown; } .border-thin { border: 2px solid RosyBrown; padding: 20px; margin-bottom: 10px } .divd4{ background: #64B448; color: #fff; cursor: pointer; } 
 <p>Click on div four and see what happens</p> <div class="border-thin divd2" id="d2"> <p>I am Div 2</p> <div class="border-thin divd3" id="d3"> <p>I am Div 3</p> <div class="border-thin divd4" id="d4"> <p>I am a simple paragraph inside div four</p> <p>I am a another paragraph inside div four</p> </div> <div class="border-thin divd5" id="d5"> I am Div 5 </div> </div> </div> 

The key thing here is to pass the event object so you can check what is the element actually receiving the click .

Since #d3 contains both #d4 and #d5 I'm assuming you don't want those elements to fire either.

If that's the case, you can use Node.contains() to check if the element is a descendant of your target element.

The Node.contains() method returns a Boolean value indicating whether a node is a descendant of a given node, ie the node itself, one of its direct children, [...]

If you just want to prevent the action for the element #d3 itself, you don't need to d3.contains and just if (e.target != d3) should do.

 // find elements var main1 = $("#main1") var d3 = $("#d3").get(0) // Get the HTMLElement // handle click and hover pointer main1.on("click", function(e) { if (!d3.contains(e.target)) { console.log("I'll open a window"); } else { console.log("I'm " + e.target.id + " and won't open a window") } }); main1.hover(function() { $(this).css("cursor", "pointer"); }); 
 .border { border: 5px solid RosyBrown; } .border-thin { border: 2px solid RosyBrown; } .divmain1 { width: 90%; margin: 0 auto 0 auto; overflow: hidden; } .divd1 { width: 30%; float: left; } .divd2 { width: 60%; float: right; margin: 0 0 0 3.5%; } .divd3 { margin: auto; width: 90%; } .divd4 { width: 30%; } .divd5 { width: 30%; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="center border divmain1" id="main1"> <a href="https://www.google.ca" style="display: block">link</a> <p> Main </p> <div class="border-thin divd1" id="d1"> <p>d1</p> </div> <div class="border-thin divd2" id="d2"> <p>d2</p> <div class="border-thin divd3" id="d3"> <p>d3</p> <div class="border-thin divd4" id="d4">d4</div> <div class="border-thin divd5" id="d5">d5</div> </div> </div> </div> </body> </html> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM