« 2007年7月 | メイン | 2007年9月 »

2007年8月30日

意欲を維持するヒント集
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

こんばんわ、sashaです。今日は精神論的な話です。

みなさんは「やる気」とか、「意欲」とか、どうやって維持していますか?特に最近やる気がないとか言うわけではぜんぜんないのですけど、日々の雑務に追われていると、モーチベーションが下がったときにクリエイティブに対処出来なくなりがちだよね、といことは自分にも他人にもごくたまにあるように思います。

最近、A List Apartで紹介された記事を読んで、こういうこと、自分でもいつも覚えておきたいし、自分の周りにいる多くの人にとっても役に立てばいいなー、と思ったので、ちょっと自分なりの言葉に置き換えながら翻訳してみました。

すべて知っているかのような偉そうな口調をしていますが、私自身に対する戒めと教えとして書いてますので、お許しください。また、原文では「be motivated to create (作り出すために意欲的であること)」といった書き方をしていますが、ここではあえて、読者の方に多いであろう開発者の方々を意識しつつ、「モノづくり」という言い方をしています。ただ、意欲的であることは万人にとっての課題だと思いますし、業種、職種に関わらず全ての人に応用できるヒントだと思っています。

原文: Staying Motivated by Kevin Cornell from A List Apart Magazine
Translated with the permission of A List Apart Magazine and the author.


どんなお仕事をされているかに関わらず、仕事をする上で意欲的で生産的であることって、とっても大事。でもだれしも、しばしモノを作り出すことに限界を感じることがあるのではないでしょうか。で、集中力を維持したり、プロジェクトを楽しんだりすることが、難しくなってしまうわけです。では、どうやったら、意欲を維持することができるでしょうか。

「意欲を維持すること」、という課題は、結構長期的に考えないといけない問題です。初めは茨の道でも、あなたの意志と継続性によって、そのうち常に意欲を簡単に操れるようになるはず。大事なのは、適切なタイミングで適切な選択が出来るよう、学習していくことなのです。

もちろん、人には個人差があります。人にはそれぞれ、モノづくりに没頭するための独自の処方箋があるはず。ここでは、その処方箋を見るけるためのアイデアを紹介しますが、結局は、適切な選択をしていかなければならないのは、あなた自身でしかありません。長期的に意欲を維持できるようになるには、あなたの行動に対して注意を払うことや、カンに素直になることも重要です。またある時は、自分自身を励ましてみたり、騙してみたり、また自分自身と交渉してみたりすることが必要になってくるでしょう。

【フェーズ 1 : 意欲を維持する習性を身に着ける】

先述したように、初めは茨の道です。しかも、結果はすぐには現れません。でも、何事も自分で始めないと始まらないもんです。それではまず、「意欲を維持する」習性を身に着けるために、まず出来ること、今始められる事をご紹介しましょう。

目標を設定しよう

達成感があれば、意欲を維持するのもちょっと楽になれますよね。達成感は、目標無しでは得られません。ちょっと先の未来の自分が達成できる事をまず設定します。

現実的なタスクを積み重ねよう

興味や意欲は、達成感と直接関係しています。現実的な目標を設定することで、自分自身に、「失敗」という刹那さよりも「成功」というご褒美をたくさんあげましょう。まずは、小さなタスクの積み重ねから。小さな「成功」というご褒美をたくさん自分にあげることが出来るようになったら、ちょっとずつゴールを大きくしてあげましょう。

仕事場を整えよう

オフィスの一角であろうが自宅であろうが、モノづくりだけのためのスペースを作りましょう。で、ここがそのスペースだと決めたら、モノづくりはそこだけで。そこで成功を積み重ねることで、あなたは無意識的にその場所で次の成功を生み出すことを学んでいくのです。やがては、その場所に立ち入った瞬間、モノづくりのイメージがわいてくるようになるはずです。

「降参」するのではなく、「退却」しよう

問題があったらあきらめてはいけません。ちょっとの間隅に寄せておいて、又戻ってきてがんばりましょう。問題が解決できたら、それが自信となり、知識となり、成果となるのですよ。

自分のサイクルを見つけよう

決まった時間に眠くなったりおなかが空いたりするのと同じように、モノづくりにも生理的に最適な時間帯と、そうでない時間帯があるはずです。あなたが最も生産的になれる時間帯を見つけて活用しましょう。そして生産的になれない時間帯は、事務的なあれこれやルーチンワークを片付けたりするのに使いましょう。

使いやすいツールを用意しよう

モノづくりってそれだけで大変な作業です。使えないツールを使うことで余計に大変にするなんて、とんでもない。作りたいものを作れる環境を整備するために、自分に合ったツール探しには時間や予算を(できるだけ)惜しみたくないですよね。

進捗を把握しよう

どれだけ作業が進んだのか、をみる事をは最強のモーチベーションになります。2ヶ月前の自分がどこにいて、今の自分がどこにいるのかを、しばしば見てみることが大切です。振り返って見てみたら、どれだけこの2ヶ月の間に成し遂げ、どれほどのモノを作り出したのかにびっくりするでしょう。いやもしかしたら、ぜんぜん成し遂げていないなぁ、と思うかもしれません。そのときこそ、意欲を高めるチャンス。いずれの結果にせよ、進捗を把握する意義は大きいはず。


【フェーズ 2 : スランプの時も意欲を維持する】

フェーズ 1でご紹介したような事を実行していたら、いつかはきっと、いつでも意欲を維持できるようになるはず。それでも、たまにはスランプはやってくるのです。そんな時こそ、新しい事を試してみましょう。この際、意欲を取り戻すためにあえて障害を設定してみたり、ちょっと引き下がってみたりするなど、違う角度からの対処方法も必要です。

ちょっと違う角度からの対処方法を、少しご紹介します。

目標なんて作るな

モノづくりがまだアイデアレベルのときや、実験的なことをやってみようと思い立ったとき、目標を設定してしまうことはアイデアや実験の可能性をぶち壊して可能性があります。たまには物事を成り行きに任せましょう。モノづくりが調子に乗ってきたら、タイムラインやタスクの設定などという行動を、自然ととっているはず。

非現実的なゴールを設定しよう

多分、自分の能力の限界を超えるほどのものを自分に課すことが功を奏するもあるんです。もちろん、目標を達成できないとか、目標を達成できても自分が燃え尽きてしまうなんていうリスクも背負わなければなりませんけど。

仕事場から抜け出そう

いつもの仕事場は、モノづくりのための意欲を生成する条件となるべきですが、たまには、違うところで仕事をすることも役に立つでしょう。いつもと違う刺激が、あなたのアイデアとか生産性とかに、いい影響を与えてくれる可能性があるからです。

仲間に学ぼう

他の人が何をやっているかを見てみましょう。何かインスピレーションを与えてくれるかもしれないし、そんなにすごい事を発見できなかったとしても、自分に対する期待が大きすぎたんだなー、などと現実的な発見もあるはずです。

仲間を無視しよう

仲間に学ぶ事にはそれなりの効果もありますが、一方で、人の功績にばかり着目してしまいがちになり、自分自身の目標にブレが出てきたりします。もっと悪いのは、あなた自身の仕事が他の人の仕事からかけ離れて過ぎているのではないかと心配になってしまうこと。あなたの仕事が人の仕事とは違うのは当たり前で、だからスゴイのに。

外的刺激を見つけよう

モノづくりのヒントは、人々や自然の中にあふれているのです。自分を取り巻くものにもっと近づいてみてみましょう。、アイデアが沸き起こったり、問題解決の糸口が見つかったりするかもしれません。「モノづくりモード」にあなたを戻してくれる刺激が、どこかにきっとあるはず。

内的刺激を見つけよう

そこら中にあふれる外的刺激を、すべて取り除くことも、また一つの手。例えば、ジョギングなど単純なスポーツに没頭したりしてはどうでしょう。頭を空にして、頭脳がなにもすることがなくなったとき、頭脳に素敵なアイデアのためのスペースが生まれたりするのです。

スケッチブックやノートを持ち歩こう

いいアイデアも悪いアイデアも、記録しておく必要があります。人の記憶なんて当てにならないのですから。長期的な記録としてアイデアをメモっておくことで、頭脳に空きスペースを与えてあげたら、その分抱えこんだ問題解決のために使うことができるのです。そして、次にスランプに陥ったりしてアイデアが浮かばないときだって、ノートがライブラリ代わりになってあなたのお仕事を手伝ってくれることになるでしょう。

そのまま突き進もう

モノづくりモードに入っていないあなたにとってはとってもつらいことですけど、とりあえず突き進むことが一番なときだってあるのです。一時はもう無理!と思っていたのに、意欲がいつしか惰性で戻ってきたのを感じる時があるでしょう。もし、それでも意欲が戻ってこなくて、人生最悪の仕事をしている気がしていても、後から振り返ればいいモノ作ってることだってあるんです。後にならなければわからないんですもの。とりあえず全力で突き進みましょう。

障壁を与えよう

タイムリミットをセットしたり、いつものツールを使わないと決めたり、とにかく自分を窮地に陥れてみましょう。時には、そんな障壁が成功への鍵だったりするのです。

障壁を取り除こう

しばしば私たちは、不必要な障壁を与えてしまって、重要な問題を解決する能力を低下させてしまうことがあります。問題解決するための障壁が大きすぎると感じ始めたら、その障壁の必要性そのものを検証してみることも必要です。

がんばっていきましょう♪



いかがでしょうか、長期的に意欲を維持するためにできること、見えてきましたか?あとはあなた自身の感覚と能力を信じて、試行錯誤を重ねてあなた自身の処方箋を見つけてみてください!

------

9月5日 15:02
原文のコピーライト表記についてご指摘を頂きましたので修正させていただきました。
ご指摘を下さった方、ありがとうございました。

2007年8月28日

JavaScriptライブラリといえば jQuery(入門編)
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

こんにちわ。山下です。

最近、私の周りではJavaScriptライブラリといえば、jQuery の名前がまず最初に挙がってくるようになってきました。今回は、jQueryって何が便利なの?っていう人向けに、ポイントを掻い摘んで説明します。

1.名前空間を汚さない

他のJavaScriptライブラリとかだとStringとかArrayを直接拡張してたりしますが、jQueryはグローバルな名前空間を汚しません。eachとかmapのような便利な関数もすべてjQueryオブジェクトの属性として定義されています。

jQuery.each, jQuery.extend, jQuery.grep, jQuery.map, jQuery.merge, jQuery.trim, etc.

また、標準では $ にショートカットが割り当てられるのですが、jQuery.noConflict()と書くことで prototype.js などと混ぜて使えます。

<script src="prototype.js"></script>
<script src="jquery.js"></script>
<script type="text/javascript">
    jQuery.noConflict();
</script>


2.要素の選択がらくらく

これが私がjQueryを一番気に入っている理由なのですが、CSS 3と XPath をミックスしたような構文で要素を選択することができます。すべてのjQueryでの操作は、DOMからひとつまたは複数のノードを選択することから始まります。以下に要素選択の例を挙げますが、かなり直感的に理解できるのではないでしょうか。

jQuery('div.panel')
    class="panel"なすべてのdiv要素
jQuery('p#intro')
    id="intro"なすべての段落
jQuery('div#content a:visible')
    id="content"のdivの中のすべてのvisibleなリンク
jQuery('input[@name=email]')
    name="email"なすべてのinput要素
jQuery('table.orders tr:odd')
    class="orders"な奇数行
