JQuery выяснить, если родитель потерял «фокус» - PullRequest
6 голосов
/ 04 февраля 2010

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

HTML структурирован так (дополнительные имена классов используются для ясности):

<ul>
    <li class="primaryMenuItem">
        <a href="">Link 1</a>
        <ul class="popUpMenu">
            <li><a href="">Sub Link 1</a></li>
            <li><a href="">Sub Link 2</a></li>
        </ul>
    </li>
    <li class="primaryMenuItem">
        <a href="">Link 2</a>
        <ul class="popUpMenu">
            <li><a href="">Sub Link 1</a></li>
            <li><a href="">Sub Link 2</a></li>
        </ul>
    </li>    
</ul>

Ссылка 1 и Ссылка 2, когда наведены, будут отображать списки подменю (выпадающее меню). У меня это отлично работает с некоторыми jQuery и плагином jQuery hoverIntent.

Проблема в том, что в данный момент это работает только с мышью.

Следующая задача - заставить это работать через клавиатуру.

Я могу легко добавить событие фокуса к ссылкам верхнего уровня, которые затем вызывают вторичные меню:

$('ul.primaryMenuItem a:first').focus([call showMenu function]) 

Это прекрасно работает.

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

Это тоже отлично работает.

Однако, если это не удастся, если у вас открыто последнее меню и из него открыта вкладка. Поскольку вы не открыли другое меню, оно остается открытым.

Задача состоит в том, чтобы выяснить, как / когда закрывать меню, и в какой логике (jQuery) это выяснить. В идеале, я бы закрыл меню, когда фокус на элементе на странице ДРУГОЙ, чем на любом из дочерних элементов меню.

Логично, я ищу это:

$('li.primaryMenuItem').blur([close $(this).find('ul.popUpMenu'))

Однако вы не можете этого сделать, так как на самом деле у LI нет фокуса, а есть тег привязки внутри него.

Есть предложения?

UPDATE:

возможно, лучший / более простой способ задать вопрос:

Через jQuery, есть ли способ «посмотреть», чтобы увидеть, переместился ли фокус за пределы всех дочерних элементов определенного объекта?

Ответы [ 6 ]

6 голосов
/ 04 февраля 2010

Вы можете использовать всплывающее окно события, чтобы проверить, что фокусируется на событии focusin. Я имел успех со следующим кодом:


$("li:has(ul.popUpMenu)").focusin(function(e) {
    $(this).children().fadeIn('slow');
  });
  $('body').focusin(function(e) {
    if (!$(e.target).parent().is('ul.popUpMenu li')) {
      $('ul.popUpMenu').fadeOut('slow');
    }
  });

Вы могли (вероятно) сделать его более оптимизированным, но это работает.

2 голосов
/ 12 января 2012

Как насчет, если вы делаете следующее:

$('#link_A_id, #link_A_id > *').focusout(function () {
    if ($(document.activeElement).closest('#link_A_id').length == 0)
        //focus is out of link A and it's children
});
2 голосов
/ 04 февраля 2010

Используйте новые функции jquery 1.4: focusin и focusout вместо blur и focus. Вот как focusout отличается:

Событие focusout отправляется на элемент, когда он, или любой элемент внутри из этого теряет фокус. Это отлично от события размытия в том, что это поддерживает обнаружение потери фокуса из родительских элементов (другими словами, поддерживает пузыри событий).

0 голосов
/ 11 апреля 2013

У меня была похожая проблема ... Я создал jsfiddle, чтобы определить, когда родительский набор полей теряет фокус, а затем вызывать функцию.Конечно, это можно оптимизировать, но это только начало.

http://jsfiddle.net/EKhLc/10/

function saveFields() {
  $.each($('fieldset.save'),function(index, value) {
    // WHERE THE POST WOULD GO
    alert('saving fieldset with id '+ value.id);
    $(value).removeClass('save');
  });

}
$('.control-group').focusin(function(){
  var thefield = $(this).parent('fieldset');
  if (!thefield.hasClass('active')) {
    if($('fieldset.active').length > 0){

      $('fieldset.active').removeClass('active').addClass('save');
      saveFields();
      }
    thefield.addClass('active');
    } else {
        console.log('already active');
    }
});
0 голосов
/ 12 сентября 2011

Это помогло мне ... http://plugins.jquery.com/project/focus

Он автоматически обнаружит, что вы все еще находитесь в родительской зоне. Вместо этого он в основном меняет фокусировку jQuery, что, как мне кажется, должно работать.

<div class="parent">
   <input type="text" />
   <input type="text" />
</div>

$('#parent').focusout(function () {
    console.log('focusout of parent');
});

Я не понимаю, почему нажатие клавиши табуляции для перемещения текстового поля между дочерними элементами должно вызывать фокусировку на родительском элементе, поскольку вы все еще находитесь в этом родительском элементе. Должно быть, что-то происходит, что на мгновение выводит тебя из себя, и я подозреваю, что это ошибка ... кто-нибудь со мной в этом? Ну, в любом случае плагин выше исправляет это. Просто включите его перед вашим кодом, чтобы «исправить» это. Хотел бы кто-нибудь объяснить, почему это не ошибка, если это не так.

Спасибо, Дом

0 голосов
/ 04 февраля 2010

Попробуйте это

$('li.primaryMenuItem:last li a:last').blur([do whatever you need to do])

Логически, если ваш пользователь выдвигает на первый план, он, должно быть, фокусировал последний якорь.

Вы даже можете настроить свой собственный обработчик событий, например:*

$('li.primaryMenuItem:last').bind('myblur', function() ...);

и вызовите его в последнем событии размытия якорей:

...blur(function() {
    $(this).parents('li.primaryMenuItem').trigger('myblur'); ...
...