超軽量・VanillaなJavascriptでiPhoneなどのtouchデバイスでDrag & Drop Sort
2019-04-19
HTML5の標準でDrag&Dropが実装されましたので、jQueryなどを使わなくてもドラッグ&ドロップが簡単に実現できるようになりました。 ただし、マウスイベントのみという状況なので、iPhoneなどのマウスを使わない、Touchイベントのデバイスでは一工夫必要です。
実際に動くデモを見てもらったほうが早いので、iPhoneなどのTouchデバイスで以下のリストをドラッグして並び替えてみてください。
2019/4/19修正:タッチしている座標を取得するのにe.changedTouches[0].pageXとすべきところがe.pageXとなってました。これを公開した2015年当時はちゃんとテストしたと思うけど、動いてたのかなぁ?
Drag and Drop sort デモ
- One
- Two
- Three
JavaScriptのコードはたったこれだけです。
もちろんjQueryなどのライブラリは一切使用しません。
デモではPCでもドラッグできるように、dragenterなどのイベントも設定していますが、基本的には、必要なのは以下のコードのみです。
JavaScriptコード + HTML
<style>
#demo{
border:1px solid #333;
}
#demo li{
margin:10px;
padding:10px;
background:#aaa;
}
</style>
<div id="demo">
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
</div>
<script>
var lis = document.querySelectorAll('li');
var draggingItem;
[].forEach.call(lis, function(li){
li.setAttribute('draggable', true);
li.addEventListener('touchstart', function(e){
draggingItem = li;
});
li.addEventListener('touchend', function(e){
draggingItem = null;
});
li.addEventListener('touchmove', function(e){
e.preventDefault();
var getOrder = function(elem){
return [].indexOf.call(elem.parentNode.children, elem);
}
var ec = e.changedTouches[0];
var pointedElement = document.elementFromPoint(ec.pageX - window.pageXOffset, ec.pageY - window.pageYOffset);
if(!pointedElement.getAttribute('draggable') || pointedElement == draggingItem) return;
var order = getOrder(pointedElement) - getOrder(draggingItem);
if(order > 0) {
pointedElement.parentNode.insertBefore(pointedElement, draggingItem);
} else if (order < 0) {
pointedElement.parentNode.insertBefore(draggingItem, pointedElement);
}
});
});
</script>
きもは、touchmoveイベントで設定している以下の関数で、
var pointedElement = document.elementFromPoint(ec.pageX - window.pageXOffset, ec.pageY - window.pageYOffset);
if(!pointedElement.getAttribute('draggable') || pointedElement == draggingItem) return;
これがHTML5で実装されていないtouchenterの代わりの役目をしています。
そろそろみんなjQueryから脱して、Vanillaなコードを広めていきましょうよ。