読者です 読者をやめる 読者になる 読者になる

グリモンを書いてるときにはまったところ

tech

Close Blockというグリモンを書いてるときにXPCNativeWrapperというものではまってのでメモ。
引用文とかソースコードを開閉するグリモン - maru source

XPCNativeWrapper

グリモンをだと以下のコードだと上手く動かない。

var div = document.getElementsByTagName("div")[0];
div.ondblclick = myFunc;

alert(div)してみると

[object XPCNativeWrapper [object HTMLDivElement]]

と出てくる。

ネットで調べてみるとXPCNativeWrapperというのはMozillaがセキュリティのために実装してるものだということが分かりました。
詳しくは以下のサイトで。
XPCNativeWrapper | MDN
Greasemonkeyの共通な落とし穴を避ける - minghaiの日記


回避策としては

  • wrappedJSObjectを使ってオリジナルを取り出す。
  • setAttribute() , addEventListener()を使ってXPC経由で処理をする

正直僕はXPCのことをあまりよく分かっていないです。けどセキュリティのためにXPCでラップされているということならwrappedJSObjectは極力使わないほうがいいのかと思い、愚直にsetAttribute等を使うことにしました。

addEventListenerした関数を手動で呼び出せない

だいたいは上手く動くようになったのですが、addEventListenerした関数を手動で呼び出す方法が分からなくて困りました。
XPCでラップされていない場合はaddEventListenerを使わずにプロパティに関数を登録して、実行することができます。

div.ondblclick = myFunc;
div.ondblclick();

function myFunc()
{
  alert(this.innerHTML);
}

でもXPCでラップされている場合はdiv.ondblclick = myFuncを実行できないので、addEventListenerを使うのですが、登録した関数を手動で呼び出すことができない。

div.addEventListener("dblclick" , myFunc , true);
//以下のようにはかけない
div.myFunc();

function myFunc()
{
  alert(this.innerHTML);
}

引数でオブジェクトを渡す

で結局悩んだ末に以下のように実装。引数にオブジェクトを渡してmyFunc内で対応。

div.addEventListener("dblclick" , myFunc , true);
myFunc(null , div);

function myFunc(e , obj)
{
  var target;
  if(obj){ target = obj; }
  else{ target = this; }

  alert(target.innerHTML);
}

う〜ん、すっきりしない><
何かいい方法があれば教えてください。