简体   繁体   中英

Make part of div clickable

I'm having trouble with a popup window that, when visible, needs to close when a user clicks on the underlying gray area (the area behind the popup window), and not on the popup window itself.

Is there any way I can achieve this?


HTML

<div>
    <div class="b-popup" id="uploader">
    <div class="b-popup-content" id="uploader">
        Text in Popup<br>
        <a href="javascript:PopUpHide()">Hide popup</a>
    </div>
</div>

CSS

*{
    font-family: Areal;
}
.b-container{
    width:200px;
    height:150px;
    background-color: #ccc;
    margin:0px auto;
    padding:10px;
    font-size:30px;
    color: #fff;
}
.b-popup{
    width:100%;
    min-height:100%;
    background-color: rgba(0,0,0,0.5);
    overflow:hidden;
    position:fixed;
    top:0px;
}
.b-popup .b-popup-content{
    margin:40px auto 0px auto;
    width:600px;
    height: 600px;
    padding:10px;
    background-color: #c5c5c5;
    border-radius:5px;
    box-shadow: 0px 0px 10px #000;
}

JavaScript - jQuery

$('div.b-popup').click(function () {
    PopUpHide();
});

Sample is here: http://jsfiddle.net/p7NbX/15/


I've tried to set function call on div click, but it closes popup if I click on popup content div.

Add a click event listener to the whole .b-popup but close the popup only if the event target is different than the .b-popup-content element ( edit: or any of its children, as pointed out by @BrettCaswell ), for example:

$('.b-popup').on('click', function(e){
    if( ! $(e.target).is('.b-popup-content, .b-popup-content *') ){
        PopUpHide();
    }

});

http://jsfiddle.net/p7NbX/1515/

 $(document).ready(function(){ PopUpHide(); $("#popup1").click(function(e){ if( e.target !== this ) return; PopUpHide(); }); }); function PopUpShow() { $("#popup1").show(); } function PopUpHide() { $("#popup1").hide(); } 
 *{ font-family: Areal; } .b-container{ width:200px; height:150px; background-color: #ccc; margin:0px auto; padding:10px; font-size:30px; color: #fff; } .b-popup{ width:auto; background-color: rgba(0,0,0,0.5); overflow:hidden; position:fixed; top:0px; bottom:0px; left:0; right:0; } .b-popup-content{ margin: 3em auto 0 auto; width: 100px; height: 40px; padding: 0.9em; background-color: #c5c5c5; border-radius:5px; box-shadow: 0.05cm 0.05cm 1em rgba(0,0,0,0.8); } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="b-container"> Sample Text <a href="javascript:PopUpShow()">Show popup</a> </div> <div class="b-popup" id="popup1"> <div class="b-popup-content"> Text in Popup <a href="javascript:PopUpHide()">Hide popup</a> </div> </div> 

Here's an alternative, that boils down to <Element>.addEventListener(<eventName>, <function>.bind(<this>[,<arg1>][,<arg2>]));

bind wraps the intended function, and performs a call on it using additional specified parameters (args). The first parameter of bind will be the this instance of the function. Setting it to undefined will pass the original this instance.


Short Answer (jQuery)

$(document).ready(function()
{
    $("#popup1").hide();
    $('.b-popup').on('click', function(targetId, e){
        console.log("%o %o %o", targetId, e.target.id, e);
        if( e.target.id !== targetId ){ return; }
        PopUpHide();
    }.bind(undefined, "popup1"));       
});


function PopUpShow(){
    $("#popup1").show();
}
function PopUpHide(){
    $("#popup1").hide();
}

the fiddle: http://jsfiddle.net/p7NbX/1514/


Original Answer

The following sample is really more geared for reuse and oop (ish).

/* I'm going to declare and keep my initialization code in an object. 
   that I'll run when the document is ready. 
*/
var MyHandlerManager = 
{     
    'elms' : [],
    'init': function()
    {            
        var CssSelector = "div.b-popup";
        var elms = document.querySelectorAll(CssSelector);
        for (var i = 0; i < elms.length; i++)
        {                
            elms[i].addEventListener('click', MyHandlers.HidePopupHandler.bind(undefined, elms[i].id));                
        }

        /* you can skip this. 
           You don't need to keep a reference to elms (NodeList) for the EventListeners to function properly.  
        */
        MyHandlerManager.elms = elms;
    }
};

You can do anonymous functions instead of referencing the existing functions as handlers, but I like to declare my handlers this way..

This bring some debugging and runtime considerations; like,

  • clearing out the console.logs lines easier and/or,
  • replacing the handler functions at some later point if need be necessary.

var MyHandlers =
{
    "ShowPopupHandler": function (targetId, e)
    {
        console.log("targetId: %o :: e.target.id: %o :: EventArgs: %o", targetId, e.target.id, e);
        if (e.target.id !== targetId) { return; }

        var elm = document.getElementById(targetId);            
        elm.style.display = "block";
    },
    "HidePopupHandler": function (targetId, e) 
    {
        console.log("targetId: %o :: e.target.id: %o :: EventArgs: %o", targetId, e.target.id, e);
        if (e.target.id !== targetId) { return; }

        var elm = document.getElementById(targetId);            
        elm.style.display = "none";
     }
};

$(document).ready(function(){
    PopUpHide();
    MyHandlerManager.init();
    /* Again, you could just take the code in the init() function
       and run it here..
       using 'bind' to wrap the intended function and call it, passing the elm.id as an argument (first arg) into anonymous functions. 
    */
});

function PopUpShow(){
    $("#popup1").show();
}

function PopUpHide(){
    $("#popup1").hide();
}

This should work, it worked for me (courtesy of dystroy):

Original Answer

If needed, you might want to use the clicked element position and size, using $(this).offset() , $(this).width() and $(this).height(). For example :

$('mydivselector').click(function(e) {
  if (e.pageY > $(this).offset().top + 0.5*$(this).height()) {
      // bottom was clicked

 } else {
      // up of the div was clicked

 }
});

If you want to prevent default action and event propagation, return false from the event handler.

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