Home > Latest topics

Latest topics 近況報告

たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。

萌えるふぉくす子さんだば子本制作プロジェクトの動向はもえじら組ブログで。

宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

Page 3/248: « 1 2 3 4 5 6 7 8 9 »

情報化タブのプログレスバーをいじってみたよ - Oct 08, 2009

Tab Progress BarのプログレスバーがFirefox 3.7のモックアップ風なのを見て「羨ましい!」と思ったのでInformational Tabのデフォルトスタイルをそのように変えてみた。一応、設定で今まで通り(ラベルの下に表示)にも戻せる。

で、やるならとことんやってみっか!と一念発起して、モックアップにあるような光るプログレスバーを再現しようと頑張ってみた。 伸びるバーの部分は背景画像で、ぽわーんと光った感じは-moz-box-shadowを使ってるので、Firefox 3.5じゃないと期待通りには見えない。

ブックマークを常にタブで開くようにするためだけのアドオンを公開したよ - Aug 19, 2009

その名もズバリ「Open Bookmarks in New Tab(ブックマークを新しいタブで開く)」。何のひねりもない。

ツリー型タブにこの機能を付けれという要望が何度も何度もいろんな人から寄せられていて、しかしどうも調べてみると、Tab Mix Plusの一機能としてはこういう機能があるものの、これだけを実現してくれるアドオンが実は存在してなかったらしい(userChrome.jsを使える人はそっちで解決してしまうから、アドオンでなければ使えないというレベルのユーザには行き渡っていない?)、ということで作った次第です。userChrome.jsでやる人が多いんだろうなあということからも分かるように、メインの実装はたったこんだけ。これ以上機能を追加するつもりはないです。全く。

工夫?というか、実際使ってみて感じたことをフィードバックした点としては、ブックマークを中クリックした時にも常にタブで開くようにしてる、というあたりでしょうか。

作り手としてバカ正直に考えると、「普通の左クリックと中クリックの挙動をそれぞれ反転させればいいんじゃね?(そうすれば新しいタブで開きたい時と現在のタブに読み込ませたい時に使い分けれて便利じゃね?)」ということでそうしてしまいそう(事実、最初はそうしてた)なんだけど、実際に使ってみると自分の場合はブックマークを中クリックすることが癖になってて、タブで開きたいのに現在のタブに読み込まれて「ムキー!!!」となってしまった。

それに、こういう要望を出す人というのは多分、ミドルクリックでタブで開けるということをそもそも知らない(ミドルクリックという操作がある事自体を知らない)か、2ボタンマウスを使ってるかで、ハナから操作を使い分ける気なんか無いんだろうなあ。とも考えられる。

つまり「操作によって挙動を変えるという自由」が、混乱の元であったり、そもそも誰もそんな自由を欲してないんじゃないか、と。なので、「左クリックでも中クリックでもとにかくブックマークは新しいタブで開く」という挙動を初期設定としておいた。設定を変更すれば、中クリックした時は現在のタブに読み込ませるという挙動にもできるけど、作者の推奨設定はあくまでこうですよってこと。

ツリー型タブの修正 - Aug 11, 2009

先週1週間は夏休み取って家に缶詰でずっともえじら組のマンガ描いてたんだけど、その間大量にバグ報告が来てたのをずっと見て見ぬふりしてたのを今週になってやっと修正した。

ブックマークフォルダの内容をタブで開けなくなるという問題はFirefox 3.0.xでのみ発生する問題で、原因はJavaScriptコードモジュールのPlacesUtilsにFirefox 3.5から追加された機能をそうとは知らずに使ってしまっていたせいだった。

あとブックマーク周りの変更が結構ボロボロだったのをだいぶ直した。特にスターアイコンのことは自分であんまり使わないからすっかり忘れてて、直すのに難儀した。Firefox自身がeditBookmarkOverlay.xulを動的に読み込んでいて、そのeditBookmarkOverlay.xulに対してツリー型タブがオーバーレイを適用しているために問題が……とか、とてもバッドノウハウくさい。結局、XULオーバーレイでどうこうするのは諦めてJavaScriptで動的にDOM要素を生成して挿入することにした。

