Born Neet
- The Emotional Programmer -
| Next Entry … j | Prev Entry … k |
| Next Page … J(Shift + j) | Prev Page … K(Shift + k) |
| Scroll Down … Space / Page Down | |
| Scroll Up … Shift + Space / Page Up | |
っというわけで、TwitterからWassrに乗り換えてみました。
まぁTwitter自体全然使ってないですけどねー。
(そもそもSNSっていうかコミュニケーションが苦手っていう…)
で、せっかくAPIも公開されてることなので、今までTwitterの発言を表示してた部分にWassrの発言を表示するようにしました。
興味のある人はどうぞー。
[html, css]
今回は(面倒なので)html、cssに変更を加えないのがテーマ(?)だったため、
<div id="twitter_div"><dl><dt><a href="http://wassr.jp/user/tnantoka/" id="twitter-link"><img src="http://file.blog.bornneet.com/wassr_bubble_logo.png" alt="Wassr: Do you follow me?" /></a></dt><dd><ul id="twitter_update_list"></ul></dd></dl></div>
と、ほぼ前のままでOKです。
(画像とリンクをWassrにしただけ。cssは変更なし)
[js]
WassrはJSONPに対応してるので、
<script type="text/javascript" stc="http://api.wassr.jp/statuses/show.json?id=tnantoka&callback=wassrCallback"></script>
とかやれば、
wassrCallback([{
"link":"http://wassr.jp/user/tnantoka/statuses/e6wr6C1Ebz",
"epoch":1215324666,
"user_login_id":"tnantoka",
"areacode":null,
"rid":"e6wr6C1Ebz",
"photo_url":null,
"reply_message":null,
"photo_thumbnail_url":null,
"reply_user_nick":null,
"html":"テスト",
"reply_status_url":null,
"text":"テスト",
"user":{"screen_name":"t*"},
"slurl":null,
"areaname":null
}]);
ってな感じに、発言のオブジェクトをコールバック関数に渡して呼び出してくれます。
あとはTwitterのjs等を参考に、
function wassrCallback(wassrs) {
document.getElementById('twitter_update_list').innerHTML = '<li><span>'+wassrs[0].text+'</span> <a style="font-size:85%" href="'+wassrs[0].link+'">'+parseEpoch(wassrs[0].epoch)+'</a></li>' + '<li style="text-align: right; margin-top: 5px; font-size: 85%;"><a href="http://twitter.com/tnantoka">Twitter\u306F\u3053\u3061\u3089</a></li>';
}
function parseEpoch(epoch) {
var pass = new Date / 1000 - epoch;
var s;
if (pass < 60) {
s = 'less than a minute ago';
} else if (pass < (60 * 2)) {
s = 'about a minute ago';
} else if (pass < (60 * 60)) {
s = 'about ' + parseInt(pass / 60) + ' minutes ago';
} else if (pass < (120 * 60)) {
s = 'about an hour ago';
} else if (pass < (24 * 60 * 60)) {
s = 'about ' + parseInt(pass / (60 * 60)) + ' hours ago';
} else if (pass < (48 * 60 * 60)) {
s = '1 day ago';
} else {
s = parseInt(pass / (24 * 60 * 60)) + ' days ago';
}
return s;
}
みたいな関数を用意しておけばいいだけです。
(画像、js、htmlをTwitterのバッジからそのまま流用しちゃってるので、一応Twitterへのリンクを入れておきました^^)
[まとめ]
以上でーす。
テストとか全然してないので不具合とかあったらごめんなさい(>_<)
Fastladder(or livedoor Reader)を使ってる人にはおなじみの棒人間ローダ。
かわいいですよねー。
で、せっかくオープンソースなんだから、ということでやってみました。
これです↓