jQuery('a[@href^="http://"]')
    すべての外部リンク(http://で始まる) 
jQuery('p[a]')
  1つ以上のリンクを含む段落


3.メソッド・チェーン

2.で説明した要素の選択は、すべてjQueryオブジェクトが返ってきます。そして、そのオブジェクトのメソッドを実行した結果もjQueryオブジェクトが返ってきます。これはどういうことかというと、複数のメソッドを呼び出す必要がある時に何度もセレクタを書くことなく、シンプルに書けるということです。

例えば、id="message"の要素の背景色を赤に変更して、内容を'Hello!'に書き換えて表示するなんてことが下の1行で書けます。

jQuery('#message').css('background', 'red').html('Hello!').show();


4.イベント処理

click関数に引数を渡した場合はクリックされた際にその処理を行い、指定しなかった場合はクリックをシミュレートします。

jQuery('p').click(function() {
   jQuery(this).css('background-color', 'red');
});
    pタグをクリックしたら、背景を赤に変更
jQuery('p:first').click()
    最初の段落をクリックした動作を行う


次の例では、aタグにmouseoverとmouseoutのイベントを割り当てます。マウスカーソルが重なると背景色をオレンジに変更し、離れると白に変更します。hover()の最初の引数がmouseoverで2番目がmouseoutになります。

jQuery('a').hover(function() {
    jQuery(this).css('background-color', 'orange');
}, function() {
    jQuery(this).css('background-color', 'white');
});


one()関数は、1度だけ実行するイベントを割り当てます。最初に段落をクリックするとalertメッセージが表示されますが、もう一度クリックしても何も起こりません。

jQuery('p').one('click', function() { alert(jQuery(this).html()); });


5.Ajax

AjaxでHTMLの断片をサーバからGETして、divのinnerHTMLに流し込むのは、たったの1行で書けます。これだけです。

jQuery('div#intro').load('/some/fragment.html');

JSONデータもこんな感じで取得して自動的に変数に格納されるので、とても簡単です。

jQuery.getJSON('/some.json', function(json) {
    alert('JSON rocks: ' + json.foo + ' ' + json.bar);
});


6.プラグイン

jQuery自体は21KBしかないのですが、プラグインを使うことでjQueryのインスタンスオブジェクトに機能を追加することができます。jQuery Pluginsのページに、世界のユーザが作成した100以上の便利なプラグインが用意されているので、これを利用することができます。

私が以前書いたエントリ、
 簡単Ajaxライブラリ「jQuery」と便利なプラグインたち
も参考にして頂ければと思います。



以上、jQuery入門編と題して特徴を説明しましたが、もし興味を持ってくれる人がいれば次回はもう少し掘り下げていきたいと思います。


2007年8月27日

角丸画像を簡単に作る
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

Keitaです。最近、モテるためにがんばっていますが、周りの女性は誰一人として振り向いてくれません。
さて、そんなわけで、世間では、いろいろな角を丸めると、モテるといううわさを聞いてとりあえず角を丸めることにしてみました。

でも、CSSの角を丸める方法は、わりと論争の的でこれがいいよ!と人に勧める知識もないので、とりあえず、画像を丸めてみることにしました。

今回も、Webアプリケーションに関する面倒な問題を簡単に解決するツール、PHPを利用します。

画像を加工するのに何使うは、結構、選択肢があるのですが、そのものずばりの関数があるimagick 2.0を使いたいと思います。

コードはこんな感じです。
<?php
     $image =& new Imagick();
     $image->readImage('test2.jpg');  // ファイルを読み込む
     $image->roundCorners(20, 20);    // 角の半径を指定する
     $image->setImageFormat('png');   // 画像形式をpngに
     $image->writeImage('test2r.png'); //ファイルに保存

これで、完了です。
なんて簡単!
それでは、よい角丸ライフを!!


っと、まだリリースもしてない拡張をトピックに出すだけだと気が引けるので、MagickWand用のコードも載せておきたいと思います。

先のimagick 2.0.0を参考に、さくっとつくったもので、わりと検証してなかったり変数名なんだよとかいう感じですが、気にしないでください
//MagickWand 1.0.4+ 6.3.3.1にて動作確認
function MagickRoundcorners($hwnd, $xRounding, $yRounding,$strokeWidth  = 10, $displace = 5, $correction = -6)
{
    $imageWidth = MagickGetImageWidth($hwnd);
    $imageHeight = MagickGetImageHeight($hwnd);

    if ($imageWidth === false || $imageHeight === false){
        return false;
    }

    $status = MagickSetImageType($hwnd, MW_TrueColorMatteType);

    
    $color = NewPixelWand();
    $draw = NewDrawingWand();
    $maskImage = NewMagickWand();

    $status = PixelSetColor($color, "transparent");

    if ($status === false) {
        MyMagickDestoryWand($maskImage, $color, $draw);
        return false;
    }

    $status = MagickNewImage( $maskImage, $imageWidth, $imageHeight, $color );
    
    if ($status === false) {
        MyMagickDestoryWand($maskImage, $color, $draw);
        return false;
    }

    MagickSetImageBackgroundColor($maskImage, $color);
    $status = PixelSetColor($color, "white");
    
    if ($status === false) {
        MyMagickDestoryWand($maskImage, $color, $draw);
        return false;
    }

    DrawSetFillColor($draw, $color);
    $status = PixelSetColor($color, "black");
            
    if ($status === false) {
        MyMagickDestoryWand($maskImage, $color, $draw);
        return false;
    }
    
    DrawSetStrokeColor($draw, $color);
    DrawSetStrokeWidth($draw, $strokeWidth);

    DrawRoundRectangle($draw, $displace, $displace, $imageWidth + $correction, $imageHeight + $correction, $xRounding, $yRounding );
    $status = MagickDrawImage($maskImage, $draw);

    if ($status === false) {
        MyMagickDestoryWand($maskImage, $color, $draw);
        return false;
    }


    $status = MagickCompositeImage($hwnd, $maskImage, MW_DstInCompositeOp, 0, 0);
    if ($status === false) {
        MyMagickDestoryWand($maskImage, $color, $draw);
        return false;
    }

    $draw = NewDrawingWand();
    $maskImage = NewMagickWand();
    $color = NewPixelWand();

    $status = PixelSetColor($color, "transparent");

    if ($status === false) {
        MyMagickDestoryWand($maskImage, $color, $draw);
        return false;
    }

    MagickNewImage($maskImage, $imageWidth, $imageHeight, $color );


    DrawSetFillColor($draw, $color);
    DrawSetStrokeColor($draw, $color);
    DrawSetStrokeWidth($draw, 2);


    DrawRoundRectangle($draw, 0, 0, $imageWidth, $imageHeight, $xRounding, $yRounding);
    MagickSetImageBackgroundColor($maskImage,$color);
    $status = MagickDrawImage($maskImage,$draw);

    if ($status === false) {
        MyMagickDestoryWand($maskImage, $color, $draw);
        return false;
    }

    
    $status = MagickCompositeImage($hwnd, $maskImage, MW_OverCompositeOp, 0, 0);
    
    if ($status === false) {
        MyMagickDestoryWand($maskImage, $color, $draw);
        return false;
    }

    MyMagickDestoryWand($maskImage, $color, $draw);
    
    return true;
}

function MyMagickDestoryWand($mwand, $pwand, $dwand)
{
    DestroyMagickWand($mwand);
    DestroyPixelWand($pwand);
    DestroyDrawingWand($dwand);
}
使い方
$image =  NewMagickWand();
MagickReadImage($image, 'file.jpg');
MagickRoundcorners($image, 20, 20);
MagickSetFormat($image, 'png');
MagickWriteImage($image, 'file.png');
最後に、コードなんて書きたくないよ!というものぐさなあなたのために、角を丸くしてモテるページを用意してみました。
といってもお昼休みにちゃちゃっとつくったものなので、なんか、致命的なバグがあるかもしれませんので、あんまりいじめないでください。(今、一部うごかないらしいです。)

それでは、よいモテライフを!

PS.ほれたでしょうか?

2007年8月24日

5分でできるウェブサーバのセキュリティ向上施策
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

こんにちは、naoya です。

先日、ウノウが公開しているサービスの中にいくつかの脆弱性が見つかったため、社内で「脆弱性発見大会」を開催しました。この大会は、二人一チームに分かれてウノウが公開している各サービスの脆弱性を見つけることを目的とした大会です。結果は、いくつか各サービスに脆弱性が見つかり、すぐに修正することができました。

僕のチームは、ウノウのホームページやラボブログなど細かいサービスを担当しました。その中で、いくつかのウェブサーバにセキュリティ上あまい設定がありました。

今日は、ウェブサーバのセキュリティ向上のための設定方法についてエントリします。なお、ウェブサーバはApache 2.2系を前提としています。

サーバ情報の表示しない

ウェブサーバ(Apache)で、404などのエラーページを表示したとき、ヘッダやページの下にApacheやOSのバージョンが表示されます。こういったサーバ情報をわざわざ表示する必要はありません。サーバ情報の表示しないようにするには、Apacheの設定ファイル(httpd.conf)に、次の設定を追加します。

  ServerTokens ProductOnly
  ServerSignature Off

この設定を追加後、Apacheを再起動するとServerヘッダにはApache、エラーページにもサーバの情報は表示されなくなります。


.で始めるディレクトリは公開しないようにする

ウノウでは、すべてのサービスをsvn(Subversion)で管理しています。アップデートもsvnで行っています。そのため、.svnディレクトリが誤って公開されていることがあります。.svnディレクトリには、ソースコードが入っていますので公開しない方がいいです。.svnだけでなく、.で始まるディレクトリを公開しないようにするようには、Apacheの設定ファイル(httpd.conf)に、次の設定を追加します。

.svnディレクトリにはソースコードが入っているので、注意する必要があります。

  <Directory ~ "/\..+/">
        Order Deny,Allow
        Deny from All
  </Directory>


最後に、PHPのセキュリティ向上施策も追記しておきます。

PHPファイルに対してリクエストすると、HTTPヘッダにX-Powered-Byという情報が入っています。X-Powered-Byヘッダには、PHPのバージョンが次のような形で含まれています。

X-Powered-By: PHP/4.3.11

このヘッダを隠すには、PHPの設定ファイル(php.ini)に、次の設定を追加します。

  expose_php = Off


この他にも、ウェブサーバのセキュリティ向上のための情報がありましたら、ぜひ教えてください!

2007年8月23日

赤ちゃんの目をシミュレートするテストツール?「TinyEyes」
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

こんにちは! やまもと@テスト番長です。

ラボブログでご紹介するネタを暖めていたら、結構話が大きくなってきてしまい、更にもう少し暖めたくなりました。
なので今回は代わりに、先日幸せの青い鳥を探してネットをうろうろしていた時に見つけた軽めのネタをご披露したいと思います。


tinyeyes
tinyeyes posted by (C)フォト蔵

生まれたての赤ちゃんはまだモノが良く見えていないんだそうです。
その赤ちゃんの視界をシミュレートするサイトです。
「TinyEyes」

赤ちゃんが生まれてからの週数と、対象までの距離をセットして画像をアップロードすると、それがどんなふうに見えているのかシミュレートして表示してくれます。

新生児向けのWEBコンテンツを作ることになったら、大活躍しそうなテストツールですね!(多分出番ない)

2007年8月21日

Flashの新しい可能生 Asynchronous Flash + XMLSocket
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

尾藤正人(a.k.a BTO)です

昨日ラボプロジェクトとして実験的に開発している新規プロジェクト「プラッシュ」をβ公開しました。 簡単に説明するとプラッシュはFlashとXMLSocketを使う事でブラウザだけでネットワーク対戦ができるゲームポータルサイトです。 今回はプラッシュで使われているFlashとXMLSocketを使ったアプローチについて考察してみたいと思います。

はじめに

正直に告白すると僕はFlashを一行も書いた事がありません。(汗) なので、Flashの部分に関してはFlash側の開発者であるyossyに聞いたり、Webで調べた情報がほとんどです。 不正確な情報が含まれてる可能性がありますが、その辺を考慮していただければと思います。

FlashのXMLSocketで何ができるのか

FlashのXMLSocketを使うと直接ソケット通信を行う事ができます。 AjaxやCometのような技術は元々ステートレスなHTTP上で非同期通信を実現していますが、 XMLSocketは直接ソケットを叩けるので自然な非同期通信を行う事ができます。 AjaxやCometはデータのやり取りをする度にコネクションが切れますが、XMLSocketはずっとコネクションをはったまま通信を行います。

通信の度にコネクションを確立するアプローチだと、毎回接続するためのコストがかかります。 XMLSocketはずっとコネクションをはっているので、通信の度に接続する必要がなく、よりリアルタイムな通信を実現する事ができます。 プラッシュではそれをネットワーク対戦ゲームに応用しました。

Flashを使ったリアルタイム通信で何ができるのか

それは僕にもわかりませんが、大いなる可能生は感じています。 Flashを使う最大のメリットはブラウザだけで動作する事です。 それにリアルタイム通信が加わった時に、従来ブラウザだけではできなかったことがブラウザだけでできるようになり、新たなる市場が開拓されるかもしれません。

何が必要なのか

FlashでXMLSocketを使用した通信を行うには次のものが必要です。
・Flash Player 5以降
・XMLSocketサーバ
・プロトコル

Flash Player 5以降

Flash Player 5以降でないとXMLSocketは使えないそうです。

XMLSocketサーバ

XMLSocketは直接ソケットを叩くので、独立したサーバが必要になります。 プラッシュではオリジナルのXMLSocketサーバを開発しました。

プロトコル

XMLSocketでの通信はソケットを直接叩くので具体的なデータのやり取りについては定められていません。 汎用的なプロトコルは存在しないので、クライアント側、サーバ側であらかじめ決められたプロトコルを定めて通信を行う事になります。 プラッシュではXMLをベースにした独自プロトコルで通信を行っています。

Flash+XMLSocketを使った既存の実装は

Flash+XMLSocketを使ったチャットの実装はいくつか公開されているようです。 それ以上本格的なものはなかなか見つからないのが現状です。

天鳳というオンライン麻雀がありますが、これはFlash+XMLSocketで作られています。 天鳳は大変素晴らしい実装なので一度遊んでみるといいと思います。

Flash+XMLSocketをもっと普及させるには

Flash+XMLSocketを使ったリアルタイム通信は古くから存在するにも関わらず、それほど注目されていませんでした。 僕はこの技術に大いなる可能生を感じていて、もっと広く普及しないかなと思っています。 そこでこの技術が普及するために何が必要かを考えてみました。

名前をつける

技術がより一般的になるためには呼びやすい名前が必要です。 「FlashとXMLSocketを使ってリアルタイム通信するやつ」なんてのはかったるくて呼びづらい。 何か良い名前はないでしょうか。

開発の敷居を下げる

より多くの実装が出てくるには開発の敷居を下げる事が重要。 開発の敷居を下げるために必要なことをつらつらと書いてみます。

フリーの汎用的なXMLSocketサーバ

既にXMLSocketサーバの実装はいくつかあるようですが、開発が止まっていたり、チャットに特化しているのが実情のようです。 フリーで汎用的なXMLSocketサーバがあれば開発の敷居を大きく下げる事ができると思っています。

モジュールのような形でプログラムを書く事ができて、LLで実装できるようなやつ。 プラッシュではRubyでXMLSocketサーバを書いてます。 LLでもうまくやれば十分サーバの開発は可能です。

汎用的なプロトコル

実装するたびに毎回独自プロトコルを作るのは大変ですから、汎用的なプロトコルが欲しいところ。 汎用的で可読性が高くて単純で拡張性が高いプロトコルがいいかなと思っています。 汎用的なプロトコルを定義するだけでなく、もちろんそれをベースにしたFlashライブラリ、XMLSocketサーバの実装も必要です。

まとめ

みなさんもFlash+XMLSocketを使って何か実装してみてはどうでしょうか。 今までにない何かが作れるかもしれません。

今回プラッシュで作った成果物は何らかの形でうまく公開できないか思案中です。 公開する時には、またこのブログで紹介したいと思います。

MySQL オペミスでデータが破損してしまった場合の復旧方法
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

こんにちは satoです。

オペミスで update に where句を付け忘れたり、プログラムのバグでデータが破損してしまったりした場合でも、バイナリログには更新SQLがすべて書き込まれるので、バックアップデータからオペミスが起こるまでの全てのSQLを流し込めれば、元の状態に戻すことは可能です。

 •バイナリログを取っている
 •オンラインバックアップをとっている(mysqldumpやMySQLを止めた状態でのcpによるバックアップとバイナリログ)
 •バックアップ時点でのバイナリログの書き込み位置を保存している

以上のような状態でデータが壊れた時の復旧手順をまとめてみました。シナリオとして

 •ある1カラム email をupdateしようとしたら、間違ってwhere 句を付け忘れ 全レコードをupdateしてしまった
 •気がついたのが半日後

というオペミスが発生したとします

1) データベースが更新されない状態にします(メンテナンス画面など)

