インストール(npm)
npm install summernote
でnode_modulesに入る
レイアウトがいろいろ用意されている。
通常はrequire('summernote');
で行けるが
日本語化とレイアウトをbootstrap4ベースにしたかったけどサンプルなかった。
多分以下で行けるはず。
resources/js/bootstrap.js
require('summernote/dist/summernote-bs4.min');
require('summernote/dist/lang/summernote-ja-JP.min');
resources/js/app.scss
@import 'summernote/dist/summernote-bs4.min';
フロント側(bladeファイルとjavascript)
divタグを用意するだけ。textareaタグでもよい。
edit.blade.php
<div id="summernote"></div>
<textarea id="summernote" class="form-control" name="description"></textarea>
edit.js
$(document).ready(function()
{
$('#summernote').summernote({
lang: 'ja-JP',
height: 300,
});
})
画像挿入時のサーバ転送
デフォルトはimgタグにbase64エンコードされたデータとして挿入されます。
独自のサーバにアップロードしてそのURLをimgタグに挿入する方法も用意されている。
$('#summernote').summernote({
...略...
callbacks: {
onImageUpload: (files) => {
/* ローカルファイルを選んだあと呼ばれるのでサーバーへアップする */
insertImageFile(files[0]);
},
onMediaDelete: (target) => {
/* 画像を削除するを選んだ時呼ばれるのでサーバーへ削除要求する */
removeImageFile(target[0].src);
},
},
...略...
function insertImageFile(file)
{
let formData = new FormData();
formData.append('file', file);
fetch('/insert-image-file', formData,...)
.then((response) => {
if (response.ok) {
// サーバ側で応答に画像のurlを付与する
let imgNode = document.createElement('img');
imgNode.src = response.url;
$('#summernote').summernote('insertNode', imgNode);
}
});
}
function removeImageFile(src)
{
/* 削除のアクションを呼ぶ */
let formData = new FormData();
formData.append('src', src);
fetch('/remove-image-file', formdata, ...)
.then((response) => {
if (response.ok) {
}
}
}
サーバ側(laravel/php)ではinsert-image-fileとremove-image-fileに対応する
アクションを用意する。
app/Http/Controller/TestController.php
public function insertImageFile(Request $request)
{
/* ファイル名をuuidに変換 */
$uuid = (string) Str::uuid();
$ext = $request->file('file')->extension();
$file = $uuid . '.' . $ext;
$imgpath = $request->file('file')->storeAs('attachments', $file, 'public');
$url = Storage::disk('public')->url($imgpath);
return response()->json(['result' => 'OK', 'url' => $url]);
}
public function removeImageFile(Request $request)
{
/* storageまでのパスを取得 */
$url = Storage::disk('public')->url('');
/* 画像のパス(URL)からサーバ内のローカルパスに変換 */
$delete_file = str_replace($url, '', $request->src);
$resp = Storage::disk('public')->delete($delete_file);
return response()->json(['result' => 'OK']);
}
フォームのsubmitアクション
HTMLエディタの入力欄に対応するinputタグがないので
submitのクリックイベントを引っ掛けて隠し属性のinputを追加してsumbmitする
buttonタグにname="submit"があるとformのsubmitが効かないので削除する。
追記(2020/12/15)
普通にtextareaタグにid設定すればsummernoteのレイアウトになるっぽいので
以下の処理は必要ない。
$("#submit_button").click((e) => {
/* 一旦submitを無効 */
e.preventDefault();
let description = $('#summernote').summernote('code');
let edit_form = document.getElementById('edit_form');
if (edit_form != null) {
inputDescription = document.createElement("input");
inputDescription.type = 'hidden';
inputDescription.name = 'description';
inputDescription.value = description;
edit_form.appendChild(inputDescription);
edit_form.submit();
}
});