mr.jsはフロントエンド開発のためのフレームワークを提供します。モジュール化されたJSの記述、ファイル管理、必要最低限のユーティリティ機能を提供します。
世の中にはフロントエンド開発に関する様々な便利なライブラリ、フレームワークが存在しています。mr.jsはこれらwebに存在する有益なリソースの中から、webページを構築するために最低限必要な仕組みを抽出しパッケージ化しました。
1ファイル、1モジュール管理。排他的に管理されたモジュールを必要なときに簡単に読み出せる仕組みを提供
雛形モジュールを継承し、スピーディにカスタムモジュールを設計可能
工事中
ブラウザで使用できる機能をチェックする機能を提供
ua判定、テンプレート、cookie操作等、開発に必要な機能を提供
簡易メッセージ機能を搭載
非圧縮のmr.jsと圧縮されたmr.min.jsがあり、こちらが本体となります。
結合前のソースコードです。
簡単なサンプルがあります。
mr.jsはjQueryに依存しています。
- 2015.02.06 v1.0.0 リリース
mr.jsをbowerを使用してインストールします。node.js, bowerがインストールされていない場合、先にこれらをインストールしておく必要があります。
bower install git+ssh://git@git.rakuten-it.com:7999/~shinsuke.a.yamada/mr.js.githtmlに<script>を使用しmr.jsを読み込みます。mr.jsはjQueryに依存していますので、一緒に読み込む必要があります。また後述しますモジュールjsとメインjsには実際の処理内容を記述します。
<!-- mr.min.js depends on jQuery -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<!-- mr.min.js -->
<script src="bower_components/dist/mr.min.js"></script>
<!-- module js -->
<script src="js/module/module.mod01.js"></script>
<!-- main js -->
<script src="js/main.js"></script>独立した1まとまりの処理は、モジュールjsに記述します。メインjsでは各モジュールを呼び出したり、呼び出したモジュールをDOMにアサインする処理を記述します。
;(function($, $MR) {
var Mod01;
Mod01 = $MR.require('Mod01');
$(function() {
var mod01;
mod01 = $MR.applyModule('.js-click', Mod01);
});
})(window.jQuery, window.$MR);window.$MRを参照する事でmr.jsの機能にアクセスすることができます。
;(function($, $MR) {
...
})(window.jQuery, window.$MR);$MR.requireを使用してモジュールを読み込みます。引数で指定する値は、モジュールjsで定義されたものになります。
Mod01 = $MR.require('Mod01');$MR.applyModuleに対象のエレメントのセレクタと適応するモジュールを渡し、モジュールを初期化します。
mod01 = $MR.applyModule('.js-click', Mod01);モジュールjsに実際の処理内容を記述します。定義したモジュールはreturn文で返し、メインjs内で$MR.requireメソッドを使用して呼び出されます。
window.$MR.define('Mod01', function ($, $MR) {
var Utils = $MR.Utils,
Mod01;
Mod01 = Utils.extend($MR.View, {
events: {
'click .js-click': '_render'
},
_init: function() {
this._delegate();
},
_render: function() {
this.$el.text('hello!');
}
});
return Mod01;
});モジュールの定義には$MR.defineメソッドを使用します。モジュールの名前と本体のファンクションを引数として渡します。ファンクションには実行時にjQueryとmr.jsへの参照が渡されます。モジュールの名前とモジュールのファイル名には同じワードを指定する必要があります。例えばMod01としてモジュールの名前の定義する場合、そのファイル名はmodule.mod01.jsとします。モジュール名はキャメルケースで、ファイル名は全て小文字を使用してください。(ファイル名のプリフィックスは変更可能です。)
window.$MR.define('Mod01', function ($, $MR) {
...
});関数やプロトタイプ文等を使用し独自でモジュールを定義するこもできますが、mr.jsが提供するモジュールを継承する事でもモジュールを定義する事ができます。$MR.ViewにはBackbone.jsライクのメソッドが用意されており、エレメントやイベントのバインド処理が簡単に記述できる様になっています。
Mod01 = Utils.extend($MR.View, {
...
});定義したモジュールは最後にreturnで返す必要があります。
return Mod01;mr.jsが提供するモジュール管理の仕組みはとてもシンプルな物です。require.jsの様に依存関係を定義する事はできません。各モジュールファイルは次の3つのどれかを選択してください。
一番シンプルな方法です。<script>でモジュールファイルを一つずつ読み込みます。記述する際は次の順序を保証する必要があります。各モジュールjsの順序は気にする必要はありません。各モジュールは他のモジュールに依存しない形(jQuery等外部のライブラリは除く)で定義する必要があります。もしモジュール感の依存関係を定義する場合、メインjs内で定義します。
- jQuery
- mr.js
- 各モジュールjs(モジュールのロード順序は関係ない)
- メインjs
<!-- mr.min.js depends on jQuery -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<!-- mr.min.js -->
<script src="bower_components/dist/mr.min.js"></script>
<!-- module js -->
<script src="js/module/module.mod01.js"></script>
<!-- main js -->
<script src="js/main.js"></script>mr.jsを含め、メインjs、モジュールjsや、その他外部ライブラリをすべてMinifyして、1ファイルとして読み込む場合、上記別々に読み込む場合と同様の順序で定義します。
あらかじめ全てのモジュールを読み込むのではなく、必要なモジュールのみメインjs内でモジュールjsを非同期で読み込む事が可能です。jQuery, mr.js, メインjsの読み込み順は前述と同じです。モジュールjsは決められたディレクトリ・名前で格納する必要があります。
初期設定では、mr.jsが存在するディレクトリ(ベースディレクトリ)を基準に、「module/の中にmodule.%modulename%.jsという名前」のファイルを読み込むようになっています。%modulename%はモジュールを定義したときに決めた名前(を小文字に変換したもの)と一致している必要があります。ベースディレクトリ、モジュールディレクトリ、モジュールファイル名のプリフィックス(デフォルトは"module")は以下の様に変更できます。
<script>
window.$MR.Const.baseDir = 'js'; //ベースディレクトリ
window.$MR.Const.moduleDir = 'mod'; //モジュールディレクトリ
window.$MR.Const.modulePrefix = 'mod'; //モジュールファイル名のプリフィックス
</script>この記述はmr.jsの定義の後、メインjsの前に記述して下さい。
モジュールを定義する際に使用するメソッドです。このメソッドは原則「1モジュール内で1度のみ」しか使えません。第1引数にモジュールの名前を指定します(大文字から始めるとが好ましい)。第2引数にはfunctionを記述し、その中で実際のモジュールの定義を行います。当該funcitonは引数にjQueryとmr.jsへの参照を受け取る事ができます。
window.$MR.define('Mod01', function ($, $MR) {
var Mod01
...
return Mod01;
});1モジュールjs内で複数のモジュール定義をオブジェクトとして返す事も可能です。
return {
Mod01: Mod01,
Mod02: Mod02
};$MR.defineで定義されたモジュールを読み込む際に使用するメソッドです。基本的にはメインjsの中で使用します。第1引数にモジュールの名前を指定します。
var Mod01 = $MR.require('Mod01');読み込んだモジュールはnewでインスタンスを生成するか、後述する$MR.applyModuleを使用しDOMエレメントへアサインします。
new Mod01();
or
$MR.applyModule('.js-hoge', Mod01);$MR.requireは指定したモジュールが$MR空間上に存在しない場合、非同期でモジュールを読み込みます。(モジュールjsのパス、名前のルールは非同期で読み込むを参照)。非同期で読み込む場合、jQueryの$.Deferred().promise()を返します。doneメソッドにはモジュール本体が渡されますので、モジュールjsがロードされた後に処理を続行する事が可能です。
$MR.require('Mod02').done(function(Mod02) {
var mod02 = new Mod02();
});複数のモジュールjsのロードを同期したい場合は、$.whenメソッドを使用します。
$.when(
$MR.require('Mod01'),
$MR.require('Mod02'),
).done(function(Mod01, Mod02) {
var mod01 = new Mod01();
var mod02 = new Mod02();
});モジュールをDOMエレメントへアサインします。第1引数にはエレメントのセレクタ、第2引数にモジュールを指定します。モジュールに渡すoptionsがある場合、第3引数にオブジェクトの形で渡します。戻り値として生成されてインスタンスを配列の返します。またこの配列はモジュール内でinstancesプロパティとしても参照する事が可能です。
var mod01 = $MR.applyModule('.js-hoge', Mod01, {hoge: 1});
console.log(mod01); // [ インスタンスの配列 ]
console.log(mod01[0].instances); // [ インスタンスの配列 ]mr.jsが提供する雛形モジュールを継承することで、簡単に独自モジュールを定義する事ができます。継承する際には$MR.Utils.extendメソッドを使用します。
- Bone
- Model
- View
var Mod01 = $MR.Uitls.extend($MR.Bone, {
// 独自の定義
};雛形モジュールに定義されているプロパティ、メソッドは次の命名規則を採用しています。雛形モジュールを継承してモジュールを定義する際もこの命名規則を採用される事を推奨します。
インスタンス内からしか呼ばれない事を想定した内部(プライベート)プロパティ、メソッドを定義する際、「_(アンダースコア)」を接頭辞としています。
通常参照、実行される事のない事を想定し、またオーバーライドされたくない内部(プライベート)プロパティ、メソッドを定義する際、「__(アンダースコア2つ)」を接頭辞としています。
インスタンス内、外を問わず参照、実行されることを想定した外部(パブリック)プロパティ、メソッドの定義。(一部例外あり)
またjQueryオブジェクトを格納するプロパティは$hogeのように「$」を接頭辞としています。
$MR.Boneはイベントハンドリング関連のメソッドを持ったシンプルな雛形モジュールです。このモジュールを継承する事で、あらかじめ次のメソッドを持ったモジュールを定義する事ができます。
自分のメソッドのthisを自分自信で束縛するために使用する内部メソッド。例えばjQueryのonにハンドラとして登録する際に使用すると便利です。
var Mod01 = $MR.Uitls.extend($MR.Bone, {
_create: function() {
$(window).on('load', this._bind('hoge'));
},
hoge: function() {
this.value = true; //このthisは必ず自分になる。
}
});jQueryのonに似たイベントのハンドラを登録するためのメソッドです。第3引数にオブジェクトを指定することでthisを束縛できます。
module.on('eventName', callback [, target]);onで登録したハンドラを削除するためのメソッドです。
module.off('eventName', callback [, target]);onで登録されているインスタンスに対し、指定したイベントを発火させます。
module.trigger('eventName');対象となるインスタンスのイベントを監視し、発火されたとき指定のメソッドを実行します。onと似ていますがlistenToは監視するインスタンスを必ず指定する必要があります。
mod01.listenTo(mod02, 'eventName', callback);listenToで登録したイベントの監視を停止します。
mod01.stopListening(mod02, 'eventName', callback);$MR.Boneを継承したシンプルな雛形モジュールです。主にUI処理を伴わないビジネス処理用として使用する事ができます。
このモジュールが使用するデフォルトの設定が格納されているプロパティ。
_createメソッドで生成される、インスタンスの設定値を格納するプロパティ
インスタンスが生成された際に実行されるコンストラクタメソッド(内部メソッド)。インスタンス生成時の引数optionsとthis.defaultsを結合したオブジェクトをthis.settingsに格納しthis._initを実行します。特に必要がない限りこのメソッドの直接実行、またオーバーライドの必要はありません。
_create: function(options) {
this.settings = $.extend({}, this.defaults, options);
this._init();
}モジュールの初期処理メソッド(内部メソッド)。インスタンスが生成された後実行されます。デフォルトではブランクのfunctionが定義されています。自由にオーバーライドする事が可能です。
$MR.Boneを継承したUI処理を行うことに特化した雛形モジュールです。DOMエレメントの操作をする際に便利なメソッドが定義されています。このモジュールを継承して独自にUI処理を定義することができます。
このモジュールが使用するデフォルトの設定が格納されているプロパティ。
this._createメソッドで生成される、インスタンスの設定値を格納するプロパティ
インスタンスが対象とするDOMエレメントを格納するプロパティ。this._createメソッドで設定されます。
this.elをjQueryオブジェクト化したものを格納するプロパティ。this._createメソッドで設定されます。
this.elとその子要素へのイベント監視をまとめて定義するためのプロパティ。定義した内容はthis._delegateメソッドを実行する事で登録されます。オブジェクトの形で定義し、key値にイベント名、そのイベントが発火したときのハンドラとして、value値に自分のメソッドをそれぞれ文字列で定義します。
events: {
'click': '_handler'
}複数のイベントに対して共通のハンドラを定義することもできます。
events: {
'click mouseener': '_handler'
}また、this.elの子要素へのイベント監視は、key値にイベント名と一緒にそのセレクタを定義します。このように子要素に対する登録は内部的にjQueryのdelegateメソッドに渡されるため、まだ存在しない要素に対するイベント監視も登録する事が可能です。
events: {
'click .hoge': '_handler'
}インスタンスが生成された際に実行されるコンストラクタメソッド(内部メソッド)。インスタンス生成時の引数optionsとthis.defaultsを結合したオブジェクトをthis.settingsに格納します。またthis.elにはアサインされた対象のDOMエレメントを、this.$elにはそのjQueryオブジェクトを格納し、最後にthis._initを実行します。特に必要がない限りこのメソッドの直接実行、またオーバーライドの必要はありません。
_create: function(options) {
this.el = options.el;
this.$el = $(this.el);
this.settings = $.extend({}, this.defaults, options, this.$el.data('options'));
this._init();
}モジュールの初期処理メソッド(内部メソッド)。インスタンスが生成された後実行されます。デフォルトではブランクのfunctionが定義されています。自由にオーバーライドする事が可能です。
this.$メソッドの結果をキャッシュするために内部的に呼ばれる、this.settings.cacheを生成するためのメソッド。通常意図的に呼ぶ必要はありません。
this._delegate, this._undelegate内部で呼ばれるイベント登録/解除メソッド
this.eventsで定義されたイベント監視パターンを登録し、監視を開始します。また第1引数にイベントを定義したオブジェクトを指定する事で、this.events以外の定義を登録することが可能です。さらに第2引数にthisに束縛したいインスタンスを指定する事ができます。
this._delegate({
'click': '_handler'
}, mod02);this._delegateで登録したイベントを解除するためのメソッド。
this.$el.findへのショートカット。this.$el内のエレメントを参照します。
var $hoge = this.$('.hoge');一度参照したエレメントはthis.settings.cashe.$にキャッシュされます。2回目に同じセレクタで参照した場合はキャッシュを参照します。キャッシュをクリアしたい場合は、第2引数にtrueを指定します。
this.$('.hoge'); // DOMツリーを捜査
this.$('.hoge'); // キャッシュを参照
this.$('.hoge', true) // キャッシュをクリアDOMツリーを捜査した結果、エレメントが見つからなかった場合はnullを返します。
if (!this.$('.hoge')) {
// エレメントが存在しない場合
}工事中
$MR.Featureを参照する事で、目的の機能がブラウザで使用可能かどうかを確認することができます。現在確認できる機能は以下の通りです。
タッチ機能が使用できる場合はtrue、できない場合はfalseが格納されます。
if ($MR.Feature.Touch) {
// タッチ機能が使用できる場合
}FormData APIが使用できる場合はtrue、できない場合はfalseが格納されます。
if ($MR.Feature.FormData) {
// FormData APIが使用できる場合
}XHRUploadが使用できる場合はtrue、できない場合はfalseが格納されます。
if ($MR.Feature.XHRUpload) {
// XHRUploadが使用できる場合
}$MR.Utilsにはモジュールを実装する際等に便利なユーティリティ機能がまとめられています。
window.navigator.userAgentから分かるブラウザ名が格納されているプロパティ。ブラウザ名のパターンは以下の通り。
- android (Android 標準ブラウザ)
- android2 (Android 2.x系 標準ブラウザ)
- iso (iPhone, iPad, iPod Mobile Safari)
- ie (IE)
- other(その他)
if ($MR.Utils.ua === 'ios') {
// iPhone, iPad, iPod Mobile Safari
}プリフィックス付きのtransitionendイベント名が格納されています。
console.log($MR.Utils.transitionend) //Webkit系の場合、webkitTransitionEnd
### - animationend
プリフィックス付きのanimationendイベント名が格納されています。
```javascript
console.log($MR.Utils.animationend) //Webkit系の場合、webkitAnimationEnd
### - hasCookie
第1引数に指定した名前のクッキーが存在するかを調べるためのメソッド。
```javascript
$MR.Utils.hasCookie('cookieName' [,options]);指定したクッキーが存在する場合true、しない場合falseを返します。
if ($MR.Utils.hasCookie('hoge')) {
// クッキーhogeが存在する
}第2引数にoptionsを指定する事で2次元クッキーの存在確認が可能です。
// クッキーhogeの値が"foo=1:bar=2"の場合
if ($MR.Utils.hasCookie('hoge:foo', {delimiter: ':'})) {
// クッキーhogeの中にfooが存在する場合
}第1引数に指定した名前のクッキーの値を取得するためのメソッド。
$MR.Utils.getCookie('cookieName' [,options]);hogeという名前のクッキーを取得する場合。
var hoge = $MR.Utils.getCookie('hoge');第2引数にoptionsを指定する事で2次元クッキーの値を取得可能です。
var hogeFoo = $MR.Utils.getCookie('hoge:foo', {delimiter: ':'});第1引数に指定した名前のクッキーの値をセットするためのメソッド。
$MR.Utils.setCookie('cookieName', value [,options]);hogeという名前のクッキーに値をセットする場合。
$MR.Utils.setCookie('hoge', 100);第2引数にoptionsを指定する事で2次元クッキーの値をセットすることも可能です。
$MR.Utils.setCookie('hoge:foo', 100, {delimiter: ':'});第1引数に指定した名前のクッキーの値を削除するためのメソッド。
$MR.Utils.deleteCookie('cookieName');第1引数に指定したキーのlocalStorageの値を取得するためのメソッド。
$MR.Utils.getStorageItem('key');オブジェクトを実行結果として返します。値の取得に失敗した場合、errorプロパティにtrueがセットされます。成功した場合はdataプロパティに取得した値がセットされます。
var result = $MR.Utils.getStorageItem('key');
console.log(result); // {error: false, data: 'hoge'} -> 成功!第1引数に指定したキーのlocalStorageに、第2引数に渡された値をセットするためのメソッド。
$MR.Utils.setStorageItem('key', value);オブジェクトを実行結果として返します。値のセットに失敗した場合、errorプロパティにtrueが、成功した場合はfalseがセットされます。
var result = $MR.Utils.setStorageItem('key', 'foo');
console.log(result); // {error: false} -> 成功!ユニークなIDを返すメソッド。第1引数に文字列を与えると、文字列+IDを返します。
var id1 = $MR.Utils.uniqueId();
var id2 = $MR.Utils.uniqueId('a');
console.log(id1); // 0
console.log(id2); // a1あるモジュールを継承したモジュールを定義するためのメソッド。
Mod01 = $MR.Utils.extend(継承モジュール, モジュール定義);コンストラクタを定義したい場合は、_createメソッドに定義します。
Mod01 = $MR.Utils.extend($MR.Bone, {
_create: function:function() {
...
}
...
});テンプレートエンジン。第1引数にテンプレート、第2引数にデータオブジェクトを指定します。
var template = $MR.Utils.template(tmpl, data);テンプレート内では、$でjQueryを参照する事で来ます。また__dで第2引数に指定したデータオブジェクトを参照できます。
<div class="<%= name %>">
<p><%= value %></p>
<% $.each(__d.arr, function() { %>
<span>this</span>
<% }); %>
</div>複数のオブジェクトを要素に持つ配列内から、特定のオブジェクトが存在するindexと値が格納されたオブジェクトを返すメソッド。
var array = [
{type: 'a', value: 10},
{type: 'b', value: 11},
{type: 'c', value: 12},
{type: 'a', value: 13}
],
search1 = {type: 'a'},
search2 = {type: 'd'};
var ret1 = $MR.Utils.where(array, search1);
var ret2 = $MR.Utils.where(array, search2);第1引数に指定した配列の中に、第2引数で指定したオブジェクトが存在するかを調べ、indexesとvaluesをメンバに持つオブジェクトを返します。
indexes、valuesはそれぞれ配列になっており、結果が複数見つかった場合は、その全てが格納されます。見つからなかった場合nullを返します。
ret1 -> {
indexes: [0, 3],
values: [{type: 'a', value: 10}, {type: 'a', value: 13}]
}
ret2 -> nullある目的のために必要な設定値、メソッドが定義された部品。モジュールはそのままでは使用できず、実際にはモジュールから生成されたインスタンスを使用する。1つのモジュールから複数のインスタンスを生成する事が可能。
モジュールを元に生成された実体。インスタンスはモジュールで定義されたプロパティ、メソッドを持ち、基本的に同じモジュールから生成されたインスタンス動詞でも、そのプロパティ、メソッドはそれぞれ別空間に存在するため干渉し合わない。
モジュールからインスタンスを生成する際に実行される、モジュールがもつ特別なメソッド
インスタンスが持つ変数
インスタンスが持つ関数
あるモジュールを元に別のモジュールを定義すること。
This project is created on 2015-02-04 using generator-rff v0.6.0.