Last.fm for jQuery を改造してみました

Last.FM から再生履歴を取得して表示するツールです。このページの左のツールバーで動いています。本家にインスパイアして作成したのですが、次の点で拡張しています。

  1. 一定時間たつと自動で表示内容を更新する。
  2. アルバムアートが見つからない場合、アーティストの画像で代替する。
  3. 各曲の情報を順番にフェイド・インして表示する。
  4. strftime.js を使って Last.FM プロフィールページのように再生時刻を表示する。

サンプルページを開く

そしてついでに github デビュー。

delphinus35/lastfm – GitHub
https://github.com/delphinus35/lastfm

設置方法などは README.md と付属の sample.html に書いているのでそちらを見てください。

Last.FM の API Key の取り方など、細かいことは前回の記事参照。でもまあ、特別なことしない限り付属の API Key をそのまま使って問題ないっぽいです。

ホントは何ヶ月も前にできてたんだけど、ドキュメント書いたりするのが面倒でほったらかしてました。何とか今年中に公開できて良かった。

では、良いお年を!

Prototype.js で継承&オーバーライド

今更ながら、Prototype.js でクラスの継承とオーバーライドをやってみた記録。

しばらく使ってなかったら、$super() という便利なものができていた。

コード例

// 基底クラス
var Parent = Class.create({
    // コンストラクタ
    initialize: function() {
        // <p> 要素を生成して <body> に挿入
        this.ele = new Element('p');
        $$('body')[0].insert(this.ele);
    }
    // “word”を画面に表示
    ,say: function(word) {
        this.ele.update(word);
    }
});

// Parent を継承したクラス
var Child = Class.create(Parent, {
    // コンストラクタ
    initialize: function($super) {
        // Parent のコンストラクタを実行
        $super();
    }
    // Parent の say() をオーバーライドする
    ,say: function($super, word, word2) {
        $super(word);
        // “word, word2”という文字列を画面に表示
        this.ele.update(this.ele.innerHTML + ', ' + word2);
    }
});

var c = new Child;

c.say('One', 'Two');
// -> 画面上に 'One, Two' と表示される。

メソッドを定義するとき第一引数に $super を与えると、親クラスの同名のメソッドへの参照が与えられる。これを使ってメソッドのオーバーライドが簡単にできるのだ。

第二引数以降は親クラスから順に与えられる。これを使って引数の数すら変えることができる。上の例で言えば、Parent クラスの say() メソッドは引数を一つ採るが、Child クラスの say() メソッドは二つ採る。

jQuery.getJSON() の罠

とある Web アプリケーションを作っていたときのこと、Firefox ではまともに動くのに、IE ではバージョンを問わず機能しないことがあった。調べてみると、(珍しいことに)IE の方が仕様に則った正しい動作をしていたためであった。

最初に結論を言うと、毎回違う結果が欲しいのなら、$.getJSON() よりも $.post() を使えって話。

GET メソッドによるサーバーアクセスはブラウザにキャッシュされる。同じパラメータでのアクセスを繰り返そうとしても、ブラウザによっては、ローカルキャッシュを返すことでサーバーへのアクセスを行わない。これは GET メソッドの冪等性を考えれば自明のことだ。

冪等 – Wikipedia

冪等性は、大雑把に言って、ある操作を1回行っても複数回行っても結果が同じであることをいう概念である。

(中略)

HTTP の GET 要求は冪等とみなされる。Webの機構は基本的にその前提で要求結果をキャッシュに保持する。HTTP の POST 要求(フォーム送信に使われる)は冪等とはみなされないため、POST 要求はキャッシュされない。

Continue reading

【jQuery】IE8 でエラーが出て slimbox が使えない件について

このサイトでは画像の表示に slimbox を使っているのだが、いつの頃からか IE でバグって使えなくなっていたようだ。……そう、そもそも IE ではサイトの検証を全然してなかったのだorz

画像をクリックすると、謎のエラー「オブジェクトでサポートされていないプロパティまたはメソッドです。」が出てしまう。

2011-02-03_172614.png

IE8 の開発者ツールでデバッグしてみると、6289 行目(v1.4.4)、或いは、7284 行目(v1.5)が原因のようだ(このことに言及しているソースがキャッシュにしか残っていなかった。すぐに消えちゃうかも。)。このエントリーによると、ColorboxFancybox といったライブラリも使用不能になっていた模様。

Kawaz – 2010/12/17に書かれた日記一覧
http://webcache.googleusercontent.com/search?q=cache%3Ahttp%3A%2F%2Fwww.kawaz.org%2Fblogs%2F2010%2F12%2F17%2F&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja:official&hl=ja&client=firefox-a

var elemdisplay = {},
	rfxtypes = /^(?:toggle|show|hide)$/,
	rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
	timerId,
	fxAttrs = [
(以下略)

これを以下のように書き換えると直る。

var elemdisplay = {},
	rfxtypes = /^(?:toggle|show|hide)$/,
	rfxnum = new RegExp( '^([+\-]=)?([\d+.\-]+)([a-z%]*)$', 'i' ),
	timerId,
	fxAttrs = [
(以下略)

jQuery-1.x.x.min.js を使っている場合は簡単に書き直せないので Perl を使った。

$ perl -i.orig -ple "s:bT=/([^/]*)/i:bT=new RegExp('\1','i'):" jquery-1.5.min.js

【Vim】新機能“conceal”構文属性を使う

Vim 7.3 の新機能“conceal”の使い道がよくわからなかったのだが、こんな使用例があるようだ。

js-mask – More concise JavaScript using Vim’s “conceal” feature : vim online
http://www.vim.org/scripts/script.php?script_id=3324

Javascript では“function(){}”をひたすら重ねていくのでコードが冗長になりがち。それを見た目なりときれいにしてしまおうというのがこのプラグイン。

例えばこんなコードが、

// 1~5の合計「15」と表示する
(function(){
    alert(
        (function( ary ){
            function sum( a ) {
                var s = 0;
                a.forEach( function( i ){ s += i } );
                return s;
            }
            return sum( ary );
        })( [ 1, 2, 3, 4, 5 ] );
    );
})();

Continue reading

【Perl, Javascript】数値に位取りのコンマを挿入する

ものすごく車輪の再発明な気もするが、備忘録としておいておく。

Perl クックブックのレシピ 2.16 によると、表題のことを行う関数は次のように表せる。

sub commify {
    my $text = reverse $_[0];
    $text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g;
    return scalar reverse $text;
}

これを Javascript で表すと次のようになる。

String.prototype.reverse=function(){return this.split('').reverse().join('')};
Number.prototype.commify=function(){return this.toString().reverse().replace(/(\d\d\d)(?=\d)(?!\d*\.)/g,'$1,').reverse()};
// 使用例
alert( (123456789).commify() );     // 「123,456,789」
alert( (-123456789).commify() );    // 「-123,456,789」
alert( (1234.56789).commify() );    // 「1,234.56789」

Continue reading