hypertext

rel-nextとページングナビゲーション

制作者の意図を優先すればどんな定義でも正しい。が、ここではユーザの期待に基く定義について書く。

引用するのは文章 - Weblog

人間に読ませるならば、日附の過去に向かつては PREV (前へ)を出力するのが自然。この Weblog のページ捲りナビでは、PREV で古い日附の記事が「現れる」ようにしてあります。

この人のブログのトップページでは、1ページ目から2ページ目に向けてrel-prevが向けられ、2ページ目から1ページ目に向けてrel-nextが向けられているが、私はこれをまったく自然だとは思わない。人間が眺める順序、あるいはクローラが辿る順序を考えれば、ページ番号が進む方向にrel-nextが向けられるのが自然だ。なぜなら、その一連の文書群は記事の集合ではなくページの集合であり、ナビゲーションが指向しているものは時間軸の移動ではなくページ捲りだからだ。個別記事におけるnextは新しい記事でよいが、各ページにおけるnextは時間軸とは関係なく、次のページに向けられるべきである。

あるいは、系列における最初の文書を考える。記事集合における最初の文書は一番最初に書いた記事である。rel-nextは次に書かれた記事に向く。同様に、ページ集合における最初の文書は1ページ目である。rel-nextは次のページに向く。ここで、2ページ目から1ページ目にrel-nextが向けられた場合を考える。すると、最初の文書は最後のページ、たとえば50ページ目となる。これは明らかに不自然だ。この場合、(出力されるページ数に上限がなければ)ページ数の増減に従って最初の文書のURIが移動することになる。起点が移動するのは妙だ。

「個別記事とページングで時間軸の向きが異なるのは不自然だ」という主張があるかもしれない。しかし、この手の形式的なルールは、多くの場合作者以外には考慮されないものである。各文書の目立つところにきちんと示しでもしない限り、その有効性は極めて薄い。記事集合とページ集合をきちんと区別して、それぞれの系列に合わせた指定をすべきである。

いづれにしてもタイムスタンプを識別するだけの手間なので、職業プログラマなら、まあ、誰にでも出来る。

タイムスタンプを比較するだけの簡潔な定義が、常にユーザの期待と一致するとは限らない。どうして人間の考えることなのに、こんなにもシステマチックなのだろう。Webにはnextのない「1ページ目」が多すぎる。私にはそのことが不自然に思えてならない。

文書群をどう並べるか

ページの並びならページ番号順に並べるのが自然。記事の並びなら記事が公開された順序に並べるのが自然。月別にまとめたものの並びなら月が進む順序に並べるのが自然、である。その文書が何の並びにあるのかユーザが把握できないのであれば、それは文書の書き方が悪い。

また、「previous page」は「過去のページ」を意味しないし、日本語でも「前のページ」は「過去のページ」を意味しない。人間が束ねた資料を読み進めるとき時間軸を考慮することは稀であり、機械生成された文書群でもそれは同じである。50ページの次を読もうとして49ページが出てくる仕組みが自然なわけがない。

仕様書に時間軸についての言及がないのだから、それぞれについての本質的な並びを採用すればいいだけだ。本質的な並びがない文書群は、そもそも順序付けをする必要がない。

「2ページ目は過去だから前ですよ」なんて定義は無意味だ。2ページ目はページである限り、1ページ目の次でいい。実際、ユーザは2ページ目に読み進めようとしているのだ。時間軸は問題ではないし、時間に関係のないページ集合の場合と同様に扱われるのが自然だ。ブログシステム限定のルールは用をなさない。

rel-nextとページングナビゲーション (2)

基本設計 - Weblog

「ページ捲りナビゲーション」を時系列を基に設計するのは誤りである。このブログではと言っているが、ユーザが見ているのはあなたのブログだけではない。あなたがあなたのブログにおいてどう設計したか、どう統一したかはユーザからすればどうでもいいことだ。ブログかどうかすら、問題ではない。一貫して居る方が利用者にも分かり易いというが、その利用者というのは通りがかったユーザのことではなく、極端に言えばブログを管理しているあなたのことでしかない。全体として同じ方針に基づいて設計されて居る事が大事と言うが、全体が指すのが個々のブログでしかないのなら、それは単なるローカルルールである。

そこで、私は「ページ捲りナビゲーション」を用いるユーザの期待を基に考えよ、と言っている。「ページ捲りナビゲーション」を利用するユーザはページを捲ろうとしているのだから、ページ番号が進む順にページ捲りが行なわれるのが直感的であり自然だ。「次」は時系列と関係なくページ番号を基準として定められるべきである。

