Hatena::ブログ(Diary)

webとかmacとかやってみようか

2012-03-06

はてなBlogへ引っ越しました

今さらながら、はてなBlogへ引っ越しました。

http://dsuket.hatenablog.com/

引っ越しする、というほど最近更新もしてないんだけど。。

心機一転、新居でぼちぼち更新していこうかと思ってます。

とりあえずこちらもしばらくは残しておこうか。

2011-12-27

Safari の Webインスペクタで行番号がずれる問題を解決

注意: この内容は古くなっています。Safari6 に対応した記事を書きました!

Safari6 の Web インスペクタで行番号がずれる問題


Safari の開発メニューに、Webインスペクタというものがあります。

Firefoxでいうところの FireBugChrome の Developer Tools と同等のものです。これなくしては Webアプリの開発はできないくらい超絶便利なものなのですが、一つだけ重要な問題がありました。

それは、日本語が入っているファイルの行番号がずれて表示される、という問題です。リソースタブやスクリプトタブでファイルを開いたときに、横に行番号が表示されます。この行番号が実際のファイルの中身と同期していないのです。

f:id:dice-t:20111227165321p:image:left

実際に見た方がわかりやすいでしょう。これがその様子です。

スクリプトの方は3行だけ選択しているのですが、対応する行番号がめちゃくちゃになっています。どうも日本語が入ると行が高くなり、その分だけどんどんずれていってしまうようです。ソースが数百、数千行ともなると、このずれも大きくなり、何行目を指しているのかさっぱりわかりません。

特に JavaScriptデバッグ時に大きな問題になります。一般的にブレークポイントを置いてデバッグしますが、ブレークポイントはこの行番号の所に設置するのです。しかし、現在表示しているソースの箇所と行番号が大きく違うため、どこにブレークポイントを置いていいのか非常に難しい。

フォント関係の問題だとは思っていましたが、Safariの設定でも特にそのようなものはないし、めっきりお手上げ状態でした。

それが、遂に、解決する方法を見つけました!

Web インスペクタ自体も JavaScriptで書かれたツールで、以下のディレクトリに入っています。(Macの場合、Windowsはわかりません。。。)

2012/04/24 追記: Safari 5.1 より使用するフレームワークが変更になり、パスが変わりました。指摘頂いたk2oさんありがとうございます!

/System/Library/StagedFrameworks/Safari/WebCore.framework/Versions/Current/Resources/inspector

参考までに それ以前の Safari の場合はこちらになります。

/System/Library/Frameworks/WebKit.framework/Versions/A/Frameworks/WebCore.framework/Versions/A/Resources/inspector

この中の「textViewer.css」が テキストを表示する部分のCSS指定を行っています。このファイルを開いて、先頭の .text-editor 定義にフォント定義を追加します。

.text-editor {
    position: absolute;
    top:0;
    left:0;
    right:0;
    bottom:0;
    white-space: pre;
    overflow: auto;
    /* 以下を追記 */
    font-family: "Mig 1M", monospace;
    font-size: 11px;
    line-height: 1.3;
}

font-family と font-size はお好みで変えてください。重要なのは line-height をあわせること。固定値でも倍数でもどちらでも大丈夫なようです。

これを保存し(編集には管理者権限が必要です)、Safari再起動すると反映されます。

f:id:dice-t:20111227171817p:image:left

直った箇所を見てみます。

ちゃんと行番号とソースの選択箇所が一致していますね!

Web インスペクタは HTMLJSで書かれたツールなので、他にも自分用にカスタマイズすると便利になりそうですね。

これで Safari でもバリバリ開発できるぜー!

2011-02-17

Jasmine で 継続的なJavaScriptのテストをする

風邪で3日も寝込んでしまったので、JavaScriptのテストツールについて調べてみた。その中で、特に Jasmine というのが気になった。使ってみるとなかなかよさげ。

Jasmineは、JavaScriptBDD(behavior-driven development)を行うフレームワークで、RubyRSpecのように振る舞いを定義する。Sencha Touchのテストにも使われているらしい。ちなみに、RSpecについては スはスペックのス が詳しい。

なぜこれが良いかは、公式ドキュメントにずばりある。

Background ? jasmine/jasmine Wiki ? GitHub

There are some great JavaScript testing frameworks out there already, so why did we write another?

None of the existing frameworks quite worked the way we wanted. Many only work from within a browser. Most don't support testing asynchronous code like event callbacks. Some have syntax that's hard for JS developers or IDEs to understand.

So we decided to start from scratch.

適当意訳

既に数多の優れたJavaScriptスティングフレームワークがあるのに、なぜ別のを作ったか?

我々の望みを完全に実現するフレームワークが無いからです。ほとんどのものはブラウザ中でしか動かないし、イベントコールバックの様な非同期テストをサポートしていない。またいくつかは難しい文法やIDEを必要とする。

だから、我々は一から作ることを決めたのです。

JsUnitやQUnitSeleniumのことを言ってるなぁという感じですが、たしかに後発なゆえ、なかなか良くできているかと思いました。BDDというところもなかなか良い。

