段々とタグクラウドが遅くなってきたし、元々話題があっちへいったりこっちへいったりするせいで、そもそもタグクラウドとの相性が悪いです。
で、ちゃんとタグの一覧が欲しいなぁと思ったので作りました。
Tumblrのタグの一覧を取得する方法
前にも言いましたが、そんなAPIはないです。何度もリクエストを投げてこっちでマージするしかありません。
GETのパラメータでoffsetを指定すればn件目から取得できるので、再帰的にoffsetだけを増やしたリクエストを投げられればOKです。
最新記事一覧でも使ってるんですが、Tumblr APIコール用のFunctionを作ってしまいます。
function tumblrApiCall(baseUri, onSuccess, onError, onEmpty) {
/// <summary>Tumblrと通信</summary>
/// <param name="baseUri" type="String">URI (GET)</param>
/// <param name="onSuccess" type="Function">成功時処理</param>
/// <param name="onError" type="Function">エラー時処理</param>
/// <param name="onEmpty" type="Function">値なし時処理</param>
/// <returns type="Function" />
return function () {
jQuery.ajax({
type: "GET",
url: baseUri,
dataType: "jsonp",
success: function (data) {
// ステータスコードを見て200以外であればError
if (data.meta.status != 200) {
if (onError != null) onError(data);
return;
}
// postsがなければEmpty
var json = data.response.posts;
if (json == null || json.length <= 0) {
if (onEmpty != null) onEmpty(data);
return;
}
onSuccess(json);
}
});
};
};
あ、ちゃんとvsdoc書くようにしました。なんか上手く読み込まれないこともあるんですが。
Tumblrとの通信に失敗してもステータスコードは必ず200が返って来ます。そのため、返ってきたjsonのmeta.statusプロパティを見てやる必要があります。めんどくさいですね。
後は全記事を取得し終えるまでonSuccess内でtumblrApiCallを呼び出してやるだけです。
TumblingDice.prototype.tagList = function () {
/// <summary>タグ一覧取得</summary>
var baseUri = function (offset) { return "http://api.tumblr.com/v2/blog/" + domain + "/posts/?api_key=" + apiKey + "&offset=" + offset };
var offset = 0;
var tagList = new Array();
var $div = jQuery("#tags");
var onSuccess = function (json) {
// TagをtagListに保存する
json.map(function (x) {
return x.tags
}).forEach(function (tags) {
tags.forEach(function (tag) {
// 既に保存してあるTagの場合はカウントアップする
if (tagList.some(function (x) {
return x.tagName == tag;
})) {
tagList.filter(function (x) {
return x.tagName == tag;
}).forEach(function (x) {
x.count = x.count + 1;
});
} else {
tagList.push({ tagName: tag, count: 1 });
}
});
});
// jsonのlengthが20未満ならばそれ以上データはないのでjQueryでデータを展開する
if (json.length < 20) {
// 名前順にソートする
tagList.sort(function (a, b) {
var x = a.tagName;
var y = b.tagName;
if (x < y) return -1;
if (x > y) return 1;
return 0;
});
$div.find(".loading").remove();
$div.append(createTagList(tagList));
return;
}
// 次の20件を取得しに行く
offset = offset + 20;
tumblrApiCall(baseUri(offset), onSuccess, onError, onEmpty)();
};
var onError = function (data) {
$div.find(".loading").remove();
$div.append($("<p/>").text("Error:" + data.meta.msg));
};
var onEmpty = function (data) {
$div.find(".loading").remove();
if (tagList.length > 0) {
$div.append(createTagList(tagList));
return;
}
$div.append("<p>Empty</p>");
};
tumblrApiCall(baseUri(offset), onSuccess, onError, onEmpty)();
}
function createTagList(tagList) {
/// <summary>タグ一覧作成</summary>
/// <param name="tagList" type="Array">タグ一覧情報</param>
/// <returns type="jQuery" />
var $ul = jQuery("<ul/>").attr({ id: "tag-list" });
var $a = jQuery("<a/>");
var $li = jQuery("<li/>").attr("class", "tag-link");
for (var i = 0; i < tagList.length; i++) {
var x = tagList[i];
var $tagLink = $a.clone()
.attr({ href: "http://" + domain + "/tagged/" + x.tagName })
.text(x.tagName + " (" + x.count + ")");
$ul.append($li.clone().append($tagLink));
}
return $ul;
}
本当はちゃんとキャッシュ用のクラスを作ったので読み込み終わった後にそこに突っ込んでるんですが、そっちの説明は面倒なので削除してます。