つまるところ「前=過去」の人は、例外なく「ページ捲りナビ」と言いつつページを捲るナビゲーションを指向していない。その一方で、ページ番号を振り、順序付けし、ページの集合であるように見せる。当然騙されたユーザは混乱するわけだが、この手の人は「いやいや、このブログでは前=過去で統一されているのでprevを選んでください」と真顔で言う。ここに時系列が現れること自体が不自然なのだが、氏の言う「プログラマの論理」に毒された人間は規則的であるということに安心して、合理的だと言って憚らない。しかし、「前=過去」に統一したいのなら、ページ番号も過去のものから順に振っていけばよいのではないか。最も古いページを1ページ目とし、トップページを50ページ目とすればよい。ところが、彼らは1ページ目を最も新しいものとする。基準がばらばらなのである。その結果、時系列による並び換えを可能にしただけで、論理は破綻する。氏はそれを直視できないゆえに、「例外」と言ってごまかしている。この場合も時系列のソート順に応じてnextとprevが入れ替わるようにすれば「例外」は起こらないのだが、そのような形式的な統一にユーザの視点から見た益はなく、たかが一属性のソート順によってナビゲーションの向きが変わるということ自体が不自然なのである。そもそも、各ページが時間情報をもっているかどうかすら一般には不定である。たとえば適合度によってソートされた検索結果ページの場合、各アイテムの時間情報はばらばらで、規則的ではない。たまたまブログが時間に関して規則的であるというだけで、ならばブログに限定した定義を採用したところでユーザは混乱するだけだ。ブログの特性に依存した定義を与えるべきではない。

人間が読むナビの話か、機械が処理するナビの話か、どちらなのですかという問いについて。私は機械が処理するナビ、具体的にはrel属性について言っている。が、氏はどうも機械に処理させるのもまた人間である、ということを考慮していないように見える。たとえばOperaのナビゲーションバー、Firefoxの同種Add-on、あるいは単純なブックマークレット、これらを操作するのは人間だ。そもそも、本文中に含まれるナビゲーションはこれらによって実現される機能が多くのブラウザに欠けているために存在するものである。ゆえに両者に本質的な違いはない。あるのは機械的な操作に利用されるか、人間が文字として認識するかという違いだけだ。もっとも機械的な操作に利用される場合でも、ナビゲーションバーのように視覚的に訴えるものであれば、それは「人間が見るナビ」であるといえる。範疇も概念も変わらない。区別する必要がないのだ。

氏は「previous」と言えば過去だ、歴史的にそうだ、常識的にそうだと主張するが、「previous」は常に「過去」を意味しない。「previous」が意味するのは「一連の系列における前」であって、一連の系列を時系列に固定するのは正しい解釈ではない。そこで一連の系列が何かを考える必要があるのだが、私はそれがページ捲りの場合はページ番号だと言っている。何より氏自身が「物理的な次のページ」という言葉を用いているのだから「物理的な前のページ」もあるはずで、私からすれば物理的も何もそれらは単純に次・前のページであるし、わざわざ直感に反する再定義をする必要もない。

氏の「一貫した設計」は、利用者主導でも何でもない、単なる設計者の独り善がりである。もっとも独り善がりであろうと何だろうと、仕様書を基準とすれば間違いにはならないのであるが、それを「利用者主導」としプログラマの怠慢を問う氏の主張には異を唱える。個々のブログの範囲で統一するのではなく、ブログであろうと検索結果ページであろうとページ捲りが一様にページ捲りとして機能するように統一するのが、利用者主導というものだ。

余談

氏のブログのトップページに限って話をするなら、「過去の3件」にも「前の月」にもrel-prevが向いている時点でトップページが何の系列にあるのか曖昧で訳がわからない。rel属性は現在の文書に対する関係を表すものであり、近くに並べられたリンクと比較した関係を表すものではない。HTML 4.01仕様書のリンクについての章にもlink要素に対してはDocument relationships、a要素のrel属性に対してはthe relationship from the current documentと明記されている。つまりトップページが表示する「最新の3件」に対して「前の月」は文書レベルでの関係がないという点で不適切な指定なのだが、過去・未来を形式的に置換するからこういうことになるのだろう。

DOM-Level-3-XPathについて

どうしてDOM-Level-3-XPathはevaluateする際、expression中のUnprefixedNameに対してprefixを空文字列(もしくはnull)としてresolverを呼ばないのだろう。XPathEvaluator#createNSResolverも同様に空文字列に対して第一引数contextにおけるデフォルト名前空間を返すresolverを生成するようにすればよいと思うのだが、こうしたとき何が不都合となるのかがわからない。

XML Path Language (XPath) # 2.3 Node Tests

A QName in the node test is expanded into an expanded-name using the namespace declarations from the expression context. This is the same way expansion is done for element type names in start and end-tags except that the default namespace declared with xmlns is not used: if the QName does not have a prefix, then the namespace URI is null (this is the same way attribute names are expanded).