[やったこと]
ダウンロード
まずは、Fastladderのソースを取ってきます。
Subversion(svn)が必要です。(※)
Trac Lightningなら、pythonまでついて来ていいですよ。
(これでハッカーの仲間入り!?)
svnさえ入れちゃえばあとは簡単です。
コマンドプロンプトを起動して、保存したいディレクトリに移動。
cd ディレクトリパス
ですね。(知ってるって?いや、一応ね…)
そして、fastladder - Google Codeにしたがって、
svn checkout http://fastladder.googlecode.com/svn/trunk/ fastladder-read-only
と入力&Enterすれば、自動的にダウンロード(チェックアウト)されます。
(-read-onlyは書かなくてもいいっぽいですね)
※ と思ってたらFastladder Open Source / Free DownloadからUnix版をダウンロードすればいいだけでした^^;
まぁ最新のソースはsvnがないとダメってことで(笑)
ソースを見る
ソースは無事手に入れましたが、どうやって棒人間を操ってるのかイマイチわかりません…ということにします。
ここで役に立つのがWeb Developer。
「枠表示」→「マウスカーソルの個所を枠で囲う」とやれば、棒人間の情報を教えてくれます。
こんな風に。
というわけで、棒人間はloadiconというid(#)を持つらしいことがわかりました。
ここまでくれば楽勝です。
Devas等で、*.jsファイル内の"loadicon"を検索すれば、わんさかヒットします。
とまぁ、なんだかんだで見つけ出して、ごにょごにょしたソースがこちら。
/**
* original: http://fastladder.org/
*
* fastladder/public/js/reader_main.js
* 3272~
*/
var LoadEffect = {
// ICON_PATH : "/img/icon/",
ICON_PATH : "http://file.blog.bornneet.com/",
LOADICON_NUM : 1,
RESTICON_NUM : 3,
Start : function(){
var L = LoadEffect;
var path = L.ICON_PATH;
if(L.LOADICON_NUM > 1){
// var n = 1 + Math.floor(Math.rand(L.LOADICON_NUM));
var n = 1 + Math.floor(Math.random() * L.LOADICON_NUM);
path += "loading" + n + ".gif";
} else {
path += "loading.gif";
}
// $("loadicon").src = path;
document.getElementById("loadicon").src = path;
// setStyle("loading",{visibility:"visible"})
// document.getElementById("loadicon").style.visibility = 'Visible';
},
Stop : function(){
var L = LoadEffect;
var path = L.ICON_PATH;
if(L.RESTICON_NUM > 1){
// var n = 1 + Math.floor(Math.rand(L.RESTICON_NUM));
var n = 1 + Math.floor(Math.random() * L.RESTICON_NUM);
path += "rest" + n + ".gif";
} else {
path += "rest.gif";
}
// $("loadicon").src = path;
document.getElementById("loadicon").src = path;
}
};
fastladder/public/js/reader_main.jsの3272行目~ほぼそのままです。
(fl_aio.jsにもありますが、そっちは全ソースをまとめてあるだけのファイルっぽいのでreader_main.jsから引用してます)
Fastladder内の関数に依存する部分は変更しました。
($、setStyle、Math.randの3つです。setStyle部分は特に(僕は)いらなかったので変更後のソースもコメントアウトしてます)
あと、pathは自分が画像ファイルを置くパスに変更する必要があります。
画像を探す
最後に、画像をどうにかすれば完了です。
Firefoxなら画像上で右クリックすると、「画像の表示」とか「URLのコピー」があるので、URLを知ることができます。
その方法でバテている棒人間(上の画面キャプチャで表示されています)を調べると、「rest1.gif」という画像名でした。
そして、fastladderフォルダ内を"rest1.gif"で検索すると、public/img/iconに格納されていることがわかりました。
さらに、ソースと見比べつつ画像を物色した結果、どうやら、

の4種類が使われているようです。
これらを、pathに設定したところに置けば無事動くはずです。
お疲れ様でした!
[ブログに使う]
…これだけで終わるとホントに「抜き出し」ただけなのでなんかやってみましょう。
ということで、このブログに張ってみました。
(右上のキーボードアイコンの左横です。わかりにくい説明…)
これまでの手順よりさらに簡単ですので、皆さんのブログにもどうですか?
やり方は以下のとおりです。
予め、上の4種類の画像をアップロードしておきます。
次に、
<img id="loadicon" src="http://file.blog.bornneet.com/loading.gif" />
とかいうimgタグをiconを表示したいところに書きます。
そして、下のような手抜きスクリプト
var stopLoadIcon = function(id) {
var path = 'http://file.blog.bornneet.com/';
var RESTICON_NUM = 3
var n = Math.ceil(Math.random() * RESTICON_NUM);
var src = path + "rest" + n + ".gif";
document.getElementById(id).src = src;
}
をどこかで読み込んで or 書いておきます。
さらに、ページで実行されるjsの最後っぽいところで、
stopLoadIcon('loadicon');
と呼び出せばOKです。
これでローディング中の読者のイライラが少しは軽減されるかもしれません。
いつも重くてすいませんm(_ _)m
[心配ごと]
いくらオープンソースとはいえ、画像のみ(ほぼそう言えるでしょう)を抽出して使っちゃっていいものか。
まぁ、OSSライセンスの中でも特に緩い部類に入る(と僕は理解している)MITだし、大丈夫!
…なはず(>_<)
[忘れたこと]
あっ!吹き出し系の処理も一緒に抜き出そうと思って忘れてた…。
えーと…いつかやるかもです。
っぽいタイトルにしてみました。
釣りと言われたら否定できませんm(_ _)m
では、本題。
昨日の記事を書くために改めてクロージャについて調べてみたんですが、
昨年後半からかなりの数の記事が書かれてることに今さら気づきました。
2007~8年はクロージャ入門記事が豊作だったようですね。
何かありましたっけ?
やっぱり、JavaScript 第5版の出版の影響で理解できた人が増えたりしてるんでしょうか。
何はともあれ、僕が悩みまくって「これはひどい」な記事を書いてた頃より、さらに学びやすくなってると思います。
(この時はなぜか今回あげた記事を全て見逃していました…)
ってことで一度断念した人も、
Cでいうならポインタ!
ギターでいうならF!!
(初心者にとって大きな壁になるという意味でね)
なJavaScriptのクロージャに再挑戦してみませんか。
以下ただのまとめです。
(2007年以降の記事に絞ってみました…つもりです、古いのまざってたらごめんなさい)
Core JavaScript 1.5 Guide:Working with Closures - MDC
基本的にこれで十分だと思います。
さすが(唯一といってもいい)まともなJSリファレンスを提供してくれてるMDC。
こんなの読んでもわからない?
そうですか、そうですよね。
ならお次は、@ITなんてどうですか?
第3回 変数の宣言とスコープ - @IT
まだまだあります。
nothing but ordinary - JavaScript はじめてのクロージャ入門
クロージャを利用しながらひとつのプログラムを作っていく感じがステキです。
JavaScriptでのクロージャの使い方
ループで犯すミスをわかりやすく解説。
JavaScript クロージャとレキシカルスコープ - Backstage of theater.js
説明が丁寧です。
さっきから何か小難しいんですけど!!
すいません…。
ならこの辺はどうですか?
短いし読みやすいですよ。
あるSEのつぶやき: JavaScriptのクロージャー
Haida's weblog: クロージャ
なんとなくわかってきた気もするけど…。
やっぱ動きがないとイメージ湧かないですよね。
僕もそうです。
この辺は実行できるサンプルがありますよ。
func09 ≫ JavaScript、クロージャをおさらいしてみる
[ヅラド] [JavaScript]クロージャとイベントのサンプル 3種類 5パターン
Bugle Diary: [javascript]クロージャについて
動画もあります。
Web/JavaScript 講習会 part.7 (this, スコープと環境、クロージャ)
スライドも。
JavaScript勉強会
っていうか文系だからわかんないって!?
奇遇ですね、僕もド文型です。
では、読み物風のこちらをどうぞ。
Life is beautiful: Javascriptの黒魔術=クロージャを宮沢賢治風に説明してみる
クイズもあります。
Life is beautiful: Javascriptクイズ(中級者向け):無名関数と実行効率の話
Life is beautiful: Javascript、クロージャを使ったプライベート関数の隠蔽について
以上、ふざけ半分でまとめてみました。
ここにあげたのはごく一部で、まだまだあります。
軽く検索しただけでも30件以上はありました。
JavaScript クロージャ - Google 検索
Yahoo!検索 - JavaScript クロージャ
で探してみてください。
かなりの数の記事がひしめき合ってますので、フィーリングにあう記事が見つかるかもしれませんよ。
※ 超長文注意!
動的スクリプトローディング(さんざん既出だと思うけど - IT戦記が、さっぱりわかんなくて凹んだ。
でも、いろいろとJSのエッセンスが詰まってそうな気がしたので、頑張って読んでみた。
で、一応わかったつもりにはなれたので説明してみる。
(駄文だけど僕と同じレベルの人にはもしかしたら役に立つかもしれません)
非常に長いですが、よろしければどうぞ。
では、早速始めます。
[引用]
まずは、全体を引用。
(コピーしにくいように一応行番号を入れてます。使わせてもらうなら、せめて本家を訪問するのが礼儀かと。)
1: var load = function(src, check, next) { 2: check = new Function('return !!(' + check + ')'); 3: if (!check()) { 4: var script = document.createElement('script') 5: script.src = src; 6: document.body.appendChild(script); 7: setTimeout(function() { 8: if (!check()) setTimeout(arguments.callee, 100); 9: else next(); 10: }, 100); 11: } 12: else next(); 13: };
はい、さっぱりわかりませんね(>_<)
僕もそうでした(す?)。
ってことでこれから、1行ずつ見ていきまーす。
(全ての行を解説します。bornnnetbornneetは初心者を見捨てません!)
[はじめに]
(一応説明)この「関数は外部jsファイルを読み込んで、ロードが完了するのを待った後、指定の関数を実行する」というものです。
(説明が下手ですいません)
実際に使っている場面を想定したほうが(僕は)わかりやすいので、以下の解説では、jQueryを読み込んだ後、alertでバージョンを表示するという体で話を進めます。
つまり、
load(
'http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js',
'window.jQuery',
function() { alert($.fn.jquery); }
);
という呼び出しをしているってことです。 jQueryはAJAX Libraries APIから読み込んでいます。
[本題]
前置きがかなり長くなりましたが、コードリーディング(1回言ってみたかった!)に入ります。
1, 13行目
1: var load = function(src, check, next) {
13: };
1(~13)行目では、外部jsのロードを行う無名関数を定義して、loadという変数に代入しています。
引数は3つで、それぞれの意味は
| src | 外部jsのURLやパス |
|---|---|
| check | 読み込み完了を判断するために、存在の有無を確認するオブジェクト |
| next | 完了後に実行したい関数 |
となっています。
わかりにくいのは、checkですね^^
この関数では、外部jsの読み込み完了を判断する必要がありますが、JSにはそんな機能はありません。
(っていうか外部ファイルのロード自体もHTMLを利用して実現してるぐらいです)
ただ、多くのjsファイル(ライブラリは特に)読み込まれるとグローバル領域に何かしらのオブジェクトを作ります。
なので、そのオブジェクトの有無をチェックすることで、外部jsのロード完了をしろうというわけです。
jQueryだと、window.jQueryがそのオブジェクトになります。(window.はグローバルを示します)
function load(src, check, next) {
}
と書かないのは、前者の方が汎用性が高いためだと思われます。
if文等ブロック内に書けたりとかするので。
(function文だと関数の中に書けないからこっちの形にしてるんだと思ったけど、今回調べてみたらそんな情報は見当たらなかったので勘違いだったみたい)
あと、コピペして使うことを考えるとfunction式にしてた方が使い勝手がいいとか、単にスマートでカッコいいとかの理由で僕もこの方が好きです。
2行目
2: check = new Function('return !!(' + check + ')');
2行目はけっこう重要です。
処理としては、引数のcheckで指定されたオブジェクトがグローバル領域に存在するかどうかをチェックする関数を作成して、checkに代入するということをしています。
まず、!!ですが、これはオブジェクトの有無をbooleanに変換するテクニックです。
また、()で括っているので、引数checkの内容を確実に式として評価することができます。
こうすることで、オブジェクトがあるならtrue、ないならfalseという結果を得られます。
evalを使っても同じことができますが、この方が簡単です。
また、window[check]とかだとメソッドまで確認することができないので、やはりこの方法がいいんでしょう。
そして、Functionコンストラクタで定義された関数のスコープはグローバルになるので、グローバル領域に指定のオブジェクトがあるかどうかを知ることができます。
つまり、今回の例だと、
function() {
return !!(window.jQuery);
}
という関数をグローバルに作ったイメージです。
さらに、この関数はここで実行されるわけではなく、checkという変数に代入されるので、setTimeoutに渡す無名関数の中でも使うことができるのです。(詳細後述)
3, 12行目
3: if (!check()) {
12: else next();
ここは簡単です!
3行目では、さっき作った関数を呼び出して、既にその外部jsが読み込まれていないかを確認します。
指定のオブジェクトがあった場合は、12行目に飛び、実行したい処理を行なって、このload関数は終了します。
4~6行目
4: var script = document.createElement('script')
5: script.src = src;
6: document.body.appendChild(script);
ここも特に難しくありません。
body要素に新しいscript要素を追加することで、外部jsを読み込みます。
今回の場合、
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
という要素が追加されることになります。
いよいよメイン!7~10行目
7: setTimeout(function() {
8: if (!check()) setTimeout(arguments.callee, 100);
9: else next();
10: }, 100);
ここが一番重要&難しいところだと思います。
まず、7行目と10行目では、setTimeoutを使って、渡した無名関数を100ミリ秒後に実行する、という指定を行っています。
そして肝心なのは、その無名関数です。
8行目前半のif文では、2行目で作った関数を呼び出しています。
先ほども書きましたが、無名関数の中では宣言されていないcheckという変数を使っています。
JavaScriptでは、親関数(エンクロージャ)の中で宣言した変数(レキシカル変数)は、その中で作られた関数(クロージャ)からずっと参照することができます。(親関数の実行が終わってもなくなりません)
そのため、ここでもcheck()とすることで、指定オブジェクトの有無を確認する関数を呼び出すことができるのです。
(クロージャの実用的な使い方ですね!)
順番が前後しますが、9行目は外部jsが読み込まれた場合の処理で、実行したい関数を呼び出しています。
このnextも親関数の中で引数として宣言されているので、ここで使用することができます。
ラストスパート!!
長々と説明してきましたが、8行目後半を説明すればおしまいです。(あとちょっと耐えてください)
ここはcheck()がfalseなら、つまり、まだ指定オブジェクトが存在しない場合に実行される処理です。
さっきと同じようにsetTimeout関数を使っているので、100ミリ秒後にarguments.calleeという怪しいものを実行しようという意味になります。
arguments.calleeは、実行中の関数自身を参照しています。
ここで注意ですが、実行中の関数自身とは、load関数ではなく7行目でsetTimeoutに渡されている無名関数のことです。
したがって、check()がtrueを返すまで、100ミリ秒毎に指定オブジェクトの有無をチェックするという処理を繰り返すことができるのです。
そして!外部jsファイルの読み込みが完了すれば、先ほど説明した9行目が実行されて、

と、表示された後、無事この関数の役目は終了となります。
[おわりに]
以上、僕はこんな風に考えてます。
JS勉強中の同士のお役に立てれば幸いです。
(理解が足りないところも多々あると思いますが…;)
突っ込みは大歓迎です!
お気づきの点があればコメント等でご指摘お願いしますm(_ _)m
[余談]
こういう処理も遅延って表現していいのかなぁ?
amachangさんの記事では動的ロードとされてるけど…。
まぁ遅延ロードって書いてる人もいる(↓)し、いいか!
なにより、遅延って言葉はハッカーっぽくてステキ!!
[See also]
JavaScriptで遅延ロードをする方法についてのおさらい (Clouder::Blogger)
malaさんの作。(オリジナルの記事はこちら)
2005年…3年前かぁ、すごいなぁ。
waitのみの実装のため関数自体が短く、あまりトリッキーな書き方もされていないので、こっちの方が直感的にわかりやすいかもです。
需要があれば解説しますよ?
クオリティはこの程度になりますが(笑)
[参考]
Core JavaScript 1.5 Reference:Functions - MDC
Core JavaScript 1.5 Guide:Working with Closures - MDC
[追記]
誤字を訂正。(2008/06/27 19:05)
まさか自分のドメイン名を間違えるとは^^;
一応使ってみようとしたんだけど…。
何か画面が読み込み中のまま真っ白になる事態に遭遇して断念。
どうやら、ページ読み込み後にgoogle.load()を呼び出すのはNGらしい。
例えば、
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('jquery', '1'); // いける
window.onload = function() { google.load('jquery', '1'); }; // ダメ
</script>
って感じ。
まぁ、動的に読み込みたい場合は、
'http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js'
とかを直接指定すればいい話ですけどね。
ホスティングしてくれるだけでも十分ありがたいし。
※ もう長ったらしい名前を書くのが面倒くなってきたので、今後は「Ajax Libs API」と勝手に呼ぶことにします(>_<)








