Page Index
日付 題名 記事の要約
2003.5.1 エラーパラダイス IE4とNetscape3のエラー繁盛記
2003.5.4 幻のNetscape5 Geckoのバージョン判別苦戦記
2003.5.5 第2次ブラウザ大戦 標準化への道
2003.5.6 ちっぽけな理由と壮大な苦労 「フォルダを開く」奮戦記
2003.5.18 大ボケ500エラー 掲示板CGIに隠された罠
2003.5.19 更新情報スクリプト サイト設定のアイデア

 ノートパソコンのセットアップを終え、早速IE4と Netscape3 で新 Transient Edition をうろうろしてみる。旧ブラウザを徹底回避したつもりだったのに、エラーが出るわ出るわ。やはり実際に確認するのが一番である。思惑はあてにならぬのだ。特に Netscape3 は switch や正規表現など特殊構文の多くに対応してないため、実行しなくてもエラーが起きる。もうファイルを読みこませない以外に対処方法がないのだ。
 それにしても、if (location.replace) でIE4がエラーを起こすとは思わなんだ。オブジェクト判別ができないのかと思いきや、if (document.all) はちゃんと動く。なんと難儀なのだろう。

 他、Public Edition も見てみると、Netscape3 では大量のエラーで閲覧どころの話ではなかった。なにせ1回のエラーごとにウィンドウが開くため、瞬時にタスクバーが Netscape で占領される。これはたまらん。

 さて、これからが本番である。今のところ旧ブラウザにはスタイルシートを一切読みこませてないので、見事なテキストブラウザと化す。Netscape3 はもともと対応してないので仕方ないが、IE5までテキストブラウザにするつもりはない。
 よって、旧ブラウザ用のスタイルシートを作成しなければならない。IE4は class="class1 class2" といった多重クラスに対応してないため、確認しながらでないと怖い。(IE5でなくIE4にこだわっている理由は、ここにある)


幻のNetscape5

2003.5.4.Sun

 Netscape には5.xがない。4.78の次は6.0である。5.0は途中で開発が頓挫して葬られたという話だが、その辺の詳細は知らない。
 しかし、JavaScript 上では Netscape6 のバージョンは5として扱われているため、siteCTSのブラウザ識別では Netscape6 を

if (navigator.appName == "Netscape") {
  ver = parseFloat(navigator.appVersion.substr(0, 3)) *10;
  if (ver >= 50)
    ver += 10;
}

 として見分けている(た)。
 parseFloat(navigator.appVersion.substr(0, 3)) で「5.0」が取得されるので、それに10を掛けて整数にする。(小数点だと扱いが面倒くさいからだ)
 で、50以上だったらさらに10を足す。これで「ver が60だったら Netscape6」という感じ。

 ところが、困ったことに Netscape7 も「5.0」なのである。「6.0」ではないのだ。つまり、JavaScript 上では Netscape7 は Netscape6 なのだ。わけわからん。(その話でいくと、IE6は未だにIE4なのだけど)
 要するに、navigator.appVersion はもう使い物にならないことを意味する。こんなアテにならないものはいらぬ。その代替はおなじみ navigator.userAgent であるのだけど、これまた表記に一貫性がない。

navigator.userAgent.toLowerCase();

//Netscape6
mozilla/5.0 (windows; u; windows nt 5.1; ja-jp; rv:0.9.4.1) gecko/20020314 netscape6/6.2.2

//Netscape7
mozilla/5.0 (windows; u; windows nt 5.1; ja-jp; rv:1.0.2) gecko/20021120 netscape/7.01

 バージョンはともに5.0になってることがわかる。だからといって、尻にある詳細バージョンも小数点があったりなかったりで、ちっともアテにならない。
 まぁ正規表現を使えばなんてことはなく、

