Mach3.laBlog

“userData” – Alphabetical Advent Calendar 2013

この記事は賞味期限切れです。(更新から1年が経過しています)

“U” は userData の “U”。

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の欠如)

コメント

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*