Introduction

ブログ内検索

  • このサイトの記事を検索 by Google

おすすめの一冊!

無料ブログはココログ

« 2009年8月 | トップページ | 2009年11月 »

2009年9月

2009-09-21

bk1_to_amazon

オンライン書店 bk1 の書籍ページに Amazon へのリンクを
自動的に埋め込むスクリプト(SleipnirScript&ぐりもん)
を書いてみました。



Seaoak は本を買うとき Amazon ではなくて bk1 を使ってます。
なぜかというと、ココログを始めたときにココログと連携して
いたのが bk1 で、「読んだ本のリスト」とかを作ると自動的に
bk1 へのリンクが生成されるようになっていたからです。
あと、Amazon だと過去に買った本がページ上に表示されてしまう
のがちょっと恥ずかしかった、というのもあります。
# 今はこの機能は OFF にできるのかな?

その bk1 なのですが、品揃えという点では悪くないのですが、
内容紹介とか書評とかがほとんど無いのがちょっと不満。
その点、さすがに Amazon は情報量が多いです。

で、bk1 で面白そうな本を見かけたときに、その本の Amazon のページを
のぞいてみることがあります。そのとき、ISBN をコピペして検索する
わけですが、これがちょっとめんどい。



というわけで、リンクを勝手に追加する SleipnirScript を書いてみました。
ページ内の文字列を取得してリンク要素を追加するだけなので、
イベントハンドラも使わないし、とってもカンタンでした。

唯一調べたのが、ISBN の計算方法。
bk1 のページに載っているのは IBSN13 という13桁のコードなのですが、
Amazon のリンク (URL) に使われているのは ISBN10 という10桁のコード。
基本的には ISBN13 の最初の3桁を削れば ISBN10 になるのですが、
最後の1桁はチェックサム(チェックデジット)なので再計算が必要なのです。
今回は WikiPedia の ISBN の項目を参考してコーディングしました。



で、あまりに単純なスクリプトになってしまったので、せっかくだから
Firefox の GreaseMonkey でも動くようにしてみることに。

ちょっと試行錯誤した結果、次のようなことが非互換性がわかりました。
# Sleipnir 2.8.5 と Firefox 3.0.14 です

  1.スクリプトの文字コードが違う。SleipnirScript は Shift-JIS で、
   GreaseMonkey は Unicode (UTF-8N) を期待してるっぽい。
   期待と違う文字コードにすると、スクリプトの説明文が化けたり、
   スクリプト中の日本語との比較(パターンマッチング)に失敗する。

 2.TABLE 要素の子としていきなり TR 要素を並べたとき、TABLE 要素の
   childNodes[] の順番が違う。Sleipnir だと TBODY 要素が先頭要素
   (firstChild) なのに、Firefox だと2番目の要素になってる。

 3.Firefox だとTBODY 要素の childNodes[] にゴミが混じる。
   Sleipnir だと TBODY 要素の childNodes[] はすべて TR 要素。
   Firefox だと childNodes[] の奇数番目の要素だけが TR 要素で、
   偶数番目の要素として Text ノードが勝手に挿入されている。


予想より手間がかかってしまいましたが、とりあえずどちらでも動く
スクリプトにすることができたので、公開します。


    ⇒ bk1_to_amazon.user.js
    最新版は userscripts.org にあります http://userscripts.org/scripts/show/75657

Sleipnir + SeaHorse の方は
     C:\Program Files\Fenrir & Co\Sleipnir\plugins\seahorse\
にコピーして、「Sleipnir オプション」の「拡張機能」の「SeaHorse」
のところで「再読み込み」ボタンを押せば組み込まれます。

Firefox + GreaseMonkey の方は、ダウンロードしたスクリプトを
Firefox のウインドウにドラッグ&ドロップして、開いたダイアログで
「インストール」ボタンを押せば組み込まれます。


バグ報告、ご要望など、お待ちしてます♪

2009-09-12

イベントハンドラのスコープへ

SleipnirScript の中でイベントハンドラを設定するには
ちょっと抜け穴的な手続きが必要になります。

    ⇒  SeaHorse でイベントハンドラ

このやり方では、定義した関数を toString() して Eval しているので、
イベントハンドラのコンテキスト(スコープ)が普通とは違っています。

