gotin blog

Whatever gotin wanna write

Date.prototype.setMonthの私にとってややこしいこと

選択日curDateの日にちを1日に設定してから指定されたdateの月,年に設定し,カレンダテーブルを再生成しています。最初に日にちを1日に設定しているのは,日にちによっては意図した月と異なる月になってしまう可能性があるためです。たとえば1月31日を表すDateオブジェクトに対し setMonth(1)を実行する(Dateオブジェクトは1月を0として扱うため,1は2月を表す)と,2月31日ではなく,3月3日に変更されます。このようにDateオブジェクトは存在しない日時を示さないように適切に処理する機能があるのですが,カレンダの生成処理では指定した月に応じたカレンダを表示したいので,このような月のジャンプが起こらないようにしたいわけです。そのため日にちを先に1日するようにしています。

Greasemonkeyによるアプリケーション開発:第3回 Greasemonkeyによるカレンダアプリケーションの機能向上|gihyo.jp … 技術評論社

↑これってあまりにも安直な対策。しかもユーザビリティ悪い。1/31のときに一月先に移動したら、2/1ではなく(ましてや3/3でもなく)2/28(閏年なら2/29)になってほしいのが普通だと思われます。

ちゃんとした対処をするべきだと思ったんですが、説明が面倒になるかと思ってあのようにしてました。
対処するなら↓こんな感じでしょうか。

Date.prototype.addMonth = function (offset) {
  var oldDate = this.getDate();
  this.setMonth(this.getMonth() + offset);
  if (Date.limitMode && 
     oldDate != this.getDate()){
   this.addDate(-this.getDate());
  }
  return this;
};

Date.prototype.addDate = function (offset) {
  this.setDate(this.getDate() + offset);
  return this;
};

こんな↑感じのものでも書いておけば、

  Date.limitMode = true;
  alert(new Date(2007, 1-1, 31).addMonth(1));   // 2007/1/31 + 一月 #limitMode
  // 結果:Wed Feb 28 2007 00:00:00 GMT+0900 (JST)  (2007/2/28)

  Date.limitMode = false;
  alert(new Date(2007, 1-1, 31).addMonth(1));   // 2007/1/31 + 一月 #normalMode
  // 結果:Sat Mar 03 2007 00:00:00 GMT+0900 (JST)   (2007/3/3)

ってな感じに。
あいかわらずクロスブラウザを試す余力がなく、Firefox2.0.0.6 on Macでしか試してません^^;

画面を一時的に消す

//けす
Array.prototype.forEach.call(document.body.childNodes, function(e){if(e.style)e.style.visibility="hidden";});
//もどす
Array.prototype.forEach.call(document.body.childNodes, function(e){if(e.style)e.style.visibility="visible";});

とすれば、消してから何かを表示、表示を終えたらもどす、というようなことができると思ったんですが、それだともともとhiddenにしていたものまでvisibleにしてしまうことになってしまいます。

で代わりに考えたのが↓これ

var toggleView = (function(){
  var tmp = document.createElement("div");
  function toggle(){
    tmp.firstChild ? show():hide();
    function hide(){
      while(document.body.firstChild){
        tmp.appendChild(document.body.firstChild);
      }
    }
    function show(){
      while(tmp.firstChild){
        document.body.appendChild(tmp.firstChild);
      }
    }
  }
  return toggle;
})();

toggleView()の呼び出しで消す、もどすを繰り返せるようになります。もとのvisibilityもキープできて便利。
いやいや、

document.body.style.visibility="hidden"

でいいじゃん、って思うところですが、それだと消したあとに「別の何か」を表示できなくなってしまうのでダメなのです。
で、なんでこんなことをしてるかというと、
スライドショーのようにテキストを読むGreasemonkeyスクリプト、YHC
↑これがとてもすばらしいんですが、なぜか私の環境だとスライドショー中に元のページ要素がチラっと一部だけ顔をのぞかせたりすることがあったので、元の要素を一旦消してしまえばこのチラツキも消えるだろうと考えたからなのです。
結果、うまくチラツキが消えるようになりました。
このチラツキ現象は gmacsでプレゼンテーション でも発生していたので、ずっと直したかったのですが、ようやっと直せることとなりました。
以上、ページ内に未挿入のElementを使うと一時的にどかす処理ができるんだ、という発見でした。