Hatena::ブログ(Diary)

Firefoxアドオンとか このページをアンテナに追加 RSSフィード

ホームページ
 Firefoxアドオンの作り方
 Read All Tweets(タイムラインを逆順に)
 検索ボックス自動入力(学習機能付き)
 定期的にチェック!

2009-05-19

nsIAlertsService の代替

2009/06/10 追記:ライブラリ化しました。

2009/06/22:スペルミスを修正

f:id:masahal:20090130110058p:image

nsIAlertsServiceWindows でしか使えない、複数行を表示するのは面倒などの問題があるので、代替する方法です。

次のようなファイルを作ります。

alert.xul(chrome://sample/content/alert.xul)

<!-- nsIAlertsService で使われるのと同じ css ファイル -->
<?xml-stylesheet href="chrome://global/skin/alerts/alert.css" type="text/css"?>

<window id="alertNotification"
        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        windowtype="alert:alert"
        xmlns:xhtml2="http://www.w3.org/TR/xhtml2"
        xmlns:wairole="http://www.w3.org/2005/01/wai-rdf/GUIRoleTaxonomy#"
        xhtml2:role="wairole:alert"
        pack="start"
		onload="sampleAlert.onAlertLoad()">
  <script type="application/x-javascript" src="chrome://sample/content/alert.js" />
  <hbox id="alertBox" class="alertBox" orient="horizontal">
		<hbox class="alertImageBox" pack="center" align="center">
		<!-- アイコン画像  -->
		<image id="alertImage" />
		</hbox>
		<vbox id="alertTextBox" class="alertTextBox">
			<description id="alertTitle" class="alertTitle plain" /> 
			<!-- テキストが入る vbox 要素 -->
			<vbox id="alertTexts">
			</vbox>
		</vbox>	
  </hbox>

  <!-- onload イベントが発生する前に高さと幅を設定するため、インラインで実行する  -->
  <script type="application/x-javascript">sampleAlert.prefillAlertInfo();</script>
</window>

"chrome://global/content/alerts/alert.xul"を元にしています。

alert.js(chrome://sample/content/alert.js)

var sampleAlert={
disableAnimation : null,//alert window のアニメーションが有効かどうか
openTime : null,//alert window を表示する時間(ミリ秒)
finalHeight : 0,//alert window の最終的な高さ
slideTime : 10,//alert window をアニメーションする場合何ミリ秒周期でスライドさせるか
slideIncrement : 1,//スライドさせる単位

prefillAlertInfo : function(){
	var icon = window.arguments[0].icon;
	var title = window.arguments[0].title;
	var text = window.arguments[0].text;
	
	sampleAlert.disableAnimation = window.arguments[0].disableAnimation;
	sampleAlert.openTime = window.arguments[0].openTime;
	if(!sampleAlert.openTime) sampleAlert.openTime = 3000;
	
	var alertImage = document.getElementById("alertImage");
	alertImage.src = icon;
	var titleDescription = document.getElementById("alertTitle");
	titleDescription.value=title;

	//行ごとに description 要素を作ってテキストを入れていく
	var lines = text.split("\n");
	var textBox = document.getElementById("alertTexts");
	for(var i=0; i<lines.length; i++){
		var remLabel = document.createElement("description");
		remLabel.setAttribute("value", lines[i]);
		remLabel.setAttribute("class", "alertText plain");
		textBox.appendChild(remLabel);
	}
},
onAlertLoad : function(){
	//alert window のサイズを中身に合わせる
	window.sizeToContent();
  

	//Alert window の最大高さ設定
    var alertSliderMaxHeight = window.arguments[0].maxHeight;
	if(alertSliderMaxHeight>0) {
		//最大高さ設定よりも大きい場合はそれを最終的な高さにする
		if (window.outerHeight > alertSliderMaxHeight){
  			window.outerHeight = alertSliderMaxHeight;
		}
	}

	//アニメーションが有効かどうか
	if(sampleAlert.disableAnimation){
	//アニメーション無しの場合
		//スクリーンの右下に表示する
		window.moveTo( (screen.availLeft + screen.availWidth - window.outerWidth) - 10,
			screen.availTop + screen.availHeight - window.outerHeight);
		sampleAlert.playAlertSound();
		setTimeout(sampleAlert.closeAlert,sampleAlert.openTime);
	}
	else{
	//nsIAlertsService と同様の徐々にあがっていくアニメーションを入れる場合
	    //元の高さを最終的な高さとして設定
	    sampleAlert.finalHeight = window.outerHeight;
		//高さを1にしてアニメーションを行う
		window.outerHeight = 1;
		//スクリーンの右下に表示する
		window.moveTo( (screen.availLeft + screen.availWidth - window.outerWidth) - 10,
			screen.availTop + screen.availHeight - window.outerHeight);
		setTimeout(sampleAlert.animateAlert, sampleAlert.slideTime);
	}
},
animateAlert : function(){
	if ( window.outerHeight == 1 ) {
		sampleAlert.playAlertSound();
	}
	if (window.outerHeight < sampleAlert.finalHeight){
		window.screenY -= sampleAlert.slideIncrement;
		window.outerHeight += sampleAlert.slideIncrement;
		setTimeout(sampleAlert.animateAlert,sampleAlert.slideTime);
	}
	else setTimeout(sampleAlert.closeAlert, sampleAlert.openTime);  
},
playAlertSound : function(){
	//効果音が有効でないなら
	var enableSound = window.arguments[0].enableSound;
	if(!enableSound) return;
	
	var sound = Components.classes["@mozilla.org/sound;1"].createInstance(Components.interfaces.nsISound);
	//鳴らす音楽ファイル(wave)
	var filePath = window.arguments[0].soundFile;
	//鳴らすファイルを指定しない場合、デフォルト音
	if (!filePath){
		sound.beep();	
	}
	else {
		try{
			var file = Components.classes["@mozilla.org/file/local;1"]
							.createInstance(Components.interfaces.nsILocalFile);
			file.initWithPath( filePath );						
   			var ios = Components.classes['@mozilla.org/network/io-service;1']
   						.getService(Components.interfaces.nsIIOService);
			var fileURI = ios.newFileURI(file);	
			sound.play(fileURI);
		}catch(e){};
	}
},
closeAlert : function(){
	if(sampleAlert.disableAnimation) window.close()
	else{
		if (window.outerHeight > 1){
		    window.screenY += sampleAlert.slideIncrement;
    		window.outerHeight -= sampleAlert.slideIncrement;
    		setTimeout(sampleAlert.closeAlert, sampleAlert.slideTime);
		}
		else window.close(); 
	}
}
}

以下のコードから呼び出します。

var alertsFile = "chrome://sample/content/alert.xul";

//ウィンドウ左に表示される画像
var icon = "chrome://mozapps/skin/xpinstall/xpinstallItemGeneric.png"
var title="title";
var text="text1\ntext2";
//音を鳴らすかどうか
var enableSound = true;
//鳴らす場合、音のファイル(指定しない場合ビープ音になる)
var soundFile = "C:\\WINDOWS\\Media\\chimes.wav";
//徐々に表示されるアニメーションを無効にするかどうか
var disableAnimation = true;
//ウィンドウを開く時間(ミリ秒、デフォルトで3000)
var openTime = 3000;
//最大制限高さ。指定しない、または0にした場合、制限なし。
var maxHeight=0;

var newOptions = { icon : icon, title: title, text: text, enableSound : enableSound,
					soundFile : soundFile, disableAnimation : disableAnimation,
	  				 openTime : openTime, maxHeight : maxHeight};
window.openDialog(alertsFile, "alert:alert",
				"chrome,dialog=yes,titlebar=no,popup=yes", newOptions );

実際にコードを組み込む場合 sample とついている変数をすべて自アドオンのものに変更してください。

ReminderFoxソースを参考にしました。

window.open について

window.open - MDC

piro_orpiro_or 2009/05/20 18:42 非常に有用だと思いました。
いろんなアドオン作者が衝突を気にせず気軽に使えるような形でのライブラリ化も、ご検討いただけると嬉しいです。

masahalmasahal 2009/05/21 12:12 ライブラリ化というのはだいたい piroさんがやってるような感じ( http://piro.sakura.ne.jp/xul/lib/src/keyDetecter.xul )にすればいいんでしょうか。
仕様など、作るにあたって気をつけることとかありますか?

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証