XPath 1.0仕様では「ただしxmlns属性で宣言されたデフォルト名前空間は使用されない、接頭辞がない場合の名前空間URIはnull」とされている。要はこれに従っているものと思われるが、何故わざわざexpression contextのデフォルト名前空間を無視するのだろう。expressionをcontextに依存させたくないということだろうか?しかしデフォルト名前空間のみを例外としたところでPrefixedNameは変わらずcontextに依存するのだから、これは理由にならないはずである。まったくもって謎だ。

具体的な誰かが見えるようになったらおしまい

ユーザビリティを考えるにあたって「具体的な誰かを想定する」というのは有効だと思うが、コンテンツに関しては「具体的な誰かが想定される」ようになったらおしまいだと思う。mixi、Twitterその他ウエッブサービスはそのほとんどが周囲のユーザに向けた行動を促す機能を内包しているゆえに、外から見るとつまらない。最近は、特定の友人とのコミュニケーションのためだけにブログを使うような人はどんどんmixiやTwitterを使えばいいと考えるようになった。

早く「ブコメ(笑)ブコメレス(爆笑)メタブクマ(核爆)URL短縮サービス+一言(超新星爆発)」みたいな空気になってほしい。ああいうのを、「外の人」が気にする必要はない。コミュニティを指向するなら、コミュニティらしく外部から分断されればいいだけだ。そして分断を受け入れられる者が、それを選べばいい。

TeXコードをMathMLノードに置換するJavaScript「ASCIIMathML.js」を見つけた

ASCIIMathML: Math on the web for everyone

複雑なMathMLコードを直接ソース中に書くことなく、MathMLノードを表示できる。クライアントサイドで変換するのが適切かどうかという問題はあるが、すばらしい。Editorを使って変換されたMathMLコードを得ることもできる。

同作者による「ASCIIsvg」というスクリプトもある。こちらはスクリプトコードからSVGによるグラフを生成する。

自分では試していないが、クライアントサイドではなくローカルでTeXコードをMathMLコードに変換したい場合は「itex2MML」が使えるようだ。

リクエストされたリソースが存在しないときリダイレクトするWebサービス

たとえばURIのアカウントIDの部分を存在しないIDに置き換えたときとか、年月としてYYYYMMを取る部分でYYYYだけを入れたときとか、何でリダイレクトするんだろう。要求されたURIに対するリソースが存在しないなら404 Not Foundを返せばいい。404を返してリソースが存在しなかったことの説明と、そのサービスのトップページなりユーザレベルでのブログのトップページなりへのリンクアンカーを見せればいい。何でリダイレクトするんだ?リダイレクトしたら、クライアントは「要求したリソースが存在しなかった」という結果を理解できない。閲覧者はいつのまにか開いておいたタブがトップページになっていて戸惑う。そしてどこから転送されたのかも知ることはできず、ただ意味もなくトップページを見せられ、そこには何一つ要求したリソースに関する情報がない。このようにする意味がまったく理解できない。何なんだ?SEOか?GoogleがそのURIへの参照を転送先のURIへの参照と等価なものとして計算するようにするためか?もしそうであるなら、それはスパム行為であると言うほかない。

RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1 # 10.3.2 301 Moved Permanently

The requested resource has been assigned a new permanent URI and any future references to this resource SHOULD use one of the returned URIs.

RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1 # 10.3.3 302 Found

The requested resource resides temporarily under a different URI. Since the redirection might be altered on occasion, the client SHOULD continue to use the Request-URI for future requests.

301 Moved Permanentlyも302 Foundもリソースが存在しなかったときにページをrefreshさせるステータスではない。Googlebotを誘導するためのステータスでもない。URIの恒久的、一時的な移動を示すステータスだ。存在しないアカウントIDや不適切な年月が指定された場合は、要求されたリソースが移動しているのではなくもとから存在しないのだから404を返すべきである。例外処理としてリダイレクトを用いるのはおかしい。

RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1 # 10.4.5 404 Not Found

The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent.

余談

ただしログインしなければ表示できないリソースがログインしていない状態でリクエストされたとき、ログインページへ303(302)するのはありだろう。この場合はリソースがログイン状態によっては存在しているという点で上記のケースとは異なる。この場合は404(存在しない)も200(成功)も401(要Basic認証)も適切ではない。

Twitter嫌い

本当にあの人がTwitter使うようになったら終わりだなと思う。Twitterユーザを全員アクセス禁止にしたい。follower・非followerとかどう考えても「無意識に他人を蚊帳の外に置く」システムそのもので、私はそういうシステム・空間・人に関わりたくないし、そういうシステムに参加しない人が割を食うようにはしたくない。「誰でもできるんだからすればいい」とか、どうして言えるんだろう。現実は「誰でもできるんだからしないと不利」になっていて、従わなかった人間が損をしていくようになっている。従う必要なんてそもそもないにも関わらずだ。そういったシステムをまた一つ生産し、支え、維持する存在というものを拒否したい。


