2010年6月20日日曜日

文字の大きさ

MacBook Pro 17"を購入しました。プロセッサをi7に、またハードディスク ドライブをシリコン ドライブ(ソリッド ステート ドライブ)に交換するなどしています。

起動して一番に思った事は「文字が小さい」

初期設定の解像度では12ポイントの文字が小さくて、老眼が進行している私には読みにくくなっています。WYSIWYGで有名になったMacintoshも、今や紙に印刷するのではなく、コンピュータ上で自分の好きな大きさにして読み書きするので、文字の大きさにポイントを用いる意味が無くなってしまいました。

ただ、自分が読みやすい文字の大きさとは、書きやすい文字の大きさとは、などと余計な事を考えなくてはならなくなりました(笑)

平安時代などの古い手紙の写真を見ると、書かれた文字に多少の大小はあってもかなり大きなものでした。それが、江戸時代の版画技術の向上(欧州の印刷技術の向上)などにより、大量の印刷物が市場に流通するようになり、それに伴って貴重で高価な紙の量を減らし経費を削減するために、読むための文字の大きさが小さくなった…ように思います。

また、鉛筆や万年筆の登場で小さな文字が書けるようになり、さらにシャープペンシル、ボールペンで加速化されました。

それがコンピュータ技術により、好きな大きさの文字で書いて、好きな大きさの文字で読むようになった、と言う事でしょう。

実際、ノートPCにシリコン ドライブを搭載することで、故障を心配することなく読み書きできるようになりました。さらに、iPhoneやiPod touchで読み書きする場所や時間などの制約が少なくなり、iPadでそれが加速化されようとしています。

iPhoneやiPod touchで書いて送信した文章はその内容に関係なく、書いた場所と時間は自動的に記録されますので、その統計だけでも大量の情報を未来に残す事になります。68億ある世界人口の四分の一でもTwitterなどインターネットで何かを書くようになれば、世界はどうなるのか?などと夢想します。

2010年6月9日水曜日

Safari 5の互換性

データベースは変更せずに動きましたが、以下のようなタグで表示されるテキスト フィールドの幅が変わりました。
< input id="xxx" size="12" type="text" />

Safari 5のデータベース

Safari 5をダウンロードしてデータベースを試した結果。少なくとも、私がSafari 4を使って試しに書いたデータベースを開く事が出来ました。

また、[環境設定]の[セキュリティ]で[データベースを表示]ボタンを押して表示されるデータベースのリストが改善されました。今までは開いたデータベースのみを表示したのですが、Safari 5では開かなくても表示されるようになりました。Safari 4ではこれが不便でした。

[開発]メニューの[エラーコンソールを表示]で表示されるウィンドウで、データベースを表示する機能は今までと同様です。データベースを開いた状態で、上欄から[ストレージ]を選択して、左欄から[データベース]を選択すると、データベース名やテーブル名が表示され、ウィンドウ内にデータが表示されます。

ただし、[ストレージ]に便利な機能が追加されていました。開いているページのCOOKIEの詳細を表示してくれます。これが標準で付いているのは便利そうです。

2010年6月6日日曜日

Apple - HTML5

私が2007年の資料に手こずっている間に、Appleは現在のHTML 5などの技術を使ったデモを発表しています。

Apple - HTML5
http://www.apple.com/html5/

Appleお得意の見た目のきれいさと、そのための技術には唖然とします。

2010年6月5日土曜日

8. 後日談

<最初にもどる> <pre>
謎などと大袈裟な事を書きましたが、どうしても定義が見つからなかった構文があったのです。以下のオブジェクトのメンバ宣言です。何処かにあるはずなのですが、見つかりません。

オブジェクトのメンバ宣言をするときに以下の例ようにしてSettingとGettingを簡単に宣言し、利用方法も簡単になります。
function MyObject() {
}

MyObject.prototype = {
 get id() {
  return this._id;
 },
 set id(x) {
  this._id = x;
 },
}

function myCode() {
 myObject = new MyObject();
 myObject.id = 3;
 alert('id is ' + myObject.id);
}
上の式でメンバ変数を宣言できますし、WebKitのサンプルコードsticky-notesのようにメソッドも宣言できます。

この便利な点はメンバ変数とそのset getが羅列するだけで簡単に宣言できる点です。また、下のtest()のように簡単にメンバ変数への代入と呼び出しができます。ただし、上の関数を使えるのは一度だけのようです。同じオブジェクトに追加宣言はできず、追加できるのはメソッドのMyObject.prototype.methodNameだけのようです。

