jQueryUIのdatepickerを使ってハマった所 その1

jQueryUIのdatePickerは簡単に日付選択のライブラリを設置できて便利なんですが、デザインをいじるのがめちゃくちゃ大変です。
今回はそんな話。

★カレンダーの表示幅を広げたい(特に複数月のカレンダーを出しているとき)

これが難解・・・。まだ初期表示はbeforeShow()でこんな感じに書けば出来ます。

例)表示幅を38emにしたい場合。

$("#calendar").datepicker({

  beforeShow: function(input,inst){

    setTimeout(function(){
      $(input).datepicker("widget").attr("style",datepicker_div.attr("style").replace(/width: [0-9]+em;/,"width: 38em;"));
      //別にこれでも問題はないですよ。
      $(input).datepicker("widget").css("width","38em");
    },10);
  }
});

見た感じ行けます。
ただ、月を変更すると戻るんですよねー・・・。
で、じゃあそれはonChangeMonthYear()で書けばいいじゃんと言われそうなんで書いてみます。

$("#calendar").datepicker({
  onChangeMonthYear: function(year,month,inst){
    setTimeout(function(){

      $(this).datepicker("widget").attr("style",$(this).datepicker("widget").attr("style").replace(/width: [0-9]+em;/,"width: 38em;"));
      //別にこれでも問題はないですよ。
      $(this).datepicker("widget").css("width","38em");
    },10);
  }
});

さて、これで動かしてみると・・・
Chromeとかでは普通に見えますが、Firefoxで見ると違和感が出ます。
「ガチャ」っとなるというか、表示がカタッとしますよね。
どうしてかというと、一旦月を変えたときに表示されるHTMLに対して確かにこれでwidth書き換えしているんですが・・・
再度書き換え直されている模様です。

トレースしていくと、ここら辺が犯人。

//(jquery-ui ver 1.8.8 665行目あたりから始まる_updateDatepicker()メソッドの693行目)

          var width = 17;
          if (cols > 1)
               inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
          else
               inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');

ここのif文がtrueになったとき!最後の.css()で上の固定長になっている「17 * (表示月数) em」と設定されてしまうので、結果的に
一旦これで戻されてしまいます。

どういう流れになっているかとまとめるとー

1.beforeShow()で生成された#ui-datepicker-div のstyleを書き換える(ここで希望通りのサイズになる)
2.月を移動させる
3.1で定義したサイズのまま新しい月のデータが入る
4._updateDatepicker()内の処理が走り一旦サイズがもとに戻される
5.onChangeMonthYear()のsetTimeout()内に書いた処理でまた希望通りのサイズに変更される

4->5の流れのところでガタッとした感じになるんですね・・・・。
というか固定長で17っていれないでよ・・・。設定変えたいよ・・・。

苦し紛れの回避方法ですが、一旦表示を消しておいてから表示するという方法もあります。

$("#calendar").datepicker({
  onChangeMonthYear: function(year,month,inst){
    setTimeout(function(){

      $(this).datepicker("widget").attr("style",$(this).datepicker("widget").attr("style").replace(/width: [0-9]+em;/,"width: 38em;"));
      //別にこれでも問題はないですよ。
      $(this).datepicker("widget").css("width","38em").show();  // < - ここで再度表示
    },10);
    $(this).datepicker("widget").hide();  // <- ここのタイミングで一旦消す
  }
});

これ一瞬表示が消えるのが難点です。
アニメーションでごまかしてください(ぇ

ということで、皆さんjQueryUIでdatepickerを使うときはご用心。


Comments

“jQueryUIのdatepickerを使ってハマった所 その1” への3件のフィードバック

  1. Kick the tires and light the fires, problem ofallifciy solved!

  2. You mean I don’t have to pay for expert advice like this anymore?!

  3. Già rivederlo nella versione “pulita” dell’edizione DVD mi aveva fatto riscoprire emozioni che non ricordavo da quando ero bambino… mannaggia a me, perché non ho aspettato a fare l’acquisto ?!? :)Comunque mi accodo al commento di Wolf… voglio vedere quel rimasterizzato!!! :)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です