Jquery'de kapatmak için dış menüye tıklayın


107

Bu nedenle, iş gereksinimlerine göre bir tıklamada gösterilen bir açılır menüm var. Menüden uzaklaştıktan sonra menü tekrar gizlenir.

Ama şimdi, kullanıcı belgede herhangi bir yere tıklayana kadar yerinde kalmasını sağlamam isteniyor. Bu nasıl yapılabilir?

Bu, şu anda sahip olduğum şeyin basitleştirilmiş bir sürümü:

$(document).ready(function() {
  $("ul.opMenu li").click(function(){
   $('#MainOptSubMenu',this).css('visibility', 'visible');
  });

  $("ul.opMenu li").mouseleave(function(){
      $('#MainOptSubMenu',this).css('visibility', 'hidden');
  });
});



<ul  class="opMenu">
  <li id="footwo" class="">
    <span id="optImg" style="display: inline-block;"> <img src="http://localhost.vmsinfo.com:8002/insight/images/options-hover2.gif"/> </span>
      <ul id="MainOptSubMenu" style="visibility: hidden; top: 25px; border-top: 0px solid rgb(217, 228, 250); background-color: rgb(217, 228, 250); padding-bottom: 15px;">
        <li>some</li>
       <li>nav</li>
       <li>links</li>
       </ul>
    </li>
</ul> 

