Скрыть при нажатии за пределами нескольких элементов

Мне нужно сделать кроссбраузерные теги в jQuery. Поэтому вместо создания чистых HTML-тегов элемента SELECT я использую вложенные элементы. На странице будет доступно много полей выбора, поэтому они должны корректно работать друг с другом.

Изменить: следует использовать эффекты затухания "fadeIn() / fadeOut()" вместо "hide() / show()"

Представляем пример:

Вместо классического чистого HTML-элемента выпадающего списка:

<select>
  <option>Option 1</option>
  <option>Option 1</option>
  <option>Option 1</option>
</select>

У меня есть вложенные элементы, поэтому я могу правильно их стилизовать:

<div class="gui-selectbox">
  <a class="gui-selectbox-button">
    <span class="gui-btn-l"></span>
    <span class="gui-btn-c">Option 1</span>
    <span class="gui-btn-r"></span>
  </a>
  <div class="gui-selectbox-dialog">
    <ul>
      <li>Option 1</li>
      <li>Option 2</li>
      <li>Option 3</li>
    <ul>
  </div>
</div>

Вот код: http://jsfiddle.net/aspirinemaga/XR4Y3/

Это должно работать таким образом:

  • Когда я нажимаю на любой элемент, он должен закрыть все поля выбора
  • Когда я нажимаю «.gui-selectbox-button», он должен отображать «.gui-selectbox-dialog» своего родителя «.gui-selectbox».
  • Если пользователь щелкает за пределами «.gui-selectbox-button» и «.gui-selectbox-dialog», он должен закрыть все открытые поля выбора.

ОБНОВЛЕНО:

Как я могу указать функции не закрывать родительский div, если текущая цель является его дочерним элементом?

Вот пример: http://jsfiddle.net/aspirinemaga/ejyRR/5/. Это третий элемент.


person aspirinemaga    schedule 06.01.2012    source источник
comment
href="selectbox-button" должно быть class="selectbox-button"?   -  person Jeff Wilbert    schedule 06.01.2012
comment
Я сделал вам рабочий JSfiddle: jsfiddle.net/XR4Y3/5   -  person Jules    schedule 06.01.2012


Ответы (3)


Вы можете немного консолидировать свой код. Это сделает то, что вы хотите.

Пример 1

$('html').on('click', function() {
    $('.gui-selectbox-dialog:visible').hide();
});

$('.gui-selectbox').on('click', function(event) {
    $('.gui-selectbox-dialog:visible').hide();
    $(this).find('.gui-selectbox-dialog').show();

    event.stopPropagation();
});

$('.gui-selectbox-dialog ul').on('click', 'li', function(event) {
    alert('selected = ' + $(this).text());

    event.stopPropagation();
});

Демонстрация скрипта: http://jsfiddle.net/tJ7Qb/

Изменить: обновлен мой код и демонстрационная ссылка, так как у меня были части, использующие старый метод событий .click(), а некоторые — новый метод .on(). Также добавлено оповещение о выборе опции.

person Jeff Wilbert    schedule 06.01.2012
comment
Большое спасибо Джефф! Постараюсь адаптировать мой код к вашему. - person aspirinemaga; 06.01.2012
comment
Я обновил свой ответ, чтобы исправить некоторые несоответствия в коде с использованием старого и нового кода jQuery. Теперь все закодировано для поддержки последней версии 1.7.1 с использованием .on() методов обработки событий. - person Jeff Wilbert; 06.01.2012
comment
Кстати, Джефф, мне нужно использовать эффект fadeIn/fadeOut, я пытался поставить функцию .stopPropagation перед эффектом .fadeIn, но он заставляет его мигать. Любая идея исправить это? - person aspirinemaga; 06.01.2012
comment
Я обновил код, как я могу узнать, является ли моя текущая цель дочерней частью того же div? значение: определить, является ли он вложенным или нет? спасибо - person aspirinemaga; 09.01.2012
comment
@Jeff - есть ли способ в jquery сказать это: если мой вложенный элемент открыт, и я хочу его закрыть, я могу сделать это, снова нажав на его кнопку, чтобы он закрылся. но могу ли я связать ту же функциональность за пределами открытого элемента? Например: я нажимаю на 3-й элемент, он открывается, затем я нажимаю на 4-й элемент, который находится внутри открытого в данный момент элемента. но я могу закрыть 4-й, щелкнув за его пределами, ДАЖЕ на содержимом 3-го элемента. надеюсь я ясно выразился - person aspirinemaga; 09.01.2012

На самом деле, Крис Койер @ CSS-Tricks.com уже сделал то, что вы пытаемся сделать.

Он также предоставляет весь код и пояснения. Удачи :)

person Madara's Ghost    schedule 06.01.2012
comment
Спасибо, но у меня нет проблем сделать это с состоянием .hover. У меня проблемы с состояниями кликов. И, кстати, он использует тег ввода, поэтому вы не можете использовать вложенные элементы внутри ввода. - person aspirinemaga; 06.01.2012

Что вы можете сделать, так это назначить функцию click() своему телу. И внутри этой функции проверьте, какой именно элемент был нажат. Если это не одно из ваших полей «выбрать», закройте открытые. В противном случае откройте или закройте тот, который был нажат.

Позвольте мне пояснить это в некотором коде:

$(document).click(function(event) {

    if (gui_currentSelectboxID != null) {
        $this = $(event.target);
        $parent = $this.parent().parent();

        //Check if the clicked item was NOT the gui-selectbox option
        if ($parent.attr('class') != 'gui-selectbox') {
            $('#' + gui_currentSelectboxID).children('.gui-selectbox-dialog').fadeOut(100);
            $('#' + gui_currentSelectboxID).children('.gui-selectbox-button').removeClass('active');
        }
    }

});

Это должно помочь:

http://jsfiddle.net/XR4Y3/5/

Вы все еще можете оптимизировать это, проверив, действительно ли существует .parent().parent(), потому что, например, document не будет иметь двух родителей. Другие оптимизации заключались бы в использовании функций, которые вы фактически объявили, чтобы скрыть поля выбора и т. Д.

person Jules    schedule 06.01.2012