var range = document.createRange();
range.selectNodeContents(container);
range.collapse(false);
range.insertNode(range.createContextualFragment(<![CDATA[
   <row align="center" id="treestyletab-parent-row">
      <label id="treestyletab-parent-label"
         control="treestyletab-parent-menulist"/>
      <menulist id="treestyletab-parent-menulist"
         flex="1"
         oncommand="TreeStyleTabBookmarksServiceEditable.onParentChange();">
         <menupopup id="treestyletab-parent-popup">
            <menuseparator id="treestyletab-parent-blank-item-separator"/>
            <menuitem id="treestyletab-parent-blank-item"
               value=""/>
         </menupopup>
      </menulist>
   </row>
]]>.toString().replace(/^\s*|\s*$/g, '').replace(/>\s+</g, '><')));
range.detach();

こんな感じにしておけば、XULの「タグを書くだけでUIを作れる」という利点をそれほど殺さなくても済む……と思う。E4XのXMLオブジェクトを生成した物を既存のDOMツリーに直接組み込むことができれば話は早いんだけど、そういうことは無理っぽいので、createContextualFragment()にしてる。ここではE4XのCDATAマーク区間をヒアドキュメント代わりに使ってるんだけど、文字列置換でタグの間の空白文字を消してるのと、toString()をわざわざ書いていることに注意が必要。前者を忘れると要素ノードの間にいちいちテキストノードが生成されてややこしいことになるし、後者をを忘れるとStringクラスの物ではなくXMLオブジェクト自身の方のreplace()メソッドが呼ばれてしまって文字列置換にならないので。

修正ついでに、ブックマーク項目の「親のタブ」を設定する機能について、もうちょっと自由に使えるように手を入れてみた。ツリー構造を書き換えるのと同時に、ツリーとして表示される時の順番に合わせてブックマークを自動的に並べ替えるようにした。

ツリー型タブでブックマークにツリー構造を保存できるようにしてみた - Jul 31, 2009

ツリー型タブ 0.8.2009073101/02で、「このツリーをブックマーク」や「すべてタブをブックマーク」した時に、ツリーの構造を含めてブックマークを保存するようにしてみた。だいぶ前から要望を受けてて、「確かにそうするべきだよなあ」とは思ってたんだけど、どうやって実現すればいいかで悩んでた。でもFirefox 2のサポートを切ったことによって、API経由でPlacesデータベースに色んな情報を簡単に保存できるようになったので、思い切って実装してみた。

他のアドオンからもこの機能を使えるように、APIを用意してある。複数のタブからブックマークを作成する場合、以下のように、PlacesUIUtils.showMinimalAddMultiBookmarkUI()でブックマークの追加を行う前後にツリー型タブのAPIを呼んでやると、タブのツリー構造がブックマークに保存される。

var tabs = Array.slice(gBrowser.mTabContainer.childNodes);

var isTSTBookmarksTreeStructureAvailable = (
        'TreeStyleTabBookmarksService' in window &&
        'beginAddBookmarksFromTabs' in TreeStyleTabBookmarksService &&
        'endAddBookmarksFromTabs' in TreeStyleTabBookmarksService
    );
if (isTSTBookmarksTreeStructureAvailable)
    TreeStyleTabBookmarksService.beginAddBookmarksFromTabs(tabs);
try {
    PlacesUIUtils.showMinimalAddMultiBookmarkUI(tabs.map(function(aTab) { return aTab.linkedBrowser.currentURI; }));
}
catch(e) {
}
if (isTSTBookmarksTreeStructureAvailable)
    TreeStyleTabBookmarksService.endAddBookmarksFromTabs();

このAPIはマルチプルタブハンドラでもさっそく使ってる。

やってることはどういう事かというと……

  1. まずTreeStyleTabBookmarksService.beginAddBookmarksFromTabs()の方では、ブックマークされる予定のタブのツリー構造をシリアライズして内部に保持した上で、ブックマークの監視を開始する。
  2. 次に、PlacesUIUtils.showMinimalAddMultiBookmarkUI()で複数のブックマーク項目が新たに作成される。この時、TreeStyleTabBookmarksServiceはブックマークの追加を監視していて、新しく作られたブックマークのIDを内部に保持する。
  3. 最後に、TreeStyleTabBookmarksService.endAddBookmarksFromTabs()の中で、追加されたブックマークと元になったタブとを対応させ、ツリー構造の情報(親のタブにあたるブックマーク項目はどれか、という情報)を、ブックマークのアノテーションとして保存する。この時、タブの数と作られたブックマークの数とが一致しない場合(ブックマークの追加がキャンセルされたとか、未知の機能によってタブと関係ないブックマークが同時に作成されたとか)は想定外のエラーということで、何もせず終了する。

