web-dev-qa-db-ja.com

divのスクロールバーをクリックすると、IEでblurイベントが発生します

ドロップダウンのように機能するdivがあります。そのため、ボタンをクリックするとポップアップが表示され、この大きなリストをスクロールできます。したがって、divには垂直スクロールバーがあります。 divの外側をクリックすると、つまりぼかしでdivが消えるはずです。

問題は、ユーザーがdivのスクロールバーをクリックすると、IEが誤ってonblurイベントを発生させるのに対し、Firefoxは発生しないことです。Firefoxは依然としてスクロールバーをの一部として扱うと思います。 divは正しいと思います。IEも同じように動作するようにしたいだけです。

23
Riz

IEスクロールバーをクリックしたときにblurイベントが発生するという同様の問題があります。どうやら、IE7以下、およびIE8がquirksmodeでのみ発生します。

これが私がグーグルで見つけたものです

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

基本的に、ぼかしを行うのは、その人が現在フォーカスされているdiv以外のドキュメントのどこかをクリックしたことがわかっている場合のみです。スクロールバーをクリックしたときにdocument.onclickが起動しないため、スクロールバーのクリックを逆に検出することができます。

3
Chris MacDonald

オートコンプリートドロップダウンのスクロールバーでも同様の問題が発生しました。ドロップダウンは、アタッチされているフォーム要素がフォーカスを失ったときに非表示にする必要があるため、正しい要素にフォーカスを維持することが問題になりました。スクロールバーがクリックされたとき、Firefox(10.0)のみが入力要素にフォーカスを保ちました。 IE(8.0)、Opera(11.61)、Chrome(17.0)、Safari(5.1)はすべてフォーカスを削除しました入力により、ドロップダウンが非表示になり、非表示になっているため、ドロップダウンでクリックイベントが発生しませんでした。

幸い、問題のあるブラウザのほとんどで、フォーカスの移動を簡単に防ぐことができます。これは、デフォルトのブラウザアクションをキャンセルすることによって行われます。

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

イベントハンドラーに戻り値を追加すると、IEを除くすべてのブラウザーで問題が解決されました。これを行うと、デフォルトのブラウザアクション(この場合はフォーカスシフト)がキャンセルされます。また、クリックの代わりにマウスダウンを使用すると、入力要素でblurイベントが発生する前にイベントハンドラーが実行されます。

これはIE唯一残っている問題です(そこには驚きはありません)。IEのフォーカスシフトをキャンセルする方法はないことがわかりました。幸い、IE =は、ドロップダウンでフォーカスイベントを発生させる唯一のブラウザーです。つまり、入力要素へのフォーカスは、IE専用のイベントハンドラーを使用して復元できます。

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

IEのこのソリューションは完全ではありませんが、フォーカスシフトはキャンセルできませんが、これが最善の方法です。何が起こるかというと、入力でぼかしイベントが発生し、ドロップダウンが非表示になります。その後、非表示になっているドロップダウンにフォーカスが移動し、入力へのフォーカスが復元され、ドロップダウンの表示がトリガーされます。私のコードでは、ドロップダウンの再入力もトリガーされるため、選択が少し遅れて失われますが、ユーザーがスクロールしたい場合はとにかく選択はおそらく役に立たないので、私はこれを許容できると思いました。

私の例は質問とは少し異なりますが、これがお役に立てば幸いです。私が集めたものから、質問はIEドロップダウンを開いたボタンではなく、ドロップダウン自体でブラーイベントを発生させることでした。これは私には意味がありません...私の使用のようにフォーカスイベントハンドラーは、スクロールバーをクリックすると、IEでスクロールバーが含まれている要素にフォーカスが移動することを示します。

16
Feysal

回答が遅れましたが、同じ問題が発生し、現在の回答はうまくいきませんでした。

ポップアップ要素のホバー状態は期待どおりに機能するため、blurイベントでは、ポップアップ要素がホバーされているかどうかを確認し、ホバーされていない場合にのみ削除/非表示にすることができます。

$('#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/

4
Timm

これは古い質問ですが、IE11にも当てはまるので、ここで私が行いました。

メニューのmousedownイベントを聞いて、このイベントにフラグを設定します。ぼかしイベントをキャッチしたときに、マウスダウンフラグがオンになっている場合は、フォーカスを元に戻します。 Edge、FF、およびChromeはblurイベントを発生させませんが、mouseupイベントを発生させます(IEは発生しません))ので、mousedownフラグをリセットしますそれらのマウスアップ(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
Melanie

Focusoutとfocusinを使用する(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();
});
1
Prateek Batla

おそらく、-1に設定されたtabindex属性をdivノードに追加してみてください。

0
user951436

私も同じ問題を抱えていました。メニューをラッピング(より大きな)divに配置することで解決しました。ラッパーにぼかしを適用すると、うまくいきました!

0
Oumar