はじめに
ちょっとお仕事で必要が生じて、異なるiframe間でドラッグ&ドロップでデータをやり取りする機能を実装することになったので、その検証メモ。
今回は、Laravelを使って組んでいく。
なお、実行環境は以下だが、構築の詳細は割愛。
- VirtualBox 7.1.0
- AlmaLinux 9.4
- PHP 8.3.22
下準備
まずはLaravelのプロジェクトを作る。
cd /var/www/html composer create-project laravel/laravel:11.* sample07 chmod -R a+w sample07/storage/ chmod a+w sample07/bootstrap/cache
お仕事がLaravel 11なので、バージョンとしてLaravel 11系を指定しているが、最新のLaravel 12系でも問題なく動くと思う。
ファイルの作成・編集
sample07/resources/views/sample/index.blade.php
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <base href="/sample07/public/" /> <title>親ページ</title> <link rel="stylesheet" type="text/css" href="sample.css" /> <script type="text/javascript" src="sample.js"></script> </head> <body> <h1>親ページ</h1> <iframe width="100%" height="300" src="sample/frame1"></iframe> <iframe width="100%" height="300" src="sample/frame2"></iframe> </body> </html>
sample07/resources/views/sample/frame1.blade.php
ドラッグ元。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <base href="/sample07/public/" /> <title>ドラッグ元</title> <link rel="stylesheet" type="text/css" href="sample.css" /> <script type="text/javascript" src="sample.js"></script> </head> <body> <h1>ドラッグ元</h1> <table> <thead> <tr> <th>商品番号</th> <th>商品名</th> </tr> </thead> <tbody> <tr data-id="A12345" class="draggable" draggable="true"> <td>A12345</td> <td>こしひかり</td> </tr> <tr data-id="B67890" class="draggable" draggable="true"> <td>B67890</td> <td>あきたこまち</td> </tr> <tr data-id="C54321" class="draggable" draggable="true"> <td>C54321</td> <td>ゆめぴりか</td> </tr> </tbody> </table> <script type="text/javascript"> initDrag(); </script> </body> </html>
sample07/resources/views/sample/frame2.blade.php
ドロップ先。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <base href="/sample07/public/" /> <title>ドロップ先</title> <link rel="stylesheet" type="text/css" href="sample.css" /> <script type="text/javascript" src="sample.js"></script> </head> <body> <h1>ドロップ先</h1> <div id="dropzone" class="dropzone">ドロップターゲット</div> <script type="text/javascript"> initDrop(); </script> </body> </html>
sample07/app/Http/Controllers/SampleController.php
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class SampleController extends Controller { public function index() { return view('sample.index'); } public function frame1() { return view('sample.frame1'); } public function frame2() { return view('sample.frame2'); } }
sample07/public/sample.css
table { border-collapse: collapse; outline: none; } th, td { border: 1px solid #ccc; } .draggable { cursor: grab; } .dropzone { min-height: 150px; border: 2px dashed #999; background-color: #e9e9e9; padding: 10px; } .dropzone.drag-over { background-color: #d1ffd1; border-color: green; }
sample07/public/sample.js
function initDrag() { const draggables = document.querySelectorAll(".draggable"); draggables.forEach((draggable) => { draggable.addEventListener("dragstart", (ev) => { console.log(draggable.dataset.id + ": Drag start"); // ドラッグするデータの種類と値を設定 ev.dataTransfer.setData( "text/dataIds", JSON.stringify([draggable.dataset.id]) ); // ドラッグ元の要素を一時的に非表示にする setTimeout(() => { draggable.style.opacity = "0.5"; }, 0); }); draggable.addEventListener("dragend", (ev) => { // ドラッグ終了時に元のスタイルに戻す draggable.style.opacity = "1"; }); }); } function initDrop() { const dropZone = document.querySelector("#dropzone"); dropZone.addEventListener("dragover", (ev) => { ev.preventDefault(); dropZone.classList.add("drag-over"); }); dropZone.addEventListener("dragleave", (ev) => { dropZone.classList.remove("drag-over"); }); dropZone.addEventListener("drop", (ev) => { ev.preventDefault(); const data = ev.dataTransfer.getData("text/dataIds"); const dataIds = JSON.parse(data); // ドロップ時のアクション console.log(dataIds); dropZone.classList.remove("drag-over"); }); }
今回は検証なので、ドロップ時の処理はコンソールにドラッグされた要素のIDを出力するだけ。
sample07/routes/web.php
<?php use Illuminate\Support\Facades\Route; Route::get('/', function () { return view('welcome'); }); Route::get('/sample', [\App\Http\Controllers\SampleController::class, 'index']); Route::get('/sample/frame1', [\App\Http\Controllers\SampleController::class, 'frame1']); Route::get('/sample/frame2', [\App\Http\Controllers\SampleController::class, 'frame2']);
動作確認
以下のURLにアクセスして動作確認。
http://<your-ip-address>/sample07/public/sample
ドラッグ元のテーブルの行をドラッグして、ドロップ先にドロップしたときにIDがコンソールに出力されれば完成。
参考
Geminiと会話しながら作りました。