Archive for the ‘Greasemonkey’ Category

Post Now browsing to Twitterで設定画面が開かないバグ修正

Post Now browsing to Twitterで設定画面がうまく開かない現象が起きていたみたいで、以前はGM_configというGUI用のライブラリを使っていたのですが、今回usconfigに移行しました。
なので、今まで設定画面が開かないなどの現象が起きていた人はインストールしなおしてください。
(おかしいときは ツール→Greasemonkey(もしくはステータスバーの猿アイコン)→ユーザースクリプトの管理→Post Now browsing to Twitterを選択→✓関連付けられた設定も削除にチェック→アンインストール → インストール)

こっからはGM_configからUSConfigへ移行方法について。

GM_configは前から少し不安定な感じがあったので、同種のライブラリであるUSConfigに変えました。
GM_configとUSConfigの違いを簡単に挙げてみると(移行するに当たっての変更点)

まずはGUIの書き方が別物なので、そこはすべて書き直す必要があります。

GM_configの場合

GM_config.init('Configuration for Post Now browsing to Twitter', {
    'defaultTag': {
        'label': 'Prefix:',
        'type': 'text',
        'default':'Now browsing: '
    },
    'isSelection': {
        'label': 'Use selectionQuote',
        'type': 'checkbox',
        'default':true
    },
    'ShortURL': {
        'label': 'Short URL',
        'type': 'select',
        'options': {
            'bit.ly': 'bit.ly',
            'j.mp': 'j.mp',
            'goo.gl': 'goo.gl',
            'is.gd': 'is.gd',
            'tinyurl.com': 'tinyurl.com'
        },
        'default':'bit.ly'
    },
    'ShortCutKey': {
        'label': 'ShortcutKey:',
        'type': 'text',
        'default':'CS-Enter'
    },
    'PostWithCtrl': {
        'label': 'Post with Ctrl+Enter:',
        'type': 'checkbox',
        'default': false
    },
    'bitlyUserName': {
        'section': ['bit.ly'],
        'label': 'bit.ly Username:',
        'type': 'text',
    'default':
        'remiko'
    },
    'bitlyAPIKey': {
        'label': 'bit.ly APIKey :',
        'type': 'text',
        'default': 'R_fa2240c646c07b2091x'
    }
}, configStyle , {
    open: function () {
        // ショートカットの入力補助
        var iframe = document.getElementById("GM_config");
        var iframeDoc = iframe.contentDocument;
        iframeDoc.getElementById("field_ShortCutKey").addEventListener('keydown', function (evt) {
            evt.preventDefault();
            this.value = shortcut.get(evt);
        }, false);
        // OAuth Setting
        if (TWOauth.isAuthorize()) {
            TWOauth.injectToConfig();
        } else {
            XHRloading.createText(iframeDoc);
            TWOauth.getRequestToken(TWOauth.injectToConfig);
        }
    },
    save: function () {

    } // reload the page when configuration was changed
});

USConfigの場合

Config.define('usc_basic', function() {
	with (this.builder) {
		var shortURL_opt = [
			'bit.ly',
			'j.mp',
			'goo.gl',
			'is.gd',
			'tinyurl.com'
		]
		dialog(
			"Post Now browsing to Twitter Settings",
			{ width: 600, height: 700 },

				section(
						"User options",
						"Behavior/keyboard Preference",
						grid(
								text("Prefix:", 'defaultTag', "Now browsing: ", { size: 20 }), '\n',
								checkbox("Use selection quote", 'isSelection', true), '\n',
								checkbox("Post with Ctrl+Enter", 'PostWithCtrl', false), '\n',
								text("ShortcutKey:", 'ShortCutKey', "CS-Enter", { size: 16 })
								)
						),
				section(
						"Short URL options",
						"select used Short URL service",

						grid(
								select("Short URL Services", 'ShortURL', shortURL_opt, "bit.ly"), '\n',
								text("bit.ly Username:", 'bitlyUserName', "remiko"), '\n',
								text("bit.ly APIKey :", 'bitlyAPIKey', 'R_fa2240c646c07b2091c6bc6d109089ef', { size: 30 })
								)
						),
				section(
						"OAuth Authorization",
						"Sign in with Twitter"
						)
				);
	}
}, {
	saveKey: 'GM_config',
	aftersave: function() {

	},
	afteropen : function() {
		// ショートカットの入力補助
		var iframeDoc = this.frame.contentDocument;
		iframeDoc.getElementById("control_ShortCutKey").addEventListener('keydown', function (evt) {
			evt.preventDefault();
			this.value = shortcut.get(evt);
		}, false);
		// OAuth Setting
		if (TWOauth.isAuthorize()) {
			TWOauth.injectToConfig();
		} else {
			XHRloading.createText(iframeDoc);
			TWOauth.getRequestToken(TWOauth.injectToConfig);
		}
	}
});

