Нажатие на полосу прокрутки div запускает событие размытия в I.E - PullRequest
23 голосов
/ 08 января 2010

У меня есть div, который действует как выпадающий список. Так что он появляется, когда вы нажимаете кнопку, и позволяет пролистывать этот большой список. Таким образом, у div есть вертикальная полоса прокрутки. Предполагается, что div исчезнет, ​​если вы щелкнете за пределами div, то есть при размытии.

Проблема в том, что когда пользователь нажимает на полосу прокрутки div, IE ошибочно запускает событие onblur, а Firefox - нет. Я предполагаю, что Firefox все еще рассматривает полосу прокрутки как часть div, что я считаю правильным. Я просто хочу, чтобы IE вел себя так же.

Ответы [ 7 ]

16 голосов
/ 09 февраля 2012

У меня была похожая проблема с полосой прокрутки в выпадающем меню автозаполнения. Поскольку выпадающий список должен быть скрыт, когда элемент формы, к которому он присоединен, теряет фокус, поддержание фокуса на правильном элементе стало проблемой. При нажатии на полосу прокрутки только Firefox (10.0) продолжал фокусироваться на элементе ввода. IE (8.0), Opera (11.61), Chrome (17.0) и Safari (5.1) все удалили фокус со ввода, в результате чего раскрывающийся список был скрыт, а поскольку он был скрыт, события щелчка не будут срабатывать в раскрывающемся списке.

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

dropdown.onmousedown = function(event) {
    // Do stuff
    return false;
}

Добавление возвращаемого значения в обработчик событий решило проблему во всех браузерах, кроме IE. Это отменяет действие браузера по умолчанию, в этом случае смещение фокуса. Кроме того, использование mousedown вместо click означало, что обработчик событий будет выполнен до того, как событие размытия будет запущено для элемента ввода.

Это оставило IE как единственную оставшуюся проблему (нет ничего удивительного). Оказывается, нет способа отменить смещение фокуса на IE. К счастью, IE - единственный браузер, который запускает событие фокуса в раскрывающемся списке, а это означает, что фокус на элементе ввода можно восстановить с помощью обработчика событий, эксклюзивного для IE:

dropdown.onfocus = function() {
    input.focus();
}

Это решение для IE не является идеальным, но хотя смещение фокуса не может быть отменено, это лучшее, что вы можете сделать. Что происходит, так это то, что событие размытия срабатывает на входе, скрывая раскрывающийся список, после чего фокус срабатывает на скрытом раскрывающемся раскрытии, который восстанавливает фокус на входе и вызывает показ раскрывающегося списка. В моем коде это также вызывает повторное заполнение раскрывающегося списка, что приводит к небольшой задержке и потере выбора, но если пользователь хочет прокрутить выбор, в любом случае, вероятно, бесполезен, поэтому я счел это приемлемым.

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

4 голосов
/ 23 мая 2014

Поздний ответ, но у меня была та же проблема, и текущие ответы не работали для меня.

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

$('#element-with-focus').blur(function()
{
    if ($('#popup:hover').length === 0)
    {
        $('#popup').hide()
    }
}

Вам нужно будет сместить фокус обратно на исходный элемент, с которым связано событие размытия. Это не мешает прокрутке:

$('#popup').focus(function(e)
{
    $('#element-with-focus').focus();
});

Это не работает с IE7 или ниже - просто перестаньте его поддерживать ...

Пример: http://jsfiddle.net/y7AuF/

3 голосов
/ 18 июля 2016

Это старый вопрос, но так как он все еще относится к IE11, вот что я сделал.

Я слушаю событие mousedown в меню и устанавливаю флаг для этого события. Когда я ловлю событие размытия, если флаг mousedown включен, я возвращаю фокус. Так как Edge, FF и Chrome не будут запускать событие размытия, но будут запускать событие mouseup (что IE не будет), для них я сбросил флаг mousedown на mouseup (на размытие для IE).

  mousedown: function (e) {
      this.mouseddown = true;
      this.$menu.one("mouseup", function(e){
        // IE won't fire this, but FF and Chrome will so we reset our flag for them here
        this.mouseddown = false;
      }.bind(this));
    }

 blur: function (e) {
      if (!this.mouseddown && this.shown) {
        this.hide();
        this.focused = false;        
      } else if (this.mouseddown) {
        // This is for IE that blurs the input when user clicks on scroll.
        // We set the focus back on the input and prevent the lookup to occur again
        this.skipShowHintOnFocus = true; // Flag used to avoid repopulating the menu
        this.$element.focus();
        this.mouseddown = false;    
      } 
    },

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

3 голосов
/ 26 января 2010

У меня похожая проблема с IE, запускающим событие размытия при нажатии на полосу прокрутки. По-видимому, это происходит только в IE7 и ниже, а IE8 в причудливом режиме.

Вот что я нашел в Google

https://prototype.lighthouseapp.com/projects/8887/tickets/248-results-popup-from-ajaxautocompleter-disappear-when-user-clicks-on-scrollbars-in-ie6ie7

По сути, вы делаете размытие только в том случае, если вы знаете, что человек щелкнул где-то на документе, кроме текущего выделенного элемента div. Возможно обратное обнаружение щелчка на полосе прокрутки, поскольку document.onclick не срабатывает при нажатии на полосу прокрутки.

1 голос
/ 06 января 2014

Использовать фокусировку и фокусирование (специфичные для IE события)

$(document).bind('focusout', function(){
     preventHiding = false;
     //trigger blur event
     this.$element.trigger('blur');

});

$(document).bind('focusin', function(){
     preventHiding = true;
});

$(document).bind('blur', function(){
       // Did anyone want us to prevent hiding?
       if (this.preventHiding) {
         this.preventHiding = false;
         return;
       }
       this.hide();
});
0 голосов
/ 18 сентября 2011

Возможно, попробуйте добавить атрибут tabindex, установленный на -1, к узлу div.

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

У меня была такая же проблема. Решено, поместив меню в упаковочный (больший) div. С размытием, примененным к обертке, это сработало!

...