「独り言」で喧嘩を売られた。

OperaのShift+BackspaceはFastForwardにもなる

進めないときにShift+Backspaceを押すとFastForwardが動く。わざわざ最下部までスクロールしてSpaceを押す必要なかった。この機能は新しく開いたブログ記事の続きを読むのに便利。

w3mでTwitterにアクセスすると406 Not Acceptableが返される問題の解決法

Acceptヘッダにワイルドカード抜きのtext/htmlを追加すれば200を返すようになる。Twitterサーバはtext/*を理解できないらしい。

深江直人(カッペ)さんのサイトをGoogleの検索結果から消す

-filetype:aspx

とりあえずaspx以外を見て、巻き添えが気になったときだけマイナスを取ってaspxなリソースを検索し直している。

ひどいCSS画像置換

はてなブックマークのエントリページに「コメント表示/非表示の切り替え」とかいうボタンが増えているのに気づいた。のだけど、spanの中にテキストを置き、そのテキストをtext-indentで吹っ飛ばし、background-imageでアイコン画像を背景に指定することで「画像ボタン」が表現されていて最低だと思った。と言っても何がダメなのかわからない人が多いのだろうけど、これは要するに「画像を見れば何をするボタンかは当然わかるでしょう」という制作者の態度を表している。説明のためのテキスト(=「コメント表示/非表示の切り替え」)はSEOと制作者の負担削減のためだけに与えられており、ユーザがそれを知るにはFirebugをインストールする必要がある。もちろんDOM Inspectorでも管理者ツールでもCSSオフでもソースを直接読むのでもいいが、いずれにせよそのままではテキストは製作者によって-9999px左に移動されられており、ツールチップやステータスバーなどの標準的な方法でそのテキストを得ることはできない。さて、ユーザはどうやってそれが何をするボタンか知ればよいのか。押して推測しろとでも言うのだろうか。開発ブログのログを読め、ヘルプを見ろとでも言うのだろうか。ひどいUIである。

しかし何故img要素で画像を埋め、alt属性に吹っ飛ばしたテキストを入れ、title属性に何をするボタンであるかの説明を書く方法を選ばないのだろう。最初はCSS Spriteのために仕方なくやっているのかと思ったがそのようでもなく、本当に「検索エンジンにテキストとして見せるため」「HTMLに触らずに画像情報を管理するため」だけにやっているようだ。改善を望みたいが、この会社は以前からインプットボックスをただのテキストのように見せる「騙しUI」を作っていたりするのでまるで期待できない。潰れるまで続くのだろう。

Googleカスタム検索を利用して「二次情報除外検索」を作った

二次情報除外検索

ソーシャルブックマークなどを除外しまくるカスタム検索。デフォルトの検索言語がEnglishなので、日本語での結果を出したいときはパラメータからhl=jaと指定する必要あり。現時点での除外リストは以下。

wiki.livedoor.com/word/*
tech.newzia.jp/*
synclick.jp/*
blog.fc2.com/tag/*
builder.japan.zdnet.com/tag/*
keyword.livedoor.com/*
k.hatena.ne.jp/keywordblog/*
www.blogpet.net/bookmark/*
seo.kndb.jp/*
www.choix.jp/*
mark.jolt.jp/*
*.rightclicksright.org/*
*.pg-feed.com/*
*.rightclicksright.net/*
*.designmasterdatabase.net/*
*.designlinkdatabase.net/*
*.designrecipedatabase.net/*
*.designiddatabase.net/*
*.thumbnailcloud.net/*
*.basefeed.net/*
bookmark.goo.ne.jp/*
pookmark.jp/*
bookmarks.yahoo.co.jp/*
bookmark.fc2.com/*
1470.net/*
faves.com/*
swik.net/*
buzzurl.jp/*
clip.nifty.com/*
clip.livedoor.com/*
b.hatena.ne.jp/*

ユーモアについて

己の無神経さをユーモアだと言い張る人というのは想像以上に多くいるものらしい。彼らにとって嫌みとユーモアは同じもので、そこには何の機知も機転もない(正確には機転を利かせたつもりでいる)。そして、その嫌みに喜ばない人間を「センス」がないと言う。

location.hashにページ番号を「代入」するJavaScript製スライドショーが嫌いだった

ブラウザ履歴がフラグメント違いの同一文書で埋まるのを体験するたびに頭にくる、どうしてlocation.replace()を使わないのだろうか……と以前は思っていたが、彼らがそんなことを心の底からどうでもいいと考えているように、私自身も最近はどうでもいいと考えるようになった。

mayokara <http://mayokara.info/>