作成日:2025年06月09日
FileMakerでDrag&Dropを実現する


どうも、にゃん太です
先日、FileMakerでもDrag&Dropで操作したいという要望がありました
そうした操作へは対応してこなかったので、この機会に少し調べてみたいと思います
今回のメモでは、FileMakerで実行可能なDrag&Dropについて書いていきます
テキストのDrag&Drop
FileMakerは、テキストのDrag&Dropに対応しています
選択した内容を別のフィールドへドロップすると、内容が複製して登録されます
この時、テキストフィールド以外では、上書きされてしまいます
テキストフィールドは指定の場所へ差し込みを行います
この処理で注意したい点が2つあります
一つは、「取り消し」ができない事です
テキストフィールドであれば、ドロップされた情報を破棄すれば復元は可能です
しかし、それ以外のフィールドでは値が上書きされてしまい、元の情報に戻す事ができません
もう一つは、強制保存される点です
「レコードの変更を自動的に保存する」のチェックを外しておいた場合でも、自動的にドロップされた結果が保存されいます
これは、同一レコードの場合は「保存しない」で元に戻す事ができます
しかし、別のレコードや別のアプリケーションなどからドロップした場合は何故か保存されてしまい、メッセージも表示されません
個人的には誤操作が怖いので、ドラッグ&ドロップの許可を外す事を推奨しています

