Flickr から画像を選択するスクリプト for a-blog cms

Flickrの画像を選んで、各サイズのURLを要素に代入する



だけのスクリプトのはずなのに、思ったより手間がかかった。スタバで電源の続く限りで、スクリプトを書き殴ってきました。

※ 2010-10-29 18:32頃、掲載スクリプトを多少まともに書き直しました。スタイルも変更されています。HTMLに変更はないので、JSとCSSの貼り替えのみで対応します。

生き返れ画像URLユニット

a-blog cmsの画像URLユニットの使い勝手が不親切なままで、気にはなっていたのですが、ようやっと着手した次第。もっと他にやるべきことがあるとか思わないでもない。手が付いたが先ということで。

そんなわけで、Flickrから画像URLを黙々とコピペするのが辛くなってきた人の為の機能です。とりあえず動きます。スクリプトが冗長な気がするのでリファクタリングせんと。

今回は全体が長めのエントリーです。

  • 機能の動作フローの説明(スクリーンショットつき)
  • 今の時点で動作させるための説明とコード
  • コピペ用のスクリプト本体

余談ですが、このエントリーを書いている最中に、ロリポップの障害(DDos攻撃?)で、画像をアップロードできなくなりました。(通常アクセスも激重)せっかくなので、Skitchで撮ったキャプチャを、直接Flickrにアップロードしてから、今回の機能で挿入してみたら何とも便利! デジカメはEye-fiから、iPhoneはAppから、PCのキャプチャはSkitchから、全てFlickrに直送できるはず。イイかも。

こんな感じ的な動作フローと画面紹介


1. まずはクリック


クリックして起動

ユニット内のリンクをクリックすると、次のスクリーンショットのようなウインドウが開きます。

カスタマイズすれば、検索対象のユーザーを選択式にしたり、検索ワードを指定したり、クリエイティブコモンズに絞り込んだりできる。


2. サムネイルから画像を選択


画像を選択

サムネイルがずらずらと表示されるので、ここから好きな画像をクリックして選択します。

今のところ新しい順に100件しか表示されないので、もうちょっと頑張ってページャーも実装しないといけない。あと、認証までサポートしてないのでpublicな画像しか表示されません。


3. サイズを標準・拡大でそれぞれ選択して挿入


サイズを選択

写真の元サイズによってMediumやLargeのサイズ感が大幅に異なるため選択式にしてます。その画像が保持しているサイズを別途、APIから取得しているので、選択肢は画像ごとに異なります。

本当はサイズも勝手に判定して、もっと手数少なくお手軽に動作させたかった。


せっかちさん用の導入方法

そんな感じで使える今回の機能ですが、むっつりと自分だけ使っていると怒られるので、情報とコードはシェアしておきたいと思います。

/themes/system/admin/entry/column.html 200行目付近を編集

下記コードを参考にハイライトされている行を追記すればOK。実質、entryFormColumnSettingTable内に、class="js-quick_select"とrel属性に、対象のNSIDが入ったa要素があればオッケー。

<!-- BEGIN eximage -->
<table class="entryFormColumnSettingTable"><!-- BEGIN preview:veil -->
    <tr>
        <th>プレビュー&nbsp;</th>
        <td><a href="{normal}" rel="highslide"><img src="{normal}" width="90" height="" alt="プレビュー" /></a></td>
    </tr><!-- END preview:veil -->
    <tr>
        <th>Flickr参照&nbsp;</th>
        <td><a href="#" class="js-quick_select" rel="自分のFlickrのNSIDを入れる">自分のPhotostreamから選択</a></td>
    </tr>
    <tr>
        <th>標準画像&nbsp;</th>
        <td><input type="text" name="eximage_normal_{id}" size="45" value="{normal}" /></td>
    </tr>
    <tr>
        <th>拡大画像&nbsp;</th>
        <td><input type="text" name="eximage_large_{id}" size="45" value="{large}" /></td>
    </tr>

見栄え用のCSSを追記する

見栄え調整オンリーのCSSなので、適宜修正してください。自分が作りながら書いた分を参考程度に載せておきます。

#js-flickr-thumbnail_box,
.js-flickr-size_box {
    width: 530px;
    height: 360px;
    padding: 10px;
    font-size: 13px;
    background-color: #ffffff;
    border: 1px solid gray;
    -webkit-border-radius: 7px;
    -moz-border-radius: 7px;
    border-radius: 7px;
    -webkit-box-shadow: 1px 1px 3px rgba(0,0,0,0.3);
    -moz-box-shadow: 1px 1px 3px rgba(0,0,0,0.3);
    box-shadow: 1px 1px 3px rgba(0,0,0,0.3);
    overflow: auto;
    text-align: center;
}
.js-flickr-size_box {
    height: 530px;
}

.js-flickr-thumbnail_item {
    float: left;
    margin: 5px;
    cursor: pointer;
}

.js-flickr-size_box-table {
    width: 480px;
    margin: 10px auto;
    border-collapse: collapse;
}
.js-flickr-size_box-table tr {
    border-bottom: 1px solid #999;
}
js-flickr-size_box-table tr th {
    padding: 5px;
    background-color: #f0f0f0;
    text-align: center;
}
.js-flickr-size_box-table tr td {
    padding: 5px 20px;
}

スクリプトが読み込まれるようにする

外部ファイルにしてもいいですし、script要素に貼ってもよいのですが、とにかくエントリー編集画面で、このエントリーの最後にある長いスクリプトが読み込まれるようにします。

テンプレートの編集と、スクリプトの挿入さえすれば、きっと動くはず。PHPは触っていないので、テーマディレクトリ内の作業で収まります。

標準化できるように整理して、製品版にも組み込まれると嬉しい人もいるかもしれませんね。Flickrからの画像取得って、なんともブログ的機能な気もしますけど...。

