Blog スタッフブログ

【JavaScript】Pure JavaScriptで書かれたシンプルで使いやすいモーダルプラグイン「Tingle.js」

Category | Blog
/ 27,459views

こんにちは、CTOの奥田です。

先日イチロー選手が引退されました。
小学生の頃、近所の友達とグリーンスタジアムにオリックスの試合を何度か観に行きました。
彼の素晴らしいプレーとその肩に書かれた「がんばろう神戸」の文字は私達に勇気をくれました。

いつまでも私のヒーローはイチロー選手です。
長い現役生活、本当にお疲れ様でした。

さて、今回はPure JavaScriptで書かれたシンプルなモーダルを実装できるプラグイン「Tingle.js」をご紹介致します。

Table of contents

  1. Tingle.jsとは
  2. インストール
  3. 使い方
  4. カスタマイズ方法
  5. iframeの表示
  6. フッターボタンのコールバック
  7. さいごに

Tingle.jsとは

Tingleは Pure JavaScriptで書かれたシンプルなモーダルプラグインです。
軽量かつjQueryなど他のライブラリとの依存関係は必要なく、簡単に実装できます。
以下に公式サイトに載っている説明の箇条書きを載せておきます。

  • 依存関係は必要ありません
  • CSSで完全にカスタマイズが可能です
  • CSSトランジションで動作します
  • 単純なAPI
  • ダウンロードする追加フ​​ァイルはありません
  • UXを念頭に置いて作成しています

インストール

まずはインストールしましょう。

Bower
bower install tingle --save
NPM
npm install tingle.js --save
JS
<script src="tingle.min.js"></script>

Tingle.jsはCSS, Less, Sassなど様々な方法でカスタマイズが可能です。

<link rel="stylesheet" href="tingle.min.css">

使い方

使い方は簡単です。
jQueryのプラグインほど簡単ではありませんが、拡張性が高く作られていてJSが書ける人にはこちらの方が柔軟にカスタマイズが可能かと思います。
まずは公式サイトに載っているサンプルをそのまま貼り付けてみた以下のデモを見てみてください。

tingleは new tingle.modal()でインスタンスを生成することで使用可能となります。

var modal = new tingle.modal();

以下のオプションを指定可能です。

タイプ説明
footerbooleanフッターを表示するかどうか
stickyFooterbooleanフッターを固定する場合はtrueを設定します
closeMethodsarray利用可能なcloseメソッド(オーバーレイ、ボタン、エスケープ)
onOpenfunctiontingleが開いているときに実行するコールバック(遷移終了後)
onClosefunctiontingleが閉じられたときに実行されるコールバック
beforeOpenfunctionモーダルを開く前に実行するコールバック
beforeClosefunctionモーダルを閉じる前に実行するためのコールバック(モーダルを閉じるにはtrueを返さなければなりません)
cssClassarrayTingleコンテナに追加されるカスタムCSSクラス
closeLabelstring閉じるボタンに表示されるラベル(モバイル版)

また、以下のメソッドを使用してmodalをコントロールできます。

NameDescription
open()モーダルを開きます (.tingle-enabledがbodyに追加されます)
close()モーダルを閉じ、存在する場合はコールバックを実行します
setContent(content)モーダルコンテンツを設定する
getContent()モーダルコンテンツを取得する
setFooterContent(content)フッターコンテンツを設定する
getFooterContent()フッターコンテンツを取得する
addFooterBtn(label, cssClass, callback)フッターにボタンを追加します(スタイルと配置にはcssClassを使用します)
checkOverflow()モーダルの位置を変更できるようにします(非同期コンテンツで役立ちます)
isOverflow()モーダルの高さがビューポートの高さよりも大きい場合はtrueを返します
destroy()モーダルを削除します(DOMから外してイベントをアンバインドする)

カスタマイズ方法

このままだとかなりポップな感じの印象ですがTingle.jsは簡単に見た目をカスタマイズすることができます。
以下のデモをご確認ください。

記述したスタイルは以下です。
このように意外と簡単にカスタマイズが可能です。

/**
* tingle modal modified
**/
.tingle-modal {
    padding-top: 40px;
    padding-bottom: 40px;
}
.tingle-modal-box {
    width: 850px;
    max-width: 90%;
    border-radius:0 ;
}
.tingle-modal-box__content{
    padding: 0;
}
.tingle-modal__close{
    height: 45px;
    width: 48px;
    outline:none !important;
    background-color: rgba(0,0,0,.8);
}
@media(max-width: 540px){
    .tingle-modal {
        padding: 20px 15px;
    }
    .tingle-modal-box {
        max-width: 100%;
    }
    .tingle-modal__close{
        font-size: 1.6rem;
        left: auto;
        right: 0px;
        line-height: 1.6rem;
    }
    .tingle-modal__closeIcon{
        font-size: 1.2rem;
        margin-right: 0;
    }
    .tingle-modal__closeLabel{
        display: none;
    }
}
@media(min-width: 541px){
    .tingle-modal__close{
        font-size: 1.2rem;
        top: 20px;
        right: 20px;
    }
    .tingle-modal__closeIcon{
        font-size: 1.2rem;
        margin-right: 0;
    }
}

