勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

summernoteにギャラリーから画像を挿入する機能を追加する方法

summernoteの画像機能はデフォルトだと「画像ファイルを選ぶ」「URLから画像を挿入する」の2つになるが、WordPressのようにアップロード済みの画像をギャラリー表示し、ギャラリーから画像を選択することで画像挿入可能な機能を新たに追加したい。以下にサンプルと実装方法をメモ。

 

summernoteについて

summernote自体の使用方法については過去記事参照。

 

サンプル

https://taitan916.info/sample/summernote/gallery/

 

実装方法

WYSIWYGエディタ側(index.php)

<style>
.gallery_img{
    cursor: pointer;
    max-width: 22%;
    padding: 5px;
    margin: 2px;

    img{
        width: 100%;
        border: 1px solid #ccc;
        padding: 3px;
        border-radius: 3px;
    }

    img.choice{
        border: 1px solid #000;
    }
}
.gallery_area{
    display: flex;
    flex-wrap: wrap;
    overflow: auto;
    height: 200px;
}
</style>

<form action="./" method="post">
    <div>
        <label>
            <input type="radio" value="on" name="switching" checked>On
        </label>
        <label>
            <input type="radio" value="off" name="switching">Off
        </label>
    </div>
    <textarea name="editor" id="editor"></textarea><br>
    <input type="submit" value="送信">
</form>

<script type="text/javascript" src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-lite.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.20/dist/summernote-lite.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.20/lang/summernote-ja-JP.min.js" type="text/javascript"></script>

<script>
$(function(){
    const selector = '#editor';

    //summernoteの開始
    startSummernote(selector);

    //summernoteのOn / Off切り替え
    $('input[name="switching"]').on('change', function(){
        if( $(this).val() == 'on' ){

            //summernoteの開始
            startSummernote(selector);
        }else{

            //空の場合はsummernote側で<p><br></p>が挿入されるので削除
            if( $(selector).summernote('code') == '<p><br></p>' ){
                $(selector).val('');
            }

            //summernoteの破棄
            $(selector).summernote('destroy');
        }
    });

    $(document).on(`click`, `.gallery_img`, function(){
        $(`.gallery_img img`).removeClass(`choice`);
        $(this).find(`img`).addClass(`choice`);

        $(`.note-group-image-url .note-input`).val($(this).data(`url`));

        $(`.note-image-btn`).attr(`disabled`, false)
    });

    //summernoteの開始用関数
    function startSummernote( selector ){
        if( !selector ) return false;


        //オプション設定
        const summernote_option = {
            lang: 'ja-JP',
            height: 300,
            focus: true,
            callbacks: {
                onDialogShown: function(dialog){

                    if( $(`.note-modal.open`).attr(`aria-label`) ){
                        $.ajax({
                            url: `./img_list.php?t=${$.now()}`,
                            method: `GET`,
                        })
                        .done(function( result ){
                            const list = JSON.parse(result);
                            if( list.length ){

                                $(`.note-group-gallery-url`).remove();

                                let list_html = '';
                                $.each(list, function(key, val) {
                                    list_html += `
                                        <div class="gallery_img" data-url="${val}">
                                            <img src="${val}">
                                        </div>
                                    `;
                                });

                                const html = `
                                    <div class="form-group note-group-gallery-url" style="margin-top: 20px;">
                                        <label for="note-dialog-gallery" class="note-form-label">ギャラリーから画像を挿入する</label>
                                        <div class="gallery_area">
                                            ${list_html}
                                        </div>
                                    </div>
                                `;
                                $(`.note-modal.open`).find('.note-modal-body').append(html);

                            }
                        });
                    }
                }
            }
        }

        $(selector)
            //オプションを指定して初期化
            .summernote(summernote_option)

            //エンタークリック時に<br>タグを挿入
            .on('summernote.enter',
                function(we, e){
                    $(this).summernote('pasteHTML', '<br>&ZeroWidthSpace;');
                    e.preventDefault();
                }
            );
    }

});
</script>

ギャラリー用の画像検索(img_list.php)

<?php
$pattern = './img/*.*';
$list = [];
foreach ( glob( $pattern ) as $file ){
    $list[] = str_replace('./img/', 'https://test.com/img/', $file);
}
echo json_encode($list);

注意点等

画像が多い場合は読み込みに時間がかかると思われるので、WordPressのように「さらに読み込む」的な機能を追加した方がよさそう。

 

所感

少々力業な実装方法かもしれないがやりたかったことはできた。過去にメモした画像のアップロードと組み合わせて使っていけそう。

 - jQuery JavaScript

  関連記事

jQueryで画像(<img>タグ内)のsrc情報を取得する場合
jQueryで画像(タグ内)のsrc情報を取得する場合

すぐに出てこなかったのでメモ。 $('#test').attr('src'); ...

jQueryで画像を遅延ロードする「jquery.lazyload.js」の利用方法
jQueryで画像を遅延ロードする「jquery.lazyload.js」の利用方法

画像を遅延ロードさせたい時にはjQueryプラグインのlazyloadが便利。以 ...

javascriptやjQueryで画像を書き換えても変わらない場合
javascriptやjQueryで画像を書き換えても変わらない場合

けっこう前に画像をアップロードしてリアルタイムにプレビューする機能を作った時に、 ...

Ajaxでプラグイン無しのファイルアップロード方法
Ajaxでプラグイン無しのファイルアップロード方法

画像ファイルを添付できて、尚且つAjaxを用いた非同期通信のフォームを作りたかっ ...

画像アップロード前の時点で画像が選択されているか確認
画像アップロード前の時点で画像が選択されているか確認

やりたかった事は、フォーム内で画像をアップロードする際、 ちゃんと画像がローカル ...