[解決済み] 子要素の上にドラッグすると、親要素の 'dragleave' が発生する
質問
概要
以下のようなHTML構造になっているので、その上に
dragenter
と
dragleave
イベントを
<div id="dropzone">
要素を使用します。
<div id="dropzone">
<div id="dropzone-content">
<div id="drag-n-drop">
<div class="text">this is some text</div>
<div class="text">this is a container with text and images</div>
</div>
</div>
</div>
問題点
の上にファイルをドラッグすると
<div id="dropzone">
を使用します。
dragenter
イベントは期待通りに発生します。しかし、マウスを子要素の上に移動させると、例えば
<div id="drag-n-drop">
を実行すると
dragenter
イベントが発生します。
<div id="drag-n-drop">
要素で、その後に
dragleave
イベントが発生します。
<div id="dropzone">
要素を使用します。
にカーソルを合わせると
<div id="dropzone">
要素で、もう一度
dragenter
イベントが再び発生し、それはそれでクールなのですが、その後に
dragleave
イベントが左の子要素に対して発生するので
removeClass
という命令が実行されてしまい、カッコ悪いです。
この動作が問題となる理由は2つあります。
-
を付けるだけです。
dragenter
&です。dragleave
から<div id="dropzone">
ということで、なぜ子要素にもこれらのイベントが付随しているのか理解できません。 -
の上にドラッグしたままです。
<div id="dropzone">
要素の子要素にカーソルを合わせているときにdragleave
を発射してください。
jsFiddle
ここで、jsFiddleをいじってみましょう。 http://jsfiddle.net/yYF3S/2/
質問
ファイルをドラッグして
<div id="dropzone">
要素を使用します。
dragleave
は、子要素の上をドラッグしていても発生しません...。
<div id="dropzone">
要素の境界内の任意の場所でホバーリング/ドラッグしてください。
はいけません。
をトリガーします。
dragleave
イベントが発生します。
少なくともHTML5のドラッグ&ドロップに対応しているブラウザでは、クロスブラウザ対応にする必要があるので、次のようにします。 この答え は適切ではありません。
GoogleやDropboxはこれを理解しているようですが、彼らのソースコードはminified/complexなので、彼らの実装からこれを理解することはできていません。
解決方法は?
ようやく満足のいく解決策を見つけました。実は、欲しいものを実現する方法をいくつか見つけたのですが、どれも今回の解決策ほどうまくはいきませんでした。
#dropzone
別のものでは、ブラウザからカーソルを離してもボーダーが消えないというものでした。
とにかく、私の一番のハックションはこれです。
var dragging = 0;
attachEvent(window, 'dragenter', function(event) {
dragging++;
$(dropzone).addClass('drag-n-drop-hover');
event.stopPropagation();
event.preventDefault();
return false;
});
attachEvent(window, 'dragover', function(event) {
$(dropzone).addClass('drag-n-drop-hover');
event.stopPropagation();
event.preventDefault();
return false;
});
attachEvent(window, 'dragleave', function(event) {
dragging--;
if (dragging === 0) {
$(dropzone).removeClass('drag-n-drop-hover');
}
event.stopPropagation();
event.preventDefault();
return false;
});
これはかなりうまくいくのですが、Firefoxでは問題が発生しました。
dragenter
ということで、カウンタがずれてしまいました。しかし、それにもかかわらず、それは非常にエレガントなソリューションではありません。
そんな時、こんな質問を偶然見つけました。 Firefox でウィンドウの外側をドラッグしたときに dragleave イベントを検出する方法
そこで、私は 答え と、自分の状況に当てはめて考えてみました。
$.fn.dndhover = function(options) {
return this.each(function() {
var self = $(this);
var collection = $();
self.on('dragenter', function(event) {
if (collection.size() === 0) {
self.trigger('dndHoverStart');
}
collection = collection.add(event.target);
});
self.on('dragleave', function(event) {
/*
* Firefox 3.6 fires the dragleave event on the previous element
* before firing dragenter on the next one so we introduce a delay
*/
setTimeout(function() {
collection = collection.not(event.target);
if (collection.size() === 0) {
self.trigger('dndHoverEnd');
}
}, 1);
});
});
};
$('#dropzone').dndhover().on({
'dndHoverStart': function(event) {
$('#dropzone').addClass('drag-n-drop-hover');
event.stopPropagation();
event.preventDefault();
return false;
},
'dndHoverEnd': function(event) {
$('#dropzone').removeClass('drag-n-drop-hover');
event.stopPropagation();
event.preventDefault();
return false;
}
});
これはクリーンでエレガントで、これまで私がテストしたすべてのブラウザで動作しているようです(IEはまだテストしていません)。
関連
-
[解決済み] jQueryでdata属性で要素を選択する
-
[解決済み] jQuery UIダイアログのクローズボタンを削除するには?
-
[解決済み] チェックボックスのチェック/アンチェックは、jqueryを使用していますか?重複
-
[解決済み] Twitter Bootstrapのモーダルウィンドウを閉じないようにする
-
[解決済み] jQueryを使用してCSSのdisplay noneまたはblockプロパティを変更するにはどうすればよいですか?
-
[解決済み] jQueryでフォームフィールドをクリアする
-
[解決済み] jQueryでloading spinnerを表示するには?
-
[解決済み] jQuery OR Selector?
-
[解決済み】absoluteの親divの子要素をホバーしたときのonmouseoutをjQueryなしで防止する。
-
[解決済み] jQuery append() - 追記された要素を返す
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Microsoft JSONの日付はどのようにフォーマットするのですか?
-
[解決済み] 選択オプション「selected」を値で設定する
-
[解決済み] jQueryのイベントハンドラを削除する最良の方法?
-
[解決済み] jQuery データ属性の値に基づいて要素を検索する方法は?
-
[解決済み] jQuery UIダイアログのクローズボタンを削除するには?
-
[解決済み] jQuery hasAttrで要素に属性があるかどうかをチェックする【重複あり
-
[解決済み] Google Maps APIでマウスのスクロールホイールによる拡大縮小を無効にする方法
-
[解決済み] Bootstrapのモーダルを閉じる
-
[解決済み】jQuery:keyPress Backspaceが発射されない?
-
[解決済み] jQuery append() - 追記された要素を返す