読者です 読者をやめる 読者になる 読者になる

ふっちーのやんのかやんねーのかブログ

ITの技術的なこともそうでないことも。

【Javascript】jQueryのプラグインを作成する

こんにちわ。ふっちーです。

Javasriptを使っていると、近年においてもjQueryの利用に行き着く方が多いのではないかと思う。

よりjQueryを楽しむため「jQueryプラグインを作成する」方法について、実際にプラグインを作成しながらあらためてまとめてみる。

新しい関数のプロパティを追加する

はじめに、jQuery.fnオブジェクトに新しい関数のプロパティを追加する。 追加したプロパティ名がプラグインの名前となる。

// 即時関数で囲む
;(function( $ ) {
    // 新しい関数のプロパティを追加する
    $.fn.myPlugin = function( ) {

        // プラグインのコードはここに作成する
    
    };
})( jQuery );

1. 即時関数で囲む

JavaScriptは関数スコープであるため、スコープを限定する際は関数で囲む必要がある。 即時関数で囲まれた内部で定義された変数はローカル変数となり、外部のグローバルな変数を上書きして汚染することが無いため、安全に変数定義を行うことができる。

jQueryプラグインを作成するにあたり、他のプラグインでも利用されているドルマークが衝突しないよう、即時関数の引数にjQueryを渡し、$という変数に格納しこれを利用する。

2. jQueryプラグインの関数を定義する

即時関数内で「$.fn.関数名」とプロパティを定義することで、jQueryプラグインの関数として認識される。 ここで定義した関数名がプラグイン名となる。

プラグインの機能を作成する

関数のプロパティ内にプラグインの機能を作成する。 今回は、対象の要素群の高さを、最大の高さに合わせるプラグインを作成してみる。

;(function( $ ) {
    $.fn.flatHeight = function() {
        // height() を使って対象の要素群の最大の高さを取得する
        var maxHeight = 0;
        this.each(function() {
            maxHeight = Math.max( maxHeight, $( this ).height() );
        });

        // 要素群に取得した高さを設定する
        this.css( "height" , maxHeight );

        // thisを返す
        return this;
    };
})( jQuery );

// div要素群に作成したプラグインを適用する
$( "div" ).flatHeight();

1. コンテキスト

対象となるDOM要素のプロパティを利用したい場合はthisから取得する。

プラグインの関数のスコープが有効な範囲内では、thisは呼び出されたプラグインjQueryオブジェクトを参照しているため、jQuery関数でのラッピングは不要となる。

2.メソッドチェーンを持続させる

jQueryプラグインは上記のサンプルのように、いくつかの方法で要素の集合をシンプルに書き換えていくというものが多い。

プラグインにおいてメソッドチェーンを持続させるために、プラグインはthisを返し、続いている次のメソッドに対象の要素群を引き渡すようにしておく必要がある。

作成したプラグインを利用する

実際にdiv要素が3つ横に並ぶページを作成し、ここまでで作成したプラグインを適用させてみる。

<html>

<head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>

    <style type="text/css">
    div {
        float: left;
        background-color: gray;
        padding: 5px;
        margin: 5px;
    }
    </style>
</head>

<body>
    <div>
        DIV1<br />
    </div>

    <div>
        DIV2<br />
        DIV2<br />
    </div>
    
    <div>
        DIV3<br />
        DIV3<br />
        DIV3<br />
    </div>

    <script type="text/javascript">
        ;(function( $ ) {
            $.fn.flatHeight = function() {
                // height() を使って対象の要素群の最大の高さを取得する
                var maxHeight = 0;
                this.each(function() {
                    maxHeight = Math.max( maxHeight, $( this ).height() );
                });

                // 要素群に取得した高さを設定する
                this.css( "height", maxHeight );

                // thisを返す
                return this;
            };
        })( jQuery );

        $( "div" ).flatHeight();
    </script>
</body>

</html>

Before

f:id:fuchinoue_j:20160228133856p:plain

After

