近況報告たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。動向はもえじら組ブログで。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。Shadowのコード(textshadow.js)を教材にして拡張機能開発のノウハウを解説していくシリーズ。XPathをノードの検索に活用する方法を紹介したけど、肝心のXPathが書けなきゃ意味がないわけで。XPathって、ノードセットがどうとかノードテストがどうとか軸がどうとか修飾がどうとか、いざ勉強しようとしてもこれ専用の用語がやたらたくさん登場してきてものすごく萎える。CSSのセレクタの方が、機能は限られてるけどまだ分かりやすい。CSSのセレクタとXPath式の対応表があればいいのになあ、ということを、だいぶ前から僕は思ってた。Box)でそういうコンテンツがあったんだけど、移転のゴタゴタか何かで消滅したままになってる。XPath」みたいなキーワードでGoogleで検索してみて上位にくるエントリは、情報が不十分だったり間違いが含まれてたりする。いうわけで、CSS3セレクタ(このエントリを書いた時点ではワーキングドラフト)とXPath式の対応表で、詳細な物を作ってみた。Shadowのコード(textshadow.js)を教材にして拡張機能開発のノウハウを解説していくシリーズ。W3CのDOMでは、要素ノード(およびそのリスト)を得る方法として以下の方法がある。getElementById(aName)IDをキーにして単一の要素ノードを得る。getElementsByTagName(aTagName)タグ名、要素名をキーにして要素ノードのリストを得る。childNodes子ノードのリスト。本当はネームスペースを指定して検索する物もあるんだけど、ここでは割愛。DOMではないがこういうのもある。getElementsByClassName(aClassName)クラス名をキーにして要素ノードのリストを得る。aValue)属性名と属性値をキーにして要素ノードのリストを得る。属性値として「*」を渡すとその属性を指定された要素全てを得る。FirefoxでXULドキュメントにおいて利用可能。探したい要素ノードの条件が複雑な時は、これらを使って取得したノードリストをループ回して条件判断しないといけないし、そもそもこれらでは要素ノード以外は取得できない。そこで最近のJS界隈でよく使われているのが、XPathだ。XPathとは、/html/descendant::li[@class="navigation"]という風な「式」でXMLノードを特定する技術だ。XPathの書き方を新たに憶える必要はあるが、これを使えば、複雑な条件に合致するノードのリストを一発で取得することができる。3でもOperaでも、普通にDOMとJavaScriptでごりごりやるのに比べて20倍以上高速に動作するという話もある。XPathで提案されているXPath関係の機能が利用できる。Laboratoryの「DOMとXPathの連携」(サイトが消えてるので、インターネットアーカイブからどうぞ)を見て欲しい。3でも利用できるようになっている。Shadowのコード(textshadow.js)を教材にして拡張機能開発のノウハウを解説していくシリーズ。Firefoxの拡張機能で、DOM要素ノードを動的に生成したり、編集したり、そうして生成したノードを後でまた収集したり、といった操作を行うような物を作る時は、必然的に、ソースの中に要素名や属性名が登場してくる。this.processBox(nodes.snapshotItem(i));}こういう操作が一カ所だけにしか登場しないんなら別にいいけど、複数箇所で、似たような操作が何度もある場合は、要素名であるとか属性値・属性名であるとかノード検索の条件であるとかを、コードの冒頭で定数(定数プロパティ)として定義しておくことをお薦めしたい。'/descendant::*[@class="my-custom-box"]',(略)すると、さっきのような箇所はこうなる。this.processBox(nodes.snapshotItem(i));}textshadow.jsの冒頭箇所を見てみると、動的に生成するIDのプレフィクスとか、途中で生成する要素のクラス名であるとか、XPath式の中に埋め込む検索条件だとかを、片っ端から定数としてまとめて定義していることが分かるはずだ。しておくと、いざクラス名が他の拡張機能とかぶっていたと判明した時なんかでも、ソースの頭の方をちょこっと書き換えるだけで済む。class属性の値として文字列リテラルが書かれている箇所を片っ端から探すようなことはしなくていい。確かにたいていの場合はそうなんだけど、でもそれじゃ解決できない時もある。Shadowのコード(textshadow.js)を教材にして拡張機能開発のノウハウを解説していくシリーズ。JavaScriptでは、普通に宣言した変数や関数はグローバルな物になる。array[aKey];}だから、Firefoxで最初から定義されてるグローバル変数や関数と同じ名前の変数や関数を定義してしまうと、エラーが起こるし、最悪の場合はFirefoxが動かなくなってしまう。新規ウィンドウを開く関数「loadURI」を定義。新しいウィンドウが開かれるようになってしまう。そのウィンドウをgBrowserという変数に格納する。要素ノードへの参照としてgBrowserが定義されているから。これを防ぐ手っ取り早い方法としてお勧めしたいのが、自分の拡張機能で使う変数や関数を、「自分の拡張機能専用のサービスオブジェクト」のプロパティやメソッドとして保持するようにするというやり方だ。:activeのダイナミック疑似クラスに対応させた......つもり。試してみたら:focusは意図通り動いてくれない。2007テキストシャドウに、userContent.css内の指定を読む機能を加えた。圧倒的多数のサイトではtext-shadowはまだまだ使われていないけれども、ユーザースタイルシートを使えば色々遊べるよ、と。いっても全サイトで同じ色の影しか指定できない、サイトごとにいちいち影の色を指定しなきゃいけない、なんてのじゃあとてもじゃないけど使ってらんないので、userContent.css内の指定のみ、色が無指定の時はCSS3の仕様を無視して自動的にそれっぽい影の色を適用するようにしてみた。}とかuserContent.cssに書いとけば、色んなサイトで影が付いて楽しくなるかもしれません。ちなみに、XPCOMを使ってもuserChrome.cssやuserContent.cssから生成されたスタイルシートオブジェクトには絶対にアクセスできない。今回は、新規に空のドキュメントを生成し、そこにxml-stylesheet処理命令でuserContent.cssを読み込ませて、生成されたスタイルシートオブジェクトを参照する、という裏技を使っている。2007テキストシャドウを作って以降、何かの機会に見るページで不意に影付きテキストがあったりして、「ああ、今まで僕は『古いブラウザの人は最新のWeb技術の恩恵を受けられなくてかわいそうだなあ』とか思ってたけど、いつの間にか、Firefoxユーザの自分自身の方が『最新の技術の恩恵を受けられずにみすぼらしいページしか見れずにいるかわいそうな人』になっていたんだ......」と切なくなる。2007テキストシャドウでの影付けの基本原理は以下の通り。以下の解説を図を使って書き直しました。2007テキストシャドウを地道に改良し続けている。3でも動くようにしたGeckoもtext-shadowに対応してくれ!というバグにこれを貼り付けて煽ってみようかと思ったら、貼られていたテストケースで::first-line疑似要素が使われてて表示できなくてこりゃまずいと思ったんで、元々対応する気の無かった疑似要素と疑似クラスにまで頑張って対応してみた。疑似クラスについてはGeckoすら対応してない物にまで対応してたりして。名前の通り、CSS3のtext-shadowを無理矢理再現するインチキ拡張機能。以下は原理的にどうしようもない問題。:after疑似要素以外はサポートの目処が付いた。:selection等はこの実装だと実現してもあまり意味がないし、そもそもFirefoxではセレクタ自体が無視されてしまうので、実装はオミットしても良さげ。0.2.2007080702でダイナミック疑似クラスに対応した。無駄な文字列までコピーされてしまう問題は0.2.2007080101で解決した。以下はめんどくさいから実装をさぼってる部分。そのうちどうにかするかもしれないし、しないかもしれない。userContent.css内に書かれたtext-shadowの指定を読めない。0.2.2007080602で、userContent.cssで書かれた指定も反映するようにした。名前空間付きのセレクタに対応していない。ウィンドウをリサイズした時に自動で再描画しない。0.1.2007072902で再描画処理を入れた。mm、cm、pt、pcなどの絶対単位に対応していない。絶対単位は72dpi固定でとりあえずサポートした(0.1.2007073101)。ちなみにemとexの算出方法もいいかげんです。@mediaルールやなんかにも対応してません。0.1.2007072801で@mediaに対応した。セレクタの優先順位もまともに評価してません。0.2.2007080101で、セレクタの優先順位も計算するようにした。style属性で指定されたtext-shadowには対応してない。style属性での指定には0.1.2007072800で対応した。0.1.2007072802で複数の影の表示に対応した。Firefoxの仕様上の問題で3つ以上の指定は正しく認識できない。セレクタから要素ノードを選択する処理は、selector.jsを丸パクリ。組み込んでみたら予想以上にまともに動いてくれなかったので、半泣きになりながら修正してやっとちゃんと使えるようにした。