элемент javascript body.onclick связанное событие setTimeout - PullRequest
3 голосов
/ 24 ноября 2010

Я хочу сделать всплывающее окно div, которое исчезает, когда я нажимаю за его пределами. Мне нужен чистый JS, а не JQuery или что-то. Поэтому я делаю следующее ...

функция, которая заставляет div исчезать:

function closePopUps(){
    if(document.getElementById('contact-details-div'))
        document.getElementById('contact-details-div').style.display = 'none';
    //...same code further...
} 
function closePopUpsBody(e){
    //finding current target - http://www.quirksmode.org/js/events_properties.html#target
    var targ;
    if (!e) var e = window.event;
    if (e.target) targ = e.target;
    else if (e.srcElement) targ = e.srcElement;
    if (targ.nodeType == 3) // defeat Safari bug
        targ = targ.parentNode;

    //is we inside div?    
    while (targ.parentNode) {
        //filtering "Close" button inside div
        if (targ.className && targ.className == 'closebtn')
            break;
        if (targ.className && targ.className == 'contact-profile-popup')
            break;
        targ = targ.parentNode;
    }
    //if it not a div, or close button, hide all divs and remove event handler
    if ((targ.className && targ.className == 'closebtn')
        || !(targ.className && targ.className == 'contact-profile-popup')) {
        if(document.getElementById('contact-details-div'))
            document.getElementById('contact-details-div').style.display = 'none';
        //...some more code here...

        document.body.onclick = null;
    }
}

возможно, этот код некрасив, но это не главная проблема ...

Основная проблема - когда я присоединяю событие к телу, оно выполняется немедленно! и div исчезает сразу, я даже не вижу этого.

<tr onclick="
closePopUps();
document.getElementById('contact-details-div').style.display='block';
document.body.onclick = closePopUpsBody;
return false;">

если я не использую скобки, он не будет выполнен?

document.body.onclick = closePopUpsBody(); //this executes
document.body.onclick = function(){closePopUpsBody()}; //this is not
document.body.onclick = closePopUpsBody; //this is not

наконец я закончил с этим решением

<tr onclick="
closePopUps();
document.getElementById('contact-details-div').style.display='block';
setTimeout('document.body.onclick = closePopUpsBody;', 500);
return false;">

но я думаю, что это безумие. итак, что я делаю не так?

Ответы [ 3 ]

3 голосов
/ 24 ноября 2010

Вы должны прекратить всплеск событий. Простой [ демо ]

var box = document.getElementById('box');
var close = document.getElementById('close');

// click on a box does nothing
box.onclick = function (e) {
  e = e || window.event;
  e.cancelBubble = true;
  if (e.stopPropagation)
    e.stopPropagation();
}

// click everywhere else closes the box
function close_box() {
  if (box) box.style.display = "none";
}

close.onclick = document.onclick = close_box;
2 голосов
/ 24 ноября 2010

Обычно события распространяются на родителей. Если вы нажмете на <div>, то для <body> также будет вызываться onClick.

Первое: отладьте порядок вызываемых функций: поместите window.dump("I am called!") в свои обработчики.

Полагаю, вам нужно вызвать event.stopPropagation() где-нибудь в вашем коде. (См. https://developer.mozilla.org/en/DOM/event)

О вопросе в скобках:

document.body.onclick = closePopUpsBody;//this is not
document.body.onclick = closePopUpsBody();//this executes

Это выполняется, потому что вы вызываете функцию closePopUpsBody (), чтобы вернуть значение, которое будет присвоено свойству onclick. В JavaScript имя функции представляет объект функции (как любая другая переменная). Если вы ставите скобки после имени переменной, вы говорите: «Выполните это для меня, как функцию».

1 голос
/ 24 ноября 2010

Вот полный пример того, как вы могли бы сделать это.

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title></title>
    <style>
        body { font-family: Tahoma; font-size: 1.1em; background: #666666; color: White; }
        #layer01 { border: 1px solid black; width: 200px; height: 100px; position: absolute; 
                   top: 100px; left: 100px; background: white; padding: 10px; color: Black;
                   display: block; }
    </style>
</head>
<body>
    Click anywhere outside the layer to hide it.

    <div id="layer01"> Test Layer </div>

    <script type="text/javascript">
        isIE = (window.ActiveXObject) ? true : false;

        document.onclick = function (e) {
            var l = document.getElementById("layer01");

            if (!isIE && e.originalTarget == l)
                e.stopPropagation();
            else if (isIE && event.srcElement == l)
                event.cancelBubble = true;
            else 
                l.style.display = "none";
        }

    </script>
</body>
</html>
...