自己紹介

第2回目の板敷さんからバトンを受けまして第3回目を担当させて頂く手塚です。よろしくお願いします!


僕と板敷さんの関係ですが、以前現場で一緒に仕事をしていました。
その現場で苦も楽も経験した仲間であり先輩です。
色々とお世話になりました。m(- -)m
板敷さんとはその時からお付き合いさせて頂いています。


さて、簡単に自己紹介をさせて頂きます。
平日は真面目にお仕事、週末はたまにクラブで踊る事がストレス発散の音楽大好きエンジニアです。
(音楽のジャンルはHip Hop、Soul、Funk等が好き!)
仕事の谷間の時期には長期休暇を頂いては海外に現実逃避旅行してます。
(融通が利くのがフリーの良い所!)


仕事面ですが、今までは主に設計・実装(言語はJava等)の仕事が中心ですが、
現在は運用業務・運用チーム管理・業務改善・実装のサポートと色んな事をやっています。
まさに頭をフル回転させています。
責任のある仕事を任されている事にありがたみを感じ、充実の毎日です。
(やりがいある仕事じゃないとつまらないですよね!)


今回はひょんな事からコラムを書く事になり、HTML5について勉強しました。
もちろん以前からHTML5については知っていたのですが、実際にコーディングするのは初めてです。
ですので、皆さんと同じ目線でコラムが書ければと思っています。
これから主流になるであろう技術なので早めに覚えたい所ですね!


ドラッグ & ドロップについて

第3回目はドラッグ&ドロップについて実装していきます。
今までもJQueryのプラグイン等を使用する事でドラッグ&ドロップは実装可能でしたが、
HTML5からは標準機能として追加されてます。(便利!)
個人的には標準仕様でこんな事が出来る事に次世代を感じてます!


今回はドラッグ&ドロップ機能の4つのイベントを使用して実装していきます。
各イベントの説明は以下の通りです。

表1.ドラッグ & ドロップのイベントの種類
イベント名説明
dragstartドラッグ開始のイベントを処理
dragenterマウスカーソルが、要素と重なった瞬間に呼び出されるイベント
dragoverマウスカーソルが要素上を横切っている間、断続的に発生するイベント
dropドロップ処理イベント



ドラッグ開始処理

さて早速ですが実装に移ります。
最初にこの関数では数字に対してdragstartイベントを追加します。 リスト1を見てみましょう。

リスト1 addEventListenerToNumberButton関数
function addEventListenerToNumberButton() {

var numImages = document.querySelectorAll("img[id^='num']"); // (1)

for(var i = 0; i < numImages.length; i++) { // (2)
var numImg = numImages.item(i);
numImg.addEventListener("dragstart", function(event) {
event.dataTransfer.setData("text", event.target.id);
}, false);
}
}


(1) Selectors APIを使い、idが"num"で始まるimgタグを全て取得します。
Selectors API のクエリには、ドキュメント内のすべてのオブジェクトが含まれます。カッコ内の条件をもとにオブジェクトを絞って取得しています。ここで取得した値は数字のimgタグです。
var numImages = document.querySelectorAll("img[id^='num']");  //(1)


(2) 取得した数字にドラッグ開始イベント(dragstart)を登録します。
dragstartイベント時にdataTransferに数字のIDをセットする事でドロップ時に取得可能となります。
for(var i = 0; i < numImages.length; i++) {  //(2)
var numImg = numImages.item(i);
numImg.addEventListener("dragstart", function(event) {
event.dataTransfer.setData("text", event.target.id);
}, false);
}



ドロップ処理

続きましてdragenter、dragover、dropイベントを追加する関数です。 リスト2を見てみましょう。

リスト2 addEventListenerToLeftNum関数
function addEventListenerToLeftNum(leftNum) {
leftNum.addEventListener("dragenter", function(event) {
event.preventDefault(); // (1)
}, false);

leftNum.addEventListener("dragover", function(event) {
event.preventDefault(); // (1)
}, false);

/*
* ドロップイベント処理を追加
*/
leftNum.addEventListener("drop", function(event) { // (2)
var id = event.dataTransfer.getData("text"); // (3)
var selectedNum = id.slice(3); // (4)

if (leftNum.id == "leftNum1") { // (5)
selectedLeftNum1 = selectedNum;

} else if (leftNum.id == "leftNum2") {
selectedLeftNum2 = selectedNum;
}

var numImg = document.getElementById(id); // (6)
var newImg = document.createElement("img");
newImg.src = numImg.src;

var oldChild = leftNum.firstChild;
leftNum.replaceChild(newImg, oldChild); // (7)

event.preventDefault();

if (isReadyToCalculate()) { // (8)
checkAnswer();
}

}, false);
}


(1) dragenterイベントとdragoverイベント時のデフォルト動作をキャンセルします。
leftNum.addEventListener("dragenter", function(event) {
event.preventDefault(); // (1)
}, false);

leftNum.addEventListener("dragover", function(event) {
event.preventDefault(); // (1)
}, false);


(2) 次にdropイベント時の処理を書いて行きます。
leftNum.addEventListener("drop", function(event) { // (2)


(3) dragstartイベント時にセットした数字のidをdataTransferから取得します。
var id = event.dataTransfer.getData("text");	// (3)


(4) 数字ボタンのid(num1~10)から、"num"の部分を除く数字を取得します。
var selectedNum = id.slice(3);	// (4)


(5) ドラッグされた数字を、「選択中左辺値(1, 2)」に設定します。
if (leftNum.id == "leftNum1") {	// (5)
selectedLeftNum1 = selectedNum;
} else if (leftNum.id == "leftNum2") {
selectedLeftNum2 = selectedNum;
}


(6) ドラッグされた画像ファイルをドロップエリアにコピーします。
var numImg = document.getElementById(id);    // (6)
var newImg = document.createElement("img");
newImg.src = numImg.src;


(7) すでに画像が存在する場合、新しくドロップされたものと入れ替えます。
var oldChild = leftNum.firstChild;    // (7)
leftNum.replaceChild(newImg, oldChild);


(8) 答え合わせ処理(※)の実行が可能か確認し、可能であれば答え合わせを実行します。
※第5回に説明予定です。
if (isReadyToCalculate()) {    // (8)
checkAnswer();
}


プログラム開始処理

最後に開始時に作成した各イベントを追加する処理です。 リスト3を見て行きましょう。

リスト3 addEventListener関数

document.addEventListener("DOMContentLoaded", function() { // (1)
addEventListenerToNumberButton();

var leftNum1 = document.getElementById("leftNum1");
addEventListenerToLeftNum(leftNum1);

var leftNum2 = document.getElementById("leftNum2");
addEventListenerToLeftNum(leftNum2);

setUpCalcArea();
}, false);

(1) DOMContentLoadedイベント発生時、先ほど実装したドラッグ & ドロップの処理、計算エリア初期化(※)の処理を呼び出します。
DOMContentLoadedイベントとはブラウザが起動し、DOMツリーを完成させた時に発生するイベントで、HTML5から標準化されるイベントです。
※計算エリア初期化の処理については第5回に説明予定です。



最後に

第3回のコラムの内容はドラッグ&ドロップでした。どうでしたか?

今までのHTMLでは出来なかった新しい可能性が見えてくるのではないでしょうか。
発想次第では面白いアプリも作成可能ですよね。

次回はCSS3でアニメーションです。
いつもニコニコ人情系エンジニアの遠藤さんよろしくおねがいします!


ペタしてね読者登録してね