【问题标题】:Make part of div clickable使部分 div 可点击
【发布时间】:2015-02-03 16:14:23
【问题描述】:

我遇到了一个弹出窗口的问题),而 not 在弹出窗口本身上。

有什么方法可以实现吗?


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();
});

样品在这里:http://jsfiddle.net/p7NbX/15/


我尝试在 div 点击时设置函数调用,但如果我点击弹出内容 div,它会关闭弹出窗口。

【问题讨论】:

  • 在浏览器中... html 元素是最小的交互单元。所以......把任何html元素放在那个地方。将处理程序绑定到该元素的单击事件。
  • “底层灰色区域”是弹出掩码还是链接文本周围的包装?
  • @isherwood,不,如果您点击显示弹出窗口,弹出窗口将在深灰色背景上打开

标签: javascript jquery html javascript-events


【解决方案1】:

为整个.b-popup 添加一个点击事件监听器,但仅当事件目标与.b-popup-content 元素不同时才关闭弹出窗口(edit: 或其任何子元素,正如@BrettCaswell 所指出的那样),例如:

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

});

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

【讨论】:

  • @BrettCaswell 你说得对,我只考虑 OP 代码的范围,而不是更一般的情况。固定。
  • pawel,是的,很好。我删除了我之前的评论,因为它听起来有点粗糙。对此感到抱歉。
【解决方案2】:

$(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>

【讨论】:

  • 在不添加其他部分的情况下将无法正确运行 sn-p.. 它会稍微偏离您的 jQuery 实现,但至少可以运行..
【解决方案3】:

这是一个替代方案,归结为&lt;Element&gt;.addEventListener(&lt;eventName&gt;, &lt;function&gt;.bind(&lt;this&gt;[,&lt;arg1&gt;][,&lt;arg2&gt;]));

bind 包装预期的函数,并使用附加的指定参数(args)对其执行调用。 bind 的第一个参数将是函数的 this 实例。将其设置为 undefined 将传递原始的 this 实例。


简答 (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();
}

小提琴:http://jsfiddle.net/p7NbX/1514/


原答案

以下示例确实更适合重用和 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;
    }
};

您可以执行匿名函数而不是将现有函数作为处理程序引用,但我喜欢这样声明我的处理程序..

这带来了一些调试和运行时的考虑;喜欢,

  • 更容易清除 console.logs 行和/或,
  • 如有必要,稍后替换处理函数。

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();
}

【讨论】:

    【解决方案4】:

    这应该有效,它对我有效(由dystroy提供):

    Original Answer

    如果需要,您可能希望使用被点击的元素位置和大小,使用 $(this).offset()、$(this).width() 和 $(this).height()。例如:

    $('mydivselector').click(function(e) {
      if (e.pageY > $(this).offset().top + 0.5*$(this).height()) {
          // bottom was clicked
    
     } else {
          // up of the div was clicked
    
     }
    });
    

    如果要阻止默认操作和事件传播,请从事件处理程序返回 false。

    【讨论】:

    • 这很有趣,但它解决了一个完全不同的问题和关注点。这个问题只是关于处理冒泡事件。
    猜你喜欢
    • 2010-11-01
    • 1970-01-01
    • 2013-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 2011-06-07
    相关资源
    最近更新 更多