【メモ】『js権威ガイド』-第17章イベント処理17.7-17.8


1.ドラッグ&ドロップイベント:
(1). draggableプロパティのある要素はすべてドラッグ&ドロップソースです.
(2). ユーザが要素をドラッグするとdragstartイベントがトリガーされます.
(3). dragstartイベントのハンドラで呼び出すことができます.
a. dataTransfer.setData()ドラッグ&ドロップデータを指定します.HTML5: dataTransfer.items.add()
b. dataTransfer.effectAllowedは、移動、コピー、リンクを含む転送操作を指定します.
c.dataTransfer.setDragImage()とaddElement(不完全なサポート)は、ドラッグ時の視覚効果を指定します.
(4). ドラッグ中にドラッグイベントがトリガーされ、ドラッグ中にデータを変更したり、ドラッグ画像を更新したりすることができます.
(5). 要素の配置時にdragendイベントがトリガーされ、ドラッグ&ドロップソースが移動操作をサポートする場合、dataTransferがチェックされます.dropEffectが実際に移動操作を実行しているかどうか、実行している場合はデータが転送され、ドラッグ&ドロップソースから削除する必要があります.
簡単なドラッグ&ドロップソースの例:
var clock = document.getElementById("clock");
var icon = new Image();
icon.src = "clock.jpg";

clock.draggable = true;
clock.ondragstart = function(event) {
	var event = event || window.event;
	var dt = event.dataTransfer;

	dt.setData("Text", new Date() + "
"); if (dt.setDragImage) dt.setDragImage(icon, 0, 0); };
(6). ドラッグアンドドロップオブジェクトがドキュメント要素に入ると、ブラウザはその要素でdragenterイベントをトリガーします.
(7). ドラッグアンドドロップターゲットはdataTransferを使用します.typesドラッグ&ドロップオブジェクトのデータを検証します.dtを使用する.effectAllowedドラッグアンドドロップ操作のタイプを確認します.
(8). ドラッグ&ドロップターゲットは、ドラッグ&ドロップオブジェクトの配置に興味があることを示します.dragenterイベントをキャンセルします.
(9). dragoverイベントを受信し、配置に興味がある場合はdragoverイベントをキャンセルします.
(10). ドラッグ&ドロップオブジェクトがドラッグ&ドロップターゲットから離れた場合(enterおよびoverイベントがキャンセルされた)、ドラッグ&ドロップターゲットはdragleaveイベントを受信します.
(11). ドラッグ&ドロップターゲット上でドラッグ&ドロップオブジェクトを解放するdropイベントをトリガーする場合はdtを使用します.getData()は、設定するデータを取得し、ドラッグアンドドロップが1つ以上のファイルである場合はdt.filesはFileクラス配列を取得します.html 5ではdtを通過することができる.itemsはファイルと非ファイルのデータにアクセスします.
var lists = document.getElementsByTagName("ul");
var regexp = /\bdnd\b/;
for (var i = 0; i < lists.length; i++) {
	if (regexp.test(lists[i].className)) dnd(lists[i]);
}

function dnd(list) {
	var original_class = list.className;
	var entered = 0;
	
	list.ondragenter = function(e) {
		e = e || window.event;
		var from = e.relatedTarget;
		
		entered++;
		if ((from && !ischild(from, list)) || entered == 1) {
			var dt = e.dataTransfer;
			var types = dt.types;
			
			if (!types || //IE
				(types.contains && types.contains("text/plain")) || //HTML5
				(types.indexOf && types.indexOf("text/plain") != -1))//Webkit 
				{
					list.className = original_class + " droppable";	
					//            
					return false;
				}
				
			return;
		}
		//       
		return false;
	};
	
	list.ondragover = function(e) {return false;};
	
	list.ondragleave = function(e) {
		e = e || window.event;
		var to = e.relatedTarget;
		
		entered--;
		if ((to && !ischild(to, list)) || entered <= 0) {
			list.className = original_class;
			entered = 0;
		}
		return false;
	};
	
	list.ondrop = function(e) {
		e = e || window.event;
		var dt = e.dataTransfer;
		var text = dt.getData("Text");
		
		if (text) {
			var item = document.createElement("li");
			item.draggable = true;
			item.appendChild(document.createTextNode(text));
			list.appendChild(item);
			list.className = original_class;
			entered = 0;
			return false;
		}
	};
	
	var items = list.getElementsByTagName("li");
	for(var i = 0; i < items.length; i++)
		items[i].draggable = true;
		
	list.ondragstart = function(e) {
		var e = e || window.event;
		var target = e.target || e.srcElement;
		
		if (target.tagName != "LI") return false;
		var dt = e.dataTransfer;
		dt.setData("Text", target.innerText || target.textContent);
		dt.effectAllowed = "copyMove";
	};
	
	list.ondragend = function(e) {
		e = e || window.event;
		var target = e.target || e.srcElement;
		
		if (e.dataTransfer.dropEffect ==="move")
			target.parentNode.removeChild(target);
	};
	
	function ischild(a, b) {
		for(; a; a = a.parentNode) if (a === b) return true;
		return false;
	}
};

2.テキストイベント:
テキスト入力の処理例:
if (elt.addEventListener) {
    elt.addEventListener("keypress", func, false);
    elt.addEventListener("textInput", func, false);
    elt.addEventListener("textinput", func, false);
}
else {
    elt.attachEvent("onkeypress", filter);
}

function func(event) {
    var e = event || window.event;
    var target = e.target || e.srcElement;
    if (e.type === "textinput" || e.type === "textInput") text = e.data;
    else {
        var code = e.charCode || e.keyCode;
        if (code < 32 || e.charCode == 0 || e.ctrlKey || e.altKey)
            return;
        var text = String.fromCharCode(code);
    }
}

テキスト挿入の処理例:
function forceToUpperCase(element) {
	if (typeof element === "string") element = document.getElementById(element);
	element.oninput = upcase;    // IE
	element.onpropertychange = upcaseOnpropertyChange;   //IE
	
	function upcase(event) {
		this.value = this.value.toUpperCase();
	};
	function upcaseOnPropertyChange(event) {
		var e = event || window.event;
		if (e.propertyName === "value") {
			this.onpropertychange = null;
			this.value = this.value.toUpperCase();
			this.onpropertychange = upcaseOnPropertyChange;
		}
	};
}