teratail header banner
teratail header banner
質問するログイン新規登録

質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.30%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

334閲覧

SortableJS で「クローン」と「入れ子」の同時利用

munekun

総合スコア117

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2024/09/29 07:27

0

1

実現したいこと

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'と同じにしつつ、親子間の移動でクローンしたくないのです。
良い方法が思い浮かぶ方がいらっしゃいましたらよろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

逆転の発想で、一致した条件のときのみクローンを作成するのではなく、条件が一致しないにも関わらずクローンが作成されたとき削除するのはどうでしょう?

javascript

1onEnd: evt => { 2 if(evt.to.className != "right"){ 3 evt.clone.remove() 4 } 5}

投稿2024/10/01 09:23

FoxRefire

総合スコア148

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

munekun

2024/10/01 10:22

たびたびありがとうございます。しばらくご回答がつかず半ば諦めていた問題でしたのでめっちゃ嬉しいです。助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問