ストレステストはしていませんが、上記のサンプルコード程度ならFirfox 3.6.3でも動作しました。

ECMAScriptにおける「オブジェクトリテラル」と言う書式では、配列を拡張してオブジェクトを宣言できます。
myObject = {
 myVar: -- numbers,
 myVar: '-- words',
 myFunc: function() {
  -- definition
 }
}
似てはいるのですがどうも違うように思います。
<最初にもどる> <pre>

7. 恐怖の仮面this

<pre> <next>
myHandlerに渡される引数のeはイベントが発生した位置などを含む情報が入っています。しかし、サンプルコード2のaddEventListenerに渡されるthis.myHandlerには引数がありません。さらに、試しに、サンプルコード1のfunction(e) { self.myHandler(e) を function() { self.myHandler()とするとエラーになります。これでも良いような気もするのですが、どうもSafariの実装が
怪しいような気も・・・(笑)

いずれにしても、最初の二行は同じですし、動作も同じです。その後も変数が一カ所違うだけだと思って見逃すと・・・
探偵失格です(大笑)

それでは事件解明にかかりましょう。

犯人はthisなのです。二つのサンプルにあるthisは別人…いや、別のオブジェクトを指しています。

addEventListenerの使い方として良く紹介されているのですが、サンプルコード2のthisはHTMLの<div>を指しています。JavaScriptの仕様では、イベント駆動の元になるオブジェクトがJavaScriptのオブジェクトではなく、HTMLの<div>であると考えているようです。

ところがサンプルコード1のthisではMyObjectから作られたmyRectオブジェクトを指しています。たとえば、サンプルコード1では以下のようになっています。
alert(this.myObject.offsetLeft);
これはthis.myObjectで表す四角の左端の座標offsetLeftを表しています。ではthis.myObjectとは?と言うと、MyObject()内にある以下のコードで以下のように表しています。
this.myObject = myObject;
そう、例の問題のコードです。この左辺のthisがmyRectになるわけです。だからこそサンプルコード1では以下の式でmyRectのプロパティが呼び出せたのです。逆に、サンプルコード2ではHTMLの<div>にはthisというプロパティがないので「undefined」になってしまったわけです。
alert(this.myVar);
サンプルコード2ではHTMLの<table>などHTMLの入れ子構造(ネスト構造)になっているものを扱うには分かりやすく便利そうです。しかし、上記のように親となった関数を指したくなる場合がある事も事実です。

実際にWebKitのサンプルコードsticky-notesでは、addEventListenerで呼び出されたハンドラから、さらにaddEventListenerでハンドラを登録してそれぞれで変数を共有しています。グローバル変数という手もありますが、オブジェクトが繰り返し生成される(四角が作られる)たびにグローバル変数を生成していては後始末が大変です。

個人的には明示的にどちらを選択するのかを引数を追加するか、関数名で明示したほうが分かりやすいように思うのですが・・・。

閑話休題、一件落着したと思ったのですが、まだ謎が残っていました。それは・・・つづく(笑)
<pre> <next>

6. addEventListenerの浮気

<pre> <next>
二つのサンプルコードの違いは以下の通りです。二つのウィンドウにそれぞれのサンプルコードを左右に並べて表示してじっくりと比較してみてください。
サンプルコード1
myObject.addEventListener('mousedown', function(e) { self.myHandler(e) }, false);
サンプルコード2
myObject.addEventListener('mousedown', this.myHandler, false);
サンプルコード2が一般的によく紹介されている書き方です。this.myHandlerは生成されたオブジェクトのmyHandler関数です。サンプルコード1ではfunction(e)でハンドラを定義しています。分かりやすいように改行を入れると以下のようになります。
  myObject.addEventListener(
    'mousedown', 
    function(e) { 
      self.myHandler(e) 
    }, 
    false
  );
ここは関数定義の中ですので、ここでthisを使えば新規の関数定義となります。そこでコンストラクタ内のthisをselfに入れてself.myHandler(e)とすることでオブジェクト内のmyHandlerメソッドを指しています。

なぜこのような面倒な事をしているのでしょう?また、この後のthis.myObject = myObject;という式も妙です。さらに、もう一つ気になるのは謎の引数eの存在です。実はthisがこの一件に強く絡んでいるのですが・・・三文探偵小説なら事件はいよいよ混迷を深めてきたというところでしょうか(苦笑)
<pre> <next>

5. サンプル コード2

<pre> <next>
サンプルコード1と同様に、このコードもhtmlのファイルにしてSafariで実行してみてください。

実行すると灰色の四角が表示され、表示された灰色の四角をクリックするとクリックした位置のX座標と四角の左端の座標、そして謎の「undefined」がアラートボックスで表示されます。
<html>
<head>
<style>
.myCSS {
  background-color: rgb(240, 240, 240);
  height: 250px;
  width: 200px;
  position: absolute;
  left: 200px;
  top: 200px;
}
</style>
<script>
function MyObject() {
 var self = this;
 var myObject = document.createElement('div');
 myObject.className = 'myCSS';
 myObject.addEventListener('mousedown', this.myHandler, false);
 this.myObject = myObject;
 document.body.appendChild(myObject);
}

MyObject.prototype.myHandler = function(e) {
 alert(e.clientX);
 alert(this.offsetLeft);
 this.style.left = '100px';
}

function loaded() {
 myRect = new MyObject;
}
</script>
</head>
<body onload="loaded()">
</body>
</html>
<pre> <next>

4. addEventListenerとthis

<pre> <next>
謎は二つです。

  1.addEventListenerに書かれた謎のfunction()

  2.myHandler関数内のthisとはだれか?

この二つが「奇妙な愛憎劇」のように絡んでいます(笑)

addEventListenerは先にも書きましたように、マウスのボタンが押された時にシステムから渡されるイベントを取り込んで、そのイベントを扱う(ハンドルする)関数としてmyHandler()関数を登録しています。このmyHandler()関数はすぐには実行されずイベントが発生した時に(非同期に)実行されます・・・と言う事は他のサイトにも書かれていて、言わずもがなの話しです。

構文は以下のようになります。

  addEventListener(イベント名, ハンドラ関数名, falseまたはtrue)

イベント名はclickやkeyup、mousedownなどイベント駆動型のプログラミングでおなじみのもので、指定したイベントが発生するとハンドラ関数が呼び出されます。最後の引数はイベントが呼び出されるタイミング(登りか下りか)を表します。

論より証拠です。実際にサンプルコード1を書き換えて、この構文に合わせてaddEventListenerを呼び出すとどのようになるか「現場検証」してみましょう(笑)
<pre> <next>

3. コードの流れ

<pre> <next>
コードの流れは以下のようになります。

1.ファイルの読み込み
  最初に<body onload="loaded()">からloaded()関数を
  経由してMyObject()のコンストラクタが呼び出されます。

2.コンストラクタ
  コンストラクタではcreateElement('div')で<div>タグが
  生成され、classNameで.myCSSのスタイルが指定され
  ます。

3.スタイル
  .myCSのスタイルでは四角の色、高さと幅などが指定され
  ています。

4.イベント登録
  addEventListenerでマウスのボタンが押された時のイベ
  ントをフックしてハンドラとしてmyHandler()関数を非同
  期で呼び出します。

5.メンバ登録
  オブジェクト自身を自分のメンバとして登録します。

6.オブジェクト生成
  最後にappendChildでオブジェクトを生成します。

以上が起動時の動作ですが、その後に四角の上でマウスのボタンが押されると以下のようになります。

7.ハンドラ関数myHandlerが起動します。

8.座標などを表示します。

さて、最初からもう少し詳しく見ていきましょう。オリジナルsticky-notesでは少々違和感のある起動コードが書かれていますが、1では分かりやすくするために良く知られた方法にしています。

2.は6とともに、<div>タグをcreateElement()で生成し、スタイル シートや各種の属性など宣言してappendChild()で生成しています。この方法はJavaScriptから<div>や<table>などのタグをJavaScriptで生成する方法としてあちらこちらのサイトで紹介されてますので、特に問題はないと思います。

3.は画面の好きなところに四角を描く方法です。種明かしされれば「ナンダ」という気が…(笑)ただし、leftとtopは絶対位置で指定しますので、position: absolute;で絶対位置を指定し忘れると四角が左上の隅に張り付いてしまいます。もちろん、この失敗をしたので気付きました(笑)

4.これが難問です。5と7、8とも絡んで理解を阻んでいます。・・・と言う事で項目をあらためましょう。iptで生成する方法としてあちらこちらのサイトで紹介されてますので、特に問題はないと思います。

3.は画面の好きなところに四角を描く方法です。種明かしされれば「ナンダ」という気が…(笑)ただし、leftとtopは絶対位置で指定しますので、position: absolute;で絶対位置を指定し忘れると四角が左上の隅に張り付いてしまいます。もちろん、この失敗をしたので気付きました(笑)

4.これが難問です。5と7、8とも絡んで理解を阻んでいます。・・・と言う事で項目をあらためましょう。
<pre> <next>

2. サンプル コード1

<pre> <next>
まずは、以下のコードを見てください。このコードはファイルにしてSafariでローカルに実行できます。

実行すると灰色の四角が表示され、表示された灰色の四角をクリックするとクリックした位置のX座標と四角の左端の座標、そしてmyRectオブジェクトのメンバであるmyVarの"this is myVar"がアラートボックスに表示されます。
<html>
<head>
<style>
.myCSS {
  background-color: rgb(240, 240, 240);
  height: 250px;
  width: 200px;
  position: absolute;
  left: 200px;
  top: 200px;
}
</style>
<script>
function MyObject() {
 var self = this;
 this.myVar = "this is myVar";
 var myObject = document.createElement('div');
 myObject.className = 'myCSS';
 myObject.addEventListener('mousedown', function(e) { self.myHandler(e) }, false);
 this.myObject = myObject;
 document.body.appendChild(myObject);
}

MyObject.prototype.myHandler = function(e) {
 alert(e.clientX);
  alert(this.myObject.offsetLeft);
  alert(this.myVar);
}

function loaded() {
 myRect = new MyObject;
}
</script>
</head>
<body onload="loaded()">
</body>
</html>
<pre> <next>

1. SafariのJavaScript

AppleがSafariに(実験的に?)搭載しているHTML 5の仕様にはデータベースなど興味深いものがたくさんあります。そのデータベース機能などを利用したサンプルがWebKitのサイトに公開されています。

http://webkit.org/demos/

サンプルはこの下の各ディレクトリにまとめてありますので、Safariでソースコードをもとにファイルを一つずつ手元に保存すると、ローカルでも実行できます。wgetなどのツールをご存じの方はまとめてダウンロードすると良いでしょう。ちなみにこの項目を書いている2010/06/01の時点では以下の四つのデモが入っています。
  • calendar
  • editingToolbar
  • sticky-notes
  • transitions-and-transforms
また、デモの一つeditingToolbarは、Mac OS Xに標準で付属しているDeveloper向けキットにもあります。深いディレクトリにあるので、"FancyEditingToolbar"で検索するとよいでしょう。

このサンプルの中で一番古いsticky-notesは2007年10月19日公開されています。このsticky-notesのHTMLファイルを読み込むと、画面に黄色い四角が表示されています。この四角には文字を書く事ができます。HTMLで画面に四角を書くとなると、とりあえず<table>タグを使う事を考えてしまう私には驚きです(苦笑)

しかも、この四角をクリック ドラッグするとウィンドウ内の好きなところに移動します。その移動は昔のMacintoshの用に枠をアニメーション表示して、ボタンを放したところに表れるというものではなく、パワフルなリアルタイム描画です・・・と書けば年寄り扱いされますね(笑)

さらに、「New Note」ボタンを押すと黄色い四角が追加表示されます。黄色い四角の上にマウス カーソルをおくと左上にDashboardと同じボタンが表示され、クリックすると四角がアニメーションで閉じます。アニメーションの動きが良くわからない方はシフト キーを押してクリックしてみてください。Dashboardと同じゆっくりとしたアニメーションを楽しめます。このコード自体はDashboardのStickiesの簡易版と考えれば良さそうですが、これを発展させればWebブラウザ内にウィンドウ システムが出来ます。

このコードのデータベース部分に関しては英語や日本語で紹介しているサイトがありますが、他の部分もなかなか難しい事をしています。他の部分に関してインターネットを調べてみたのですが、解説している資料が見つかりませんでした。やむなく、コードを書いて調べた結果が以下の項目です。きっと何処かに仕様書や解説があると思うのですが、枯れ木も山の賑わい と思い紹介します。
データベース部分は、関してはSafariとSQLiteをキーワードにしてインターネットを検索すれば、さまざまな解説が日本語と英語で出てきますので、そちらを参照ください。これはこれで面倒で色々とある事は確かなのですが、今回は話しが長くなるのでパス!だれも年寄りの長話は聞きたくない、いや読みたくないでしょう(笑)

なお、実験した環境はMac OS X 10.5.8、Safari 4.0.4 (5531.22.7)とBBEdit 9.5(2740)のPreviewですが、Firefoxでも動く事があります。
<next>