Subscribed unsubscribe Subscribe Subscribe

枕を欹てて聴く

香炉峰の雪は簾を撥げて看る

FirefoxのJSでdialogを拡張する

NortificationBoxみたいに最初からwindowから要素自体を取得することができないので、openDialogで作るしかない。
ただ、openDialogの第一引数はURIであり(本来ならここに、自分の作ったxulファイルへのURIを入れるが、今回はJSだけで何とかできないか模索)、簡単に空のDialog要素を取得することが難しい。

// utility functions
var XUL_NAMESPACE = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
var HTML_NAMESPACE = "http://www.w3.org/1999/xhtml"
var Cc = Components.classes;
var Ci = Components.interfaces;

// 現在のwindowを取得する
var WindowMediator      = Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator);
function getMostRecentWindow(){
  return WindowMediator.getMostRecentWindow('navigator:browser');
}

// Dialog Class
function Dialog({id,title,init}){
  this.id = id || "test";
  this.title = title || "test";
  this.init = init;
}

Dialog.prototype = {
  show: function(){
    var self = this;
    // 解決策として、data URIを使うという無理やりな選択肢
    var str=<><dialog id={this.id} title={this.title} xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml"></dialog></>.toXMLString();
    var data = 'data:application/vnd.mozilla.xul+xml;charset=utf-8,<?xml version="1.0"?><?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>'+str;
    var w = getMostRecentWindow().openDialog(data,'','');
    w.addEventListener('DOMContentLoaded',function(e){
      self.dialog = this.document.getElementById(self.id);
      self.init.call(this, e);
    },false);
  },
}

こんな感じで、

    var okfun = <><![CDATA[
    (function(){
     var dd = document.getElementById('test');
     alert(dd);
     return false;
     })()
    ]]></>.toString();

    var opt = {
      id:'test',
      title:'test2',
      init:function(){
        var doc = this.document;
        var dialog = doc.getElementById('test');
        var img = doc.createElementNS(HTML_NAMESPACE,'html:img');
        img.src = 'http://media.tumblr.com/TCJrI4Ms9bqdys0xNq1RSTSg_500.png'
        dialog.appendChild(img);
        // dialog.acceptDialog(); // OKを押したときと同じ処理が起こる
        dialog.setAttribute('ondialogaccept',okfun);
        dialog.setAttribute('ondialogcancel',"return true");
      },
    }

    var d = new Dialog(opt);
    d.show();

OKを押されたときの関数とかをまさかのCDATAセクション+toString()なんかで記述しないといけないとか、しかもその部分のスコープはdialog側で、呼び出し元スコープに定義してあるものが使えないとかまあなんというか使い物にならない。
利点は、dialogにappendChildとかjsでできること、xul書かなくてもjsだけで使えること。

独自のdialog使いたかったらやっぱxulで書いて、分離したほうが楽。
その点NortificationBoxは使いやすくて便利。