$('document[id!=MainOptSubMenu]').click(function()Menüde olmayan herhangi bir şeyi tetikleyeceğini düşünerek böyle bir şey denedim ama işe yaramadı.



Yanıtlar:


196

Bu sorunun kullandığı yaklaşıma bir göz atın:

Bir elemanın dışındaki bir tıklamayı nasıl tespit ederim?

Belgenin gövdesine, pencereyi kapatan bir tıklama olayı ekleyin. Belgenin gövdesine yayılmasını durduran pencereye ayrı bir tıklama etkinliği ekleyin.
$('html').click(function() {
  //Hide the menus if visible
});

$('#menucontainer').click(function(event){
    event.stopPropagation();
});


16
çok güzel ama $ ['html'] kullanmalısınız. body değil click (). Vücut her zaman içeriğinin yüksekliğine sahiptir. Çok fazla içerik yok ya da ekran çok yüksek, sadece vücudun doldurduğu kısımda çalışıyor.
Şuradan

harika çözüm. neden .click () ile çalışıp .live ile çalışmadığına dair herhangi bir fikriniz var mı ('click', func ...?
Hat

3
Bu yaklaşımla ilgili tek sorun, başka nedenlerden ötürü durduran bir tıklama dinleyicisine sahip olan nesnelerin hiçbir etkisinin olmamasıdır. Neden böyle olduğunu anlıyorum, ama yine de bu çözümün bir sınırlaması.
DanH

53

Cevap doğrudur, ancak sayfanızda her tıklama gerçekleştiğinde tetiklenecek bir dinleyici ekleyecektir. Bundan kaçınmak için dinleyiciyi yalnızca bir kez ekleyebilirsiniz:

$('a#menu-link').on('click', function(e) {
    e.preventDefault();
    e.stopPropagation();

    $('#menu').toggleClass('open');

    $(document).one('click', function closeMenu (e){
        if($('#menu').has(e.target).length === 0){
            $('#menu').removeClass('open');
        } else {
            $(document).one('click', closeMenu);
        }
    });
});

Düzenle: stopPropagation()ilk düğmeden kaçınmak istiyorsanız bunu kullanabilirsiniz

var $menu = $('#menu');

$('a#menu-link').on('click', function(e) {
    e.preventDefault();

    if (!$menu.hasClass('active')) {
        $menu.addClass('active');

        $(document).one('click', function closeTooltip(e) {
            if ($menu.has(e.target).length === 0 && $('a#menu-link').has(e.target).length === 0) {
                $menu.removeClass('active');
            } else if ($menu.hasClass('active')) {
                $(document).one('click', closeTooltip);
            }
        });
    } else {
        $menu.removeClass('active');
    }
});

Böyle bir kodu çok görüyorum, bu, menü bağlantısına her tıklandığında belgeye yeni bir tıklama işlevi eklemeyecek mi? Yani, sayfayı yenilemeden menü bağlantısını 1000 kez tıklarsanız, hafızayı kaplayan ve aynı zamanda çalıştıran 1000 işleve sahip olacaksınız?
eselk

Boşver, "bir" işlevini görmedim, şimdi bunun neden işe yaradığını anlıyorum: api.jquery.com/one
eselk

2
güzel bir çözüm, ancak e.stopPropagation()ilk etkinliğin one()işleyicide tetiklenmesini durdurmak için Chrome'da kullanmak zorunda kaldım
antfx

18

stopPropagationOnlar HTML öğesine yakın işleyicileri bağlı olabilir diğer menülerde dahil olmak üzere diğer olay işleyicileri engelleyebilir çünkü seçenekler kötü.

İşte user2989143'ün cevabına dayalı basit bir çözüm :

$('html').click(function(event) {
    if ($(event.target).closest('#menu-container, #menu-activator').length === 0) {
        $('#menu-container').hide();
    }
});

17

Bir eklenti kullanmak sizin için uygunsa, Ben Alman'ın burada bulunan tıklama eklentisi eklentisini öneririm :

kullanımı şu kadar basit:

$('#menu').bind('clickoutside', function (event) {
    $(this).hide();
});

Bu yardımcı olur umarım.


8

Araştırabileceğiniz 2 seçenek:

  • Menüyü gösterirken, arkasına sayfanın geri kalanını kaplayan büyük bir boş DIV yerleştirin ve menüyü (ve kendisini) kapatmak için buna bir tıklama etkinliği verin. Bu, ışıklı kutularda kullanılan yöntemlere benzer, arka planda tıklandığında ışık kutusu kapatılır
  • Menü gösterildiğinde, gövdeye menüyü kapatan tek seferlik bir tıklama olay işleyicisi ekleyin. Bunun için jQuery'nin '.one ()' kullanırsınız.

6

Grsmto'nun çözümünün bir çeşidini buldum ve Dennis'in çözümü sorunumu çözdü.

$(".MainNavContainer").click(function (event) {
    //event.preventDefault();  // Might cause problems depending on implementation
    event.stopPropagation();

    $(document).one('click', function (e) {
        if(!$(e.target).is('.MainNavContainer')) {
            // code to hide menus
        }
    });
});

5

Bu çözümü aynı sayfada aynı davranışa sahip birden çok öğeyle kullanıyorum:

$("html").click(function(event){
    var otarget = $(event.target);
    if (!otarget.parents('#id_of element').length && otarget.attr('id')!="id_of element" && !otarget.parents('#id_of_activator').length) {
        $('#id_of element').hide();
    }
});

stopPropagation () kötü bir fikirdir, bu, düğmeler ve bağlantılar dahil birçok şeyin standart davranışını bozar.


Bu harika, ancak bunu şu şekilde basitleştirebilirsiniz$target.closest('#menu-container, #menu-activator').length === 0
Code Commander

5

Geçenlerde aynı sorunla karşılaştım. Aşağıdaki kodu yazdım:

    $('html').click(function(e) {
      var a = e.target;
      if ($(a).parents('.menu_container').length === 0) {
        $('.ofSubLevelLinks').removeClass('active'); //hide menu item
        $('.menu_container li > img').hide(); //hide dropdown image, if any
     }
    });

Benim için mükemmel çalıştı.


4

Peki buna ne dersin?

    $(this).mouseleave(function(){  
        var thisUI = $(this);
        $('html').click(function(){
                thisUI.hide();
            $('html').unbind('click');
         });
     });

3

Click-event yerine mousedown-event'i kullanmayı daha kullanışlı buluyorum. Kullanıcı, tıklama etkinlikleri olan sayfadaki diğer öğeleri tıklarsa tıklama etkinliği çalışmaz. JQuery'nin one () yöntemiyle birlikte şu şekilde görünür:

$("ul.opMenu li").click(function(event){

   //event.stopPropagation(); not required any more
   $('#MainOptSubMenu').show();

   // add one mousedown event to html
   $('html').one('mousedown', function(){
       $('#MainOptSubMenu').hide();
   });
});

// mousedown must not be triggered inside menu
$("ul.opMenu li").bind('mousedown', function(evt){
    evt.stopPropagation();
});

3

Ben bile aynı durumla karşılaştım ve mentorumdan biri bu fikri kendime sundu.

adım: 1 açılır menüyü göstermemiz gereken düğmeye tıklandığında. ardından aşağıdaki sınıf adını "more_wrap_background" aşağıda gösterildiği gibi geçerli etkin sayfaya ekleyin

$('.ui-page-active').append("<div class='more_wrap_background' id='more-wrap-bg'> </div>");

2. adım, ardından div etiketi için aşağıdaki gibi bir tıklama ekleyin:

$(document).on('click', '#more-wrap-bg', hideDropDown);

hideDropDown, açılır menüyü gizlemek için çağrılacak işlevdir

Adım 3 ve açılır menüyü gizlerken önemli adım, daha önce eklediğiniz sınıfı kaldırmanızdır.

$('#more-wrap-bg').remove();

Yukarıdaki kodda kimliğini kullanarak kaldırıyorum

.more_wrap_background {
  top: 0;
  padding: 0;
  margin: 0;
  background: rgba(0, 0, 0, 0.1);
  position: fixed;
  display: block;
  width: 100% !important;
  z-index: 999;//should be one less than the drop down menu's z-index
  height: 100% !important;
}

2
$("html").click( onOutsideClick );
onOutsideClick = function( e )
{
    var t = $( e.target );
    if ( !(
        t.is("#mymenu" ) ||     //Where #mymenu - is a div container of your menu
        t.parents( "#mymenu" ).length > 0
        )   )
    {
        //TODO: hide your menu
    }
};

Ve dinleyiciyi yalnızca menünüz görünür durumdayken ayarlamak ve menü gizlendikten sonra dinleyiciyi her zaman kaldırmak daha iyidir.


1

Bunun gibi bir şeye ihtiyacınız olduğunu düşünüyorum: http://jsfiddle.net/BeenYoung/BXaqW/3/

$(document).ready(function() {
  $("ul.opMenu li").each(function(){
      $(this).click(function(){
            if($(this).hasClass('opened')==false){          
                $('.opMenu').find('.opened').removeClass('opened').find('ul').slideUp();
                $(this).addClass('opened'); 
                $(this).find("ul").slideDown();
            }else{
                $(this).removeClass('opened'); 
                $(this).find("ul").slideUp();               
            }
      });
  });    
});

Umarım sizin için yararlıdır!


1

': Visible' seçiciyi kullanın. .Menuitem'in gizlenecek öğe (ler) olduğu yerde ...

$('body').click(function(){
  $('.menuitem:visible').hide('fast');
});

Veya bir var içinde .menuitem öğelerine zaten sahipseniz ...

var menitems = $('.menuitem');
$('body').click(function(){
  menuitems.filter(':visible').hide('fast');
});

0

Karmaşık olmak zorunda değil.

$(document).on('click', function() {
    $("#menu:not(:hover)").hide();
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.