2003年5月分。
Googleは日頃大いに活用させてもらっているのですが、検索結果からページを辿る際には、キーワードのハイライトがあることから、元のページではなくGoogleで保存されたキャッシュのページを見ることも多々あります。特にファイルサイズが大きい場合は、キーワードを見つけやすくするため、その傾向がより高いです。
そんなわけでキャッシュのページをよく見るのですが、正しいHTML+CSSで作成されたページのキャッシュを見た場合、あの上部に挿入されている、「これはGoogleのhttp://〜のキャッシュです」云々と書かれている枠(tableによる)が崩れた表示になってしまうことがたまにあります。
挿入されるtableとその内部はHTML的にかなり無茶苦茶なマークアップであり、またその挿入の仕方もかなり無理矢理なので、そこをなんとか改善してほしい……という気持ちはあるものの、一般利用者にとってはそんな事情は窺い知ることはできず、ただ「表示が崩れた」と見られるのみでありましょう。もしかするとその表示の崩れた理由が「CSSを使っているからだ」などと思われるかも知れず、そうなるのはちょいと癪です。ならばこちらで、キャッシュに挿入されるtableを整形してやればいいではないか、ということを思いつきました。勿論CSSを使って。
CSSの対応が比較的進んでいるMozilla(Gecko)系ブラウザやOperaへの対処は、さほど難しくはないです。Googleのキャッシュに挿入されるtable要素にはborderやらwidthやらの属性も付いてくるので、属性セレクタを使うことにより、自サイト内のtable要素に対するスタイルと区別すればよいわけです。
Googleキャッシュのtableは三重になっており、外側に二重のtable、あと、「これらのキーワードがハイライトされています」の部分でもう一つtableがあります。これらはそれぞれ外側から、
<table border="1" width="100%">
<table border="1" bgcolor="#ffffff" cellpadding="10" cellspacing="0" width="100%" color="#ffffff">
<table border="0" cellpadding="0" cellspacing="0">
というタグになっています。当サイト内のtableではborder属性は(多分)使っていなかったので、子孫セレクタとの合わせ技で
table[border="1"] { ... }
table[border="1"] table[border="1"] { ... }
table[border="1"] table[border="1"] table[border="0"] { ... }
という指定にしてみました。Operaでは、複数の属性を参照する属性セレクタ( table[border="1"][width="100%"]
とか)が効かないようなので、その辺も考慮して。あと、tableの中にはbやらfontやらcodeやらのインライン要素も入っているので、それを逆に利用してスタイル指定してみたり。
で、取り敢えず対処前から対処後のようにすることができました。具体的なスタイル指定は当サイトCSSファイルの末尾の方を参照。
さてMozilla、Operaはいいとして、問題はIEであります。やはり多くのお客さんはIE利用者ですので、むしろこちらの方をぜひ対処したいのですが、IEでは属性セレクタが使えないというのが難点。せめて一番外側のtableにclass属性のひとつも付けてりゃいいのに、とGoogleへのうらみ言の一つも言いたくなるところ。
まあ、class属性がないなら付けるしかないでしょうなあ、というわけであまり使いたくなかった奥の手、JavaScriptの出番であります。ページ読み込み時に実行させているスクリプトに以下のコードを追加しました。
/* Googleのキャッシュで挿入されるtableにclass付けする */
function googleCacheClass() {
if (!location.host.match(/(google|216\.239\.\d{2}\.100)/i)) return;
gTable = document.getElementsByTagName('table').item(0);
gTable.className = 'google-cache';
}
で、このclass付けされたtableを元にしたスタイル指定を更に追加。実際の指定についてはこちらも当サイトCSSファイルの末尾の方を参照下さい。これでIEにも(スクリプトが有効であれば)一応対処できました。
今回のこれは「いくらなんでもやり過ぎなのでは」と自分でも疑問だったりします。普通に閲覧する際にも大きくなったCSSファイルやスクリプトを読み込ませてしまうデメリットを考えると、あまりオススメはできません。と念のため追記。
(2003年5月11日)
「自分の意思で鳥肌を立たす」というのは果たして一般的な動作でありうるのでしょうか
……という自分の先日の疑問について、しまけんさんより言及頂きました。
コレは無理です…。ど、どうやると出来るんでしょうコレ、操れると面白い気がするので。
ええと、やり方としては
てな感じで、これで全身にぞわわっとくるのですが、いかがでしょう。数十秒くらいなら鳥肌状態を維持することもできますが、あまりやると疲れます。
実は自分も耳を動かせるのですが、しまけんさんのように左右別々
にまでは出来ず、両方同時にしか動かせないのです。幼少の折にもっと鍛錬しておけば勝てたのに!(←何にか)と後悔することしきりでありましたことよ。
(2003年5月13日)
WinIEがabbr要素を理解しないことへの対応として、The Web Kanzakiで用いられいてたスクリプトを少し変更したものを使ってました(参照: 見よう見まねJavascript)。それで今まで動作上特に問題もなく、またinnerHTMLと正規表現を使ってソースを書き替えるという手法はスクリプトの見た目もすっきりしていて分かりやすいのですが、別の手段として、正規のDOM的手法を用いてなんとかならないかと考えまして、試してみることにしました。DOMの勉強も兼ねて。
やり方としては、abbr要素ノードからその子テキストノードとtitle属性を取り出して、それを新しく作ったspan要素に適用し、span要素を文書に追加する、という感じで行けるかなと思っていたのですが、実際にやってみるとabbr要素の子ノードが取り出せなくて躓きました。色々と試してみる中で、確認のため、
<abbr title="world wide web">WWW</abbr>
というabbr要素ノードnに対し、n.outerHTMLをとってみたところ、このような結果に。
<ABBR title="world wide web">
あれ、要素の中身と終了タグはどこに? その行方を探すべくまた色々と試したところ、どうやら理屈が分かりました。
例えば以下のようなp要素:
<p>本日は<abbr title="world wide web">WWW</abbr>日和なり。</p>
について、その全ての子ノードを取り、各子ノードのnodeType, nodeName, nodeValueを確認してみたところ、WinIEでは以下のような結果となります。
順序 | nodeType | nodeName | nodeValue |
---|---|---|---|
0 | 3 (text) | #text | 本日は |
1 | 1 (element) | ABBR | null |
2 | 3 (text) | #text | WWW |
3 | 1 (element) | /ABBR | null |
4 | 3 (text) | #text | 日和なり。 |
つまりabbr要素の開始タグ部分は空要素のように扱われており、要素の子ノードになると思っていた"WWW"は空要素ノードの
一応、MozillaとOpera 7での場合も。こちらは流石に期待通りの結果となってます。
順序 | nodeType | nodeName | nodeValue |
---|---|---|---|
0 | 3 (text) | #text | 本日は |
1 | 1 (element) | ABBR | null |
2 | 3 (text) | #text | 日和なり。 |
ともあれ、動作が多少変であってもabbr要素の中身部分をDOM的手段で(childでなくnextSiblingとして)取り出せることが分かったので、それを用いて新たにspan要素を作り、文書へ追加することは何とかできました。
が、ふと「スクリプトで新たにabbr要素を作って文書に追加したら、それはどのように扱われるのだろう」という考えがよぎりましたので試してみたところ、そうして作られたabbr要素はtitle属性がツールチップとして表示されるし、CSSによるスタイル適用もできるではありませんか。
そういうことであるのなら、何もspan要素なんかの助けを借りるまでもなく、もともとの妙な形で扱われているabbr要素をちゃんとしたabbr要素として生成しなおせばよいわけです。最終的には以下のようなスクリプトとなりました。
/* abbr要素を再生成する(for WinIE) */
function regenerateAbbr() {
var abbrs = document.getElementsByTagName('abbr');
for (var i = 0; i < abbrs.length; i++) {
var oldAbbr = abbrs.item(i);
var newAbbr = document.createElement('abbr');
newAbbr.title = oldAbbr.title;
oldAbbr.parentNode.insertBefore(newAbbr, oldAbbr);
while (oldAbbr.nextSibling.nodeName != '/ABBR') {
newAbbr.appendChild(oldAbbr.nextSibling);
}
oldAbbr.parentNode.removeChild(oldAbbr.nextSibling);
oldAbbr.parentNode.removeChild(oldAbbr);
/*alert(newAbbr.parentNode.innerHTML);*//*確認用*/
}
}
と、手間かけて作ってみたこのスクリプトなのですが、実は効率の点ではinnerHTMLを書き換える方法に劣ります。残念。しかしながらWinIEにもabbr要素をabbr要素として認識させることができる、という点に意義があるような気がするので、当サイトではしばらく前からこちらを使用しています。
(2003年5月15日)
徒書の個別記事表示のURLを、/itazuragaki/?(記事id) から /itazuragaki/id/(記事id) に変更しました。とは言え今まで通り /itazuragaki/?(記事id) の方でアクセスしても、自動で /itazuragaki/id/(記事id) に移動しますので、ご迷惑はおかけしません。
これで現在徒書で使用しているCGIスクリプトは以下の3種となりました。
(2003年5月18日)
net::memoのXHTML1.1のMIMEタイプについて。XHTML 1.1はtext/htmlでいいというのは自分も同意なのですが、以下の部分が気になりました。
また、meta要素でapplication/xhtml+xmlを宣言しておいて、サーバーが言うことを聞かないと言い訳するのもありだと思います。
meta要素のhttp-equiv属性は、サーバがHTTPレスポンスヘッダに用いる情報を収集するためのものとされていますが、サーバが必ずそのように動作しなければならないとは規定されていないと思います。実際、「meta要素を解析してその通りにHTTPヘッダを出力するサーバ」があるというのもあまり聞かないような(自分が知らないだけかもですが)。
なので、サーバがmeta要素の通りにHTTPヘッダを出してくれないからといって、必ずしもサーバが悪いとは言えないと思います。で、meta要素の通りにHTTPヘッダが出力されなければ、meta要素でのapplication/xhtml+xmlの指定も無意味なわけで、ただ無意味だけでなく、実際はtext/htmlで出力されているのだから嘘の情報を書いていることになってしまいます。そんな嘘を書くくらいだったら、application/xhtml+xmlにこだわらずに、meta要素でもtext/htmlと書く方がまだましよいのではないでしょうか。
あと、以前にsatosiiさんから伺ったことなのですが、XHTML Media Types(邦訳)には
"XHTML を application/*+xml として serve する場合には、meta http-equiv での content-type 指定は記述すべきでない (SHOULD NOT) と" という注記 [2] があります。
という話もあります。XHTML Media Typesの文脈からすると「文字エンコーディングについて、meta要素での指定はすべきでない」という話と思われますが、meta要素でエンコーディングだけ指定してContent-Typeそのものは指定しない、というのは無理なので、やはり「application/xhtml+xmlとして提供される文書には、 <meta http-equiv="Content-Type" content="..." />
という指定自体書くべきでない」ということになると思います。
XHTML文書(1.1まで)の良いところは、今までにあったHTMLと同じタグ名を使っていることにあるように思います。だからこそ少し記述に気を遣えばHTML用ブラウザで表示することも可能だし、またその同じ文書をXML文書としてしかるべきアプリケーションで処理することも可能なわけで。そういった
……と、「text/htmlのXHTML文書」を肯定する派であることを表明してみたり。
(2003年5月29日)
先週あたりからどうも風邪気味です。今のところ症状は喉にしかきていないので普段の生活は維持していますが、頻繁に咳が出てくるのはちょっとつらいところ。つい先日になって喉飴で症状が軽減されることを覚えたので、最近では飴舐めまくりな日々であります。
(2003年5月29日)
Re: XHTML1.1のMIMEタイプで、「『meta要素を解析してその通りにHTTPヘッダを出力するサーバ』があるというのもあまり聞かないような
」、などと無知なことを書いたところ、いわいさんよりApacheでの実装があるとのこと。
「
あまり聞かないような」に異論がある訳ではなく単なる FYI なのですが、Apache 用モジュールで mod_html_meta という実装はあります。試したことはないのですけど。
情報感謝です。ずっと「そのようなサーバの機能があるか」という観点で調べていたので、Apacheのモジュールを探すことには気付いていませんでした。ということでApacheのモジュール追加は初体験ながらも、自宅のCygwin + Apacheで実験。
http://www.yoshidam.net/mod_xml_charset-0.1.5.tar.gz よりソースをダウンロードして展開。
説明の通りに apxs -c mod_html_meta.c でコンパイルしてみる。
途中でエラーになってしまった。
$ apxs -c mod_html_meta.c gcc -DCYGWIN -DUSE_HSREGEX -DEAPI -DSHARED_CORE -DSHARED_MODULE -I/usr/include/ apache -c mod_html_meta.c mod_html_meta.c:134: conflicting types for `strndup' /usr/include/string.h:63: previous declaration of `strndup' apxs:Break: Command failed with rc=1
strndup
という名前が衝突しているようなので、mod_html_meta.c の中の"strndup"を試しに"strnndup"と書き換えてみる(←いいのか)。
それで再度コンパイルしてみると最後まで通って、mod_html_meta.dll ができた。
できたdllを、apxs -i -a mod_html_meta.dll でインストール。
httpd.confにmod_html_metaモジュールが追加されたことを確認し、Apache再起動。
.htaccessに以下2行を追記。
HTMLMeta on AddHTMLMeta html
んでもって手打ちtelnetでApacheサーバにHEADリクエストを出してみると……あ、確かにmeta要素での指定が反映されましたよ。
$ telnet localhost 80 Trying 127.0.0.1... Connected to croquis. Escape character is '^]'. HEAD /kits/tanpen/ HTTP/1.0 HTTP/1.1 200 OK Date: Thu, 29 May 2003 14:47:11 GMT Server: Apache/1.3.24 (Cygwin) Content-Script-Type: text/javascript ←このへん Content-Style-Type: text/css ← Last-Modified: Mon, 26 May 2003 15:39:44 GMT Connection: close Content-Type: text/html; charset=Shift_JIS ← Connection closed by foreign host.
meta要素の指定で、Content-Typeまでも変更できるのかどうかが一番気になるところだったのですが、それも問題なくできていました。うーむすごい。ただし、meta要素をSSIで追加している場合だと、さすがにその部分の指定は反映できないようでした。
で、しばらくmeta要素の指定でtext/plainにしてHTMLソースをそのまま表示させてみたりとか、image/jpegにして「画像にエラーがあるよ」とエラー表示させてみたり(Mozillaにて)などして遊んでいました。
※コンパイルのしかたについてはもっといい方法がありそうな気がしますが……。
(2003年5月30日)
net::memoのHTTPヘッダとmeta要素の擦れ違いへの返事です。或いは前回からの続き。
meta要素のContent-Typeはサーバーに対して書かれるもので、UAに対して書かれるものではありません。それに対し、HTTPヘッダはUAに対して送信されるものです。
meta要素でContent-Typeを書くことの第一の役割は、確かにその通りと思いますが、文書中にHTMLタグの形式で記述される以上、完全にHTTPサーバのためのみの情報とは言えないのではないでしょうか。
ブラウザでソースを見れば簡単に見ることができるし、その気になればDOMでmeta要素の中からhttp-equiv="Content-Type"であるものを探し、そのcontent属性の内容を参照する、ということも可能なので、UAに対しても提供される情報のひとつではあると思います。
ですから、HTTPヘッダがtext/htmlでmeta要素がapplication/xhtml+xmlだったとしても、その文書が text/htmlとapplication/xhtml+xmlの両方に適合しているのであれば、サーバーもXHTML文書も間違っているとは言えません。サーバーがmeta要素を利用しなかっただけで、XHTML文書が嘘をついているわけではありません。
Content-Typeについて、文書がそのメディアタイプに適合しているかというのは、直接には関係ないのでは。例えば、終了タグ書き忘れミスのあるHTML/XHTML文書をContent-Type: application/xhtml+xml、またはContent-Type: text/htmlで送信することも可能ではあり、その場合、application/xhtml+xmlであればエラーを表示し、text/htmlであればエラーはある程度無視しつつそれなりに文書を整形して表示することでしょう(Mozillaの場合)。これは指定されたメディアタイプによって、ブラウザが文書の扱い方を変えた結果そうなったわけです。そのように、ブラウザ(UA)に文書をどのように扱ってほしいかを示すのが、HTTPレスポンスヘッダのContent-Typeの役割と思います。
なので、(HTTPヘッダで)Content-Type: text/htmlとして提供された文書の中に <meta http-equiv="Content-Type" content="application/xhtml+xml" />
と書いてあるというのは、文書中で「この文書はメディアタイプをapplication/xhtml+xmlとして提供してます」と書いてあることになり、やはり嘘の情報になってしまうと思います。
……と長々と述べてますが、結局のところは、
そうは言っても、meta要素だけをapplication/xhtml+xmlにすることを推奨するつもりはありません。HTTPヘッダとmeta要素の内容が食い違うのは事実で、そのような状態を好ましいとは思わないからです。
というのに賛成なのでして、好ましいと思わないからこそ、meta要素でapplication/xhtml+xmlの指定は書くべきでない、と考えるのです。
以下、2003-06-02 - Hatena::agendaでの指摘より削除……
更に言えば、「XHTML文書のメディアタイプはapplication/xhtml+xmlとすべき(should)」ということを勧めているXHTML Media Types(邦訳)という文書の、正にその中で、「application/(xhtml+)xmlの文書ではmeta http-equivによる指定はすべきでない(should not)」という旨が述べられています。この一点だけでも、meta要素でapplication/xhtml+xmlの指定は書くべきでない理由としては十分、と思います。
XHTML Media Typesの勧めに従うのであれば、
とするのが最善なわけで、
というのはXHTML Media Typesの勧めるところを二つも
……削除ここまで
HTTPヘッダでContent-Typeが何と出力されているか、というのは、CGIスクリプトのHTTPヘッダを出力させる部分に触れたりとか、Apacheの設定を変えてみたりとか、telnetを使って手入力でHTTPリクエストを送ってみたりとかしてみないと、ただHTML文書を書いているだけではなかなかぴんとこない部分であるように思います。「meta要素でのContent-Type指定がHTTPヘッダにも反映される」というサーバの実装が必ずしも多数派でない以上、「Content-Typeはmeta要素で指定すればそれだけでOK」※という誤解を文書製作者へ広めないためにも、XHTML文書にmeta要素でapplication/xhtml+xmlの指定は書くべきでないと考えます。
※ 実際には、HTTPヘッダとして出力されていなければ全く意味がないわけで。
……と、以上が仕様書などを読んで自分が考えたことなのですが、ウェブでそんな主張をしている文章はあまりないようなので不安でもあり、他のXHTML利用者のご意見をぜひ伺いたいところ。
(2003年6月1日)
ネットで知り合って実際に会った人、というのは自分にはほとんどいないのですが、その数少なくも貴重な知人の一人であるおかみさん主宰のBHUコントライブへこの日は行きました。折りしも颱風の最中でしたが比較的近所だしそんなに大変なこともなかろう、と外へ出てみると雨が止みつつあり丁度よい時でありました。
会場についてみると既にほぼ満席状態。渡されたパンフレットにはクロスワードパズルがついており、上演を待つ間に今回のコント五題のタイトルを当てる趣向。あいにく書くものが無かったので記憶力を頼りに解こうとしたのですが、時間が足りず、全てのタイトルが判明する前にライブが始まってしまい、やや心残りながらも舞台へ注目。以下タイトルと感想を。
次のBHU公演にも期待してます。コントライブは勿論、先のGWに女子高演劇部により初演※されたという「パパパ・ピピピ」も是非おかみさん出演/演出で見てみたいところ。
※ i n s p i r e d !に、「パパパ・ピピピ」初演時の写真つきレポートがあります。
(2003年6月2日)