2) オペミスをしてしまった binlog のバッックアップをとり、オペミスのsqlのblog上での位置を調べます

mysqlのバイナリログを残す設定にしておくと、mysqlは更新クエリーが発生すると、バイナリログに書き込みます mysqlbinlog という mysqlに付属しているツールを使用すると、バイナリログの中身を閲覧することができます

 sudo -u mysql mysqlbinlog /var/log/mysqld/blog.000001
 
 # at 461758345
 #070821 16:00:35 server id 1  end_log_pos 127   Query   thread_id=147523        exec_time=0     error_code=0
 実行したSQL文
 # at 461758472
 #070821 16:00:35 server id 1  end_log_pos 461758499     Xid = 14244002
 実行したSQL文

#at と書いてあるのがバイナリログの位置になります。

mysqlbinlog には 便利なオプションがついていて、
ある一定の時間から一定の時間までのログを表示する (--start-datetime,--stop-datetime)
ある一定の位置から一定の位置までのログを表示する (--start-position, --stop-position)
などがあります。これを利用して、オペミスの時間から問題のSQLのバイナリログの位置を割り出します。オペミスが 2007-07-20 11:27:00 頃発生したとすると

 sudo -u mysql mysqlbinlog /var/log/mysqld/blog.000001 --start-datetime 2007-07-20 11:25:00 --end-datetime 2007-07-20 11:30:00
 # at 561758345
 #070821 11:26:46 server id 1  end_log_pos 127   Query   thread_id=147521        exec_time=0     error_code=0
 update user set email = '''

原因のSQLのバイナリログ上の位置は 561758345 となります。

3) 一番最近のバックアップ状態に戻します

4) バックアップを取ったオペミスしてしまったバイナリログから、バックアップ復元時のスタート位置と オペミス直前までの位置を指定してSQLをすべて流し込みます。

バックアップ時のバイナリログの位置は

 mysql> show master status;
+-------------+-----------+------
| File        | Position  
+-------------+-----------+------
| blog.000002 | 462862334 
+-------------+----------

と調べることができます

あとはsql文を流し込みます。mysql コマンドは標準出力のSQLを流し込むことができるので、mysqlbinlog コマンドと組み合わせ使います。

sudo -u mysql mysqlbinlog /var/log/mysqld/blog.000001_bak --start-possion 461764451 --end-possion 561758345 | mysql -u ユーザ名 -p DB名

今回の場合バイナリログが同じファイルだったのでよかったのですが、再起動したり、バイナリログのサイズがmax_binlog_sizeに達すると、自動的にファイルがローテートしてしまう場合が有るので、その場合は全てのファイルを使う必要があります。また設定によってCREATE DATABASEなどがバイナリログに書き込まれない場合がありますのでここを参照してください。今回は masterだけのサーバでしたが、スレーブからバックアップを取っている場合は show slave status でマスターの位置を調べなくてはならないとかありそうですが、方法はほとんど同じ感じだと思います。

あと、どうでもいいことなんですが、DBAって性格的な向き不向きがかなりあるようなきがします。

2007年8月20日

ブラウザだけでネットワーク対戦ゲームができる無料ゲームポータル「プラッシュ」をβ公開しました
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

尾藤正人(a.k.a BTO)です

大富豪チャット
大富豪チャット posted by (C)フォト蔵

ブラウザだけでネットワーク対戦ゲームができる無料ゲームポータル「プラッシュ」をβ公開しました

プラッシュ

プラッシュの特長

  • ブラウザだけで遊べる
  • ネットワーク対戦ができる
  • Wiiに対応している
  • 無料で遊べる

ブラウザだけで遊べる

プラッシュのゲームは全てブラウザ上で遊ぶ事ができます。 面倒なソフトウェアのインストールはいっさい必要ありません。

ネットワーク対戦ができる

プラッシュのゲームはネットワーク対戦ができます。 オンラインでリアルタイムでネットワーク越しにいろんな人とゲームを遊ぶ事ができます。

Wiiでも遊べる

今話題沸騰中のWiiに完全対応。

無料でゲームが遊べる

プラッシュのゲームは全て無料で遊ぶ事ができます。

プラッシュの仕組み

せっかくラボブログにエントリを書いているので、 少しプラッシュについての仕組みを説明します。

ゲームはFlash7で作る

今回作ったのは大富豪だけですが、ゲームはFlashで作っています。 Flash7で作っているのはWiiのOperaに搭載されているのがFlash7だから。 今後もFlash7でゲームを作っていく予定です。

XMLSocketでゲームサーバと通信する

ネットワーク対戦を行うためには何らかの形でネットワーク通信を行う必要があります。 FlashにはXMLSocketというSocketを直接叩ける仕組みがあります。 そこでプラッシュではXMLSocketを使ってゲームサーバと通信する事でネットワーク対戦を実現しています。 ゲームサーバとの通信はXMLをベースにした独自プロトコルで行っています。

ゲームサーバ

プラッシュ用にゲームサーバを独自に開発しました。 決められたプロトコルに従って、 ゲームサーバ側でゲームの進行やチャットの処理などを行って、 FlashクライアントにXMLベースのレスポンスを返しています。

最後に

ぜひプラッシュでネットワーク対戦ゲームを楽しんでください!!

2007年8月17日

ブログパーツ貼り付けタグのまとめ+Googleガジェット@はてな
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

こんばんわ、isogawaです。

ウェブサービスのブログパーツを提供しようと思ったときに、ブログサービスによっては利用可能なHTMLタグが制限されていて、ブログパーツの貼り付けタグをどういったものにするべきか悩む場合があります。そこでいくつかのブログサービスについて、ブログパーツ類の扱いがどうなっているかサクっと調べてみました。大雑把な調査なので、間違ってたりするかもしれません。お気づきの点があれば訂正させていただきますので、お気軽に突っ込んでいただければ幸いです。

Flash貼り付け用HTMLタグの利用可否

まずは、ブログパーツの多くで利用されているFlashオブジェクトを表示するHTMLタグの選択肢としては、OBJECT/EMBED、SCRIPT、そしてIFRAMEがあると思いますが、以下はこれらのタグが各ブログサービスで利用できるかどうか(裏技による例外は除く)の一覧表です。

ブログ ちなみに文字コード OBJECT/EMBED SCRIPT IFRAME
アメブロ UTF-8 × × ×
ウェブリブログ Shift_JIS
エキサイトブログ UTF-8 × × ×
FC2ブログ EUC-JP
gooブログ EUC-JP × × ×
ココログ UTF-8
Seesaaブログ Shift_JIS
JUGEM EUC-JP
So-net blog UTF-8
TypePadファミリー UTF-8
ドリコム Shift_JIS
はてなダイアリー EUC-JP
Yahoo!ブログ UTF-8 × ×
ヤプログ Shift_JIS
livedoorブログ EUC-JP
楽天広場 EUC-JP × × ×

ごらんの通りこれらのタグは、一部例外を除き少なくとも上表にあるブログサービスでは、すべてOKかすべてNGかのどちらかで、つまりこれらのひとつがNGなら他のタグもNGであるようなので、どのタグを選択するか、ブログサービス側の制限を考慮して悩む必要はないようです。

そうするとFlashオブジェクトの表示は、「Internet ExplorerでのActiveXコントロールのアクティブ化問題」を考慮するなら、OBJECTタグを直接記述するのは避けて、JavaScriptで行ったほうがよいのかなと。

全般的な留意点

貼り付けコードはブログの投稿設定などに影響されないように配慮しておく必要があります。特に、サイドバーだけではなく記事本文中にも貼り付けられることを想定している場合は、以下の設定は、殆どのブログサービスで記事本文の投稿についてはデフォルトでONの筈なので、こうした設定に影響を受けないものであるか要確認です。

  • 改行を<BR>に変換する
  • URLをリンクに変換する

また、稀な例ですが、記事本文ではタグ自体はOKでも属性がNGというブログサービスがありました(入力は可能で保存もされていますが、ウェブブラウザへの出力時に除去されます)。どうやらここでは、ID属性はとにかくNGのようなので、例えば、貼り付けコード中にID属性を付けたDIV要素があって、それをJavaScriptから操作するといったコードは正常に動作しません。

以下、特殊な対応が必要なケース。

Yahoo!ブログ

HTMLタグとしてのOBJECT/EMBEDは使用できませんが、記事本文の投稿に「Wiki文法」を使用する場合は、以下のような記述でFlashオブジェクトを挿入できます(サイドバーでは利用できません)。

[[item(http://i.yimg.jp/i/topics/blogparts/topics.swf,222,240)]]

Flashオブジェクトを挿入する際の記述は、以前は非公式のembed記法が知られていましたが、現在は新たに追加された公式のitem記法を使用します(embed記法も引き続き使用可能です)。

Wiki文法を記述する場合は、記事の新規投稿時に「Wiki文法使用」をチェックしておく必要があります。このチェックを付けずに投稿してしまった記事は、以降の編集時にWiki文法を使用することはできません。またWiki文法を使用する記事で、HTMLタグを併用することはできません。

ココログ and TypePadファミリー

ココログや、typepad.jp及びTypePad ASPを利用した各ブログサービス、それにtypepad.comでは、以下の例のようなHTMLフォームで貼り付けコードをPOSTすることで、各ブログサービスの管理画面でブログパーツ(TypePadでは「ウィジェット」と呼ばれます)が簡単に設定できる仕組みが用意されています。

<form action="https://www.typepad.jp/t/app/weblog/design/widgets" method="post">
  <div>
    <input type="hidden" name="service_key"  value="(ウィジェットAPI Key)" />
    <input type="hidden" name="long_name"    value="サンプルウィジェット" />
    <input type="hidden" name="short_name"   value="widget_example" />
    <input type="hidden" name="service_name" value="example_org" />
    <input type="hidden" name="service_url"  value="http://www.example.org/" />
    <input type="hidden" name="return_url"   value="http://www.example.org/widgets/return-page.html" />
    <input type="hidden" name="content"      value="&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.example.org/widgets/example.js&quot;&gt;&lt;/script&gt;" />
    <input type="submit" value="ウィジェットを追加する" />
  </div>
</form>

ブログサービスによってPOST先のURLが異なる場合があるものの、ウィジェットAPI Keyも含めてそれ以外は基本的に同じなので、合計20近くのブログサービスにまとめて対応できます(ただしTypePad ASPを利用したすべてのサービスがこの仕組みをサポートしているわけではありません)。

はてなダイアリー and Googleガジェット

自分のはてなダイアリーにブログパーツを設置できるようになりました、ということで、はてなが許可したものについては、従来禁止されていたHTMLタグがそのまま挿入できるようになりました。そしてその「はてなが許可したもの」の中にGoogleガジェットが含まれているため、事実上あらゆブログパーツが利用できるようになっています。

既存のブログパーツをGoogleガジェット化すると、はてなダイアリーはもちろん、iGoogleやGoogleデスクトップなどにも貼り付けることができるようになります。ブログパーツのガジェット化は(凝ったことをしなければ)非常に簡単なので、ガジェットをまだ提供していなければ、この機会に検討するといいかもしれません。

Googleガジェットの基本

既存のブログパーツをGoogleガジェット化するには、以下のような内容のXMLを作成します。

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="(ブログパーツのタイトル)" />
  <Content type="html">
    (CDATAセクションに納めた、またはエスケープ処理を施したブログパーツの貼り付けコード)
  </Content>
</Module>

これはガジェットXMLの最小構成ですが、多くのブログパーツはこれだけでイケると思います。ただしGoogleガジェットでは、その本体はIFRAME内に表示されるので、ブログパーツにリンクが設定してある場合、リンクターゲットを変更する必要があるかもしれません。

このXMLをインターネットに公開すればガジェットの提供準備は完了です。

iGoogleなどではこのXMLのURLを指定してガジェットを追加します。はてなダイアリーなど、Google以外のウェブページで利用する(Googleでは「シンジケーション」と呼ばれます)には、XMLのURLとその他のパラメータをクエリーストリングに含めた、gmodules.comのURLをSRC属性値に指定したSCRIPTタグを貼り付けます。

ガジェットXMLのロケーションは任意ですが、このXMLを取得しにやってくるのはエンドユーザのウェブブラウザではなく、Google Readerなどと同じFeedfetcherロボットなので、XMLはこのロボットがアクセス可能なロケーションに配置する必要があります。つまり、localhostや認証が必要なURLはNGです。なお、Feedfetcherはrobots.txtを無視するので、robots.txtによるアクセス制限については配慮する必要はありません。

ちなみにFeedfetcherロボットのUser-Agentは以下です。

FeedFetcher-Google; (+http://www.google.com/feedfetcher.html)

Googleガジェットの貼り付けコード

はてなダイアリーなどへのGoogleガジェットの貼り付けコードは以下のようなものになりますが、はてなダイアリーに貼り付ける場合、コードの内容には注意が必要です。

<script src="http://gmodules.com/ig/ifr?url=(XMLのURL)
&amp;(その他のクエリーパラメータ)"></script> 

はてなダイアリーでは、貼り付けられたコードがGoogleガジェットのものであるか検証が行われますが、現時点ではこの検証は非常に厳格(?)です。

上の例では、SCRIPT要素にTYPE属性が欠落していますが、これを付け足したコードは、現時点ではGoogleガジェットのものとはみなしてくれません。また、クエリーストリングに指定するパラメータは下表の通りですが、これがこの順番通りに並んでいないと、やはりNGとなります。パラメータが足りなくてもダメです。

キー 説明
url ガジェットXMLのURL。この値はエンコードしてはいけませんマジで。エンコードされてると、現時点のはてなダイアリーではGoogleガジェットのコードとはみなしてくれません。
up_なんとか この使い途は後述します。このパラメータは無しでもOKです。up_なんとかを複数指定する場合はここに(「url」と「synd」の間に)並べます。
synd 「open」で固定。
w ガジェットの本体を表示するIFRAME要素の幅(ピクセル値)。本来は数値の他に「auto」を指定して、幅を親要素のものに揃えられますが、これが「auto」だと、現時点のはてなダイアリーではGoogleガジェットのコードとはみなしてくれません。
h ガジェットの本体を表示するIFRAME要素の高さ(ピクセル値)。
title ガジェットの上部に表示されるガジェットのタイトル。日本語文字が含まれる場合、現時点のはてなダイアリーではIE6で文字化けます。
border ガジェット全体を囲む外枠のデザイン指定。指定方法はこちら
output ガジェットXMLのContent要素内にJavaScriptコードが含まれる場合は「js」。そうでなければ「html」。

この、現時点でのはてなダイアリーの貼り付けコードの検証は、ガジェットディレクトリから「自分のウェブページに追加」ボタンをクリックして遷移するページ(http://gmodules.com/ig/creator?~)で取得する貼り付けコードの構成に則ったものでないとダメ、という仕様のようです。

IFRAMEの横幅に「auto」を指定できないのは、単純にこのページの「幅」入力欄に数値以外は入力できない(正確に言うと入力はできますが「NaN」と表示されますw)ためだと思われ、同様にTYPE属性が欠落していなければならないのも、XMLのURLをエンコードしてはいけないのも、単純にここで表示される貼り付けコードがそうなっているからなのだろうなと。なので、「ここでscriptは使用出来ません」とか怒られた場合は、ここのコードと見比べてみるのが吉です。

ガジェットの動作を動的に変更させる

ブログパーツによっては、設定に応じてその動作を変更する必要がある場合に、あらかじめその設定値を貼り付けコードに含めている場合があると思います。しかしGoogleガジェットではXMLをホスティングする必要があるため、同じ方法は採り難く、別の仕組みが必要になります。

もちろんXMLをホスティングするサーバが、XMLの内容を動的に出力してもよいのですが、Googleガジェット自体にこうした仕組みが用意されており、これを利用すればXMLは静的なもので済ませられます。

以下はこの機能を利用した至極簡単なガジェットのXMLです。

<?xml version="1.0" encoding="UTF-8"?>
<Module>
  <ModulePrefs title="Hello __UP_myname__" />
  <UserPref name="myname" display_name="Name" required="true" />
  <Content type="html"><![CDATA[
    <div id="hello__MODULE_ID__"></div>
    <script type="text/javascript">
    var prefs = new _IG_Prefs(__MODULE_ID__);
    _gel("hello__MODULE_ID__").appendChild(
      document.createTextNode(
        "Hello " + prefs.getString("myname")
      )
    );
    </script>
  ]]></Content>
</Module>

iGoogleにこのガジェットを追加すると、「Name」入力欄と、「ガジェットは必要な設定がすべて完了するまで表示できません」というメッセージが表示されます。名前を入力すると「Hello (入力した名前)」と表示されます。

はてなダイアリーなどでは、貼り付けタグ中のクエリーストリングに、「up_myname=(表示したい名前)」を追加すると、「Hello (表示したい名前)」と表示されます。

ガジェットXMLのUserPref要素は、ユーザの設定値を指定できるようにするためのもので、そのname属性値に合致する入力値やクエリーパラメータ(「up_(name属性値)」キーの値)が格納されます。その値は、上の例にあるように、「__UP_(name属性値)__」という記述やGoogleガジェットのJavaScript ライブラリを使って取得できます。これを利用して、ガジェットの動作を動的に変更することができるというわけです。

ガジェット開発のメモ

UserPref要素を利用した設定変更時の動作確認は、iGoogleでやったほうがいいっぽい。そしてiGoogleでの動作確認ではデベロッパー ガジェットはマストアイテム。

いったん取得されたガジェットXMLは1~2時間程度のサイクルでキャッシュされます。開発時にキャッシュを無効にする方法は以下。

  • iGoogle上ではデベロッパー ガジェットを利用する。
  • シンジケーションの場合はクエリーストリングに「nocache=1」を追加する(でも、はてなダイアリーではもちろんNG)。

2007年8月16日

フォームのユーザビリティを改善する10のTips
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

miyakeです。Webアプリケーションにおけるユーザーインタフェースの代表格と言えばフォーム。今日はそんなフォームのUIを作るに当たって、普段自分が心掛けていることをつらつらとご紹介します。

■チェックボックスやラジオボタンはfieldset,label要素でくくる

チェックボックスやラジオボタンには一般的にその内容を表すテキスト(ラベル)が付けられますが、input要素だけでマークアップした場合、チェックボックス(ラジオボタン)の部分しかクリックすることができません。

label要素を用いることで、ラベルの部分をクリックしてフォームを操作することが可能になります。これは是非設定しておきましょう。

ラベルをクリックできると思って期待を裏切られると、かなりのストレスになりかねません。

また、そのチェックボックスやラジオボタンのグループをfieldset要素で囲んでおくことをお勧めします。マークアップ的な理由というよりも、後からCSSでデザインをに手を入れる時に、CSSだけで対応できる範囲が広くなることのメリットが大きいです。

実際のHTMLは以下のようになります(紙面の都合上適宜改行していますが、実際は一行で書く方が安全です)。

<fieldset>
 <input type="radio" id="fav1" name="favorite" value="1" />
 <label for="fav1">犬好き</label>
 &nbsp;&nbsp;
 <input type="radio" id="fav2" name="favorite" value="2" />
 <label for="fav2">猫好き</label>
</fieldset>

以下、長いので続きを読むでどうぞ。

注)この部分、当初はlabel内にinputを入れていましたが、不適切ではないかとのご指摘をコメントにて頂き、修正しました。ご指摘ありがとうございました。また、fieldset要素を使用する場合、xhtmlの仕様ではfieldsetの後にlegend要素によるラベルを付けるべきであるとされていますが、本エントリでは省かせて頂きました。

また、はてなブックマークのコメントにて、「Safari2ではlabel部分をクリック出来ない」という情報を寄せて頂きました。確認したところ、確かにラベル部分をクリックしても選択できませんでした。未確認ですがSafari3では大丈夫だそうです。情報ありがとうございました。

■エラー時は class="error" を付ける

入力エラーがあった場合には、フォーム項目の脇にエラーメッセージを表示します(場合によってはページ上部にも)。この時、フォームの要素に対してエラーであることを表すクラスを指定し、CSSで装飾を施すことで「どの項目を入力し直す必要があるか」をユーザーに伝えます。

<p><input type="text" name="name" class="error" value="" /></p>
<p class="error">※お名前を入力してください。</p>

このようなHTMLを出力するようにプログラムを組んでおけば、

input.error {
    background:#fc0;
}

こういったCSSでエラーがあった項目の背景に色を付けたりできます。

チェックボックスやラジオボタンの場合は、label要素やfieldset要素にもそれぞれ class="error" を指定しておきます。

input要素だけに付けた場合、チェックボックス(ラジオボタン)の部分だけしかスタイルが適用されません。また、Firefoxでは背景色の指定自体が効きません。

IEとFirefoxでフォームのCSS実装が異なる
IEとFirefoxでフォームのCSS実装が異なる posted by (C)フォト蔵

labelやfieldsetに背景色を指定すると、ラベル部分も含めてスタイルを制御できます。プログラマ的には、「とりあえずエラーのクラス名を付けておいて細かいところはデザイナー任せ」というスタンスが妥当なところでしょぅか。

■ログインフォームはページ読み込み時にフォーカスさせる

メールアドレス(ID)とパスワードを入力してログインするような一般的なログインページではJavaScriptを使って、ページが表示された時に最初の項目をフォーカスするようにしておきます。

他にも色々なフォームがあって、その中の一つがログインフォームという場合はこの限りではありませんが、ログインすることが目的のページでは是非設定しましょう。

ちょっとしたことですが、一度この形式に慣れてしまうと、そうなっていないフォームにはストレスを感じてしまいます。

■大切なボタンは大きくする

画面設計にもよりますが、入力内容を確定するsubmitボタンなどを大きくすることでユーザビリティの向上が見込めます。

昔自分が担当していたシステムでバージョンアップのついでに確定ボタンを大きくしたら、追加機能よりもそちらを喜ばれたことがあります。

毎日ずっとネットに触れていると「キーボードでsubmitするから」とか思ってしまいがちですが、「入力はキーボードでするけど、最後のボタンはマウスでクリックする」という操作をする人も(自分のいた環境では)少なくありませんでした。

また、サイトのターゲット層によってはボタンだけでなく、他の項目の文字サイズや要素毎の余白も検討する価値があります。

■ボタンのテキストは「押したらどうなるか」が分かるように

ボタンには「登録」や「投稿」といった単語だけでなく、「この内容で登録する」「日記を投稿する」のように「そのボタンをクリックすることで何が起こるか」が伝わりやすいようなラベルを設定します。自分は「○○を○○する」といった文脈で書くことが多いですね。

「フォームに何かを入力して、submitボタンを押す」という行為は、特にPCに不慣れな人にとっては心理的な抵抗・プレッシャー、場合によっては恐怖感さえ感じるもののようです。

その根本には、「何が起こるか分からない不安」というのがあるようです。フォームのテキストに十分な情報を持たせることで、少しでもその不安を和らげることができればいいですね。

■画面遷移と現在位置をチャートなどで見せる

入力・確認・完了の3画面程度であれば必要性は薄いと思われますが、それ以上に画面遷移するようなフォームでは

  • フォームの一連の処理でどれだけの画面があるか
  • 今表示しているのはその中のどのページか

を示すナビゲーションを設置するのも一つの手です。通常のパンくずナビゲーションを設けている場合はそちらに組み込むのも手ですが、ECサイトなどでは購買のフローを明確にするために使われることがあります。

■フォーム要素の幅はCSSで指定する

input要素には幅を指定するsize属性がありますが、この指定では実際のところ狙い通りの幅で表示させるのは難しいです。input要素の幅はsize属性ではなく、CSSで指定することをお勧めします(幅の単位は要件に応じて)。

また、textarea要素には列数と行数を指定するcols,rows属性があります。こちらはDTD上必須の属性として定義されていますので、設定した上で幅だけを改めてCSSで指定してやるといいでしょう。cols属性だけで指定するとブラウザ間で幅を一定にできないようてす。

■全角英数字は必要に応じて半角に変換する

メールアドレスが全角で入力された場合、「半角英数字で入力してください」というエラーを出すよりも、サーバサイドで半角に変換してあげた方が親切です。

特にPCに不慣れな方が一所懸命メールアドレスを入力したのに、このエラーメッセージを突きつけられると心が折れる可能性は高いように思います。

設計ポリシーによっては難しいかも知れませんが、登録時は自動変換せずに半角だけを認め、その後のログインなどでは全角でも通るように変換する、といったアプローチも考えられます。

また、フリガナの入力などで半角カタカナを全角カタカナに変換する処理も入れておくといいかも知れません。全角ひらがな→全角カタカナの変換も可能ですが、そこまで対応するかは検討の余地があるでしょう。

■前後のスペースも必要に応じて削除する

メールアドレスやユーザーIDをコピー&ペーストで入力した時に、末尾にスペースが入ってしまってエラーになる場合があります。

入力された内容の先頭と末尾にあるスペースをシステム側で落としてやることで、こうした状況を防ぐことができます。

■郵便番号検索を付ける

フォームのユーザビリティと言うよりは、一つの機能になってしまうので詳細は省きますが、あると無いとで大きく利便性が変わってきます。郵便番号→住所の自動入力はもちろんですが、住所→郵便番号も引けるとより便利ですね。

フォームはユーザーとサイトをつなぐとても大切なインタフェースです。

が、プログラム的な要素とデザイン的な要素の両方が求められ、分業が発生しがちなこともあってか、望ましくない実装になっているフォームが多々見られます。

ここに挙げた項目は必ずしも全ての状況て正しいものではありません。また、内容的にも決して目新しい物ではありません

重要なのは、

  • 自分のサイトのターゲットは誰なのか?
  • その人達はフォームがどうなっていると嬉しいか?

ということを考えた上で、その都度最適な形を考えることだと思います。

実際の業務では様々な制約から理想的なフォームを追求するのが難しい部分もあるかと思いますが、本稿が皆さんのフォーム構築の一助になれれば何よりです。

2007年8月15日

グラフィック作りのコツとカン
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

こんにちは。yamazakiです。
前回はレイアウトなどについて非常にざっくりとですが書いてみたわけですが、いかがでしたでしょうか。
そろそろ「グラフィック」のほうも少し書いてみようかという気になってきたので、グラフィック品質を高めるベーシックな技術についても少しずつ書いていってみようと思います。

基本のき

具体的な話に入る前に、まずは基本的な話から。
とりあえず、ざっとあなたの周囲を見回してみてください。壁にしても、PCにしても、「単なる一色のベタ塗り」にはなっていないのではないかと思います。光の加減などで、「影」や「グラデーション」がついていると思います。また、ものの表面には「つるつる」「ざらざら」といった「質感」があるのが当たり前、という中で私たちは生活しています。
そのため、人の目はそういう「グラデーション」や「影」、「質感」がある状況を「見慣れて」います。

グラフィック上の処理で影をつけたり、グラデーションをつけたり、「質感」にこだわってみたりするのは、そういう「見慣れたもの」に近づけるという意味があります(それだけでもないですが)。
通常目にするものに対して違和感のあるもの、に対しては人は「安っぽさ」みたいなものを感じることがありまして、そういった意味で「グラデーション」や「影つけ」、「質感づけ」というのは、わりと「高品質なグラフィック」感を出すのに有効だったりします。

ということでそれでは、実際にグラデーションや影などをグラフィック上で使うときのコツなどを簡単に…。

グラデーション

色→白に抜けるグラデーションはあまり使わない

「白」っていうのはわりと特殊な色で、色のついたものが白に抜けていくようなグラデーションになっていること、って実はわりと少ない。ので、避けます。

少し複雑な色使いをしてみる

夕暮れに空が薄く虹色っぽくなっているのを見てきれいだと思うこともあります。単に一色の明暗でなくて、色相の違う複数の色のグラデーションを作ってみるときれいなグラデーションができたりします。たとえば「緑寄りの暗い青」から「水色っぽい明るい青」に変化するグラデーションを作ってみると、ちょっといい感じです。

grad
grad posted by (C)フォト蔵

grad2
grad2 posted by (C)フォト蔵


影付け

はっきりした影、というのはあまり現実にはありません。色んな光源からの光がミックスされて、複雑な影ができる状況を普段目にすることが多いです。
なのでグラフィック上でもそれに習ってみます。

shadow
shadow posted by (C)フォト蔵

立体感を出す

影やグラデーションに関係するところで「立体感」についても一つ。
人の目はなぜか知りませんが、必ず「上」、とくに「左上」に光がある、と仮定してできるハイライト、影に基づいて「膨らんでる」「へこんでる」と判断しがちです。

ボタンを作るときなどにはそのことを意識して作ると立体感などがうまく出てくれます。

rittai
rittai posted by (C)フォト蔵


テクスチャ

テクスチャ、というのは「表面の質感」のことです。たとえば金属であればツルツルしている、布であればデコボコしていて光を反射しにくい、など。そういった特徴を画面上で再現するために、グラデーションや表面のグラフィックの書き込みなどを駆使して「つるつる」「ざらざら」「でこぼこ」などを表現していきます。

texture1
texture1 posted by (C)フォト蔵

texture2
texture2 posted by (C)フォト蔵

以上、今回はちょっと時間がなくて細かい解説ができないのが残念なところではありますが、何かのヒントになったら幸いです。

Webアプリケーションの国際化
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

komagataです。

先日、社内の勉強会でWebアプリケーションの国際化について話したので資料を公開します。

資料内で出てくるソースは下記でダウンロードできます。

関連: ブラウザ上で翻訳ファイルが編集できるソフト「Pootle」

2007年8月14日

言語モード毎にキーボードマクロを設定する(Emacs)
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

こんばんは。bokkoです。

Emacsを使っている人に限らず、タイプ数を減らすために、
キーボードマクロを使っている人は多いと思います。
私の場合、for文やmain関数などをキーボードマクロで自動生成したりしているのですが、
最近、ほかの言語の構文と名前がかぶってしまったり、
RubyやPythonで書いているときは欲しいんだけど、
CやC++で書いているときは、全然いらないマクロがあったりするのが気になったので、
整理することにしました。
最初はマクロに言語の名前をつけて区別しようとしたのですが、
Emacsではadd-hookが使えるので、そっちを使って言語モード毎にマクロを設定することにしました。

(setq c_macros_dir "~bokko/emacs-macros/c/")
(add-hook 'c-mode-hook
          '(lambda ()
             (load-file (concat c_macros_dir "create_nested_block_main.macs"))
             (load-file (concat c_macros_dir "create_nested_block_for.macs"))
             (load-file (concat c_macros_dir "create_nested_block_while.macs"))
                                                        ・
                                                        ・
                                                        ・
             ))
(setq php_macros_dir "~bokko/emacs-macros/php/")
(add-hook 'php-mode-hook
          '(lambda ()
             (load-file (concat php_macros_dir "create_nested_block_func.macs"))
             (load-file (concat php_macros_dir "create_nested_block_class.macs"))
             (load-file (concat php_macros_dir "create_nested_block_foreach.macs"))
             (load-file (concat php_macros_dir "var_dump_exit.macs"))
                                                        ・
                                                        ・
                                                        ・
             ))

このように書くと、各言語モードだけに必要なキーボードマクロを設定することができますし、
別の言語に同じ名前のマクロがあっても大丈夫です。

Pythonで携帯の機種判別をする
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

こんにちは、chihiroです。今回はPythonでモバイルサイトを開発する場合に便利なライブラリ、WSGIUserAgentMobileを紹介します。これはUserAgentからキャリアや端末情報を取得するためのライブラリです。

Google Code WSGIUserAgentMobile
http://code.google.com/p/wsgiuseragentmobile/

これは基本的にはPHPのPEAR::Net_UserAgent_Mobile、さらに元を辿ればPerlのHTTP-MobileAgentを、僕がPythonに移植したものですが、いくつか独自のメソッドやプロパティを追加しています。インストールから、基本的な使い方、Djangoで使用する場合の例をご紹介します。

インストール

諸般の事情によりまだPython Package Indexに登録していないので、開発レポジトリから直接インストールして下さい。

レポジトリからチェックアウトしてからインストールする場合、次のようにします。

$ svn checkout http://wsgiuseragentmobile.googlecode.com/svn/trunk/ uamobile
$ cd uamobile
$ python setup.py install

または、easy_installを使って直接レポジトリからインストールすることもできます。

$ easy_install http://wsgiuseragentmobile.googlecode.com/svn/trunk/

簡単な使い方

デバイスの判定を行うには、uamobileモジュールのdetect関数を使います。detectに与える引数は辞書型オブジェクトです。

>>> from uamobile import detect
>>> detect({'HTTP_USER_AGENT':'KDDI-SA31 UP.Browser/6.2.0.6.3.129 (GUI) MMP/2.0'})
<EZwebUserAgent "KDDI-SA31 UP.Browser/6.2.0.6.3.129 (GUI) MMP/2.0">

detect関数には、少なくともHTTP_USER_AGENTというキーと値だけは与えなくてはなりません。さもないと、当然ながらUserAgentの判定ができないので、detect関数はNonMobileオブジェクトを返します。

>>> detect({})
<NonMobileUserAgent "">

よく使うメソッド・プロパティ

carrier, short_carrierでキャリア名、キャリア名の頭文字を取得できます。

>>> dev = detect({'HTTP_USER_AGENT':'KDDI-SA31 UP.Browser/6.2.0.6.3.129 (GUI) MMP/2.0'})
>>> dev.carrier
'EZweb'
>>> dev.short_carrier
'E'

PHP版、Perl版との違いとしては、ライブラリ内部での用語・表現に、VodafoneではなくSoftBank、AirHではなくWILLCOMという語を使用している点があります。

>>> dev = detect({'HTTP_USER_AGENT':'Vodafone/1.0/V904SH/SHJ003 Browser/VF-NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1'})
>>> dev.carrier
'SoftBank'
>>> dev.short_carrier
'S'
>>> dev = detect({'HTTP_USER_AGENT':'Mozilla/3.0(WILLCOM;SANYO/WX310SA/2;1/1/C128) NetFront/3.3'})
<WillcomUserAgent "Mozilla/3.0(WILLCOM;SANYO/WX310SA/2;1/1/C128) NetFront/3.3">
>>> dev.carrier
'WILLCOM'
>>> dev.short_carrier
'W'

キャリアを判定するメソッドとして、is_docomo(), is_ezweb(), is_softbank(), is_willcom(), is_nonmobile()があります。それぞれ、DoCoMo端末、au端末、SoftBank端末、WILLCOM端末、それ以外のときにTrueを返します。

>>> dev = u.detect({'HTTP_USER_AGENT':'DoCoMo/2.0 N904i(c100;TB;W30H20)'})
>>> dev.is_docomo()
True
>>> dev.is_ezweb()
False
>>> dev.is_softbank()
False
>>> dev.is_willcom()
False
>>> dev.is_nonmobile()
False
>>>

serialnumberプロパティから、DoCoMo端末ならばFOMA製造番号、au端末ならばサブスクライバID、SoftBank端末ならば製造番号を取得できます。

>>> dev = detect({'HTTP_USER_AGENT':'DoCoMo/2.0 N904i(c100;TB;W30H20;ser333333333333333;icc8888888888888888888F)'})
>>> dev.is_docomo()
True
>>> dev.serialnumber
'333333333333333'
>>> dev = detect({'HTTP_USER_AGENT':'Vodafone/1.0/V904SH/SHJ003/SN333333333333333 Browser/VF-NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1'})
/CLDC-1.1">
>>> dev.serialnumber
333333333333333

SoftBankだけの特殊なプロパティとしてjphone_uidがあります。これはSoftBank利用者が通知設定を有効にしている場合(My SoftBank⇒各種変更手続き⇒ユーザID通知設定)に、コンテンツ提供者に通知される端末毎に一意なIDです。実際のjphone_uidは英数字(a-zA-Z0-9)からなる16桁の文字列です。

>>> dev = detect({'HTTP_USER_AGENT': 'Vodafone/1.0/V904SH/SHJ003 Browser/VF-NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1',
                 'HTTP_X_JPHONE_UID': 'xxxxxxxxxxxxxxxx' })
>>>dev.jphone_uid
'xxxxxxxxxxxxxxxx'

displayプロパティでDisplayオブジェクトを取得できます。これは端末の画面サイズにあわせて表示するコンテンツを変える場合に便利です。

>>> dev = u.detect({'HTTP_USER_AGENT':'DoCoMo/2.0 N904i(c100;TB;W30H20)'})
>>> dev.display.width
240
>>> dev.display.height
352
>>> dev.display.color
1
>>> dev.display.depth
262144

端末がCookieを利用かどうかを調べるには、supports_cookie()メソッドを使います。

>>> docomo = u.detect({'HTTP_USER_AGENT':'DoCoMo/2.0 N904i(c100;TB;W30H20)'})
>>> docomo.supports_cookie()
False
>>> au = detect({'HTTP_USER_AGENT':'KDDI-SA31 UP.Browser/6.2.0.6.3.129 (GUI) MMP/2.0'})
>>> au.supports_cookie()
True
>>> sb = detect({'HTTP_USER_AGENT':'Vodafone/1.0/V904SH/SHJ003 Browser/VF-NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1'})
>>> sb.supports_cookie()
True

応用編・Djangoで使う

Djangoで使用する場合、Middleware層に端末判定処理を追加するとよいでしょう。例えば、myprojectというプロジェクトのmyappというアプリケーションにmiddleware.pyとして、次のようなMiddlewareを用意します。

# myproject/myapp/middleware.py
from uamobile import detect, exceptions

class UserAgentMobileMiddleware(object):
    def process_request(self, request):
        try:
            request.device = detect(request.META)
        except exceptions.NoMatchingError, e:
            raise

判定に失敗した場合、NoMatchingErrorが発生します。上記のMiddlewareでは、たんに、例外を再度raiseしているだけですが、本来ならば、非モバイルブラウザとしてそのまま処理を続行するか、あるいは、エラー画面を表示するといった対応が必要でしょう。

このMiddlewareを有効にするために、settings.pyのMIDDLEWARE_CLASSESにこのクラスを追記します。

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    # 追加
    'myproject.myapp.middleware.UserAgentMobileMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.middleware.doc.XViewMiddleware',
)

後はビューやテンプレートから"request.device"のようにしてUserAgentサブクラスのインスタンスにアクセスできます。

Djangoで本格的なモバイルサイトを構築する場合には、Cookieが使えない端末のセッションIDの処理といったモバイルサイトならではの対応が必要とされますが、そのあたりのノウハウはまた機会を改めて紹介したいと思います。

まとめにかえて

このWSGIUserAgentMobileは僕が開発を担当しているgumiでも使用しています。興味がある方は、是非、携帯でhttp://gu3.jp/にアクセスしてみて下さい。

また、このライブラリはまだベータ版なのですが、バグの報告や何かご質問がありましたら、コメントやトラックバックでお知らせいただくか、下記メールアドレスに直接ご連絡いただければ幸いです。

>>> 'Y2hpaGlyb19zYWthdG9rdUB1bm9oLm5ldA=='.decode('base64')

2007年8月13日

プログラミングに使いやすいフォントを選ぶ
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

yukiです。

人によってまちまちですが、見易さや生産性にかなり影響する(と思っている)プログラミング時のフォントについて紹介します。
マカーの方はデフォルトで十分読みやすいフォントが入っているので、ここではwindows向けとして紹介させて頂きます。
個人的に選ぶポイントは、


  • ゼロ・オーは斜線で区別がつく

  • 日本語も使える

  • 長時間見ても疲れない(一番大事)


です。これいいよ!というのがあったら絶賛募集中です。

有名どころかもしれませんが

M+フォント

M+フォント
M+フォント posted by (C)フォト蔵
普段はコレを使わせていただいています。
自分的にはゼロ(0)とオー(O)の差が分かりやすく◎です。
ゼロの中にスラッシュやドットが入っていて読みやすく、等幅なので使いやすいです。

VLゴシックフォントファミリ

上記のM+を元に製作されたフォントです。 弊社CTOが過去に参加されていたVineLinuxのProjectVineの方が製作されています。

小夏フォント

ちょっとクセがありますが、縮小しても見やすくいい感じのフォントです。

XANO明朝フォント

日立と契約し無償で配布されているフォント。明朝体なので若干日本語が厳しめですが、英数字には良いかも知れません。

また、ClearTypeを使うとWindowsでも多少美しくなるので、ClearTypeに対応したフォントがあれば試してみる価値があるかもしれません。

2007年8月10日

さくらインターネットで添付画像付きのマルチパートメールをPHPで送ってみる
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

matsudaです。こんにちは。

最近周りの環境に触発され、PHPでプログラミングを初めています。
で、なんとなくHTMLで画像が添付されてて、マルチパートなメールを送りたくなったので簡単な雛形を作ってみました。

・最近プログラミングはじめた
・PEARのインストールとかよくわからない
・簡単に、添付画像とテキストでメールを送れればいい

な人にオススメです。

さくらインターネットを利用していて、PEARのライブラリのインストールとかよくわからない!っていう人に効果を発揮するはずです。宛先と送信元メアドをかきかえて、ためしに利用してみてください。

<?php

//内部のエンコード
mb_language("japanese");
mb_internal_encoding("UTF-8");

//画像の取得と画像のエンコード
$img = file_get_contents("http://art6.photozou.jp/pub/835/122835/photo/4258910_thumbnail.jpg");
$img_encode64_000 = chunk_split(base64_encode($img));

//ヘッダ情報
$sendto   = "ここに宛先メアド";
$subject  = "ここにサブジェクト";
$headers  = "FROM:" . "ここに送信元メアド". "\r\n";
$headers .= 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-Type: multipart/related;boundary="1000000000"' . "\r\n";

//テキストパート、HTMLパート
$message =<<<END

--1000000000
Content-Type: text/plain; charset=iso-2022-jp
Content-Transfer-Encoding: 7bit

テキストパートはここ

--1000000000
Content-Type: text/html; charset=iso-2022-jp
Content-Transfer-Encoding: 7bit

<html>
<body>
ここがHTMLパート<br>
画像表示はこんな感じで<br>
<img src="cid:img_id_000"<<br>
</body>
</html>

--1000000000
Content-Type: image/jpeg; name="images000.jpg"
Content-Transfer-Encoding: base64
Content-ID: <img_id_000>

$img_encode64_000

--1000000000--

END;

//メール用にサブジェクトと本文をエンコード
$subject = mb_encode_mimeheader($subject);
$message = mb_convert_encoding($message, "JIS");

//最後に送信!!
mail( $sendto, $subject, $message, $headers); 
?>

2007年8月 9日

inline-blockでマルチカラムレイアウト
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

yamaokaです。

2007年7月19日、CSS 2.1が再び勧告候補になりました。正式な勧告になるのは来年になりそうですが、CSSに携わっている人は今のうちから内容に目を通しておくといいかもしれません。

adds a few highly requested features including the inline-block value for the display property, the color orange and the values pre-wrap and pre-line for the white-space property.

勧告候補になるにあたり、新たに追加された機能は上記引用の通りです。

今回は、試しにinline-blockを使ったマルチカラムレイアウトを作ってみようと思います(inline-blockに関しては既にOperaとSafariで先行実装されており、試すことができます)。

今までマルチカラムなレイアウトを作るには2通りの方法がありました。

  1. ブロック要素をfloatさせて並べる方法
  2. ブロック要素をposition指定して並べる方法

それぞれの実装方法に関しては、「 Lucky bag::blog: CSSによる段組レイアウトのフレームワーク」が詳しいので参考にしてみてください。いずれの方法も一般的なものですが、導入には多少の注意が必要です(Internet Explorerのfloat関連のバグとか、position指定による弊害とか)。

では、inline-blockを使うとどうなるのでしょうか。2カラムのレイアウトを試しに作ってみます。

まずはHTML、シンプルに。

<div id="container">
  <div id="contents">
    <p>
      contents<br>contents<br>contents<br>contents<br>
      contents<br>contents<br>contents<br>contents<br>
      contents<br>contents<br>contents<br>contents<br>
      contents<br>contents<br>contents<br>contents<br>
    </p>
  </div><div id="sidebar">
    <p>
      sidebar
    </p>
  </div>
</div>

そしてCSS。

#container {
  width: 530px;
  margin: 0 auto;
  border: solid 1px #808080;
  background-color: #eee;
}
#contents {
  display: inline-block;
  width: 300px;
  margin: 10px;
  background-color: #fcc;
  vertical-align: top;
}
#sidebar {
  display: inline-block;
  width: 200px;
  margin: 10px 10px 10px 0;
  background-color: #ccf;
  vertical-align: top;
}

それをOpera(バージョン9.22、Windows版)で表示させてみた結果。 inline-block

以上の手順で、2カラムのレイアウトがとても簡単にできてしまいました。これはいいですね。特に悩むような箇所もなく、非常にシンプルに記述することができます。3カラムにする場合は、単純にもう一つinline-blockなブロックを追加すればよさそうです。

Internet ExplorerやFirefoxでinline-blockが実装されるのはまだまだ先になりそうですが、マルチカラムレイアウトが非常に簡単にできるようになるので、早く実装されてほしいところですね。

ちなみに、#contentsと#sidebarのvertical-align属性にtopを指定しているのは、内包されるブロック要素の上側に寄せて配置するためです。Inline formatting contextという章に、以下のように書いてありました。

When the height of a box B is less than the height of the line box containing it, the vertical alignment of B within the line box is determined by the 'vertical-align' property.

また、HTMLで#sidebarのdivの開始タグを#contentsの閉じタグの直後に書いているのは、Operaで表示した場合に2つのブロックの間に謎のスペースが開いてしまうのを防ぐためです。改行などを入れるとスペースが開いてしまうようなのでこうしています。

2007年8月 8日

ブラウザ上で翻訳ファイルが編集できるソフト「Pootle」
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

pootle7

komagataです。

アプリケーションを国際化する場合は大体gettextを使ってPOファイルを作って、MOファイルを作ってという感じですが、エンジニアでない人に使ってもらったり、複数の人と共同で翻訳作業をしたい場合に敷居の高さを感じてしまいます。

もっと手軽に翻訳作業が出来るソフトが無いかと思って探したところ、Pootleというソフトを知りました。

Pootleの特徴:

  • ブラウザ上でPOファイルの編集。
  • CVS, Subversion, darcsといったバージョン管理ソフトとの連系。(updateやcommitができる)
  • 複数プロジェクトの管理。
  • ブラウザ上でユーザー管理。
  • プロジェクト毎にユーザー単位の細かい権限管理。
  • 単数系・複数系への対応。
  • Fuzzyへの対応。
  • Python製。

BitTorrentやFirefox, GNOME, KDE, OpenOffice.orgの一部で翻訳に使われているそうです。

Pootleのインストール:

Ubuntu 7.04の場合:

$ sudo apt-get install pootle

パッケージが無い場合:

インストール地獄。

jToolkitは、

python jToolkitSetup.py install

Pootleは、

python pootlesetup.py install

それ以外は、

python setup.py install

でインストール出来ました。

pootle.prefsファイルを修正して翻訳したいプロジェクトを設定します。

    rails_gettext:
      fullname = "Rails GetText Sample"
      description = "Terminology project that Pootle should use to suggest terms"
      checkstyle = "standard"

また指定のディレクトリ以下に、

プロジェクト名/言語名

の形でPOファイルを置く必要があるので適宜シンボリックリンクを張ります。

/usr/binにPootleServerコマンドが入るので実行するとデフォルトで8080番ポートで起動します。

Pootleトップページ:

pootle1

ブラウザ上でユーザー管理が出来ます。

ユーザー管理画面:

pootle2

複数のプロジェクトを一括して管理出来ます。

プロジェクト管理画面:

pootle3

プロジェクト毎にユーザーの権限を細かく設定できます。

プロジェクト毎のユーザー権限管理画面:

pootle4

言語毎の翻訳状況の進捗が一覧できます。

pootle5

ブラウザ上でPOファイルが編集できます。コメントやFuzzyにも対応しているので便利です。

pootle6

実際に仕事でエンジニアでない方に使ってもらいましたが、少しの説明だけで問題無く翻訳作業をしてもらえました。個人的にはUIにちょっと癖があるかなと思ったんですが、予想以上に使ってもらった感触は良かったです。特に会社などで複数の国際化プロジェクトを抱えているところでは導入を検討してみてはいかがでしょうか。

2007年8月 7日

携帯サイト作成のためにも使えるPHPのライブラリ
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

harukiです。

携帯サイト作成の際に使えるPHPのライブラリを知っているだけ羅列してみます。

Net_UserAgent_Mobile

基本となるライブラリです。機種判定など、様々な用途に使用します。
細かい情報については、スクレイピングなどをしたりして自前で用意する必要があります。

PEAR::Mail

メールの送信に使用できます。
特殊な送信の際は、Mail::factory()にsmtpで使用することになりますが、キャリアの迷惑メールの設定にも気をつける必要があります。

Mail_mime_Decomail (Y-110's Wiki)

Mail_mimeと同じ使い方で、デコメール送信用にMIMEを組み立てることができるのでとても便利です。

Mail_mimeDecode

空メール・エラーメールなどを受け取って解析する際に使用します。
解析の際には、Mail_RFC822::parseAddressListも使用します。

Net_IPv4

キャリアのIP帯域の判定に使用します。

HTTP_Download

auでのFlashや動画などの分割ダウンロードの際にも使用できます。
setContentType()でvideo/3gpp2などが指定できないので、手を加える必要があります。

画像処理

使える画像の種類が違うため変換したり、リサイズなどの処理のために使用します。
ライブラリについてはこちらのエントリに詳しくまとめられています。

上記のライブラリで、ある程度、末端の処理の手間を省けるのではないでしょうか。
それ以外の処理は、普段使用しているフレームワークなどでがんばることになります。。。

便利なライブラリがあったらぜひ教えて下さい。

JavaScriptを使わないスターレイティングの作り方
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

こんにちわ、山下です。
Amazonなどで使われているような商品を☆の数で評価するスターレイティングというものがあります。今回は、CSS The Star Matrix Pre-loadedに紹介されている記事を参考に、その作り方を簡単に紹介しようと思います。

1.画像を用意する

まず次のような1枚の画像を用意します。16×16ピクセルの☆が、横に5個、縦に11個並んでいて、下に向かうに従って色の付いている☆の数が増えているのがポイントです。

star-matrix.gif

2.HTMLを書く

HTMLはとてもシンプルで、ULリストを使います。

<ul class="rating onestar">
<li class="one"><a href="#" title="1 Star">1</a></li>
<li class="two"><a href="#" title="2 Stars">2</a></li>
<li class="three"><a href="#" title="3 Stars">3</a></li>
<li class="four"><a href="#" title="4 Stars">4</a></li>
<li class="five"><a href="#" title="5 Stars">5</a></li>
</ul>

ULタグ自体には、rating と onestar という2つのクラスが指定されていて、ratingは基本的なスタイル指定用です。2番目のonestarで初期値を設定しています。表示したい☆の数に応じて、onestar, twostar, threestar..といったように設定します。
また、それぞれのリストアイテム(li)には識別できるように、one, two, three..といったクラスを割り当てておきます。

3.CSSを書く(1)

基本的なスタイル指定は次のようになります。

.rating{
    width:80px;
    height:16px;
    margin:0 0 20px 0;
    padding:0;
    list-style:none;
    clear:both;
    position:relative;
    background: url(images/star-matrix.gif) no-repeat 0 0;
}
ul.rating li {
    cursor: pointer;
    /*ie5 mac doesn't like it if the list is floated but ie6 does\*/
    float:left;
    /* end hide*/
    text-indent:-999em;/* hide text*/
}
ul.rating li a {
    position:absolute;
    left:0;
    top:0;
    width:16px;
    height:16px;
    text-decoration:none;
    z-index: 200;
}
ul.rating li.one a {left:0}
ul.rating li.two a {left:16px;}
ul.rating li.three a {left:32px;}
ul.rating li.four a {left:48px;}
ul.rating li.five a {left:64px;}

ULタグの背景画像として☆を表示して、その上に16x16ピクセルのアンカーをそれぞれの☆の上に並べるイメージです。また、テキストは表示しないので、text-indent:-999em としておきます。以上は、次の画像を見ると少し分かりやすいかもしれません。

star_layout.png

4.CSSを書く(2)

初期状態で表示する☆の数を設定します。「1.HTMLを書く」でULクラスの2番目に指定したものです。表示する☆の数に応じて、背景画像を縦方向に16ピクセルずつずらして表示します。

.nostar {background-position:0 0}
.onestar {background-position:0 -16px}
.twostar {background-position:0 -32px}
.threestar {background-position:0 -48px}
.fourstar {background-position:0 -64px}
.fivestar {background-position:0 -80px}

5.CSSを書く(3)

最後にここが最大のポイントなのですが、マウスオーバーで☆の表示が変わるようにhover属性を指定します。☆の数に応じて16ピクセルずつずらすのは先ほどと同じなのですが、widthを80ピクセルにして初期表示の背景画像に重ね合わせて表示します(そのためにz-indexを小さくしています)。

ul.rating li a:hover {
    z-index:2;
    width:80px;
    height:16px;
    overflow:hidden;
    left:0;
    background: url(images/star-matrix.gif) no-repeat 0 0
}
ul.rating li.one a:hover {background-position:0 -96px;}
ul.rating li.two a:hover {background-position:0 -112px;}
ul.rating li.three a:hover {background-position:0 -128px}
ul.rating li.four a:hover {background-position:0 -144px}
ul.rating li.five a:hover {background-position:0 -160px}

以上で完成したのが、このサンプルです。




実際にサーバ側にデータを登録するには、もう少しやらなければならないことがあります。アンカーをクリックしたら、JavaScriptでPOSTするようにしたり、サーバ側でデータを受け取ってデータベースに格納するなどをしなければなりません。今回はそこまでは解説できませんでしたが、AJAXでページ遷移なしに処理するのもそんなに難しくないと思いますので、ぜひ挑戦してみてください。

それでは皆さん、良い評価ライフを!

PHPで暗号化して、Flashで復号してみたときのメモ
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

Keitaです。

もう、半年くらい前になりますが、画像をFlashとPHPの間だけデータを暗号化できないかなーとおもって試したことがあります。結論としては、Flashで解読できているということは、Flashをうまいことやればデータが抜き出せるし、そもそも、暗号化する意味が個人的に皆無だったのと、画像ほど大きいデータになると解読に時間がかかってしまったので、「あー、まぁほかにやることもあるし、いいや」とおもって、忘れることにしました。

でも、まぁ昔こういうことやって遊んだなぁという記録と、もしかすると誰かの役にたつかと思い記事にさせていだきます。

環境は、サーバサイドはPHP5で、クライアントは、Flex2で作成しました。

PHP側でデータをこんな感じに暗号化して、それをクライアントで受け取る感じにしました。
暗号化形式は、Blowfishを利用しました。

まず、データの暗号化の部分ですが、これはPHPのPEARのCrypt_Blowfishを使いました。

    $filename = 'filename.jpg';
    include_once 'Crypt/Blowfish.php';
    $keyword = 'test';
    $data = file_get_contents($filename);
    $blowfish =& Crypt_Blowfish::factory('ecb', $keyword);
    echo $blowfish->encrypt($data);

こんな感じで適当にファイルを変換してHTTP通信で送信します。(実際は静的化していました)

Flash側は、AS3のライブラリであるAs3Cryptoを使いこんな感じのコードを書きました。ちなみに、暗号化したい対象が画像だったので、Loaderを使っています。

※AS3とかFlex2とかは、僕は、初心者なのでだめだめな感じなので、ソースを公開するのけど、たぶんちゃんとは使えないような気がします。

package jp.comuni.loader{
(中略)
    public function CryptLoader(params: Object)
    {
        this.crypt = getCrypt(params);
    }

    private function getCrypt(params: Object): ICipher        {
        var pad:IPad = new NullPad();
        var key: ByteArray = Hex.toArray(Hex.fromString(params.key));
        var crypt:ICipher =
            Crypto.getCipher('blowfish-ecb', key, pad);
    
        pad.setBlockSize(crypt.getBlockSize());
        if (crypt is IVMode) {
            trace('IVMode');
            var ivmode:IVMode = crypt as IVMode;
            ivmode.IV = Hex.toArray('');
        }
        return crypt;
    }
    
    private function decrypt(data: ByteArray): ByteArray
    {
        crypt.decrypt(data);
        return Hex.toArray(Hex.fromArray(data));
    }
(後略)
}
実際のソース


呼び出し側
    params = {key : 'passcode'} 
    var request:URLRequest=new URLRequest("http://example.com/pathtodata");
    var cryptloader:CryptLoader = new CryptLoader(params);

    cryptloader.loadURL(request);

ざっくりとこんな感じで、暗号化の意味はあんまりないものの、Webサーバ~ブラウザの上で動作するFlashまで一応それっぽい暗号化をするするアプリケーションを作ることができました。

ここらへんまじめに考えると、SSLとか公開鍵方式とかまじめに考えていく必要があるのですが、結局、ほかのことに興味がいってしまい今のところ完成させる気がないのがお恥ずかしい気持ちになりつつ、忘れることにしました。

もし、これを見た誰かがなんらかの成果物をだす参考(暗号化、復号化のサンプルくらいにはなるはず)になれれば、それはそれで、きっとささやかながら、誰かを幸せにできたということなので、それはそれでうれしいかなと思います。

※ はてブにいただいたコメントによると暗号化に対する言葉は復号だということでタイトルを変更させていただきました。ご指摘ありがとうございました。

2007年8月 5日

buttonタグでサブミットするあれこれ
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

CSSでいつも悩まされるのはクロスブラウザですけど、フォームでは特に面倒くさい要素が山盛りですよね。ボタンの文言を動的に変えたいから画像はなるべく使いたくないけど、だからといってブラウザのデフォルトのボタンとか、味気ないですものね。

今日は、フォームにつきもののボタンについて考えてみます。

私たちがボタンに求めるモノって、何でしょう。
  • データを送信(submit)する
  • どのブラウザでも同じように見える
  • 使い回しが聞く
  • ボタンについている文言がどんなに長くなっても、水平方向の長さがフレキシブル
  • 上記のようにサイズ的にフレキシブルであっても、見た目の美しさを阻害しない
  • ボタンの大きさ=クリックできるエリアの大きさ
  • 画像がdiableされていても使用可
  • CSSがdisableされていても使用可
  • ボタンのように見えて実はただのリンクの時のもある

これらの要求を解決してくれる方法が複数出てきているので、まとめてみたいと思います。

共通する鍵は、inputタグの代わりに、buttonタグを使用している点です。

1.今までのようにinputを使用
<input type="submit" value="Submit" />

2.buttonタグを使ってみる
<button type="submit">Submit</button>


この二つの方法は、まったく同じ様にデータを送信して、さらにタブインデックスやアクセスキーもアサインできるし、状況に応じてdisableにすることもできます。 見た目の違いといえば、1の方法だとSafariでデフォルトでつくアクアなデザインが、2ではつかずにFirefoxのような、面白みのないグレーのボタンになること。実はこれが、素敵なデザインのボタンを作るうえで重要な鍵なんです。input type="submit"を使用すると、Safariではアクアなあのボタンイメージを強制されてしまって、例えば
<div class="submitBtn"><input type="submit" value="Submit" /></div>
などとしてsubmitBtnに素敵なスタイルを施してあげても、アクアなボタンが重なってきて邪魔されます。でも、button要素なら大丈夫。Safariでもアクアなボタンは出てきませんから、ほかのブラウザと同じようにスタイルしてあげることができます。

もうひとつ重要な鍵は、button要素では中にほかのHTML要素を入れてあげられることです。

たとえば、
<button type="submit"><img alt="print.png" src="http://labs.unoh.net/print.png" width="16" height="16" />プリント</button>

などとアイコンを入れたりというのも、これで可能になるわけです(全くスタイルしてない状態なのでずれてますが、ご勘弁ください)。

そしてもちろん、CSSや画像がアクティブになっていなくても、buttonタグの行動は変わりません

この特性を応用しているのが、下記の二つのサンプルです。それぞれ画像入りでわかりやすいサンプルを紹介してくれているので、私のほうは手を抜いて、まとめだけにします。

1. 基本編(Particletree)

ボタン自体はシンプルにbackground-colorとborderのみを使い、ボタンアクションの内容に応じて小さなアイコンを乗っける方法です。上のほうに、前述したbutton要素の特性も説明してあります。実際にデータを送信するためのボタンと、リセットなどデータを送信する必要のない場合のリンクと、どちらも同じような見た目にするために、buttonタグとaタグを同様にスタイルしています。

さらにアイコンを挿入することで、Web Applicationで複雑になりがちなフォームアクションを、感覚的にわかりやすく表現することができるのです。

2.応用編

上記を応用して、sliding doorのテクニックでbackground-imageを使用できるようにしたのがこの二つの例。
Alex Griffioen - ここではさらに、ボタンを押したときのあのポチッという感覚を再現するために、:activeを使用しています。
Filament Group - こちらではマウスオーバーしたときに画像が変わるように、:hoverが使用されています。

ちなみに、Alexの例ではaタグが使用されているのですが、もちろんbuttonに置き換えればデータを送信するわけです。ただ、残念ながらIEでは:active、:hoverなどのダイナミック疑似クラスはaタグ以外では有効ではありませんので、ポチッと感やマウスオーバーは犠牲にしなければなりません。

いかがでしたか?お試しください!


----------
8月6日午前1時追記

2.buttonタグを使ってみる
にて、buttonタグを書いたつもりが、
<input type="submit" value="Submit" />
と、1と全く変わらないコードになっていたというなんともマヌケなミスをしていましたので修正しました。

2007年8月 1日

yumのローカルミラーリポジトリを構築する方法
このエントリーをブックマークに追加 このエントリーをlivedoorクリップに追加

naoya です。

フォト蔵などのサービスは、社内にあるサーバ群で運用しています。現在、サービスの規模が成長するにつれて、サーバの台数も約20台強くらいになってきました。

すべてのサーバには、Fedora Core 5がインストールされていて、すべてのサーバにまったく同じパッケージがインストールされています。パッケージの更新には、Fedora Core 5に付属しているyumを使ってすべてのサーバを定期的に更新をしているのですが、yum-fastestmirrorをインストールしている状態でもパッケージの更新に時間がかかるようなってきました。

そこで、一台のサーバにyumのローカルミラーリポジトリを構築してパッケージのダウンロード時間を減らしてみました。今日は、yumのローカルミラーリポジトリを構築する手順を紹介します。

1.必要なパッケージのインストール

yum-utilsとcreaterepoパッケージをインストールします。

# yum -y install yum-utils createrepo

2.リポジトリディレクトリの準備

ローカルミラーリポジトリ用のディレクトリ(例えば、/var/www/html/repos)を用意します。

3.同期用のシェルスクリプトの実行

Fedora repository mirroring script using reposyncにyumのローカルミラーリポジトリを同期するためのシェルスクリプトが紹介されていました。このままだと、Fedora Core5でうまく動作しないこと、最近CentOSの別サーバ群も増えたため、repos_sync.shとして変更しました。

repos_sync.shを使って、Fedora Core 5のアップデートパッケージを同期するには、次のように実行します。

# repos_sync.sh fedora updates

また、repos_sync.shをcronに登録しておけば定期的に更新できて便利です。

4.リポジトリの公開

ローカルミラーリポジトリをHTTPでアクセスできるように公開します。Apacheの設定ファイルに、次の内容を追加します。下記の設定は、ローカルミラーリポジトリのサーバ名をreposとしています。

<VirtualHost * *:443>
    ServerName repos
    DocumentRoot /var/www/html/repos
</VirtualHost>

5.yumの設定変更

それぞれのサーバのyumで参照するミラーをローカルミラーリポジトリに変更します。yumで参照するミラーを変更するとには、/etc/yum.repos.d/*.repoファイルを変更します。例えば、/etc/yum.repos.d/fedora-updates/repoの場合は[updates]セクションのmirrorlistを次のように設定します。その他の*.repoファイルも同じように変更します。

mirrorlist=file:///etc/yum.repos.d/mirrorlist

/etc/yum.repos.d/mirrorlistを次の内容で作成します。

http://repos/repos/fedora/core/5/$ARCH

あとは、他のサーバからyum check-updateを実行して、正しくローカルミラーリポジトリが参照されていることを確認します。

また、社内にあるサーバ群は、社員の間でpermo(パーモ)と呼ばれているのですが、なかなか浸透しません。今、社内でこの名前を浸透させる作戦を模索中ですが、それはまた別の機会に紹介したいと思います。