IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

Facebook 向けウェブサービスは IE6 に対応すべきか ( 2011年12月の Facebook のブラウザシェア )

はじめに

みなさん、お元気ですか><リリースも終わって、一息ついたあまちゃんです!
ヽ(´ー`)ノわー
さて今日は、最近「お花サプライズ!」というサービスをリリースしたのですが、そのときにちょっと面白いデータを見つけたのでそのいきさつも含めて紹介したいと思います。

(今日のテーマはこの円グラフ)

フェイスブック系のサービスはどのブラウザに対応すれば良い?

よく、ウェブサービスを開発するときの悩みとして「古いブラウザでのデザインをどのくらいケアするか?」というものがあります。
「お花サプライズ!」でも、割と短い期間で実装することを目標としていたり、本番の HTML を書いた経験があまりないメンバーが多くいたことで「IE6 や IE7 への対応が鬼門なんじゃないか?」という心配が常にありました。
そこでよぎる甘い誘惑

このご時世、 IE6 とか IE7 に特別対応する必要なんてないんじゃね?

で、調べてみると大概の場合は「やっぱり IE6 や IE7 は無視できない… orz」となるのですが、「お花サプライズ」は、ターゲットユーザをフェイスブックだけに限定しています。
フェイスブック自体が「IE6 を非推奨にしていたりする」ということもあるので

ひょっとしたら IE6 や IE7 をそこまでケアしなくても大丈夫なんじゃないだろうか?

そう思って、ちょっと調べてみました。

ウェルカムページメーカーのデータをもとに調べる

実は、お花サプライズ!を作る前にちょっと作ったプチサービスがありまして、それがフェイスブックページのウェルカムページを作るサービス「ウェルカムページメーカー」です。
作ってからずっと放置してるんですけど、何げにずっと伸びてて、今は 3100 ページ以上のフェイスブックページに導入されていて、月間ユニークユーザーベースで 110,000 人からのアクセスがあります。

(9月〜今日までの訪問数、にょきにょき〜)
使われているページも、アナウンサーのページや、 歌手のページ、アニメのページ、EC サイト、企業のページ、個人のページと色々なページに使われていて、そこまで偏りはないと思うので、このサービスの統計をもとにフェイスブックでのブラウザシェアを考えてみたいと思います。
また、フェイスブックのウェルカムページを見れるのは基本的には PC なので、モバイルはこの統計には含みません。

昨日から 30 日前までのデータを使う

まずは、バージョンを問わないブラウザのシェアを見てみると以下のようになりました。
訪問数ベース↓

PV ベース↓

やはり、 IE を使っている人が多いですね!
では、次に IE をバージョンごとに分割したグラフを作ってみます。
訪問数ベース↓

IE6: 3.15%、 IE7: 5.09%
PV ベース↓

IE6: 3.78%、 IE7: 5.87%
表にまとめると以下のようになりました

ブラウザ 訪問数(%) PV(%)
IE6 3.15 3.78
IE7 5.09 5.87
IE8 27.92 32.81
IE9 14.86 19.04
IE10 0.00 0.00
Chrome 23.04 16.36
Firefox 14.34 13.77
Safari 8.68 6.16
Android Browser 1.52 0.98
Opera 0.51 0.52
0.89 0.71

やはり、フェイスブックユーザに限定すると IE6 や IE7 のユーザが少ないことが分かりますね。

各ブラウザに対応するために必要なコスト

次に、各ブラウザに対応するコストを僕の主観で数値化してみる
以下の数値は、プロジェクト全体でかかる時間のうち、特定ブラウザへの対応時間以外にかかる時間を 1000 としたときに、どのくらい時間を費やす必要があるかを数値化したもの

ブラウザ JavaScript で同じ挙動を実現するのに必要な時間 CSS で文言が見えないなどの大きな崩れを解消するのに必要な時間 CSS で見た目の崩れをすべて解消するのに必要な時間
IE6 10 20 60
IE7 10 10 30
IE8 2 1 5
IE9 2 1 3
IE10 2 1 2
Chrome 1 1 1
Firefox 1 1 1
Safari 1 1 1
Opera 5 1 2

単位訪問あたりの作業時間を計算してみる

サービスへの訪問数 1% あたりのコストを計算してみる

ブラウザ 1% の訪問に対して JavaScript で同じ挙動を実現するのに必要な時間 1% の訪問に対して CSS で文言が見えないなどの大きな崩れを解消するのに必要な時間 1% の訪問に対して CSS で見た目の崩れをすべて解消するのに必要な時間
IE6 3.17 6.35 15.87
IE7 1.96 1.96 5.08
IE8 0.07 0.04 0.18
IE9 0.13 0.07 0.20
Chrome 0.04 0.04 0.04
Firefox 0.07 0.07 0.07
Safari 0.11 0.11 0.11
Opera 9.80 1.96 3.92

このように見ると IE6 の CSS のくずれを直すこと、また、 Opera の JavaScirpt に対する修正があまり生産的でないことが分かりますね><

というわけで「お花サプライズ!」では

以下のようなポリシーでブラウザ対応することにしました

  • IE6
    • JavaScript はちゃんと動くように
    • 大きく崩れてても気にしない。ただし、押せないリンクやボタン、隠れて読めない文字があるのは許さない
  • IE7
    • JavaScript はちゃんと動くように
    • レイアウトが大きく崩れてるようなのは修正。多少の崩れは気にしない。押せないリンクやボタン、隠れて読めない文字があるのは許さない
  • Opera
    • 試さない(運任せ)
    • きっと、 Opera さんならやってくれる…!!!
  • 全般的に
    • ブラウザのバグに依存したコードは書かない

まあ、そもそも

特定ブラウザに「対応する」って言い方はあまりよくないですね(><ごめんさない
こういう場合は、「なるべく多くの人が使ってるブラウザが実装してない仕様を使わないようにする」というのが正しいのかもしれません。
まあ、何にせよ。
これだけ色々な種類のブラウザが出てくると一つ一つのブラウザへの対応というものの重要性は薄れつつあるのかもしれませんね。
それなりに多くのブラウザでそれなりに動くのがちょうどいいと思うのですよヽ(´ー`)ノ

