素人がプログラミングを勉強していたブログ

プログラミング、セキュリティ、英語、Webなどのブログ since 2008

連絡先: twitter: @javascripter にどうぞ。

履歴管理(失敗)

dataスキームを使えば、戻るボタンを押した時に関数を呼び出したりできるようになるようだ。
iframeのcontentWindowにオブジェクトを登録しても、ガベージコレクションで消されてしまうようなので、window.parentを辿ることにした。
戻るボタンでいきなり複数同時に移動されたりすると、順序が狂ってしまうようなので、失敗。

window.HistoryManager = this.HistoryManager = 
function HistoryManager() {
  this.iframe = document.createElement('iframe');
  this.iframe.style.display = 'none';
  document.body.appendChild(this.iframe);
  this.hooks = [];
  this.list = [];
}

HistoryManager.getInstance = function () {
  if ('instance' in this) {
    return this.instance;
  }
  this.instance = new HistoryManager();
  return this.instance;
};

HistoryManager.prototype.add = function (object) {
  this.iframe.src = 
    'data:text/html,' + 
    <html>
      <script id={Date.now()}><![CDATA[
        window.addEventListener('beforeunload', function () {
          var manager = window.parent.HistoryManager.getInstance();
          var index = document.getElementById('val').value;
          var key = manager.list[index];
          manager.hooks.forEach(function (fun) {
            fun(key);
          });
        }, false);
      ]]></script>
      <input id="val" value={this.list.length}></input>
    </html>.toXMLString();
  this.list.push(object);
};

HistoryManager.prototype.hook = function (fun) {
  this.hooks.push(fun);
};

this.manager = HistoryManager.getInstance();

manager.hook(function(key) {
  console.log(key);
});

manager.add(new Date());

location.hashを変更して、setIntervalでlocation.hashの変更をチェックする方法のほうがいいかもしれない。
この方法だと、きちんと作ればブックマークすることもできるようになる。
以下、IE8のhashchangeイベントをFirefoxで再現する方法。

var hash = location.hash;

setInterval(function () {
  if (hash != (hash = location.hash)) {
    var evt = document.createEvent('Event');
    evt.initEvent('hashchange', true, true);
    document.body.dispatchEvent(evt);
  }
}, 50);

document.addEventListener('hashchange', function (e) {
  console.log('hashchange!', e);
}, false);