Jasmine の使い方は他に色々あるので、以下のサイトなどを参考にしてください。

Jasmine には 静的なHTMLファイルを用いたスタンドアローンと、rubyサーバを立ててテストする rubygems 版があります。rubygems 版のメリットは、コマンドラインから実行可能という点。継続的テストにはこれが必要不可欠。

Jasmine では、 Selenium-rc を利用して自動的にブラウザを起動してテストする仕組みが有ります。

rake jasmine:ci

で実行できる。

デフォルトでは FireFox でのテストになる。実施するブラウザを変更したい場合は、環境変数 JASMINE_BROWSER に実施したいブラウザを指定すれば良い。Jasmineの場合、jasmine_config.rb で設定することが可能だ。

jasmine_runner.rb と同じ場所に jasmine_config.rb という名前のファイルを作成し、以下のように記述すれば safari でのテストが可能になる。

ENV["JASMINE_BROWSER"] = 'safari'

safariでの実行で注意することは、ポップアップブロックが有効になっているとテストが途中で止まってしまうため、これを無効にする必要がある。safariのメニュー「sfari」から「ポップアップウインドウを開かない」のチェックを外す。

なお、chromeは指定してもなぜかfirefoxになってしまう。。。

また今度調べてみよう。

2011-02-08

JavaScript の getter/setter について

JavaScript で getter/setter が使えるということを今更ながら知った。同じ ECMAScript ベースの ActionScript は使えるのになー、と思ってたら案の定使えた。はい。私の不勉強でした。。。

参考:

しかし、ほとんど使ってるのを見たことがない。いろんなライブラリでは速度が重視されるからか?とも思ったが、ライブラリだからこそ、こういうアクセッサメソッドは重要なんじゃないだろうか。

IEでは非サポートなので意味ないということかもしれないが。。(が、一応対応策はある)

とりあえず、どれくらい遅いのか測ってみることにした。

こんなオブジェクトを作って、直接アクセス、getter/setter アクセスの実行時間を比べてみた。

var Test = {
	a: 10,
	_num: 1,
	_str: 'hoge',
	_obj: {i: 1},
	get num() { return this._num; },
	set num(n) { this._num = n; },
	get str() { return this._str; },
	set str(s) { this._str = s; },
	get obj() {return this._obj; },
	set obj(o) { this._obj = o; },
};

なお、計測はこんな感じ。

function calcTime(count, fn){
	var d = new Date().getTime();
	for(var i=0; i<count; i++){
		fn();
	}
	var pd  = new Date().getTime();
	return (pd - d);
}

function start(){
	var aGetTime = calcTime(count, function(){
		var a = Test.a;
	});
	var aSetTime = calcTime(count, function(){
		Test.a = 100;
	});
	・・・

なぜか FireFox(3.6.13)では動かず。。。

Safari 5.0.3 と Chrome 9.0 で試しました。ループ回数は10000回で、何回か回した平均的な時間(ms)です。

項目SafariChrome
Test.a get 38 71
Test.a set 35 70
Test.num get 47 145
Test.num set 53 149
Test.str get 47 145
Test.str set 54 150
Test.obj.i get 47 147
Test.obj.i set 64 158

Safari はやっ!!プロパティアクセスとメソッド呼び出しはほとんど違いありません。Chromeのほうは、大体倍くらいになってますね。しかしまあ、10万回アクセスでこんなものなので通常はほとんど誤差ですね。

というわけで、積極的に使っていこうと思います。

なお、当方の環境は MacBook Air11"(OS X 10.6.6) です。

まあ、しかし毎回打つのはめんどくさいので、Objective-C の @synthesize とかみたいにできないかな、と思って作ってみた。ruby のあれですね。

function attr_accessor(obj, name, initialValue){
	var pname = "_" + name;
	obj.prototype[pname] = typeof initialValue === 'undefined' ? null : initialValue;
	obj.prototype.__defineGetter__(name, function() { return this[pname]; } );
	obj.prototype.__defineSetter__(name, function(val) { this[pname] = val; } );
};

// 使い方
TestObj = function(){
};
// オブジェクトにプロパティとGetter/Setter、初期値を付ける。
attr_accessor(TestObj, 'foo', 'Hello Accessor!');

var o = new TestObj();
alert('o.foo: ' + o.foo);

これでプロパティもばっちり隠蔽! o._foo とかでアクセスできちゃうけど、まあないよりいいだろ。

しかし、作って思ったが、あんまり意味ないな。微妙。。。

2011-01-19

Step 5: クライアント機能のコーディング

目次:Google Web Toolkit チュートリアル(目次) - webとかmacとかやってみようか

原文:Error 404 (Not Found)!!1

ここまでやってきたが、今更になって素晴らしい訳を作って下さっていることを知った。

no title

というわけで、私が訳すまでもない。。。

最近は GWTCanvasを使ったり、iphone向けにしたりしてるので、今後はそのあたりをネタにしようかと思う。