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

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

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

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

1回答

486閲覧

ドラッグでの並び替えをJSで実現させたいが、なぜか"drag"イベントが無視される。

ypp

総合スコア66

JavaScript

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

0クリップ

投稿2023/02/07 08:50

編集2023/02/07 09:11

https://codepen.io/ypppp/pen/poZGmmp

html

1dropindex: <span id="output2">0</span>,&nbsp;status: <span id="output3">idle</span> 2<div class="main"> 3 <!-- Element.prototype.after用 --> 4 <div class="dummy"></div> 5 <div class="row"> 6 <div class="bars" draggable="true"><div></div></div> 7 <img src="https://www.gravatar.com/avatar/4a597f2aa8f7a369cdfb6422b4efef03?d=identicon"> 8 <a href="javascript:void(0)">Tarou</a> 9 </div> 10 <div class="row"> 11 <div class="bars" draggable="true"><div></div></div> 12 <img src="https://www.gravatar.com/avatar/151269ed16a2dd18e9a3ecfcdfe76fc9?d=identicon"> 13 <a href="javascript:void(0)">Tanaka</a> 14 </div> 15 <div class="row"> 16 <div class="bars" draggable="true"><div></div></div> 17 <img src="https://www.gravatar.com/avatar/fec6c2f9cee65487e83664e88a1d87a9?d=identicon"> 18 <a href="javascript:void(0)">Ishiyama</a> 19 </div> 20 <div class="row"> 21 <div class="bars" draggable="true"><div></div></div> 22 <img src="https://www.gravatar.com/avatar/dfddacc86e582d2ba88d64b69141fc7b?d=identicon"> 23 <a href="javascript:void(0)">Watanabe</a> 24 </div> 25 <div class="row"> 26 <div class="bars" draggable="true"><div></div></div> 27 <img src="https://www.gravatar.com/avatar/6ba569cf685f7e79518e27f73ed2c611?d=identicon"> 28 <a href="javascript:void(0)">Aragaki</a> 29 </div> 30 <div class="row"> 31 <div class="bars" draggable="true"><div></div></div> 32 <img src="https://www.gravatar.com/avatar/26843d78eb4ba532d14069affdb88a20?d=identicon"> 33 <a href="javascript:void(0)">Fujiwara</a> 34 </div> 35 <div class="row"> 36 <div class="bars" draggable="true"><div></div></div> 37 <img src="https://www.gravatar.com/avatar/5ab508b9384dc3bcfa1d4741fd6879ca?d=identicon"> 38 <a href="javascript:void(0)">Satou</a> 39 </div> 40 <div class="dropimage"></div> 41</div>

css

