「GMailと各種ブログ編集画面に[校正する]ボタンを追加するグリモン」のコードと雑記

これまでbookmarkletをちょこちょこ作るぐらいで、greasemonkeyを触りだして数日なので結構いろんな所ではまりました。XPathも最初意味が分からなかったです。
一応今回のコードはこんな感じです。

// ==UserScript==
// @name           hatena_de_japaneseproofreader
// @namespace      http://d.hatena.ne.jp/Koonies/
// @description    GMailと各種ブログ(はてなダイアリー、FC2ブログ、Yahoo!ブログ、Seesaa、livedoorブログ)の記事編集のページに「校正する」ボタンを追加します
// @include        http*://mail.google.com/mail/h/*
// @include        http://d.hatena.ne.jp/*/edit*
// @include        http://blog*.fc2.com/control.php?mode=editor&process=*
// @include        http://blogs.yahoo.co.jp/*/MYBLOG/write.html*
// @include        http://blog.seesaa.jp/pages/my/blog/article/*/input*
// @include        http://livedoor.blogcms.jp/blog/*/article/edit*
// @include        http://mixi.jp/edit_diary.pl?*
// @include        http://mixi.jp/add_diary.pl?*
// @version        1.0
// ==/UserScript==

//[校正する]ボタンを押すと新しい画面で日本語文章校正ツール(http://www.japaneseproofreader.com/)を開きます
//ブログ校正用ブックマークレット(http://www.japaneseproofreader.com/sendblog.html)がベースです
//
//ポップアップがブロックされないよう設定してからご使用ください。
//また個人情報や会社機密など第三者の目に触れる可能性がありますのでよくご理解の上、ご利用をお願い致します。
//本スクリプト使用の結果、いかなるトラブルが起きても、当方では一切の責任を負いませんのでご了承ください。
//
//■その他
//GMail:簡易HTMLモードでのみ有効になります。(簡易HTMLモードは→https://mail.google.com/mail/h/)
//livedoorブログ:一度「プレビューボタン」を押してから「校正する」を押してください。

