JavaScript : してログ

jQuery UI Dialog で modal: true としたダイアログで、再表示したときに操作不能になるという現象に遭遇しました。 操作不能というのは、ダイアログに配置したセレクトボックスは選択リストが表示されなくなり、テキストボックスはクリックしてもキャレットすら表示されないという状態です。 ただし、フォーカスは入っているらしく Chrome などで動かすと、枠の色が変わるのが分かります。 ちなみに、モーダルでなければそういうことにはなりません。

色々と調べた結果、作りおきのダイアログがあるとダメなことが分かりました。 問題のあったページでも、そのダイアログとは別に、autoOpen: false として作っておいて、必要なときに dialog('open') しているものがありました。 これを、ボタンやリンクがクリックされた際に、都度作るようにしてみたところ、問題が解決しました。 この現象でお悩みの方は、作りおきのダイアログが他に無いか調べてみてください。

OpenLayers をバージョンアップしたところ、jQuery の draggable を適用したフローティング・パネルの動きが変になってしまいました。ゆっくりと動かして、ドラッグハンドルをマウスが外れなければ正しく動きますが、速く(といっても普通に)動かして、ドラッグハンドルをマウスが少しでも外れると、ドラッグが解除されたり、おかしな動作が始まります。マウスダウンからアップまで、ハンドリングできない状態になり、低スペックマシンではかなり操作しづらくなります。

なかなか原因が分からなくて、旧バージョンにロールバックしようかと思いましたが、分かってしまえば至って単純な原因でした。OpenLayers の新しいバージョンは、fallThrouth というオプションがデフォルトで false になっています。これを true にするだけでした。

	map = new OpenLayers.Map({
		fallThrough:       true
	});

FormData があると Ajax でファイルアップロードできるようになって大変便利なのですが、困るのが IE8 と IE9 の対応です。 IE10 からは FormData が使えますが、未だに IE8 の要求は来ます。 かつての IE6 のポジションを受け継いでいる臭が漂っています。

諦めて POST で画面リロードするところでしたが、ちゃんと調べて見ると代替策がありました。 使うのは POST ですが、見せ方としては非同期通信っぽく動きます。 サンプルコードは載せませんが、要点を箇条書きにしますので、参考にしてください。

  • 親ページに iframe を配置して見えないようにします(display:none だと Safari でまずいみたいなので、横幅&縦幅をゼロにします)
  • フォームのターゲット要素(target="<iframe名>")で、配置した iframe を指定します
  • サーバー側で POST を受け取ったら、JavaScript で親ページの関数を呼んで通知するようにします
  • 親ページでは関数が呼ばれたら、アップロード完了などのメッセージを提供できます

最近のブラウザは、showModalDialog で開いたウィンドウ内の遷移は普通に行えます。 しかし、IE8 では新しいウィンドウが開いてしまします。 ググると、iframe を入れて面倒なことして回避している輩もおられるようですが、そんなことしたくないですよね。 いろいろと調べてみると、海外のサイトに解決方法を見つけました。

IE8 はどうやらベースとなるターゲットが親ウィンドウかなんかに指定された状態で、ダイアログがオープンされているようです。 html のヘッダー部分に、ベース・ターゲットを自分自身にするよう指定すれば良いみたいです。

ベースターゲットの指定
<base target="_self" />

「オブジェクトでサポートされていないプロパティまたはメソッドです。」

この呪文の詠唱を IE が始めたら、とりあえずマウスぶん投げて甘いもんでも補給しましょう。 さて、今回は trim が原因なのですが、なんと IE8 は実装されていません。 このような基本的な、文字列操作が実装されていないなんて、はっきり言って思いもよりませんでした。 まさに(・・)です。

ならば、正規表現なんかを使って解決してもいいのですが、jQuery が使える状態なら、下記のようにすれば良いと思います。 少し前なら IE6 がー、とか言ってたけど、IE8 お前もなのか。。。 Microsoft は間違えなく、インターネットの発展の足を引っ張ってると思います。

IE8 で動かないコード
var after = before.trim();
jQuery での代替
var after = $.trim(before);

普通に alert すると [object HTMLDocument] なんて感じで何の役にも立たないですので、オブジェクトのプロパティをダンプする関数を作ってみました。alert の代わりに使用すると、オブジェクトの見通しが良くなって開発効率が上がりそうです。

function obj_dump(obj) {
	var txt = '';
	for (var one in obj){
		txt += one + "=" + obj[one] + "\n";
	}
	alert(txt);
}
テスト

未定義変数を判断したい場合は、void(0) と比較します。

if (x == void(0)) alert('undefined');

undefined 定数との比較でも実現できますが、この場合、古いブラウザで動かない場合があるので、void(0) を用いた方が良いと思います。

if (x == undefined) alert('undefined');