とりあえず一番簡単なやり方で実装してみたので、保存した後のブックマークの順番や親子関係をいじくり回すとちょっと変なことになる。一応、そんなに大きな問題は起こらないで見た目上は何となく自然な形に収まるように、と工夫はしてみたんだけど……どうだろう。

保存された「どのタブが親か?」という情報は、ブックマークのプロパティから編集できるようにしてある。親を付け替えられるようにしてみたけど、横着してるのでちょっと制限が厳しい。そのうち、親を付け替えたらそれに応じてブックマーク項目自体の親フォルダ内での位置も自動的に入れ替えるようにでもしてみようかなー。

巻き戻し/早送りボタンが26日以降クラッシュする件 - Jul 27, 2009

巻き戻し/早送りボタンでSITEINFOを使うようにしてるとクラッシュする件。wedataから取得するデータの先頭の方をスキップするようにしたら落ちなくなったので、どうも正規表現が長すぎ(内部的に、すべてのSITEINFOのURLマッチング用の部分を繋げておいて「マッチするルールがあるか無いか」だけを調べるようにしてるんだけど、その正規表現が長すぎ?)なのが原因っぽい。wedataの更新履歴を見ると、この数日の間にもいくつかルールが追加されてるみたいだし。

で、とりあえず250件ごとに区切って正規表現を作るようにしてみたところ、手元の環境では落ちなくなったみたいなので、修正版として速攻で公開してみた。

しかし念のため全部のURLマッチング用の正規表現を繋げた正規表現を使ってテストしてみたところ、これだけではクラッシュしなかった。処理が走るタイミングにも依るんだろうか? これじゃいつまた問題が再発するか分からんよ……

ともあれ、今までの「でかい正規表現にマッチするかどうか判定」→「全部のSITEINFOをループで調べる」というのに比べると、250個単位で「正規表現にマッチするかどうか判定」→「その250個の範囲のSITEINFOをループで調べる」という風に変わったので、場合によっては多少高速になったんじゃないかなーと期待している。

参考までに、テストに使った巨大な正規表現は以下の通り。

続きを表示する ...

マルチプルタブハンドラでタブのURIをコピーする時のフォーマットをカスタマイズできるようにした - Jul 20, 2009

マルチプルタブハンドラではタブを選択した後に「すべてのURIをコピー」で選択したタブのURIをコピーすることができて、その時の形式を「URIだけ」「タイトルとURI」「HTMLのリンク」の3種類から選べるようになってたんだけど、今回のバージョンアップで、ここにさらにユーザが好みの形式を追加できるようにしてみた。ついでにマイナーバージョンも1つ上げてみた。

プレースホルダにはCopy URL +と同じものを利用できる(ツールチップの説明には書いてないけど%LOCAL_TIME%%UTC_TIME%も使える)。自分は以下のものを追加して使ってる。

HTML Link List
<li><a href="%URL_HTMLIFIED%">%TITLE_HTMLIFIED%</a></li>
Markdown
[%TITLE_HTMLIFIED%](%URL_HTMLIFIED% "%TITLE_HTMLIFIED%")
Markdown (list)
 * [%TITLE_HTMLIFIED%](%URL_HTMLIFIED% "%TITLE_HTMLIFIED%")
RD
((<%TITLE_HTMLIFIED%|URL:%URL_HTMLIFIED%>))
RD (list)
 * ((<%TITLE_HTMLIFIED%|URL:%URL_HTMLIFIED%>))
Retrospectiva
[[%TITLE_HTMLIFIED%|%URL_HTMLIFIED%]]
Retrospectiva (list)
* [[%TITLE_HTMLIFIED%|%URL_HTMLIFIED%]]