if (navigator.appName == "Netscape") {
  if (navigator.product && navigator.product == "Gecko") {
    var reg = new RegExp("Netscape.?\\/[6-9]\\.\\d\\.?\\d?");
    var ver = navigator.userAgent.match(reg); //"Netscape6/6.2.0"
    reg = reg.compile("[6-9]\\.\\d\\.?\\d?");
    ver = ver[0].match(reg); //"6.2.0"
    if (ver[0].charAt(3) == ".") //小数点が2つあるか
      ver = ver[0].substr(0, 3) + ver[0].charAt(ver[0].length -1); //"6.20"
    ver = parseFloat(ver); //6.2
    ver *= 100; //620
  }
}

 これで6.xxと7.xxの判別が可能となるのであった。Netscape9.99 まではこれでOKだが、当サイトでは小数点第1位までしか見ない(すなわち ver は2桁になる)ので、この例は無意味だったりする。ちなみに Netscape3 でのエラーを防ぐためにいちいち RegExp オブジェクトを使ってるけど、本当はもっと短くできる。

 siteCTSでは if (document.all) なんて簡易判別に頼らず、ブラウザの識別はすべてクラス "Brws" が担当している。こやつは言うまでもなくブラウザを確実に見分けるのが仕事だ。ユーザーエージェントとオブジェクト判別の両方を使うので、他ブラウザがIEを詐称することは不可能。逆にIEが他ブラウザを詐称した場合、どれにも当てはまらなくなる。(それは俺のせいではないので刎ねられる対象となる)

 すべてのスクリプトはこやつの言うことを頑なに信じるので、つまり "Brws" がバグを出すとサイト全体がこけるし、あるいは嘘をつくようにするとIE6をOpera7にすることもできる。サイト設定を担当するクラス "Envs"に はそのような装置が搭載されていて、「IE6だけどエラーが起きるからIE4として扱ってくれ」なんて注文も可能なのであった。(サイト設定の"マーキングレベル"がそれ)


 かつて「ブラウザ戦争」と呼ばれたVer3〜4時代。IEと Netscape は次々に独自拡張をしていって、Webをとても住みにくくしてしまった。webmaster はそれぞれに合わせたソースを書かねばならず、労力は跳ね上がり、素人をビルダーに走らせた。
 「すべてのメディアで再生できるデータを」というHTML本来の理念が失われた、暗黒の時代。

 シェア戦争がIEの完勝に終わって久しいが、Netscape も負けてばかりではなかった。Mozilla と手を組み、レンダリングエンジン "Gecko" を組みこんだ新 Netscape は、世界のどのブラウザよりもHTMLの仕様に準拠していた。続いて後発ブラウザである Opera も仕様準拠を売りにし、シェアを急速に伸ばしていた。
 シェアでは圧倒的な差があっても、「WWWブラウザ」としては、IE5.5は完敗していたのである。

 そしてIE6もこの潮流に乗り、「互換モード/標準準拠モード」を搭載した。旧バージョンとの互換性を保つため、webmaster が簡単に選択できるようになっている(これは Netscape にも搭載されている)。
 このところ、Netscape と Opera はバージョンアップのペースが凄まじく、6.xはあっという間に7.0になった。両者とも機能が飛躍的に強化され、今やIE6は「3強の中では一番性能の悪いブラウザ」になっている(特にスタイルシートが弱い)。

 巨大であるがゆえに開発がもたついているIE7も、タブブラウザ化などの新機能が盛りこまれるらしいが、肝心要である「仕様への準拠」はいかほどであろうか。多くが待望している <link> への対応も、いいかげんに達成されるのであろうか。俺が個人的に待望している position:fixed への対応は。
 なにより、WindowsXP 専用という噂が真実ではないことを祈る。

 いよいよ加熱してきた、第2次ブラウザ大戦。前回の雌雄対決とは違い、今回は Opera もいる。Safari や iCab などのMac勢力も参戦してきた。前回の独自拡張対決とは違い、今回は加熱すればするほどWebが住みよくなる、とても素晴らしい戦争だ。
 この大戦のキーポイントは、なにはなくともスタイルシートである。HTML/XHTMLからフレームやフォント指定などの「デザイン機能」が削除された以上、これを抑えずして勝利はない。現時点では Netscape7 の完勝であり、どのブラウザの追随も許していないが、これからどう転ぶか見ものである。(まぁシェア的にはIEの独壇場であることに変わりなかろう。OS抱き合わせとはそういうことだ。)

 だけど、忘れちゃいけない。ブラウザがいくら仕様に準拠してWebを住みよくするために尽力しても、webmaster が従わねば意味がないということ。すべては我々の手にかかっているのだ。「どうせみんなIEなんだから、従うだけ無駄でしょ」なんてことを言ってると、いつまで経っても状況が良くならない。

 ともあれ、IEが5.5になると Netscape が4.78からいきなり6.0になり、さらに Opera まで6.0になり、IEが6.0になって追いついたかと思えば Netscape と Opera が早々と7.0になって、なんともかわいそうだと思うまいか。
 私は JavaScripter であると同時に JScripter でもあるので、IEには頑張ってもらいたい所存である。