二つを見比べると、GM_configはオブジェクトを定義する感じだけど、USConfigはその都度関数を呼び出す感じになってる。レイアウトの自由度はUSConfigの方が上ですが、ちょっとインデント管理が大変で書きにくい。
またUSConfigではselectに連想配列っぽいオブジェクトを使えないので、配列に直す必要があります。
後、Text() のデフォルトサイズが少し小さいので第4引数で属性にsizeを追加してます。
最後の空sectionはafteropen時に書き換えるようにしてるので、本質とはあんまり関係ないです。
USConfigの方がConfig.define()でのコールバック(afteropenなど)が豊富なので、細かい制御がしやすいと思います。
そのコードバックで設定画面のiframeをとるにはthis.frameとすればよいみたいです。

次に設定情報の取り出し方
GM_configがそのつど、keyを指定してvalueを取り出す感じだったのが(GreasemonkeyのGM_getvalueに近い)

GM_config.get(key);// value

USConfigでは設定全部をまとめたオブジェクトを最初にロードする感じになっています

var settings = Config.load();
settings.key;// value

また、設定を保存するキーの初期値はGM_configと違うのでそのまま移行させるためにはsaveKeyを’GM_config’にします。

Config.define('dialog_name', function() { with (this.builder) {
  dialog(...);
}}, {
  saveKey: 'GM_config',
  aftersave: function() {...},
});

後はGM_config.*()がConfig.*()など細かい違いあるので、それを手直しすれば移行できました。
(GM_config.close()がConfig.remove()だったのが少しはまった)

USConfig

slideshareのスライド内にでる広告を消すGreasemonkey

最近になってSlideShareではスライドの下部に広告が出るようになったので、それを自動で閉じて非表示にするGreasemonkeyです。

広告の閉じるx部分を自動でクリックする事で消しています。
全く興味のない広告をコンテンツを覆うように表示する広告は嫌いです。
UstreamのFlash動画内広告を消す方法 | Web scratchとかでも同じような方式広告が出ていますが、何度もでてきてウイルスみたいだ。
CNETとかマイコミジャーナルとかあの辺の広告も理解できない。

またニコニコ動画見てるGreasemonkeyのOAuth対応版

2010.8月末にTwitterのBASIC認証が終わったので、今までのまたニコぐりもんは動かなくなっていると思います。
なのでOAuth認証に対応してるまたニコニコ見てるを作ってみました。(作ったのは結構前だけどね)

使用方法

まずはニコニコ動画の動画ページでステータスバーのGreasemonkeyアイコンを右クリック→ユーザースクリプトコマンドからOAuth認証をする必要があります。

コマンドを実行するとOAuth認証のパネルが出てくるので、ボタンからTwitterへ行きOAuth認証してPINコードをコピーしてテキストエリアに入力すると準備完了です。

