“userData” – Alphabetical Advent Calendar 2013
この記事は賞味期限切れです。(更新から1年が経過しています)
“U” は userData の “U”。
userData
userData は、旧来の Internet Explorer で使用出来るローカルのストレージです。 ローカルの記憶領域というと今では Web Storage がありますが、 しばしばその代替として使用されています。
何が凄いのかというと、これが IE5(1999年)から実装されている点で、 Web黎明期を少し抜けたあたりで Web Storage に近しい物が既に存在していたという事になります。 一方の DOM Storage はIE8からサポートされている為あまり出番はないかもしれませんが、 いまだ息が絶えないIE6-7対応で活躍する事ができます。
Cookie との比較
Web Storage の代替として広く使われている Cookie と比較すると、容量と範囲で大きな差があります。
- 容量
- userData: およそ1MB
- Cookie: およそ5KB
- 範囲
- userData: 同じディレクトリ内のみ
- Cookie: フレキシブルに設定可能
容量は、5MBほど利用できる Web Storage には及びませんが、Cookie と比較するとかなり大きいです。 その半面、データを共有出来る範囲が同じディレクトリ内に限られてしまいます。 互いに一長一短なので、場面によってい使い分けたいところです。
userData の使い方
userData は IE独自の behavior でスタイル指定をして使います。 下の例では input 要素にしていますが、恐らくどの要素でも使えると思います。
<input type="hidden" id="my-storage" style="behavior:url(#default#userData)">
<script>
var myStorage = document.getElementById("my-storage");
myStorage.load("myStorageData");
</script>
#default#userData を behavior で指定した要素は userData を使用する為のメソッドが使えるようになります。
- load(name): ストレージからデータをロードする
- save(name): ストレージにデータを保存する
- getAttribute(key): 値を取得する
- setAttribute(key, value): 値をセットする
- removeAttribute(key): 値を削除する
ストレージ名を “myStorageData” とし、適当な値を設定してみる例です。 ロードとセーブが都度必要になる以外は、別段注意すべき所はなさそうですね。
myStorage.load("myStorageData");
myStorage.setAttribute("name", "john");
myStorage.setAttribute("email", "john@example.com");
myStorage.save("myStorageData");
ストレージに使用する要素を動的に生成する事もできますが、DOMに追加されていないと働かないので注意が必要です。 動的生成の際には addBehavior メソッドが便利です。
var myStorage = document.createElement("input");
myStorage.setAttribute("type", "hidden");
myStorage.addBehavior("#default#userData");
document.body.appendChild(myStorage);
myStorage.load("myStorageData");
localStorage の polyfill を userData で書いてみる
少し長くなりますが、IE7以下向けの localStorage の代替処理を書いてみます。 先述の通り、同じディレクトリ内でしかデータを共有する事は出来ません。
(function(){
// Detect supports
if("localStorage" in window || ! ("addBehavior" in document.body)){
return;
}
// Create element for strage
var createStorage = function(name){
var input = document.createElement("input");
document.getElementsByTagName("head")[0].appendChild(input);
input.setAttribute("type", "hidden");
input.addBehavior("#default#userData");
input.load(name);
input._commit = function(){
this.save(name);
};
return input;
};
// Storage and index object
var storage = createStorage("altLocalStorage");
var index = createStorage("altLocalStorageKeys");
// Fetures for index
index._get = function(){
var keys = this.getAttribute("keys") || "";
if(keys){ return keys.split(","); }
return [];
};
index._indexOf = function(key, keys){
var i=0; keys = keys || this._get();
for(; i<keys.length; i++){
if(keys[i] === key){ return i; }
}
return -1;
};
index._set = function(keys){
this.setAttribute("keys", keys.join(","));
this._commit();
};
// API
window.localStorage = {
setItem: function(key, value){
var keys;
if(index._indexOf(key) < 0){
keys = index._get();
keys.push(key);
index._set(keys);
}
storage.setAttribute(key, value);
storage._commit();
},
getItem: function(key){
return storage.getAttribute(key);
},
removeItem: function(key){
var keys, i;
keys = index._get(),
i = index._indexOf(key, keys);
if(i >= 0){
keys.splice(i, 1);
index._set(keys);
}
storage.removeAttribute(key);
storage._commit();
},
clear: function(){
var i = 0, keys = index._get();
for(; i<keys.length; i++){
storage.removeAttribute(keys[i]);
}
storage._commit();
index._set([]);
}
};
}());
保存されたデータを列挙する手段が見つからなかった為、キーを保存するストレージを別に作っています。 clear メソッドを実装しなければそれは必要ないので、半分以下のコード量に収まると思います。
余談ですが、IEの開発者ツールでモードを Internet Exlorer 7 にしても “localStorage” は実装されてしまっていますので、 上のコードはネイティブのIE7でないと検証する事が出来ません。
参考資料
追記
- 2014/01/23
- コードの誤りを修正(urlの欠如)
コメント