第4回:twitter の JavaScript Badge をIEで表示するとおかしい件に対応してみる
» tips
» JavaScript» WebService |

|
|

[2007年4月26日 00:18]
twitter 流行ってますね。みなさんも使っていますか?
オレはというと…ポツリポツリと呟いています。
friends は2人しかいません orz
twitter は SNS 的な使い方もできるツールなのですが、SNS よりも遥かにゆるく「低機能」なので自分としては本当にその時のステータスをブログパーツとしてこのブログに貼り付けるために使っています。
で、このブログパーツ(アチラでは Badge と呼びますね)なんですが、twitterには標準で4つの Badge が用意されていてブロガー達に重宝されているようです。内2つは Flash バージョンなんですがデザインが気に食わなかったので JavaScript 版にちょっとテコ入れをして使う事にしました。
・・・ってか写真展示に関する Tip's を公開するスペースじゃなかったのか?ここは。
スミマセン。興味の向くままノープランで書いております(苦笑)
1)IE で Badge を見ると「NaN」とかなっている
badge の 中にある relative_time 関数は「about * hours ago」とか表示してくれるんだけど、IE の場合は JavaScript に問題があって、「NaN days ago」とかなっちゃう。
原因は relative_time 関数内1行目の Date.parse だ。
Date.parse は日付文字列を Date 型にパースしてくれるんだけど、引数で渡す文字列によってはうまく日付として扱ってくれない。しかも、ブラウザによって解釈が違う。
この Badge で relative_time 関数に渡される日付文字列はJSONPから返されているのだけど、こんなフォーマットだ。
"Wed Apr 25 12:35:05 +0000 2007"
これを JavaScript で解釈しやすい下記のフォーマットに変換してみる。
"Apr 25, 2007 12:35:05"
修正は Date.parse の前に下記2行を足すだけ。
function relative_time(time_value) {
time_values = time_value.split(" ");
time_value = time_values[1]+" "+time_values[2]+", "+time_values[5]+" "+time_values[3];
var parsed_date = Date.parse(time_value);1行目では、" "スペースで配列に分解、
2行目では、並び替えをしている。(曜日とミリ秒はいらない)
これで「NaN」は解決しました。
2)9時間ズレてますけど
twitterサーバは米国(?)で UTC 、JavaScriptを動かしているのは日本で JST 、ありがちなネタです。 relative_time 関数で経過秒数である delta 変数の計算のあとに、差分を吸収するためのコードを追加します。
var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
delta = delta + (relative_to.getTimezoneOffset()*60);
getTimezoneOffset()ってのが差分を出してくれる関数。日本だと9時間だから -540 (分)が返る。単位は秒数だから 60 をかけた。
これで修正は終わりです。
一応完成したコードをのせておきます。
<script type="text/javascript">
function relative_time(time_value) {
time_values = time_value.split(" ");
time_value = time_values[1]+" "+time_values[2]+", "+time_values[5]+" "+time_values[3];
var parsed_date = Date.parse(time_value);
var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
delta = delta + (relative_to.getTimezoneOffset()*60);
if(delta < 60) {
return 'less than a minute ago';
} else if(delta < 120) {
return 'about a minute ago';
} else if(delta < (45*60)) {
return (parseInt(delta / 60)).toString() + ' minutes ago';
} else if(delta < (90*60)) {
return 'about an hour ago';
} else if(delta < (24*60*60)) {
return 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago';
} else if(delta < (48*60*60)) {
return '1 day ago';
} else {
return (parseInt(delta / 86400)).toString() + ' days ago';
}
}function twitterCallback(obj) {
var id = obj[0].user.id;
document.getElementById('my_twitter_status').innerHTML = obj[0].text;
document.getElementById('my_twitter_status_time').innerHTML = relative_time(obj[0].created_at);
}
</script>
<span id="my_twitter_status"></span> <span id="my_twitter_status_time"></span>
<script type="text/javascript" src="http://www.twitter.com/statuses/user_timeline/{YourID}.json?callback=twitterCallback&count=1"></script>
関連エントリー
・第6回:TinyURL の遷移先が怖くて開けない場合の対処法
・第5回:twitter の JavaScript Badge を改造する

ヤガー (yager)
はじめまして。
同じ問題を抱えておりましたが、知識不足で自力では修正方法がわからず、ぐぐってこちらの情報にたどり着きました。
おかげさまで無事解決。
どうもありがとうございました。