条件付メソッドチェーン実現のためjQueryのラッパーを作ってみた
発端
条件付メソッドチェーンを実現するjQuery pluginを作ってみた - 文殊堂の今後の課題を実現したい
今回作ったもの
testという名前のメソッドを呼ぶとそれ以降、
jQueryオブジェクトをラップしたオブジェクトによって
メソッドチェーンが繋がっていく。
jQueryオブジェクトを返さないメソッドを実行した場合には、
ラップしないで元のメソッドの戻り値を返す。
コード
(function($){ function JQWrapper(jQueryObj){ this._jQueryObj = jQueryObj; } for(var i in $.fn){ if(!$.isFunction($.fn[i]) || i == 'test')continue; (function(i){ JQWrapper.prototype[i] = function(){ console.log('methodName:'+i); console.log(arguments); console.log(this._jQueryObj.get()); var result = $.fn[i].apply(this._jQueryObj,arguments); if(result instanceof $){ return new JQWrapper(result); }else{ return result; } }; })(i); } $.extend( $.fn ,{ 'test':function(cond){ return new JQWrapper(this); } }); })(jQuery);
Firebug consoleから実行するの限定。
jQueryオブジェクトのメソッドを呼ぶと以下をconsoleに出力します。
- メソッド名
- メソッドが呼び出された際の引数
- そのメソッドが呼び出された(ラップされたjQueryオブジェクト)が保持するDOM要素
試してみる
サンプルコード
$('<div/>') .test() .append('<span>hogehoge</span>') .append('<span>fugafuga</span>') .append('<span>piyopiyo</span>') .append('<span/>') .html()
実行結果
methodName:append ["<span>hogehoge</span>"] [div] methodName:append ["<span>fugafuga</span>"] [div] methodName:append ["<span>piyopiyo</span>"] [div] methodName:append ["<span/>"] [div] methodName:html [] [div] "<span>hogehoge</span><span>fugafuga</span><span>piyopiyo</span><span></span>"
サンプルコード
$('<div/>') .test() .wrap('<div/>') .wrap('<div/>') .parent() .text('hogehoge') .attr('id','fuga') .parent() .html()
実行結果
methodName:wrap ["<div/>"] [div] methodName:wrap ["<div/>"] [div] methodName:parent [] [div] methodName:text ["hogehoge"] [div] methodName:attr ["id", "fuga"] [div] methodName:parent [] [div#fuga] methodName:html [] [div] "<div id="fuga">hogehoge</div>"
それで今後どうするか?
jQueryオブジェクトではなくラッパーオブジェクトで
メソッドチェーンさせているので、
jQueryオブジェクトを汚染させずに状態を持たせることが出来る。
これと、今回試した処理の横取りを使って、
$(someCSSSelector) .If(someCond) .append('<span>hogehoge</span>') .append('<span>hogehoge</span>') .append('<span>hogehoge</span>') .ElseIf(otherCond) .append('<span>fugafuga</span>') .wrap('<div/>') .parent() .text('hogehoge') .attr('id','fuga') .Else() .empty() .EndIf()
↑こんな感じのコードにぱっと見騙されたとおりの動きをさせたい。