DD: Reordering a List(その2)
さきほどの例(DD: Reordering a List)を見た際、冗長なプログラムと思ったが、以下の画面は、前の例で作成したDDList(
YAHOO.util.DDProxyを継承して作成)をまったく変えずに、タグとStyleのみ変更して作成したもの。
List1の中にList2が入れ子になっているが、これもDrag & Dropで同様の動きをする。
(ただし、「現在の順番」の表示時に、List1にList2の内容が混じってしまう。これは、修正すれば回避可能)
先ほどのようなリストと同様に、以下のような入れ子のリストもよく登場するから、使えるかも。
以下にソースコードの全文を示す。
<HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=UTF-8"> <META http-equiv="Content-Style-Type" content="text/css"> <TITLE>Ajax_Sampling</TITLE> <style type="text/css"> div.workarea { padding:10px; float:left } .div1 { border: 2px solid gray; padding:2; } .div2 { border: 1px solid gray; padding:2; } ul.draglist li { margin: 1px; cursor: move; zoom: 1; } li.list1 { background-color: #D1E6EC; border:1px solid #7EA6B2; } li.list2 { margin: 10px; background-color: #D8D4E2; border:1px solid #6B4C86; } li.list3 { background-color: #D1E6EC; border:1px solid #7EA6B2; } </style> <!-- 読み込むjs --> <script type="text/javascript" src="scripts/yui/yahoo-dom-event/yahoo-dom-event.js" > </script> <script type="text/javascript" src="scripts/yui/dragdrop/dragdrop-min.js" > </script> <script type="text/javascript" src="scripts/yui/animation/animation-min.js" > </script> <script type="text/javascript"> var Dom = YAHOO.util.Dom; var Event = YAHOO.util.Event; var DDM = YAHOO.util.DragDropMgr; ////////////////////////////////////////////////////////////////////////////// //「現在の順番」表示、「バックグラウンドの消去」の処理。 ////////////////////////////////////////////////////////////////////////////// YAHOO.example.DDApp = { init: function() { var rows=3,cols=3,i,j; for (i=1;i<cols+1;i=i+1) { // ul要素はddTargetとしてインスタンス化 new YAHOO.util.DDTarget("ul"+i); } for (i=1;i<cols+1;i=i+1) { for (j=1;j<rows+1;j=j+1) { // ul要素はddListとしてインスタンス化 new YAHOO.example.DDList("li" + i + "_" + j); } } Event.on("showButton", "click", this.showOrder); }, //「現在の順番」を拾う処理 showOrder: function() { // この関数は下で使う。 var parseList = function(ul, title) { var items = ul.getElementsByTagName("li"); var out = title + ": "; for (i=0;i<items.length;i=i+1) { out += items[i].id + " "; } return out; }; var ul1=Dom.get("ul1"), ul2=Dom.get("ul2"),u13=Dom.get("ul3"); alert(parseList(ul1, "List 1") + "\n" + parseList(ul2, "List 2") + "\n" + parseList(ul3, "List 3")); }, }; ////////////////////////////////////////////////////////////////////////////// // custom drag and drop implementation ////////////////////////////////////////////////////////////////////////////// // DDProxyを継承して、DDListを作成するための準備。 YAHOO.example.DDList = function(id, sGroup, config) { // スーパークラスのコンストラクタの呼び出し。 YAHOO.example.DDList.superclass.constructor.call(this, id, sGroup, config); //this.logger = this.logger || YAHOO; var el = this.getDragEl(); // Domを1/3の透過とする。 Dom.setStyle(el, "opacity", 0.67); this.goingUp = false; this.lastY = 0; }; //DDProxyを継承して、DDListを作成する。 //thisは、DDListのインスタンスをあらわす。 YAHOO.extend(YAHOO.example.DDList, YAHOO.util.DDProxy, { // startDragのoverride startDrag: function(x, y) { // this.logger.log(this.id + " startDrag"); // ドラッグされるProxyElementを取得 var dragEl = this.getDragEl(); // ドラッグされる元のElementを取得 var clickEl = this.getEl(); // 元のエレメントは、非表示にする。 Dom.setStyle(clickEl, "visibility", "hidden"); // ProxyElementに、元のエレメントの要素を追加。 dragEl.innerHTML = clickEl.innerHTML; // ProxyElementに、元のエレメントのスタイルをコピー。 Dom.setStyle(dragEl, "color", Dom.getStyle(clickEl, "color")); Dom.setStyle(dragEl, "backgroundColor", Dom.getStyle(clickEl, "backgroundColor")); Dom.setStyle(dragEl, "border", "2px solid gray"); }, // endDragのoverride // startDragされて、Dropされずに、Mouseupされた場合に元に戻す処理。 endDrag: function(e) { // thisは、DDListのインスタンスをあらわす。 // DDListはli要素についてインスタンス化される。 // ドラッグさている元Elementを取得 var srcEl = this.getEl(); // ドラッグされているProxyElementを取得 var proxy = this.getDragEl(); // ProxyElementをみせて、元Elementの位置を取得して // Anim(Motion)で戻る。 Dom.setStyle(proxy, "visibility", ""); var a = new YAHOO.util.Motion( proxy, { points: { to: Dom.getXY(srcEl) } }, 0.2, YAHOO.util.Easing.easeOut ) var proxyid = proxy.id; // 元エレメントのID var thisid = this.id; // 上のMotionが終わったら、proxyを消して、元のエレメントを見せる。 a.onComplete.subscribe(function() { Dom.setStyle(proxyid, "visibility", "hidden"); Dom.setStyle(thisid, "visibility", ""); }); //Motionの発火 a.animate(); }, // onDragOverで挿入が行われていることに注意。 // (注)idは、Dragされた要素が、落っことされた要素のid onDragDrop: function(e, id) { // DDM.interactionInfo.dropはonDragDropでinteractions Pointを // 意味する。(APIドキュメント) // 1回のInteractionが行われたら。 // ただしい移動(挿入、移動)後はinteraction情報がクリアされる。 // 以下の条件を満たすのは、liがUL(のドロップゾーン)にinteractする場合。 // これ以外は、endDragで戻してしまう。 if (DDM.interactionInfo.drop.length === 1) { // Interact(Drop)したときのカーソルポジション // ※PointはYAHOO.util.Point(PointはRegionのサブクラス) var pt = DDM.interactionInfo.point; // Interact(Drop)したときの元要素の領域 // ※RegionはYAHOO.util.Regionのサブクラスと思われる。 var region = DDM.interactionInfo.sourceRegion; // regionがpointを含まなければ、子要素として追加。 if (!region.intersect(pt)) { //Dropされた場所の要素を取得。(ULを拾っている) var destEl = Dom.get(id); //Drag and Dropされたオブジェクト var destDD = DDM.getDDById(id); //this.getElで取れるのは、移動元のelement //移動元のエレメントをDropされたElementの最後の子要素にする。 destEl.appendChild(this.getEl()); destDD.isEmpty = false; //DDの座標のリセット(Interaction情報のクリア) DDM.refreshCache(); } } }, // Drag中の処理。 onDrag: function(e) { // y軸方向の移動量 var y = Event.getPageY(e); if (y < this.lastY) { // goingUpはプロパティーとして定義されていることに注意 this.goingUp = true; } else if (y > this.lastY) { this.goingUp = false; } // lastYもプロパティーとして定義されていることに注意 this.lastY = y; }, // (注)idは、DragOverされた要素のid // DragOverされたら、挿入してしまう。 onDragOver: function(e, id) { // ドラッグされた元要素のelementの取得 var srcEl = this.getEl(); // ドラッグオーバーされた要素のelementの取得 var destEl = Dom.get(id); // li要素にドラッグオーバーされたら、以下の処理。 if (destEl.nodeName.toLowerCase() == "li") { var orig_p = srcEl.parentNode; var p = destEl.parentNode; // このDDListのインスタンスが上を向いて動いていれば、前に挿入 // goingUpは、onDragで計ってある。 if (this.goingUp) { p.insertBefore(srcEl, destEl); // insert above // そうでなければ、後に挿入 } else { p.insertBefore(srcEl, destEl.nextSibling); // insert below } //DDの座標のリセット(Interaction情報のクリア) DDM.refreshCache(); } } }); Event.onDOMReady(YAHOO.example.DDApp.init, YAHOO.example.DDApp, true); </script> </HEAD> <BODY> <div class="workarea"> <div class="div1"> <h3>List1</h3> <ul id="ul1" class="draglist"> <li class="list1" id="li1_1">list 1, item 1</li> <li class="list1" id="li1_2">list 1, item 2</li> <div class="div2"> <h3>List2</h3> <ul id="ul2" class="draglist"> <li class="list2" id="li2_1">list 2, item 1</li> <li class="list2" id="li2_2">list 2, item 2</li> <li class="list2" id="li2_3">list 2, item 3</li> </ul> </div> <li class="list1" id="li1_3">list 1, item 3</li> </ul> </div> <div class="div1"> <h3>List3</h3> <ul id="ul3" class="draglist"> <li class="list3" id="li3_1">list 3, item 1</li> <li class="list3" id="li3_2">list 3, item 2</li> <li class="list3" id="li3_3">list 3, item 3</li> </ul> </div> </div> <div id="user_actions"> <input type="button" id="showButton" value="現在の順番" /> </div> </BODY> </HTML>