具体的に言うと、toString() する関数の外で定義しておいた
変数や関数にそのままではアクセスできません。
# アクセスすると「未定義です」とエラーになります。

しかし、いろいろ試した結果、window オブジェクトを介することで
イベントハンドラからアクセスできることがわかりました。



まず、イベントハンドラ設定関数の外側(SleipnirScript の
コンテキスト)で window オブジェクトにプロパティを追加します。

var zzz = 'Here is SleipnirScript context.'; window.abc = function() {alert('zzz = ' + zzz)};
上記の通り、クロージャーも普通に使えます。 で、イベントハンドラの中では _window オブジェクトのプロパティ (メソッド)として参照します。アンダースコアに注意です。
_window.abc();
これで、イベントハンドラからオートメーションオブジェクトに アクセスできるようになったので、ますますデスクトップ アプリケーションに近づけた気がします。 いろいろ遊べそう。

SleipnirScript すごいかも

先日の記事 "Sleipnir with WSH" の続きです。

SleipnirScript の CreateObject() API を使うと、
任意のオートメーションオブジェクトが呼び出せるみたいです。
つまり、デスクトップアプリケーション並に何でもできそうです。

たとえば、WshShell オブジェクトを呼び出すと、環境変数の取得や
特殊フォルダ(「マイドキュメント」など)のパスの取得、
さらにはレジストリへのアクセスまでできてしまいます。

(function() { var shell = sleipnir.CreateObject('WScript.Shell'); var env = shell.Environment('System'); var num = env.Item('NUMBER_OF_PROCESSORS'); alert('環境変数(プロセッサ数):' + num); var path = shell.SpecialFolders('MyDocuments'); alert('マイドキュメントのパス:' + path) })();
これを前回紹介した FileSystemObject と組み合わせれば、 たとえばデスクトップにあるすべてのファイルを リストアップして読み取ることも可能になります。 これは試していませんが、もしかすると(もしかしなくても?) 任意の ActiveX オブジェクトを呼び出せるかもしれません。 ちょっとすごいかも。

2009-09-11

Win32 API のお勉強

Win32 API の入門書を発掘したので、ひさしぶりに読みました。

ちょっと古い本ですが(2002年から2年間の雑誌連載がベース)、いまだに 本屋さんに平積みされていたりするので、ひそかに人気なのかもしれません。 ありがちな「GUI プログラミングの入門書」でもなく、かといって OS に関する専門的な知識を前提としたマニアックな解説記事でもない、 Windows をまじめに勉強し始めるのにちょうどいいレベルの本というのは 意外に少ないのかもしれませんね。 内容は、Windows がメッセージを処理する仕組みから始まり、 ファイルシステム、メモリ管理、プロセス管理、といった OS の基本的な部分に関する解説があり、続いて実行ファイルの 構造や DLL の仕組み、プロセス間通信、といったプログラミングに 必要な基礎教養(?)に関する解説があり、さらにはデバッガの 動作原理や非同期 I/O などの雑学的な話にまで及んでいます。 それぞれの項目では、単に API 関数を言葉で説明するだけではなくて、 実際にプログラムからどのように使えばよいかを具体的なコードを示して 解説してくれています。そのため、かなり理解しやすく、また、 実際にコードを書く足がかりにもしやすいと思います。 実際のところ、この本だけで Win32 API を直接呼び出すコードを書けるか というと、情報が足りていない部分もあるかと思います。しかし、 いきなり MSDN の山の中をさまようより、この本の内容を足がかりにして 調べていけば、より短い時間で必要な情報にたどりつけると思います。 そういった意味ではちょうどいいレベルの内容のような気がします。 最近の .NET Framework でプログラミングする場合、これらの Win32 API に 直接触れることは少ないはずですが(触れなくてもいいようになっているはず)、 .NET と言えども最終的にはこれらの Win32 API を呼び出して動作している以上、 知っておいて損の無い話だと思います。というか、これら Win32 API の仕組みを 知らずに .NET の世界だけで考えてプログラミングすると、思わぬ落とし穴が ありそうでちょっと怖い気がします・・・ Seaoak はずっと UNIX (Solaris/Linux) の世界でプログラミングしてきたので Windows の世界は素人なのですが、意外な違いがあったりして楽しく読めました。 Windows でプログラミングをする人には広くオススメできる一冊だと思います。