nsIZipWriterを使ってFirefoxでZIPアーカイブを作る - Jul 16, 2009

nsIZipWriterを使えばアドオンでZIPアーカイブを作れるということを割と最近になってやっと知ったので、アドオンのXPIへのパッケージングまで全部アドオンでできるやん!と思ったんだけど、使い方がよく分からんかったので、実験と練習もかねてコンテキストメニュー拡張の短縮構文で使える汎用的な処理を書いてみた。

要点だけ抜き出すとこんな感じ。

// aSources = nsIFileの配列
// aZipFile = 作るZIPアーカイブのnsIFile
// aCompressionLevel = 圧縮率(0で無圧縮、9で最大圧縮、デフォルトは6)
zipFilesAs : function(aSources, aZipFile, aCompressionLevel) 
{
    // Firefox 3以降じゃないと動かないよ!
    if (!('nsIZipWriter' in Components.interfaces))
        throw Components.results.NS_ERROR_NOT_IMPLEMENTED;

    if (!aSources || !aSources.length || !aZipFile) return;

    if (aZipFile.exists() && !this.isZipFile(aZipFile))
        aZipFile.remove(true);

    const PR_RDWR        = 0x04;
    const PR_CREATE_FILE = 0x08;
    const PR_APPEND      = 0x10;
    const PR_TRUNCATE    = 0x20;

    var writer = Components
                    .classes['@mozilla.org/zipwriter;1']
                    .createInstance(Components.interfaces.nsIZipWriter);

    if (aCompressionLevel === void(0))
        aCompressionLevel = writer.COMPRESSION_DEFAULT;

    // 新規ZIPアーカイブと既存のZIPアーカイブではフラグが違う
    var flags = aZipFile.exists() ?
                    PR_RDWR | PR_APPEND :
                    PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE ;
    writer.open(aZipFile, flags);

    aSources.forEach(function(aFile) {
        var entry = this+aFile.leafName;
        // フォルダに対応するエントリの有無を調べる時は、
        // エントリ名の末尾に「/」が必要
        var entryForCheck = aFile.isDirectory() ? entry+'/' : entry ;

        // すでにあるエントリで、フォルダではない物は削除。
        // (フォルダを削除しないのは、内容をマージするため)
        if (!aFile.isDirectory() && writer.hasEntry(entryForCheck))
            writer.removeEntry(entry, false);

        // 新しいエントリを追加
        if (!writer.hasEntry(entryForCheck))
            writer.addEntryFile(entry, aCompressionLevel, aFile, false);

        if (aFile.isDirectory()) {
            var files = aFile.directoryEntries;
            while (files.hasMoreElements())
            {
                arguments.callee.call(
                    entry+'/',
                    files.getNext().QueryInterface(Components.interfaces.nsILocalFile)
                );
            }
        }
    }, '');

    writer.close();
},

// ファイルの内容を実際にZIPアーカイブとして読んでみて、ZIPアーカイブかどうか調べる
isZipFile : function(aFile)
{
    var isZip = false;

    if (!aFile || !aFile.exists()) return isZip;

    var reader = Components
                    .classes['@mozilla.org/libjar/zip-reader;1']
                    .createInstance(Components.interfaces.nsIZipReader);
    try {
        reader.open(aFile);
        try {
            var entries = reader.findEntries('*');
            while (entries.hasMore())
            {
                entries.getNext();
                isZip = true;
                break;
            }
            if (!isZip) {
                entries = reader.findEntries('*/');
                while (entries.hasMore())
                {
                    entries.getNext();
                    isZip = true;
                    break;
                }
            }
        }
        catch(e) {
        }
        reader.close();
    }
    catch(e) {
    }

    return isZip;
},

Mozilla Party JP 10.0 - Jun 01, 2009

