web-dev-qa-db-ja.com

onclick()およびonblur()の順序の問題

カスタムドロップダウンメニューを表示する入力フィールドがあります。次の機能が欲しい:

  • ユーザーが入力フィールド以外の場所をクリックすると、メニューが削除されます。
  • より具体的には、ユーザーがメニュー内のdivをクリックすると、メニューが削除され、andどのdivがクリックされたかに基づいて特別な処理が行われます。

これが私の実装です。

入力フィールドには、ユーザーが入力フィールドの外側をクリックしたときに(親のinnerHTMLを空の文字列に設定することにより)メニューを削除するonblur()イベントがあります。メニュー内のdivには、特別な処理を実行するonclick()イベントもあります。

問題は、入力フィールドのonclick()が最初に起動し、onblur() sを含むメニューを削除するため、メニューがクリックされたときにonclick()イベントが起動しないことです。

メニューdivのonclick()onmousedown()onmouseup()のイベントに分割し、マウスを下げるとグローバルフラグを設定し、マウスを上げるとクリアされるようにして、問題を解決しました。 この答え で提案されたものに。 onmousedown()onblur()の前に起動するため、メニューdivのいずれかがクリックされた場合はフラグがonblur()に設定されますが、画面上のどこかではありません。メニューがクリックされた場合、メニューを削除せずにすぐにonblur()から戻り、onclick()が起動するのを待ちます。この時点で、メニューを安全に削除できます。

よりエレガントなソリューションはありますか?

コードは次のようになります。

<div class="menu" onmousedown="setFlag()" onmouseup="doProcessing()">...</div>
<input id="input" onblur="removeMenu()" ... />

var mouseflag;

function setFlag() {
    mouseflag = true;
}

function removeMenu() {
    if (!mouseflag) {
        document.getElementById('menu').innerHTML = '';
    }
}

function doProcessing(id, name) {
    mouseflag = false;
    ...
}
76
1''

私はあなたとまったく同じ問題を抱えていました。私のUIはあなたが説明したとおりに設計されています。メニュー項目のonClickをonMouseDownに置き換えるだけで問題を解決しました。私は他に何もしませんでした。 onMouseUp、フラグはありません。これにより、これらのイベントハンドラーの優先度に基づいてブラウザーが自動的に並べ替えられるようになり、私からの追加作業なしで問題が解決しました。

これがあなたにとってもうまくいかなかった理由はありますか?

138
johnbakers

onmousedownonfocus に置き換えます。そのため、このイベントは、フォーカスがテキストボックス内にあるときにトリガーされます。

onmouseuponblur に置き換えます。テキストボックスからフォーカスを外した瞬間に、onblurが実行されます。

これがあなたが必要とするかもしれないものだと思います。

[〜#〜] update [〜#〜]

onfocus関数を実行するとき-> onblurで適用するクラスを削除し、onfocusで実行するクラスを追加する

そして

onblur関数を実行するとき-> onfocusで適用するクラスを削除し、onblurで実行するクラスを追加します

フラグ変数は必要ありません。

更新2:

Onmouseoutおよびonmouseoverのイベントを使用できます

onmouseover-カーソルがその上にあることを検出します。

onmouseout-カーソルが離れたときを検出します。

4
HIRA THAKUR

よりエレガントな(ただしパフォーマンスが低い可能性が高い)ソリューション:

入力のonblurを使用してメニューを削除する代わりに、onblurの後に起動する_document.onclick_を使用します。

ただし、これは、入力自体がクリックされたときにメニューが削除されることも意味します。これは望ましくない動作です。 event.stopPropagation()で_input.onclick_を設定して、ドキュメントクリックイベントへのクリックの伝播を回避します。

2
1''

onClickonMouseDownに置き換えないでください。

このアプローチややうまくいくの場合、2つは根本的に異なるイベントであり、ユーザーの目には異なる期待を持っています。この場合、onMouseDownの代わりにonClickを使用すると、ソフトウェアの予測可能性が損なわれます。したがって、2つのイベントは互換性がありません。

たとえば、ボタンを誤ってクリックした場合、ユーザーはマウスのクリックを押したまま、要素の外側にカーソルをドラッグし、マウスボタンを放すと、最終的にアクションが発生しないことを期待します。 onClickはこれを行います。 onMouseDownは、ユーザーがマウスを押したままにすることを許可せず、代わりにユーザーに頼ることなくすぐにアクションをトリガーします。 onClickは、コンピューターでアクションをトリガーするための標準です。

この状況では、onMouseDownイベントでevent.preventDefault()を呼び出します。デフォルトでは、onMouseDownはデフォルトでblurイベントを発生させますが、preventDefaultが呼び出された場合は発生しません。その後、onClickが呼び出される機会があります。 onClickの後でのみ、ぼかしイベントが発生します。

結局、onClickイベントは、両方が同じ要素内で発生する場合にのみ、onMouseDownonMouseUpの組み合わせです。

1
eyeino

onfocusでonclickを変更

onblurとonclickがあまりうまくいかない場合でも、明らかにonfocusとyes onblurです。メニューが閉じられた後でも、内部でクリックされた要素に対してonfocusが有効であるためです。

私がやったし、それは働いた。

0
Brasil