1body { 2 user-select: none; 3 overflow-y: hidden; 4} 5.main { 6 border: black 1px solid; 7 width: 300px; 8 padding: 5px 10px; 9 display: flex; 10 flex-direction: column; 11 overflow-y: hidden; 12 position: relative; 13} 14.dummy { 15 display: none; 16} 17.row { 18 display: flex; 19 align-items: center; 20 gap: 10px; 21 width: calc(100% - 22px); 22 height: 30px; 23 background-color: white; 24 padding: 5px 0; 25} 26.row > * { 27 height: 30px; 28} 29.bars { 30 width: 30px; 31 cursor: s-resize; 32 display: flex; 33 align-items: center; 34 justify-content: center; 35} 36.bars > div { 37 fill: black; 38 background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48cGF0aCBkPSJNMCA5NkMwIDc4LjMgMTQuMyA2NCAzMiA2NEg0MTZjMTcuNyAwIDMyIDE0LjMgMzIgMzJzLTE0LjMgMzItMzIgMzJIMzJDMTQuMyAxMjggMCAxMTMuNyAwIDk2ek0wIDI1NmMwLTE3LjcgMTQuMy0zMiAzMi0zMkg0MTZjMTcuNyAwIDMyIDE0LjMgMzIgMzJzLTE0LjMgMzItMzIgMzJIMzJjLTE3LjcgMC0zMi0xNC4zLTMyLTMyek00NDggNDE2YzAgMTcuNy0xNC4zIDMyLTMyIDMySDMyYy0xNy43IDAtMzItMTQuMy0zMi0zMnMxNC4zLTMyIDMyLTMySDQxNmMxNy43IDAgMzIgMTQuMyAzMiAzMnoiLz48L3N2Zz4="); 39 background-repeat: no-repeat; 40 width: 15px; 41 height: 15px; 42} 43.row img { 44 width: 30px; 45 pointer-events: none; 46} 47.row a { 48 text-decoration: none; 49 color: #c000f5; 50} 51.row a:hover { 52 text-decoration: underline; 53} 54.dragging { 55 position: absolute; 56} 57 58.dropimage { 59 width: calc(100% - 7px); 60 height: 37px; 61 border: 2px dashed grey; 62 display: none; 63 z-index: 99; 64} 65.dropimage-show { 66 display: block; 67}

js

1(() => { 2HTMLCollection.prototype.forEach = function(fn) { 3 Array.prototype.forEach.call(this, fn); 4} 5 6let main, users, height, top, clientY, dropindex, drop, bars; 7window.addEventListener("DOMContentLoaded", e => { 8 main = document.getElementsByClassName("main")[0]; 9 // すべての横目 10 users = document.getElementsByClassName("row"); 11 // 項目の一つの高さ 12 height = users[0].getBoundingClientRect().height; 13 // 画面上からの高さ 14 top = users[0].getBoundingClientRect().top; 15 clientY = main.getBoundingClientRect().top; 16 // ドロップ先に出るイメージ要素 17 drop = document.getElementsByClassName("dropimage")[0]; 18 19 // ハンバーガーボタン 20 bars = document.getElementsByClassName("bars"); 21 bars.forEach((value, index) => { 22 value.setAttribute("data-index", index); 23 24 value.addEventListener("dragstart", dragstart); 25 value.addEventListener("drag", dragging); 26 value.addEventListener("dragend", dragend); 27 }) 28}); 29 30function dragstart(e) { 31 // ハンバーガーボタンを非表示にする 32 e.target.style.opacity = 0; 33 34 // position: absolute追加 [[原因はおそらくここ]] 35 e.target.parentElement.classList.add("dragging"); 36 37 // デバッグ用 38 console.clear(); 39 document.getElementById("output3").innerText = "dragstart"; 40 console.log("dragstart"); 41} 42 43function dragging(e) { 44 // バグ?対策 45 if(e.clientY == 0) return; 46 47 // ハンバーガーボタンを表示する 48 e.target.style.opacity = null; 49 50 // ドラッグを視覚的にわかりやすくするため 51 e.target.parentElement.style.top = (e.clientY - top - 10) + "px"; 52 53 // カーソルの座標からドロップ先のインデックスを計算 54 dropindex = Math.floor((e.clientY - clientY) / height); 55 56 // 範囲外対策 57 if(dropindex < 0) dropindex = 0; 58 if(dropindex >= users.length - 1) dropindex = users.length - 1; 59 60 // ドラッグしている自身の要素を無視する 61 if(dropindex >= Number(e.target.getAttribute("data-index"))) dropindex++; 62 // ドロップ先に出る要素の位置を変更する 63 document.querySelectorAll(".dummy, .row")[dropindex].after(drop); 64 65 // ドロップ先に出る要素表示 66 drop.classList.add("dropimage-show"); 67 68 // デバッグ用 69 document.getElementById("output2").innerText = dropindex; 70 document.getElementById("output3").innerText = "dragging"; 71 console.log("dragging"); 72} 73 74function dragend(e) { 75 // ハンバーガーボタンを表示 76 e.target.style.opacity = null; 77 e.target.parentElement.style.top = null; 78 79 // position: absolute削除 80 e.target.parentElement.classList.remove("dragging"); 81 82 // 実際にドラックした要素をドロップ先に移動する 83 document.querySelectorAll(".dummy, .row")[dropindex].after(e.target.parentElement); 84 85 // インデックスを振りなおす 86 bars.forEach((value, index) => { 87 value.setAttribute("data-index", index); 88 }); 89 90 // ドロップ先に出るイメージ要素を非表示にする 91 drop.classList.remove("dropimage-show"); 92 // ドロップ先に出るイメージ要素を一番下に移動する 93 main.children[main.children.length - 1].after(drop); 94 95 // デバッグ用 96 document.getElementById("output3").innerText = "dragend"; 97 console.log("dragend"); 98} 99})();

イメージ説明
上記はハンバーガーボタンをドラッグアンドドロップで要素の並び替えを可能にしたものです。
一番上はドラッグアンドドロップで実際に移動できますが、
イメージ説明
2番目以降(※たまに動作するときがあります)は移動しようとしてもドラッグの途中で強制的に"dragend"イベントが発行されます。
イメージ説明
いろいろ考えてみましたが、2番目以降もイベントの登録はされており、なぜ"drag"イベントが無視され、"dragend"イベントが強制的に発行されるかの理由がわかりません。
どなたか原因がわかる方はいらっしゃいますか?

補足:

css

1.dragging { 2 position: absolute; 3}

をコメントアウトすると"drag"イベントは無視されなくなります。おそらく、座標が関係しているものだと思いますが、具体的な解決方法が思い浮かびません。

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

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

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

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

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

guest

回答1

0

ベストアンサー

css

1.dragging { 2 position: absolute; 3}

こちらのクラスを付与した際に、topが定義されていないので、マウス位置とのズレが生じ、ドラッグが終了しています。

一例ですが、

javascript

1e.target.parentElement.style.top = (e.clientY - top - 10) + "px"; 2e.target.parentElement.classList.add("dragging");

このように事前にtopの値を設定してやることで、正常にドラッグできるようになります。

投稿2023/02/07 23:27

macaron_xxx

総合スコア3191

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

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

ypp

2023/02/08 13:17 編集

topを指定してみましたが、今度は一番下の要素だけドラックできません。。。
macaron_xxx

2023/02/08 23:25

一番下の要素をドラッグした時にmainの高さが一時的に要素が一つ抜けた状態となるために、こちらもドラッグ位置から外れてしまいます。 `main`の高さを定義してしまうか、`.dropimage-show`を先に表示してしまうなどの対策が必要です。
ypp

2023/02/11 07:33

返信が遅くなりすいません。 >> `main`の高さを定義してしまうか、`.dropimage-show`を先に表示してしまうなどの対策が必要です。 の二つとも追加してみましたが、改善されません。 デバッグしたところ、mainの高さは291px、ドラッグ要素のy座標は280px、とmainを下回っているのにもかかわらず動かせない状態です。 https://codepen.io/ypppp/pen/poZGmmp
macaron_xxx

2023/02/12 23:01

どちらも入れてしまうとだめです。 doropimage-showの表示を元に戻すと正常に動くかと思います。
ypp

2023/02/15 15:17

返信が遅くなりすいません。 dropimage-showを削除すると想定通り動きました。本当にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.44%

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

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

質問する

関連した質問