最後に

みなさんも、フェイスブックユーザをターゲットとしたサービスを作ることがあれば参考にしてみてくださいー
ではではーヽ(´ー`)ノ

IE9 できる/できない系

今までできなかったことができるようになる系

  • SVG サポート
  • application/xhtml+xml への対応
  • video/audio のサポート(次の Preview 版で)

今までも、頑張ればできたけど非常にめんどくさかったことが簡単にできるようになる系

  • CSS3 Background や Border や半透明系
  • CSS3 Selector の対応拡大
  • DOM 2 Style, DOM 3 Events, DOM 2 Range, Selection

未だにできない系

IE8 の DOM のプロトタイプと Getter/Setter API はどうなるか

ちょっと前に

Microsoft 公式に以下のような発表がありました。
Responding to Change: Updated Getter/Setter Syntax in IE8 RC 1 – IEBlog
また、以下のようなドキュメントも公開されています。

これらの内容での概要を自分なりにまとめてみます。

概略

要点は

  • DOM オブジェクトのプロトタイプが使えるようになる
  • DOM オブジェクトに既存の Getter/Setter API が使えるようになる
  • DOM オブジェクトに ECMAScript 3.1 の Getter/Setter API(PropertyDescriptor)が使えるようになる
  • DOM オブジェクト以外の Getter/Setter は出来ない

ということです。

DOM オブジェクトのプロトタイプが使えるようになる
// Element のプロトタイプに isElement というプロパティを作る。
Element.prototype.isElement = true;

// そうすると
// 要素に isElement というプロパティが出来る
alert(document.body.isElement); // true
alert(document.createElement('div').isElement); // true

// HTMLDocument のプロトタイプに hoge という関数を作る
HTMLDocument.prototype.hoge = function() {
    alert('fuga');
};

// そうすると
// document に hoge という関数が出来る
document.hoge(); // fuga
DOM オブジェクトに既存の Getter/Setter API が使えるようになる
// Element のプロトタイプに innerHTML Setter を取得する
var nativeInnerHTML = Element.prototype.__lookupSetter__('innerHTML');

// Element のプロトタイプに innerHTML Setter を設定する
Element.prototype.__defineSetter__('innerHTML', function(html) {
    alert(this.tagName + 'の innerHTML が設定されました!');
    return nativeInnerHTML.call(this, html);
});

// body の innerHTML に値を設定する
document.body.innerHTML = '<p>Hello, world!</p>'; // 「body の innerHTML が設定されました!」と表示される
DOM オブジェクトに ECMAScript 3.1 の Getter/Setter API(PropertyDescriptor)が使えるようになる
// Element のプロトタイプに innerHTML Setter を取得する
var nativeInnerHTML = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML').setter;

// Element のプロトタイプに innerHTML Setter を設定する
Object.defineProperty(Element.prototype, 'innerHTML', {
    setter: function(html) {
        alert(this.tagName + 'の innerHTML が設定されました!');
        return nativeInnerHTML.call(this, html);
    }
});

// body の innerHTML に値を設定する
document.body.innerHTML = '<p>Hello, world!</p>'; // 「body の innerHTML が設定されました!」と表示される
DOM オブジェクト以外の Getter/Setter は出来ない
// 下記はエラーが発生する
Object.defineProperty(Object.prototype, 'hoge', { setter: function() { alert('fuga') } });  // Error!

以下を参照してください。

The first parameter (the object on which to attach the accessor) supports only DOM instances, interface objects and interface prototype objects in Internet Explorer 8.

Internet Explorer for Developers | Microsoft Docs

ただ、そのうち出来るようにしたい的なことはかかれていました。
当然、オブジェクトリテラル内で定義することは出来ないと思われます。

とりあえず

これで言いたいことは終わりなのですが、もうチョイ詳しいことも書いておきます。

Getter/Setter API の背景と流れ

Getter/Setter API に関しては、ちょっと複雑な経緯があるのでここまでの流れを紹介します。

  1. ECMAScript 3 の仕様が固まる。この時点で Setter/Getter API の仕様は存在しない
  2. Firefox が勝手に Getter/Setter API を実装(これが、さっき紹介した「既存の Getter/Setter API」)
  3. Safari, Opera もそれを追従
  4. IE8 Beta2 もそれを追従
  5. ECMAScript 3.1 で、新しく Getter/Setter の仕組み(PropertyDescriptor)およびその API が仕様化される
  6. IE8 では、既存の API を残しつつ、新しい API を実装することに決定(←イマココ!
  7. Mozilla, Opera, Apple, GoogleECMAScript 3.1 の仕様に同意しているので、この流れに追従するものと思われる。

こういう流れがあったんですね。

プロトタイプとは何か

これは、何回も書いていると思うのですが何回でも書きます!

プロトタイプとは複数オブジェクトの共通プロパティを持つオブジェクト

プロトタイプとは、複数のオブジェクトの共通プロパティを持つオブジェクトです。
たとえば、 document.body や document.documentElement や document.createElement('div') の共通プロパティを持っているのが Element.prototype というオブジェクトです。
以下の例をみてください。

var body = document.body;
var html = document.documentElement;
var div = document.createElement('div');

Element.prototype.hoge = 1;

alert(body.hoge); // 1
alert(html.hoge); // 1
alert(div.hoge); // 1

Element.prototype.hoge = 2;

alert(body.hoge); // 2
alert(html.hoge); // 2
alert(div.hoge); // 2

簡単ですよね。
これの、 Element.prototype が document.body や document.documentElement や document.createElement('div') のプロタイプです。

共通プロパティの代表はメソッド

この仕組みは主にメソッドで使われます。
たとえば、以下のように Element.prototype にメソッドを作ると body や div でも呼び出せるようになるのです。

var body = document.body;
var html = document.documentElement;
var div = document.createElement('div');

Element.prototype.sayTagName = function() { alert(this.tagName) };

body.sayTagName(); // BODY
html.sayTagName(); // HTML
div.sayTagName(); // DIV

たとえば、ブラウザの実装にもよりますが appendChild や removeChild などのメソッドもプロトタイプで定義されています。

IE で「DOM オブジェクトのプロトタイプを使えるようになる」とはどういうことなのか

今までの IE の特徴は

  • DOM オブジェクトはプロトタイプを持っていない
  • DOM オブジェクトの実装が標準仕様に従っていない(主にイベント周り)

というところでした。
これが IE8 からは

  • DOM オブジェクトがプロトタイプを持っている(New!!)
  • DOM オブジェクトの実装が標準仕様に従っていない(主にイベント周り)

という風になったのです。

それはどういうことか

標準仕様に従っていない部分がプロトタイプに局所化されたということになります。
ということは、 JavaScript を書く人はプロトタイプを標準準拠の API に書き換えてしまうことが出来るようになったのです。
たとえば、以下の記事のように IE に addEventListener を実装することが出来ます。

// Apply addEventListener to all the prototypes where it should be available.
HTMLDocument.prototype.addEventListener =
Element.prototype.addEventListener =
Window.prototype.addEventListener = function (type, fCallback, capture)
{
  var modtypeForIE = "on" + type;
  if (capture)
  {
    throw new Error("This implementation of addEventListener does not support the capture phase");
  }
  var nodeWithListener = this;
  this.attachEvent(modtypeForIE, function (e) {
    // Add some extensions directly to 'e' (the actual event instance)
    // Create the 'currentTarget' property (read-only)
    Object.defineProperty(e, 'currentTarget', {
      getter: function() {
         // 'nodeWithListener' as defined at the time the listener was added.
         return nodeWithListener;
      }
    });
    // Create the 'eventPhase' property (read-only)
    Object.defineProperty(e, 'eventPhase', {
      getter: function() {
        return (e.srcElement == nodeWithListener) ? 2 : 3; // "AT_TARGET" = 2, "BUBBLING_PHASE" = 3
      }
    });
    // Create a 'timeStamp' (a read-only Date object)
    var time = new Date(); // The current time when this anonymous function is called.
    Object.defineProperty(e, 'timeStamp', {
      getter: function() {
        return time;
      }
    });
    // Call the function handler callback originally provided...
    fCallback.call(nodeWithListener, e); // Re-bases 'this' to be correct for the callback.
  });
}

// Extend Event.prototype with a few of the W3C standard APIs on Event
// Add 'target' object (read-only)
Object.defineProperty(Event.prototype, 'target', {
  getter: function() {
    return this.srcElement;
  }
});
// Add 'stopPropagation' and 'preventDefault' methods
Event.prototype.stopPropagation = function () {
  this.cancelBubble = true;
};
Event.prototype.preventDefault = function () {
  this.returnValue = false;
};
Internet Explorer for Developers | Microsoft Docs

MSDN に書いてる暇があるなら!それを実装して出荷してくれよ!!!」という言葉はかみ締めておきましょう。

プロトタイプだけでは解決できない非互換

DOM のプロパティには代入が特殊な意味を持つということが多々あります。
たとえば、

document.body.innerHTML = '<p>hoge</p><p>fuga</p><p>piyo</p>';

alert(document.body.childNodes.length); // 3

document.body.innerHTML = '<p>hoge</p><p>fuga</p>';

alert(document.body.childNodes.length); // 2

このように、代入すること自体に代入以外の意味があることが多々あるのです。
このようなプロパティに非互換がある場合は、プロトタイプがあるだけでは解決ができません。
どうしても、 Getter/Setter という仕組みが必要なのです。

そもそも Getter/Setter ってなんなのさ!

Getter/Setter とは、プロパティの代入や参照が発生したときに、指定した関数オブジェクトを呼び出す仕組みです。
たとえば、以下のようなものです。

var obj = {};

// hoge という Getter を作る
obj.__defineGetter__('hoge', function() { return 1 });

alert(obj.hoge); // 1

// hoge という Setter を作る
obj.__defineSetter__('hoge', function(v) { this._v = v; return v * 2 });

alert(obj.hoge = 2); // 4
alert(obj._v); // 2

既存の Getter/Setter API の詳細

Firefox, Safari, Opera で使える Getter/Setter API の詳細を説明します。

  • __defineGetter__
  • __defineSetter__
  • __lookupGetter__
  • __lookupSetter__
  • オブジェクトリテラル内で定義
__defineGetter__

ゲッターを作ります。

document.body.__defineGetter__('hoge', function() {
    return 'fuga';
});

alert(document.body.hoge); // fuga
__defineSetter__

セッターを作ります。

document.body.__defineSetter__('hoge', function(v) {
    this.v = v * 2;
    return v;
});

var a = document.body.hoge = 2; // このようにしたときに a にはセッターが返した値が入る

返り値として、受け取った値を返すようにしておかないと式の値がおかしくなるので注意が必要です。

__lookupGetter__

ゲッターを探します。

var innerHTMLGetter = document.body.__lookupGetter__('innerHTML');

// innerHTML を参照したときと同じことができる
innerHTMLGetter.call(document.body);

このとき、 __lookupGetter__ はプロトタイプが持つゲッターも探してくれます。

__lookupSetter__

ゲッターを探します。

var innerHTMLSetter = document.body.__lookupSetter__('innerHTML');

// innerHTML に 'hoge' を代入したときと同じことができる
innerHTMLSetter.call(document.body, 'hoge');

同様に、 __lookupSetter__ はプロトタイプが持つゲッターも探してくれます。

オブジェクトリテラル中に定義

以下のような set/get キーワードを使って、オブジェクトリテラル中で定義することができます。

var hoge = {
    get a() { return this._a * 2 },
    set a(v) { this._a = v; return v } 
};

hoge.a = 1;
alert(hoge.a); // 2

プロトタイプと Getter/Setter API だけでは対応できない微妙な問題

プロトタイプと既存の Getter/Setter API があれば、ほとんどの非互換による問題は解決できるのですが、

  • プロパティが for in されるかされないか
  • プロパティが書き換え可能か
  • プロパティが削除可能か

に依存したコードが存在する場合は、既存の Getter/Setter API では対処することができません。
その代表的な例はオブジェクトをハッシュとして使っている場合などです。
この微妙な問題を解決するためには、

  • プロパティが for in されるかされないか
  • プロパティが書き換え可能か
  • プロパティが削除可能か

というプロパティの属性を設定出来ることが望まれます。
ECMAScript 3.1 の PropertyDescriptor を使うと Getter/Setter を作ることと同時にこれらのプロパティの属性を設定することも出来るようになります。

ECMAScript 3.1 の PropertyDescriptor の詳細

ECMAScript 3.1 では Getter/Setter も、「削除可能か、書き換え可能か、 for in されるか」という属性も、プロパティの値もすべて PropertyDescriptor というもので扱われます。
つまり、プロパティの状態はすべて PropertyDescriptor を使って決めることができます。
この PropertyDescriptor についての詳細は、以前に記事を書いたのでそちらをごらんください。
(注:以下の記事執筆時点で flexible という名前だったプロパティに関しては、現時点で configurable という名前に変更されています。)
次の JavaScript の仕様はこうなる! ECMAScript 3.0 から 3.1 への変更点まとめ - IT戦記

Safari4 と IE8 で実装された DOM Storage とは何か

はじめに

皆様 JavaScript のスピード競争が激化し、 ECMAScript 3.1 の仕様の策定が進むなど、激動の JavaScript 時代をいかがお過ごしでしょうか。
さて今日は、今、ちまたで大ブレイクの兆しを見せている DOM Storage という仕様を紹介したいと思います。

DOM Storage とは何か

まず、 DOM Storage とはどんなものなのでしょうか。
とても簡単に言ってしまえば、とてもたくさんのデータが保存できてサーバーに自動で送られない Cookie みたいなものです。
さらに、 Cookie とは違って JavaScript からとても扱い易く作られています。
では、この DOMStorage の具体的なソースコードを見てみましょう。

<!DOCTYPE html>
<html>
<head><title>DOMStorage の使い方</title></head>
<body><script>

// DOM Storage は localStorage というオブジェクトを経由してアクセスされます。
if (!localStorage.name) {

    // 使い方はただ代入するだけ
    localStorage.name = prompt('初めまして>< 名前を教えてください')
}

// 簡単にデータを取り出せます
document.write(localStorage.name + 'さんこんにちは!');
</script></body>
</html>

たった 4 行です。
この HTML を DOM Storage に対応しているブラウザで見ると、最初の一回だけ名前を聞かれて以降は聞かれないという挙動をします。
サンプルはこちら
簡単ですね!

よく分からない><

もう少し説明します。
当たり前のことですが、普通の JavaScript のオブジェクトってページ遷移すると値を失いますよね。

object.count = object.count || 0;
object.count++;
alert(object.count);

でも、 localStorage というオブジェクトのプロパティに値を代入しておくと、ページ遷移後でも値が保存されたままになるのです。

localStorage.count = localStorage.count || 0;
localStorage.count = parseInt(localStorage) + 1; // localStorage には文字列として保存されるので、 parseInt が必要
alert(localStorage.count);

それが DOM Storage です。

オブジェクトとかもぶち込めるの?

ぶち込めることはぶち込めるのですが、データはすべて文字列化されて保存されます。
つまり、"[object Object]" というような文字列が保存されたりします。

具体的にはどう嬉しいの?

今までの Web アプリケーションでは、クライアントデータの保存はほとんどサーバサイドで行われていました。
DOM Storage を使うと、ローカルのデータはローカルに保存するという当たり前のことが出来るようになります。
使われ方としては、

  • 設定や状態の保存
  • 大きなデータの一時的な保存
  • HTML や JSON などのキャッシュ

メリットとしては

  • サーバ資源の節約
  • パフォーマンスの改善

などがあげられます。

どのブラウザで使えるの?

DOM Storage は以下のブラウザで使うことができます。

新しいブラウザでは、軒並み使えるようになる予定ですので、当然 Opera でも対応してくることになると思います。

新しい仕様と古い仕様

ただ一つ、注意する点は DOM Storage には古い仕様と新しい仕様があって、

  • 古い仕様を実装しているブラウザ
    • Firefox2
    • Firefox3
  • 新しい仕様を実装しているブラウザ

となっています。
一番最初に書いた例は、新しい仕様での書き方なので、実際には古い仕様でも動くように改造する必要があります。
改造と言っても単純で、

<!DOCTYPE html>
<html>
<head><title>DOM Storage の使い方</title></head>
<body><script>
// *** この 1 行を追加するだけ
window.localStorage = window.localStorage || window.globalStorage[location.hostname];
// *** この 1 行を追加するだけ

if (!localStorage.name) {
    localStorage.name = prompt('初めまして>< 名前を教えてください')
}
document.write(localStorage.name + 'さんこんにちは!');
</script></body>
</html>

上の例のように 1 行を追加するだけです。

具体的に保存できる容量は?

容量は仕様には定義されていませんが、例えば IE8 では 10 MB の大容量を扱うことができます。
Safari4Firefox の容量を知っている人がいれば教えてください><

仕様の全貌

この DOM Storage というものの仕様は HTML5 という仕様の一部で、Structured client-side storageという章で定義されています。

localStorage と sessionStorage

ここまで、 localStorage しか紹介してきませんでしたが、 DOM Storage には以下の二つのオブジェクトがあります。

  • localStorage
  • sessionStorage

localStorage はブラウザを落としても、データが残るオブジェクトで、 sessionStorage はそのタブ(ウィンドウ)が起動している間だけデータを保持します。

データの追加、書き換え

ここまでの例では、代入によるデータの追加方法だけを紹介していましたが、 setItem 関数によるデータの追加方法もあります。

localStorage.setItem('hoge', 'fuga'); // localStorage.hoge = 'fuga'; と同じ意味
sessionStorage.setItem('hoge', 'fuga'); // sessionStorage.hoge = 'fuga'; と同じ意味
データの参照

データの参照方法はプロパティとしての参照方法以外に、 getItem 関数による参照方法があります。

alert(localStorage.getItem('hoge')); // alert(localStorage.hoge); と同じ意味
alert(sessionStorage.getItem('hoge')); // alert(sessionStorage.hoge); と同じ意味
データの削除

データの削除方法は delete 演算子、または、 removeItem を使います。

delete localStorage.hoge;
localStorage.removeItem('hoge');
データの列挙

保存されたデータの列挙方法は、 length プロパティと key 関数を使います。

for (var i = 0; i < localStorage.length; i ++) {
  var key = localStorage.key(i);
  var data = localStorage.getItem(key);
}

length プロパティは保存されたデータの個数を表し、 key 関数は数値を受け取りデータのプロパティ名(キー)を返します。

データが共有される範囲

データは同じ origin (プロトコル + ドメイン + ポート)で共有されます。
例えば、

storage イベント

DOM Storage は同じドメインなら複数のドキュメント間で共有できるのが便利ですが、別のページから突如書き換えられてしまう可能性があります。
そのような場合を細かく制御するために、 storage イベントというものが存在します。
使い方は、以下のようになります。

document.onstorage = function(e) {
  e = e || envet; // for IE

  if (e.window != window) { 
    alert(
      '別のドキュメントによって' +
      e.key + 'が' +
      e.oldValue + 'から' +
      e.newValue + 'に書き換えられました!');
  }
};

上の例のようにイベントオブジェクト e の

  • e.window には、書き換えたドキュメントの window オブジェクトが、
  • e.key には、追加したデータのプロパティ名(キー)が、
  • e.oldValue には、書き換えられる前のデータが、
  • e.newValue には、書き換えられた後のデータが、

入っています。

でも IE6, IE7 ユーザーが・・・そんなあなたに

「一番ユーザが多いブラウザ(IE6 と IE7)で使えないんじゃ、いくら便利なものとは言え使えないよ><」というのはもっともだと思います。
でも、そこで諦める必要はありません。 IE 独自の機能を使って、IE6, IE7 でも DOM Storage が使えるようになってしまう夢のようなライブラリ「Ex DOM Storage」が今日リリースされました。
これで、思う存分 DOM Storage を使い倒すことができます。素晴らしい!

簡単な使い方

以下のように、 script タグを読み込んでやるだけです!簡単!

<html><head>
  <title>hoge</title>
  <script src="http://svn.coderepos.org/share/lang/javascript/exdomstorage/trunk/src/exdomstorage.js"></script>
</head>
<body>...</body>
</html>

ただし、自分のサーバーに置くときは、この js ファイル以外にも以下のリンク先にあるファイルをすべて置いて、適切な mime-type を設定しなければなりません。
http://svn.coderepos.org/share/lang/javascript/exdomstorage/trunk/src/

さらに詳細な情報は

作者様のページをどうぞ

まとめ

  • IE8 や Safari4 からは、 DOM Storage が使えるようになる。
  • Firefox では古い仕様だが、簡単に新しい仕様と同じように使うことができる。
  • IE6 や IE7DOM Storage を使えるようにするためのライブラリがリリースされた。

という訳で、 DOM Storage は未来の技術から、現在使える技術へと姿を変えました。皆様も DOM Storage を使って、クライアントサイドのパワーをフルにいかした Web アプリケーションを作ってみてはいかがでしょうか。

IE8 の DOM オブジェクトが呼び出し可能な件

なんだこれ

if (document('hoge') === '[object HTMLDocument]') alert('Oops!');
if (document.body('hoge') === '[object HTMLBodyElement]') alert('Oops!');
if (document.getElementById('target')('hoge') === '[object HTMLDivElement]') alert('Oops!');

HTML5 の DOCTYPE 宣言って IE6 でも標準モードになるんですね

HTML5 の DOCTYPE 宣言

<!DOCTYPE html>

ですが、今までなんとなく「どーせ IE6 では互換モードなんでしょー」って感じで生きてきたんです。
ごめんなさいごめんなさい><

サンプルコード

確認してみてください

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>HTML5 の DOCTYPE 宣言とレンダリングモードのテスト</title>
    </head>
    <body>
        <h1>HTML5 の DOCTYPE 宣言とレンダリングモードのテスト</h1>
        <dl>
            <dt>CSS1Compat</dt>
            <dd>標準モード</dd>
            <dt>BackCompat</dt>
            <dd>互換モード</dd>
        <dl>
        <script type="text/javascript">alert(document.compatMode)</script>
    </body>
</html>

まとめ

今度から HTML5 でコーディングすることにしてみます。(当然ブラウザが対応してない nav とか section とかは使いませんが)

【速報】IE8 Beta 2 で DOM オブジェクトに対して Getter / Setter を追加できるように!

さっき IE8 Beta 2 が出ましたね!

ということで、インストールをしてみました!


IE8 Beta 2 の DOM オブジェクトに以下の Getter Setter 用の関数群を発見!

  • __defineGetter__
  • __defineSetter__
  • __lookupGetter__
  • __lookupSetter__

ちゃんと動いている見たいです!
これは本当にすごいです!感動!

var body = document.body;

// IE にだけ存在しない
// textContent プロパティを body に作ってみる
body.__defineGetter__(
    'textContent',
    body.__lookupGetter__('innerText'));

body.__defineSetter__(
    'textContent',
    body.__lookupSetter__('innerText'));

body.textContent = 'ほげほげ';

// ・・・!!

ご・・・ごくり・・・

使えるのは DOM オブジェクトだけ

ただ、現状では window や document や要素オブジェクトや属性オブジェクトやイベントオブジェクトなど、 DOM 系のオブジェクトでしか使うことができないようです。

まとめ

IE8 では DOM オブジェクトのプロトタイプを取得する手段がないので、使われる場面は多少限定的になるでしょうが、これはとても大きな変化です。
DOM Scripting が大きく変わるかも知れません。
また、今は時間がないので、具体的に何に役に立つのかは時間のある土日とかにいろいろ試してみたいと思います!
ではでは!
Enjoy JavaScripting!