f:id:fuchinoue_j:20160228133524p:plain

なんということでしょう。

デフォルトとオプション

次に、オプションを受け取り、プラグインの動作を変更させる構成を用意する。 これは、プラグインが呼び出された時に拡張可能なデフォルトのセッティングを持っておくとよい。 デフォルトのオプションによる拡張は$.extendを利用する。

それでは、先ほど作ったプラグインに、最小の高さを設定できるオプションを用意してみよう。

;(function( $ ) {
    $.fn.flatHeight = function( options ) {
        // 渡された任意のオプションで拡張されるデフォルトを作成する
        var settings = $.extend( {
          'min-height'         : 0 // 最小の高さのデフォルトを設定した
        }, options);

       // height() を使って対象の要素群の最大の高さを取得する
        var maxHeight = settings['min-height']; // 最小の高さ設定を適用させるように拡張した
        this.each(function() {
            maxHeight = Math.max( maxHeight, $( this ).height() );
        });

        // 要素群に取得した高さを設定する
        this.css( "height", maxHeight );

        // thisを返す
        return this;
    };
})( jQuery );

オプションを指定した呼び出しは以下のとおりとなる。

$( 'div' ).flatHeight({
    'min-height' : 100 // 最小の高さのオプションを設定した
});

After

f:id:fuchinoue_j:20160228222407p:plain

プラグインメソッド

プラグインを作成する際、1つのプラグインjQuery.fnオブジェクトに対して複数のネームスペースを作成する状況を作ってはいけない。

プラグイン内で複数メソッドをもたせる場合、オブジェクトリテラルプラグインメソッド全てを集約し、利用するプラグインメソッドの文字列を渡すことで呼び出す必要がある。

では、例として先ほど作ったプラグインに、対象の要素群の表示・非表示を行うメソッドを追加してみる。

;(function( $ ) {
    var settings = {
        'min-height': 0 // 最小の高さのデフォルトを設定した
    }

    var methods = {
        init : function( options ) {
            // 渡された任意のオプションで拡張されるデフォルトを作成する
            settings = $.extend( settings, options );

           // height() を使って対象の要素群の最大の高さを取得する
            var maxHeight = settings['min-height']; // 最小の高さ設定を適用させるように拡張した
            this.each(function() {
                maxHeight = Math.max( maxHeight, $( this ).height() );
            });

            // 要素群に取得した高さを設定する
            this.css( "height", maxHeight );

            // thisを返す
            return this;
        },
        show : function () {
            this.show();

            return this;
        },
        hide : function () {
            this.hide();

            return this;
        },
        html : function (content) {
            this.html(content);

            return this;

        }
    };

    $.fn.flatHeight = function( method ) {
        // メソッド呼び出し部分
        if ( methods[method] ) {
            // 呼び出すメソッドを指定した場合
            return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            // 引数がオブジェクトである場合、また、呼び出すメソッドを指定しない場合
            // init() を呼び出す
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.flatHeight' );
        }
    };
})( jQuery );

// 初期化メソッドの呼び出し
$('div').flatHeight();

// オプションを設定した初期化メソッドの呼び出し
$('div').flatHeight({
    "min-height":100
});
// hideメソッドの呼び出し
$('div').flatHeight("hide");
// htmlメソッドの(引数を渡す)呼び出し
$('div').flatHeight("html", "TEST");

一般的なアーキテクチャとなるが、全てのメソッドプラグインの親クロージャカプセル化し、渡された最初の文字列によってメソッドを呼び出す形式を取る。メソッドがパラメータを必要とする場合、追加のパラメータを渡すことができるようになっている。

最後に

不足も多いと思うが、以上がjQueryプラグインを作成する基本的な構成となる。

jQueryの処理をプラグイン化することで、構造をコンパクトにし、コードの再利用とメンテナンスをシンプルにしてくれると思う。 プラグインの作成を躊躇している方は、是非プラグインの作成を行いjQueryを楽しんでいただきたい。