QUILL(javascript / WYSIWYG / htmlエディター)のメモ

WYSIWYGのQUILL(htmlエディター)ってのを使う

作成日:2022-02-08, 更新日:2024-02-26

基本

  • 公式: https://quilljs.com/
  • ツールチップにマウスオーバーしても何も表示されない(ツールチップを見て、何ができるのかが分からない人には厳しい)
  • 日本語化は無し

テーマ

  • Snow: テキストボックスの上部にアイコンが並ぶ。オーソドックスなツールバー形式
  • Bubble: 装飾したい文字を選択するとツールチップが表示

追加JS

  • KaTeX: https://github.com/KaTeX/KaTeX
    →数式を表示したいときに使う
  • highlight js: https://highlightjs.org/
    →プログラムソースなどの配色関連で使う

form送信するとき

QUILLってヤツはtextareaに対しては使えない。
そのため入力された値をform送信する際は、別途渡す処理が必要

<form>
  <input type="hidden" name="quill_html"><!-- QuillでつくったHTMLを格納するための要素 -->
  <div id="editor-container"></div><!-- Quillのエディタになるトコ -->
  <button type="button" id="btn_send">送信</button>
</form>

<script>
  let wrap_quill_container = '#editor-container';
  let quill = new Quill(wrap_quill_container, {
    theme: 'snow'
  });

  $('#btn_send').on('click', function(){
    let html_val = '';
    let quill_text = quill.getText(); // いったんテキスト取得
    if ( quill_text.replace("\n", '') != '' ) { // 改行コードを消して値があるか確認
      html_val = quill.root.innerHTML; // 値があるのでHTML取得
    }
    $('input[name="quill_html"]').val(html_val); // 「input[type=hidden]」にセット
    $(this).parents('form').submit(); // form送信
  });
</script>

ツールチップに吹き出しを追加する場合

手っ取り早いのはBootstrapのtooltipsのCSS+JSの設定追加。
詳細は分からないけど・・・

  • Bootstrapの公式のような吹き出しにはなってくれなかった
  • cselectタグの一つ目を選択しづらいって問題もあった

ってことで自作するのが無難。

吹き出しを自作

最終的に気づいた・・・問題点

  • ツールチップの下に吹き出しを使いたい場合、z-indexを指定する必要アリ

希望する仕様

  • 吹き出しがウィンドウ枠外にいかないようにしたい

最終的な仕様

  • 吹き出しはツールチップの上
    ※z-indexを他で使ってたら面倒だから避けたい→ツールチップの下に表示は諦める
  • JSで左端・右端のツールチップにマウスオーバー時の吹き出し位置を設定
  • 吹き出しは一言程度しか表示させないので改行禁止にする
  • ツールチップにtitle属性に吹き出しの内容をセット

サンプルソース

▼css

.quill_tooltips {
  position: relative;
  cursor: pointer;
}
.quill_tooltips .speech_bubble {
  display: none;
  position: absolute;
  padding: 0.3rem 0.5rem;
  font-size: 0.8rem;
  color: #fff;
  border-radius: 5px;
  background: #000;
  width: auto;
  white-space: nowrap;
}
.quill_tooltips .speech_bubble:before {
  content: "";
  position: absolute;
}
.quill_tooltips .speech_bubble.spBble_tl { /* ツールチップの上・左  */
  top: -40px;
  left: 0px;
}
.quill_tooltips .speech_bubble.spBble_tl:before {
  top: 100%;
  left: 6px;
  border: 6px solid transparent;
  border-top: 8px solid #000;
}
.quill_tooltips .speech_bubble.spBble_tr { /* ツールチップの上・右  */
  top: -40px;
  right: 0px;
}
.quill_tooltips .speech_bubble.spBble_tr:before {
  top: 100%;
  right: 6px;
  border: 6px solid transparent;
  border-top: 8px solid #000;
}
.quill_tooltips:hover .speech_bubble {
  display: inline-block;
}

▼HTML+script部

  <div id="quill_toolbar">
    <span class="ql-formats">
      <select class="quill_tooltips ql-header" title="スタイル">
        <option value="2">見出し1</option>
        <option value="3">見出し2</option>
        <option value="4">見出し3</option>
        <option value="" selected="selected">標準</option>
      </select>
      <button class="quill_tooltips ql-bold" title="太字"></button>
      <button class="quill_tooltips ql-italic" title="斜体"></button>
    </span>
    ~ 省略 ~
    <span class="ql-formats">
      <button class="quill_tooltips ql-clean" title="書式をリセット"></button>
    </span>
  </div>
  <div id="quill_editor" class="editor_wrp"></div>
</div>
<script src="quill.min.js"></script>
<script>
  var quill = new Quill('#quill_editor', {
    modules: {
      toolbar: '#quill_toolbar'
    },
    theme: 'snow'
  });

  // 吹き出しの作成+位置の設定
  $(function () { // Quillの描画関連が終わるのを待つ必要あり
    $('.quill_tooltips').each(function(){
      var tagName = $(this)[0].tagName;
      if ( tagName != 'SPAN' && tagName != 'BUTTON' ) {
        return true; // selectタグはspanが追加され、マウスオーバーで使われるのはspan。
      }
      var description = $(this).attr('title');
      var pos_speech_bubble = 'tl';
      if ( description != '' ) {
        if ( $(this).position().left < 300 ) {
          pos_speech_bubble = 'tl'; // ウィンドウ左から300px未満は、ツールチップの上・左に表示
        }
        else {
          pos_speech_bubble = 'tr'; // それ以外は、ツールチップの上・右に表示
        }
        $(this).append('<span class="speech_bubble spBble_'+pos_speech_bubble+'">'+description+'</span>');
      }
    });
  });
</script>

関連項目