認証済みだったら動画タイトル部分にまたニコのボタンが出るので、それをクリックしてコメントを入力してまたボタンを押せばTwitterへ投稿できます。(nico.msのURLを使って投稿します。

オリジナルの機能としてはコメント入力欄の右側に文字数のカウンターが付いてるぐらいです。

mataniconicomiteru for Greasemonkey
http://userscripts.org/scripts/show/83795

 

OAuth for Greasemonkeyのラッパーライブラリ

Post Now browsing to TwitterをOAuth認証に対応しました | Web scratchでGreasemonkeyスクリプトの「Post Now browsing to Twitter」をOAuth認証に対応したものを作りました。
OAuthのJavaScript実装はいくつかあるみたいですがGreasemonkeyで使う感じになってるものは無かったみたいなので、OAuth.jsを使ったtwitterでのOAuth認証を手助けするラッパーみたいなものを書きました。

xAuthを使えば楽な気もしますがブラウザベースのものはxAuthを使わずにOAuthを使ってねとの事です

大部分は

を参考に書きました。
何となく分かるかも知れませんが、今回扱うアプリはApplication Typeがclientタイプのものです。

Read the rest of this entry »

Post Now browsing to TwitterをOAuth認証に対応しました

Twitterへ今見ているサイトをコメントと共に投稿する「Post Now browsing to Twitter」がOAuth認証に対応しました。
このGreasemonkeyをインストールする前に、以前のバージョン(2010年6月より前)のものを入れている場合はそれをアンインストールしてから、改めて「Post Now browsing to Twitter」をインストールして下さい。(以前と設定の互換が無くなったため設定ごと破棄をお勧めします)
ツール→Greasemonkey(もしくはステータスバーの猿アイコン)→ユーザースクリプトの管理→Post Now browsing to Twitterを選択→✓関連付けられた設定も削除にチェック→アンインストール

Read the rest of this entry »

GreasemonkeyにGrowlのような通知を呼ぶ機能を加える「Dbus Notify」

紹介するDbus Notify for GreaseMonkeyはGreasemonkeyスクリプトにGrowlのような通知を行うAPIを加えるアドオンです。
Greasemonkeyにcallout.notifyというAPIを追加するだけのシンプルなアドオンです。
使い方は単純でDbus Notify for GreaseMonkeyをインストールして、Greasemonkeyスクリプト内にcallout.notifyのAPIを使った記述を加えるだけで動きます。(当たり前だが、インストールしてない環境だと動かない)

APIは凄くシンプルで、callout.notify(title, message, [options])となっていて、タイトルはそのまま、メッセージはタイトルの下に表示されていて、optionのhrefが設定されている場合はリンクになる。

optionで設定できるのもhrefとiconぐらいで、Greasemonkeyからページの外側に通知を出したいなーって思う人はそれだけを求めるならアドオンなどにしないでこれを使うのもいいかも。

簡単なサンプル

gist: 426775 – Dbus Notify for GreaseMonkeyのテスト- GitHub
http://gist.github.com/426775

APIの解説

lackac’s callout at master – GitHub
http://github.com/lackac/callout

Greasemonkeyに何か機能を加えるアドオンって意外と見かけない感じがする。
Greasemonkey でクリップボードを扱う…悪い方法(?) – Griever でも言っているように受け口を持つと悪用の可能性も出てくるが、セキュリティ的な影響がでないように狭い範囲で機能追加できれば楽しそうだなーと思った。

メディアマーカーで楽しく読書管理する

メディアマーカーは読書管理を行えるWebサービスで、基本的な読書管理のシステムも優れていながら、Twitterへの連携やiPhoneアプリもあるので、とても使い勝手がよいサービスです。
今回は自分がどのようにメディアマーカーを使っているか、自分流の読書管理方法について書いてみる。

まず、読書管理について自分で心がけているのは

  1. どんな本だったかが直ぐ分かること
  2. 読書した本の登録が面倒くさくならないこと
  3. 読書管理を楽しめること

これを目標にしていろいろな読書管理方法を試してきました。
1のように後から見返したときにどんな本だったかを知るために読書した本を管理しているところが大きいので、以前はどんな内容だったかをレビュー形式で書いたりしていました。
しかし、本のレビューみたいに詳しく 書いていくと面倒臭さが増し2や3を破ってしまう事になり、あまり長くは続きませんでした。
(レビュー書く事が全く苦ではない人はブログや私本管理Plusを使って書きためるのもいいかもしれません)

後から見たときに本の内容を簡単に思い出す方法を考えていて思いついたのが、本の内容を貼り付けてしまえばいいと考えました。
つまり、本を読んでいるときに小説なら気になったフレーズ、漫画なら気になったコマをそのまま貼り付けてしまえばいい!
それを実現するためにとった方法は、本をカメラで撮影して画像にしてしまうという方法。
漫画などはこの方法で気になった部分を画像にできるし、小説はちょっとカメラに精度が必要となってしまうので、できなかった場合はiPhoneで気になったフレーズを書き写して、メディアマーカーiPhoneアプリで先に登録しておくといい。
最近流行ってる書籍の電子化で、既に電子化したものをビューアーで読んでいる場合はスクリーンショット機能を使って気になった部分を画像として保存しておく。
そうしてできた画像をDropboxのPublicフォルダに入れておいて外部からも参照できるようにしておく。
後は、メディアマーカーに数行のレビュー(レビューとはいえないレベル)とDropboxにある画像を貼り付けて画像を表示すれば、後から見たときに直ぐ内容が分かって便利になる。

簡単な書籍の内容についてと画像

簡単な書籍の内容についてと画像

この気になった部分を画像にして貼り付けるのは意外と楽しくて、かつ撮影してそこで直ぐ完結するので手間があまりかからない。特に電子化している場合はスクリーンショットを取るだけなので一瞬で終わる。
また画像を貼り付けるときに、Dropboxに一つの書籍について複数の画像がある場合、エクスプローラの”Copy Public Link”だと一個づつしかURLをコピーできないし、Imgタグで囲うのが面倒なのでコマンドラインで動くバッチのようなものを作る。

このProgram.csのdropboxPath部分を自分のDropbox環境に合わせてからコンパイルする。
csc.exeで以下のよう に指定するとコンパイルできる。(csc.exeの場所は.NETのどっかにあるかと、もしくはVisual Studio使うとか)

>C:\Windows\Microsoft.NET\Framework\v3.5\csc.exe Program.cs

コ ンパイルしてできたexeファイルにD&Dや送るからファイルを渡すと渡したファイルのURLをimgタグにしたものがクリップボードにコピーさ れるので、それをメディアマーカーに貼り付けるだけでよくなる。

さらにメディアマーカーは書籍登録時にタグをつけることができ、後から見返すときにそれらの情報をつけておくと分かりやすくなるため、タグ付けを補助するGreasemonkeyを導入する。

それぞれ、登録時にAmazonとbooklogにつけられている書籍のタグを表示してくれるので、クリックするだけで書籍に関係あるタグを追加できる。

補助ツールを使うことで書籍の登録の面倒臭さも低減されるし、何よりも書籍の内容を画像で表示するのは思っている以上に楽しい事だと思う。

evernote+iPhoneで似ている事をやっている人もいます。
やっぱりカメラで写真を撮るのと書き出すのは圧倒的に手間が違うし、いつも持ち歩いてるiPhoneでもカメラは何とかなることが多いので面倒な手間が結構減ります。

Blog Forest: 読書メモの作成にevernoteを使う
http://morimorishop.com/2009/03/evernote_2.html

evernoteなら画像のOCR機能があるので検索できるという淡い期待もありますが、 Amazonから情報を引っ張れたり他とは関係の情報を切り離して見られるメディアマーカーのようなサービスで書籍を管理した方が自分にとっては便利かなーと思う。
後から見返したときに楽しいというのも大きな点。
あくまでevernte+写真はメモにして、そこから文字を書き出すというのも一つの手であると思います。

以上。

おまけ、Dropboxの画像をPublic経由で表示してるので少し重たくなってしまう。
表示する画像をローカルのものと差し替えるGreasemonkey

@include
originSrc
newSrc
の三カ所を書き換える必要がある。

セキュリティの理由からpref.jsに以下を追加してメディアマーカーからローカルの画像を表示できるようにしておかないと機能しない。

user_pref("capability.policy.localfilelinks.checkloaduri.enabled", "allAccess");
user_pref("capability.policy.localfilelinks.sites", "http://mediamarker.net");
user_pref("capability.policy.policynames", "localfilelinks");
Muses Factory » Firefoxでcheckloaduri.enabledの設定が反映されない
http://reva.s28.xrea.com/archives/38.html

Greasemonkeyでサイト既存CSSの影響を受けないポップアップパネルを作る方法

Greasemonkeyは各サイトでユーザースクリプトを実行できて便利ですが、ある要素を挿入したときにそれがサイトに元々書いてあるCSSの影響を受けてしまうことがあります。
一つのサイトならまだしもhttp*で動くようなものだと対応仕切れないのでiframeを使いサイトに書いてあるCSSの影響を受けないパネルを作る。
iframeの中はそのサイトにあるCSSの影響を受けないので、iframe内にGreasemonkeyで表示したいものを置けば影響を受けないものが作成できる。
makeFrameというのが今回の主題。

makeFrame(gotFrame1);
makeFrame(gotFrame2);

function gotFrame1(iframe, win, doc) {
  iframe.height = "350";
  iframe.width = "500";
  iframe.style.position = "fixed";
  iframe.style.bottom = iframe.style.left = "0";
  doc.body.innerHTML += "Frame1ですね。"
}
function gotFrame2(iframe, win, doc) {
  iframe.height = "350";
  iframe.width = "500";
  iframe.style.position = "fixed";
  iframe.style.bottom = iframe.style.right = "0";
  iframe.style.backgroundColor = "#ddd";
  doc.body.innerHTML += "Frame2ですよ。"
}
// Creates a new iframe and attaches it to the DOM, waits for it to load, tests
// that we did not hit https://bugzilla.mozilla.org/show_bug.cgi?id=295813 nor
// https://bugzilla.mozilla.org/show_bug.cgi?id=388714 (and retries otherwise),
// to finally call the provided done callback, passing the iframe, its window
// and document. (The optional name parameter, if provided, will be used to name
// the iframe in window.frames, or be created as "pane-1" onwards, otherwise.)
/*
    var cacllback = function(iframe, win, doc){

    }
    makeFrame(cacllback);
    makeFrame(cacllback , "frameName");
    makeFrame(cacllback , "frameName" , true);// debug mode
*/
function makeFrame(callback/*(iframeTag, window, document)*/, name, debug) {
    function testInvasion() {
        iframe.removeEventListener("load", done, true);
        var message = ((new Date) - load.start) + "ms passed, ";
        try { // probe for security violation error, in case mozilla struck a bug
            var url = unsafeWindow.frames[framename].location.href;
            message += url == "about:blank" ? "but we got the right document." : "and we incorrectly loaded " + url;
            if (debug) console.log(message);
            done();
        }
        catch(e) {
            if (console && console.error && console.trace) {
                console.error(e);
                console.trace();
            }
            if (debug) console.log(message + "and our iframe was invaded. Trying again!");
            document.body.removeChild(iframe);
            makeFrame(callback, name);
        }
    }
    function done() {
        clearTimeout(load.timeout);
        if (debug) console.log("IFrame %x load event after %d ms", framename, (new Date) - load.start);
        var win = unsafeWindow.frames[framename];
        var doc = iframe.contentWindow.document;
        // 苦し紛れのエスケープ
        var esframeName = "'"+framename+"'";
        // 自分自身のiframeを閉じるボタン
        var xImg = doc.createElement("img");
        xImg.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAATElEQVQoka2RSQ4AIAgD+f+jp96M0aq49AgdUiB0qZCkONQ/EBAwDOrrU7A1uZqN2hodtNwRqNdz0VOg62+jzuDUcVzkf+/I6h28UQHjW25Gob5AIAAAAABJRU5ErkJggg=="
        xImg.setAttribute("onclick", "parent.document.getElementsByName("+esframeName+")[0].style.display='none';");
        xImg.setAttribute("style","background-color:red;border:3px;position:fixed;top:0px;right:0px");
        doc.body.appendChild(xImg);
        callback(iframe, win, doc);
    }
    var iframe = document.createElement("iframe");
    var framename = iframe.name = typeof name != "undefined" ? name : ("pane" + (makeFrame.id = (makeFrame.id || 0) - 1));
    iframe.setAttribute("style", "overflow:auto;z-index:18999; border:0; margin:0; padding:0;top:auto; right:auto; bottom:auto; left:auto;background-color:#fff");
    iframe.src = "about:blank";
    iframe.addEventListener("load", done, true);
    var frames = makeFrame.data || {};
    var load = frames[framename] || {
        start: new Date,
        sleepFor: 400
    };
    load.timeout = setTimeout(testInvasion, load.sleepFor);
    load.sleepFor *= 1.5;
    frames[framename] = load;
    makeFrame.data = frames;
    document.body.appendChild(iframe);
}

makeFrame関数は(callback ,[フレームのname , debugモード])という引数なので、gotFrame1という関数(callback)を引数にしてmakeFrameを読んでいる。 callbackには(iframe, iframeのwindow, iframeのdocument)が入ってるいるので、iframeのstyleをいじればパネルの色やサイズ、表示する場所などを指定できる。 上記のソースだと左下にframe1、右下にframe2が表示できる。

表示例

元ネタからの改良点

  • パネルを閉じるボタンの追加

それぞれのパネル右上に表示されているxボタンは、パネルを閉じるボタンとして機能している。 innerHTMLが+になってるのはiframe内にxボタンを追加しているため。

  • Flashより上部に表示

パネルなのでFlashがあってもその上に表示できるようにした方が動作的にはいいと思うのでCSSを少し修正した。
要素をFlashより上部する方法は以前書いたFlashよりも前面にポップアップを表示するFirefox 3.6でFlashの上に position: fixed; な要素を表示できなくなった件 – なんとなく目記を見るといい。
Firefox3.6では挙動が変わったので注意。
Flashより上に表示するには”position: fixed; overflow: auto;”とした要素であり、以下の条件を満たす必要がある。

  1. 透過でない(Opacityを使わない or 背景色を無指定にしない)
  2. CSS3?(-moz-)系のstyleを使わない。(-moz-box-shadowなどは陰の部分だけFlashより後ろに表示されてしまう
    角丸border-radiusなどは要素に適応されるので要素全体がFlashより後ろに表示される。)

このmakeFrameを使ったサンプルGreasemonkeyとして
ニコニコ動画再生ページからその動画のマイリストコメントをパネル上で参照できる

Nico MylistComments for Greasemonkey
http://userscripts.org/scripts/show/72319

を作ってみた。

元ネタ(元ネタのサンプルはtypoがあるので、そのままだと動かない)

HTML Injection Tips – greasemonkey – GitHub
http://wiki.github.com/Martii/greasemonkey/html-injection-tips
makeFrame

gistへGreasemonkeyを貼るときに自動でファイル名を入力するスクリプト

GistにGreasemonkeyスクリプトをペーストする時に、自動でファイル名を入力してくれるGreasemonkeyを書きました。
入力されるファイル名は@nameの要素+.user.jsとなるので、コードをペーストするだけでRawからインストールできるようになります。

// @name           gist fill in fileName automatically

という感じで書いてあったなら、gist fill in fileName automatically.user.jsというファイル名が勝手に入力されます。

Add another file…で追加したテキストエリアにも対応させてあります。

gistのトップページ( http://gist.github.com/ ) と編集ページで動作します。

gist fill in fileName automatically for Greasemonkey
http://userscripts.org/scripts/show/71914

Read the rest of this entry »

twilogに日付毎のページへ飛ぶリンクをつけるGreasemonkey

twilogの日付の隣あたりに日付毎のページへ飛ぶリンクをつけるGreasemonkeyです。
要は下のスクリーンショットみたいに日付ページへ飛ぶリンクをつけるだけです。

カッとなってつけたけどデフォルトでないのが意外。

twilog date linker for Greasemonkey
http://userscripts.org/scripts/show/70683
プロフィール: azu(アズ)
Firefoxの事やソフトウェアの紹介や使い道、Greasemonkeyの作成
  • OS:Windows Vista, 7
  • ブラウザ:Firefox
  • Twitterのアカウントはこちら
  • azu_re
  • メールアドレス(Twitterの方が確実)
  • info@ドメイン名
リンク

WebMoney ぷちカンパ