勝手に添削: Selection内のHTML Textをいい感じに取得する2010年02月05日 09時15分

というわけでやってまいりましたこのコーナー! 本日のお題は「Selection内のHTML Textをいい感じに取得する - 枕を欹てて聴く」でございます。選択範囲のHTMLソースを抜き出すというやつですね。では早速いってみましょう!

  if(src.focusNode){
    // selection

まずは HTML5 テキスト選択 APISelection オブジェクトが登場! 以後これに対する操作が続きます。しかしこの Slection オブジェクト、getRangeAt メソッドを使うとなんと選択範囲に対応する DOM 2 Traversal and RangeRange オブジェクトが取れちゃうんです!

    // common parent node search
    (以下 21 行省略)

それ Range#commonAncestorContainer で取れるよ!

      // common配下のindexを見て, focus と anchorがどちらが前方かを調べる
      (以下 9 行省略)

それ Range#startContainerRange#endContainer でわかるよ!

      // focusに沿って後方をremove
      (以下15行省略)
      // anchorに沿って前方をremove
      (以下11行省略)

それ Range#extractContents()Range#cloneContents() でできるよ!

というわけで不要な要素を除去する部分は置いといて今までの経過をまとめてみると、

function convertToHTMLString(source, safe) {
  if (!source || (source.getRangeAt && source.isCollapsed)) return '';
  var range = source.getRangeAt ? source.getRangeAt(0) : null;
  var node = range ? range.cloneContents() : source.cloneNode(true);
  if (safe) { ... }
  return new XMLSerializer().serializeToString(node);
}

なんということでしょう! コメント空行抜きでも 86 行あった部分が実質たったの 2 行に!

これに残った部分を付け足していくわけですが、出来上がった品はこちらになります。(お試しはこちら!)

まとめ

以上、もろもろの要因で無駄にハイテンションの nanto_vi (なんと) がお届けしました!

Firefox 3.6 での XPath による要素取得2010年01月24日 22時44分

Firefox 3.6 にしたら、動的に生成した文書からの XPath による要素取得ができなくなったという報告が挙がっています。

この原因は、Firefox 3.6 で HTML 要素の名前空間の扱いが変わったことにあります。Firefox 3.6 (Gecko 1.9.2) では、HTML5 に従い、HTML 要素が (XML 文書中でなくても) XHTML の名前空間 (HTML5 でいうところの「HTML の名前空間」) http://www.w3.org/1999/xhtml に属するようになりました。

これに伴って、これまでは XML 文書中でも有効だった、XPath 式の評価における HTML 要素の特別扱い (要素名の大文字小文字を区別しない、非修飾名を HTML の名前空間に属するものとみなす) が、HTML 文書中でのみ有効となったようです。なお、この特別扱いは、XPath 1.0 に違反しますが、HTML5 で認められています

document.implementation.createDocument(null, 'html', null) で作成されるのは XML 文書なので、接頭辞なしの XPath 式では HTML 要素を取得できなくなってしまいました。このことは、「HTMLDocument の動的な生成」でも、(こちらは Firefox 3.7a ですが) createDocument メソッドでの名前空間なし XPath の結果が×になっていることで確認可能です。

解決策としては、HTML 文書を作成するようにすればいい話です。これには XSLT の HTML 出力を使ってもいいのですが、なぜか今現在の Firefox nightly (3.7a1pre 20100123) ではこの方法がうまくいかないので、createDocument メソッドに文書型宣言と名前空間を指定するほうをおすすめします。

ちなみに AutoPagerize では document.cloneNode メソッドを使っていますが、これは読み込む文書が基本的に同じ Web サイト内のものであり、現在の文書が HTML 文書なら次も HTML 文書、XML 文書なら次も XML 文書と推定できるからです。XML 文書から HTML 文書を読み込む場合など、汎用性を考えるならやはり createDocument メソッドを使ったほうがいいでしょう。

Kanasan.JS Jetpack ワークショップ2009年12月30日 18時08分

Kanasan.JS Jetpack ワークショップに行ってきました。Jetpack は Firefox 用の簡易拡張プラットフォーム。私としては通常の拡張機能のほうが高い自由度を持てて好きなのですが、Firefox を広く一般に使ってもらうには、簡単なものを簡単に作れるようにするという点が重要なのでしょう。

最初に mollifier さんによる Jetpack 入門があった後、二人組になり各グループで Jetpack フィーチャーを作っていくという流れ。私は satyr さんとペアになったのですが、さすが satyr さん、ゴルファーだけあって見慣れぬ記法を次々と使ってきます。

var { href } = location;

上のコードは分割代入の省略形式で、

var { href: href } = location;

の略、さらには、

var href = location.href;

の略なのですが、JavaScript 1.8 以降 (Firefox 3 以降) での機能とあって、私自身も久しく頭から抜けていました。

そんなこんなで完成した (といっても実際のコーディングはほとんど satyr さんでしたが) のが、現在閲覧中のページの W3C Markup Validation Service での検証結果をステータスバーに表示する Jetpack フィーチャー、HTMLValidator for Jetpack です。

ちなみに開発中に引っかかったのが、特定の名前空間に属する要素の jQuery での扱い。http://validator.w3.org/check?uri=http%3A%2F%2Fnanto.asablo.jp%2Fblog%2F&output=soap12 のように output パラメータに値 soap12 を指定すると、検証結果が、

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Body>
<m:markupvalidationresponse env:encodingStyle="http://www.w3.org/2003/05/soap-encoding" xmlns:m="http://www.w3.org/2005/10/markup-validator">
    <m:uri>http://nanto.asablo.jp/blog/</m:uri>
    <m:checkedby>http://validator.w3.org/</m:checkedby>
    <m:doctype>-//W3C//DTD HTML 4.01 Transitional//EN</m:doctype>
    <m:charset>utf-8</m:charset>
    <m:validity>true</m:validity>
    ...
</m:markupvalidationresponse>
</env:Body>
</env:Envelope>

と XML 形式で返ってくるのですが、ここから jQuery で validity 要素を選択するには、res を返ってきた XML 文書ノードオブジェクトとして、

$(res).find("m\\:validity")

のように指定する必要があるのでした。

そもそも DOM の getElementsByTagName メソッドからして、引数に指定できるのは要素名 (非修飾名) のみと勘違いしていたのですが、実際は、名前空間に属する要素を選択するためには接頭辞も含めた修飾名を指定する必要があるとのこと。名前空間の指定に、語彙に対して常に一意な名前空間 URI ではなく、文書片ごとに変わる可能性のある名前空間接頭辞を用いるのは、大変気持ち悪いです。

初めての JavaScript 第 2 版2009年12月30日 17時07分

O'Reilly Japan から書籍『初めての JavaScript 第 2 版』(Shelley Powers 著、武舎広幸・武舎るみ訳) (Amazon) が出版されています。出版にあたって、私が技術レビューを務めさせていただきました。販促効果があるのかわかりませんが、帯に推薦文も寄せています。

単なる JavaScript の書き方にとどまらず、デバッガの使い方など基礎になる事柄を幅広く取り扱っていますので、JavaScript を始めたいという方は一度手にとってみることをお勧めします。また、周囲にそのような方がいる場合もぜひ勧めてあげてください。

読み終えた方は、『JavaScript 第 5 版』(Amazon) や『JavaScript: The Good Parts』(Amazon) に進むのもいいですし、Prototype.js などのコードリーディングをしてみるのもいいと思います。なお、ここで Prototype.js の名前を挙げたのは、次の二つの理由によります。

  1. ソースコードが比較的読みやすい。
  2. 既にコードリーディングを行った人が大勢いて、Web 上に多数のコード解説がある。

第 2 回 WCAG 勉強会 @ 関西2009年12月30日 16時23分

先日開かれた WCAG 勉強会 @ 関西 (Twitter) の第 2 回勉強会に参加しました。

WCAG 2.0 とは

Web アクセシビリティに関する指針です。W3C が発効しており、本文といくつかの関連文書からなります。これを基に JIS X 8341-3 (Web コンテンツ JIS) が改定される予定です。

Web Content Accessibility Guidelines (WCAG) 2.0 (日本語訳)
ここでは「本文」と呼びます。4 つの原則と 12 の指針からなりますが、要点だけ書かれているのでやや読みづらいです。
Understanding WCAG 2.0 (日本語訳)
本文の各指針に対して、そのような指針を設けた意図や、補足の説明、個々の事例などが書かれています。「解説書」と呼ばれますが、こっちこそ本文という感じです。
Techniques for WCAG 2.0
HTML や JavaScript といった既存の技術を、どう使えば各指針に対応できるのか、また逆にどう使うと指針に対応していないとみなされてしまうのか、が記述されています。「技術書」と呼ばれます。
How to Meet WCAG 2.0
「クイックリファレンス」とも呼ばれます。使用する技術や達成水準を指定することで、各指針に対応する本文、解説書、技術書の項目を探し出せます。

本文は時代の変化にも対応できるように書かれていますが、解説書や技術書は一般的な環境の移り変わりにつれて随時更新されるかもしれないそうです。

勉強会の流れ

今回の範囲は「原則 1: 知覚可能」の「ガイドライン 1.1: 代替テキスト」までで、事前に本文と解説書の該当箇所を読んでおくこととなっていました。当日は、各自が範囲内の事項に関する疑問点を、付箋紙に書き出してホワイトボードに貼り付け、それらをひとつずつ、あるいはいくつかまとめて全員で議論するという形でした。

Kanasan.JS でもそうですが、全員でひとつのことについて議論するというのは、一度にさまざまな視点が得られて面白いです。

メディアと代替テキスト

ガイドライン 1.1 代替テキスト:すべての非テキストコンテンツには代替テキストを提供して、拡大印刷、点字、音声、シンボル、平易な言葉などのような、ユーザが必要とする形式に変換できるようにする。

ここでいう「代替テキスト」とは、あるメディア (媒体) から別のメディアに変換するための、中間メディアのことです。画像から点字へ、音声から字幕へ、直に変換できれば苦労はないのですが、現状ではそれが困難なため、テキストというメディアを用意することで変換にかかる負担を軽減しようというのです。

この変換は、必ずしも自動で行われるわけではありません。一定の精度を確保するためには人力での変換が必要、ということもまだまだ多いようです。

シンボルメディア

メディアの例として「シンボル」とありますが、これはアイコンやピクトグラムの組み合わせなどで文意を表すことを指すようです。実際にアイコンを並べてニュースを伝えるニュースサイト (サンプルページ、PDF) もあるほか、漫画の新聞も一種のシンボル化ではないかと思います。

感覚的なコンテンツ

WCAG 2.0 では、特定の場合には中間メディアたる代替テキストを提供しなくてもいいとされています。そのひとつが感覚的なコンテンツで、たとえばコンサートの動画があったとき、最低限「そこに動画がある」「それはコンサートの動画である」といったことが識別できる代替テキストがあればよく、「そのコンサートを聞いてどう感じたか」などの主観的な情報は必ずしも含む必要はありません。

類似文字の使用に関する注意

技術書で失敗例として挙げられているのが、代替テキスト無しでの類似文字の使用です。これは、ある文字の代わりに見た目のよく似た文字を使うことで、ひらがなの「し」の代わりにギリシャ文字の小文字イオタ (ι) を使う、漢字「神」の代わりにカタカナと漢字を並べて「ネ申」と書く、といった例があります。このことは、文字を直接ソーステキストに埋め込んだ場合だけでなく、HTML の文字参照や JavaScript のエスケープシーケンスなどで間接的に埋め込んだ場合にも当てはまります。

ただし、何が何でもダメというわけではなく、適切な代替テキストが指定されていればいいようです。技術書には、代替テキストの指定方法として、abbr 要素とその title 属性を使った例が載っています。

<abbr title="化物語">イヒ牛勿言吾</abbr>

アクセシビリティ・サポーテッド

WCAG 2.0 での重要な概念が「アクセシビリティ・サポーテッド」(本文解説書) です。これは、コンテンツが実在の支援技術 (拡大鏡、スクリーンリーダ、代替ポインティングデバイスなど) で利用可能でなければいけないということで、技術書の中にも特定のブラウザや支援技術に関する注意書きが見られます。

点字ディスプレイ

持ち運びできる円盤式点字ディスプレイがヒットしているそうです。あらかじめテキストを記憶しておいて電車の中で読むといったことが可能で、音声よりも速く読めるとか。

音訳マニュアル

代替テキストを点字や音声に変換する際の指針として、音訳マニュアルが役に立つそうです。点字では、単に読みをそのまま抜き出せばいいというわけではなく、「橋」「箸」「端」はそれぞれ区別がつくよう説明を加えるなど、さまざまなノウハウが必要とされるようでした。

ナビゲーションスキップ

サイトのヘッダやサイト全体にまたがるナビゲーションなど、ページの本文とは関係ない部分を読み飛ばせるような仕組みをブロックスキップといいます。ブロックスキップの実現手法の一つとして、ページの先頭に本文へのリンク (視覚メディアではしばしば非表示にされる) を付けるナビゲーションスキップ (スキップリンク) があります。

しかし、少なくとも勉強会参加者の周辺では、ナビゲーションスキップを使っている人はいないようでした。ナビゲーションスキップはサイトごとに異なるので使いづらい、Yahoo! や Google などよく見るページでは本文より前のリンクを飛ばす操作に慣れている、適切な見出しと支援技術の見出しジャンプ機構があれば十分、といった背景があるそうです。

雑感

実際に業務として Web アクセシビリティに携わっている方々の話を聞け、大変参考になりました。知らないこと、わかっていなかったことがほとんどで、まさしく聞くと見るとは大違いです。Web 製作に関わる方々はこの勉強会に参加して損はないと思います。

Web アクセシビリティと聞くと、ぽっと出の新しくてよくわからないものと思う方もいるかもしれませんが、障害者が情報に触れる手段に関しては古くからさまざまな試みがなされてきたこと、そしてそれらの積み重ねが Web にも応用できるという点は非常に重要なことだと思います。アクセシビリティを何か特別なものとみなすのではなく、ノウハウの蓄積された、すぐそこにある日常として受け入れることが大切です。

関連リンク