実現したいこと
JavaScript の SortableJS を利用しています。要素をドラッグ&ドロップで移動させるライブラリです。
これを利用し、同一リスト内は単純なドラッグ&ドロップでの移動を実現しつつ、異なるリスト間をクローンで移動させたいと思っています。ただしリストは入れ子構造です。
発生している問題
「クローン」と「入れ子」の同時利用ができません。
マニュアル
[クローン] https://sortablejs.github.io/Sortable/#cloning
[入れ子] https://sortablejs.github.io/Sortable/#nested
該当のソースコード
マニュアルに従い「クローン」と「入れ子」を以下のように実装しました。
クローンは .left
と .right
間の移動時のみとしたいのですが、「入れ子」における親と子の移動時にまでクローンされてしまう状況です。
例えば、salmon 1 を salmon 3 内に移動させるときまでクローンされてしまうということです。
https://jsfiddle.net/1g2w5enm/
html
1<head> 2 <script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.14.0/Sortable.min.js"></script> 3 <style> 4 .row { 5 display: flex; 6 } 7 8 .item { 9 padding: 5px 10px; 10 border: 1px solid gray; 11 } 12 13 .item.turquoise { 14 background-color: turquoise; 15 } 16 17 .item.salmon { 18 background-color: salmon; 19 } 20 </style> 21</head> 22 23<body> 24 <p>salmon 1 を salmon 3 内に移動させるときまでクローンされてしまう<br> 25 (クローンは .left と .right 間の移動時のみとしたい)</p> 26 27 <div class="row"> 28 <div class="left"> 29 <div class="item salmon">salmon 1</div> 30 <div class="item salmon">salmon 2</div> 31 <div class="item salmon">salmon 3 32 <div class="left"> 33 <div class="item salmon">salmon 3-1</div> 34 <div class="item salmon">salmon 3-2</div> 35 </div> 36 </div> 37 </div> 38 <div class="right"> 39 <div class="item turquoise">turquoise 1 40 <div class="right"> 41 <div class="item turquoise">turquoise 1-1</div> 42 <div class="item turquoise">turquoise 1-2</div> 43 </div> 44 </div> 45 <div class="item turquoise">turquoise 2</div> 46 <div class="item turquoise">turquoise 3</div> 47 </div> 48 </div> 49 <script> 50 const allLleftElement = document.querySelectorAll('.left'); 51 const allRightElement = document.querySelectorAll('.right'); 52 53 for (var i = 0; i < allLleftElement.length; i++) { 54 new Sortable(allLleftElement[i], { 55 group: { 56 name: 'shared', 57 pull: 'clone' 58 } 59 }); 60 } 61 62 for (var i = 0; i < allRightElement.length; i++) { 63 new Sortable(allRightElement[i], { 64 group: { 65 name: 'shared', 66 pull: 'clone' 67 } 68 }); 69 } 70 </script> 71</body>
試したこと
おそらく「クローンするか否か」に際し、「.left
か.right
か」だけでなく「親か子か」までもがその根拠になってしまっているのだと思われます。
するとpull: 'clone'
オプションを使う限り回避できないのではと思い、さらにオプションを漁って別方向で実装しようと試みました。
オプション一覧
https://github.com/SortableJS/Sortable?tab=readme-ov-file#options
クローン生成を上記のようなpull: 'clone'
オプションに頼らず自前で.appendChild()
し、.onAdd
オプションのときに「.left
か.right
か」を見るという方法で、下記clone ()
関数にまとめました。
JavaScript
1 const allLleftElement = document.querySelectorAll('.left'); 2 const allRightElement = document.querySelectorAll('.right'); 3 4 const clone = (evt) => { 5 const fromList = evt.from; 6 const toList = evt.to; 7 8 if ( 9 (fromList.classList.contains('left') && toList.classList.contains('right')) || 10 (fromList.classList.contains('right') && toList.classList.contains('left')) 11 ) { 12 const clone = evt.item.cloneNode(true); 13 fromList.appendChild(clone); 14 } 15 } 16 17 for (var i = 0; i < allLleftElement.length; i++) { 18 new Sortable(allLleftElement[i], { 19 group: { 20 name: 'shared', 21 pull: true, 22 put: true 23 }, 24 onAdd: (evt) => { 25 clone(evt); 26 }, 27 }); 28 } 29 30 for (var i = 0; i < allRightElement.length; i++) { 31 new Sortable(allRightElement[i], { 32 group: { 33 name: 'shared', 34 pull: true, 35 put: true 36 }, 37 onAdd: (evt) => { 38 clone(evt); 39 }, 40 }); 41 }
実現できたといえばできたのですが、クローンのタイミングがpull: 'clone'
と違って最後になってしまい使いにくさを感じます。(最後になってしまうのを避けたければonMove
で、などいろいろ試行錯誤中ですが、私ごときの腕ではうまく実装できません。)
クローンの方式はpull: 'clone'
と同じにしつつ、親子間の移動でクローンしたくないのです。
良い方法が思い浮かぶ方がいらっしゃいましたらよろしくお願い致します。

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2024/10/01 10:22