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

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

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

複数ウィンドウのスクロール、入力を同期するGreasemonkeyスクリプト(globalStorageを使った同ドメイン間のスクリプトの通信)

デモ動画:
2008-09-24_1540 - javascripter's library

// ==UserScript==
// @name           syncScroll
// @namespace      http://d.hatena.ne.jp/javascripter/
// @include        http*
// ==/UserScript==

GM_registerMenuCommand("start demo", function(e){
    syncScroll();
  });

function syncScroll(){
  var scrollService = new SyncService("scroll");
  scrollService.addListener(function(message){
      var [x, y] = eval(message);
      window.scrollTo(x, y);
    });
  window.addEventListener("scroll", function(e){
      scrollService.message(uneval([window.scrollX, window.scrollY]));
    }, false);
  var inputService = new SyncService("input");
  inputService.addListener(function(message){
      var o = eval(message);
      var [x, y] = o.pos;
      var elem = document.elementFromPoint(x, y);
      elem.value = o.value;
    });
  window.addEventListener("input", function(e){
      var elem = e.target;
      var pos = elem.getBoundingClientRect();
      inputService.message(uneval({pos: [pos.left, pos.top], value: elem.value}));
    }, false);
}

function SyncService(uname){
  this._uname = "SyncService" + uname;
  this._listeners = [];
  this._lastItem = null;
  this._listen();
}
SyncService.prototype.addListener = function(fn){
  this._listeners.push(fn);
};
SyncService.prototype.removeListener = function(fn){
  this._listeners.splice(this._listeners.indexOf(fn), 1);
};
SyncService.prototype.message = function(str){
  unsafeWindow.globalStorage[location.host].setItem(this._uname, str);
};
SyncService.prototype._listen = function(){
  var self = this;
  function listener(){
    var item =  unsafeWindow.globalStorage[location.host].getItem(self._uname);
    item && (item = item.value);
    if (item != self._lastItem){
      self._lastItem = item;
      self._listeners.forEach(function(fn){
          fn(item);
        });
    }
  }
  window.addEventListener("storage", listener, false);
  this._listener = listener;
  window.addEventListener("beforeunload", function(e){
      window.removeEventListener("storage", listener, false);
      unsafeWindow.globalStorage[location.host].removeItem(self._uname);
    }, false);
};

unsafeWindowを使ったり、JSONのパースにevalを使ったり、安全ではないので、使い終わったらオフにするかアンインストールするべき。