超軽量・VanillaなJavascriptでiPhoneなどのtouchデバイスでDrag & Drop Sort

2015-09-01

HTML5の標準でDrag&Dropが実装されましたので、jQueryなどを使わなくてもドラッグ&ドロップが簡単に実現できるようになりました。 ただし、マウスイベントのみという状況なので、iPhoneなどのマウスを使わない、Touchイベントのデバイスでは一工夫必要です。

実際に動くデモを見てもらったほうが早いので、iPhoneなどのTouchデバイスで以下のリストをドラッグして並び替えてみてください。

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 pointedElement = document.elementFromPoint(e.pageX - window.pageXOffset, e.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(e.pageX - window.pageXOffset, e.pageY - window.pageYOffset);
if(!pointedElement.getAttribute('draggable') || pointedElement == draggingItem) return;

これがHTML5で実装されていないtouchenterの代わりの役目をしています。

そろそろみんなjQueryから脱して、Vanillaなコードを広めていきましょうよ。

JavaScriptHTML5