Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use JQuery to listen for all clicks on the html body Except a specific div and its children

I am trying to use a jQuery listener to listen for a users clicks on the html body and perform a specific function if anywhere on the body has been clicked except for a specific div and the children within that div.

The idea is that the div is a popup type element and instead of having to have a close button that the user can click, they should just be able to click anywhere on the page besides that div and it will automatically close.

I have been using this listener:

var initialClick = false;
$('body').on('click.addPhoneListeners', function(event) {
    var target = EventUtility.getTarget(event);
    if(initialClick) {
        if(target.parentNode.id != clone.id && target.id != '') {
            finish();
        };
    }
    initialClick = true;
});

Which listens for all clicks on the body and unless the click comes from within the element I want the user to be able to interact with, it closes. Unfortunately this only works with a div that has only one level of children. As soon as I start getting multiple hierarchies such as this:

<div id="addressContainer">
    <div id="address" class="hidden row">
        <div class="row">
            <div id="address.primary" class="hidden">P</div>
            <div id="address.type"></div>
            <div id="address.street"></div>
            <div id="address.editButton" class="hidden"><a id="addressEditButton">Edit</a></div>
            <div id="address.deleteButton" class="hidden"><a id="addressDeleteButton">Delete</a></div>
        </div>
        <div class="row">
            <div id="address.city"></div>
            <div id="address.state"></div>
            <div id="address.zip"></div>
        </div>
        <input type="hidden" id="address.id"></input>
    </div>
</div>

The target.parentNode.id gives me the objects parent element as opposed to the addressContainer id and thus does not work. Is use the top level parent from within nested elements? Other elements will be using this same code, so it has to work on both divs with just one level and div's with multiple.

UPDATE: Found a few excellent solutions, thanks guys. I do however have one other question. Refer to my code above where I set an initialClick boolean to false, then set it to true. I am doing this because for some reason if I don't, when I go to add the popup div, the initial click from the button used to set that popup fires the listener and closes the popup before I have a chance to do anything. This has been my solution around the problem, but is that the only way? Or am I just setting the listener slightly incorrect?

like image 587
ryandlf Avatar asked Jan 09 '12 14:01

ryandlf


People also ask

What is Click () method?

The click() method simulates a mouse-click on an element. This method can be used to execute a click on an element as if the user manually clicked on it.

Can you click on a div HTML?

We simply add the onlcick event and add a location to it. Then, additionally and optionally, we add a cursor: pointer to indicate to the user the div is clickable. This will make the whole div clickable.

What is difference between click and Onclick in jquery?

So onclick creates an attribute within the binded HTML tag, using a string which is linked to a function. Whereas . click binds the function itself to the property element.

Can you give a div onclick?

We can bind a JavaScript function to a div using the onclick event handler in the HTML or attaching the event handler in JavaScript. Let us refer to the following code in which we attach the event handler to a div element. The div element does not accept any click events by default.


2 Answers

I usually do something like this:

$(document).click(function(e) {
  // hide popup
});

$('#popup_div').click(function(e) {
  e.stopPropagation();
});

That way the clicks from your popup never propagate to the document, so the close function never fires.

like image 200
Mathletics Avatar answered Oct 23 '22 02:10

Mathletics


Replace

if(target.parentNode.id != clone.id)

with

if ($(target).closest("#" + clone.id).length === 0)

(I left the second clause alone since it didn't seem related to your question.)

This tries to find the closest ancestor with ID equal to clone.id. If none is found, an empty jQuery object is returned (i.e. one with length === 0), which is what we test for.


Incidentally: jQuery normalizes event.target, so you can just use that instead of whatever custom monstrosity EventUtility.getTarget(event) embodies.

like image 2
Domenic Avatar answered Oct 23 '22 02:10

Domenic