JavaScriptで確実にmouseupをつかんでblur()する。

JavaScriptで確実にmouseupをつかんでblur()する。

Marker Workbook

PDF.jsとReactでブラウザ上で完結する暗記帳的なものをつくった。 - Qiita

ではキーボード・ショートカットでスペースを使うのですが、ボタン押下後にスペースを押すと、そのボタンにフォーカスが残っていて再度押下されてつらいということになりました。

というわけで押下後はフォーカスを外していきたいのですが、マウスアップにe.currentTarget.blur()とした場合、マウスダウンしたままでボタンの外にカーソルを移動しマウスアップした場合、マウスアップイベントは発行されません。ので、blur()が不発に終わります。ぶるぁ。

というわけで、古来からの手法で、blur()されるボタンをReactでつくります。

import * as React from "react";
import * as ReactDOM from 'react-dom';

export default class BlurButton extends React.Component {
  render(){
    let onMouseDown = (e)=>{
      this.props.onMouseDown && this.props.onMouseDown(e);

      let button = e.currentTarget;
      let up = (e)=>{
        button.blur();
        window.removeEventListener('mouseup', up);
      };
      window.addEventListener('mouseup', up);
    };

    return <button {...this.props} {...{onMouseDown}}>{this.props.children}</button>
  }
}

マウスダウン時にwindowにイベントリスナーを付与して、どこでマウスアップしようがとにかくblur()します。

buttonタグを単純にリプレイスできるように、propsは単純にバケツリレーして、onMouseDownだけはラップしてblur()を入れます。

これでとりあえずスペースやエンターでボタンが再度押下される不幸がなくなりました。