また、要素をdisplay:noneにした要素で囲み、その中身をsetContentすることで汎用性の高いモーダルを実装することができます。

<div class="d-none">
    <div id="modal__content">
        ここにコンテンツを配置
    </div>
</div>
// data-modal属性を持つトリガーボタンを取得
var modalTrigger = document.querySelectorAll('[data-modal]');
if(modalTrigger.length > 0){
    for (let i = 0; i < modalTrigger.length; i++) {
        var el = modalTrigger[i];
        //イベントをバインド
        _addModalEvent(el);
    }
}
function _addModalEvent(el){
    el.addEventListener('click',function(event){
        event.preventDefault();
        // data-modalに指定したIDの要素を取得
        var target = el.getAttribute('data-modal');
        // モーダルのコンテンツを取得
        var modalContent = document.querySelector(target);
        if(modalContent){
            // コンテンツをセット
            modal.setContent(modalContent.innerHTML);
            // モーダルオープン
            modal.open();
        }
    })
}

iframeの表示

先程のサンプルでiframeを非表示要素として配置してしまうとURLの末尾にautoplay=1をつけている場合、表示はされていませんが動画自体が再生されてしまいます。
そんな時は動画のURLを取得してiframe要素を毎回生成してしまいましょう。

<a href="" class="btn btn-primary btn-lg" data-modal data-src="Youtube URL">modal open</a>
var modalContent = "";
// instanciate new modal
var modal = new tingle.modal({
    beforeClose: function() {
        // モダルの要素内を削除
        modal.setContent("");
        return true;
    }
});
var modalTrigger = document.querySelectorAll('[data-modal]');
if(modalTrigger.length > 0){
    for (let i = 0; i < modalTrigger.length; i++) {
        var el = modalTrigger[i];
        _addModalEvent(el);
    }
}
function _addModalEvent(el){
    el.addEventListener('click',function(event){
        // 通常のクリックイベントをキャンセル
        event.preventDefault();
        var target = el.getAttribute('data-modal');
        var src = el.getAttribute('data-src');
        if(src!=""){
            // .iframe-content要素を生成
            var iframeContent = document.createElement('div');
            iframeContent.setAttribute("class","iframe-content");
            // iframe要素を生成
            var iframe = document.createElement('iframe');
            // 必要な属性を付与する
            iframe.setAttribute("allow","autoplay; encrypted-media");
            iframe.setAttribute("allowfullscreen","");
            iframe.setAttribute("frameborder","0");
            // src属性をセット
            iframe.setAttribute("src",src);
            // .iframe-content要素に追加
            iframeContent.appendChild(iframe);

            // modalにセット
            modal.setContent(iframeContent);
            // modalをopen
            modal.open();
        }
    })
}

フッターボタンのコールバック

フッターにボタンを追加して何かイベントを実行したい場合はaddFooterBtnを使います。
また、closeMethodsを空にすることで他のボタンで閉じる動作をなくすことができます。
押すたびにどんどんボタンが増えていくのでsetFooterContent("")を忘れずに。

var modalContent = "";
// instanciate new modal
var modal = new tingle.modal({
    footer:true,
    closeMethods:[],
    beforeClose: function() {
        return true; // close the modal
    }
});
// data-modal属性を持つトリガーボタンを取得
var modalTrigger = document.querySelectorAll('[data-modal]');
if(modalTrigger.length > 0){
    for (let i = 0; i < modalTrigger.length; i++) {
        var el = modalTrigger[i];
        //イベントをバインド
        _addModalEvent(el);
    }
}
function _addModalEvent(el){
    el.addEventListener('click',function(event){
        event.preventDefault();
        // data-modalに指定したIDの要素を取得
        var target = el.getAttribute('data-modal');
        // モーダルのコンテンツを取得
        var modalContent = document.querySelector(target);
        if(modalContent){
            // コンテンツをセット
            modal.setContent("");
            modal.setContent(modalContent.innerHTML);

            modal.setFooterContent("");
            modal.addFooterBtn('閉じる', 'tingle-btn tingle-btn--primary', function() {
                if(window.confirm('モーダルを閉じます。よろしいですか?')){
                    modal.close();
                }
            });
            // モーダルオープン
            modal.open();
        }
    })
}

さいごに

今回はかなり便利なモーダルを実装可能なTingle.jsをご紹介させていただきました。
今やモーダルはCSSで実装できてしまう時代ではありますが、様々なイベントの実行などを柔軟に行うには、やはりJavaScriptの力なしではできません。
皆さんもぜひ使ってみてください。

Category | Blog
Author | Mineo Okuda / 27,459views

Company information

〒650-0024
神戸市中央区海岸通5 商船三井ビルディング4F

Contact us

WEBに関するお問い合わせは
078-977-8760 (10:00 - 18:00)