久々のエントリーです。
最近はまったく忙しくて、全然勉強する時間もありゃしません。
弊社の人が作ったJavaScriptでトグル処理をするソースコードがメールで流れてきて それに触発されて、自分もいろいろ書いてみて、社内でシェアしたものをうpします。
まるごとJavaScriptを見ていて、クロージャっていいよね。という気分だったので クロージャをおさらいしてみました。 トグル処理の様々な実装方法テスト in JavaScript
最終的なソースコードはこんな感じになったよ。
- /**
- * オブジェクトを継承する(Objectを汚染拡張 from prototype.js)
- * @param destination 拡張されるオブジェクト
- * @param source 雛形オブジェクト
- */
- Object.mixin = function( destination, source ){
- for (property in source)
- destination[property] = source[property];
- return destination;
- }
- /**
- * トグル可能な要素を表すクラス
- */
- var TogglableElement = function(){};
- TogglableElement.prototype = {
- flag:true,
- resultTarget:undefined,
- toggle:function(){
- this.flag = !this.flag;
- },
- update:function(){
- this.resultTarget.innerHTML = ( this.flag ) ? 'ON' : 'OFF';
- },
- onmouseup:function(){
- this.toggle();
- this.update();
- }
- };
- /**
- * 初期化
- * イベントハンドラはHTML内ではなく、スクリプト内で定義
- */
- function init(){
- /* オブジェクト拡張方式 */
- var btn1 = document.getElementById('btn1');
- var btn2 = document.getElementById('btn2');
- // ボタン要素をトグラブルオブジェクトに拡張する
- Object.mixin( btn1, TogglableElement.prototype );
- Object.mixin( btn2, TogglableElement.prototype );
- // 出力先を定義する
- btn1.resultTarget = document.getElementById('result1');
- btn2.resultTarget = document.getElementById('result2');
- /* クロージャ渡し方式 */
- document.getElementById('btn3').onmouseup = getToggleClosure( document.getElementById('result3') );
- document.getElementById('btn4').onmouseup = getToggleClosure( document.getElementById('result4') );
- /* ソースコードの表示トグル */
- document.getElementById('viewsource-a').onclick = getToggleClosure2( document.getElementById('sourcecode-a'), viewSourceCode );
- document.getElementById('viewsource-b').onclick = getToggleClosure2( document.getElementById('sourcecode-b'), viewSourceCode );
- document.getElementById('viewsource-c').onclick = getToggleClosure2( document.getElementById('sourcecode-c'), viewSourceCode );
- }
- /**
- * トグル処理&DOM操作のクロージャ関数を返す
- * 1つの関数を各所で使い回せるようにクロージャ化する
- * @param target HTMLElement 内容を書き換えるHTML要素
- */
- function getToggleClosure( target ){
- var flag = true; // フラグ。レキシカルスコープ内に保持
- var target = target; // ターゲット。レキシカルスコープ内に保持
- return function(){
- flag = !flag; // フラグを逆転
- target.innerHTML = ( flag ) ? 'ON' : 'OFF'; // flag==trueならON
- };
- }
- function getToggleClosure2( target, callback ){
- var flag = true;
- var target = target;
- var callback = callback
- return function(){
- flag = !flag; // フラグを逆転
- callback.apply( this, [ target, flag ] );
- };
- }
- function viewSourceCode( target, flag ){
- this.innerHTML = ( flag )? 'ソースコードを表示する' : 'ソースコードを隠す';
- target.style.display = ( flag )? 'none' : 'block';
- }
- /**
- * window.onloadにリスナーを貼る
- */
- if( /msie/.test(navigator.userAgent.toLowerCase()) )
- window.attachEvent( 'onload', init );
- else
- window.addEventListener( 'load', init, true );