2009-09-09

瑠璃色の地球

夏川草介「神様のカルテ」を読みました。

信州の地方病院に勤める医師のお話です。 大学病院の医局に勤めることが常道ななかで、 地方病院に勤めることに自らの道筋を見いだす、 そんな医師のお話です。 Seaoak の知り合いにも医師(の卵?)がいるのですが、 日頃はバカな話ばかりしているのが、仕事となると このようなたいへんな状況かとおもうと、少しばかり 頭が下がる思いです(でも話してる内容は・・・ そんなお話の中で心にとまったひとことを:
 しばしば医療の現場では患者の家族が「できることは全てやってくれ」と 言うことがある。五十年前までの日本では日常の出来事であったし、 その結果のいかんに関わらず、その時代はそれで良かった。 稚拙な医療レベルの時代であれば、それで良かった。  だが今は違う。  死にゆく人に、可能な医療行為全てを行う、ということが何を意味するのか、 人はもう少し真剣に考えねばならぬ。「全てやってくれ」と泣きながら叫ぶことが 美徳だなどという考えは、いい加減捨てねばならぬ。
ぼくら一般人は「できることを尽くすのが礼儀だ」というような気持ちを 持ちがちだと思いますが、そのようなきれいごとでは済まされない、 リアルな所感が表れていると思います。
 大量の輸血を行い、昇圧剤をつかい、場合によっては人工呼吸器につないで 呼吸を確保する。うまくいけば数日は持ちこたえるかもしれない。 信州一帯の貴重な血液製剤を取り寄せて輸血すれば、安曇さんの心臓は 二日ぐらいは働いているかもしれない。  なすべきか、なさざるべきか・・・。  医師の権限のすさまじさは、これらの事柄がただちに実行できることにある。
ここには、医師の権限の大きさと、それに対する責任の重さが表れていると思います。 日常的にこのような判断を迫られている重圧を推し量らずにはいられません。 最後に、このお話を読んで、思い出した歌があります。
「明けない夜はない。止まない雨はない。そういうことなのだ、学士殿」
松本聖子「瑠璃色の地球」です。
夜明けの来ない夜は無いさ あなたがポツリ言う 燈台の立つ岬で 暗い海を見ていた 悩んだ日もある 哀しみに くじけそうな時も あなたがそこにいたから 生きて来られた 朝陽が水平線から 光の矢を放ち 二人を包んでゆくの 瑠璃色の地球 泣き顔が微笑みに変わる 瞬間の涙を 世界中の人たちに そっとわけてあげたい 争って傷つけあったり 人は弱いものね だけど愛する力も きっとあるはず ガラスの海の向こうには 広がりゆく銀河 地球という名の船の 誰もが旅人 ひとつしかない 私たちの星を守りたい 朝陽が水平線から 光の矢を放ち 二人を包んでゆくの 瑠璃色の地球 瑠璃色の地球
iTunes Store で買おうと思ったらカバーしかみつからなくって、 とりあえずそれを聴きながらこの記事を書いています。 昔、合唱で歌ったことを思い出したりしました。

2009-09-08

SleipnirScript with WSH

前々回の記事で「SleipnirScript でファイルを読み込む際に EOF がわからない」
と悩みを書いたのですが、さっそくコメントで情報をいただきました!
958 さん、ありがとうございます~^^

つまりは、SleipnirScript の中で WSH のオートメーションオブジェクトを
呼び出して使えば OK、というお話です。

さっそく以前買った WSH の本を発掘してきて調査。
# だいぶ前に JScript を勉強したことがあるのですw


で、今回は、FileSystemObject オブジェクトと TextStream オブジェクトを 使うということになります。SleipnirScript の CreateObject() API で オートメーションオブジェクトを取得できるので、とってもカンタン♪
var fso = sleipnir.CreateObject('Scripting.FileSystemObject'); if (! fso) return; if (! fso.FileExists(fileName)) return; var fileObj = fso.OpenTextFile(fileName); if (! fileObj) return; while (! fileObj.AtEndOfStream) { var line = fileObj.ReadLine(); if (line.match(/^\s*$/)) continue; var fields = line.split(/\s+/); var name = fields[0]; table[name] = true; } fileObj.Close();
ちなみに、いただいたコメントでは AtEndOfLine がうまく動かない (空行で終了してしまう)とのことでしたが、AtEndOfLine の代わりに AtEndOfStream を使えば大丈夫でした。 これまで、応急処置として「連続した空行が1000行以内なら読み飛ばせる」 みたいなちょっと恥ずかしいコードになっていたので、まともなコードに できてうれしいです♪

2009-09-05

uncensored favotter

Twitter で注目されている発言がわかる「ふぁぼったー」ですが、
先日からアヤシイ単語が規制されるようになってしまいました。

もちろん理性的には納得できる話ですし、ぼく自身はそういうアヤシイ発言は
たぶんしないのですが、正直なところなんとなくイヤな気がしていました。
なんというか、Google の影響力をじわじわと受けているような?
# べつに Google がきらいなわけじゃないです(むしろ好きです)

そんな中、ふぁぼったーの中の人もユーザも Win-Win になれるような
ソリューションが登場しました。ふぁぼったーのサイト上は規制して、
でもユーザからの見た目は以前のまま、という策です。

ふぁぼったーの <censored>を突破するGreasemonkeyスクリプト書いた -- 5.1さらうどん
この実体は GreaseMonkey スクリプトで、規制された発言を元の発言に 自動的に差し替える、というものです。すばらしいアイディア! で、さっそくインストールしてみたのですが、ふぁぼったーの仕様が 変わったのか、ある時点からうまく動かなくなってしまいました。 仕方ないのでちょっとソースを読んでデバッグしようかと思ったのですが (ちょうど GreaseMonkey を勉強していたところでしたし)、 ふと気がつくと、なぜか全面的に書き直していました・・・・ で、ついでというか、せっかくなので、censored された単語がわかるように strike タグで囲むようにしてみることにしました。ちょうど先日調べた 文字列比較アルゴリズムを使ってみたかった、というのもあります。   ⇒ 文書比較アルゴリズムの解説 いわゆる diff コマンドに代表される文書比較(文字列比較)ですが、 これまで Seaoak は単純で力業なものだと思いこんでいました。 それが上記のサイトを見ると予想外にエレガントだったので、 びっくりしたものです。「人力検索はてな」でベストアンサーに なっていたのもうなづけます。 とりあえずインプリできたので、ここで公開してみます。   ⇒ uncensored_favotter-090904a.user.js   ※先頭の単語が censored されていると打消しし損なうバグを修正   ⇒ uncensored_favotter-090908a.user.js   ※ Firefox のバージョンによっては動かないのを修正(kx8 氏に感謝!)   ⇒ uncensored_favotter-090912a.user.js   ※ ふぁぼったーのドメインが変わったのに対応   ⇒ uncensored_favotter-20100318a.user.js   ※ Chrome/Opera にも対応   ⇒ uncensored_favotter-20100501a.user.js   最新バージョンはぐりもんスクリプト集積サイト userscripts.org に置いてあります↓   http://userscripts.org/scripts/show/66874 giginet 氏の visible_censored スクリプトとは同居できないので、 もしお試しいただける場合は一度アンインストールしてから インストールしていただければと思います。 よろしくお願いします♪

2009-09-03

ファイルの末尾がわからない

Sleipnir の SeaHorse スクリプト (SleipnirScript) で
ちょっと困った問題があって悩んでます。



SleipnirScript では、組み込みスクリプト用の機能を使って
ローカルファイルの読み書きができます。
ただ、用意されている API はほんとにシンプルで、

    OpenFile() ・・・ファイルオブジェクトを取得
    Write()    ・・・文字列を書き込む
    ReadLine() ・・・1行読み込む
    Close()    ・・・ファイルを閉じる

の4種類しかなかったりします。

詳しくは、Sleipnir をインストールするとインストール先の
documents フォルダに作られる Sleipnir-Script.txt に
書いてあります(詳しくも何もないのですが・・・)。



で、問題は、読み込み時にファイルの末尾に到達したかどうかを
どうやって判断すればよいかわからない、ということです。

たとえば、以下のコードでファイルを読み込もうとします。

var fileObj = sleipnir.OpenFile(fileName, 'r'); if (! fileObj) return; while (line = fileObj.ReadLine()) { result.push(line); } fileObj.Close();
一見するとうまく動きそうなのですが、読み込むファイルの中に 空行があるとそれ以降の行を読み込んでくれません。 なぜなら、空行があると ReadLine() は「空文字列」を返しますが、 JavaScript では空文字列は「false」と解釈されるので、 while 文から抜けてしまうからです。 そこで、上記のコードを
while (null != (line = fileObj.ReadLine())) {
のように変えてみると、あっさり Sleipnir が暴走します・・・ つまり、ファイル末尾に到達しても ReadLine() は「null」や 「未定義値」ではなく「空文字列」を返すみたいなのです。 というわけで、空行を読み込んだのかファイル末尾に到達したのか、 スクリプトから区別する方法がありません。 困りました・・・

2009-09-02

SeaHorse でイベントハンドラ

Sleipnir の SeaHorse スクリプトで遊んでます。
お気に入りのサイトを勝手に改造したりとか。

JavaScript の勉強にもなるし、作っているうちに
「これってもしかして Web アプリじゃない?」
とか勘違いしそうになるので、楽しいです♪



ところで、SeaHorse スクリプトは普通のページ内の
JavaScript とは別のコンテキストで動いているので、
そのままではページ内フォームとかのイベントハンドラを
設定できなかったりします。

それでちょっと調べてみたら、強力な解決策がありました!

 ⇒ SleipnirScriptからイベントを使う方法メモ - ここここあ

なんと、Sleipnir のデフォルト設定で JavaScript を OFF にしていても
イベントハンドラを有効にできちゃうというスグレモノです。

ポイントとしては、関数定義を toString() しているので
もともとのスコープが無効になっていることでしょうか。
ハンドラ関数からはスクリプト全体のスコープが見えません。

結局、サンプル中の hoge() には補助関数も含めて
ベタ書きする必要があります。

でも、「JavaScript 第5版」に載っていた IE 独自のクライアント永続性
(behavior) もちゃんと使えました(こんなの↓

var uniqueKey = 'hogehoge'; // 永続化用のキー elem.style.behavior = "url('#default#userData')"; function saveToStorage(key, value) { var now = (new Date()).getTime() var period = 365 * 24 * 60 * 60 * 1000; elem.setAttribute(key, value); elem.expires = (now + period).toUTCString(); elem.save(uniqueKey); } function loadFromStorage(key) { elem.load(uniqueKey); return elem.getAttribute(key); }
とくに違和感もなく普通に使えたので、すばらしいです♪ IE 独自のクライアント永続性を使うと cookie に悩まされることもないので、 安心してデータの保存ができます(どうせ Sleipnir なら IE でしょうから) もともと cookie でしか保存できないところを勝手に複数パターン 保存できるようにしたり、なかなか楽しいです♪

栗本薫『仮面舞踏会』

栗本薫の『仮面舞踏会 ~伊集院大介の帰還~』を再読。



かなり古いお話ですけど(なにしろパソコン通信の時代)、
現代の Twitter やネトゲに通じるところがあるように思えます。
ネトゲのチャットや Twitter は、言ってみれば文字だけの
コミュニケーションなわけで、その中でも人間性が感じられるのは
やっぱり面白いことだと思います。

これはぼく自身が何回も経験したことだけれども、たとえば掲示板に同じように 「友達になって下さい」というアップをのっけたとしても、三つのせて、 それがどれも女名前で同じような年でそんなに差のない文章でも、その中で 歴然とモテるものがある。全然誰もそれに反応しない気の毒なやつもある。 そうなるともう、画面に浮き出してくる無機質的な文章が、それ自体何かの 生命を持っていて、魅惑的なニオイをはなってる文章とそうでなくて むしろひとをシラケさせる文章とが存在してるんだ、としかいいようがない。
平安時代の貴族たちは、ぜんぜんあいての顔をみないで歌をやりとりするだけで 恋がどんどんもりあがったというけれども、パソコン通信をしているぼくたちは 現代の平安貴族かもしれない。
文章にはその人間のすべてが出る、ということをぼくは最近よく考える。 同じようなことをかいてるのにどういうわけか感じの悪い、 と読むものに感じさせる文章がある。またぼくがやだなと思う文章に むしずの走るような賛同のレスをつけるやつもいる。誰もがなんだか ひきつけられる文章をかくやつもいる。
実際のところ魅力的な文章を書くのはむずかしいけれども、 文字だけのコミュニケーションを通じて、 ぼくなりの人間性を感じてもらえたらうれしいなぁ、 と思う今日この頃でした。

ボタンはボタンらしく

今日も無意味に JavaScript をいじってしまいましたw


とある便利なサイトを勝手に改造する SeaHorse スクリプト (SleipnirScript)
を作っているのですが、その中でページ上に勝手にボタンを追加しています。

そのボタンなのですが、フォームの input/button 要素ではなくて
HTML の span 要素に onclick イベントを設定して、擬似的にボタンに
みせかけています(フォームのボタンだと大きすぎて収まらないため)。

なので、デフォルトのままだと、

 ・マウスカーソルが上に来ても何も反応しない
 ・マウスカーソルが上に来てもカーソルの形が「I」のまま

という感じで、言われないとボタンに見えなかったりします・・・


今日の改造は、

 ・マウスオーバーで色を変える
 ・マウスオーバー時のマウスカーソルを「指」に変える

というものです。

単に onmouseover イベントを捕まえて変化させ、
onmouseout イベントを捕まえて元に戻すだけ。

マウスカーソルの変更は、

_document.body.style.cursor = 'hand';
で「指」の形にして、
_document.body.style.cursor = '';
で元に戻す、という感じでカンタン。 やっぱり「ボタンはボタンらしく」という UI のキホンは大事ですよねー # ドキュメントを書かない場合は特に・・・

2009-09-01

ついったー用語

あいかわらず Twitter のフォロー先を探してさまよってます。
ようやく 48 名まで増えたので、ちょっとひと息かなー


で、ついったー用語がだんだんわかってきたのでメモ。

    TL:
        TimeLine。発言が流れていく様。

    Favorite:
        面白いと思った発言につけるマーク。メモ代わりに便利?

    RT:
        ReTweet の略。誰かの発言を引用して発言するときに使うもの。

    #hogehoge:
        特定の話題に関する発言につけるタグ。日本語は不可。

    buzztter:
        今話題になっている単語を教えてくれる。「ばずってる」とか言う。

    ふぁぼったー:
        みんなが Favorite している発言がわかる。

    なう:
        「いま~してるところ」の略(しかし「出産なう」にはおどろいたw)

    空目:
        空耳(そらみみ)の視覚バージョン。一般用語らしいけど知らなかった。

    ついたったー:
        Twitter をしてる人たち。

    リナカフェ:
        秋葉原にあるカフェ。元 Linux カフェ。ついたったーの聖地らしい?


あと、URL を書くときは URL 短縮サービス(bit.ly とか)
を使うのがお約束みたい。

p.s.  昨夜の「ガンダム折れてる」はびっくりしましたw

クロージャーでつまらないミス

JavaScript (GreaseMonkey) を書いていて、
つまらないミスをしてしまったので、メモ。


いくつか並んでいる HTML 要素にそれぞれイベントリスナーを設定する場合、
for ループで addEventListener() を呼ぶことがあると思います。
そのとき、イベントリスナーとして無名関数を使うと、ちょっと罠にはまる
可能性があります。

たとえば、こんなコードを書いちゃったり ↓

var list = ['a', 'b', 'c']; for (var i=0; i<list.length; i++) { button[i].addEventListener( 'click', function() { alert(list[i]); }, false ); }
このコードはたぶん期待した動きをしません。 ボタンを押しても "undefined" という値が表示されるハズです。 なぜかというと、無名関数の中で変数 i を参照しているからです。 変数 i は関数の外のスコープにあるのでクロージャーとなりますが、 変数 i はイベントリスナーを登録した時点でインクリメントされて しまうため、コールバックされたときには i=3 になっているのです。 正攻法でやるなら、イベントリスナーごとにスコープを作ってあげて 変数 i の値をコピーしておいてあげる必要があります。
var list = ['a', 'b', 'c']; for (var i=0; i<list.length; i++) { (function() { var id = i; button[i].addEventListener( 'click', function() { alert(list[id]); }, false ); })(); }
冷静に考えれば当たり前のことなんですけど、 実際に書いたコードが正しく動かなくて、 ちょっと悩んでしまいました。 クロージャー+無名関数の組み合わせは強力で便利なのですが、 けっこう落とし穴あるので要注意かも。

« 2009年8月 | トップページ | 2009年11月 »