[ 項目が追加されているところ / 11KB ] ページ右上にあるコンテンツ移動セレクトボックスに、4つほどの管理用項目を追加してみた。上の3つは ExpContext の「サーバーチェンジ」と同じだし、一番下のも機能的には同じである。(もちろん、これらはローカルの時しか出現しない)

 …が、この「This Folder」にものすごく苦労したんである。これを選ぶと、今見ているページのフォルダを開きたいのだが、普通に window.open() でIEにフォルダを開かせると、XPではなぜか「大きいアイコン」で表示されてしまうのだ。これがすごく嫌なんである。たったそれだけのために苦労したんである。

 というのも、http://127.0.0.1/ で見ている時はローカルファイルであろうともインターネット扱いであるから、ActiveX でエクスプローラを起動することもできない。ExpContext はマイコンピュータゾーンで実行されるからこそ可能なのだ。

 ならばと、いったん別のウィンドウでローカルファイルを開かせてみる。これなら ActiveX も使えるからだ。しかし、そこからURLを間接的に取得しようとすると、これもセキュリティチェックに刎ねられた。URLさえ取得できれば、後は好き放題なのに。設定はともかく、参照もできないとは難儀な仕様だな。

 こうなると、もっと根本的に違う手段が必要である。そう、JavaScript の面影を残さないほどの強力な JScript が。(あいにく俺はVBSを使えないので)

 そうこうしてできたのが、以下のスクリプト。このローカルファイルを window.open() で開くのである。

<script type="text/jscript">
var path, ie, e = new Enumerator((new ActiveXObject("Shell.Application")).Windows());
for (; !e.atEnd(); e.moveNext()) {
  ie = e.item();
  path = ie.LocationURL;
  if (ie.FullName !== "C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE")
    continue;
  if (/transient|valid/.test(path) && !/FolderOpen\.html/.test(path)) {
    path = path.match(/\/(transient|valid)[^#?]+/)[0];
    path = "F:" + path.substring(0, path.lastIndexOf("/") +1).replace(/\//g, "\\");
    (new ActiveXObject("Shell.Application")).ShellExecute("explorer", path);
    setTimeout("window.close()", 300);
  }
}
</script>

 流れを簡単に言えば、「今実行されているIEとエクスプローラを全部取得して順番に見ていき、siteCTSのウィンドウだったらパスを取得、それをフォルダのパスに加工してエクスプローラを起動」というものである。勘が良ければ気づくだろうけど、siteCTSのウィンドウが10個あったら、それぞれのフォルダが10個開いてしまう仕様。siteCTSの作業をしてる時は基本的にIEはひとつしか開かないので、まぁなんとかなるかな、と。

 ちなみに私は、実行中のウィンドウのパスを取得する LocationURL というプロパティを知らず、LocationPath とか LocationHref とか手あたり次第に試して、自力で発見してしまった。我ながら暇なことをする。(だって for in に反応しないんだもの)


大ボケ500エラー

2003.5.18.Sun

 当サイトの掲示板に投稿しようとすると、なにやらサーバーエラーが起きる旨の噂を風に聞き、試してみるとバッチリ Internal Server Error。ぎゃー。
 早速調査に乗り出すも、ローカルテスト用コードの削除忘れっつぅ情けないミス。誰かこいつなんとかしてくれ。

[ エラー部分のソース画像 / 7KB ]

 管理人がPerlに慣れてない上、元が改造品なのでスクリプトも混沌としており、かなり頭の痛い当掲示板。リニューアル版ではすべて一新しようと画策しているものの、構想にスキルが追いつかない。この隔日日記のCGIをXHTML対応に改造するだけで息を切らしてるくらいだから、スキル不足は相当なものだ。っていうか素人レベルっていうか話にならないっていうか。頑張れ俺。


更新されたコンテンツを強調表示する期間
しない・3日・7日・14日・21日・30日
説明:更新されたコンテンツには赤い下線が表示され、ぼやぼや明滅します。この強調表示をする期限を指定してください。初期設定は7日です。
更新されたページを開いたら強調表示を解除する
説明:名の通り。上記の期限設定に係わらず、一度開いた時点で更新強調表示を解除します。いるかどうかは別として、「一度開いたら必ず読む」という人向け。

 …と、こんなサイト設定を追加しようと画策中。トップページにある更新日チェックスクリプトを拡張して、他のコンテンツでも使えるようにしよう、というもの。これにより、たとえばパチョ奮闘記の索引とかで、記事の追加後○日以内だったらタイトルを自動で強調表示…ということが可能になる。
 1番めはわけもないけど、2番目はなかなか難しい。パスかファイル名をキーにして new Date() の値を入れておき、次に来た時これを比較…という感じにすれば簡単だけど、そうするとファイルの数だけキーが増える。Valid Editionは結構大きなサイトになるので、将来を考えれば非現実的。バックナンバーなどは更新チェックする必要もないのだから、その辺を見分けるようにすればいい。となると、そのための処理が別途必要だ。
 <meta name="updatecheck" content="enable"> でも作るか…?
 うーん。