JavaScript
HTML5

HTML5でファイルをドロップする際に画面全体にオーバーレイを表示する方法

More than 3 years have passed since last update.

そもそもファイルをドラッグ&ドロップする方法は以下の記事が参考になります.
JavaScript - HTML5でファイルをドラッグして読み込むやつ - Qiita

本題

上記の記事はとてもわかりやすく参考になるのだが,タイトルに書いたようなことをすると少しはまる.
どういう事かと言うと以下の用なコードを書いた時にdragleaveイベントがオーバーレイが出たときに発火してしまうのだ.

$('body').on('dragover', function(e){
    e.stopPropagation();
    e.preventDefault();
    $('#overlay').fadeIn(300);
});

$('body').on('dragleave', function(e){
    e.stopPropagation();
    e.preventDefault();
    $('#overlay').fadeOut(300);
});

一瞬オーバーレイが表示されたかと思ったらすぐにまた消えてしまう.
これを解決する方法を探しているとstackoverflowに参考になるものを発見した.
HTML5 dragleave fired when hovering a child element
これの回答の通りにマスクを作ってやるとうまく動く.
ポイントはdragleaveイベントとdropイベントのハンドリングをマスクのイベントリスナーで処理しているところである.
以下にこれを考慮したコードを示す.

var drop_mask = $('<div />').css({
    position: 'fixed',
    top: 0,
    left: 0,
    width: '100%',
    height: '100%',
    opacity: 0,
    display: 'none',
    'z-index': 9999
});

$('body').append(drop_mask);

$('body').on('dragover', function(e){
    e.stopPropagation();
    e.preventDefault();
    drop_mask.show();
    $('#overlay').fadeIn(300);
});

drop_mask.on('dragleave', function(e){
    e.stopPropagation();
    e.preventDefault();
    drop_mask.hide();
    $('#overlay').fadeOut(300);
});

drop_mask.on('drop', function(e){
    e.stopPropagation();
    e.preventDefault();
    drop_mask.hide();
    $('#overlay').fadeOut(300);
});

オーバーレイ自体のコードはこんな感じ.

<div id="overlay"></div>
#overlay{
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: black;
    opacity: 0.8;
    display: none;
}