動作検証にランチ写真載せてみたり。おいしかった。


和風マッシュポテト

あわびの蒸し焼き

和牛すきやき


付録 とりあえず(たぶん)動くスクリプト

以下のスクリプトが、エントリー編集画面で実行されるようにしてください。手っ取り早いのはTouch_Editで囲って、ドキュメント内にscript要素にコピペしちゃうことかも。

$(function()
{
    /**
     * Flickr API Key and some parameter
     */
    var flickr_api_key              = '自分のAPIキーを入れてね',
        quick_select_wrapper        = '.entryFormColumnSettingTable',
        quick_select_target_normal  = 'input[name^="eximage_normal"]',
        quick_select_target_large   = 'input[name^="eximage_large"]',
        quick_select_show           = function($elm)
        {
            $elm.show().position({
                'of'    : window,
                'my'    : 'center center',
                'at'    : 'center center'
            });
        };

    /**
     * Quick Select from Thumbnails
     */
    $('.js-quick_select').live('click', function()
    {
        var user_id = this.rel,
            $parent = $(this).parents().filter(quick_select_wrapper).get(0);

        if ( document.getElementById('js-flickr-thumbnail_box') != null )
        {
            var $thumbBox = $('#js-flickr-thumbnail_box');

            // show
            quick_select_show($thumbBox);

            // memory
            $.data($thumbBox.get(0), 'parent-target', $parent);
        }
        else
        {
            var $thumbBox = $('<div id="js-flickr-thumbnail_box" />').appendTo('body');

            $.ajax({
                type    : 'GET',
                url     : 'http://api.flickr.com/services/rest/',
                data    : {
                    format  : 'json',
                    user_id : user_id,
                    api_key : flickr_api_key,
                    method  : 'flickr.photos.search'
                },
                dataType: 'jsonp',
                jsonp   : 'jsoncallback',
                success : function(json)
                {
                    $('#js-flickr-thumbnail_box').hide();

                    // append thumbnails
                    var photos  = json.photos.photo,
                        i       = 0,
                        iz      = photos.length;

                    for ( ; i < iz; i++ ) {
                        var photo = photos[i],
                            thumb = 'http://farm'+photo.farm+'.static.flickr.com/'+photo.server+'/'+photo.id+'_'+photo.secret+'_s.jpg';

                        var $cont = $('<div class="js-flickr-thumbnail_item" id="'+photo.id+'">'+
                                          '<img src="'+thumb+'" alt="'+photo.title+'" />'+
                                      '</div>').appendTo($thumbBox);
                    }

                    // show
                    quick_select_show($thumbBox);

                    // memory
                    $.data($thumbBox.get(0), 'parent-target', $parent);
                }
            });
        }

        // event
        $(document).unbind('click.thumbBox');
        $(document).bind('click.thumbBox', function ( )
        {
            $thumbBox.hide();
            $(document).unbind('click.thumbBox');
        });
        return false;
    });

    $('.js-flickr-thumbnail_item').live('click', function()
    {
        var photo_id = this.id,
            src      = $('img', this).attr('src').replace(/_s\./, '_m.'),
            thumbnail= '<img src="' + src + '" />',
            sizebox_id = 'js-flickr-size_box'+photo_id,
            $parent = $($.data($('#js-flickr-thumbnail_box').get(0), 'parent-target')),
            $normal = $(quick_select_target_normal, $parent),
            $large  = $(quick_select_target_large,  $parent);

        if ( document.getElementById(sizebox_id) != null )
        {
            $('#js-flickr-thumbnail_box').hide();

            var $sizeBox = $('#'+sizebox_id);

            // show
            quick_select_show($sizeBox);
        }
        else
        {
            var $sizeBox = $('<div id="'+ sizebox_id +'" class="js-flickr-size_box">'+
                                '<form>'+
                                    '<table class="js-flickr-size_box-table">'+
                                        '<tr><th>サイズ名</th><th>標準</th><th>拡大</th></tr>'+
                                    '</table>'+
                                    '<input type="button" name="insert" value="Insert" />&nbsp;'+
                                    '<input type="button" name="cancel" value="cancel" />'+
                                '</form>'+
                              '</div>').appendTo('body');

            $.ajax({
                type    : 'GET',
                url     : 'http://api.flickr.com/services/rest/',
                data    : {
                    format  : 'json',
                    photo_id : photo_id,
                    api_key : flickr_api_key,
                    method  : 'flickr.photos.getSizes'
                },
                dataType: 'jsonp',
                jsonp   : 'jsoncallback',
                success : function(json)
                {
                    $sizeBox.prepend(thumbnail);

                    // append selects;
                    var sizes   = json.sizes.size,
                        i       = 0,
                        iz      = sizes.length;

                    for ( ; i < iz; i++ ) {
                        var size = sizes[i];
                        $('table', $sizeBox).append('<tr>'+
                                                        '<th>'+size.label+' ( '+size.width+' × '+size.height+ ')</th>'+
                                                        '<td><input type="radio" name="normal" value="'+size.source+'" /></td>'+
                                                        '<td><input type="radio" name="large" value="'+size.source+'" /></td>'+
                                                    '</tr>');
                    }

                    // show
                    quick_select_show($sizeBox);

                    // event
                    $('[name="insert"]', $sizeBox).click(function()
                    {
                        $normal.val($('input[name="normal"]:checked', $sizeBox).val());
                        $large.val($('input[name="large"]:checked', $sizeBox).val());
                        $sizeBox.hide();
                    });
                    $('[name="cancel"]', $sizeBox).click(function()
                    {
                        $sizeBox.hide();
                    });
                }
            });
        }

        return false;
    });
});