Mozilla Party JP 10.0のライトニングトークでの発表資料「UxUを使った自動テストで安心アドオン開発」を公開しました。何度か練習してなんとか5分以内に収まるように直前まで削ってましたが、結局早口でまくし立てるばかりの通訳泣かせな発表になってしまいました。

  • 台湾のコミュニティの話が興味深かった。頻繁に集まってるとか、Mozillaに限らずクリエイティブコモンズとかそういう方面からの関心でも人を集めているとか。あと兵役で抜けなきゃいけない人が多いのがマジ辛いと言ってたのも覚えている。
  • gyuqueさんの発表が大変面白かった。
  • 瀧田さんと吉岡さんの対談で「電子レンジがネットに繋がっても嬉しくない」という風な話が出ていたけれども、今日野菜炒めを作ってて思ったけどレシピの掲示場所としては実に適しているという気がした。扉を開け閉めする都合上、電子レンジの前は必ず空いてるから、ディスプレイが見えなくなるということは絶対にないし。
  • 担当通訳の人が滝川クリステル似の美人で、話してる時の相槌が「あーはぁ?(英語な人がよくやるあれ)」で、しかし名乗った苗字は日本人だった。
  • hknさんのドラ娘が眼福だった。

宴会で、おそらくAir Mozillaあたりで使うであろうメッセージビデオの撮影に呼び出された。当たり障りのない無難なことを喋った(自粛してそうしたわけではなくそれくらいしか言うことがなかった)ので採用されない可能性は高いと思う。

  • 慶応の一色教授(W3Cの中の人)と話した時に、「どんなアドオン作ってるの?」という話からXHTMLルビサポートのことを話して、CSSの縦書きとかルビとかの話になった。
    • 曰く、あの辺の仕様は印刷業界のプロの人達が本気で議論して作ってる感じで、InDesignとかそういう特定のツールに依存しないで印刷品質の物を作れるようにということを真面目に考えてるそうだ。
    • 「でも実際できるようになっても使う人どれくらいいるんだろう?」と言われたので、Geckoを縦書きに対応させようとしてるryoqun氏とチャットで少し話した時にも言った「同人小説の界隈だと需要あると思いますよ、竜破斬でドラグスレイブとか」(例が古い)という話をしたらウケたようだった。

その後残りのメンバーの一部とカラオケに行き、終電の時間で仕切り直して徹夜カラオケして、帰ってきて寝て起きたら19時だった。親に電話した(荷物が届いたことを連絡しようと思った)ら「声がおかしいぞ」と言われた。

高橋メソッドドリブン開発 - May 28, 2009

Mozilla Partyの発表用資料を準備してる最中、自分で作っておきながら画像の埋め込みの仕様がクソ過ぎることにブチギレて、高橋メソッド in XULを久しぶりに改良してた。

  • 画像を全部確実にプレロードするようにした。
  • 画像の埋め込み指定に幅と高さの指定が無い時は、プレロードした画像それ自体の大きさで表示するようにした。
    • 幅か高さのどちらかが省略されていた場合、指定されている方の大きさに合わせてアスペクト比を保って拡大・縮小表示するようにした。
    • 幅や高さにパーセント値を指定した場合は、ウィンドウサイズに対する割合として計算するようにした。
  • ウィンドウの大きさが変わった時にちゃんと再描画するようにした。

公開ページはまだ更新してない。改良されたバージョンはリポジトリに置いてある

ツリー型タブとマルチプルタブハンドラのAPIドキュメントの追加 - May 16, 2009

not enough memory - snj: 最近,Firefoxはもっと拡張間で連携プレーした方が良いんじゃないかって思ってきた....

リンク先に書かれてる話からは少しズレる。どちらかというとこの前書いた互換性の話の方だ。

アドオン同士で連携するには、機能が使いやすくまとまってるということが当然必要だけど、それだけでなく、外部から安心して使えるということも非常に重要だと思う。公開されていて、今後のアップデートでも後方互換性が保証されていないと、安心して使えない。「ソースを掘り返してこういう機能を見つけたから使ってみてるけど、これって知らんうちに削除されてしまったりしないか?」という不安があってはいけない。機能が「今のバージョンにあるかないか」ではなく、「今後もあり続けるのかどうか」が重要だと思う。

ツリー型タブは以前からいくつかAPIを公開してはいたけど、基盤になる処理をもっと公開APIとして表に出すことにした。公開した物は原則として後方互換性を維持していく方針でいる。

マルチプルタブハンドラの方も地味にAPIを整備している。

もう僕は疲れたんで、この辺使ってよろしくやってくれってことで……

Page 3/248: « 1 2 3 4 5 6 7 8 9 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき