Drag & Drop - HTML5 版

 

Firefox 3.5 以外に、Chrome 4 でも動くように JavaScript を修正しました。 Chrome 3, Safari 4 では視覚的に問題がありますが動きます。 修正内容は更新履歴を参照してください。

2009-11-18

HTML5 の Drag and Drop API を使用して作成した、ドラッグ&ドロップのサンプルです。

作り方は、 HTML5 Drag and drop demonstration を参考にしました。 実際に動いているものを目にすると励まされますね。 どうも有難う、Laurent Jouanneau.

他の資料としては、 ドラッグの操作 - MDC あたりにも目を通しておくと良いかも知れません(より良い実装方法が見つかるかも?)。

Demo

問題.次の表をドラッグ&ドロップにより完成させてください。

FIFA World Cup 開催国
2006年
Berlin
2010年
Johannesburg
2014年
Rio de Janeiro
選択肢

  

ソースコード

ここでは JavaScript のみ掲載します。 HTML と CSS については 全ソースコード を参照してください。

JavaScript では、HTML5 のネイティブAPIを呼び出すだけです。 いかなる外部ライブラリも使用しません。

JavaScript
<script type="text/javascript">
//<![CDATA[
(function() {

var $ = function(id){return document.getElementById(id)};

var correct = { opt0: 'ans1', opt1: 'ans2', opt2: 'ans0' }  // 正解

// 採点
var mark = function(event) {
    var points = 0;
    var max = 0;
    for (key in correct) {
        var answer = $(key).parentNode.id;
        points += (correct[key] == answer) ? 1: 0;
        ++max;
    }
    var score = Math.floor(points / max * 100);
    var judge = (score >= 70) ? '合格': '不合格';
    $('result').innerHTML = judge + ':' + score + '%';
}

// ドラッグ開始
var doDragStart = function(event) {
    event.dataTransfer.setData('text', event.currentTarget.id);
}

// ドロップゾーンに入った
var doDragEnter = function(event) {
    event.currentTarget.setAttribute('class','dropzone dragenter')
}

// ドロップゾーンに滞在中
var doDragOver = function(event) {
    if (event.currentTarget.getElementsByClassName('draggable').length === 0) {
        event.preventDefault();  // ドロップを許可
    }
}

// ドロップゾーンから出た
var doDragLeave = function(event) {
    event.currentTarget.setAttribute('class','dropzone');
}

// ドロップされたときの処理
var doDrop = function(event) {
    event.currentTarget.appendChild($(event.dataTransfer.getData('text')));
}

// NodeList(HTMLCollection) を Array に変換
nl2a = function(nl){
    var a = [];
    for (var i = 0; i < nl.length; ++i) { a.push(nl[i]); }
    return a;
}

// 初期化
window.addEventListener('load', function(event) {
    // ドロップゾーン
    nl2a(document.getElementsByClassName('dropzone'))
         .filter(function(elm){return elm.nodeName === 'DIV'})
         .forEach(function(elm){
             elm.addEventListener('dragenter', doDragEnter, false);
             elm.addEventListener('dragover',  doDragOver,  false);
             elm.addEventListener('dragleave', doDragLeave, false);
             elm.addEventListener('drop',      doDrop,      false);
         });

    // ドラッグ要素
    nl2a(document.getElementsByClassName('draggable'))
         .filter(function(elm){return elm.nodeName === 'DIV'})
         .forEach(function(elm){
            elm.getElementsByTagName('img')[0].setAttribute('draggable', 'false');
            elm.setAttribute('draggable', 'true');
            elm.addEventListener('dragstart', doDragStart, false);
         });

    $('submit').addEventListener('click', mark, false);
    $('wait').style.display = 'none';
}, false);

})();
//]]>
</script>

更新履歴

日付 内容
2009-11-18 修正 Chrome 4 でも動くように JavaScript を修正しました。
….setData('id',…) → ….setData('text',…)
….getData('id',…) → ….getData('text',…)
2009-02-28 変更 気に入らない所を修正(特に「初期化」と「ドロップの受け入れ拒否」)
2008-09-12 初版