JavaScript で、フェードイン・アウトをする(新型?)

う〜〜ん、まだまだ、書き慣れないとだめだなぁ〜。

<!DOCTYPE html>
<title>Opacity Changer</title>

<body>
<h1 id="hoge">フェードイン・アウト</h1>
<section>
  <p id="fuga">
    クリックすると、フェードイン・アウトを繰り返します
  </p>
</section>

<script>

(function () { //IEはパス

  function Fade (node/*HTMLElement*/, step/*Number*/, interval/*Number*/, opacity/*Number*/) {
    this.node     = node;
    this.step     = step;
    this.interval = interval;
    this.opacity  = opacity;
    this.timerId  = null;
    this.mode     = step < 0 ? -1: 1;
  }

  //______________
  
  var
  // (非)表示
  setVisibility = function (sw/*Boolean*/) { 
    this.visibility = sw ? 'hidden': 'visible';
  },
  
  // 透明度
  setOpacity = function (alpha/*Number*/) {
    this.opacity = alpha / 100;
  },
  
  // タイマーを止める
  stop = function () {
    this.timerId && clearInterval (this.timerId);
    this.timerId = null;
    return this;
  },

  // タイマー開始
  start = function (func/*Function*/) {
    var that = this;
    this.timerId = setInterval (function () { func.call (that) }, this.interval);
  },
  
  // 増減
  fluctuation = function () {
    var alpha = this.opacity + this.step * this.mode;

    if (alpha < 0) {
      alpha = 0;
      setVisibility.call (this.node.style, false); // 0なら非表示
      stop.call (this);

    } else if (100 < alpha) {
      alpha = 100;
      stop.call (this);
    }

    this.opacity = alpha;
    setOpacity.call (this.node.style, alpha);
  },
  
  //______________
  
  // フェードイン処理
  In = function () {
    if (0 == this.mode)
      setVisibility.call (this.node.style, true);

    this.mode = 1;
    this.timerId || start.call (this, fluctuation);

    return this;
  },

  // フェードアウト処理
  Out = function () {
    this.mode = -1;
    this.timerId || start.call (this, fluctuation);
    return this;
  },

  // フェードイン・アウトのトグル処理
  Toggle = function () {
    this.mode *= -1;
    this.timerId || start.call (this, fluctuation);
    return this;
  },

  // 初期化
  init = function (node, step, interval, opacity) {
    if (!arguments.length) return null;

    var obj = new Fade (
      node,            // 対象のノード
      step     || -5,  // 変化量
      interval || 30,  // タイマーの間隔
      opacity  || 100  // 初期値の透明度
    );
    
    setVisibility.call (node.style, !!opacity);
    setOpacity.call (node.style, opacity);

    return obj;
  };
  
  

  //______________

  Fade.prototype.fadeIn     = In;
  Fade.prototype.fadeOut    = Out;
  Fade.prototype.fadeToggle = Toggle;

  Fade.init = init;

  this.Fader = Fade;

})()

// ここから手抜き
var hoge = Fader.init (document.getElementById ('hoge') );
var fuga = Fader.init (document.getElementById ('fuga') );

document.onclick = function(){ hoge.fadeToggle() };
fuga.node.onclick = function(){ fuga.fadeToggle() };


</script>