相談内容
画面上でタグをドラッグ&ドロップできる画面を作成しています。
knockout.jsでHTMLをループさせると、ドラッグ&ドロップが出来ません。
どのようにして解決すればいいのでしょうか?
該当のソースコード
html
1<?php 2echo $this->Html->script('knockout.js',array('inline' => false)); 3echo $this->Html->script('knockout.mapping.js',array('inline' => false)); 4echo $this->Html->css('vehicle_dispatch_schedule.css',[ 'inline' => false ]); 5echo $this->Html->script('VehicleDispatchSchedule.js',array('inline' => false)); 6echo $this->Html->script('drag_and_drop.js',[ 'inline' => false ]); 7 8?> 9 10<div> 11 <div class="placement"> 12 <table style="border: 1px solid; width: 10rem"> 13 <!-- ko foreach: carData --> 14 <tbody> 15 <tr style="height: 3rem;"> 16 <td class="driver_column droppable-place" style="border: 1px solid;"></td> 17 </tr> 18 </tbody> 19 <!-- /ko --> 20 </table> 21 <table class="outer_frame" style="width: 3rem"> 22 <tr> 23 <td class="draggable-item item" data-dandd-group="driver">佐藤<br><input class="item_input"></td> 24 </tr> 25 </table> 26 </div> 27</div>
###drag_and_drop.js
javascript
1function initializeDragAndDrop(parameters) { 2 3 // sample: http://jsfiddle.net/radonirinamaminiaina/zfnj5rv4/ 4 5 // 初期値を設定 6 parameters = Object.assign({draggableSelector: '.draggable-item', 7 droppableSelector: '.droppable-place', 8 dragOverClass: 'drop-place-focus', 9 groupData: 'dandd-group', }, 10 parameters); 11 12 13 let draggingItem = undefined; // ドラッグ中のタグ情報(未ドラッグ中ならundefined) 14 let insertFlg = true; 15 16 // ドロップ可能なグループ設定か? 17 function droppableGroup(data, place) { 18 return (! place.data(parameters.groupData) || ! data.data(parameters.groupData)) || // グループ設定なし 19 (place.data(parameters.groupData) && data.data(parameters.groupData) && place.data(parameters.groupData) === data.data(parameters.groupData)) // 同じグループ 20 ; 21 } 22 23 // ドラッグ開始 24 function dragStart(e) { 25 draggingItem = this; // ドラッグ中タグを格納 26 27 /* console.log('dragstart', this); */ 28 } 29 30 // ドラッグ終了 31 function dragEnd(e) { 32 draggingItem = undefined; // ドラッグ中タグを無効化 33 } 34 35 // ドラッグ移動中 36 function dragOver(e) { 37 e.preventDefault(); 38 39 // ドラッグ中以外は無視 40 if (draggingItem === undefined) { 41 return; 42 } 43 44 const data = $(draggingItem); 45 const place = $(this); 46 47 // マウスの当たっている箇所に応じて、マウス形状を変更する。 48 if (droppableGroup(data, place)) { 49 e.originalEvent.dataTransfer.dropEffect = "copy"; 50 } else { 51 e.originalEvent.dataTransfer.dropEffect = "none"; 52 } 53 } 54 55 // ドラッグ中にタグ内に移動した。 56 function dragEnter(e) { 57 58 // ドラッグ中以外は無視 59 if (draggingItem === undefined) { 60 return; 61 } 62 63 const data = $(draggingItem); 64 const place = $(this); 65 66 67 if (!place.is(parameters.draggableSelector) && droppableGroup(data, place)) { 68 // マウスの当たっている箇所にクラスを設定する。 69 //place.find(parameters.draggableSelector).hide(); 70 place.addClass(parameters.dragOverClass); 71 } 72 } 73 74 // ドラッグ中にタグ外に移動した。 75 function dragLeave(e) { 76 // ドラッグ中以外は無視 77 if (draggingItem === undefined) { 78 return; 79 } 80 81 const data = $(draggingItem); 82 const place = $(this); 83 84 if (!place.is(parameters.draggableSelector) && droppableGroup(data, place)) { 85 // マウスの当たっている箇所用クラスを外す。 86 //place.find(parameters.draggableSelector).show(); 87 place.removeClass(parameters.dragOverClass); 88 } 89 } 90 91 // ドロップ 92 function drop(e) { 93 e.preventDefault(); 94 95 if (draggingItem === undefined) { 96 return; 97 } 98 99 const data = $(draggingItem); 100 const place = $(this); 101 102 if (droppableGroup(data, place)) { 103 // ドラッグ中のタグをドロップ先に設定 104 105 // 元データからコピーし、イベントを追加 106 const newData = data.clone() 107 .prop('draggable', true) // ドラッグ許可 108 .on('dragstart', dragStart) // ドラッグ開始 109 .on('dragend', dragEnd) 110 .on('dragover', function() {}) 111 .on('dragenter', dragEnter) 112 .on('dragleave', dragLeave) 113 ; 114 115 116 $(this).empty().append(newData); // コピーしたタグ情報をドロップ先に追加 117 118 // ドロップ先からの移動の場合、元のタグは削除 119 if (data.parent().is(parameters.droppableSelector)) { 120 data.remove(); 121 } 122 } 123 124 // マウス形状の設定を初期化 125 e.originalEvent.dataTransfer.dropEffect = ""; 126 127 // マウスの当たっている箇所用クラスを外す。 128 $('.'+parameters.dragOverClass).removeClass(parameters.dragOverClass); 129 draggingItem = undefined; 130 } 131 132 133 $(parameters.draggableSelector) 134 .prop('draggable', true) // ドラッグ許可 135 .on('dragstart', dragStart) // ドラッグ開始 136 .on('dragend', dragEnd) // ドラッグ終了 137 .on('dragover', function() {}) // ドラッグ移動中 138 .on('dragenter', dragEnter) // ドラッグ中にタグ内に移動した。 139 .on('dragleave', dragLeave) // ドラッグ中にタグ外に移動した。 140 ; 141 142 $(parameters.droppableSelector) 143 .on('dragover', dragOver) // ドラッグ移動中 144 .on('dragenter', dragEnter) // ドラッグ中にタグ内に移動した。 145 .on('dragleave', dragLeave) // ドラッグ中にタグ外に移動した。 146 .on('drop', drop); // ドロップ 147 148}
###VehicleDispatchSchedule.js
'''javascript
$(function() {
let vehicledispatchscheduleModel = function(){ let self = this; self.carData = [a, b, c, d, e] initializeDragAndDrop({ draggableSelector: '.draggable-item', droppableSelector: '.droppable-place', dragOverClass: 'drop-place-focus', groupData: 'dandd-group', },); } ko.applyBindings(new vehicledispatchscheduleModel());
});
'''
###vehicle_dispatch_schedule.css
css
1.placement{ 2 display: flex; 3 flex-direction: row; 4} 5.driver_column{ 6 width: 16%; 7 text-align: center; 8 font-size: 96%; 9} 10.outer_frame{ 11 border: solid 1.5px; 12}
補足情報(FW/ツールのバージョンなど)
足りない情報がありましたら、コメントにお願いします。