背景
私は、データベースに手動でソート順の番号を入力しなくても済むように、ソート可能なリストを作成中です。これは、HTML5 のドラッグ アンド ドロップ機能、つまりdrag*
JavaScript の新しいイベントを介して機能します。
現時点では、ほとんどの部分で動作しています。クリックしてドラッグすると、自動的に並べ替えられます。
問題
私の知る限りでは、drop
、およびイベントdragstart
はdragend
、それらが入る要素のみを認識します。マウスがドロップゾーンの上半分にあるか、下半分にあるかはわかりません。
私が望んでいるのは、リスト項目の上半分にマウスを移動したときに、ドラッグしたコンテンツが項目の上に配置され、下半分にマウスを移動したときに、ドラッグしたコンテンツが項目の下に配置されます。
現在:
下のスクリーンショットでは、私のコードの動作例 (簡略化) を示しています。border-bottom
ドロップ ターゲットに を使って、それがターゲットであることを示しています。「アイテム 1」が「アイテム 2」の上にある場合、マウスを上半分または下半分のどちらに置いているかに関係なく、「アイテム 2」の下部が点灯していることに注目してください。
コード
var dragging = null;
document.addEventListener('dragstart', function(event) {
dragging = event.target;
event.dataTransfer.setData('text/html', dragging);
});
document.addEventListener('dragover', function(event) {
event.preventDefault();
});
document.addEventListener('dragenter', function(event) {
event.target.style['border-bottom'] = 'solid 4px blue';
});
document.addEventListener('dragleave', function(event) {
event.target.style['border-bottom'] = '';
});
document.addEventListener('drop', function(event) {
event.preventDefault();
event.target.style['border-bottom'] = '';
event.target.parentNode.insertBefore(dragging, event.target.nextSibling);
});
ul {
margin:0;
padding:0
}
li {
cursor:move;
display:block;
padding:20px 10px;
background:white;
border-bottom:solid 1px gray;
}
<ul>
<li draggable="true" class="sortable-bulk">List Item 1</li>
<li draggable="true" class="sortable-bulk">List Item 2</li>
<li draggable="true" class="sortable-bulk">List Item 3</li>
<li draggable="true" class="sortable-bulk">List Item 4</li>
<li draggable="true" class="sortable-bulk">List Item 5</li>
<li draggable="true" class="sortable-bulk">List Item 6</li>
<li draggable="true" class="sortable-bulk">List Item 7</li>
<li draggable="true" class="sortable-bulk">List Item 8</li>
<li draggable="true" class="sortable-bulk">List Item 9</li>
<li draggable="true" class="sortable-bulk">List Item 10</li>
</ul>
質問
ドラッグ中のマウスの位置に応じて、常に下ではなく上または下にドロップする方法はありますか?
ベストアンサー1
答え
運命のいたずらか、別の質問に対するコメントの返信が、ここでの答えに私を導いてくれました。狼戦争ここで評価に値するのは私を指差して適切なイベントとメソッドに。
とにかく、答えに移りましょう。解決策は、dragover
イベントを使用するのではなく、dragenter
イベントを使用することです。dragover
ホバーしている限り、イベントは発生し続けます。
質問コードからのコードの変更
コードを削除しますdragenter
:
document.addEventListener('dragenter', function(event) {
event.target.style['border-bottom'] = 'solid 4px blue';
});
次のように置き換えます:
document.addEventListener('dragover', function(event) {
event.preventDefault();
var bounding = event.target.getBoundingClientRect()
var offset = bounding.y + (bounding.height/2);
if ( event.clientY - offset > 0 ) {
event.target.style['border-bottom'] = 'solid 4px blue';
event.target.style['border-top'] = '';
} else {
event.target.style['border-top'] = 'solid 4px blue';
event.target.style['border-bottom'] = '';
}
});
次に、セクションでdrop
、ドロップ ターゲットにどの境界線があるかを確認し、それを使用してドラッグしたコンテンツを上または下に挿入します。
完全な動作コード:
var dragging = null;
document.addEventListener('dragstart', function(event) {
var target = getLI( event.target );
dragging = target;
event.dataTransfer.setData('text/plain', null);
event.dataTransfer.setDragImage(self.dragging,0,0);
});
document.addEventListener('dragover', function(event) {
event.preventDefault();
var target = getLI( event.target );
var bounding = target.getBoundingClientRect()
var offset = bounding.y + (bounding.height/2);
if ( event.clientY - offset > 0 ) {
target.style['border-bottom'] = 'solid 4px blue';
target.style['border-top'] = '';
} else {
target.style['border-top'] = 'solid 4px blue';
target.style['border-bottom'] = '';
}
});
document.addEventListener('dragleave', function(event) {
var target = getLI( event.target );
target.style['border-bottom'] = '';
target.style['border-top'] = '';
});
document.addEventListener('drop', function(event) {
event.preventDefault();
var target = getLI( event.target );
if ( target.style['border-bottom'] !== '' ) {
target.style['border-bottom'] = '';
target.parentNode.insertBefore(dragging, event.target.nextSibling);
} else {
target.style['border-top'] = '';
target.parentNode.insertBefore(dragging, event.target);
}
});
function getLI( target ) {
while ( target.nodeName.toLowerCase() != 'li' && target.nodeName.toLowerCase() != 'body' ) {
target = target.parentNode;
}
if ( target.nodeName.toLowerCase() == 'body' ) {
return false;
} else {
return target;
}
}
ul {
margin:0;
padding:0
}
li {
cursor:move;
display:block;
padding:20px 10px;
background:white;
border-bottom:solid 1px gray;
}
<ul>
<li draggable="true">List Item 1</li>
<li draggable="true">List Item 2</li>
<li draggable="true">List Item 3</li>
<li draggable="true">List Item 4</li>
<li draggable="true">List Item 5</li>
<li draggable="true">List Item 6</li>
<li draggable="true">List Item 7</li>
<li draggable="true">List Item 8</li>
<li draggable="true">List Item 9</li>
<li draggable="true">List Item 10</li>
</ul>