var start = new Date().getTime();
var data = [{file:"test.htm",title:"ファーストポスト",mtime:1138748434,ctime:1138748434,body:"あーまあね。いろいろあったよいろいろ。いろいろね。いろいろ"},
{file:"autolink.htm",title:"自動リンク",mtime:1102336142,ctime:1102336142,body:"自前のフィルタ作った。改行をbrにするだけ。あとは関連リンクの作成。タイトル調べてエントリ名が入ってたらリンク付記する。マウスオーバーでハイライト。ファーストポスト、こんな感じ。"},
{file:"js_encode.htm",title:"JavaScriptで文字コード変換",mtime:1102340462,ctime:1102340462,body:"http://nurucom-archives.hp.infoseek.co.jp/digital/escape-codec-library.html理論上できるのはわかってたがほんとに作ってる人いたのか。ネタ元http://www.horaguchi.net/article.php?q=685"},
{file:"internetweek2004_wiki.htm",title:"wikiの今後",mtime:1102343486,ctime:1102343486,body:"黙殺されてるのかと思ったらレポートが載っていた。http://bb.watch.impress.co.jp/cda/event/7742.htmlhttp://pcweb.mycom.co.jp/articles/2004/12/06/internetweek/wikiにビジネスモデルという言葉は疎遠だ。あーしてこーして金が儲かるといった、わかりやすい成果は期待できないが、情報共有が生産性を上げて、経費を削減するというのは確かだ。Wikiを導入することで得られるメリットと、導入にかかるコストを正確に計算できるやつがいねーから、たぶんいつまでもこんなんなんだろう。"},
{file:"diary_200412070358.htm",title:"[Blog] サムネイルの自動作成",mtime:1102359522,ctime:1102359522,body:"MTはなんだかややこしくなってるし、ダウンロードするのに登録とか必要になっていたので、blosxomを使うことに決まったわけで。以前書いたスクリプトをちょいと流用、まだ最低限の機能しか実装していない。せっかくなのであまり他で見かけないような機能を実装してみようかと思う。大まかな案としては。-文中のリンクを抜き出して-自動でタイトル取得とサムネイル画像を生成-最近言及されたページを画像で一覧表示、JavaScriptでの検索など便利なモジュールが色々見つかったので割と簡単に出来そう。"},
{file:"diary_200412070435.htm",title:"とりあえずの予定",mtime:1102361711,ctime:1102361711,body:"もうね、何だかんだでBlogでしょ。とりあえず適当なツール書いてアップすんにも何かと都合がよさそうなのでBlogでも書いておくかな、みたいな感じで。バグ報告とかバージョンアップとかメンテナンスとかその他もろもろも全部Blogで、みたいな。まあそんなところで。個人的にちまちまと書いているものを、発表していけたらと思ってたりします。短期的プロダクツ-このBlogのカスタマイズ(適度に)-コードネーム BlindBind長期的プロダクツ-最強のWikiエンジン-横断検索エンジン詳しく説明しようとすると大変なので適当に。BlindBindは今までにない(少なくとも自分は聞いたことない)種類のソフトウェアで、需要が多きい(はずなのだが誰も必要としていない)ソフトウェアです。なんのこっちゃ。Wikiとか検索については蔵出ししてないようなアイディアがいくつもあり、ただ、どうせなら言葉で書くよりも動くもんで見せたいという欲求があり、ちまちまと書いていたりします。"},
{file:"diary_200412090513.htm",title:"キーワード",mtime:1102536886,ctime:1102536886,body:"リンクの管理、キーワードを使うべきだろう。例えばWiki風に[[]]でリンクすべき単語を囲うことで明示的なリンク。単語登録され、リンク先アドレスを設定する。その語句が他のエントリ内に存在していればキーワードのオートリンク、明示的ではないリンク。みたいな。サムネイル自動化機構が大体、見えてきた。半自動化というべきか。Win32::CaptureIEを使っている。"},
{file:"diary_200412090523.htm",title:"[Perl] Class::DBI",mtime:1102582678,ctime:1102582678,body:"最近作ったものに。Class::DBIからDBD::Googleを呼び出すという検索スクリプト。ここまで抽象化できるとなると、使い方も変わってくる気がするのだ。GoogleAPIに手を出すと、Googleの機能を使うことに夢中になってしまいがちなのだが、DBD::GoogleというモジュールはGoogleへのアクセスをデータベースドライバとして実装している。そしてClass::DBIはデータベースをオブジェクト構造として扱うことができるようになる。Class::DBI::Cacheableというのと組み合わせれば透過的キャッシュを利かせられる、ネットワーク越しのGoogleへのアクセス回数を減らし、応答速度を高められるだろう。もはやなにがなんだか。何かしらついでにGoogleの検索結果を表示するようにしてみたい。と思ったら。Class::DBI::Cacheableはretrieveのオーバーライドのようだ。複雑なクエリーの場合は使えない。やはり自前でキャッシュ管理すべきか。"},
{file:"diary_200412100448.htm",title:"[Perl] WWW::Google::PageRank",mtime:1102621688,ctime:1102621688,body:"WWW::Google::PageRankはGoogleツールバーからのアクセスを再現してウェブサイトのページランクを取得してくれる。Google的にアリなのかどうかはわからんが、特定用途、主にGoogleのページランクが知りたいときなどに役に立つ。被リンクやトラックバックなんかをページランクでソートできたら面白いんじゃないかと思ってみたり。"},
{file:"diary_200412100519.htm",title:"Bloglines",mtime:1102623597,ctime:1102623597,body:"日本語対応きっかけに少し前から使っているのだがさすがに使い勝手がいい。改善の余地は大いにあるけれどよく考えられてる。P2P使ったスマートな負荷分散やらキャッシングやらが普及しない限りはRSSリーダーはウェブサービスとして実装されるほうが受け入れられるのだろうな。データを自分のマシンに蓄積しておきたい、という需要もあるのだが、件数が増えるとさすがに巡回もつらくなってくる。APIで更新日時付きのRSS一覧が取得できれば最高なんだが。WEBに埋め込むにしても単に一覧出しただけじゃ面白くない。やっぱ自前でアンテナ実装しようかな、という気もしてくる。"},
{file:"diary_200412110231.htm",title:"Googleに入力補完機能",mtime:1102701544,ctime:1102701544,body:"http://www.google.com/webhp?hl=en&complete=1時期Googleに備わるであろう単語補完＆件数表示機能。まるで魔法のようだが、バックグラウンドでXMLHTTP通信をしている。XMLHTTPはJavaScriptから特定のアドレスに任意のデータをPOSTしたり、同じドメイン内のXMLデータを取得したり出来る。フォームを送る警告とか通信中の表示がまったくでないわけで、XMLHTTPを使ったキーロガーなんてのを作ったことがあったが、さすがGoogle、これぞまっとうな使い道だ。XMLHTTPはOperaで使えないのが問題だったんだが、最新版のOperaはXMLHTTPが使える模様。まあ、Googleがこんな機能つけたらOperaの方も対応せざるを得ないだろう。似たようなのものに。http://asp03.infosign.co.jp/~saida/mt/index.php?p=104Blogのインクリメンタル検索、動的ロードしている。http://blog.bitflux.ch/文字が追加入力された場合にリクエストしているようだ。----Googleにいついてもう少し詳しく調べてみた。入力に変化があるたびに問い合わせている模様。一度補完された検索ワードについてはメモリ内の変数を使って、存在しなければ問い合わせ、負荷対策もちゃんと考えてある。補完候補と検索件数だけでいいので通信量はさほどでもない。GoogleAPIを使って検索する前に検索件数がわかるような検索フォームを作ったら面白いんじゃないかと考えていたが、こういった補完候補並べるようなのはGoogle自らじゃないとできないな。太刀打ちできない。----日本語対応の可能性は？現時点では完全未対応。IME変換前のデータなんかを逐一送られても困るだろうな。まあ類似キーワード自動判別して動的ロードしてキーボード操作で選択、ぐらいなら結構楽に作れそうだ。作ってみようかな。"},
{file:"diary_200412112154.htm",title:"[JavaScript] 実用的なエディター",mtime:1102769691,ctime:1102769691,body:"JavaScriptで書かれた化け物みたいなアプリケーションにhtmlAreaというのがあるのだが、WYSIWYG編集よりも、きちんと実用的なエディターを作る方が良いんじゃないか、とも思う。WYSIWYGは確かにわかりやすいし、簡単に実装できるが、それよりも、構造化された文章をきちんと書きたいのだ。アンドゥ、リドゥ機能。その場でのプレビュー。行番号表示、アウトライン解析、辞書補完、GREP編集。GREP編集てのは単語が含まれてる行を抽出してそれをそのまんま編集できるような機能。なぜか見かけない。あったら絶対便利だろうに。Suffix Array に関する論文を読んでいてhttp://namazu.org/~satoru/sary/JavaScriptを使ったDiff出力を高速化する方法を思いついた。速度によっては実用的に使えるものになるかもしれない。"},
{file:"diary_200412112214.htm",title:"悪のJavaScript",mtime:1112080674,ctime:1112080674,body:"結構やばめのスクリプトを書いた。ユーザビリティの向上に役立てたいのだが、悪いことにも使えてしまう。は、タイピングの軌跡まで再現できるようなチャットを作ろうとして、それの材料として作った。まあそのうち公開できるかもしれない。"},
{file:"diary_200412131612.htm",title:"JavaScriptを使ったやや高速なDiff概要",mtime:1102921930,ctime:1102921930,body:"多分もっとちゃんとしたアルゴリズムがあるんだろうけど適当に思いついたので書いてみる。配列new_lineとold_lineの比較。まず、先頭キャラ1文字をキーにした連想配列を作っておく。例えばAで始まる行の行番号が2,4,6だったとすると。AのcharCodeが65なので。 old_first_char[65][0] = 2 old_first_char[65][1] = 4 old_first_char[65][2] = 6こんな具合の配列ができる。同様に、新しい配列のAで始まる行も調べておく。互いの「A」で始まる行のうち0～3番目の行番号の内容を比較する。 old_line[old_first_char[65][0]] と new_line[new_first_char[65][0]] を比較する。 old_line[old_first_char[65][1]] と new_line[new_first_char[65][1]] を比較する。new_first_char[65] = [2, 4, 6]だったとしたら、たった3回の比較で終了する。文書が殆ど変更されていない場合は、n回のループで比較が終了することになる。典型的な富豪的スクリプターなのでオーダーlogだのnmだのn^2だのとか良くわかってないが、多分こんな感じ。単純にループさせると9行の場合はループ回数9*9で81回。先頭文字がAAABBBCCCなら最大(3*3)*3で27回ですむ。短い文章の場合はonkeyupで処理しても負担は少ない。インクリメンタルDiffだ。テキストエリアの編集の場合、エンター押すたびDiff取るのが良いかもしれない。ただ、JavaScriptは大きな配列を扱おうとすると、とたんに遅くなるのが困り所。まだアップしてないネタがたまってきた。アップするのが面倒くさい。"},
{file:"diary_200412131654.htm",title:"Google Suggestをいかにパクるか",mtime:1102925971,ctime:1102925971,body:"単純に補完機能を実装するだけであれば、RandomNoteのようなユーザーの検索クエリ、全文検索結果の件数をキャッシュする機構を備えれば、わりと簡単に作れるだろう。検索ヒストリをインクリメンタル検索するだけでいい。これを「手法A」と呼ぼう。呼ぶことにする。----ユーザーの入力した語句から取ってくるのが一番楽ではあるけれど、Googleのやっていることはそれだけではない。Google Suggestがいかにしてその語句を選び出しているのか、というサーバーサイドの処理に関しても、もっと注目を集めていいのではないかと思う。例えば「GoogleといえばToolbar」のような連想は、単純に検索結果が多い順ではなく、その語句に対して関連付けられた単語のうちで特徴的なものを検出し、それらをランク付けした結果だろう。検索されたキーワードを人気キーワードのランキングとして公開する手法はかなり前からあったが、単語同士の関係性まで含めて統計として利用している点が目新しい。----GoogleとAmazonはデータマイニングの最先端にあって、両極だ。両者とも大量に蓄積されたデータベースから有用な情報を効率よく取り出すことで利益を上げているが、その方法論は全く異なる。手法AはAmazonのA。手法GはGoogleのG。Amazonはユーザーの行動、購入履歴からあなたにお薦めの本を見つけ出すが、Googleであれば、本の中身を全文検索してあなたにお薦めの本を見つけ出すだろう、ということだ。Amazon的な、Googleがあれば-このリンクをクリックした人はこんなサイトも見ています。-もっともお気に入りに追加されているサイトを上位に表示。-この語句で検索した人は、こんな語句でも検索しています。プライバシー云々の懸念はあるものの、手法Aを使うメリットは大きい。莫大な計算なくしては導き出せない検索結果が徒労に過ぎず、人に聞けば一瞬で解決してしまうようなこともあるものだ。"},
{file:"diary_200412172133.htm",title:"世界最小P2P",mtime:1103286793,ctime:1103286793,body:"Pythonで15行http://www.freedom-to-tinker.com/tinyp2p.htmlPerlで9行http://ansuz.sooke.bc.ca/software/molester/Rubyで6行http://www.rubyist.net/~matz/20041216.html#p01Slashdot本家、ネタ多しhttp://developers.slashdot.org/article.pl?sid=04/12/15/1953227&tid=95bashで2行http://developers.slashdot.org/comments.pl?sid=132907&cid=11096822molesterは外部モジュールを使っていない、本当に9行。他のは外部モジュールに依存しているところが大きい(特にbash)単なるファイル転送ではなく繋がった複数のノードの中からファイルを見つけてきて転送するという動作するあたりがポイント。だと思われる。----時期を同じくして似たような記事が。.NETで実装する簡易ファイル交換ソフトhttp://www.atmarkit.co.jp/fdotnet/special/networkprog/networkprog_01.html何行だ、何行だ？とりあえずLL最強ということで。"},
{file:"diary_200412180101.htm",title:"JavaScriptでエディターを作っている",mtime:1118819586,ctime:1118819586,body:"スタイルシートとJavaScriptで行番号付きのエディタがほぼ完成。想像以上にうまくいった。後はヒストリ管理や、変更行強調あたり実装したい。Wikiの編集手法に関して、少し違ったアプローチが出来そう。WYSIWYG編集へ逃げない。"},
{file:"diary_200412181833.htm",title:"編集インターフェースを考える",mtime:1103362543,ctime:1103362543,body:"行番号付きのエディタのサンプル。http://la.ma.la/misc/edit.htmlIEでしかまともに動かない。Firefoxの場合、textareaのonscrollを取ってくれないので、onkeydownで動くように。ただし、行番号ずれる。wikiのエディタとして、変更行強調や、検索ハイライトなどと組み合わせることで有用に使えるようになる予定、いまのところ実用性なし。座標で行番号を計算しているので、折り返しが入ると2行として扱われてしまう。これは痛い。気持ち悪い。行番号の意味がさほどない。しかし、これを回避するためにはどの位置で論理的な改行がされているのかを調査する必要がある。標準のテキストエリアじゃどうやっても無理だ。IEとmozilla限定のhtml編集コンポーネント有効にしてbrタグの回数カウントしてやるしかなさそうだ。あまり気が進まないが、どのみちキーワード強調やハイライト付きのエディタ作るにはそれしかないのだから仕方ないか。----IE5.5以降使えるContentEditablehttp://www.microsoft.com/japan/msdn/web/html/mshtml/createwp.aspmozillaのhtml編集http://www.mozilla-japan.org/editor/midas-spec.html----結構前から実装されてはいるのだが、一部マニアの間でしか使われておらず、驚くほど普及していない。＞WYSIWYG でリアルタイムの編集可能な Web ページをさっそく実装しましょう（友人の羨望の的になること間違いなしです）。まあ、4年も経ってるわけだが。ブラウザ依存を避けて使われていないのかと思ったら、案外知られてなかったりもする。今更のようだけど、頑張ればFirefoxとIE両方で動くリッチエディタを作れるようになったことで、今後普及してくるかもしれない。無理やりスクリプト混在させるより、IE用、Firefox用と分けてしまった方が楽だろうな。----ちなみにContentEditable属性はwebサイトを印刷する時に、広告やいらない部分を消したりするのに使うと便利。ちなみにMSDNで紹介されているUserDataもあまり知られていない。Cookieの代わりに使えて、サイトに関連付けたテキストをローカルに保存できる。これを使えばサーバーにテキストを保存しない個人用のWikiなんてのも作れる。メモ帳なら以前作ったが、オートリンクや整形などを備えたWikiを作れたら面白いかもしれない、草稿はUserDataへ、書き終えたらサーバーにアップロード、といった。"},
{file:"diary_200412190711.htm",title:"リアルタイムプレビュー",mtime:1103407863,ctime:1103407863,body:"相変わらずWikiの編集インターフェース調整。全画面表示+ニ画面スプリット+リアルタイムプレビューこれが個人的にすごく使い勝手がいい。エンターを押すたびに差分表示とプレビューを実行。レンダリングエンジンを切り替えて、TeXとかPodとかリアルタイムで描画できれば面白いことが出来そうだ。応用すれば、プログラムのソースコード書いて実行結果を即時に出したりとかもできそうだ。JavaScriptの開発環境にしようか。ソースとレンダリング結果を同期スクロールさせると、対応がわかりやすい。行番号表示と組み合わせて、今表示しているソースの部分だけ描画、あるいは変更のあった行だけを再描画するなどしてプレビューの負荷を減らせそうだ。そこらへんの負荷はマシンが速いと気にならなかったりもするのだが、推奨2GHzのWikiなんてさすがにありえねーだろう。"},
{file:"diary_200412201620.htm",title:"[Perl] 補完付きCPAN",mtime:1103527526,ctime:1103527526,body:"Google SuggestのJavaScriptをそのまま流用している。http://teknikill.net/cpan/http://blog.livedoor.jp/nipotan/archives/11041353.html経由----どうせだからGoogleSuggest以上のもの作ってみようかな。ちょい時間割けば作れる。アイディアもたまってるし。"},
{file:"diary_200412282246.htm",title:"PHPのリファレンスにインクリメンタル検索",mtime:1104241600,ctime:1104241600,body:"PHPのリファレンスに、http://www.php.net/manual/ja/JavaScriptでインクリメンタル検索がついてる。関数名を先頭一致で検索、上下キーで循環スクロールできる。これとはあまり似てないが、Perlの関数名をインクリメンタル検索するものをちょっと前に書いた。検索というよりはカンペツール。コードをクリップボードにコピーすると、使われている関数のリファレンスをポップアップ表示してくれる。関数の数が増えすぎると負荷が多くなって使い物にならないように考えていたのだが、300～400程度の単語が文中に含まれているのかを調べるだけならほとんど一瞬で終わる。ただリファレンスの内容が余所からの転載なので公開していいものやらどうか。Wikiで内容を共同編纂できるようなものを作ってそのうち公開したい。"},
{file:"diary_200501100737.htm",title:"次期検索インターフェースの雛形",mtime:1105310350,ctime:1105310350,body:"あけましておめでとうございます。もう10日です。正月休みすぎて調子が乗らないのでリハビリで検索ツール作りました。連続検索とサムネイルとなでるインターフェースとインクリメンタル検索の組み合わせ。インターフェースマニア以外には大して面白くないと思われ。スクリーンショットhttp://la.ma.la/misc/google_hta.pngダウンロードhttp://la.ma.la/misc/google.hta挙動が一般的ではなかったり、もっと便利になりそうだなーと安易に浮かぶような手抜き部分はあるものの作りこむとコード汚くなるので、こんぐらいで公開。サイトのサムネイルを並べてインクリメンタル検索で絞り込んで開いたりとか、そのうちOperaなんかが実装してくれそうな気がする。影響受けてるのはiRiderです。技術デモということで。この系統でそのうちサイト近辺探索ツールとか作ってみたい。ウェブサイト自動サムネイル機構と組み合わせて。**連続検索検索ワードを連続して入力する感覚。いちいちページを切り替えたり検索結果が返ってくるまで待つことなく、ガシガシ検索。クリップボードからペーストでまとめて検索とかどうだろう。**なでるインターフェースiRiderのパクり。**サムネイルIEの独自拡張zoomを使って実現してます。**タブブラウズHTMLだけでタブブラウザもどき。ホイールでタブ切り替えとか出来るけどつけてない。サムネイル部分をDOM操作で行ったり来たりさせてる。**検索結果の絞込み大きく集めて手元で振り分け。インクリメンタル検索。例によって作りこむとソースが汚くなるので簡易バージョンで。**既読未読振り分け去年の12月11日ぐらいに書いたスクリプトの流用。JavaScriptでリンクの既読未読を振り分けるという恐ろしい代物。別エントリで詳しく書こうかと思います。注意：セキュリティ上の制限を迂回するためhta(htmlアプリケーション)になっています。開くページ全部が、信頼済みサイトと同等の権限で動くことになります。このツールで見ず知らずのサイトを訪問するのはとても危険です。意味がわからない場合は実行しないでください。責任取れません。Googleドメイン上に設置するか、GoogleAPIを使って自前で検索結果用意すればWEB上で使えるはず。bookmarkletで無理やりGoogleを書き換えて実装するなんてのも考えたのだけど面倒くさそうだったのでやめた。誰か作る猛者はいないか。動作無保証。コード流用は勝手にどうぞ。制作はテレビ見ながら10時間。まあまあ。"},
{file:"diary_200501130023.htm",title:"iPod shuffle",mtime:1105543399,ctime:1105543399,body:"iPod shuffleは単にUSBメモリとして見ても結構安い。そこら辺の電器屋でUSBメモリを定価で買うぐらいならiPod shuffle買ったほうが良さげだなあと思えてしまう。液晶無し、バッテリ内蔵、重さ大きさあたりはGroovox SPあたりとかぶってる。http://www.milestone-net.co.jp/products/groovox_sp/index.htmlコンセプト自体はそんなに目新しいわけでもないだろう。ただ、安い。MP3プレーヤーではなくUSBメモリを意識した価格設定なのだろう。充電するためにいちいちPC立ち上げるのが億劫な場合はACアダプタよりはUSB電池箱のほうが何かと使い回しが利いて良いだろう。予備の電池持ち運べるし。まあ多分、充電しながらは使えないだろうけど。USB扇風機とか回せる。USB Battery Packhttp://www.rakuten.co.jp/jtt/541283/574417/バッテリエクステンダーhttp://www.pdakobo.com/press/030312.htmバッテリエクステンダー2http://www.pdakobo.com/review/accessories/extender.htmちびっこ Power Bank XOhttp://www.mib.co.jp/products/powerbankxo/powerbankxo.htmlもしくはGENO http://www.geno.co.jp/にて30円で売ってるUSB延長ケーブルを使って自作とか。USB Battery Packが秋葉原で1000円で売ってたので使っている。これがなかなかいい感じ。"},
{file:"diary_200501140707.htm",title:"入力インターフェースを考える",mtime:1105654745,ctime:1105654745,body:"最近タブレット使った入力手法を考えている。タブレットPCは結局あんまり流行らなかったらしいけどOneNoteの登場が早かったらもっと普及していたのではないかと。skypeの登場で、今年あたりにようやく既存のテキストベースのコミュニケーションからブロードバンドを生かしたコミュニケーション手法への移行が進みそうな気がする。もちろんWebカメラとか音声チャットとか、以前から出来ることは出来ていたのだけれど。OneNote、実際よく出来てるわけで。手書きのメモをIMEと連携して文字として変換してくれる点。このあたりはどうやってもウェブ上では再現できない。入力だけでなく、細かいスクロールやジェスチャーによる機能の呼び出しなんかにも、タブレットPCは有効に使えそうだと思う。もっと安くなれば欲しいんだけどな。おもちゃで買うにはまだ高すぎる。----というわけでJavaScriptを使ったピクトチャットもどきが作れそうなのであれこれと試しているところ。ただし、文字認識が出来ない以上、メインの入力手法として使うのはどうかと思うので、あくまでもwikiの注釈インターフェースとして模索中。http://bookmarklet.daa.jp/画面に絵を書くブックマークレットが紹介されている。http://bookmarklet.daa.jp/linedraw.html仕組みはこのURLをIFRAMEをブラウザ上に重ね合わせて表示してMS-VMLで線を引いている。VMLを使っているからIE限定だ。同じようなことをFireFoxでやるとして、FireFoxで使える拡張機能の一つAll-in-One gesturesというのを思い出した。その機能の中にマウスジェスチャーの軌跡を画面に描画するオプションがある。mozillaの拡張機能というのは、すべからくJavaScriptで書かれているはずで、JavaScriptで画面に直接マウスで絵を描くことは可能であるということだ。やり方は大体想像がついていたが、実際どうやってるか調べてみるとやはり指定サイズの要素を作って座標を絶対指定で追加しているだけ。欠点は大量にドットが追加されていくため、動作がどんどん重くなっていくこと。コードコピーして同様のを適当に作ってみたが、IEだとやはり使い物にならない。mozillaの描画エンジンが優秀なのと、ジェスチャー中だけの表示なので気にならなかったが、やはり大量に線を引いたときの処理速度が問題になる。IEの場合はVML使うように処理を分けるべきだろうか。簡単な図面なんかを描くのにいちいち外部アプリケーションを立ち上げるのは面倒だ。ブラウザ上で直接絵を描くのは今後Wikiにとって重要な要素になるような気がする。以前はJAVAで書かれたお絵かきアプレットを使っていたが、今ならFlashか。まあ、Notaがすでにやっていることなのでどうでもいい。あくまでJavaScriptでやってみるか。VMLや、描画データを保存→ブラウザで描画、というのも考えられるがサーバーサイドで2値のGIF画像あたりに変換してやるのが妥当だろう。SVGを使う。http://cgi.no-ip.org/wema/なんてのもありだろうけれど、ブラウザのネイティブサポートが普及しない限りはやっぱり厳しい。"},
{file:"diary_200501150558.htm",title:"JavaScriptでペイント",mtime:1105736330,ctime:1105736330,body:"というわけで作ってみた。http://la.ma.la/misc/plot/draw.html線が描けるだけ。やっぱり重い。重い。JavaScript側の処理-点を打つべきx,yの座標の配列作ってCGIに送る。CGI側の処理-GDで点を打ってpng画像で保存とりあえずこれだけ。IEの場合のみVML使うようにした方が良いと思う。本格的に絵を描くのだったら、筆圧やらレイヤやらサポートしたJAVAアプレット使うべきだろう。作図ぐらいには使えるだろうか。----注釈インターフェースの方向性としては-ドラッグで画像サイズを決定、絵を書き込む。-IFRAMEまたはXMLHTTPでデータを送る、画面の切り替えなしに画像作成。-透過画像が作成されるので、画像ドラッグで位置を調整、貼り付ける。こんな感じかなあ。ドット集合のままドラッグで移動させると、ブラウザ負荷がすごそうだから、画像に変換した後で位置決めの方が良いだろうと思う。"},
{file:"diary_200501212325.htm",title:"JavaScript Vectorgraphics Library",mtime:1106319002,ctime:1106319002,body:"JavaScriptのグラフィックライブラリhttp://www.walterzorn.com/jsgraphics/jsgraphics_e.htm以前TooltipAPIを使ってみたことがあるのだが、他にもずいぶんと面白いものを作ってたんだなあ。隣接したピクセルを同じ要素にまとめることで描画パフォーマンスを上げている。同じような最適化をしようとしていたところなので丁度いいかも。使ってみようかな。Drag & Drop APIもなかなかよくできてる。http://www.walterzorn.com/dragdrop/dragdrop_e.htm宮川達彦氏のブックマークから発見http://del.icio.us/miyagawa----ついでに。同サイトであくまでデモンストレーションとして公開されている「Rotate Image」は恐ろしい。処理に時間がかかりすぎてブラウザが落ちたりすることもあり。画像をスタイルシートのclipを使って1ドットずつ切り出し、座標を絶対指定で表示したものを重ね合わせることによって、JavaScriptで画像の回転を実装するというものだ。やりすぎ。"},
{file:"diary_200501241547.htm",title:"動的ロードあれこれ",mtime:1106549249,ctime:1106549249,body:"JavaScript及び、その他技術の組み合わせによる、動的ローディング手法について、書いてみた。http://ma.la/mirrorman/wiki.cgi/%e5%8b%95%e7%9a%84%e3%83%ad%e3%83%bc%e3%83%89XMLHTTPは以前使ったとき使い勝手が悪く、丁度IEでローカルファイルを読み取れる脆弱性とか色々問題あったので、あまり深追いはしなかったのだけれど、やっぱこれからはXMLHTTPが流行るかなあ、と思う。GoogleSuggestで有名になったし、ブラウザの対応状況もいい。XMLRPCなんかと親和性の高いコードが書けるのもメリットが大きいのだが、他ドメインのサーバーと通信できるわけではないので、自分のドメイン内でしか使えないのが痛い。すでにXMLを使ったリクエスト、レスポンスの実装があるのなら、対外的なインターフェースと内部で使うインターフェースを共通化できて嬉しいのかもしれない。個人的にXMLHTTPの一番のメリットは通信状態がステータスバーに出ないことで、多分この「こっそり通信する」仕様は意図的にそうしているのだと思う。開発者にとってはありがたいのだが、一般ユーザーにとってはどうなんだろう。作ろうと思えばキーロガーやマウストラッカーなんてのも作れるわけなので、サーバーに何を送ってるのかわからないというのは、ちょっと気味が悪い。Operaでは通信状態がステータスバーに出る。Operaの実装はプライバシーに配慮したものだろうと思う。今、3年ほど前から作っているチャットスクリプトを大幅に手直ししているのだが、XMLHTTPを使おうかどうか悩む。「誰々がメッセージを入力しています」というような通信にIFRAMEを使うと鬱陶しいので、そこらへんの細かい通信にはXMLHTTPを使うのもいいかもしれない。（やっぱキーロガーだ）"},
{file:"diary_200501250246.htm",title:"サムネイル付きブックマークを簡単に作成",mtime:1106588766,ctime:1106588766,body:"webshothttp://phpspot.net/php/webshot/http://www.ringolab.com/note/daiya/archives/002908.html先月あたりからプロフィール代わりに見たサイトのスクリーンショットを淡々と記録するというのをやろうかと思っているのだが、なんか似たようなのを発見。IEのツールバーというのがネックか。タブブラウザで使えないのは困る。Win32::CaptureIEというモジュールを使うためだけに、Windowsサーバーを立てたのだが、どうもサイトによっては上手く動作してくれなくて困っていた。ちょっと放置中だけれど。今やってる作業が終わったら手をつけようかと思う。構想はというと。-Bloglinesで購読しているサイトのURL--OPMLでインポートできる。-del.icio.usに登録したサイトのURL--RSSで取得できる。-BlogやWikiからリンク張ったページのURL--適当なツール作ってリンク抽出-被リンク(リファラー)のURLを全部まとめ上げて、セキュリティ特化した専用Windowsマシンでアクセスさせてスクリーンショット作成、サムネイル作って自動でアップロード、といった具合の。サムネイル作成サーバーを別にしておけば、どのブラウザからでもブックマークレットから呼び出したりできる。というかサムネイルをリアルタイムで作ってくれるサービスってないものかな。んでそれに加えてRSSフィードの有無とかGoogleのページランクとか更新日とかの情報を関連付けてインクリメンタル検索できるようにしてメタ情報が付加されたグラフィカルなブックマークサイト構築みたいなのを。URLにマウスオーバーでリンク先のサムネイルがツールチップで表示されるようなのもやってみたい。"},
{file:"diary_200501250339.htm",title:"画像のインクリメンタル検索",mtime:1106591954,ctime:1106591954,body:"あまり大っぴらに公開できるものではなかったのだけど、去年の夏ごろに画像をインクリメンタル検索するスクリプトを書いた。必要なのは検索の対象となるテキスト情報だけで、ブラウザ上で軽快に動作する。なかなか使い物になった。動的にイメージタグを生成するので、画像は必要に応じてロードされ、重くならない。対象のデータが1万件程度であれば問題なく、検索ヒット数に制限をもうけて、ヒットしすぎた場合は打ち切るようにしていた。サーバーサイドと連携するようなタイプにすれば1万件以上でも問題なく動かせるだろう。ふと、Picasa2はどんな感じなのかな、と思って試しに使ってみたのだが、インターフェースかくあるべし、というべき素晴らしいものだった。現状、日本語のファイル名に対応していないけれど、インターフェースに興味がある人は必見だと思う。http://www.picasa.com/-文字列でのインクリメンタル検索-拡大縮小のスライダコントロール-日付範囲のスライダコントロールこれ、検索の三種の神器だと思う。これだけでほとんど完璧だ。タグとかフォルダ分類とかは、はっきり言っていらない。面倒くさい。後は、表示件数に応じて一覧が画面内に収まるように自動でズーム倍率を切り替えるようなオプションがあればほとんど完璧か。イメージ検索、というかサムネイル画像付きの検索はこれから伸びる分野だと思う。ファイルタイプを表すアイコンやfaviconを使ったサイトの見出しよりも、今後は実際のファイルの中身を反映した見出しを用いるタイプの検索にシフトしていくのではないかと思う。"},
{file:"diary_200501270559.htm",title:"JavaScriptでペイント、開発版",mtime:1106773142,ctime:1106773142,body:"少し留守になるかもしれないのでとりあえずアップ。保存ルーチンをまだつけていない。http://la.ma.la/misc/plot/draw2.html-zで一手戻す、+/- or q/a でブラシサイズを変更。というキーバインドをとりあえず実装。作りこめば色変更とか、直線描画とかも色々できるだろうな。ただ、この手書き機能を組み込んだチャットと、そのチャットを組み込んだWikiを作るというのが目的なので単体であまり作りこむつもりはない。IEの場合、VMLを使った描画にしてみた。MSNメッセンジャーの手書きモードと、書き心地はそう変わらないが、やっぱり線が増えてくると重くなるのでそれほど書き込むことはできない。DIV要素を足していく方式の描画エンジンをまず作ってIEの場合のみVMLを使った関数で上書き、という方向性で。VMLはもう終わっている技術なので。SVGが使えれば一番いいんだけれど。firefoxでの動作が、どうすれば負荷が少なくなるのか手探り状態。実際に描いたり、CPUの使用率を見てあれこれ実験中。こうすれば速くなるだろう、と想像で実装しているのだが、いまいち効果が見えない。垂直もしくは水平に動いた場合はwidth、heightをいじるようにしたりとか、次の描画に使うための要素を予め作成しておいて、getElementByIdを使わないで済むように変数にキャッシュしておいたりとか。最適化をしているつもりなのだが、一番最初のドットを大量に足していく方式のほうがなぜか描画が早い気がする。既存オブジェクトのスタイル操作よりも新規に作ったほうが速いのかも。しかしドットを大量に作るとやっぱり死ぬほど重くなるので不可。今更ながらJavaScriptでのオブジェクト指向な書き方を覚えようかと思って大幅に書き直している。個別の関数の中にブラウザ判別が入るのは美しくない。丸ごとオーバーライドしてしまおう。イベント処理なんかもHTMLから綺麗に分離できるので、今まで書いたコード全部直したくなったり。タブレットPCが欲しい。"},
{file:"diary_200501291454.htm",title:"del.icio.us登録のためのSleipnirスクリプト",mtime:1106978084,ctime:1106978084,body:"Sleipnirからdel.icio.usに登録するためのスクリプトを書いてみた。テキスト選択、マウスジェスチャ、タグ選択、と3工程で登録できる。http://la.ma.la/misc/add_del.icio.us.txt保存して好きな名前に変更して拡張子jsにしてsleipnirのスクリプトディレクトリに保存。設定とかはスクリプト内に直書きでもいいかなと思ったけど、どうせだから設定ファイルの読み書きを使ってみた。雛形にしようかと思ったので、よく使いそうな処理を無意味に織り込んである。独自APIとか何やらがイヤであまり使う機会がなかったのだけれど、基本的には普通のJavaScriptなのでブックマークレットよりもちょっと複雑な処理させたいときには案外使える。書き方工夫すれば各種タブブラウザで互換のスクリプトとか作れるんじゃないかと思うんだが、どうなんだろ。すでに登録用のスクリプトがあったので、参考にさせてもらった。http://cubic9.com/Sleipnir_Script/#sl_delicious_tagbutton以下、特に意味なし。----最近、これhttp://del.icio.us/試してみているのだけれど。普段常用しているSleipnirではブックマークに登録してある特定のサイト以外はセキュリティ設定が全部オフになるようにしている。困ったことにJavaScriptをオフにしているとブックマークレットが使えないわけで、巡回先でいちいちJavaScriptをオン、リンクバーのブックマークレットのボタンをクリックという手順を取らねばならず、面倒くさい。IEの右クリックメニューに追加でも良かったのだけれど、右クリック後の項目選択が面倒なので、あまり好きじゃない。普段からJavaScriptをオン、は却下。というわけであんまり使ってなかったのだが、今日になって「実験バージョン」というほうのブックマークレットには、分類に使うタグを「自分の履歴」か「他の人の付けたタグ」から選ぶ機能があることに気づいた。これは使えるんじゃないか、使わないと損じゃないか。タグを使った分類というのには疑問を感じていたのだが(そんなのは自動でやれよ、という)こういった提示された選択肢からいくつかを選ぶ、という行動をユーザーに取らせることである種のモデレーションとして機能していくかもしれない、と思った。同じ記事でも人によって、どういった分類をするのかは異なる。「面白いサイト」として登録しているのかもしれないし「くだらない、死んでしまえ」と思って登録している可能性もある。そのサイトに対して、どんなタグがついたのか統計を取ることで、どういう切り口でそのサイトを読んでいるのかがわかるようになる。単純な「同じサイトを登録している人」だけではなく、タグ分類の傾向を読み取ることで「あなたと同じような感性を持っている人」を探すことができるようになるんじゃないか、と、そういうことを思う。----オンラインブックマークとして使うには、検索インターフェースが貧弱すぎてどうかと思うので、便利に使えるようなのを作ってみたくなった。ただ、RSSからもAPIからでも肝心のpopularity(どれだけの人に登録されているか)が取得できないので、使い物にならない。HTML解析で作るしかないかなー、とかなんとか。"},
{file:"diary_200502042238.htm",title:"JavaScriptで作ったお絵かきBBS",mtime:1107524321,ctime:1107524321,body:"http://la.ma.la/bbs/コード整形してだいぶ汎用性を高めたつもり。わかりやすいデモとしてお絵かきBBSを作ってみた。-IEの場合はVMLの自由曲線を使って描画します。-他のブラウザの場合は1ドットのspan要素を使って描画します。-GDを使ってサーバー側でpng画像に変換します。firefoxかoperaの場合は2GHz以上推奨。書き込むたびにガンガン重くなる。----この手のツールはすでにFlashやJAVAアプレットで優れた実装があるわけだけど、なんでわざわざJavaScriptで作るかというと。まず起動が早いので、思い立ったらすぐに書けるという点。それから、FlashやJAVAアプレットは、表示エリア内にしか書き込めないのに対して、JavaScriptの場合はhtml中のほかの要素の上に書き込むことができるというメリットがある。とりあえずここまで出来ているので、手書きで付箋メモなんかの実装は簡単にできそうだ。"},
{file:"diary_200502081950.htm",title:"Google Maps",mtime:1107930311,ctime:1107930311,body:"http://maps.google.com/mapsあれやこれやと、このサービスについてレビューなどをする人が出てくるだろうが・・・本当に驚くべきところはFlashを使っていないという点ただ一つだ。----少し補足。http://ma.la/mirrorman/wiki.cgi/GoogleMaps"},
{file:"diary_200502102148.htm",title:"BBSのソース",mtime:1132189247,ctime:1132189247,body:"BBSにコメントとRSS出力をつけてみた。なんか気付くたびにちょくちょく直してるので最新のソースではないですが、とりあえず置いておきます。http://la.ma.la/misc/jspaint.zip仕様とかはここに。http://ma.la/mirrorman/wiki.cgi/JavaScriptPaint稼動中のは実験バージョンということで適当に改良でも加えていきます。試し書きはご自由にどうぞ。http://la.ma.la/bbs/JavaScriptが複雑なので難しいかもしれませんが、他のBBSやBlogに組み込んだりは勝手にやってもらってかまいません。今は透過png画像を生成してますが、生データを元に他の形式で出力することもできます。GD::SVGを使ったSVGの生成をやってみました。アニメーションGIFやFlashも頑張れば出来ると思います。アクティブデスクトップかサイドバーに表示して手軽に手書きメモを取るツール、なんてのもいいかなあと思ったが、チャットとwikiを早いうちに公開できるレベルにしたいので手書き関係はひとまず終了したい。"},
{file:"diary_200502150845.htm",title:"2ちゃんねるヘッドラインのRSSが凄い件",mtime:1109930654,ctime:1109930654,body:"なんかごちゃごちゃなので、最初にまとめておくと、-2chヘッドラインのRSSは全文配信でかなり使える-RSSリーダーはthunderbird+検索フォルダ使うと便利-サイズが大きいので直接受信しないでcoralを使おうということで。----2chのニュース系の板のスレッド一覧を束ねて新着順に表示してくれる2ちゃんねるヘッドラインというものがあるのですが、これが1週間ぐらい前から、RSSの提供を開始しています。ここにまとまってます。http://www.pblog.net/mt/archives/002377.php勝手にRSSを生成するのは以前からあったが、2chのドメインから公式に提供されているのは多分初めて。いまのところ、フォーマットはRSS2.0で文字コードはShiftJIS。素晴らしいのは、国内のあらゆるジャンルのニュースを網羅していて、さらにタイトルだけではなく記事本文が全て含まれている点。ニュースのRSS配信としては間違いなく国内最大。とりあえずbloglinesで購読してみましたが記事が長すぎ多すぎで読みきれず役に立ちません。bloglinesは自分の興味のある分野のRSSを100も200もチェックする場合には最強ですが、過去記事を保存していないので、こういった用途には向いてません。----配信されてくるのが自分が興味があるのかないのかわからない「ごちゃまぜのニュース」なので、とりあえず蓄積しておいて後で検索してなんぼです。2ちゃんねるヘッドラインのRSSを読むのに適したリーダーの条件は、「検索結果をフォルダと見なして表示することが出来ること」です。スタンドアロンのRSSリーダーをあれこれ試してみましたが意外とこの機能を備えているものが無く、使えそうなのはoperaとthunderbirdだけでした。rss2mailでGmailに送って、どこからでも読める、なんてのも良いかもしれません。OperaのRSSリーダーはラベルを使って検索結果をフォルダ表示したり、さらには学習による自動ラベル付けなんかもできますが7.5は不安定、8.0はまだbetaなのでデータの移行がちゃんとできるか心配です。thunderbirdは細かい使い勝手が洗練されていなかったり、登録が面倒だったりしますが、これからの改善が期待できるので、とりあえずthunderbirdにデータを蓄積することにしました。ニュースだけでなく、地震情報のRSSなんかもあるので、蓄積しておけば後でなんかの役に立つかもしれません。thunderbirdの検索フォルダ機能は「表示」のプルダウンメニューから検索フォルダを保存、で登録できます。この機能があること自体知らなかったので、スクリーンショットを載せておきます。http://la.ma.la/misc/thunderbird_search.pngなんか色々いじってたら同じ記事を何回も受信してしまったので、Duplicate Message Removerという拡張を入れてみました。重複記事を削除してくれます。http://split-s.blogspot.com/2005/02/duplicate-message-remover-01.html----全文配信なので、結構サイズが大きく、大体200KBほどあります。2ch全体の転送量からすれば微々たるものかもしれませんが、こんなのを大勢が定期的に受信したら転送量がえらいことになると思うので、RSS用のキャッシュプロキシとかないかなーと探してみましたが、見つからなかったのでとりあえず、coralを使うことにしました。一定時間キャッシュが入るので、完全リアルタイムには更新されませんが今のところ取りこぼしなく受信できています。http://headline.2ch.net.nyud.net:8090/bbynews/news.rss----追記2ちゃんねるヘッドラインのRSSを2時間分ぐらい取りこぼした。どうもcoralは振り分けられるサーバーによってキャッシュ状況が全然違うみたいだ。ダブって受信してしまうのも、多分そのせい。RSSのキャッシュに特化したオープンなプロキシって無いものか。----追記 2005-03-04RSScacheというのが、なにやら良さげです。http://www.rsscache.com/http://my.rsscache.com/headline.2ch.net/bbynews/news.rss"},
{file:"diary_200502191947.htm",title:"ソーシャルブックマークの未来予想",mtime:1108810043,ctime:1108810043,body:"自分に出来ることは数限られてるけど、これからどんな技術が、どう組み合わさって、どう発展していくのかは大体予想がつく。これからブラウザの拡張機能としてサイドバーにソーシャルブックマークが組み込まれるだろう。それは自分が今見ているページからドメイン内の人気のあるページをリストアップしてくれたりどんなタグがついているのか、誰がブックマークしているのか、関連しているページは何か、関連している本は何か、関連する商品は何か、ページ内の単語のwikipediaへのリンク、逆リンク、前回の更新箇所(diff)、同じページを見た人のオンライン状況、ページの評価、などなどを取得してくれる。ブラウザ本体画面のほうはともかく、サイドバーの方はtorなどのP2P匿名プロキシを経由して、さらにはcoralのような分散キャッシュサーバーを利用して、プライバシーの漏洩を心配することなく、転送量もサーバー負荷も気にすることなく、思う存分メタ情報を受信する。ページのロードと同時に、あなたが必要としている情報と、もしかしたら必要とするかもしれない情報も勝手に取得する。----そうなったときに重要なのはプライバシーを漏洩せずに問い合わせできるインターフェースを用意することだ。もし、del.icio.usでGoogle Mapsをブックマークしているユーザーを調べたい場合は、http://del.icio.us/url?url=http://maps.google.com/これでもいいのだが、クライアント側でMD5値に変換してから問い合わせてやることもできる。http://del.icio.us/url/0706dc411e92332c6c93758cc7b37225つまり、自分が今見ているページの具体的なURLが何であるかをdel.icio.usに教えなくても、どんなタグがついてるのか、誰がブックマークしているのかを取得できるということだ。渡されるのがMD5ハッシュ値であれば、それがパスワード付きのURLだろうが、イントラネット内の社外秘のURLだろうが、まるで関係がない。誰もブックマークしていなければ、del.icio.us側は一体何についての問い合わせであったのかすらわからない。はてなブックマークは今のところ、これが出来ない。問い合わせるにはこれだ。http://b.hatena.ne.jp/entrylist?url=http://maps.google.com/ユーザーの一覧はここに出る。http://b.hatena.ne.jp/entry/215それにしても「215」ってなんだよ。内部的には別にどうなってても構わないんだけど、オートインクリメントで全然OKなんだけど、この数字は結局、はてなのデータベースに問い合わせない限り得られない数字なわけで、分散や協調を考えていないんじゃないか。そもそもURLに対して1から順に番号を割り振っていくという行為にどうしょうもない気持ち悪さを感じるのは俺だけだろうか。----未来予想、当たるだろうか。誰もやらないんなら俺が作るか、とかなんとか、思うだけなら簡単だ。"},
{file:"diary_200502240759.htm",title:"Ajaxについて、あとファイラーを作ってみた",mtime:1109199577,ctime:1109199577,body:"JavaScriptとXMLHTTPを組み合わせた動的ロード技術全般に、なにやらAjaxなる名前がついたらしい。http://antipop.zapto.org/docs/translations/ajax.html概論のみではあるけれど、とてもわかりやすく、そして今までウェブデザイナが何もしてこなかったということが良くわかる。ここに来てようやく、JavaScriptは評価を高めつつある。JavaScriptはJavaよりも優れていると、ポールグレアムも言っていることだし。----世間がBlogだのRSSだのと騒いでいる間、JavaScriptばかりいじっていた頭のおかしい人間がここにいるわけで。iTunes程度のインターフェースであればJavaScriptで作成できます。http://la.ma.la/filer/IE、Firefox、Operaで動作確認。CPUが遅いと動作きついかもしれません。検索は完全ローカル、タグの更新が画面遷移なしに動きますがXMLHTTPは使ってません。隠しIFRAMEです。1GHz程度あれば、ストレスなく動くとは思います。とりあえず検索が試せるようにダミーのファイルを置いてあります。ソースは古臭い書き方で参考になりません。ほとんど力技。説明書なんかはここに。http://ma.la/mirrorman/wiki.cgi/%e3%83%95%e3%82%a1%e3%82%a4%e3%83%a9%e3%83%bcデスクトップサーチとか大掛かりなものでなくても、Ctrl+Fで出てくる検索がこんな感じなら便利なんじゃないかと思う。検索→選択→タグ付けの流れはブックマークとか、BlogやWikiのサイトナビゲーション、何にでも使えるような気がする。一段落ついたら、ちゃんとリファクタリングする予定。----Ajax関係のリンクhttp://piro.sakura.ne.jp/latest/2005/02.html#d23「クライアントが貧弱でもサーバが強力なら、連携を密に取りさえすれば何だってできる」クライアントとサーバー、そのバランスは自由に変えられる。どの処理をどちらにやらせるのかの判別は非常に重要なことになると思う。GoogleMapsは今まで高価なアプリケーションサーバーにやらせていた「地図の合成」という作業をクライアント側に持ってきた。アクセス数が増えても地図画像の断片を置くデータサーバーを増設するだけでいいし、今後、P2Pなんかを使ったスマートなキャッシング機構が普及すれば、それすらも不要になるだろう。頻繁に通信を行うことになっても、うまくやれば通信量もサーバーの負担も減らすことが出来る。----俺が今までやってきたことや、これから考えてるのは、Ajaxとはまた少しばかり手法が違うような気がする。サーバーは本当に単純なデータの受け渡ししか行わず、むしろ逆にクライアントがデータを検索してサーバーに検索結果を送る、というJavaScriptで分散コンピューティング的なことを、かなり真面目に考えている。とりあえずWikiのオートリンクのキャッシュ作りなんかで、実際に使うことになりそうだ。"},
{file:"diary_200502270128.htm",title:"[Ajax] location.hashを使ったセッション復元",mtime:1109436201,ctime:1109436201,body:"最近になってようやくJavaScript関係、動的ロードを使ったテクニック等について話せる相手ができまして、、なかなか充実しています。Gmail、GoogleMapsのような画面遷移なしの高速なナビゲーションが注目されています。サイトが特定のタスクに対して特化している場合、JavaScriptを使ったインターフェースの最適化が非常に有用であるのは間違いありません。ブラウザ上で動作するリッチクライアントとしてはFlashが圧倒的に有名ですが、Flashは、ブックマーク、ブラウザの戻る進む機能、文字の拡大縮小、などのブラウザが本来備えている機能が使えないため、ユーザビリティ研究者の間では嫌われ者です。http://d.hatena.ne.jp/nazoking/20050226というわけで、AjaxがFlashのような使い方をされないような実装例を考えてみたいと思います。一つは、GoogleMapsのように、現在の緯度経度、検索条件を?以降のパラメータ(QUERY_STRING)で渡してやる方法です。マップをスクロールするたびに、リンク用のアドレスが更新されて、ショートカットをコピーできるようになっています。従来のQUERY_STRINGを使う場合のメリットは、サーバー側が検索クエリを理解できるので、スクリプト無効の環境でもそれなりの表示ができるように誘導をすることができる点です。もう一つは、検索クエリの状態をlocation.hashで保存できるようにするという方法です。http://la.ma.la/filer/#find=HTAonload時にlocation.hashの値を元にして、検索条件を復元しています。また、検索時にリアルタイムで#以降の文字列が変化し、そのままブックマークすることができます。Flashでもこのような実装は可能なのかもしれませんが、少なくとも自分は今まで見たことがありません。location.hash、#以降の文字列を使うメリットは、同じURLとして扱われるためキャッシングとの相性がよいという点がまず考えられますが、さらに大きなメリットはサーバー側にログが残らないという点です。クライアント側で検索を実行するようにした場合、location.hashを使った引数の解釈から、検索の実行までが完全にローカルで行われるため、どんな検索語句を使ったのかサーバー側に一切ログを残さないで済みます。location.hashの変更をタイマーで監視して、変更に応じてデータをロード、画面を更新してやる、という手法をとれば、画面遷移なし、かつ、ブラウザの戻る進むボタンが使える、という実装も可能でしょう。----応用として、?username#passwordといったリクエストを送ることで1. サーバーはusernameに対応した、暗号化された状態のデータをXMLHTTPで送る2. クライアントは#passwordに指定された秘密鍵を使って、元のテキストに復元3. データの更新時はクライアント側がテキストを暗号化し、サーバーにデータを預けるこれによりサーバー側が元のデータを絶対に知りえないプライベートデータを保存できるストレージを用意することができる、ということを考えています。というかかなり前に考えていたのですが、構想の段階で終わっています。JavaScriptを使った公開鍵暗号の実装は、実際に試せるサイトがいくつかあります。http://www.faireal.net/demo/PigPGP/0_2_3jaサービス会社が個人情報を握ることなく実現できるソーシャルネットワークサービス、なんていうのを考えているのですが、ストックしているアイディアの量に対して、圧倒的に時間も作る能力も足りません。興味のある方は是非やってみてください。"},
{file:"diary_200502282048.htm",title:"JavaScriptで差分リロードなチャット",mtime:1109591294,ctime:1109591294,body:"3年と少し前から作っているチャットのリファクタリングをしています。http://ma.la/mirrorman/wiki.cgi/%e5%8b%95%e7%9a%84%e3%83%ad%e3%83%bc%e3%83%89ここに書いてあるチャットのことで、当時はNN4でも動くように、けっこう苦労した覚えがあります。フレームを使わないスタイルシートでのレイアウトへ変更、オブジェクト指向化、イベント定義を外部記述へ変更など、大幅に直しています。ベースの部分は3年前からほとんど変化ありません。IFRAMEで通信しているので、Ajaxとは違うと思いますが、XMLHTTPを使わなくても昔から動的ロードは出来たよ、ということで。最近はDHTMLを使ったチャットも多くなっているので、目新しくはなくなってしまっているかもしれません。まだ何かと中途半端ですが、とりあえず、動作デモとして設置してみます。http://chat.ma.la/普通のチャット、改行を含むテキストの書き込みと保存、それから手書きメッセージの書き込みが可能です。長文書き込みはタブが残るので、pythonのソースコードが貼れます。手書きはお絵かきBBSの使い回しです。ボーダーのリサイズでキャンバスを広く出来ます。IPアドレスは表示されませんが、ログとしては残しています。サーバーの負荷が高かったり、不具合が見つかったら消すかもしれません。----仕組みはログファイルのどこまでを読み込んでいるのかを記録しておき、追加された部分のみを読み込んで追記、という単純なものです。変更がなかった場合はマイナーですが「HTTP 204 No Content」というレスポンスを返すと、ブラウザは何の処理も行いません。http://www.studyinghttp.net/status_code#Code204差分リクエストは、昔XMLHTTPでrange付きリクエストが出来ないかと試行錯誤したことがあるのですが、どうにも無理みたいです。CGIを使ってログファイルを部分的に切り出してブラウザに送ってやる必要があります。サーバープッシュとクライアントプルの組み合わせで、ウェブベースでも高レスポンス、低通信量のチャットを作るというのがコンセプトなのですが、レンタルサーバー上でサーバープッシュをやるとコネクション数を多く使ってしまうので無効にしています。ブラウザ上で完全リアルタイムに更新するチャットを作るのは、それほど難しいことではありません。プライベートメッセージ、ローカルファイルのアップロード、httpからファイルのダウンロードアスキーアートで発言、MSAgentを使った発言読み上げ、mp3ストリーミング、ブラクラ送信機能、タブまたはMDI表示でマルチルーム同時参加、2ch実況、正規表現での発言フィルタ機能など、色々あったのですが、かなり意味不明なものになってしまっていたので、いったんばっさりと削りました。ウェブベースでも、メッセンジャー以上の機能を持った通信手段を作れないものかと考えています。"},
{file:"diary_200503031629.htm",title:"[Ajax] 2chスレッド最速検索復活しました",mtime:1109936007,ctime:1109936007,body:"しばらく放ったらかしにしていましたが、コード整形と、少し視覚化周りで手を加えてみました。http://x.ma.la/スクリーンショットはこんな具合。http://la.ma.la/misc/2chfind_2nd.png検索状態を復元できるようにしてみました。スクリーンショットのセッション復元IE6とfirefoxとopera8で動作確認をしてます。例によってCPUが遅いと厳しいかもしれません。検索は完全ローカルで行われるので、いったんロードが完了すればいくら検索してもサーバーに負担はかかりません。オフラインにしても検索できます。どんな単語で検索されているのかは、サーバーもプロバイダもわかりません。板移転時の、自動追尾処理なんかが面倒くさくて、実装できてません。なので、いきなり動かなくなったりするかもしれません。----使い方-板を検索後、板名をクリックすると検索対象に加えます。-板が一つに絞り込まれた場合は勝手にロードします。-板名の入力欄はスペースで区切って「板検索文字　スレッド検索文字」とすることができます。-ひらがなで検索ができます。ただし正確にふりがなが振られているとは限らないのでヒットしない場合があります。-ハイライト箇所はいい加減です。ふりがなにマッチした場合、どこにマッチしたのか正確にわからないので。----仕組みは、サーバー側でsubject.txtを取得、kakasiでふりがな付加した状態のファイルを作成。XMLHTTPを使って非同期読み込み、JavaScriptでオブジェクトに変換、といった具合です。同時に複数の板をロードするようにした場合、複数のコネクションを張って、リクエストが完了した順に読み込まれます。フレームを使うよりも圧倒的に簡単に実装できるので、非常に便利です。今までのはフレーム使ってやっていたので、全然Ajaxじゃないです。xがないです。オブジェクト指向な書き方が最近になってようやくわかってきたので、ソースも一応、参考ぐらいにはなるかもしれません。JavaScriptを使った検索は、ある程度のCPUを使っていれば一瞬で終わります。ボトルネックになるのは描画処理のほうなので、変更がない場合は画面に書き出さない、横断検索の場合は表示件数を減らす、などして高速化しています。むかし、こんなのを作ってたのですが、http://x.ma.la/demo/mekuri.html文字コードの変換に必要なADODB.StreamオブジェクトがWindowsUpdateで無効化されてしまい、使えなくなってしまいました。色々と改善の余地はあるのですが、他にやりたいことが色々あり、手を加える暇がないというか、時間をとられたくないので、あまりできません。最近は興味のある人も多そうなのでサーバー側CGIと、クライアント側のJavaScript、全部まとめてオープンソースにしようかと思ってます。"},
{file:"diary_200503040335.htm",title:"firefoxのlocation.hashには1MB以上保存できる",mtime:1111098610,ctime:1111098610,body:"色々実験していたら、Firefoxのlocation.hashには1MB以上保存できることがわかりました。一体どこまでいけるのか、見当もつきません。アドレスバーの描画がおかしくなったりしましたが、ちゃんとブックマークもできるみたいです。サンプルを置いておきます。http://la.ma.la/misc/js/hash.htmlhttp://la.ma.la/misc/js/hash.html#%E3%81%82%E3%81%B0%E3%81%B0%E3%81%B0%E3%81%B0%E3%81%B0%0D%0A%0D%0Aテキストを入れてリンク作成ボタンを押すとlocation.hash付きのリンクを書き出します。作成されたリンクは、読み込み時に入力したテキストを書き出してくれます。タグは無効化されるようになっているので、悪戯はできないと思います。ブラウザに負荷がかからないように、少しずつ画面に書き出していくようになってます。長すぎるURLを開いてブラウザがクラッシュしても、俺のせいじゃないです。ブラウザの実装が悪いと思います。適当に調べてみた情報ここらへんに。http://ma.la/mirrorman/wiki.cgi/location.hash----3/18追記デモ作ってみたhttp://la.ma.la/misc/demo/firefox_bookmark.htm"},
{file:"diary_200503141517.htm",title:"WikiばなVOL4で発表してきました",mtime:1110783925,ctime:1110783925,body:"人生で初めてプレゼンというのをやりました。レポートはblogに書こうかwikiに書こうか迷ったが、長いのと、後で直すかもしれないのでとりあえずwikiに。http://ma.la/mirrorman/wiki.cgi/WikiBanaVOL4----他の人のレポートはこのへんにhttp://wikibana.socoda.net/wiki.cgi?WikiBana%2fVOL%2e4%2f%a5%ec%a5%dd%a1%bc%a5%c8%a5%ea%a5%f3%a5%af%bd%b8"},
{file:"diary_200503151917.htm",title:"[Ajax] エントリの動的ロード",mtime:1119851622,ctime:1119851622,body:"鬱陶しくなるだろうと思って、やらないつもりだったが、やってみると案外そうでもないかな、と思ったのでつけてみた。JavaScript有効の場合に表示される(はずの)プルダウンメニュー、もしくは、右側のエントリ検索の結果にマウスオーバーするとエントリを読み込んで表示する。blosxomの場合、各エントリがプレーンテキストで保存されているので、それを直接読み込んで表示している。サーバーに負担はほとんどかからない。画像を読み込むのと同程度。エントリ一覧のロードは、今までIFRAMEを使っていたのをXMLHttpRequestを使うようにした。ついでに、カテゴリの記事件数集計を正確にしておいた。XMLHttpRequestが使えない環境では、IFRAMEHttpRequestを使う。Opera7.54で動くことを確認。http://ma.la/mirrorman/wiki.cgi/IFRAMEHttpRequestプレーンテキストの読み込みに関しては、ほとんど問題なさそうだ。大体問題はないと思うけど、いきなりブラウザが落ちるなど、やばめの不具合があれば教えていただければありがたい。"},
{file:"diary_200503180815.htm",title:"Winkを使ったlocation.hash復元のデモ",mtime:1111101303,ctime:1111101303,body:"firefoxのlocation.hashには1MB以上保存できるというのは、個人的にバカ受けだったのですが、今ひとつ反応が薄いような気がするので、実際にどんな具合で動くのかFlashを使ったデモを作ってみました。http://la.ma.la/misc/demo/firefox_bookmark.htm----winkというフリーソフトを使っています。http://www.debugmode.com/wink/久しぶりに使おうと思って調べてみたら、バージョンが上がっていて日本語の言語セットも標準で含まれている。ソフトウェアの説明書なんかを作るのに、かなりいい感じに使えると思います。----tiddlywikiのようなwikiエンジンで、書き込んだデータを丸ごとブックマークとして保存できるようにしたら面白いかもしれない。IEの場合2KB、Operaの場合64KBまでしか保存できないという制限がある。URLエンコードすると少なくなるが、エンコード方法を工夫したり、圧縮したりすれば、かなりの量を保存できるだろう。firefoxに限定するなら、小説まるごと保存するなんてのもできる。まあ際限なくというのはさすがにどうかと思うので、将来的に使えなくなる可能性もあるが、1000byteぐらいはどのブラウザでも保存できると思ってよさそうだ。"},
{file:"diary_200504080545.htm",title:"高橋メソッドなプレゼンツール",mtime:1113249184,ctime:1113249184,body:"ここのところずっと、ライブラリ整理ばっかりしてます。あとAlphaというエディタのカスタマイズに夢中です。で、何かと、もうしばらくかかりそうなので、小ネタでも。----http://la.ma.la/misc/js/takahashi.html思いついて10分ぐらいで完成。せっかくなので縦サイズも画面に収まるように改良、それから「----」で区切ってページ前後移動できるようにした。----権利放棄します、ご自由にお使いください。別に使わなくてもいいです。----高橋メソッドというのは、これhttp://www.rubycolor.org/takahashi/----追記オブジェクト指向バージョンを作ってみた。http://la.ma.la/misc/js/takahashi_oop.html追記　2005-04-11-やじうまWatchに紹介されたみたいです。オマケ。750byteにしてみた。http://la.ma.la/misc/js/takahashi_750.htmlブラウザによっては動かなくなってたりすると思います。IEとfirefoxで動作確認。これ以上は無理。誰か続きお願いします。----もう少しやってみた、700byte。http://la.ma.la/misc/js/takahashi_700.html懲りずにやってみた、600byte。クリックで進む、Ctrl+クリックで戻る。さすがにもう無理。http://la.ma.la/misc/js/takahashi_600.html改良バージョンなど作ったら、ここらへん書き込んでおくと良いんではないかと。http://www.hyuki.com/yukiwiki/wiki.cgi?%b9%e2%b6%b6%a5%e1%a5%bd%a5%c3%a5%c9%c8%bf%b1%fe%a5%ea%a5%f3%a5%af%bd%b8ということで。"},
{file:"diary_200504140039.htm",title:"[Ajax] JSAN構想とリモートデータの取得とUserJavaScript",mtime:1113410626,ctime:1113410626,body:"通常、JavaScriptを使って動的にデータを読み込む際には、データソースが同一ドメイン上にある必要があります。XMLHTTPRequestを使う場合でもIFRAMEを使う場合でも同様です。ですが、scriptタグを使う場合に限り、ドメインの制約を受けずにデータを取得することが出来ます。検索結果をページに貼り付けるJavaScriptなどでよく使われる方法ですが、これを応用して、外部ドメインに置いてあるライブラリやデータを動的に取得するというアプローチを考えています。同じようなことを考える人はいるもので、CPANのJavaScript版、JSANという構想がuse Perlにポストされています。http://blog.bulknews.net/mt/archives/001649.htmlで、先月からずっとライブラリばかり作ってたのですが、一応、問題なく動くレベルまでは来ているので、サンプルでも公開したいと思います。http://la.ma.la/misc/js/jsan.htmlhttp://la.ma.la/misc/js/suggest.htmlスクリプトのインポート方法の比較などは、まだ書きかけですが、ここにまとめようかと思います。http://ma.la/mirrorman/wiki.cgi/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%97%e3%83%88%e3%81%ae%e3%82%a4%e3%83%b3%e3%83%9d%e3%83%bc%e3%83%88----一つ目は、外部ドメインに置いた「ライブラリ」を動的ロードするというものです。初回実行時に、通信が発生しますが、サーバーサイドでの計算結果を取ってきているわけではありません。JavaScriptのライブラリを受信して、計算はローカルで行います。JavaScriptにはsleepが無いのでライブラリの読み込みが完了してから処理を再開する、といったことが出来ません。なのでタイマーを使って、ライブラリが読み込まれるのを監視する関数を作ってやる、という方法を取りました。同一ドメイン上からライブラリを受信する場合は、XMLHttpRequestの「同期モード」でjsファイルを受信してeval、という方法を使えば、完全に通信が終了してから処理を実行することが出来るので簡単です。(ただし通信完了までブラウザが固まるという問題はあります)実際に読み込まれるライブラリのファイルはこれです。MD5はコーディングスタイルの実験作なので、何かと余計な部分が多々あります。http://ma.la/lib/Digest/MD5.jshttp://ma.la/lib/MIME/Base64.js元のアルゴリズム部分は高度なJavaScript技集から、拝借しました。http://www.onicos.com/staff/iz/amuse/javascript/expert/関数名やライブラリへのインターフェースをPerlに似せているのは、サーバーサイドで同等の処理を行う場合の移植性を高めるため、というつもりなのですが大して意味は無いかもしれません。単なる趣味です。----二つ目は、GoogleSuggestの検索結果を読み込むというものです。外部ドメインの「データ」を取得するサンプルです。サーバーサイドでのプロキシ処理は行っていません。完全にJavaScriptだけで、Googleから直接検索結果を取得しています。検索エンジンがJavaScriptで検索結果を出力するインターフェースを備えていれば、CGIが使えないサーバーでも、クライアント側の制御だけで動的に検索結果を読み込むことができるようになります。JavaScriptでの検索結果出力といっても、現在良く使われているdocument.writeを使って画面に書き出す方式ではうまくいきません。GoogleSuggestで動的に読み込まれるコードは、親ページにある「sendRPCDone」という関数に検索結果を渡しています。特定の名前の関数に検索結果を渡してやる、という共通化されたインタフェースがあればいいのではないかな、と思います。----外部ドメインに置いたライブラリの動的ロードが出来ると、何がうれしいかというと-CPANのようにライブラリを一極集中してメンテナンスをすることが出来るようになる-アプリケーションが巨大化した場合、ライブラリを必要に応じて読み込むことで起動時間を短縮できるというのがまず考えられますが、それ以上に大きなメリットは、ライブラリのパスを自分の編集権限のあるローカルディスクなどに設定してやることで、ウェブサイトの機能を、自分で自由にカスタマイズできるようになる、ということです。スクリプトが上手く動作しない場合は、jsファイルを自分のHDDにコピーして編集し、動くように修正してやることが出来ます。新しいバージョンが気に入らない場合は、自分だけ古いバージョンを使い続けることが出来ます。あるいは、ウェブサイトを勝手にバージョンアップして、開発者にコミットしてやることが出来るようになります。これは、編集ツールがフリーではないFlashに対する大きなアドバンテージになるのではないかと考えています。他人のウェブサイトの機能を勝手に拡張するというのは、非常識なことなのかもしれませんが、Firefoxの拡張「Greasemonkey」がすでにそれを実現しています。OperaもOpera8のbeta3からUserJavaScript機能を搭載しています。http://japan.cnet.com/news/media/story/0,2000047715,20081548,00.htmUserCSSが所詮、見た目のカスタマイズしか出来ないのに対して、UserJavaScriptはウェブサイトの全ての機能をフルカスタマイズすることができます。ウェブサービス、特に検索やソーシャルブックマークなどの多くの人が頻繁に使うものについては、正しいインターフェースというものがなく、サービス運営者が使いやすいと考えるユーザーインターフェースが、他の人にとってもそうとは限りません。文字だけで良い人もいれば、サムネイル画像さえあればいい、という人もいます。機能や視覚化の手法などはユーザーが自由にカスタマイズできるように開放してやること、今後はそのあたりが重要になっていくのではないかな、とまあそんなことを考えています。"},
{file:"diary_200504220524.htm",title:"人生の経験値作成ツール",mtime:1114139897,ctime:1114139897,body:"真面目なネタを書くよりも、割とどうでもいいネタの方が、たくさんトラックバックがついたり、ネットランナーに取り上げられたりするようなので、またどうでもいいものを作ってみました。手抜きです。コード汚いです。人生の経験値作成ツールhttp://la.ma.la/misc/js/keiken.html-質問をコピペして、問題作成を押してください。-サンプルとして、どっかから拾ってきたのを入れてあります。-人の回答からコピペする場合、回答除去機能で○×△以降の文字列を削ることが出来ます。-カーソルキー、もしくは、マウスドラッグで回答ができます。-コメントを入れることもできます。----権利放棄します。ビジネスモデルを見出した方は勝手に改良して自分名義で発表してもらって構いません。進捗管理チェックシートとしても使えるかもしれません。"},
{file:"diary_200505080310.htm",title:"JavaScriptでBloglinesWebServiceを使う",mtime:1115489459,ctime:1115489459,body:"なんか原稿書いたりで忙しくてBlog書いてて〆切に間に合わなかったらマズいなヤバいなとか思いつつも、原稿書くのが忙しくてBlog更新できませんとかいうのは責任転嫁っぽくて失礼な気がするので適当に(10分ぐらいで)書いたスクリプトをアップする。JavaScriptとXMLHTTPで作ったシンプルなBloglinesWebServiceのクライアント、動作はIE系ブラウザ+ローカルhtmlファイル限定です。http://la.ma.la/misc/js/bws.htmlまずBloglinesのアカウントを持っていない人には何の役にも立ちません。アカウントを取るべきです。それから対象をファイルに保存して、エディタで開いてユーザー名とパスワードを自分のに設定してSleipnirとかで開いてください。素のIEだと、XPSP2から警告バーが出るようになってて鬱陶しいです。IEコンポーネントブラウザだと出てきません。雛形なのでスタイルシートもデザインもなにもありません。面白い機能もありません。ネタ元はこれ、そのまんまJavaScriptへの移植です。http://hail2u.net/blog/rss/bws_bloglines_sidebar.html新着チェックのAPIもあるので、新着があったら自動でバックグラウンドで取得してHTMLに出力するなんてのも割と簡単に作れると思います。XMLは不正な文字列が含まれているとエラーが出て使えませんでした。速度的には全然問題ないのでresponseText+正規表現パースの方が速かったりするのかもしれません。IEはローカルファイルからインターネットゾーンのリソースを取得できるので、こういうツールが割と簡単に作れます。IE限定かっていうとそういうわけでもなく、同一ドメイン上に設置すればクロスブラウザで動かせるはずです。まあ要するにAPIとかRSS出力さえ用意しておけばブックマークレットとかUserJavaScriptとか使って勝手にインターフェース丸ごとすげ替えAjax化とかそういうことが出来るので便利だと思う。IEとFirefoxではPUTメソッドとかも使えるようなのでAtomAPI叩いたりとかWebDAVクライアントとかもやれないことはなさそうだと思う。"},
{file:"iyana_hack.htm",title:"イヤなハックを考えてみた",mtime:1116812012,ctime:1116812012,body:"WEB+DB PRESS用にAjax記事を書いていたのですが、無茶を言って断りました。かなり迷惑かけまくってると思います、本当にすいません。理由は主に自分の文章力の無さからです。もう無理です、疲れました、限界です。南の島へ行ったりプールで泳いだりしたいです。あー遊ぶ金が欲しい。で、代わりといってはなんですが、暇になったのでこんなものを作ってみました。イヤなBlosxomフレーバー(IE限定)参考資料と解説、あと音声読み上げエンジンをインストールすると声が出ます。もっとカワイイ感じにしたかったのですが、無理がありました。というわけで、「こんなHackなら、しないほうがマシだ」に応募してみます。他にも適当に15個ぐらいメールで送っておきました。大賞のBlogHacks一年分をブックオフに売って焼肉でも食べに行きたいと思います。"},
{file:"diary_200505240642.htm",title:"Ajaxを使わずに、はてなキーワードをインクリメンタルサーチ",mtime:1116884763,ctime:1116884763,body:"Ajaxを使ったはてなキーワードインクリメンタルサーチというのをとくひろさんが作ってたので、対抗してAjaxを使わないはてなキーワードインクリメンタルサーチというのを作ってみました。http://la.ma.la/misc/hatena/CPUが遅いマシンだとブラクラなので注意。推奨2GHzぐらい。1GHzでもそこそこ快適。IE、Firefox、Opera8で動きます。safariでは動きません。最初にgzip圧縮済みキーワードリスト1.3MBを受信するので回線が遅いと利用開始までに時間がかかります。また、メモリをたくさん食います。ドキュメントを書くのが面倒くさいので気が向いたら詳しい解説を書きます。以下簡単な説明。----下準備1.キーワードリストを取ってくる2.kakasiで振り仮名をつける3.文字コードをUTF8に変換、gzip圧縮して保存JavaScriptの処理1.キーワードのリストをXMLHttpRequestを使って受信(初回のみ)2.ローマ字からmigemo風の曖昧検索用の正規表現文字列を作成する3.受信したキーワードのリストから検索、euc-jpのURLエンコードして画面に書き出しサーバー側でふりがな処理、クライアント側でローマ字かな変換と処理を分散することで、完全ではありませんがmigemo風の曖昧検索を実現しています。それから、JavaScriptでgrepをやらせるのに、今までは配列をループさせてString.search()で検索していたのですが、このキーワード検索は巨大な文字列からRegExp.exec()で検索しています。マッチする箇所が見つかったら、左右の改行位置で行を切り出し、検索開始位置をずらして次のマッチ箇所を探します。とまあ、結構面倒くさいことをやっています。今までは1000件程度ならJavaScriptで検索をやらせた方がいい、と考えていたのですが、この方式であれば、1万件ぐらいまでは余裕です。さすがに10万件はどうかと思いますが、1万件ぐらいなら余裕です。強調しておきます、1万件ぐらいまでは余裕です。この場合は件数というよりも「1MBぐらい」といったほうが正確かも。問題は、必ず最初に1.3MBをダウンロードしないといけない点で、300KBずつに分割なんかも考えたのですが、面倒くさいのでやめました。イントラネット内だとか、ローカルに保存して使うなどの場合は全然問題無いのですが、逆にそういう回線が速くてサーバーを自由にいじれる環境ならそれこそAjaxを使っておけという話になるので存在意義が微妙です。まあ、pure JavaScriptでも10万件から検索することができるよ！と、選択肢を一つ増やしてみた感じです。実際は、何が速いとか遅いとかよりも、上下カーソルで選択してエンターで開けるようにしてみたりとか、そういう細かいところのUIのチューニングの方がよっぽど重要で、Googleが頑張ってるのもまさにそのあたり。バックエンドがどうなってようとも、ユーザーにとってはどうでも良いのではないかと思います。"},
{file:"diary_200505310749.htm",title:"もんたメソッドなプレゼン作成ツール",mtime:1117513091,ctime:1117513091,body:"今回は2分で作った。手抜きですが何。まあいいや。とりあえず晒しとこう。http://la.ma.la/misc/js/monta.html降板するという話もあるので、どうなるんでしょうか、名前。----もんたメソッドとはhttp://www.bricklife.com/weblog/000626.html----追記piroたんが何か作ってるという噂。"},
{file:"diary_200506082215.htm",title:"続・JavaScriptでBloglinesWebServiceを使う",mtime:1118238750,ctime:1118238750,body:"なんか今、Bloglinesの言語設定を日本語にするとエラーが出るようになっていて、誰か文句言ってすぐに直るだろうと思ってたら、夜になっても全然ちっとも直ってなくて困った状況になってしまったのでこの前作ったBloglinesWebServiceの簡易クライアントをちょっと改造して記事本文も読めるようにしてみました。http://la.ma.la/misc/js/bws2.htmlファイルをローカルに保存して、IE及びIEコンポーネントブラウザで開いて使うことができます。通信を非同期にしてなかったり、結構いい加減な実装だったりですが、とりあえず直るまでの繋ぎということで。不満のある人は適当に改造して使ってください。改造・再配布はご自由にどうぞ。あと、ローカルファイル名をリファラとしてbloglinesに送ってしまうのですが、相手がbloglinesなのであんまり気にする必要もないと思いますが一応、気になる人は使わないでください。デスクトップに保存して使うとWindowsのユーザー名なんかがバレます。bloglinesに。日本語を含んでるフィードで変なRSSを吐く現象が前々からあるので、responseTextを正規表現でパースするようにしてみました。汎用性はないけど今のところエラーもなく安定して使えてる様子。Bloglinesから送られてくるRSSのソースを見るとわかるのですが、RSS2.0のpubDateが「水, 8 6 2005 12:03:00 GMT」とかになっていて、水はないだろう水は。----ちょこちょこ直したり。しかし、このエントリが読まれるのはbloglinesが直ってからだろうな。"},
{file:"diary_200506130100.htm",title:"テンプレートエディタを作ってみた",mtime:1118848173,ctime:1118848173,body:"こんなのを作ってみました。http://la.ma.la/misc/tmpledit/HTMLソースを貼り付けて、ページの構造をダンプすることが出来ます。とりあえずどんな感じかわかるように、このBlogのアドレスを入れてあるので取得ボタンを押すと出て来る様になってます。XMLHTTPでソース受信してるので外部ドメインのソース取得は無理です。ローカル保存+IEの場合は外部ドメインのソースも解析できます。こういう感じの作るやつ、と言えばわかりやすいかも。http://d.hatena.ne.jp/kamioka/20050609/1118324980まあ、これがやりたかっただけなのですが、ついでにCSSの編集もできるようにしてみました。CSS編集モードに切り替えると、タグ名とクラス名とIDを確認しながらプレビューしつつその場でCSSを編集できます。CSS適用ルーチンはこれの丸パクリ。http://tokyoenvious.xrea.jp/b/javascript/css_editor.html実際のHTML表示を見ながらやるよりも、普段表示されないクラス名やID名とかを可視化した状態で編集したほうが、脳にかかる負担は軽いかな、といった具合。そういうテンプレート編集に特化したCSSエディタみたいなのがあっても良いかなーなんて思って作ってみた次第ですが、保存とかつけてないので現状あまり使い物になりません。Firefoxの拡張でCSSをその場で編集とかそんなのがあった気もするけど、作ってしまったのでいいや。IEの場合は中途半端にtabが使えます。CSSの自動整形をやらせたくて、JavaScriptにCSSパーサー移植というのを、少し前に作りかけて放置しているので、気が向いたらそこら辺を組み込んでアップデートするかも。----6/15追記ちょこちょこ更新。ダンプ結果を印刷、保存用に新規ウィンドウで表示できるようにしました。あと説明書書いた。http://la.ma.la/misc/tmpledit/readme.txtそれと、アフィリエイト始めることにする。(今さら)"},
{file:"diary_200506161713.htm",title:"ミュージカルバトン",mtime:1138748521,ctime:1138748521,body:"なんか回ってきたようで、http://antipop.gs/mt/archives/001318.phphttp://d.hatena.ne.jp/nekoprotocol/20050616/1118873842全力でスルーしようかと思ったんだけれども、http://hxxk.jp/2005/06/14/2210こんなの見せられたら真面目に答えるよりもむしろ、こいつを自動化するツールを作って答えるべきなんじゃないかと、俺の使命はそれなんじゃないかと。そんなわけでミュージカルバトンに答えたエントリのURLを入れていくだけで自動でgraphvizみたいにリンク関係を視覚化して、ついでにちゃっかりアソシエイトIDを書き換えてボロ儲けするウェブサービスを作ってみましたとか書きたいのはやまやまなのだけれども、まだ出来てません。まあそれはそれでいいとして、アフィリエイトのテストも兼ねて書いてみようかと思って、一応書いてみたのですがAmazonに売ってないものばっかりになってしまったので仕方なくドラゴンボールとか混ぜることにしました。以下回答。----「今パソコンに入っている音楽ファイルの容量」-ギガバイト以上テラバイト以下「最後に買ったCD」-とんねるず「これが出光のまいどＣＤだ。」--非売品、ワゴンセールで20円ぐらいだったと思う。「今聴いている曲」-集中できないので音楽は聴かないことにした。「よく聴く、または特別な思い入れのある5曲」-猟奇が街にやって来る　人間椅子--プログラマなら人間椅子聴くよな。仕事中はもっぱらこれでした。-人面瘡　人間椅子--だらだらどろどろ血みどろじんめんそー。これも仕事中よく聴いていました。-遺言状放送　人間椅子--これもよく聴いてたな。-レッドリボンアーミー　ドラゴンボール　全曲集--レッドリボン軍を称える歌です。カラオケに入ってないのが残念です。-ベジータ様のお料理地獄　ドラゴンボールZ コンプリート・ソングコレクションII--寝付けないときはこれを聴きます。「バトンを渡す相手5人」inamode4の・ロリコンは死ぬべきだ、が持論の人・プリキュアをやめるべきか悩み中の人・プリキュアンじゃなくてこっそり転職活動中の人・大二病という単語がメジャーな単語だと勘違いしている人・リンクを張ってるだけのページを延々と続ける人・感動された人にバトンを渡したいと思います。あれ6人だ、まあいいか。"},
{file:"diary_200506201834.htm",title:"Amazon最速検索を作ってみた",mtime:1119261165,ctime:1119261165,body:"デモここから。http://la.ma.la/misc/aws/demo.html説明書はこれ。http://la.ma.la/misc/aws/-IE6、Firefox、Opera8で動作確認しています-Safariではスクリプトの動的ロードが出来ない関係で、動きません。-IFRAME内にパラメタ渡したCGIでscriptタグ生成とかやれば出来ないことも無さそうだが面倒なのでパス。このエントリで書いたhttp://la.ma.la/blog/diary_200504140039.htm＞検索エンジンがJavaScriptで検索結果を出力するインターフェースを備えていれば、CGIが使えないサーバーでも、クライアント側の制御だけで動的に検索結果を読み込むことができるようになります。この理論を実際に実践してみた、といったところです。Ajaxというよりむしろ、ブラウザベースのJSON-RPC的な何かという感じで、俺がAdaptive Pathなら新しい名前をつけてやる所なのですが、とりあえずAjaxで。Ajaxでいいと思います。開発期間は最初のバージョンに7時間、後は微調整に1日ぐらいです。注目すべき点はこれがCGIを全く使わずに動いているという点で、総ファイル数は2つ。htmlファイル(8KB)とxslファイル(6KB)、合わせて15KB以内です。後は全部Amazon任せで、他のライブラリも一切使っていません。問題としてはブラウザからAmazonに直接クエリを投げるやり方だと、不特定多数のユーザーから使われた場合に検索回数の制限をオーバーする可能性があるので、実際はサーバーサイドでのキャッシュをつけるのが望ましいだろうとは思うのだけれど、とりあえず、現時点でのバージョンをデモンストレーションとして公開することにします。もしAmazonのサーバーリソースが無限であるならば、こういうやり方もアリ、だと思います。現在のバージョンはあくまでデモンストレーションです。実際は、JavaScriptだけで動いてるなどと言っても、一般大多数にとってはどうでもいいことなので、アフィリエイト作成支援や、素早くクリッピングして本棚作成とか、そういうサーバーサイドの処理と組み合わせて完成形、ということになると思います。まあ技術的に面白いとか仕組みが面白いとかそういうことを書くのは技術者の悪い癖で、一般ユーザーにとっては、結局何ができるのかにしか興味がないわけで、けれども、あえてそういうことを書いていきたい。この不完全で中途半端な段階で公開するのは、たかだか15KBでも、高価なサーバーが無くても、少ない労力でも、それなりのものを作ることが出来るということを広く知って欲しいと思うからです。----ついでに、ライセンスのことライセンスはArtistic Licenseにします。訳文参照。http://www.opensource.jp/artistic/ja/Artistic-ja.html自分専用に改造したり、改造したものを名前を変えて公開したり、あるいは参考にして全く別のものを作るのは完全に自由です。変更点がどうとかはソース見ればわかるので、あんまり気にしなくて良いと思う。よくmisc以下に置いてある、単発のJavaScriptで作った簡単なアプリとかは基本的に著作権とか主張する以前の、単なるサンプルのようなものなので好き勝手改造して公開したり、なんかに組み込んだり、必要だと思うならオリジナルにリンク張るなりしてくれればいいです。あなたの作ったものはあなたのものです。好きにしてください。今回のはアソシエイトIDやらデベロッパートークンやらをソースに含んでいる関係で、コピーしたものをそのまま公開されると困るな、と思ったのでライセンスを明記することにしました。そんな感じです。"},
{file:"diary_200506231749.htm",title:"GoogleAutoPagerというのを作りました",mtime:1134619870,ctime:1134619870,body:"息抜きにGreasemonkeyスクリプトを作ってみました。逐次ロードを使った、もっと読むインターフェースの試作です。Trixieでも動きます。リンクを右クリックしてInstall User Scripthttp://la.ma.la/misc/userjs/GoogleAutoPager.user.js動いてる様子(Flash)http://la.ma.la/misc/demo/googleautopager.htm動かせない人も多いと思うので、どんな感じなのかわかるようにスクリーンキャプチャも作りました。あんまり作りこんでないですがとりあえず公開。GPLライセンスにします。任意の位置をダブルクリックで有効/無効が切り替わります。スクロール位置を定期的に検知し、下のほうまでスクロールしたら次のページを自動でロード、現在表示中の検索結果に継ぎ足していきます。電子辞書でよく見かける、どこまでもスクロールしていける画面のような感じです。----あんまり関係ないですが、Googleがpure JavaScriptによるXPath/XSLTライブラリをBSDライセンスで公開しています。http://goog-ajaxslt.sourceforge.net/XPathを使うとDOM走査をしなくても一発で要素選択できるので、コードの量が短くわかりやすくすっきりします。これを使えばGreasemonkeyスクリプトをIEやOperaに移植するのが楽になるんじゃないかと思ったのですが、なんかファイル足りなくてそのまま動きません。GoogleMapsで使われていたものっぽいので、ファイルかき集めてくれば動くのかも。とりあえず様子見。----追記 2005-12-15Firefox1.5と最新版のGreasemonkeyで動かなくなってます。色々機能追加しようかと思ってますが、とりあえず修正版作ってくれた方がいるのでそちらをどうぞ。http://beerboy.org/article.php?id=146"},
{file:"diary_200506252348.htm",title:"JavaScriptにBlogの全文検索をやらせてみる",mtime:1119711060,ctime:1119711060,body:"というのを作ってみました。http://la.ma.la/search.html----http://kengo.preston-net.com/archives/002021.shtmlhttp://johnvey.com/features/deliciousdirector/これ見てすげーなーと思って同時にここ数ヶ月のもやもやしていたものを文章に書き起こそうという気になったので明日にでもアップします。"},
{file:"diary_200506291043.htm",title:"XMLはメタデータというより生データとしての利用価値が高まりつつあり、AjaxによるUIの切り離しがそれを加速する",mtime:1120009499,ctime:1120009499,body:"全部まとめて色々書こうかと思ったのだけれど、どうにも上手くいかないので、少しずつ分割して書くことにする。まず最初にこれなのだけれどもhttp://johnvey.com/features/deliciousdirector/これは何かというと「JavaScriptで書かれたdel.icio.us APIのクライアント」である。最初に全てのブックマークを受信して、その後のタグによる絞込みなんかは全てJavaScriptで行う、というものだ。とりあえず、実際にこのデモを見るのが早いだろう。http://johnvey.com/features/deliciousdirector/demo.htmlこの方式では、ブックマークの件数が1万件を超えるようなケースになると破綻することがわかっている。del.icio.usのAPIでは特定のタグを含むブックマークを取り寄せることも出来るので、いちいちサーバーと通信して絞り込んでいくような実装も出来たはずだが、なぜ最初に全件受信して通信せずに検索をやらせるかと言うと、そっちの方が速いしサーバーに負担もかからないからだろう。使ってるマシンのCPUが遅くて、回線だけは光速で、del.icio.usのサーバーのCPUリソースが余りまくっているのであれば、サーバーサイドで検索をやらせたほうが速い、ということになるが、そういうケースの方が稀である。実際は個人のブックマークの件数などタカが知れているので、最初に全部受信したほうが良い、ということになる。----重要なことは何か。「del.icio.us direc.torはどこでも使える」ということだ。del.icio.usのキラーアプリケーションというような記述も見かけたが、何もこれは「del.icio.us専用」というわけではない。例えば、この優れたタグブラウザをはてなブックマークで使いたいと思う人がいたとして、はてなブックマークがdel.icio.usと同じ形式で出力するAPIを備えていれば、後はチョコチョコと変更を加えるだけで、ほとんどそのまま動かすことが出来るはずだ。あくまでも、APIが提供されていればの話だが「この程度」のインターフェースであれば、どこでも見かけることが出来るようになるだろう。Ajaxと他のリッチクライアントの最も大きな違いはここにある。強制オープンソースであるゆえに、全てのコードとノウハウは簡単に使い回すことができ、そして、恐ろしい速度で進歩している。ウェブサービスが共通のAPIを備えていて、XMLによる生データの提供がされていれば、Ajaxを使って最強に強まったユーザーインターフェースが、どこにでも移植可能である、ということ。----例えば検索エンジンであれば、検索結果をRSSで出力して、OpenSearchに対応させればいくらでもインターフェースは交換が利くようになる。今はまだOpenSearchに対応することはA9で検索できるようになる程度にしか思われていないけれども、OpenSearch用のA9よりも使いやすい最強に強まったユーザーインターフェースが公開されたとすれば、OpenSearchに対応するということはリッチで使いやすいインターフェースをゼロコストで利用可能になるという極めて大きな意味を持つことになる。ウェブサービスはあらゆる情報をXMLで提供し、ユーザーはそれを自分の好きな形にレンダリングして表示するようになる。AjaxはつまるところXMLビジュアライザーであり、ユーザーインターフェースの交換装置なのである。今すぐ急いでAjaxに対応、などする必要はない。APIを公開して生データにアクセスできるように開放することと、Ajaxに対応することは実は殆ど同じである。----結局、何が言いたいのかというとHTMLがメインのデータでXMLがメタデータ、という時代が終わり、XMLこそがメインのデータであり、HTMLはXMLを変換整形した結果に過ぎないという変化が起こりつつある、ということだ。それはごく限られた市場での話で、今はまだRSSリーダーを使ってる一部の情報ジャンキーぐらいしか実感していないことだけれども、確実に起こっている流れだ。データとメタデータの主従逆転が起こっているのである。全文配信されるようになったRSSは、もはやメタデータというよりもRawDataとでも言うべきものであり、BlogがRSSを吐くのではなく、RSSをHTMLへ変換した結果が、いわゆる今見ているBlogなのである。本来ならばHTMLは論理的なマークアップをしてやれば、後はブラウザがユーザーに合わせて勝手に見やすく整形してくれる、そういうものだったはずだが、いつからか1ピクセル単位で正確にレンダリングされることを求められるようになり、CSSによって文書構造とデザインが分離されるだの言ってもスタイルシートの切り替えボタンがデフォルトで見やすい位置にくっついているのはOperaだけだ。HTMLはすでにデータそのものを記述するには複雑怪奇になりすぎていて、その結果CSSとJavaScriptを駆使したバッドノウハウまみれのリッチインターフェースを構築するためのアプリケーションプラットフォームとして再利用されることが業界の主流となり、コンテンツそのものの記述はXMLが担うことになる。つまるところ大切なことはXMLによる生データを提供することで、それを視覚化する方法としてHTML+JavaScript(つまりAjax)を使うのはバッドノウハウまみれだけれど悪くない選択肢で、むしろ普及率や実行速度、開発の容易さなどを考えるとベストである。ここらへんはあくまで個人的な意見だ。"},
{file:"diary_200507050135.htm",title:"IEにFirefox風検索バーをくっつけるBookmarklet",mtime:1120494979,ctime:1120494979,body:"というのを作ってみました。このページで試してみる(IE限定)ローマ字のまま検索できるので、例えばmohicanでモヒカンにヒットします。例えばこんな具合。http://la.ma.la/misc/demo/isearch.htm上記ブックマークレットで他のページでも動かせますが、リファラが付くとイヤなのでやめてください。いきなりクッキー盗んだりするスクリプトに化ける可能性があるので、ローカルに保存して動作させることを推奨します。で、ファイル保存してJavaScript書き換えてリンクバーに登録とかいう作業は非常に面倒くさいと思うので、ブックマークレットで使うjsファイルの中にWSHを使ったインストーラーを書いてみた。----インストール方法http://la.ma.la/misc/bookmarklet/isearch.jsこのファイルを適当なフォルダに保存してダブルクリックで実行。インストーラーが起動するようになってます。XPSP2だと警告出ると思いますがOKで。信用ならない場合はソース確認して実行してください。Bookmarkletをクリップボードにコピーと、IEのリンクバーに追加ができます。Sleipnir用スクリプトも作ってみました。http://la.ma.la/misc/bookmarklet/sleipnir_isearch.zipsleipnir\\user\\ユーザー名\\scriptsフォルダに解凍してください。「ツール」に登録しておけば、ショートカットキーやマウスジェスチャで起動できます。試しにCtrl+Fを標準のダイアログと置き換えてみましたが、Firefoxもどきという感じで割と快適に使えます。ただ、JavaScriptを有効にしてないと使えないので、ちょっと困るかも。----オリジナルはこれです。http://d.hatena.ne.jp/leibniz/20050701/1120232028ライセンスはオリジナルにしたがってArtistic Licenseとします。フレームまたがって検索できなかったり、何かと不具合あります。動作無保証、自己責任で使ってください、という感じで。JavaScriptでここまでできるのか！という感じのデモではあるのですが、IEの標準のページ内検索機能も内部的にはJavaScriptで実装されているので、実はあんまりすごくないかも。"},
{file:"diary_200507070648.htm",title:"日本語テキストをテーブルで表示するJavaScriptの高速化",mtime:1120686543,ctime:1120686543,body:"いやなブログ: 日本語テキストをテーブルで表示するhttp://namazu.org/~satoru/blog/archives/000039.htmlを高速化してみた。http://la.ma.la/misc/js/tablefont.htmlオリジナルは多分、あえてDOMでテーブルを作っていると思うのだけれど、innerHTMLを使って書き直してみた。IEで6倍ぐらい、Firefoxで4倍、Operaで3倍速い。ちなみに手元の環境ではOpera8 : 30ミリ秒Firefox : 100ミリ秒IE : 360ミリ秒ぐらいになった。Operaは7までJavaScriptやDOM周りの操作が遅い遅いと言われていたのだけれど、Opera8になって何だか妙なチューニングが施されている。今はOperaは何かと癖があって扱いづらいのだけど、ブラウザベースのリッチクライアントが普及してくるとJavaScriptの実行速度がブラウザのシェアに影響を与えたりするのかもしれない。JavaScriptの高速化には色々とテクニックがあるので、そのうちチューニングガイドでも書こうかな、と思ってる。DOMとinnerHTMLのパフォーマンスの違いについてはここら辺に詳しい。http://www.quirksmode.org/dom/innerhtml.html"},
{file:"diary_200507101154.htm",title:"prototype.jsのObject汚染を回避する方法",mtime:1121140567,ctime:1121140567,body:"かなりターゲットの狭いTips。役に立たない。prototype.jsというRuby on Railsなんかのフレームワークで使われている有名なJavaScriptのライブラリがあって、これが色々と使えそうな処理を綺麗に詰め込んであり、デファクトスタンダート的な地位を確立しているのだけれど、ちょっと微妙だなーと思うところがあって、それはObject.prototypeを拡張してしまう点。実際の弊害はこういう。http://d.hatena.ne.jp/nazoking/20050425/1114374966要は連想配列として使うときに困るって話。多分prototype.jsはJavaScriptの側でロジックを組むことをあまり想定していないため、この辺の問題にあんまり配慮していないのではないかと思うのだけれど、とりあえず無理やり回避する方法を思いついたので書いてみる。http://la.ma.la/misc/js/prototype.htmlIFRAMEを作ってやって、その中でObjectやArrayなんかを作成してやれば、何にも拡張されていない素の状態のオブジェクトを返すことが出来る、という具合。どっちにしろ面倒くさいので微妙、使う機会があるのかどうか。もっと真っ当な方法があるのかも知れない。----ついでだから後二つぐらいTipsを。インストールされているフォント一覧取得(IE限定)http://la.ma.la/misc/js/fontbrowse.htmlバックグラウンドで一覧を勝手に収集して、フォントの普及率を調査するページとか作れそうだな、とか、考えたことがあった。マウスのホイール操作を検知する(IEとFirefox限定)http://la.ma.la/misc/js/wheel.htmlあんまり使われてない気がするけど、JavaScriptでマウスのホイールイベントを拾ってくることが出来る。IEの場合はonmousewheel、Firefoxの場合はDOMMouseScrollというイベントハンドラが使える。IEとFirefoxで使えればカバー範囲は十分広いと思うので、もっと積極的に使っても良い気がする。----追記 07/12一応書いておくと、これは「IFRAMEを使うことで別のJavaScript実行環境を作れる」という、いわゆるネタです。ビルトインオブジェクトをオーバーライドすると便利なんだけども影響が気になる、という時に使えるかもしれない。上記のサンプルでも使っているけど、普通のやり方だとprototypeに含まれている要素を除外して処理する関数を作ったり、メソッドを加えてやれば良いと思う。多分こんな感じ。	Object.prototype.forEach = function(func){		for(var key in this){			if(!(key in this.constructor.prototype)){				func(this[key],key,this)			}else if(this[key] != this.constructor.prototype[key]){				func(this[key],key,this)			}		}	};	obj.forEach(function(value,key,self){		alert([value,key]);	});で、これをやるとますますObject.prototypeが汚染される上、yomi[\"forEach\"] = \"ふぉーいーち\"という連想配列に対してはforEachメソッドが使えなくなるという罠もある。自前のクラスを作るにしても全部Objectオブジェクトがベースになるので、個人的にはObjectはなるべくプレーンな状態で残しておいた方が望ましいと思う。ただ、prototype.jsに関してはObject.extend()一つでコード量を大幅に減らせているメリットの方が大きいと思うので、その恩恵を受けつつもプレーンな状態のObjectを作成するにはIFRAME内で実行するぐらいしか思いつかなかった、という話。----さらに追記プロパティが、そのインスタンスに固有なのか、クラスに元々存在しているのかを調べるにはhasOwnPropertyというのを使えば良いらしい。http://www.interq.or.jp/student/exeal/dss/ref/jscript/object/objects.html#hasOwnProperty上記のコードはこれで良さそう。prototypeに含まれていない要素のみ回すforEach。	Object.prototype.forEach = function(func){		for(var key in this){			if(this.hasOwnProperty(key)){				func(this[key],key,this)			}		}	};オブジェクト指向良くわかってないので用語の使い方とか怪しいかもしれない。"},
{file:"diary_200507101222.htm",title:"マウスホイールを使って何が出来るか",mtime:1120965792,ctime:1120965792,body:"あまり気が進まなかったのだが、サンプルとして適当だったので作ってみた。Winkで作ったデモ。http://la.ma.la/misc/demo/rssroll.htmGreasemonkeyスクリプト、Firefox限定http://la.ma.la/misc/userjs/HatenaRssRolling.user.jsデモ見てもわかりづらいが、見出しの部分の上でマウスホイールを回転させるとアイテムがロールする、クリックで開閉。マウスを動かさずに読むことが出来る、というもの。いまいちだったのでカーソル上下左右でも回転と開閉できるようにしてみた。はてなは敵なので作りこむ予定無し。Firefoxでマウスホイールにイベントを割り当てたときにスクロールをキャンセルする方法が全然わかんなかったのだが「event.preventDefault()」というのを使えば良いことがわかった。IEの場合の「event.returnValue=false」に相当するようだ。DOMMouseScrollにしてもそうだが、preventDefaultについても検索結果があまりに少ないような気がする。というわけで、JavaScriptでイベントをキャンセルするサンプルつるつるして気持ち悪いページを作ることが出来る。http://la.ma.la/misc/js/cancel.htmlこのあたりはブラウザごとに癖があるので使いどころが難しいのだが、Firefoxだとキーボードの操作を何でもキャンセルできるっぽいのでブラウザ上で完全なキーバインド割り当てが出来そうだ。F5リロードなんかも無効にすることができる。XULアプリを作ることを考えると、完全にコントロール出来ないとおかしいわけだけど普通のHTML上でもできる。つまりCtrl+Sでページを保存するWikiとか作れそうだ。Sleipnirなんかの場合は、ブラウザ本体のショートカットが何よりも優先されるので、Ctrl+Sの上書きは無理。"},
{file:"diary_200507101448.htm",title:"リアル・タイム・マシーン展の遅延マリオを再現するGreasemonkeyスクリプト",mtime:1120974536,ctime:1120974536,body:"リアル・タイム・マシーン展http://realtimemachine.dotimpac.to/に、行ってきた。内容を口で説明するのが難しいのでGreasemonkeyスクリプトを書いてみた。Firefox専用。意味がわかる人がどれだけいるのか、という話ではある。これをインストールしてhttp://la.ma.la/misc/userjs/DelayMaryo.user.jsここへhttp://www.janis.or.jp/users/segabito/JavaScriptMaryo.html"},
{file:"diary_200507160912.htm",title:"ページレンダリングを妨げない広告挿入手法に関する覚書",mtime:1121472835,ctime:1121472835,body:"多分わかる人にはわかると思うんだけど、わかんない人にはわかんないと思うので、誰かわかりやすく書き直してくれると助かるんだけどとりあえず書いておく。例えば、GoogleAdsenseなんかで広告を挿入するには、外部ドメインに置いたJavaScriptを読み込んで使う。セキュリティ上の問題があるにもかかわらず外部ドメインのJavaScriptをそのドメインにあるかのように取り込めるのは、多分、そういう需要があるからだろう。 んで、そういうスクリプトの構成というのは大抵、scriptタグを挿入した位置に広告がdocument.writeを使って書き出される、というものだ。しかしこの方法には問題があって、それはscriptがロードされて実行が完了するまでページのレンダリングが止まる、ということだ。jsファイルを受信するまでにかかる時間と、解釈と実行、document.writeでブラウザに出力する、この間ブラウザはscriptタグを挿入した位置でHTMLをぶった切って表示できる範囲まで表示する、という動作をする。例えば-ヘッダ-広告-本文というような順番でページを構成した場合、広告JavaScriptがロードされて、実行完了するまで5秒かかったら、本文が表示されないまま5秒間ユーザーは待たされることになる。もし、-ヘッダ-本文-サイドバーというような後置型サイドバーの構成で、サイドバーに広告を入れる場合は、本文が先に表示されるので、ユーザーを待たせずに本文を読むことが出来る。広告JavaScriptのロードに5秒かかっても、とりあえず本文を先に読むことが出来る。という違いがある。GoogleAdsenseなんかをページに挟んでいる場合、その場所で若干レンダリングがもたつくのを体感したことのある人は多いはず、多いと思う。これはブラウザの正常な挙動である。scriptの実行が完了するまでページ全体がどういう構成になるのかわからないのだから仕方ない。GoogleAdsenseの広告挿入スクリプトは、これだ。http://pagead2.googlesyndication.com/pagead/show_ads.jsGoogleの取っている手法は-jsファイルは動的に生成しないで、共通のコードを使う。-本体HTML側で指定したパラメータに応じてIFRAMEを生成するつまり固定のJavaScriptで、動的に生成されたIFRAMEを埋め込んでいるわけだ。jsファイルに対してはブラウザのキャッシュが最大限利くようになる。とりあえず最速でjsファイルは渡しておいて、動的に生成されたIFRAMEが表示される。IFRAMEの中の表示が多少遅れても、ページのレンダリングには影響を与えずにすむ。これはJavaScript自体を動的に生成するよりも、若干スマートである。JavaScript自体を動的に生成してしまうとブラウザのキャッシュが利かないのでページ毎に毎回ダウンロードする必要がある。しかし、いずれにせよshow_ads.jsがキャッシュされていなかった場合は、jsファイルをダウンロードするまでに若干の時間がかかることになる。またIFRAMEを挿入するためにページのレンダリングはそこでいったん止まる。Googleのサーバーはレスポンスが速いので、気にしている人は少ないと思うけれど、もしこれが0.1秒でなくて1秒～2秒程度の遅延があるなら、明確に広告挿入はユーザーのストレスと結びつく。これはテーブルレイアウトだとレンダリングが遅いとか、そういうのと同系統の問題なんだけど、あんまり触れられていないような気がする。外部サーバーに置いてある画像を直リンクで表示する場合は、サーバーのレスポンスが遅くてもとりあえずページ全体のレンダリングは出来るようになっている。しかし、外部サーバーに置いてあるスクリプトを取り込む場合、一番レスポンスが遅いサーバーにページの描画全体が引きずられることになる。しかし、このページのレンダリングが遅れるという現象は、コードの書き方を少し工夫すれば解消することが出来る。----どうすればいいのか、というと。広告表示用の領域を、あらかじめ固定の幅と高さで作っておいてやり、scriptのロードが完了したらその領域をスワップする、という方法であればjsファイルのロードが遅れたとしてもページのレンダリングを妨げることは無い。例えば俺だったら本体HTMLの側でADS_TARGET_ID = \"任意のID\"広告JavaScriptの側でdocument.getElementById(ADS_TARGET_ID).innerHTML = 広告HTMLというような作りにするだろう。innerHTMLじゃなくてappendChildでもいいけど。id=ADS_TARGET_IDの領域はスタイルシートを使ってあらかじめ表示される広告のサイズに合わせておけば、不要な再描画を避けることが出来るはずだ。script要素にはdefer属性を指定しておく。defer属性が付いていれば、スクリプトのロードを待たずにページをレンダリングすることが出来る。document.writeは確かにscriptの挿入位置が広告挿入位置でわかりやすいけれど、サーバーのレスポンスが遅ければ広告が挿入されているページの表示全てに支障をきたすので、そろそろやめにしてもいいんじゃないの、っていう。これは広告だけの話ではなくて、例えばJavaScriptを使ってRSSのヘッドラインを貼り付けるようなサービスなんかでも同じことが言える。まあ、そういう提案なんだけども、具体的になんか作らないと説得力無いので、続く。"},
{file:"diary_200507182009.htm",title:"むしろdocument.writeの方を書き換えて遅延ロードを実現する",mtime:1121685001,ctime:1121685001,body:"一つ前のエントリの続き。document.writeを使うデメリットは一個前に書いたとおり、jsファイルを置いてあるサーバーのレスポンスに引きずられてページの描画が遅くなる、ということなんだけど広告にせよRSS貼り付けにせよ、どれもこれもdocument.writeで表示するHTMLを書き出すものばかりなので、むしろdocument.writeの方を書き換えてみることにした。ビフォーhttp://la.ma.la/misc/js/feed2js_old.htmlアフターhttp://la.ma.la/misc/js/feed2js.htmlFeed2JSというサービスを使っている。http://jade.mcli.dist.maricopa.edu/feed/本来は、Scriptタグの挿入位置にRSSやAtomフィードを貼り付けるサービスだ。前者が本来の使い方で、document.writeでHTMLが書き出されて、これをスタイルシートで装飾して使う。上の例では、ヘッダの次の位置に挿入してあるのでスクリプトのロードが完了するまで、フッターが描画できない。後者は、document.writeを自前の関数で「上書き」して、いったんJavaScriptのオブジェクトに格納してからページに追加している。この方法であればスクリプトのロードが完了する前にページ全体を描画することが出来る。サーバーのレスポンスが遅れても、先にページ全体が描画されているので閲覧には支障が無い。scriptタグを動的に追加してやれば、ページの描画が完了した後からアイテムを追加することもできる。応用すれば完全なRSSリーダーも作れるだろう。で、あんまり酷使するとサーバー負荷が気になるところだが、ミラーサイトもたくさんあるようなので、接続先を振り分けてやることもできるだろう。http://jade.mcli.dist.maricopa.edu/feed/index.php?s=mirrorsこれは結構無理やりな方法なので、本当はFeed2JSじゃなくてFeed2JSONが欲しいところなんだけども。つまり何が言いたいかというと色んなサイトがRSSを吐いてくれて、RSSをJSONに変換するようなサービスがあって、そのミラーがたくさんあれば、余っている回線とCPUパワーを分散コンピューティング的に使って、サーバーの負荷を気にすることなくRemixだのなんだのに使うことが出来る。という話。"},
{file:"diary_200507251926.htm",title:"ホイール回転でAmazonのカートを少し便利にする",mtime:1122291318,ctime:1122291318,body:"今、Amazon最速検索の改良バージョンを作っているのだが、Amazonはカートに入れるのは簡単なのにカートから削除するのとかがとても面倒くさい。そんなわけなのでホイール回転で注文数を変更できるようにするBookmarkletを書いてみた。input type=textで、かつ、数値が入っている入力ボックス上でホイールを回転させると数値を変更できる。IEとFirefox兼用、他のブラウザはホイールを使えないので無理。ホイールマウスを持っていない人が切なくなるが、持ってる人が便利なのに越したことはない。こんな感じで動く。http://la.ma.la/misc/demo/amazonwheel.htmBookmarkletホイールで数量変更Greasemonkeyスクリプトにしてみた。内容は同じ。http://la.ma.la/misc/userjs/AmazonCartHelper.user.jsAmazonのカートを想定して作ったけれど、日付を入れるようなボックスとか、他にも何かと使い回しが利くはず。逆に言うと、こういう改良が利くので日付を入れるようなボックスはプルダウンメニューではなくて、普通のテキストボックスの方が良いと思う。----技術的な解説。改行抜きで見づらいが、短いのでまあいいか。javascript:(function(){var inp=document.getElementsByTagName(\"input\");for(var i=0;i&lt;inp.length;i++){var c=inp[i];if(c.type==\"text\"&amp;&amp;c.value!=\"\"&amp;&amp;!isNaN(c.value)){var mkfunc=function(t){return function(e){var ct=e.wheelDelta||(e.preventDefault(),-e.detail);ct&lt;0?t.value++:(t.value&gt;0)?t.value--:0;return false}};var func=mkfunc(c);c.attachEvent?c.attachEvent(\"onmousewheel\",func):c.addEventListener(\"DOMMouseScroll\",func,false);}}})();mkfuncが関数を返す関数で、現在のループ中で選択されているinputボックスへの参照を残している。例えば対象となるinput要素が10000個あったら別々の「無名関数」が10000個できる、といった具合。クロージャというらしいですが綴りがよくわからないので、いつも関数を作るということでmkfuncとかそういう名前を使ってます。逆に、変数に「名前付きの」関数を代入してやるとうまくいかない。javascript:(function(){var inp=document.getElementsByTagName(\"input\");for(var i=0;i&lt;inp.length;i++){var n=inp[i];if(n.type==\"text\"&amp;&amp;n.value!=\"\"&amp;&amp;!isNaN(n.value)){var c=n;var func=function(e){var ct=e.wheelDelta||(e.preventDefault(),-e.detail);ct&lt;0?c.value++:(c.value&gt;0)?c.value--:0;return false};c.attachEvent?c.attachEvent(\"onmousewheel\",func):c.addEventListener(\"DOMMouseScroll\",func,false);}}})();これは少し変わった動作をする。funcが「同じ関数」を参照してしまい、その関数内で使われている変数の参照先がループによって上書きされる。具体的には一番最後のinputボックスの数値が変化するようになる。つまりこうなる。http://la.ma.la/misc/demo/scopechain.htmちょっとした神秘だ。別にクロージャを使わなくても同等のことは出来て、IE用のe.srcElementとFirefox用のe.targetを関数内で分岐させれば良い。javascript:(function(){var inp=document.getElementsByTagName(\"input\");for(var i=0;i&lt;inp.length;i++){var c=inp[i];if(c.type==\"text\"&amp;&amp;c.value!=\"\"&amp;&amp;!isNaN(c.value)){var func=function(e){var t=e.srcElement||e.target;var ct=e.wheelDelta||(e.preventDefault(),-e.detail);ct&lt;0?t.value++:(t.value&gt;0)?t.value--:0;return false};c.attachEvent?c.attachEvent(\"onmousewheel\",func):c.addEventListener(\"DOMMouseScroll\",func,false);}}})();こっちの方が普通だし、メモリにもやさしい。ようするにクロージャとかカッコいい言葉を使ってみたかっただけだ。----まあ、こんなことはどうでも良くて、たかだか500byteでユーザビリティを劇的に改善することが出来るのだということをあなた方は知らなさ過ぎるのです。"},
{file:"diary_200507272102.htm",title:"ペイント暗号解読ツール",mtime:1122465768,ctime:1122465768,body:"http://la.ma.la/misc/js/paint.htmlこれの簡易デコーダ。http://semimaru.s47.xrea.com/blog/log/eid17.html興をそぐので注意。作成補助にも使えるかもしんない。やじうまWatch経由http://internet.watch.impress.co.jp/static/yajiuma/"},
{file:"diary_200507290022.htm",title:"Ajaxを使ったシンプルなチャット",mtime:1122596340,ctime:1122596340,body:"を作ってみました。http://la.ma.la/misc/ajaxchat/サーバーサイドのソースは5行です。http://la.ma.la/misc/ajaxchat/write.txtCGIを使うのは書き込みの時だけで、表示はXMLHttpRequestを使ってログファイルを直接読み込みます。更新は差分取得で転送量とサーバー負荷を減らしています。IEとFirefoxでしか動きません。Operaはリクエストヘッダのセットが使えないので無理。仕組み-HEADリクエストでログファイルのサイズを取得-ファイル末尾1KBを取得-レスポンスヘッダから最終更新日と現在のファイルサイズを保存-If-Modified-SinceとRangeヘッダをセットして定期リロードとりあえずこれだけです。参加者表示も何もつけてませんが、改造の雛形にでもどうぞ。Range付きのリクエストは昔試したときに、ヘッダをセットしても全部取得しちゃったりと、どうにもうまくいかなかった記憶があって試してなかったのだけど、なんかうまくいくようになってる様子。こういうのを使えば負荷を極限まで減らせるわけで、カリカリにチューニングされたデータベースと、単純な追記式のログファイルだと、どちらが負荷が少ないのか気になるところ。DATA[count++]={name:\"名前\",comment:\"コメント1\"}DATA[count++]={name:\"名前\",comment:\"コメント2\",mail:\"メール\"}DATA[count++]={name:\"名前\",comment:\"コメント3\"}こんな感じにすれば、追記式で柔軟なデータ構造も保存できるんじゃないか、と考えていて、これだとJSONというかJavaScriptのコードって感じだけど。----Rangeリクエストを試したきっかけは、これなんだけどhttp://ajaxdb.jp/これ自体は微妙というかなんというか、Rangeリクエストはブラウザのキャッシュが利かないので、データベースとして使うならあらかじめファイルを分割しておくのが普通だと思う。例えばこれ。http://www.oldriver.org/jsmigemo/pure JavaScriptによるmigemoで、あらかじめ分割しておいた辞書を動的にロードすることで実現しています。やればできるものだなあ、と関心。----追記Operaは8.01からsetRequestHeaderが定義されていますが、実際に送信するヘッダに反映されないようです。8.02でも同上。8.02はなにやらPOSTメソッドの場合には反映される様子。IEやFirefoxだと、自分で定義したヘッダを追加したり、HTTPで定義されてないメソッド使ったり、基本的に何でも出来るのですがRefererやAccpect-Encodingなんかは書き換えられなかったと思う。(あんま検証してない)"},
{file:"diary_200507302354.htm",title:"Function.prototypeを拡張して遅延実行を実現する",mtime:1122757190,ctime:1122757190,body:"JavaScriptにおいて関数というのはFunctionオブジェクトで、他のビルトインオブジェクトと同様に、組み込みのメソッドがある。これがapplyとcallしかないのだけれど、こんな感じに使う。func.apply(thisObj,arguments)func.call(thisObj,arg1,arg2,arg3)thisObjには、その関数内で「this」として使うオブジェクトを指定する。applyの第二引数はargumentsオブジェクトを指定する。配列か、現在実行中の関数のargumentsオブジェクトを丸ごと別の関数に引き渡せる。つまり引数の長さが良くわかってなくても使える。callは代わりにfunc.apply(thisObj,[arg1,arg2,arg3])と書けるので、実はいらないんじゃないかと思う。これらは多分、ふつうにJavaScriptを書く上では全然必要でないし、知らなければ知らないでまったく問題にはならない。リファレンスなんかを見ても、リファレンス的な解説のみで具体的な使い方は書いていないと思う。有名なのは引数の束縛とかそういうやつなのだけれどhttp://www.interq.or.jp/student/exeal/dss/ejs/1/4.html正直、これを読んでもどういうメリットがあるのかいまいち良くわからなかった。でも、知っていれば知っているなりの書き方がある。で、具体的に作ったのがこれ。Object.extend = function(destination, source) {	for (property in source) {		if(source.hasOwnProperty(property)){			destination[property] = source[property];		}	}	return destination;}Object.prototype.extend = function(object) {	return Object.extend.apply(this, [this, object]);}Function.prototype.extend({	later : function(ms){		var self = this;		var func = function(){			var arg = func.arguments;			var apply_to = this;			var later_func = function(){				self.apply(apply_to,arg)			};			setTimeout(later_func,ms);		};		return func;	}});var func = function(v){alert(v)};func.later(1000)(\"1秒後に警告\");func.later(2000)(\"2秒後に警告\");func.later(1000).later(2000)(\"3秒後に警告\");(function(v){alert(v);arguments.callee.later(1000)(v)}).later(1000)(\"1秒ごとに実行\")Function.prototypeを拡張して、laterメソッドを加えてやる。加えるというのは正確ではなく、func.laterが見つからなかった場合に、Function.prototype.laterが実行されるようになる。これだけで、いちいち無名関数作ってsetTimeoutなんて書かなくても、あらゆる関数を簡単に遅延実行させることが出来るようになる。Object.extendは便利だから使いまくる方向で。でもprototypeはコピーしないように改造した。何をするコードかというと、元の関数を「1秒後に実行する関数」を生成して、返ってきた関数に引数を渡して実行する。この例だと引数は一つだけれど、複数の引数を必要とする関数でも同様に可能だ。「1秒後に実行」ではないので、生成された関数をさらに加工することが出来る。三番目は1秒後に実行される関数をさらに2秒遅らせて実行する。4番目はこれでもいい。var interval = 1000;(function(v){alert(v);arguments.callee.later(interval)(v)}).later(interval)(\"1秒ごとに実行\");実行中にinterval = 3000とかやったら実行中に外から周期を変更できる。arguments.calleeは現在実行されている関数の参照を表していて、これを使うと再起処理なんかをするのに関数名を決めうちにしなくて良い。とまあ、こんな具合。----追記later(1000).apply(this,arg)とかが動くように、ちょいと直した。1秒後に別のオブジェクトに変形するオブジェクトとか作れる。"},
{file:"diary_200507312214.htm",title:"Amazon最速検索β",mtime:1122815881,ctime:1122815881,body:"アップしました。まだベータです。http://la.ma.la/misc/aws/beta.html早いうちにECS4に対応しようかと思ってたのですが、先にユーザーインターフェースのほうに色々手を加えました。ファイルサイズがやや大きくなってますが、ローカルにダウンロードしても動かしやすいように1ファイルにしました。主な変更点-作者、出版社で検索結果を辿れるようになった-商品をドラッグで選択、まとめてカートに入れる機能-カスタム表示機能-検索結果を絞り込み-Firefoxのクイックサーチに対応-その他いろいろ。Firefoxの「この検索にキーワードを設定」で登録できます。こんな感じで。http://la.ma.la/misc/demo/quicksearch.htmなにげにこの機能、すごく便利だと思う。検索プラグインよりもこっちの方がいい気がする。というわけで、一応、検索結果にリンクを張ることが出来るようになってますが、betaなので将来的にクエリの書式は変わると思います。カートに加える/まとめてカートに入れる機能は、Amazonのフォームを真似て作っても動くみたいですが、正式にサポートされている方法で実装しました。http://aws.typepad.com/aws_jp/2004/12/ecs.htmlウィッシュリストに加えるフォームも付けてみました。後で買うのに便利ですが、紹介料が入らないのでおすすめできない。カスタム表示機能は、とりあえず手をつけてみた感じでまだ中途半端。テンプレートを保存して共有したりする機能を付けて、将来的にはこれがメインになると思う。----技術的な解説表示カスタマイズ用にText.QuickTemplateというのを書きました。これを参考にして作った、単純な穴埋めだけのテンプレートエンジンです。http://search.cpan.org/~roode/Text-QuickTemplate/ビルトインオブジェクトをあれこれと拡張してます。Function.laterString.fillString.fill_exprArray.eachArray.mapArray.loopObject.extendObject.eachObject.keysObject.valuesObject.loopNumber.timesこれだけ加えました。String.fillというのが肝で、QuickTemplateへのエイリアスみたいなものです。こんな感じで使います。\"My name is {{name}}\".fill({name:\"John\"}); //→ My name is John\"item\".fill(item);これだとidが「tmpl_item」の要素のinnerHTMLを拾ってきてマッピングします。テンプレートはHTML中にコメントで埋め込んであって、比較的いじりやすいと思う。toStringをオーバーライドすれば複雑なことも出来るので、実はあんまり高機能なテンプレートエンジンって必要ないような気がする。JSANにアップとかしたいのだけれど、使い方がいまいちわからない。実際にFunction.laterとか使ったりしてます。例えば連続で検索するのには最低1秒のウェイトが入るようになっていますが、do_request.later(500)(query)という具合に「500ミリ秒後に再試行」という動作を簡単に書けます。prototype拡張セットは作っとくと何かと便利なのだけど、他のライブラリなんかとバッティングする可能性もあるので、標準セットみたいなのがあるといいのかなあ、とか。とりあえず他の言語を真似て、必要そうなのを色々作ってみようかな、と思ってます。"},
{file:"diary_200508081622.htm",title:"XSLエディタを作ってみた",mtime:1123485779,ctime:1123485779,body:"XSLをエディタで編集してはブラウザでプレビューなんてことを何千回とやっているので、なんか良さげなXSLエディタがあるなら使いたいんだけど探しても見つからないので作ってみた。http://la.ma.la/misc/xsltedit/左にXSLを入れて右にXMLを入れて、XSLを編集しつつCtrl+EnterでXSLT変換。Google AJAXSLTを使ってみました。というか同梱のサンプルのスタイルをちょっといじっただけ。なんかIE6で動かないというので、フォーラム見てちょこちょこ直して動くようにしました。次のバージョンで直るとかなんとか。とりあえずそのまま圧縮したのを置いておきます。http://la.ma.la/misc/xsltedit/xslt.zipブラウザの機能で変換させたほうが速いんだろうけど、そんなに遅いわけでもない。ただ、文法的にエラーがあっても変換してくれたりするので、開発に役に立つかというと微妙かも。XSLを書く人は普段どういうツールを使っているのだろうか。というかXSLを使いこなせる人って存在するんだろうか。"},
{file:"diary_200508141140.htm",title:"JavaScriptのデザインパターン - Singleton",mtime:1123988780,ctime:1123988780,body:"JavaScriptじゃねえと書けねえよ、ってやり方でデザインパターンを実装してみるコーナー。とはいってもデザインパターンとか良くわからないので適当に覚えながら作る。間違ってる箇所あったらつっこんでくれるとありがたいです。わかりやすい文章を書く能力が欠如してるのでデザインパターンって何だとかそういうのはこっち参照。http://d.hatena.ne.jp/naoya/20050813/1123924312JavaScriptのコンストラクタはPerl同様自在に定義できます。returnでobjectを返してやれば、newの結果としてそいつを使います。普通にシングルトンなクラスを実装するにはこんな感じだと思います。function Singleton(){	var self = arguments.callee;	if(self.instance == null){		this.initialize.apply(this,arguments);		self.instance = this;	}	return self.instance;}Singleton.prototype = {	initialize : function(o){		this.foo = o;	}};var a = new Singleton(\"aaa\");var b = new Singleton();var c = Singleton.instance;alert(a.foo); // aaaalert(a==b); // truealert(b==c); // true 全部おんなじarguments.calleeは実行中の関数を参照します。コンストラクタ関数のinstanceプロパティに生成したオブジェクトをキャッシュしておいて、同じオブジェクトを使いまわすようにします。これで、いくらnewしても同じオブジェクトが出来上がるようになります。newを禁止したい？できないこともない。せっかくなのでnewを禁止して、getInstanceでオブジェクトを取得するように関数を変形するFunction.prototype拡張を作ってみよう。Function.prototype.toSingleton = function(){	var ctor = this;	var Dummy = function(){};	Dummy.prototype = ctor.prototype;	var new_func = function(){		if(new_func.__allow_create__ == null){			throw \"this is SingletonClass. use getInstance()\";			return null;		}		return ctor.apply(this,arguments)	};	new_func.getInstance = function(){		if(new_func.instance == null){			var tmp = new Dummy;			var res = ctor.apply(tmp,arguments);			new_func.instance = (typeof res == \"undefined\")?tmp:res;		}		return new_func.instance;	};	new_func.prototype = ctor.prototype;	return new_func;};// やっぱシングルトンじゃなくする。Function.prototype.removeSingleton = function(){	this.__allow_create__ = true;}getInstanceはnewを使わないのでthisキーワードが使えない。thisを使ったらnew_funcへの参照になってしまった。なので、空のオブジェクトを生成して、そいつをthisとしてコンストラクタ関数に引渡し、返値もしくはthisをインスタンスにセット、というnewの挙動を再現するようにした。これで大体問題ないはず。空のオブジェクトを作成するのにDummyを使うのは、元のコンストラクタ関数のprototypeを継承するため。これをやらないとprototype.jsのthis.initializeみたいな処理が呼べない。__allow_create__っていうフラグが立っていない場合は関数としての呼び出しは許可されないようにする。newでインスタンスを生成しようとしたらthrowでgetInstanceを使えとエラーメッセージを投げてやる。シングルトンパターンはDBのコネクションを一つに絞ったりするのに使うらしいです。まず、複数のインスタンスが生成されることを全く考慮しないで設計したConnectionクラスを作って、Connectionをシングルトンに変換させたConnectを実際に使用する、といった具合になります。全然具体的じゃないサンプルですが一応。// ベースになるクラス定義function Connection(option){	this.name = option;}// シングルトンに変形Connect = Connection.toSingleton();var db = Connect.getInstance(\"myname\");var db2 = Connect.getInstance(\"hogehoge\"); // 引数無意味alert(db==db2); // true// 短く書くとこうvar Connect = function(option){	this.name = option;}.toSingleton();// 上書きしても問題ないConnection = Connection.toSingleton();// やっぱnewで使うConnection.removeSingleton();var hoge = new Connection;// prototype.js使うならこう。var MyClass = Class.create();MyClass.prototype = {	initialize : function(option){		this.name = option	}}MyClass = MyClass.toSingleton();var huga = MyClass.getInstance();こんな具合で既存のコンストラクタ関数を何でもシングルトン化できる。Class.create().toSingleton();と書きたいところだけど、そうするとMyClass.prototypeがシングルトン化された関数に対して関連付けられてしまうので上手くいかない。いったんインスタンスを作ったら、getInstanceに引数を渡しても無視するようにした。なんかキーとか指定できるようにしたほうがいいのかな。それじゃシングルトンじゃないか。よく知らん。デザパタとかオブジェクト指向のなんたるかとかは良くわかってないが、JavaScriptに関してはけっこう真面目に勉強しなおしたのでバッチリだ。今まで書いたコード全部書き直したいが単純に時間が足りない。"},
{file:"diary_200508220821.htm",title:"beyond.jsってなに？の巻",mtime:1124667026,ctime:1124667026,body:"こどもてれびに対抗して巷のJavaScripterの間で最新流行のbeyond.jsってライブラリの解説をします。*beyond.jsとは知らないやつはモグリといっても過言ではないぐらい有名なライブラリです。嘘です。どれぐらい使われているのかは良くわかりません。Ajaxとか全然関係なくて、純粋にJavaScriptのライブラリです。beyond.jsはここからダウンロードできます。http://w3future.com/html/beyondJS/Beyond JS is a Javascript library that lets you write Javascript unlike anything you've ever written. Your code will never be the same again. It contains both useful, functional, tricky and freakish extentions and additions to Javascript. It can make your code more readable and less debugable, and even the other way around.- BeyondJSを使うとアナタが今まで書いたことの無いようなやり方でJavaScriptを書けます。- 一度使ったら元には戻れません。- JavaScriptに便利で実用的でトリッキーで奇抜な拡張を加えます。- アナタのコードをより読みやすくデバッグしやすく、なったりならなかったり。多分こんな意味だと思いますが、ドキュメントがろくに無いので全般的に何をやっているのか意味不明です。大体公式ページに張ってある唯一のサンプルがチェックボックスを入れるとマウスの動きに合わせて星が動くとかいう、とてつもなくしょぼいデモンストレーションで、しかもIE限定です。いまどきFirefoxで動かないなんてダメじゃん、と9割ぐらいが立ち去ります。このサンプルが動かないのはイベントハンドリングのやり方が違うからであってBeyondJS自体はクロスプラットフォームです、と言い訳が書かれています。ネイティブオブジェクトを拡張する「beyond.js」自体は汎用性のある部分のみ記述されていて、プラットフォーム個別の処理は、WSHで使うためのbeyondWindows、Rhinoで使うためのbeyondRhino、ブラウザで使うためのbeyondBrowserなどに分割されています。遅延評価の配列を作成するbeyondLazyなんかも面白そうですが、今回は触れません。*サンプルを読み解く一応アーカイブにいくつかサンプルなども同梱されているのですが、とりあえずトップページ張ってあるデモの解説をしてみます。多少見やすく整形したつもりです。Function.from(\"star\", \"moveTo\").delay(1000).using(	\"+\".using(		Function.from(event, \"x\"), 		\"*\".using(			\"radius\",			 Function.from(Math, \"sin\", \"angle\")		)	),	\"+\".using(		Function.from(event, \"y\"), 		\"*\".using(			\"radius\",			Function.from(Math, \"cos\", \"angle\")		)	)).curry({	radius: 30,	angle : function() {return (new Date)/50;}.asValue()}).gate(	Function.from(\"doStar\".element(),\"checked\"));これは一体何をしているのかというとマウスが動いたら「\"star\"というstringのmoveToというメソッドから関数を生成、　それを1000ミリ秒遅らせて実行する関数を生成し、　　その関数の第一引数には　　　eventのxというプロパティと　　　radiusとMath.sin(angle)を掛け合わせたもの　　　を合計したものを渡す　　その関数の第二引数には　　　eventのyというプロパティと　　　radiusとMath.cos(angle)を掛け合わせたもの　　　を合計したものを渡す　　ような関数を生成し、　その関数の引数として　　radiusに30、　　angleに現在時刻を50で割った結果を返す関数の実行結果　を関連付ける」という関数を、　doStarという要素の\"checked\"プロパティを返す関数を作って　それの実行結果がtrueの場合にのみ実行する、という関数を生成しています。ざっと数えたところ、15個ぐらいの関数を生成しています。内部的にはもっと多いかもしれません。ああなるほど「functional」って関数的って意味だったのか。*JavaScriptの標準の機能だけで書き直すif(!document.getElementById(\"doStar\").checked) return;var x = event.clientX; // Firefoxでも動くようにvar y = event.clientY;setTimeout(function(){	var angle = (new Date)/50;	var star = document.getElementById(\"star\");	star.style.left = (30*Math.sin(angle))+x + \"px\";	star.style.top  = (30*Math.cos(angle))+y + \"px\"; },1000);というわけで、なんか、普通に書いたほうが短くなりました。普通に書いたものをここに置いておきます。http://la.ma.la/misc/js/star.htmlマウスの動きに1秒遅れて、円を描きながら星が追いかける、というデモのようです。*Function.from個別に解説。Function.from(a,b,c)はオブジェクトaのbというプロパティから関数を生成して、cという引数を使う、という意味らしいです。Function.from(\"doStar\".element(),\"checked\")// →function(){return \"doStar\".element().checked}Function.from(Math, \"sin\", \"angle\")// →function(angle){return Math.sin(angle)}多分こんな感じです。内部的にはもっと複雑になっていて、いまひとつ意図がつかめません。とにかく引数を元に関数を生成する関数みたいです。*function.usingfunction.usingは引数の束縛に使います。引数を固定して、残りの引数を受け取る関数に変形します。function plus(a,b){	alert(a+b)}plus.using(3,5)(); // 8plus.using(3)(5);  // 8plus.using()(3,5); // 8*function.curryfunction.curryは任意の引数を固定します。内部のいたるところで使われています。すごいのは引数の順番がどうなっていようと、きちんと固定してくれる点です。function plus(a,b){	alert(a+b)}plus.curry({a:3})(5); // 8plus.curry({b:3})(5); // 8----引数を減らすことをカリー化(currying)と呼ぶらしく、これはHaskellの用語だそうです。function.asValue()っていうのはカリー化するときに、関数ではなく、関数の実行結果を関連付けよ、っていう意味です。多分。*string.usingstring.usingは演算子を関数に変形することが出来ます。まず文字列を関数に変形するstring.toFunctionというメソッドがあって、さらにその関数にusingを使って引数を束縛する、という実装になっています。three_plus_what = \"+\".using(3);alert(three_plus_what(5)); // 8\"+\".using(3,5)() // 8\"+\".using(3)(5)  // 8演算子を先に書くのは、lispで使われるポーランド記法っぽいです。*応用：演算子のオーバーロード今までに無いというのは確かですが、読みやすいとかデバッグしやすいかというと良くわかりません。もはや別の言語と考えて良さそうです。なんだか簡単なことをわざわざ難しく書いているように思えますが、代わりに、本来出来ないようなことが可能になります。例えば、String.prototype.usingを書き換えることで演算子のオーバーロードが可能になります。// 全ての足し算の結果を50増やすString.prototype.using_ = String.prototype.using; // オリジナルを保存String.prototype.using = function(){	var self = this;	var args = arguments;	if(self == \"+\"){		return \"+\".using_(			50,			String.prototype.using_.apply(self,args)		)	}else{		// +以外の時は本来の動作を呼び出す		return String.prototype.using_.apply(this,arguments)	}};これで、\"+\".usingを使った全ての足し算の結果が50ずれます。そんなわけで星の座標が本来より50ドットずれて表示されるサンプル。http://la.ma.la/misc/js/beyond1.html対応するのが面倒なのでIE限定で。たいして面白いわけでもない。*応用：パラメータを外部から変更する星がマウスを追いかける速さを変更してみましょう。ふつうはdelay(1000)の部分を変更しますが、別の方法でも可能です。Function.prototype.delay = Function.prototype.delay.using(10);これで全ての遅延関数の引数が強制的に10になります。マウスを動かしてすぐに星が後をついてくるようになります。これも面倒なのでIE限定で。http://la.ma.la/misc/js/beyond2.html*まとめbeyond.jsでわかるJavaScript(というよりECMAScript)の特徴を挙げるとするならば、-prototypeを変更することで広範囲にわたって挙動を変更することが出来る。-関数は任意の数の引数を受け取れる、引数の数や型に応じて挙動を変更できる。-関数自体がオブジェクトで、関数を変形させて新しい関数を作成できる。この三点ではないかと思います。なんだか無茶なことをやっているように見えるけれど、このライブラリは多分、そういう無茶なことをやるために存在するのです。「JavaScriptって演算子のオーバーロードも出来ねえのかよ？」そんなあなたにbeyond.js。もっとも、使いこなすにはHaskellとかlispを勉強しないといけなさそう。もはや誰をターゲットに書いてるのかよくわかりませんが、まあとりあえずbeyond.jsは何かとすごいです。おわり。"},
{file:"diary_200509011721.htm",title:"FeedBurnerを使うようにした",mtime:1125730902,ctime:1125730902,body:"転送量とサーバー負荷が大変なことになっているのでRSSフィードをFeedBurnerに移転しました。ドメイン全体のトラフィックの90%ぐらいがRSSへのアクセスで、1日700MBとか。7月には400MBぐらいだったんだけど。301 Moved Permanently（恒久的な移転）を吐いているので、Bloglines使ってる人は、特に何にもしなくても平気です。他のリーダーでも、ほっといてもリダイレクトするので問題は無いのだけど、毎回リダイレクトすることになるので、RSSバーとかFirefoxのLivebookmarkを使ってる人は、登録しなおしてくれるとありがたいかも。というか、この際Bloglinesを使ってくれると一番ありがたい。今なんだかんだで500フィードぐらい購読してるのだけどBloglinesじゃなかったら読める気がしない。----9/3Bloglinesは三日ぐらい様子を見て移転するらしい。あとなんかはてなRSSが巡回に来なくなった。どうしてくれよう。"},
{file:"diary_200509031529.htm",title:"IEでXMLHttpRequestを使えるようにする",mtime:1125729747,ctime:1125729747,body:"もうあんまり需要無いような気もするけど。IEで「new XMLHttpRequest」と書けるようにするラッパを書いてみた。XMLHttpRequest for IEhttp://la.ma.la/misc/js/ie_xmlhttp.html結構前にIE7(JavaScriptの方)の人が似たようなのを作ってたのですが、http://dean.edwards.name/weblog/2004/11/ie7-xml-extras/ふつうに使う分にはこれでも問題はないです。if(typeof ActiveXObject == &quot;function&quot; &amp;&amp; typeof XMLHttpRequest == &quot;undefined&quot;){	XMLHttpRequest = function(){		return new ActiveXObject(&quot;Microsoft.XMLHTTP&quot;)	}}IEでXMLHttpRequestが未定義だったら、XMLHTTPオブジェクトを返すコンストラクタを定義してやる。これだけでいい。ただ、これだとXMLHttpRequest.prototypeをいじったりすることができない。IEのActiveXObjectっていうのはちょっと特殊で、メソッドなんかがJavaScriptのfunctionではない。var xmlhttp = new ActiveXObject(\"Microsoft.XMLHTTP\");alert(typeof xmlhttp.open); // unknownこうなる。xmlhttp.openはfunctionではなくて謎オブジェクト。FirefoxやOperaのXMLHttpRequest#openは、ちゃんとfunctionになっているのだが、IEの場合は関数ではないので、関数型言語としてのJavaScriptの機能が使えない。----XMLHttpRequest for IEは何なのかというと、IEでもXMLHttpRequestのメソッドをfunctionオブジェクトとして扱うことができるようになるラッパです。あとついでにonloadイベントハンドラを定義してあるので記述が楽になります。functionalでアスペクト指向なコードを書く際に、役に立ちますが、functionalでアスペクト指向なコードを書かない場合は書き方が共通になって嬉しい程度で、その辺はすでにprototype.jsとかあるので大してメリットはないと思われる。ものすごくシンプルな例はこんな感じ。var XP = XMLHttpRequest.prototype;XP.open_old = XP.open;XP.open = function(){	alert(\"open called!\");	return this.open_old.apply(this,arguments)}XMLHttpRequest.prototypeを書き換えてやることで、通信をトレースできるようにしたり、機能を拡張したり制限を加えたりすることができるようになる。もちろんクロスブラウザで動く(safariは知らないけど)。例えば、通信するときには必ず前回のリクエストから1秒のウェイトを入れるようにする、とか、デバッグ用に通信状態をステータスバーに流すとか、他ドメインのURLを開こうとした場合はプロキシCGI経由のリクエストにするとか、UserAgentを強制的に書き換えるとか、キャッシュが利かないようにユニークなURLにするとか。全般にわたる振る舞いを効率的に記述することができるようになる。----工夫したのはこのあたり。var methods = &quot;open,abort,send,setRequestHeader,getResponseHeader,getAllResponseHeaders&quot;.split(&quot;,&quot;);var make_method = function(name){	XMLHttpRequest.prototype[name] = function(){		var params = new Array(arguments.length);		for(var i=0;i&lt;params.length;i++) params[i] = &quot;_&quot;+i;		return Function(			params.join(&quot;,&quot;),			[&quot;return this.__request__.&quot;,name,&quot;(&quot;,params.join(&quot;,&quot;),&quot;)&quot;].join(&quot;&quot;)		).apply(this,arguments);	}};for(var i=0;i&lt;methods.length;i++) make_method(methods[i]);本来のXMLHTTPオブジェクトをthis.__request__に保存していて、引数の数に応じて関数を動的に生成して、本来のXMLHTTPオブジェクトに処理を丸投げする。this.open(\"GET\",url)→(function(_1,_2){this.__request__.open(_1,_2)}).apply(this,arguments)this.open(\"GET\",url,async)→(function(_1,_2,_3){this.__request__.open(_1,_2,_3)}).apply(this,arguments)this.open(\"GET\",url,async,user,pass)→(function(_1,_2,_3,_4,_5){this.__request__.open(_1,_2,_3,_4,_5)}).apply(this,arguments)こんな具合に変換される。ふつうにラッパーを書くときは、function wrapper(){	return original.apply(this,arguments)}こんな具合にやるんだけど、オリジナルのxmlhttp.openは上記のとおり、そもそも関数ではないのでxmlhttp.open.applyが存在しない。eval使わないと無理かな、とも思ったんだけどFunctionコンストラクタ使うときれいに書けた。Functionコンストラクタは文字列から関数を生成する。add = new Function(\"a\",\"b\",\"return a+b\");そして、こう書いてもOK。add = new Function(\"a,b\",\"return a+b\");これはJavaScriptの方言ではなくてちゃんとECMA準拠。http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/15-3_Function_Objects.html#section-15.3.2.1まあ、あんまり使わないと思うんだけど。"},
{file:"diary_200509122347.htm",title:"Firefox1.5でサポートされる新しいArrayのメソッド",mtime:1126536432,ctime:1126536432,body:"について。http://nanto.asablo.jp/blog/2005/09/04/62939http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array#Methods*ループ処理を便利にするメソッド Array#forEach Array#map Array#filter Array#every Array#some引数として、callback,thisObjを受け取る。配列の各要素に対してcallback関数を実行する。callback関数はelement, index, arrayを受け取る。value,key,self。値、添え字、配列自身。Array#forEach 配列の各要素に対してcallback関数を実行するArray#map callback関数の返値の配列を返すArray#filter callback関数の実行結果が真になった要素のみ集めた配列を返すArray#every callback関数の実行結果が全て真の場合にtrueを返すArray#some callback関数の実行結果が一つでも真の場合trueを返す*出現位置を探すメソッドStringのindexOfと同じ要領。searchElementとfromIndexを受け取る。比較は===で行う。Array#indexOf searchElementが一番最初に出てくる添え字を返す。fromIndexで開始位置を変更できる。Array#lastIndexOf searchElementが一番最後に出てくる添え字を返す。fromIndexで開始位置を変更できる。lastIndexOfの挙動が少しややこしくてfromIndexをプラスで指定して左端まで来ると右端で止まる。マイナスで指定する場合は左端で止まる。*他のブラウザで使うためのコード解説がわかりづらいので、わかる人はコードで読んだほうが早いような気がする。Firefox1.5をインストールして、挙動が同じになるのを確認してみたけど、callback関数で配列を破壊したときにどうなるのかとか、細かいチェックはしてない。一応、これであってるとは思う。filterやeveryの条件は0とかnullとかundefinedでなければOK。return 1でも良い。自分でmapとかeachとか作ってやってたけど、これに合わせてcallback関数の類はvalue,key,selfの順に受け取るような設計にしときたいところ。Array.prototype.forEach = function(callback,thisObject){	for(var i=0,len=this.length;i&lt;len;i++)		callback.call(thisObject,this[i],i,this)}Array.prototype.map = function(callback,thisObject){	for(var i=0,res=[],len=this.length;i&lt;len;i++)		res[i] = callback.call(thisObject,this[i],i,this);	return res}Array.prototype.filter = function(callback,thisObject){	for(var i=0,res=[],len=this.length;i&lt;len;i++)		callback.call(thisObject,this[i],i,this) &amp;&amp; res.push(this[i]);	return res}Array.prototype.indexOf = function(searchElement,fromIndex){	var i = fromIndex&lt;0 ? this.length+fromIndex : fromIndex || 0;	for(;i&lt;this.length;i++)		if(searchElement === this[i]) return i;	return -1}Array.prototype.lastIndexOf = function(searchElement,fromIndex){	var max = this.length-1;	var i = fromIndex &lt; 0 ?	Math.max(max+1 + fromIndex,0):		fromIndex &gt; max ? max : max-(fromIndex||0) || max;	for(;i&gt;=0;i--)		if(searchElement === this[i]) return i;	return -1}Array.prototype.every = function(callback,thisObject){	for(var i=0,len=this.length;i&lt;len;i++)		if(!callback.call(thisObject,this[i],i,this)) return false;	return true}Array.prototype.some = function(callback,thisObject){	for(var i=0,len=this.length;i&lt;len;i++)		if(callback.call(thisObject,this[i],i,this)) return true;	return false}ところでさいきん、{}を省略したりむやみに三項演算子を使ったりifの代わりに&amp;&amp;使ったりする病気になった。"},
{file:"diary_200509170520.htm",title:"GoogleInstantSearchを作ってみた",mtime:1126902035,ctime:1126902035,body:"Yahoo! Instant Searchにインスパイヤされて作ってみた。だいたい1時間ぐらい。Greasemonkeyスクリプトhttp://la.ma.la/misc/userjs/GoogleInstantSearch.user.js動作対象をgoogleドメインの/で終わるページに設定しているので、動かない場合はincluded pagesをホームページに合わせて設定しなおしてください。こんな感じに動く。http://la.ma.la/misc/img/gis.png最初にFeeling luckyで検索をかけて、locationヘッダで返ってくるURLで再度検索をかけて詳細情報を出しています。検索のタイミングはキーアップから500ミリ秒後。Ctrl+Enterでヒットしたサイトに移動。あとなんか、Greasemonkeyがバージョンアップして日本語が通るようになってたので、日本語表示にしておいた。"},
{file:"diary_200509210934.htm",title:"デザインを変えました",mtime:1127925138,ctime:1127925138,body:"サイドバーを無くして文字を大きくしました。あと検索ボックスがど真ん中、ってスタイルを流行らせたい。検索ルーチンを大幅に変更しています。まあ使いやすいかどうかは別として、いろいろ凝ったことをやってみました。タイマー使ってスレッド処理っぽくしています。エントリの件数が1万件とかになってもブラウザを固めずに検索ができます。1万件とかならないのであんまり違いはでないんだけど。副産物で色々と出来上がったのだけど結局ほとんど使ってない。ソース見たい人はここからどうぞ。全然整理できてないけど。http://la.ma.la/js/色々変なことをやっているので、そのうち個別に解説を書くかも。"},
{file:"diary_200509220220.htm",title:"三項演算子の正しい書き方ってあるのだろうか",mtime:1127323277,ctime:1127323277,body:"最近は、三項演算子を多用しているのだけれど、やっぱり人が使ってるのを見ると気持ち悪い。http://d.hatena.ne.jp/brazil/20050921/1127314004Test.Builder.globalScope = typeof JSAN != 'undefined'  ? JSAN.globalScope  :  typeof window != 'undefined'    ? window    : typeof _global != 'undefined'      ? _global      : null;これは解読するのにやたら時間がかかる気がする。コロンの後が値なのか条件なのかわからないからだ。俺ならこう書く。Test.Builder.globalScope =  (typeof JSAN    != 'undefined') ? JSAN.globalScope : (typeof window  != 'undefined') ? window : (typeof _global != 'undefined') ? _global : null;三項演算子を使うときは、条件はどんなに短くても必ずカッコで囲って、先頭に持ってくるようにしている。条件をカッコで囲うだけでも、かなり読みやすくなる気がする。このコードはこういう風に読み替えることができる。if (typeof JSAN != 'undefined') { JSAN.globalScope }else if (typeof window != 'undefined') { window }else if (typeof _global != 'undefined') { _global }else { null };あるいはこういう風に。switch(true){ case (typeof JSAN != 'undefined')    : JSAN.globalScope  case (typeof window != 'undefined')  : window  case (typeof _global != 'undefined') : _global  default : null ;}脳内補完されるコードと近いので、動作が想像しやすいんじゃないかと思う。実際はif else使う場合はTest.Builder.globalScope = windowみたいに全部代入文にしないといけないしswitch文の場合はbreakも必要になるので、三項演算子を使ったほうが、はるかに短く書ける。しかし、三項演算子でif elseを全部置き換えられるかというとそうでもなくて、returnとかcontinueとかbreakとか、値を返さない制御文の類を使うことはできない。あと、イコールの後に改行はOKなんだけどreturnの後に改行するとJavaScriptはセミコロンが省略されてると見なしてうまくいかない。"},
{file:"diary_200510050749.htm",title:"JavaScriptによるQRコード生成ライブラリ",mtime:1128466472,ctime:1128466472,body:"ってのを作りました。http://la.ma.la/misc/qrcode/ネタのつもりで作ってたんだけど意外と大変だった。というか時間かけすぎた。なんの役に立つのかと言われたら何の役にも立たないと自信を持って言える。Ruby用QRコード生成クラスからの移植です。ライセンスはオリジナルに準拠します。http://www.swetake.com/qr/QRコードの仕様とかアルゴリズムとかそういうのは全然わかりません。挙動が同じになるようにしてみただけです。表示にはテーブルタグを使っています。画像オフでも表示できます。動作テストにはhttp://www.psytec.co.jp/docomo.htmlを使いました。アーカイブにdatファイル同梱したのでファイルサイズが2MB超えてます。ソースだけ見たい人は、これをどうぞ。当然これだけじゃ動かないけど。http://la.ma.la/misc/qrcode/qrcode.js*動作について遅いです。最初は文字入力されるたびにリアルタイムで生成するようなのを考えていたのですが、それだと多分10GHzぐらい必要です。遅いから何の役にも立たないねっていうことなんだけど、速かったら役に立つのかと言われても疑問。IE、Firefox、Opera8.5で動作確認しています。Firefox推奨。生成には1GHzのマシンで5秒から10秒ぐらいかかると思います。テーブルタグの描画ではなく、実際の計算に時間がかかってます。速度はOperaがやっぱ速いんだけど、なんか出力結果が他のブラウザと違う。読み取れてるので細かいことは気にしない、さすがQRコードだ、とかいう。まあそういう、すげーいい加減な具合なので変換結果を信頼しないでください。日本語は変換できません。できるんだけど対応してるリーダーがないとか(後述)。*Rubyからの移植にあたってあまり最適化とかはしないで、なるべくオリジナルのコードからの変更点が少なくなるようにしています。セミコロン省略なんかは、本来あまりやらないほうが良いです。ruby.jsからString#scan と MatchDataオブジェクトを使っています。String#countを作ってありますが、これはRuby互換ではありません。とりあえず動くようにやっつけ仕事。Fileクラスも作ったが、これはopen、readのみ。String#packとString#unpackはオプションとか良くわかんないのでこれも適当。最初は慣れ親しんだPerlから移植しようかと思ってたんだけど、Rubyからの方がずっと楽っぽい。ボトルネックは正規表現オブジェクト作成とか、そこらへんだと思う。いちおう、高速化の余地はある。* 工夫したところRubyっぽく書いたコードをJavaScriptに変換する関数を作っています。ruby_slice_supportってのを書いて// beforehor[k * max_modules_1side,0] = (170).chr()// afterhor = hor.ruby_slice(k * max_modules_1side,0).eq((170).chr())こんな具合に置換するようにした。Rubyだと、string[offset,length]で部分文字列の切り出しや置き換えができるんだけど、JavaScriptだとstring[(offset,length)]と見なされてstring[length]と同じ意味になる。さらにはstring[/regexp/]なんかができてすげーカッコいいんだけど、これはJavaScriptだとstring[/regexp/.toString()]になる。つまりstring[\"/regexp/\"]と同じ意味になる。[]の中身が[offset,length]の形式だったら.ruby_slice(offset,length)に置換して、切り出し結果にeqメソッドくっつけて左辺に使われた時の挙動をエミュレート、っていう具合。あとはforcePrivateってのを書いた。これは関数内で使われている変数名を拾ってきて強制的にvarで宣言してプライベート変数にする、というのもの。some_function = some_function.forcePrivate();とかやると、その関数内で使われてる変数が全てプライベート変数になる。ただし関数をnew Functionで再構築するため、変数のスコープとか一切関係なくなってしまう(クロージャとしては使えない)。スタティックな関数に適用するなら、まあそれなりに便利かもしれない。関数オブジェクトを文字列に落として正規表現でゴニョゴニョフィルターかけてやれば色々できるね、って言う話なんだけど。ただ、IEだと大きめの関数を生成すると死ぬほど重かったり、Operaだとなんか良くわからないエラーで失敗したりするので、あらかじめFirefox使って変換した結果を使うようにしたりしている。function.toStringは、なんかブラウザごとに勝手に整形されてたりして個性があるので、あんまり特定の動作を期待して使うべきじゃないと思われる。* 数値から文字列Number.prototype.chr = function(){	return String.fromCharCode(this)}(170).chr()はRubyだと170.chrなんだけど、数値からメソッド呼び出すときに小数点と区別付かないからカッコでくくらないとエラーでるとか(170).chrはfunctionで(170).chr()でchrメソッド実行とか、そういう違いがある。このあたりも正規表現置換でなんとかしようかとも思ったんだけど、JavaScriptだと関数オブジェクトと関数の実行を明示的に区別することは重要なので手動で書き直した。chr(170)の方が普通に楽だな、と思ったんだけど、なるべくRubyのコードいじらないというポリシーだったのでこんな具合になったり。Firefoxだとgetter/setterが使えるので、(170).chrまでならなんとかできそうだけど。String.fromCharCodeで生成した文字列は0-65535までなら、その文字コードに対する文字の割り当てが存在していなくてもきちんと文字コードを保持してくれる。* バイナリファイルの読み込み他の言語のバージョンと同じように計算済みのdatファイルというのを使います。これは計算時にXMLHttpRequestを使って受信しています。ただし、XMLHttpRequestのresponseTextは、バイナリファイルを文字化けしたテキストデータとして認識するので、うまくいかない。なのでバイナリデータの読み込みには、あらかじめ16進数ダンプしたテキストファイルを作っておいて、読み込み後にpackするという動作になっています。* 仕様：画像保存できませんQRコードの描画にはテーブルタグを使っています。画像での出力はできません。Firefoxに限れば将来的にcanvas要素とdataスキームを使って画像保存とかできるようになるかもしれません。* 仕様：京ぽんで動きませんXMLHttpRequest使えないので。そのほかにも色々問題あると思う。使うデータをあらかじめscript本体に記述するようにすればイケルとは思うんだけどデバッグが大変なのと現実的な速度で動作するとは思えないのでやる気なし。* 仕様：マルチバイト文字について基本的に対応してません。URLやメールアドレスなんかはOKですが日本語は変換できません。一応、UTF-8文字列を文字列単位でなくバイト単位で区切って渡すようにはしてあるので、「UTF-8を読めるQRコードリーダー」もしくは「読み取り結果をバイナリファイルで保存できるQRコードリーダー」があれば読めるはず。ShiftJISが実質標準っぽいので、気が向いたらShiftJIS変換ルーチン組み込んだのを作ります。気が向いたらというのは気が向いたらやるということで、気が向いたらやります。期待しないでください。"},
{file:"diary_200510060733.htm",title:"実践JavaScriptリファクタリング",mtime:1128606720,ctime:1128606720,body:"同じ事をやるにも、いろんな書き方があるわけでいかにして短くてわかりやすいコードを書くかというノウハウを紹介します。例として\"abcde\"を80回繰り返した文字列を作るとして実際に自分のコーディングスタイルがどんな風に変化していったのか、という。短くなるのは確かなんだけどわかりやすいかというと、人によるかもしれない。*  グローバル関数を定義2年前なら、多分こういう具合だった。//ふつうに関数として定義するfunction x(str,num){    var tmp = \"\";    for(var i=0;i&lt;num;i++){        tmp += str;    }    return tmp;}x(\"abcde\",80)*  Stringのメソッドとして定義1年前だとこんな感じ。//Stringのメソッドとして定義するString.prototype.x = function(num){    var tmp = \"\";    for(var i=0;i&lt;num;i++){        tmp += this    }    return tmp;}\"abcde\".x(80)最近になって短くかけるところはなるべく短く書くようにしている。//forの初期化ついでにtmpも宣言、{}を省略String.prototype.x = function(num){    for(var i=0,tmp=&quot;&quot;;i&lt;num;i++) tmp += this;    return tmp}こんな具合。見た目がすっきりする。*  配列を使うようにするちょっとパフォーマンスが気になるので、高速化してみる。文字列を加算していくのは、計算の途中で、abcde、abcdeabcde、abcdeabcdeabcdeという文字列オブジェクトがその都度生成されていくのでメモリにやさしくない。巨大な文字列の連結にはjoinを使ったほうが良い。数が大きくなると速度に差が出てくる。//配列にpushしてjoinString.prototype.x = function(num) {    var tmp = [];    for(var i=0;i&lt;num;i++){        tmp.push(this)    }    return tmp.join(\"\")}//短く書くとこうなるString.prototype.x = function(num){    for(var i=0,tmp=[];i&lt;num;tmp[i++]=this);    return tmp.join(&quot;&quot;)}*  メソッドを使いまわす←いまここ配列を埋めるArray#fillを作って、使いまわすようにする。Array.prototype.fill = function(v){    for(var i=0;i&lt;this.length;this[i++]=v);    return this}String.prototype.x = function(num){    return Array(num).fill(this).join(\"\")}\"abcde\".x(80)これでString.prototype.xは、一行に収まった。長さ80のArrayを\"abcde\"で埋めて連結する、と、意味そのままのコードになる。もしも、あらゆるforループや一時変数を排除したいならば、次のように書くこともできる。Array.prototype.fill = function(v){    return this.map(function(){return v})}String.prototype.x = function(num){    return Array(num).fill(this).join(\"\")}まあ、どのみちArray.prototype.mapを自前で定義するならforループが必要ってことにはなるんだけど。これは\"abcde\".x(10000)だったら1万回function(){return v}が呼ばれるので、動作が遅くなる。※Array.prototype.mapはFirefox1.5でサポートされる新しいArrayのメソッドを参照。* まとめビルトインオブジェクト拡張してしまうというのは、まあ行儀悪いと言えば行儀悪いんだけど、JavaScriptのprototypeベースとかオブジェクト指向とかの仕組みを理解するのには多分一番の近道なんじゃなかろうか。と思う。"},
{file:"diary_200510062243.htm",title:"実践JavaScriptリファクタリング、その2",mtime:1128606231,ctime:1128606231,body:"連載すんの？リファクタリングとか嘘で実は実践ビルトインオブジェクトハックなんだけど。例題配列 a = [3,5,4,2,1] から一番小さな値と、一番大きな値を取り出すにはどうすればいいか。多分昔はこんな風に書いてたと思うんですよ。a = [3,5,4,2,1];for(i=0;i&lt;a.length;i++){	if(i == 0){		min = a[0];		max = a[0];	}	if(min > a[i]){min = a[i]}	if(max 模範解答として、後先考えないやり方を提示しておく。a = [3,5,4,2,1];min = a.sort().shift();// 1max = a.sort().pop();  // 5短い。ただし、これをやるとaの内容は並べ替えられて最初と最後の要素が取り除かれる。a // 2,3,4内容を破壊してもかまわないなら、こういうやり方がある、ということを踏まえて次に進む。* 配列の内容をコピーするありがちな間違いとして次のようなものがある。a = [1,2,3,4,5];b = a; // コピーしたつもりb.shift() // 1a // 2,3,4,5aもbもメモリ上のどっかにある[1,2,3,4,5]という配列への参照でしかない。b = a は別の名前でアクセスできるようにしただけであって、コピーではない。だから、bの内容を破壊するとaの内容も破壊される。aと同じ内容の、別の配列を作るには次のようにする。// ごくふつうの、配列のコピーa = [1,2,3,4,5];b = [];for(var i=0;i&lt;a.length;i++){	b[i] = a[i]}Arrayのメソッドとして定義してやると、次のようになる。Array.prototype.clone = function(){	var tmp = [];	for(var i=0;i&lt;this.length;i++){		tmp[i] = this[i]	}	return tmp}a = [1,2,3,4,5];b = a.clone();b.shift() // 1// bのみ破壊されるa // 1,2,3,4,5b // 2,3,4,5配列のクローンを作成するのには、実はもっとスマートで速い方法がある。これに気付いたのは最近なんだけど。Array.prototype.clone = function(){	return Array.apply(null,this)}[1,2,3,4,5].clone() は Array(1,2,3,4,5) を呼び出す。これを使って最初の例題を解くとこうなる。Array.prototype.clone = function(){	return Array.apply(null,this)}a = [3,5,4,2,1];min = a.clone().sort().shift();// 1max = a.clone().sort().pop();  // 5a // 3,5,4,2,1オリジナルの配列の内容は変更されない。* 破壊しないソートそもそも、sortが破壊的なのがおかしいんじゃないのか、とかいう疑問を感じる。http://namazu.org/~satoru/blog/archives/000043.htmlRubyではsortが非破壊、sort!が破壊的、という区別がある。Perlでも「@a = sort(@a)」と明示的に代入しなければ元の配列の内容は書き換えられない。// JavaScriptのsortは破壊的であるa = [5,4,3,2,1];a.sort();// aの内容が置き換わるa // 1,2,3,4,5Array#sortの機能を置き換えて、オリジナルの配列が変更されないようにするには、次のようにする。// オリジナルのsortメソッドを保存Array.prototype.sortIt = Array.prototype.sort;// コピーしてソートするArray.prototype.sort = function(){	var tmp = this.clone();	return tmp.sortIt.apply(tmp,arguments)}a = [5,4,3,2,1];b = a.sort();a // 5,4,3,2,1b // 1,2,3,4,5これはかなり邪悪なハックだ。sortが破壊的であることを期待しているコードは動かなくなる。もはや全然リファクタリングではない。ソートが非破壊だと、cloneを省略して次のように書けるようになる。a = [3,5,4,2,1];min = a.sort().shift();// 1max = a.sort().pop();  // 5a // 3,5,4,2,1* firstとlastを定義shiftとpopが少し気持ち悪いので最初の要素と最後の要素を参照するメソッドを定義してやる。// Rubyのfirstとlastメソッド移植Array.prototype.first = function(size){	return (size == undefined) ? this[0] : this.slice(0,size)}Array.prototype.last = function(size){	return (size == undefined) ? this[this.length-1] : this.slice(this.length-size)}a = [3,5,4,2,1];min = a.sort().fisrt(); // 1max = a.sort().last();  // 5これで、minは並べ替えた最初、maxは並べ替えた最後、と、定義そのままのコードが完成する。実際のところ配列が巨大になるとソートが非常に遅くなってしまうのだけど、まあ100や200の配列なら問題は無いだろう。* まとめArray.prototype.clone = function(){	return Array.apply(null,this)}Array.prototype.sortIt = Array.prototype.sort;Array.prototype.sort = function(){	var tmp = this.clone();	return tmp.sortIt.apply(tmp,arguments)}Array.prototype.first = function(size){	return (size == undefined) ? this[0] : this.slice(0,size)}Array.prototype.last = function(size){	return (size == undefined) ? this[this.length-1] : this.slice(this.length-size)}Array.prototype.min = function(){	return this.sort().first()}Array.prototype.max = function(){	return this.sort().last()}a = [3,5,4,2,1];min = a.min(); // 1max = a.max(); // 5なんか、最初より長くなってるけどArray.prototypeは別のファイルに書いておけば後は使い回しが利くので、コードの記述量はどんどん減るようになる、というわけ。あとはruby.jsのソースなんかを読むと良い。メソッドチェーンを使うことで殆どの機能は、より簡潔に書くことができる。http://www.advogato.org/proj/Ruby.js/* 番外編中身を数値に限定するならばこう書ける。実はこれが一番高速だったりする。Array.prototype.min = function(){	return Math.min.apply(null,this)}Array.prototype.max = function(){	return Math.max.apply(null,this)}ただこれは、配列が空だとInfinityを返してしまうとか、そういう問題はある。"},
{file:"diary_200510091310.htm",title:"[速報] GoogleのRSSリーダー（β版）、早速真似して作ってみた",mtime:1128831057,ctime:1128831057,body:"GoogleからRSSリーダーがリリースされましたね。http://www.google.com/reader/ソース読むのとか面倒なんで真似して作ってみました。だいたい6時間ぐらいで出来た。http://la.ma.la/roll.htmlこのBlogで使ってるjsファイルをちょっといじって使ったので、キャッシュ利いてて動かない場合はリロードしてみてください。Firefoxだとアニメーションがやや重い。アニメーションを無くせばもっとサクサク動くんだけどGoogleReaderよりは軽いんじゃないかと思う。Operaはなんかスクロールしていくと強制終了します。アニメーションさせつつ、上下の要素を継ぎ足すようにしてやれば多分大丈夫だとは思うけど面倒なので現時点ではそこまでやってない。あとはIEとFirefoxではホイールを使ってページ切り替えられるようになっています。Googleの人はホイール知らないんだろうか。"},
{file:"diary_200510171151.htm",title:"一個しか更新してないのにBloglinesで上がりまくる件に対処",mtime:1129517497,ctime:1129517497,body:"多分これで直ってると思うのでテスト。「俺も原因がよくわからんのだよね」などと言ってたのだけどテキスト整形するときに上から何番目に表示されているかでIDを振っていて、それがRSSにも含まれていたのが原因。差分を強調表示してくれるRSSリーダーとかあれば早く気づいたんだろうけど。たまに文字化けしたりするのはFeedburnerのせいだと思う。"},
{file:"diary_200510171428.htm",title:"Fasterfoxが酷すぎる件",mtime:1129527110,ctime:1129527110,body:"Fasterfoxhttp://fasterfox.mozdev.org/Fasterとか見るとつい試してみたくなる衝動に駆られて試してみたんだけど、これはひどいなと思った。リンク先読み機能ってのがデフォルトで有効になっているんだけど>>>先読み機能は他にダウンロードしている場合はそちらに優先権を譲るので競合して帯域幅をパンクさせることはありません。それどころか使用していない帯域を有効活用する機能です。<<<どっちも自分のことじゃないか、相手のサーバーのことはどうでもいいのか。まあ俺は基本的には帯域幅よりサーバー負荷より人間の1分1秒のほうが貴重だとは思ってるんだけど。del.icio.us開いたら片っ端から先読みし始めるし、既読のページにもかかわらず先読みするし節操が無い。読みもしないページを片っ端からダウンロードすることが有効活用と言えるのか？もしもローカルネット内でキャッシュプロキシが利いているという前提ならばこういう実装でもいいとは思うが。このブログにもたまに物凄い勢いでアクセスしてくるFirefoxがいるんだけど、多分この拡張が原因だろう。少し前にGoogle Web Acceleratorというソフトが公開されてすぐに配布停止して今また配布再開しているんだけども、Google Web Acceleratorは- 次に読む確率が高いブログの前後のエントリ- リンクに対してマウスオーバーした瞬間なんかに先読みをしていた。さらには相手のサーバーに負荷をかけないようにGoogleがクロールしたキャッシュを使う。それに比べるとFasterfoxはひどいっていうか知性が足りないように思う。とまあ、ここまで書いといてアレなんだけどレンダリング速度の測定に使えるので結構便利。高速化に関しては何にもしなくてもFirefox1.5 beta2で随分速くなってるし、それでもまだOperaのほうがレンダリングや戻る進むは速いかって感じだったり、そんなことよりもRSSリーダーを使ったり食生活の改善に取り組んだりしたほうが効果的なのではないか、と思った。"},
{file:"diary_200510180540.htm",title:"Winnyの技術のPDFがやっと公開",mtime:1129581644,ctime:1129581644,body:"公式に流すっていうアナウンスがあったので読んでから買おうかと思って待ってたんだけどなかなか流れて来ないからもうすでに丸善津田沼店で買っちゃったんだけど。PDF(一般書籍) [金子勇] Winnyの技術 [05-10-03].zip 1,900,259 9d2dd618c580e38ea6869c51d9ed1107サイズは小さいけど本物。テキストデータなのでこんなもんだろう。Amazonで品薄状態なので今すぐ読みたいって人はPDFで読むと良いかも。まあ買ってから気づいたんだけど、今すぐ急いで読まなくちゃいけないというような本ではなかった。もうしばらく待ってる。"},
{file:"diary_200510291748.htm",title:"Amazonのカートが仕様変更してるっぽい",mtime:1130575994,ctime:1130575994,body:"http://www.drk7.jp/MT/archives/000942.htmlエラー画面がしばらくほっとけば直るようにも読めるんだけど多分仕様変更だと思う。なんかAmazletのカートに入れるボタン動かなくなってるし、はてなのも動かなくなってるな。他にも動かなくなってるアプリがちらほら。GoogleのデフォルトエンコーディングがUTF-8になったときのことが思い出されるような。あくまでフォームを勝手に呼び出してるだけなので、いつ動かなくなってもおかしくはないんだけど、こういう些細な変更でも告知とか出してくれたほうが親切な気がするんだけど単に担当者がいないんだろうな。Amazonとしては「API公開してるんでそっち使ってね、仕様変更はこっちの勝手」とか、そういう立場なんじゃないかと思う。似たような事例としてはRSS配信してるからデザインがダサくてもオーケーとか。そういう。外部と連携するようなサービスで、フォーマットを変更する可能性がある場合には互換性を保ちつつ仕様変更できるようにURLにバージョン番号や日付なんかの識別子を含めるようにするのが良いと思う。AmazonのECSなんかはすでにそうなっているし、円滑にバージョンアップするためにはとても重要なことだと思う。Amazon最速検索を作るときに参考にしたのはチュートリアルのPDFこれ印刷すれば知りたいことは大体全部載ってるんだけどこのファイルの場所がわかりづらすぎる。http://forums.prospero.com/n/mb/message.asp?webtag=am-assocdevxml&msg=6951.2&ctx=4096カートに入れるフォームの作り方。サンプルはGETになってるけどPOSTでも動く。http://aws.typepad.com/aws_jp/2004/12/ecs.htmlここらへんか。"},
{file:"diary_200510301205.htm",title:"Emacsの本を買った。",mtime:1130672313,ctime:1130672313,body:"Emacsの本を買ったけど1時間で挫折して萌ディタを使っている。*萌ディタTips : Saveと同時にSleipnirを更新f.onSave = function(){	var pnir   = new ActiveXObject(\"Sleipnir.API\");	var tabid  = pnir.GetDocumentID(pnir.ActiveIndex);	var window = pnir.GetWindowObject(tabid);	window.location.reload(true);}srcfile.javascript.txtなんかに加えるとファイルを保存するたびにSleipnirのアクティブタブをリロードするようになる。CSSとかいじってるときにとっても便利。Emacsとかダメだ、キモい。vimとかもっとキモい。無理。"},
{file:"diary_200511011141.htm",title:"現在の日時を返すスクリプト",mtime:1130823782,ctime:1130823782,body:"ちゃんとPerlで書けよ#!/usr/bin/perlprint `ruby -e \"puts Time.now.strftime('%Y/%m/%d')\"`ねたもと：http://subtech.g.hatena.ne.jp/secondlife/20051101/1130810376発端：http://d.hatena.ne.jp/naoya/20051031/1130710931----追記そういや以前JavaScriptでstrftimeっぽいのを作ったのを思い出した。http://la.ma.la/misc/js/strftime.htmlソースはこんなかに。http://la.ma.la/js/date_extra.jsかなりいい加減な気がするのでPerlのDateTime参考にして書き直そうかなあ。とか考えてたり。"},
{file:"diary_200511041713.htm",title:"キー割り当て用ライブラリを作った",mtime:1131092133,ctime:1131092133,body:"依頼を受けて作ってみた。http://la.ma.la/roll.htmlhttp://la.ma.la/js/hotkey.jsj,kでスクロールできる。使いまわしがきくように他のライブラリに依存も影響もしないように作ってあります。Bloglinesのj,kでスクロールみたいなのを作りやすいようにするのが目的。ただsafariとかは何かかなり違うらしいので、そこらへんは良く知らない。あとOperaはデフォルトでワンキーショートカットが割り当てられてたりするので動くとは限らない。全体に対してキーイベントを設定すると、フォームの入力ができなくなるっていう問題があるのでイベントの発生元がinput|textareaの場合は処理しないようにしてある。追加したコードはこんな感じ。var kb = new HotKey;kb.add([\"j\",\"2\",\"down\"], function(){rollto(c_pos + 1)});kb.add([\"k\",\"8\",\"up\"]  , function(){rollto(c_pos - 1)});kb.add([\"H\",\"home\"],     function(){rollto(0)});kb.add(\"pageup\",         function(){rollto(c_pos-3)});kb.add(\"pagedown\",       function(){rollto(c_pos+3)});kb.add(\"キー入力\" , 実行する関数)という感じで、キー割り当てを追加。複数のキーに対して同じ処理を割り当てたい場合は配列を渡せます。「shift + a」の場合は「A」を指定。Ctrlを押して二秒以内にEnterとか、そういう細かい挙動は指定できない。そこらへんはおいおい考える。kb.sendKey(\"down\")みたいにやると、カーソルの下を押したときの動作をエミュレートできます。この辺はテストの自動化なんかにも応用できそう。----普通、クリックイベントなんかを割り当てる場合buttonA.onclick = function(){...}buttonB.onclick = function(){...}buttonC.onclick = function(){...}というような具合になるのだけれども、document.body.onclick = function(e){	switch(e.target.id){	 buttonA : ...	 buttonB : ...	 buttonC : ...	}}というような記述のほうが効率が良い気がする。（実際はこういうコードじゃないけど、考え方として）とりあえずdocument.body全体にリスナーイベントを設定してしまって、クリックされたHTMLElementのタグ名、ID、CSSのClassなんかに応じて内部で処理を振り分ける方式。ウェブアプリケーションフレームワークでいうところのDispatchとかそこら辺のノウハウ応用すればもっと上手くやれそうな気がする。"},
{file:"diary_200511042135.htm",title:"Shibuya.pm Tech Talks #6 レポート",mtime:1131107748,ctime:1131107748,body:"naoyaの靴下は変だった。となりの席でhigeponが寝てた。裸足にサンダルの人がいた。二人も。人の靴下をじろじろ見るのは変態のやることだからやめようと思った。新宿で酔っ払いに絡まれて裸足にサンダルで逃げているところを裸足にサンダルの人に写真撮られた。以上、レポートでした。"},
{file:"diary_200511070134.htm",title:"Tropyクローンを作った",mtime:1131517397,ctime:1131517397,body:"なんかJavaScriptで作れ、みたいな圧力がかかったので作ってみた。http://la.ma.la/misc/tropix/(追記：ソース)http://la.ma.la/misc/tropix/tropix.zip元ネタこれねhttp://www.hyuki.com/d/200511.html#i20051105203040最速版Tropyということで、サーバー負荷と表示速度の改善を主に。JavaScript無効だと表示すらできないのであんまりよろしくないんだけど。----技術的なこと- サーバーサイドはRubyで書いた。90行ぐらい。普通のCGI。- ランダムなページのアドレスをCGIに問い合わせて、テキストはAjaxで直読みする。- 履歴を10件分保持するので、行き過ぎても戻れる。- サーバーにとてもやさしい。- ページリストを取る際に履歴をPOSTで送るので、最低10件は重複しないで表示される。- いちおうPermalinkをつけてみたけど、JavaScript必須でbotは拾えない。- 検索エンジンに載らない。- 広告収入で稼げない。もう一つクローン作ってたんだけど、あまりに狙いすぎてて、つまんない気がしたのでやめた。"},
{file:"diary_200511110409.htm",title:"ハイパーリンクとは時間軸の移動でもある、ということについて",mtime:1131649755,ctime:1131649755,body:"例えば関連性の不明な二つのテキストの間に、どれだけの時差があるかを視覚化してみるとどうなるか、というわけで、ちょっと改造してみた。http://la.ma.la/misc/tropix/"},
{file:"diary_200511210648.htm",title:"初心者にオススメ入門Ajaxのレビュー",mtime:1132963488,ctime:1132963488,body:"正直、この本はボロクソに叩こうかと思って買ったんだけど、著者プロフィールをみるとどうやら本職の人ではないらしいのであんまり叩くのはやめた。とはいっても俺も本職の人ではなくどちらかというと無職の人なので騙されたと思って買ってください。20冊売れれば元が取れるので。（某大手アルファスパマー2.0の人は20冊以上売ったらしい）全く関係ないけど個人的におすすめなのはMdNのJavaScriptビジュアルリファレンスという本で、これはもっと前に紹介しても良かったんだけど、多分今出ているJavaScript関係の書籍の中で一番役に立つ。DOM関係やイベント関係も詳しくはないけれど、とりあえず全部載ってるので、一通り目を通せば何が出来て何が出来ないのかがわかる。なにで調べればいいのかわかるので、後はGoogleで調べりゃいい。あと、WSHリファレンスのHTMLヘルプを手元に置いておくと便利。http://www.microsoft.com/japan/msdn/scripting/default.aspあとはcolinux+SpiderMonkeyもしくはRhinoとか。付け加えるとRubyのリファレンス。これはネーミングにとても役に立つ。http://elbereth-hp.hp.infoseek.co.jp/ruby.htmlというよりRubyを学ぶことはJavaScriptを学ぶ上でとても役に立つ。"},
{file:"diary_200511260836.htm",title:"全てのWeb開発者必見：fluxiom",mtime:1132963390,ctime:1132963390,body:"fluxiomである。http://www.fluxiom.com/fluxiomはRuby on Railsで作られた、ソーシャルとタギングを備えたオンラインファイラーというようなものらしい。まだサービス開始していないが、デモムービーが公開されている。fluxiomを開発している会社はscript.aculo.usの開発元ということであるので、当然「Rails + prototype.js + script.aculo.us」で作られている、ということになるのだろう。と思ってみたら、開発者のBlogに追記されていた。「Ruby on Railsで作られていて、Flashは一切使っていない」ということである。http://mir.aculo.us/articles/2005/11/24/fluxiomscript.aculo.usは「web2.0 JavaScript」だそうである。随分前からこのタイトルだ。俺は正直言って、ビジュアルエフェクトにはあんまり興味がない。ビジュアルエフェクトがWeb2.0なのかっつーとそんなわけがなく、いかにもWeb2.0言いたいだけちゃうんかと、っていう感じはする。しかし、ビジュアルエフェクトは重要である。飛んだり跳ねたり伸びたり角を丸くしたりすることは、低コストで注目を集めるのに大変効果的なテクニックである。ユーザビリティ的にも効果的なアニメーションは自分が何をやってるのかをわかりやすくする。大変重要である。俺はscript.aculo.usを誤解していた。鬱陶しいDHTMLの延長だと思っていた。しかしそれは完全な誤解でありscript.aculo.usの方向性は誤っていなかった。fluxiomのデモを見る限り、script.aculo.usはfluxiomのために作られたかのように思える。ちゃちな自己満足のための鬱陶しいエフェクトではなく、完成された一個のウェブアプリケーションに組み込まれることを、初めから想定して作られていたのである。彼らのやろうとしていることは全くもって正しい。検索やズーミングを中心に添えているあたりはPicasaを思わせる。しかし、それがオンラインで動く以上、デスクトップアプリケーションを超えるのは必然である。とにかく強烈なパフォーマンスである。全ての開発者に刺激を与え、新しい規範を示すだろう。日本の企業がこのレベルにまで到達するにはあと2～3年はかかりそうな気がする。それにしてもRailsはヤバい。はてながPerlだAmazonもPerlだのと言ってる間に、ギークたちがこっそりRubyを勉強しているというのはすでに周知の事実であるし、実際にRubyを使うかどうかは別としても2005年度RailsがWebプログラマに与えた影響は計り知れないだろう。一つ、Ajaxに関してGoogleはそんなにすごくない、ということである。Googleの保有するオーバーテクノロジーというのは巨大なCPUパワーであって、たかだか末端のユーザーインターフェース部分などは、一介のニートが6時間で真似できる程度のものである。Googleはそんなにすごくない。fluxiomはちょうヤバい。全てのWeb開発者はこのデモムービーを見るべきだ。必見である。del.icio.us使ってる人ならもう知ってると思うけど、とにかくfluxiomはヤバい。もう一回URL張っとく。http://www.fluxiom.com/"},
{file:"diary_200511260950.htm",title:"入門Ajaxが初心者にオススメできない理由",mtime:1138581578,ctime:1138581578,body:"このブログは基本的にひたすらなんか作ってリンク張るというスタンスでやってきたのでAjaxなサイトやら、ライブラリやら、フレームワークやらは全然紹介してこなかったし、あんまりそういうことをやるつもりもないのだけれど何で急にfluxiomヤバいとか書いているのかというと何もかも入門Ajaxのせいである。入門Ajaxがダメだというのは、別に内容のことではない。いや、もちろん内容が酷い部分もあるのだけれど、サンプルは初心者向けで悪くないだろうし、高度な内容を取り扱おうと思ったらきりがない。情報収集の仕方を知らない人がまとまった情報を手っ取り早く得たいと思っているならば、2500円は安い値段だ、悪くない。あと17冊買うべきだ。問題は、この本がとても閉じているということだ。日本語のリソースしか紹介していない。クロスブラウザだとかビジュアルエフェクトだとかは海外のライブラリのほうがよっぽど上手くやってるのに、そういうのをろくに参考にせず、紹介もせず、ポインタすら示さず、ただひた隠しにしているようなところがある。いつの時代だって初心者もいれば上級者もいるわけで、PerlでいうとCPANモジュール使ってフレームワークやらMVCやら使って華麗にOOPなコードを書く人も入れば、無料CGIレベルでprint連呼でhtmlタグを大文字で書く人もいる。どの言語でもそういうことはあるのだろう。けれど、特にPerlとJavaScriptの場合はとにかく上と下の格差が大変ひどいように感じる。例えば2chのJavaScript質問スレなど、いまだに「ポップアップウィンドウを制御するにはどうしたらいいんですか？」というようなレベルである。今実際行って確かめてみたら本当にそうだから救いようがない。困る。これはもうなんというか技術レベルどうこうの問題ではなく、単純に時間軸がずれているとしか思えないのである。ポップアップウィンドウなどもはやブロックされるのがデフォルトなのだから使うこと自体間違いだ。強調しておくと、俺が入門Ajaxをダメだと思うのは別に内容がどうこうということではなく、そういう時間軸のずれた人たちをそのまま放置するような姿勢が許せないということである。いや、もちろん内容が酷い部分もあるのだけれど。とにかく3日前にAjax知って入門Ajax買ってこれから勉強とか言う人は、まず何よりも先に、真っ先に、ずれた時間軸を矯正するために「RSSリーダー」と「ソーシャルブックマーク」を使うべきである、ということだ。このBlogを読んでいるような人はほぼ間違いなく使ってるはずだけれど、万が一使ってないようなことがあれば今すぐ始めるべきだ。遅くはない。Bloglinesとかdel.icio.usとか。別にはてなブックマークでもいいけれど。このBlogはそんなに更新されないし、ろくにコメントも付かないし、最速のインターフェースを研究するという大変ニッチなジャンルであるにもかかわらず実はBloglinesで600人も購読していたりする。多分日本人のBlogではトップ10ぐらいに入ってるだろう。驚くべき実体である。インターネットには裏側がある。RSSへのアクセスはページビューの10倍ぐらいあるし、はてなブックマークされた回数ときたらコメントの100倍ぐらいある。全く酷い話だ。下についてるコメント欄はダミーだ。アクセスのほとんどはRSSリーダーとソーシャルブックマーク経由だと言っていい。しかしだ。それでもなお、はてブのトップに載るより、カトゆーに載った時のほうがはるかに大量のアクセスが来るのである。正確には覚えてないがとにかくはてなブックマークで1位になるよりカトゆー家断絶に紹介されたほうが断然アクセスが来る、20倍ぐらいは来る。本当に驚くべき実体である。一体カトゆー家断絶をどんだけの人間が見てるんだよって話だ。いまだにああいうのを毎日チェックとかしてる人がいるのだろうか。俺が言いたいのは「RSSリーダー」と「ソーシャルブックマーク」という便利な道具を1万は超えるであろう読者に教えずに、秘密にし、騙し続ける事に対して罪悪感はないのか、ということだ。個人ニュースサイトの運営者なんかは当然RSSリーダーとかバリバリ使ってあちこちにアンテナ張ってるんだろうから、知らないわけがないのである。一体いつまでそういうことを続けるつもりなのか。せめてRSSを吐けと。"},
{file:"diary_200511300740.htm",title:"既読リンクを隠すブックマークレット",mtime:1133308083,ctime:1133308083,body:"いまだにかとユーとか見てる人がたくさんいるみたいなので既読のリンクを隠すブックマークレットを作ってみました。IE用 : 既読隠すFirefox/Opera用 : 既読隠すフレーム対応とかは誰か暇な人がやってくれると助かります。----すでに表示されているHTMLにCSSルールを追加する方法はJavaScriptでプレビューつきCSSエディタhttp://tokyoenvious.xrea.jp/b/javascript/css_editor_2.htmlを参考にしました。"},
{file:"diary_200511300810.htm",title:"GoogleAdsenseの「このサイトに広告を掲載」を表示させる方法",mtime:1133305851,ctime:1133305851,body:"ちょっと前にどのサイトでも出るようになるよ、ってニュースがあったんですが、出てるサイトと出てないサイトがあるようです。なんかクリック率とか支払い実績とかページランクによって違うのかなあ、と思ってあちこち見てみたんですが、そういうのは関係ないみたいで、どうやらAdsenseのアカウント設定＞広告主のオンサイト サインアップからサイト名やら説明文やらを一度入力しておくと1日ぐらいで出るようになるっぽいです。まあ、どうでもいいんですが。"},
{file:"diary_200512012226.htm",title:"情報収集のための11の質問",mtime:1133444785,ctime:1133444785,body:"http://www.jarchive.org/temp/joho.htmlバトンが回ってきたので答えるよ！ああ、もうバトンでもないか、これ。* 1.RSSリーダーを使っていますか?- Bloglines。632フィード読んでる。- 使い始めたころは50ぐらいだった。- ごくプライベートなものを除いては公開してる。* 2.アンテナを使っていますか?- アンテナや更新チェッカは使ってない。- どうしても必要ならなんでもRSSか野良RSS使う。* 3.ソーシャルブックマーク(SBM)を使っていますか?- http://del.icio.us/ma.la- http://del.icio.us/inbox/ma.la* 4.その他情報収集に使っているツールはなんですか?- GoogleAlertとGoogleアラート。- IRC、リファラ、bulkfeedsの検索結果フィード。* 5.他人にこれはお勧め!と思う方法は?- 発信すること。恥を書かないように頑張れるから。- 何か面白げなものを作ってる人がいたら継続して追いかける。- 同じ記事を自分より早くクリップしてる人のブックマークを見て良さげならsubscribe。- 他人のinboxを購読。適度に重複してると重要な記事を見逃さない。* 6.逆にこれはお勧めできないな、と思う方法は?- 素のIE使ってる奴は本気でダメ。* 7.情報収集で良く参照するサイトは?ネタ元になることが多い（自分より早い）のは、- del.icio.usのmiyagawa、higeorange、e_luck- はてなブックマークのid:brazil- MM/Memoの新着全部- あとhail2uってひとがいたんですけど今ゲーム期* 8.自分のブログで良く言及･リンクするサイトは?- 特にない。* 9.逆にここは参照してはいけない、と思うサイトは? - ReadMe張ってるようなサイト、hirax除く。* 10.WEB以外で良く情報源にするものは?- ネットランナー* 11.最後にあなたが情報収集方法を知りたい人は? - id:brazil- あとyoupy（ブラクラ注意）* 補足RSSBarとか使ってた時期もあったんだけど更新が気になってしょっちゅうリロードしてしまう癖があって、そういうの迷惑だろうから巡回は全部Bloglinesに任せることにした。del.icio.usのinboxは「そういや見たけどブックマークしなかったな」というようなのを後から探せるようにthunderbirdに読ませてたんだけど、重くて使えなくなったので今はOperaに読ませてる。そろそろ読むの大変なんだけど減らしたくはないので、もっと速く読めるインターフェース考える。あと昨日はてなスタッフと飯食ってきたんだけどあんまり大量にRSS読んだりとかはしてなさそうだった。"},
{file:"diary_200512090950.htm",title:"Haskell風にJavaScriptを書く",mtime:1138581407,ctime:1138581407,body:"ていうのをだいぶ前に作ったんだけど、コードがごちゃごちゃで何やってるか自分でもよくわかってなかったのでちょっと整理して公開。フィボナッチ数列を求めるのに大変便利です。http://la.ma.la/misc/js/haskell/関数の定義を記述すると、再帰処理でごにょごにょやって求めてくれる関数を生成します。メモ化もします。色々いじってたらなんとなく出来た。あんまり細かいツッコミされても困る。実際のところJavaScriptは再帰処理をたくさんさせるとすぐにスタックオーバーフローで止まってしまうので使い物になりません。数を大きくすると即死したりするので注意が必要です。タイマーを使って再帰処理させるとかトリッキーなことをすれば回避することもできるのだけれど面倒くさい。遅延評価っぽくなっていて、// 代入はできるtest = ack(100,100); // アッカーマン関数(100,100)// 評価すると死ぬalert(test) // Stack overflowとか、そういう具合になります。JavaScriptではtoStringやvalueOfというメソッドをいじる事で、実際にその値が使用されるまで演算を遅らせることが可能です、という記事をあとで書く。----今年はHaskellを覚えよう、などとは思っていたのだけれどインストールしただけで何もしてない。なんか本が出るそうなので言語マニアにならない程度には覚えていきたい。まあそのうち。関数型言語の時代が来るよ。たぶん。"},
{file:"diary_200512110838.htm",title:"del.icio.us買収と1470.netのExit戦略",mtime:1134257922,ctime:1134257922,body:"すでにあちこち書かれているけど米Yahoo!がdel.icio.usを買収した。del.icio.usは良くあるネットベンチャーではない。買収されるために作った会社、というのは、まあ実際そうだろう、実際そうだろうけれどもそんなこと言うやつはスーツ脳だ。スーツ脳の恐怖だ。del.icio.usは完全独立中立国家だった。- 概要を取得してAdsenseを貼り付ける、であるとか。- AmazonのURLならアソシエイトIDを付加する、であるとか。そういうことをしない。AmazonのURLは正規化したほうがいいに決まってるのにそういう特別扱いをしない。クロールをしない。ブックマーク以外のデータを保持しない。URLのMD5ハッシュ値をキーにしていてdel.icio.usにURLを教えずにそのページに関する情報を取得することが出来る(これは、だいぶ昔に書いた)。完全一致の取り出しに特化していて代わりに検索が出来ない。言うなれば、del.icio.usにはユーザーの利便性よりも美意識を取るという狂気があった。del.icio.usは単なるソーシャルブックマークサービスではない。同じものを作れる人はたくさんいる。del.icio.usよりも○○の方が高機能だ、とか、そういう話はよく聞くし、検索機能がついてたりBBSが付いてたりサムネイルが付いてたりスナップショットを保存してくれたり色々ある、そんな中にあってdel.icio.usはURLがかっこいいという理由だけで30万ユーザーを獲得した。残念なことにdel.icio.usを買収したYahoo!はevilである。いやそれは正確ではなくdel.icio.usに比べればどの企業も相対的にevilであるというだけのことだ。もちろん短期的に見ればサーバーが軽くなるとか、検索が使い物になるとか、そういうメリットのほうが大きいだろう。del.icio.usもYahoo!もユーザーも誰も損をしない。ただハッカーの士気に関わるだけで。----del.icio.usの持っているデータが全開放されたら世界が変わる。del.icio.usのCPUパワーと回線帯域が無尽蔵であれば、全てのリンクに「3users」とかくっつける事が出来る。（だから俺は常々「P2P!P2P!」とか言ってるんだけども）Googleならば世界を変えられるだけのCPUパワーを持っているかもしれない。けれどyahooには無理だ。yahooだもの。yahooに出来ることといったら、せいぜいdel.icio.usの持っているデータを使ってyahooの価値を高めることぐらいである。Flickrと連携するとか言うからげんなりする。del.icio.usがyahooの力を借りて無尽蔵のパワーを得るのならば素晴らしいけれど、あんまりそういう未来を期待できない。2%ぐらいしか期待できない。多分しばらくは今までどおり何も変わらないだろう。けれど、del.icio.usが完全独立中立国家でなくなったことは、確かだ。同じものを作れる人はたくさんいる。けれども何もかもが足りない。CPUが足りない、回線が足りない、愛してくれるユーザーが足りない。そんな中にあって、del.icio.usはURLがかっこいいという理由だけで30万ユーザーを獲得した奇跡だ。実際のところ、del.icio.usにしてみれば美意識なんてどうでも良くて、さっさと資金を調達して何か新しいことを始めたかっただけかも知れない。あるいはこれからぐんぐんevilになっていくのかもしれない。del.icio.usの買収は、わかりきっていたことだけれどもやっぱり悲しい。Web2.0て所詮パワーゲームか？どれだけユーザーを囲えるかの勝負なのか？買収だけがゴールなのか？URLがカッコ悪けりゃゴールは無いのか？どうなんだ。どうなんだよ。"},
{file:"diary_200512131313.htm",title:"del.icio.usにはてなブックマーク件数をくっつけるGreasemonkeyスクリプト",mtime:1134458726,ctime:1134458726,body:"はてなブックマークの件数をまとめて取得するAPIができた、ということでhttp://d.hatena.ne.jp/naoya/20051212/1134375086Bloglinesにはてなブックマーク件数をくっつけるGreasemonkeyスクリプトのhttp://d.hatena.ne.jp/m4i/20051213/1134425307改造して作ってみました。http://la.ma.la/misc/userjs/dxh.user.jsFirefox1.5とGreasemonkey0.6.4で動作確認してます。E4Xを使っているので1.0系では動きません。変更点はXPathをちょっといじったぐらいです。かなり簡単に作れます。なんかループが多かったのでレスポンスを連想配列に入れるようにしました。後、これ系の作る時にはXPath検索バーが便利です。http://tokyoenvious.xrea.jp/b/javascript/xpath_finder.htmlとりあえず公開、後で何か書くかも。萌ディタ強制終了して文章消えた。----1.0.1typesterさんの要望によりURL個別ページにも表示するようにしてみた。こういうの。http://del.icio.us/url/1ab69d1ff092ab4ed57297fadde9da19"},
{file:"diary_200512151101.htm",title:"全てのWeb開発者必見 : remember the milk のサインアップフォーム",mtime:1138581073,ctime:1138581073,body:"ライブドアの次世代テクノロジーセミナーの後の二次会の後のSledge勉強会で発表したネタ。http://www.rememberthemilk.com/signup/Ajaxを使ったTODO管理やらリマインダサービスらしいのですが、これのサインアップフォームがとてもよく出来ています。苗字と名前から自動でアカウント名を補完してくれたり、それをサーバーに問い合わせてそのアカウントが取得できるかどうかを確認してくれたりします。肝心のサービスの中身は使いやすいのかどうか良くわかんないというか、正直微妙な感じなんですが、一度しか通過しないサインアップフォームを作りこむ心意気が良いですね。別に必見ってほどでもないか。でも知ってる人がいなかったのでブログに書いておくことにします。"},
{file:"diary_200512151442.htm",title:"ネットランナーがWeb2.0特集",mtime:1138581305,ctime:1138581305,body:"Web2.0がなんなのか良くわかってない人は必見かも。"},
{file:"diary_200512191015.htm",title:"忘年会議2005レポート",mtime:1134954945,ctime:1134954945,body:"忘年会議2005に参加してきました。2005年の「究極のウェブサイト」第2位に選ばれました。大変光栄です。一年間、わりとよくがんばれたとおもいます。インターネットに感謝します。ありがとうインターネット。ちなみに1位ははてなブックマークでした。はてなに負けて大変不愉快です。----二次会(忘年会)ではダイヤ☆ハシモト氏と真性引き篭もりについて熱く語り合いました。「引き篭もりなのか引篭もりなのか、たまにわからなくなるよね」「真性でGoogleトップに出ますよ」などというTipsを交換した。----以上、レポートでした。真面目なレポートを読みたい方ははてなブックマークをご活用ください。http://b.hatena.ne.jp/t/%e5%bf%98%e5%b9%b4%e4%bc%9a%e8%ad%b0?sort=eid"},
{file:"diary_200512291411.htm",title:"Safariでreplace callback のエミュレーション",mtime:1135833210,ctime:1135833210,body:"replaceメソッドをhackしてsafariでもreplace callbackを使えるようにしてみた。Safari バージョン 2.0.2（416.13）で上手く動いたそうです。手元に環境が無いので細かい検証はできませんが、とりあえず。http://la.ma.la/misc/js/replace_callback/* 解説JavaScriptのString#replaceメソッドは文字列を置換して新しい文字列を返すメソッドですが、第二引数に置換後の文字列を指定する代わりにfunctionオブジェクトを渡してやると、Perlでいうところのeオプションみたいなことができます。// 大文字を小文字に、小文字を大文字にString.prototype.swapcase = function(){	return this.replace(/([a-z])|([A-Z])/g,function($0,$1,$2){		return ($1) ? $0.toUpperCase() : $0.toLowerCase()	})}\"Hello World!!\".swapcase() // hELLO wORLD!!第一引数にはマッチ文字全体、それ以降には後方参照用にカッコで囲った部分が渡されます。その後にはマッチ箇所の先頭からのoffset値、String全体が渡されます(ここでは使ってません)// 少しわかりやすく書くとString.prototype.swapcase = function(){	var reg = /([a-z])|([A-Z])/g;	var callback = function(match_text,lower,upper,index,self){		return (lower) ? lower.toUpperCase() : upper.toLowerCase()	};	return this.replace(reg, callback)}こんな感じになります。単純な置換だけではなくて、文字列の出現頻度を調べたりとか、簡単なテンプレートシステムを組んだりすることもできます。// Ruby風の変数展開String.prototype.fill = function(param){	return this.replace(/#\\{(.*?)\\}/g,function($0,$1){		return (param[$1] != undefined) ? param[$1] : \"\"	})}\"My name is #{name}.\".fill({ name : \"John\" }) // My name is Johnで、これを知ってからゴリゴリ使ってるのですが、どうもSafariでは使えないという話らしくhttp://jszen.blogspot.com/2005/12/safari-and-stringreplace-method.html次のリリースで直るそうですが、直ったところで古いバージョン使ってる人はいるわけなので作ってみました。本来のreplaceメソッドより動作は遅いはずなのでsafariの場合だけ適用するのが良いです。いくらなんでもsafari酷いなあ、と思ってたのですが、互換性を気にして便利なものを使えないよりは、自前で実装しまったほうが楽なケースも多いんじゃないかと。ブラウザの差異は大体こういう方法で吸収できるはず。* 参考ECMA-262 3rd Edition 邦訳 String.prototype.replaceのところhttp://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/15-5_String_Objects.html#section-15.5.4.11正規表現のeオプションをJavaScriptでエミュレートhttp://hail2u.net/blog/coding/emulate_regexp_e_option_in_js.html"},
{file:"diary_200512301450.htm",title:"2005年もパクられてこなかったもの私的まとめベスト3",mtime:1135931585,ctime:1135931585,body:"良く出来たものはパクられなければなりません。技術者たるもの我が社の利益だとか愛国心だとかのためではなく、人類の幸福のために行動すべきです。たかだか見た目程度でしか物事を判断できない人間がパクりは悪などという風潮を広めてまわるのは残念でなりません。大企業だろうがベンチャーだろうが一個人だろうが関係ありません、良く出来たものはパクるべきです。パクられてこなかった人の気持ちを考えたことがありますか？胸に手を当てて考えてみてください！* iRiderサムネイル表示とドラッグによる高速なタブ切り替えを備えたブラウザ。http://www.irider.com/irider/デモムービー(Flash)を見ると良いhttp://www.irider.com/demo/index.htm百式の紹介。http://www.100shiki.com/archives/2004/07/_iridercom.html* LensBar曖昧検索によるフィルタリングとなめらかなズーミング機能を備えたスクロールバーhttp://pitecan.com/research/LensBar/index.htmデモムービー(25MB)を見ると良い。http://pitecan.com/research/LensBar/lensbar.mpg* BloglinesあえてBloglinesを挙げる。殆どのRSSリーダー（特にローカルクライアントで動作するもの）はBloglinesを知らずに間違った設計をしてしまっている。論外の使い勝手で話にならない。いますぐつくりなおすべきだ。http://www.bloglines.com/* まとめ他にも何か色々あった気がするけどまあいいや。今日は三つね。"},
{file:"diary_200601010255.htm",title:"全てのウェブサイトを正月対応にするGreasemonkeyスクリプト",mtime:1136054480,ctime:1136054480,body:"さっき思いついたので作ってみた。http://la.ma.la/misc/userjs/akeome.user.js新年早々ネット巡回しているとcron仕込んで新年ぴったりに新年画像に差し替えているようなサイトをちらほら見かけたりしますが、なんの変化も見られない冠婚葬祭を重視しないサイトが非常に多くてガッカリそんなアナタに朗報このGreasemonkeyスクリプトを使えばどんなウェブサイトでもお正月ムードに変更してくれます。とかなんとか。mixiとか見るといい感じになると思います。今年もよろしくお願いします。"},
{file:"diary_200601100209.htm",title:"Wikipedia日本語版全文検索AutoPagerを作った",mtime:1136826584,ctime:1136826584,body:"Hyper Estraierを使ったWikipedia日本語版全文検索が大変素晴らしいのでGoogleAutoPagerの移植。Firefox1.5とGreasemonkey0.6.4で動作確認してます。http://la.ma.la/misc/userjs/estseekautopager.user.jsついでに色々と直してます。ローディングのエフェクトを入れたり、全体的に変なテクニックを駆使したり。- 無名関数を再帰処理させる。- GreasemonkeyからDOMParserを使う- valueOfメソッドをいじって残りスクロール量を返すオブジェクトを作るあたりは何かの参考になるかもしれません。"},
{file:"diary_200601100445.htm",title:"Firefoxでテキストをクリップボードにコピーする方法",mtime:1136868772,ctime:1136868772,body:"動作デモhttp://la.ma.la/misc/js/setclipboard_for_firefox.htmlFirefox1.5 + FlashPlayer8.5で動作確認してます。Opera8.5では動いたがOpera9では動作せず。Safariは知らない。FlashPlayerのバージョンによっても何か違うのかもしれない。元ネタhttp://a-h.parfe.jp/einfach/archives/2005/0706043145.htmlIEではデフォルト設定でブラウザからクリップボードの読み書きができる、というのは割と有名な話ですが、Flashを使うとIE以外でもクリップボードにテキストをコピーすることができます。上書きのみで読み込みはできないようなので多少は安心です。(クリップボードが勝手に置き換わってしまう、という悪戯はできる)で、このFlashを使ったクリップボード操作に使っているsetClipboard.swfというファイルは103bytesと大変小さいのですが、swfファイルをサーバーに設置するのが面倒くさいという人向けにdataスキームを使って単体で動くようにしよう、という話。dataスキームというのは「data:なんとか」という形式のURIでファイル自体を表すことができます。Firefoxのブックマークにfaviconを埋め込んだり、CSSに直接画像を埋め込んだり、Greasemonkeyに画像を埋め込んだり、ブラウザ上でアイコン作成したりするのに使われています。data URIを作成するにはPerlスクリプト、バイナリファイルも変換できるhttp://software.hixie.ch/utilities/cgi/data/data副産物、クライアントサイドで動くもの、テキストのみhttp://la.ma.la/misc/js/data.htmlを使います。----で、最初にとりあえずローカルで動くものができたのだけどサーバーにアップしたら動かない。どうもFlashの側でインターネットゾーンとdataスキームでのセキュリティ上の区分があるようで、多分dataスキームはローカルファイルとして扱われているような気がする。実験1 : setClipboard.swfをdataスキームに変換したもの、ローカルに保存すれば動くhttp://la.ma.la/misc/js/setClipboard.html実験2 : 同じ階層にsetClipboard.swfを設置、当然動くhttp://la.ma.la/misc/js/setClipboard2.html実験3 : 外部ドメインにsetClipboard.swfを設置http://la.ma.la/misc/js/setClipboard3.html実験3が成功したので、どっかしら適当なサーバーにsetClipboard.swfを置いておけばブックマークレットからも使える、ということにはなるのだけど、適当なサーバーにリファラが残るのがイヤだなあ、と思ったので何とかして単体ファイルで動かせるようにしたものが、これ。ファイル単体で完結して動く。http://la.ma.la/misc/js/setclipboard_for_firefox.html「表示するとクリップボードを指定文字列で上書きするHTMLファイル」をdataスキームを使って動的生成し、それをIFRAMEに読み込む、という回りくどい方法を取っています。dataスキーム動的生成に使ってるutf16to8とbase64encodeは高度なJavaScript技集から。http://www.onicos.com/staff/iz/amuse/javascript/expert/これでGreasemonkeyでクリップボードにコピーとか作れますね。最初の目的はGreasemonkeyでTSS Clipborad Player自動演奏でした。飽きたのであとはまかせた。----追記: 2005-01-10Firefoxではbase64が組み込み関数(btoa,atob)で使えるようなのでFirefox専用で短くしてみた。わずか27行。Greasemonkey組み込みなど、ご自由にどうぞ。http://la.ma.la/misc/js/setclipboard.txt"},
{file:"diary_200601150700.htm",title:"JavaScriptでDebugScreenを表示する",mtime:1138581234,ctime:1138581234,body:"デモ、IEかFirefoxhttp://la.ma.la/misc/js/debugscreen/IEとFirefoxではwindow.onerrorを設定するとJavaScript全体のエラーを補足できます。さらに返値をtrueにすると標準のエラーダイアログを抑制できます。簡単なサンプルはこんな感じ。window.onerror = function(mes,file,num){	alert([		\"file    : \" + file,		\"line    : \" + num,		\"message : \" + mes	].join(\"\\n\"));	return true;}あまり細かい情報を取得できるわけではないので、例外処理に使ったりはできないのですが、エラーメッセージを親切にしたりできるかもしれません。そんなわけで、ファイル名と行番号わかるなら自分自身をXMLHttpRequestで受信してエラー行付近を切り出したりできるんじゃないかと思って適当に作ってみた。arguments.callee.callerを使うと関数の呼び出し元がわかるんだけどwindow.onerrorの呼び出し元がIEじゃないとわからないようだった。あんまり役に立たないような気もするんだけどCatalystとかSledgeとかCGI::ApplicationとかでDebugScreenがブームになってたので作ってみた。遅いけど。"},
{file:"diary_200601160429.htm",title:"はてなに",mtime:1137353410,ctime:1137353410,body:"勝った"},
{file:"diary_200601161315.htm",title:"JavaScriptでDebugScreen、その2",mtime:1138581207,ctime:1138581207,body:"更新しました。ライブラリ化と適当にドキュメントを書いた。http://la.ma.la/misc/js/debugscreen/実際に使ってみたりしながら改良中。プラグイン方式で任意のオブジェクトを表示できるようにしてみました。関数を登録すると実行結果を返すので複雑なこともできます。サーバーにエラー投げるとかも、まあ、できるけど、本番環境でやるのはおすすめできない。あとは、強制的にスコープを保存する方法を思いついたのでローカル変数の内容をダンプしたりできるようにしようかな、と、考えている。var saveVars = \"window.__args__ = arguments;(\" + function(){	window.recall = function(expr){		if(expr == \"arguments\") return window.__args__;		return eval(\"(\" + expr + \")\");	}} + \")()\";function test(){	eval(saveVars); // 環境保存	var test = \"aiueo\";};function hoge(){ return test(1,2,3) }hoge();alert(recall(\"test\")); // aiueoalert(recall(\"arguments\")[0]); // 1alert(recall(\"arguments\").callee) // function test(){ ... }alert(recall(\"arguments\").callee.caller) // nullevalを使って「evalで任意の変数を取り出すクロージャ」を定義し、環境を無理やり外に引っ張り出しています。関数の呼び出しが終わった後でローカル変数を呼び戻す。適当な語彙が思い浮かばなかったので、とりあえずrecallで。argumentsを保持してやれば呼び出し元を辿れるかな、と考えていたのだけれど、最後のは上手くいかない。どうやら関数の呼び出しが終わるとFunction#callerプロパティは破棄されてしまうようだ。IE限定でarguments.caller.calleeだと上手くいったりする。arguments.callerは関数の呼び出し元のargumentsオブジェクトを参照する。Firefoxでは既に廃止されているようだ。ここら辺はECMA非準拠で環境依存が大きいのだけど、組み込めるようだったら組み込みたい。"},
{file:"diary_200601201204.htm",title:"Firefoxでの開発を高速化する自動リロードスクリプト",mtime:1137728545,ctime:1137728545,body:"以前にも書いたとおり萌ディタとSleipnirAPIを駆使して、htmlその他ソースファイルをいじると保存のタイミングに合わせてSleipnirのアクティブタブがリロードされるようになっているわけなのですが、近頃Firefox1.5をメインに使うようになってしまったのでFirefoxでも上手く動くようにしようという話。もちろん自動リロード機能を提供する拡張があるのは知ってるんだけど、編集のタイミングと関係なく1秒ごとにリロードさせたらせわしなくて仕方ない。あくまで保存のタイミングに合わせてブラウザを更新したい。最初は萌ディタからFirefoxにコマンドラインでブックマークレットを渡すというのをやってみたのだけれど、どうにも手元の環境では上手く動かない。新しいタブでブックマークレットを開いてしまったりする。WSHでFirefoxにフォーカスを合わせてF5を送るとかもやってみたんだけど萌ディタにフォーカスを戻す方法がわからない。そんなわけなのでエディタに依存せず、完全にブラウザの側で何とかすることにした。XMLHttpRequestで自分自身を取得してファイルの内容に変更があったら表示を更新するようにする。// 今開いてるページに変更があったらリロードsetInterval(function(){	var self = arguments.callee;	var req = new XMLHttpRequest;	req.open(&quot;GET&quot;,location.href,true);	req.onload = function(){		(self.old &amp;&amp; req.responseText != self.old) &amp;&amp; location.reload(true);		self.old = req.responseText;	};	req.send(null);},1000);これだと、自分自身のファイルしか見ていないので外部CSSなんかを変更したときにリロードされない。そこで（全部見張るようにしても良いんだろうけど）トリガーとなるファイルを手動で指定できるブックマークレットにしてみた。スタイルシートをいじっているときはstyle.cssなど指定すればスタイルシートの更新に合わせてページが再描画される。このページで起動されると困るのでローカルファイル専用。ブックマークレット ： AutoReloadで、いちいち実行するのが面倒くさいのでGreasemonkeyスクリプトにしてみた。ローカルファイルの場合、ファイルの更新を検知して自動で再表示するようになる。http://la.ma.la/misc/userjs/AutoReload.user.jsUser Script Commands から更新を検出するファイルとタイマーの周期を設定できるようにした。デフォルトは今見ているファイルと1000ミリ秒。後は萌ディタで保存するたびにperl -e &quot;open(FH,'&gt;c:/lastmod');print FH time;&quot;こんなワンライナーが走るようにしておいた。Greasemonkeyの側では「file:///c:/lastmod」を見張らせる。サーバー上で開発する場合はlocalhost/lastmodなんかに適宜変えるようにすれば良いだろう。----ちなみに。GM_xmlhttpRequestは他ドメインは読めるがローカルファイルは読めない。ローカルファイルからでも読めない。Greasemonkey0.6.4ではXMLHttpRequestが使えなくなっているため、代わりにunsafeWindow.XMLHttpRequestを使った。この場合、同一ドメイン、及び、ローカルファイルからローカルファイルへのアクセスができる。"},
{file:"diary_200601242029.htm",title:"はてなに入っ",mtime:1138102175,ctime:1138102175,body:"Wiki小話に行くついで、渋谷で暇だったのではてなに遊びにいった。しなもん日記のRSSを全文配信にしてくれと言うのを忘れた。"},
{file:"diary_200602011406.htm",title:"そろそろライブドア事件について一言いっとくか",mtime:1138770418,ctime:1138770418,body:"2月1日付けで株式会社ライブドアに就職しました。今後ともよろしくお願いします。"},
{file:"diary_200602081638.htm",title:"mixiのポータル化を阻害するGreasemonkeyスクリプト",mtime:1139384324,ctime:1139384324,body:"作った。idやclassが振ってないので難しいですね。http://la.ma.la/misc/userjs/mixi_anti_portal.user.js"}];