この記事を作った動機

 drag and drop の実装について毎回いちいち調べなおしている気がするので、自分用に記録を残したいと思った。

引っかかった内容

drop イベントの受け取り方

 単に、dropイベントを設定しただけでは、全く発火しない。dragoverの時点で、preventDefaultする必要があるようである。

...
    acceptDropTag(){
        // dragover で preventDefault しないことには機能しない
        this.info.addEventListener("drop",(event) => {
            this.dragedTagName = event.dataTransfer.getData("text/plain")
            if(this.dragedTagName != null){
                this.setTag(this.dragedTagName)
            }
        })

        // drop イベントが発火するようにする
        this.info.addEventListener("dragover",(event) => {
            event.preventDefault()
        })
    }
...

コンソールでは基本dataTransferの中身は見えないことがあるらしい

 dataTransferの中身は、ブラウザのコンソール内では正しく見えないようである。しかししばらくいろいろ実装を試してみたところ、すでに既存のスクリプト側でdragoverpreventDefaultして何かしらdropイベントでdataTransferについて読み出したりしている状況において、ブラウザのコンソール側から以下のようなコードを実行してみると内容を見ることができた。

document.querySelector("#videoTable > a:nth-child(5) > div.videoInfoContainer > div.tagInfo").addEventListener("drop",(event) => {console.log(event.dataTransfer.getData("text/plain"))})

// 何かしら内容が表示される。今回はタグ名として、`drive`という文字列を送るようにしていたので、以下のようにコンソールに出てきた。
// drive <- 取得したデータとしてコンソールに出力された内容

dragenterdragleave では、datatransfer の中身が見えない?

 dropイベントの発火の仕方が分からないときに、dragenterdragleaveは発火して、その中にdataTransferの項目もイベントの引数の項目に含まれていたため、dataTransferの存在を知った当初はそれを使おうとしていた。

 しかし、自分で試してみたところ、どんなにdragstartでデータを設定しても、event.dataTransfer.items[0] とか event.dataTransfer.getData("text/string") してもエラーにはならないが、空の文字列が返ってきてしまったり何も得られなかった。

document.querySelector("#videoTable > a:nth-child(4) > div.videoInfoContainer > div.tagInfo").addEventListener("dragenter",(event) => {console.log(event)})

// DragEvent {isTrusted: true, dataTransfer: DataTransfer, screenX: 2366, screenY: 676, clientX: 830, …}
// temp1 // コンソールで で "Store as global variables" をする。
temp1.dataTransfer.getData("text/plain")
''

drag and drop に関する内容

よく使うイベント一覧

  • dragstart
  • dragover
  • drop

基本的なこと

ドラッグされる側 (event はイベントをリッスンするときの引数を意味する)

  1. draggable="true"属性を何かしらの形でHTMLタグ側に設定する。
  2. dragstartイベントでドロップされた要素に渡したいデータを設定する。以下二つの選択肢がある。
    • event.dataTransfer.items.add(data,fromat) する。
    • event.dataTransfer.setData(format,data) する。

ドロップされる側 (event はイベントをリッスンするときの引数を意味する)

  1. dragoverpreventDefaultして、dropイベントが発火するようにする。
  2. dropイベントで、event.dataTransfer にアクセスしてデータを受け取る。
    • event.dataTransfer.items[indexNum]する。
    • event.dataTransfer.getData(format)する。

format 引数で指定する内容

 dataTransferでデータをセットしたり読み出すには、データが何であるかタイプを指定する必要がある。ドキュメントのサンプルコードなどを見る限り、それはMIME typeを参照して文字列として指定すればいいと思われる。

サンプルコード

ドラッグされる側

...
            tagButtonContaier.addEventListener("dragstart",(event) => {
                event.dataTransfer.setData("text/plain",tag)
            })
...

ドロップされる側

...
    acceptDropTag(){
        // dragover で preventDefault しないことには機能しない
        this.info.addEventListener("drop",(event) => {
            this.dragedTagName = event.dataTransfer.getData("text/plain")
            if(this.dragedTagName != null){
                this.setTag(this.dragedTagName)
            }
        })

        // drop イベントが発火するようにする
        this.info.addEventListener("dragover",(event) => {
            event.preventDefault()
        })
    }
...

参考にしたサイトとか