Javascript newbie - кажется, что onBlur одного элемента «переопределяет» щелчок другого - PullRequest
3 голосов
/ 11 апреля 2011

У меня есть два элемента:

<input type="text" name="pmTo" id="pmTo" onkeyup="offerSuggs('none');" onfocus="showSelect();" onblur="hideSelect();" />

и динамически созданный (это все часть программы автоматического предложения):

$suggString .= '<div name="'.$value.'" id="'.$value.'" class="suggMouseOver" onmouseover="highlightDivs(this);" onmouseout="blurDivs(this);" onclick="fillInput(this);">'.$value.'</div>';

Хорошо, а затем естьфункции событий, которые соответствуют onblur элемента ввода и затем onclick элемента div:

function hideSelect() {
            offerSuggs('checkFinal');
            document.getElementById('nameSugg').style.display="none";
            }


function fillInput(elemName) {
            document.getElementById('pmTo').value=elemName.id;
            }

EDIT: как мне заставить onclick корректно запускать элемент, по которому они щелкают, без события onblurсначала спрятать div, что делает бессмысленный клик?Тем не менее, я бы хотел сохранить функциональность предположения, что div исчезает, когда текстовое поле теряет фокус.Благодаря.

Ответы [ 2 ]

8 голосов
/ 11 апреля 2011

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

Если пользователь использует курсор для выбора элемента, то я предполагаю, что событие размытия входных данных срабатывает до события щелчка в div, и для div устанавливается отображение: ни один до срабатывания щелчка, иследовательно, пропускается div.

Исправление заключается в вызове слушателя onblur после короткого тайм-аута, поэтому:

  <input ... onblur="setTimeout(function(){hideSelect();}, 100);">

При тестировании в нескольких браузерах может потребоваться установить тайм-аут на200 мс или около того.Неважно, есть ли короткая видимая задержка после события размытия, прежде чем исчезнут предложения (т. Е. Немного длиннее лучше, чем слишком коротко).

Убедитесь, что предложения ничего не затеняютважно на странице или пользователи могут найти их скорее помехой, чем помощью.: -)

2 голосов
/ 18 апреля 2016

Принятый ответ будет работать как быстрое решение, но полагаясь на setTimeout, вы предполагаете, что пользователь будет удерживать нажатой не более n миллисекунд, прежде чем отпустить (просто представьте, кто-то колеблется при щелчке ). Чтобы быть более уверенным, что щелчок пройдет, вы можете установить более длительное время ожидания, но это означает, что ваш скрываемый элемент будет оставаться видимым намного дольше после размытия.

Итак, давайте посмотрим на корень проблемы.

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

  1. mousedown
  2. blur
  3. mouseup
  4. click

Таким образом, к тому моменту, когда события mouseup / click готовы к срабатыванию, был вызван слушатель размытия, и элемент, над которым вы когда-то парили, уже исчез.

Вот общее исправление (основанное на том факте, что событие mousedown запускается первым), которое должно работать:

var searchEl = $('#search');
var listEl = $('#dropdown');
var keepListOpen = false;

searchEl
  .on('focus', function() {
    listEl.show();
  })
  .on('blur', function() {
    // Hide the list if the blur was triggered by anything other than
    //  one of the list items
    if (!keepListOpen) {
      listEl.hide();
    }
  });

listEl.find('li')
  .on('mousedown', function(event) {
    // Keep the list open so the onClick handler can fire
    keepListOpen = true;
  })
  .on('click', function(event) {
    // Proof that the list item was clicked
    alert('clicked option');
  });

$(window).on('mouseup', function(event) {
  // Return the keepListOpen setting to its default and hide the list

  // *NOTE* We could have tied this handler to the list items, 
  // but it wouldn't have fired if a mousedown happened on a
  // list item and then the user dragged the mouse pointer 
  // out of the area (or out of the window)
  if (keepListOpen) {
    listEl.hide();
    keepListOpen = false;
  }
});

// Bind to `window.top` if your page might be displayed in an iframe
// $(window.top).on('mouseup', function(event) {
//  if (keepListOpen) {
//    listEl.hide();
//    keepListOpen = false;
//  }
//});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="search" type="text" placeholder="Click Here">

<ul id="dropdown" style="display: none;">
  <li>Click Me 1</li>
  <li>Click Me 2</li>
  <li>Click Me 3</li>
</ul>
...