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
**技術的な動作
**
var fileExtension = ".user.js";
var addAutoEvent = function(fileID){
var editArea = document.getElementsByName("file_contents[gistfile"+fileID+"]")[0];
var editFileName = document.getElementsByName("file_name[gistfile"+fileID+"]")[0];
editArea.addEventListener("paste", function(e){
// この瞬間はまだtargetのvalueが空である。
var obj = e.target;
obj.addEventListener('input', function(evt){
// クリップボードの内容がinputされた
evt.currentTarget.removeEventListener(evt.type, arguments.callee, false);
var pasteValue = obj.value;
var m = pasteValue.match(/@names+([ws]+)n/i);
m = m && m[1];
if(m && !editFileName.value){
m = m.replace(/s+$/ , "");
// m = m.replace(" " , "_" , "g");// 第3引数 繰り返し
editFileName.value = m + fileExtension;
// console.log(m + fileExtension);
editFileName.focus();
}
}, false);
}, false);
};
// 追加されたテキストエリアにもイベントをつける
var addButton = document.getElementById("add-gist");
addButton.addEventListener("click",function(){
document.getElementById("files").addEventListener("DOMNodeInserted",function(e) {
// テキストエリアが追加された
e.currentTarget.removeEventListener(e.type, arguments.callee, false);
var editAreaLength = document.getElementsByClassName("file").length;
addAutoEvent(editAreaLength);
} ,false);
} ,false);
// 最初から表示されているテキストエリアにイベントをつける
addAutoEvent(1);
addEventListener("paste" , ...);
でペーストに対してイベントリスナーを付け加えることができるのですが、この瞬間に
e.target.value
としても内容は空(もしくは元からそこに書いてあったもの)となり、期待するテキストエリアの文字列は取得できません。
なので、pasteのイベントリスナー内で
editArea.addEventListener("paste", function(e){
// この瞬間はまだtargetのvalueが空である。
var obj = e.target;
obj.addEventListener('input', function(evt){...
のように、inputイベントをつけると、実際に文字列がテキストエリアに入った瞬間にinputイベントが動くので、
inputイベント内で
obj.value
を見るととテキストエリア内の文字列が取得できます。
(ペーストされた部分のみを扱いたい場合はgist: 338606 – GitHubを参考に)
後は、inputのイベントはそのまま残っているとジャマなので自身を参照してremoveEventListenerしておいて、やりたかったことをやる。
追加されたテキストエリアにもイベントを加えるのもほとんど同じ形をしています。
まず、addボタンに対してclickイベント付け加えます。
gistでは元々addボタンに対してclickイベントがつけられていて、複数のclickイベントがあったときはつけられた順に実行されるので、元々あったclickイベント→Greasemonkeyでつけたclickイベントの順に実行される。
しかし、元々あったclickイベントではxmlhttprequestを使って非同期にテキストエリアを追加しているので、
テキストエリアを追加(gist側)→テキストエリアにイベントをつける(Greasemonkey) ということをやりたい場合にテキストエリアが追加されるまで待たないといけません。
JavaScriptではそういうときにsetIntervalで回したり、watch(IEでは動かない)でプロパティを監視したりできると思いますが、
今回はDOMNodeInsertedを使ってDOMに要素が追加されたら発火するイベントをつけることにした。
var addButton = document.getElementById("add-gist");
addButton.addEventListener("click",function(){
document.getElementById("files").addEventListener("DOMNodeInserted",function(e) { ...
#files 要素内に新しいテキストエリアが追加されると、DOMNodeInsertedイベントが発火するので、非同期で追加されたテキストエリアに関しても、最初に作成したpasteイベントをつけることができる。
この時に前と同様にDOMNodeInserted内で自分自身をremoveEventListenerしておく。
DOMNodeInsertedとかドキュメントがあんまり見当たらない。
DOMNodeInserted event JavaScript : http://help.dottoro.com/ljmcxjla.php
DOM Mutation Events は非同期にして使おう – JavaScriptで遊ぶよ – g:javascript : http://javascript.g.hatena.ne.jp/edvakf/20100204/1265312155
偶然にもpaste→input、click→DOMNodeInsertedという感じで両方とも、イベントリスナー内でaddEventListenerという形になった。
以上
お知らせ欄
JavaScript Primerの書籍版がAmazonで購入できます。
JavaScriptに関する最新情報は週一でJSer.infoを更新しています。
GitHub Sponsorsでの支援を募集しています。