これでも外部からのドロップは禁止できませんが、誤操作リスクは大きく下がると思います
オブジェクトのDrag&Drop
項目を分けましたが、基本的にはテキストのDrag&Dropと同じです
異なるフィールドへオブジェクトを複製する事ができます
違う点としては、オブジェクトフィールド以外へのドロップが行えない点があります
テキストのDrag&Dropの場合は、ドロップされた後に入力規則のチェックによりエラーメッセージが表示されましたが、オブジェクトの場合はドロップ自体を受け付けません
他には、「選択テキストのドラッグ&ドロップを許可する」のチェックを外していてもDrag&Dropを実行できる点です
この機能は、写真データの取り込みを行う場合や、外部ファイルのインポートを行う場合に便利に使用できます
他にも、例えばこちらのサイトの様に工夫すれば、色々な事ができそうです
Webビューアを使用したDrag&Drop
FileMakerで実行できる基本的なDrag&Dropを説明してきましたが、複雑な処理を行おうと思うと、色々と機能面で不足する事があります
そんな時は、Webビューアを使用してJavascriptで実現する方法もあります
今回は、基本的なやり方を説明していきます
オブジェクトを移動できる様にする
まずはオブジェクトを移動させてみましょう
HTMLに配置したオブジェクトは、基本的には動かせません
HTML
<!DOCTYPE html> <html lang='ja'> <head> <meta charset='UTF-8'> <meta http-equiv='content-language' content='ja'> <meta name='viewport' content='width=device-width, initial-scale=1.0, user-scalable=1'> </head> <body> <div id='dragBox'> <div id='dragObject' class='obj'></div> </div> </body> </html>
動かすにはその為のスクリプトを記述する必要があります
方法は色々ありますが、クリックイベントを基軸に考えてみましょう
- オブジェクトの上でマウスを押したらしたらドラッグ開始
- マウスを移動したらオブジェクトが追随する
- マウスを上げたらオブジェクトのドラッグを終了
単純ですが、こんな動きを作成してみましょう
Javascript
const obj = document.getElementById('dragObject'); var drag = false; var position = { x: null, y: null }; obj.addEventListener('mousedown', function(e){ drag = true; position.x = e.clientX; position.y = e.clientY; }); obj.addEventListener('mousemove', function(e){ if(drag){ obj.style.top = parseInt(window.getComputedStyle(obj).top) + e.clientY - position.y + 'px'; obj.style.left = parseInt(window.getComputedStyle(obj).left) + e.clientX - position.x + 'px'; position.x = e.clientX; position.y = e.clientY; } }); obj.addEventListener('mouseup', function(e){ drag = false; position = { x: null, y: null }; });
枠外に出た場合などのエラー処理は出来ていませんが、オブジェクトのドラッグは出来る様になりました
とはいえ、こんな風に動かすだけの処理を作る事はあまりないでしょう
もう少し、実用性のありそうな動きを考えてみましょう
- オブジェクトが1~5まで存在する
- 特定の位置にドロップする事ができる
- ドロップしたらオブジェクトの番号を通知する
どうでしょうか
これなら、応用次第で実用的な処理になりそうです
もう少し、動作を詰めてみましょう
- オブジェクトが1~5をドラッグできる
- マウスを上げたらドロップ処理は終了
- マウスを上げた位置が特定のオブジェクトの範囲内なら移動終了
- 範囲外の場合は元の位置に戻す
- 別のオブジェクトが移動されてきたら、前のオブジェクトは元の位置に戻す
そのまま使える処理ではなさそうですが、応用は出来そうです
この処理を作成してみましょう
Javascript
const basePosition = [ {x:5, y:5}, {x:65, y:5}, {x:125, y:5}, {x:185, y:5}, {x:245, y:5}, ]; var drag = [false, false, false, false, false]; var position = { x: null, y: null }; const targetBox = document.getElementById('target'); const targetPosition = { xs: targetBox.offsetLeft, xe: targetBox.offsetLeft + targetBox.offsetWidth, ys: targetBox.offsetTop, ye: targetBox.offsetTop + targetBox.offsetHeight, }; const objs = document.getElementsByClassName('obj'); for(let i = 0; i < objs.length; i++){ objs[i].style.top = basePosition[i].y + 'px'; objs[i].style.left = basePosition[i].x + 'px'; objs[i].addEventListener('mousedown', function(e){ drag[i] = true; position.x = e.clientX; position.y = e.clientY; objs[i].style.zIndex = 10; }); objs[i].addEventListener('mousemove', function(e){ if(drag[i]){ objs[i].style.top = parseInt(objs[i].style.top) + e.clientY - position.y + 'px'; objs[i].style.left = parseInt(objs[i].style.left) + e.clientX - position.x + 'px'; position.x = e.clientX; position.y = e.clientY; } }); objs[i].addEventListener('mouseup', function(e){ let x = e.clientX; let y = e.clientY; if(x >= targetPosition.xs && x <= targetPosition.xe && y >= targetPosition.ys && y <= targetPosition.ye){ for(let j = 0; j < objs.length; j++){ objs[j].style.top = basePosition[j].y + 'px'; objs[j].style.left = basePosition[j].x + 'px'; } objs[i].style.top = targetPosition.ys + 2 + 'px'; objs[i].style.left = targetPosition.xs + 2 + 'px'; alert('オブジェクト' + i + 'をセットしました'); }else{ objs[i].style.top = basePosition[i].y + 'px'; objs[i].style.left = basePosition[i].x + 'px'; } drag[i] = false; position = { x: null, y: null }; objs[i].style.zIndex = 2; }); };
色々半端な造りではありますが、概ね望む挙動となっているかと思います
これをベースに応用すれば、色々な処理が作成できそうです
draggable属性を使用する
先ほどとは別の方法として、draggable属性を使用する方法があります
ドロップ先の制御などはこちらの方が簡単に出来ます
以下の条件で処理を作成してみましょう
- オブジェクトが1~5まで存在する
- ドロップ先も1~5まで存在する
- 対応する番号の場所にドロップする必要がある
動作テストスクリプト
const basePosition = [ {x:5, y:5}, {x:65, y:5}, {x:125, y:5}, {x:185, y:5}, {x:245, y:5}, ]; const endPosition = [ {x:185, y:5}, {x:65, y:5}, {x:245, y:5}, {x:5, y:5}, {x:125, y:5}, ]; const objs = document.getElementsByClassName('obj'); const targets = document.getElementsByClassName('target'); for(let i = 0; i < objs.length; i++){ objs[i].style.top = basePosition[i].y + 'px'; objs[i].style.left = basePosition[i].x + 'px'; objs[i].draggable = true; objs[i].addEventListener("dragstart", function(e){ e.dataTransfer.setData("id", event.currentTarget.id); }); targets[i].style.bottom = endPosition[i].y + 'px'; targets[i].style.left = endPosition[i].x + 'px'; targets[i].addEventListener("dragover", function(){ event.preventDefault(); }); targets[i].addEventListener("drop", function(e){ let dropTarget = e.currentTarget.id.slice(-1); let dragTarget = e.dataTransfer.getData("id").slice(-1); if(dropTarget == dragTarget){ objs[dragTarget].style.bottom = endPosition[dragTarget].y + 2 + 'px'; objs[dragTarget].style.left = endPosition[dragTarget].x + 2 + 'px'; objs[dragTarget].style.top = 'auto'; } }); };
※objectタグで上手く埋め込めなかったので、ここだけリンクになります
以上で今回のメモ書きは終了です
FileMakerに組み込むところまでは書きませんでしたが、Webビューアを使用したDrag&Drop処理の基礎はこれで分かると思います
また機会があれば、もっと実用的な使い方を書いてみます

以上で今日のメモ書きは終了です
内容はいかがでしたか?
もしご意見やご要望、誤りの指摘などありましたら、下記フォームよりお気軽にご連絡ください