(function(){
	var arr = [
		{
			"url"     : 'mail\.google\.com',
			"title"   : '//input[@name="subject" and @class="i"]',
			"body1"   : '//textarea[@name="body" and @class="mi"]',
			"body2"   : '',
			"body3"   : '',
			"preview" : '//input[@type="submit" and @name="nvp_bu_send"]'
		},
		{
			"url"     : 'd\.hatena\.ne\.jp',
			"title"   : '//input[@name="title"]',
			"body1"   : '//textarea[@id="textarea-edit"]',
			"body2"   : '',
			"body3"   : '',
			"preview" : '//input[@type="submit" and @name="preview"]'
		},
		{
			"url"     : 'blog.+\.fc2\.com',
			"title"   : '//input[@id="entry_title"]',
			"body1"   : '//textarea[@id="body"]',
			"body2"   : '//textarea[@id="extend"]',
			"body3"   : '',
			"preview" : '//input[@type="submit"]'
		},
		{
			"url"     : 'blogs\.yahoo\.co\.jp',
			"title"   : '//input[@name="title" and @class="frm_txt"]',
			"body1"   : '//textarea[@name="content" and @class="frm_textarea"]',
			"body2"   : '',
			"body3"   : '',
			"preview" : '//a[@href="javascript:submitAll(1)"]'
		},
		{
			"url"     : 'blog\.seesaa\.jp',
			"title"   : '//textarea[@name="article__subject"]',
			"body1"   : '//textarea[@id="article__body"]',
			"body2"   : '//textarea[@id="article__body_more"]',
			"body3"   : '',
			"preview" : '//input[@type="submit" and @name="confirm"]'
		},
		{
			"url"     : 'livedoor\.blogcms\.jp',
			"title"   : '//input[@id="entryTitle"]',
			"body1"   : '//textarea[@id="inputBody"]',
			"body2"   : '//textarea[@id="inputBodyMore"]',
			"body3"   : '//textarea[@id="inputBodyPrivate"]',
			"preview" : '//input[@id="previewButton"]'
		},
		{
			"url"     : 'mixi\.jp',
			"title"   : '//input[@name="diary_title" and @class="editareaWidth"]',
			"body1"   : '//textarea[@id="diaryBody"]',
			"body2"   : '',
			"body3"   : '',
			"preview" : '//input[@type="submit" and @class="formBt01"]'
		}
/*
		{
			"url"     : '',
			"title"   : '//',
			"body1"   : '//',
			"body2"   : '',
			"body3"   : '',
			"preview" : '//'
		}
*/
	];
	
	var debug=1;
	var xpath;
	var cnt=0;
	var i=arr.length;
	
	//while((i--) && (location.host.indexOf(arr[i]["url"]) == -1));
	while((i--) && (!location.host.match(arr[i]["url"])));
	
	if (i<0) {
		if (debug) console.log("アドレスのマッチングに失敗しました:" + location.host);
		return;
	}
	
	xpath = arr[i];
	
	/*document.addEventListener*/ 
	window.addEventListener(
		'load',
		function() {
			cnt++;
			if (cnt>1) return;
			
			var kakunin= document.evaluate(xpath["preview"],document,null,7,null).snapshotItem(0);
			
			if (debug) {
				//alert("stop");
				console.log( xpath["url"]);
				console.log( "title:"   + document.evaluate(xpath["title"  ],document,null,7,null).snapshotLength );
				console.log( "body1:"   + document.evaluate(xpath["body1"  ],document,null,7,null).snapshotLength );
				console.log( "body2:"   + document.evaluate(xpath["body1"  ],document,null,7,null).snapshotLength );
				console.log( "preview:" + document.evaluate(xpath["preview"],document,null,7,null).snapshotLength );
			}
			
			if (kakunin) {
				var kousei = document.createElement("input");
				kousei.type = "button";
				kousei.value = '\u6821\u6b63\u3059\u308b'; /* 校正する */
				
				kousei.addEventListener(
					'click',
					function() {
						var sendText = "TcheckON" + 
						               document.evaluate(xpath["title"],document,null,7,null).snapshotItem(0).value +
						               '\n\n' +
						               document.evaluate(xpath["body1"],document,null,7,null).snapshotItem(0).value;
						
						if (xpath["body2"]!='') {
							sendText = sendText +
							           '\n\n' +
							           document.evaluate(xpath["body2"],document,null,7,null).snapshotItem(0).value;
							
							if (xpath["body3"]!='') {
								sendText = sendText +
								           '\n\n' +
								           document.evaluate(xpath["body3"],document,null,7,null).snapshotItem(0).value;
							}
						}
						
						window.open('http://www.japaneseproofreader.com/',
						            sendText,
						            'resizable=yes,status=no,menubar=no,toolbar=no,location=no,scrollbars=yes');
					},
					true
				);
				
				kakunin.parentNode.insertBefore(kousei, kakunin.nextSibling);
				//kakunin.parentNode.insertBefore(kousei, kakunin);
			}
		},
		true
	);
	
})();

Chromeで作っていて、一応Firefoxでも見ておくかと思ったら動かない。。。

原因はdocument.addEventListenerでこれをwindow.addEventListenerに変えたらようやく動きました。
今日のコードで一番ここでハマりました。1時間くらいかなぁ。
addEventListener('load') - みずぴー日記
を参考にさせて頂きました。

それと今回のコードとは関係ないですが、

// @include        http://www.google.tld/*

Google Chromeだと認識しない(?)のもハマった一つ。
これと下記の

// @include        http://www.google.*

だと何か違いがあるんですかね?あちこち見たけど結局分かりませんでした。

まあ何にせよgreasemonkey、面白いです。
簡単に作れて、どんどん便利になる。まあちょと手の込んだことをしようとすると途端に難しくなるんですけども。