アーカイブ
Tyzohブログ - ikarashiさんのエントリ
 ikarashiさんのエントリ配信

2007/06/20
[Secure-SBM:015] ブックマーク登録(1)

執筆者: ikarashi (3:24 pm)
こんにちは,五十嵐です.ソーシャル・ブックマークの心臓部分,ブックマークの登録部分を作っていきます.

ブックマークを登録する際には URL の他にタイトルを取得できると便利です.もちろん,タイトルが適切に付いていないページもありますので,自分で編集できることも条件になります.表示しているページをボタンひとつでブックマークできれば便利ですが,それは段階を追って,いずれ作ることにして,ここでは手で URL を入力して,そのページのタイトルを取得し,必要があればタイトルを編集した後,登録するという手順で作業できるようにします.これらが /personal のページで操作可能とします.
右図のように DHTML と非同期通信を使用した Ajax で,ページの切り替えをおこなわなくて済むようにデザインします.

詳細は省略しますが,ssbm.js にクロスブラウザ(複数のブラウザ対応)用の関数 _XMLHttpRequest を追加しました.
続いて,personal_center.tt に入力フォームと javascript を設定します.
root/template/personal/personal_center.tt フォーム部分:
<h2>ブックマーク登録</h2>
<form method="POST" action="/registbookmark"
        id="registbookmarkform" name="registbookmarkform">
<input type="button"
        id="bookmark_gettitle" name="bookmark_gettitle" value="タイトル取得">
<input type="reset"
        id="bookmark_reset" name="bookmark_reset" value="リセット">
<input type="submit"
        id="bookmark_submit" name="bookmark_submit" value="登録">
<table width="100%" border="0">
<tr><td>タイトル:</td>
        <td>
        <input type="text" size="40"
        id="bookmark_title" name="bookmark_title" value="no title"></td>
        </tr>
<tr><td>URL:</td>
        <td>
        <input type="text" size="40"
            id="bookmark_url" name="bookmark_url" value=""></td>
        </tr>
<tr><td>タグ:</td>
        <td>
        <input type="text" size="40"
            id="bookmark_tags" name="bookmark_tags" value=""></td>
        </tr>
<tr><td>コメント:</td>
        <td>
        <input type="text" size="40"
            id="bookmark_comment" name="bookmark_comment" value=""></td>
        </tr>
</table>
</form>

javascript の部分:
var httpObject;
var timer_id;
var timeout_sec = 10;

function checkTimeout(){
        if( --timeout_sec <= 0 ){
                clearInterval( timer_id );
                httpObject.abort();
                alert( 'Timeout' );
                return false;
        }
}

function requestTitle( url, func ){
        httpObject = _XMLHttpRequest();
        if( ! httpObject ){
                alert('お使いのブラウザには対応していません.');
                return false;
        }
        timer_id = setInterval( 'checkTimeout()', 1000 );
        httpObject.open( 'GET', '/gettitle?bookmark_title=' + url, true );
        httpObject.onreadystatechange = function () {
                if( httpObject.readyState == 4 ){
                        clearInterval( timer_id );
                        if( httpObject.status == 200 ){
                                func( httpObject.responseText );
                        }else{
                                alert( httpObject.readyState + ':' 
                                    + httpObject.status + ':' 
                                    + httpObject.statusText );
                                return false;
                        }
                }
        }
        httpObject.send('');
}

function getTitle( url ){
        if( url == "" ){
                return;
        }
        var funcRef = function ( title ) {
                var newtitle = title;
                if( newtitle == '__no_title__' ){
                        newtitle = 'no title';
                }
                _getElementById('bookmark_title').value = newtitle;
        }
        requestTitle( url, funcRef );
}

document.registbookmarkform.bookmark_gettitle.onclick = function(){
        var url = document.registbookmarkform.bookmark_url.value;
        if( url == "" ){
                alert( 'URL を入力してください.' );
                return false;
        }
        getTitle( url );
}
httpObject.onreadystatechange へ設定した匿名関数の中で,"this" を使いたかったのですが,firefox では動かなかったので,httpObject をそのまま使用しました.W3C のサンプルには,"this" で記述されているのですが... ( 「The XMLHttpRequest Object」 (W3C) 参照)

サーバ側の '/gettitle' のコードを追加します.LWP::Simple::get() を使用して,指定された URL にアクセスし,タイトルを取得します.
lib/SecureSBM/Controller/Personal.pm
sub _gettitle : Private {
    my $url = shift;
    my $title = ''; 

    if( my $content = LWP::Simple::get( $url ) ){
        my ( $tmpt ) = $content =~ m{<title>([^<]*)</title>}i;
        $title = Jcode::jcode($tmpt)->utf8;
    }
    return $title;
}

sub gettitle : Path('/gettitle') {
    my ( $self, $c ) = @_; 
    my $url = $c->req->param('bookmark_title');
    my $title = ''; 

    if( $title = _getBookmarkTitle( $c, $url ) ){
        $c->log->debug('*** already url exists ');
        $c->res->body( $title );
        return 1;
    }   

    $title = _gettitle( $url );

    if( $title eq '' ){
        $title = '__no_title__';
    }
    $c->res->body( $title );
}
_getBookmarkTitle() でブックマークが既に登録されているかどうかを確認しています.body に空文字が設定されると,end アクションでテンプレートが呼ばれてしまうので,'__no_title__' という文字を入れて回避しています.javascript 側でも '__no_title__' という文字を受け取った場合の処理を行っています.

次回は "/registbookmark" のアクションを lib/SecureSBM/Controller/Personal.pm に追加します.今回もだいぶ長くなってしまったので,コードは次回以降にしますが,ブックマークは他の人とも共有しますので,既に存在している場合に注意しなければなりません.

2007/03/27 記

参考:

Keyword: Perl Catalyst Secure-SBM SSBM セキュア・ソーシャル・ブックマーク
ikarashiさんのブログを読む | コメント (0) | トラックバック数 (0) | 閲覧数 (3333)
Trackback is not accepted now.
印刷用ページ 友達に送る
 
投稿された内容の著作権はコメントの投稿者に帰属します。
サイト内検索
ブログ カレンダー
«  «  2008 3月  »  »
24 25 26 27 28 29 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5