Скрыть элемент при клике снаружи без документа / body-event-listener - PullRequest
0 голосов
/ 01 апреля 2012

Я создал очень простой «выпадающий список» jQuery, который состоит из двух элементов div.При нажатии на первый div отображается второй div.Теперь я хочу, чтобы второй div снова закрывался, когда я нажимал за пределами этого div.Но я не могу (и на самом деле не хочу, если это не нужно) использовать прослушиватель событий для документа или тела, например:

$('#div2').click(function(e) {
    doSomething();
    e.stopPropagation();
});
$(document).click(function() {
    $("#div2").hide();
});

Причина: у меня есть другие элементы на страницекоторые используют e.stopPropagation();, и если пользователь щелкнет эти элементы после открытия раскрывающегося списка, он не закроется снова.

Я нашел этот плагин, jALDropdown, который каким-то образом обрабатывается, чтобы закрыть раскрывающийся список, даже если я нажимаю наe.stopPropagation();, или даже где-то за пределами страницы или браузера, и он, похоже, не использует никаких документов / body-event-listener: http://india.assigninfo.com/assignlabs/jaldropdown

К сожалению, он не работает с Opera, поэтому я могуНе используй это.И я не нашел версию исходного кода, которая не была бы свернута, поэтому я не смог выяснить, как она работает.

У вас есть идеи, как архивировать такое поведение, чтобы раскрывающийся список закрывался?(элемент скрыт), если я нажимаю за пределами элемента, страницы или даже браузера, без документа / body-event-listener?Спасибо!

Ответы [ 2 ]

1 голос
/ 01 апреля 2012

Почему бы не оставить функцию $ (document) .click (), чтобы скрыть разделение, а затем добавить эту функцию в код и вызывать ее вместо event.stopPropagation ():

function stopPropAndCloseDiv2(event) {
    $('#div2').hide();
    event.stopPropagation();
};

Я проверил это, и кажется, что оно будет работать нормально. Вам просто нужно помнить, чтобы использовать его.

UPDATE:

Это грызло меня, и я нашел другой ответ на этом замечательном сайте, который я знаю. Вот ссылка:

добавить код в функцию программно с помощью JS

Я попробовал этот подход, и он, кажется, работает: http://jsfiddle.net/kXkFS/8/

Вот код (в разметке тестовой страницы есть две кнопки):

jQuery.Event.prototype.stopPropagation = (function() {
    var cached_function = jQuery.Event.prototype.stopPropagation;

    return function() { 
        if ( this.type == "click") {
            // Your logic here.
            console.log("I am a modified version of event.stopPropagation()!");
        }
        cached_function.apply(this, arguments); // use .apply() to call it.
    };
}());

$(document).click( function() { console.log("The document caught the event, too."); });
$('#clicker').click( function() { console.log("I'm going to let this event bubble."); });
$('#anotherClicker').click( function(event) { event.stopPropagation(); });

Спойлер: когда вы нажимаете кнопку "кликер", документ также попадает в консоль. Когда вы нажимаете кнопку «anotherClicker», пользовательская функция event.stopPropagation () регистрируется на консоли, а документ не регистрируется на консоли. Теперь вы можете добавить обработчик событий щелчка в документ.

Одна вещь: это может добавить некоторые накладные расходы, но только если вы часто вызываете stopPropagation ().

Если кто-то захочет оценить мудрость использования такого объекта jQuery, пожалуйста, сделайте это. Интересно, но я не вижу, чтобы такие безобидные изменения, как эта, взорвали веб-страницу в будущем.

0 голосов
/ 01 апреля 2012
//generic drop-down menu
//NOTE: only pass a menu object if there are multiple menus per toggle object
var dropDown = function( toggle, menus )
{
  toggle.click( function( e ) {
    e.preventDefault();
    //NOTE: container is assuming that the next sibling is the dropdown.
    //change container to suit your needs
    var container = $( this ).next();
    if( menus !== undefined && !container.is( ':visible' ) ){ menus.hide(); }

    if( !container.is( ':visible' ) )
    {
      container.fadeIn( 'fast' );
    }
    else
    {
      container.fadeOut( 'fast' );
    }
  });
}

//close stuff when the window is clicked
var window_click = function( obj )
{
  $( window ).click( function( e ) {
    if( obj.is( ':visible' ) )
    {
      obj.fadeOut( 250 );
    }
  });
}

//override the window_click function when needed
var stop_prop = function( obj )
{
  obj.click( function( e ) {
    e.stopPropagation();
  });
}

Теперь просто используйте их там, где хотите, вот так:

var toggle = $( '#myToggle' );
var menu = $( '#myMenu' );

dropDown( toggle, menu );
window_click( menu );
stop_prop( toggle );
stop_prop( menu );

Для моей выпадающей разметки я почти всегда использую эту модель:

<span class='toggle_name'></span>
<ul class='menu_name' style='display:none;'>
  <li>cool man</li>
</ul>      

Чтобы обойти разбросанную функцию stopPropagation (), вы также можете создать небольшую функцию, которая вручную закрывала все классы меню. Супер просто:

var menus = {
  //add any dropdown menu ids or classes here
}

//run this method on any conflicting stopProp clicks
var closeMenus = function()
{
  for( var key in menus )
  {
    if( menus.hasOwnProperty( key ) )
    {
      menus[key].hide();
    }
  }
}
...