2013-07-24 6 views
9

Я пытаюсь скрыть Bootstrap Popover, когда пользователь щелкает где-нибудь вне popover. (Я действительно не знаю, почему создатели Bootstrap решили не предоставлять эту функциональность.)Скрытие Bootstrap Popover на Click Outside Popover

Я нашел следующий код on the web, но я действительно не понимаю.

// Hide popover on click anywhere on the document except itself 
$(document).click(function(e) { 
    // Check for click on the popup itself 
    $('.popover').click(function() { 
     return false; // Do nothing 
    }); 
    // Clicking on document other than popup then hide the popup 
    $('.pop').popover('hide'); 
}); 

Главное я считаю запутанным является линия $('.popover').click(function() { return false; });. Разве эта строка не добавляет обработчик события для события click? Как это предотвращает вызов popover('hide'), который следует из скрытия popover?

И кто-нибудь видел лучшую технику?

Примечание: Я знаю, что варианты этого вопроса заданы здесь раньше, но ответы на эти вопросы включают код более сложный, чем код выше. Так что мой вопрос действительно о выше

+0

Прочтите это: http: // stackoverflow.com/questions/1357118/event-preventdefault-vs-return-false – Icarus

+0

@Icarus: Спасибо, но это действительно не отвечает на мой вопрос. Я знаю, что возврат false останавливает дальнейшую обработку, но как добавление обработчика кликов изменяет поведение следующей строки? И разве это не остановит клик от работы после закрытия popover? –

+0

Этот код делает именно то, что вы описали. Каждый раз, когда кто-то щелкнет в любом месте документа (включая '.popover'), он добавит прослушиватель событий, который абсолютно ничего не делает. это просто пустая трата памяти, поскольку на одном и том же элементе может быть много прослушивателей событий, и они просто собираются друг на друга. – Dogoku

ответ

8

код, который я сделал http://jsfiddle.net/BcczZ/2/, который, надеюсь, ответ на ваш вопрос

Пример HTML

<div class="well> 
    <a class="btn" data-toggle="popover" data-content="content.">Popover</a> 
    <a class="btn btn-danger bad">Bad button</a> 
</div> 

JS

var $popover = $('[data-toggle=popover]').popover(); 

//first event handler for bad button 
$('.bad').click(function() { 
    alert("clicked"); 
}); 


$(document).on("click", function (e) { 
    var $target = $(e.target), 
     isPopover = $(e.target).is('[data-toggle=popover]'), 
     inPopover = $(e.target).closest('.popover').length > 0 

    //Does nothing, only prints on console and wastes memory. BAD CODE, REMOVE IT 
    $('.bad').click(function() { 
     console.log('clicked'); 
     return false; 
    }); 

    //hide only if clicked on button or inside popover 
    if (!isPopover && !inPopover) $popover.popover('hide'); 
}); 

Как я уже говорил в моем комментарии , обработчики событий не перезаписываются, они просто складываются. Поскольку на кнопке .bad уже есть обработчик событий, он будет запущен вместе с любым другим обработчиком событий.

Откройте консоль в jsfiddle, нажмите 5 раз на странице (а не кнопку popover), а затем нажмите bad button вы должны смотреть щелкнули печататься одинаковое количество раза вы нажали

Надеетесь, что это помогает


PS: Если вы думаете об этом, вы уже видели, как это происходит, особенно в JQuery. Подумайте обо всех $(document).ready(...), которые существуют на странице с использованием нескольких jquery-плагинов. Эта строка просто регистрирует обработчик события на событии ready документа

+0

Хорошо, спасибо за демонстрацию. Глядя на код, который я изначально разместил, это вряд ли кажется идеальным для меня, поскольку я мог бы добавить нового обработчика, который просто возвращает false весь день. Там может расти любое количество из них, если страница не обновляется. Не кажется идеальным вообще. –

+0

просто удалите код, который имеет дело с «плохой кнопкой», и используйте остальную часть моего кода. должен работать так, как вы этого хотите – Dogoku

1

Я просто сделал более основанное на событии решение.

var $toggle = $('.your-popover-button'); 
$toggle.popover(); 

var hidePopover = function() { 
    $toggle.popover('hide'); 
}; 

$toggle.on('shown', function() { 
    var $popover = $toggle.next(); 
    $popover.on('mousedown', function(e) { 
     e.stopPropagation(); 
    }); 
    $toggle.on('mousedown', function(e) { 
     e.stopPropagation(); 
    }); 
    $(document).on('mousedown',hidePopover); 
}); 

$toggle.on('hidden', function() { 
    $(document).off('mousedown', hidePopover); 
}); 
0

короткий ответ вставить это самонастройки min.js

когда всплывающее окно ONBLUR скроет поповер
, когда всплывающее окно больше, чем один, старше поповер будет скрывать

$count=0;$(document).click(function(evt){if($count==0){$count++;}else{$('[data-toggle="popover"]').popover('hide');$count=0;}});$('[data-toggle="popover"]').popover();$('[data-toggle="popover"]').on('click', function(e){$('[data-toggle="popover"]').not(this).popover('hide');$count=0;}); 
0

Non из выше решения работали на 100% для меня, потому что я должен был щелкнуть дважды на другом или том же popover, чтобы открыть его снова. Я написал решение с нуля, чтобы быть простым и эффективным

$('[data-toggle="popover"]').popover({ 
     html:true, 
     trigger: "manual", 
     animation: false 
    }); 

    $(document).on('click','body',function(e){ 
     $('[data-toggle="popover"]').each(function() { 
      $(this).popover('hide'); 
     }); 

     if (e.target.hasAttribute('data-toggle') && e.target.getAttribute('data-toggle') === 'popover') { 
      e.preventDefault(); 
      $(e.target).popover('show'); 
     } 
     else if (e.target.parentElement.hasAttribute('data-toggle') && e.target.parentElement.getAttribute('data-toggle') === 'popover') { 
      e.preventDefault(); 
      $(e.target.parentElement).popover('show'); 
     } 
    });