新・日々の暮らしに疲れてない?

一人バンド、火頭工房

【Chrome拡張機能】拡張機能のアイコンをクリックするだけで機能を実行するぅ

拡張機能のアイコンをクリックするだけで機能を実行するにはどうしたらいいのか。

 

ポップアップファイルの中で関数を実行すればいいじゃんね、実行後ページをwindow.close() で閉じれば動作した。

 

コンテンツスクリプトなんかとやり取りが必要ならそう単純じゃないでしょうが、とりあえずこれで 満足。任意のタイミングで機能を実行したい時は、この操作が確実でいいですね。(まぁキーボード操作も良いんですけど、発火のコントロールが結構難しい)

 

でもこれだとよくある、ポップアップページで機能の設定をいじる、ということが出来ない。実行時にポップアップページが開かれてしまったら閉じる手間も増えるしナンセンス。


どうするか。

 

特定のキーを押した状態でアイコンをクリックすると、設定画面が開くようにしたら良いのでは?でもどうやってそれを検知する?(キーボード操作の安定がうんぬん言っといてなんですが)

 

色々試してみたら、まぁまぁ面倒なことがわかりました。

 

・まずキーボードを押した離したどーたらはコンテンツスクリプトでないと検知できない。

・履歴の消去はポップアップスクリプトからしか行えない。
・コンテンツスクリプトからポップアップファイルへはメッセージを直接飛ばせない。
・コンテンツスクリプトからバックグラウンドページはメッセージを飛ばせる。
・バックグラウンドページの変数をポップアップファイルから取得できる(これは知らなかった)、 あとメッセージも飛ばせるんじゃなかったかな?

 

ようやく道が見えました。以前もこういう拡張機能内でのメッセージのやり取りで苦労しましたが、一度作ってしまったら忘れてしまうんですよね。

 

バックグラウンドにこういうアクセスの仕方があるとは新発見でした ↓

chrome.extension.getBackgroundPage().変数名;

 

さて、流れとしては、

・onkeydownで、例えば「コントロールキー」が押されているかどうかを監視する ↓
・押されていたらバックグラウンドページに適当なメッセージを飛ばす ↓
・バックグラウンドページ内で変数にメッセージを記録 ↓
・ポップアップが開かれた時に関数を実行、バックグラウンドの中の変数の状態を取得 ↓
・コントロールキーが押されている状態なら関数の実行を中止し、普通にポップアップページが開くようにする。押されていながければ関数を実行、履歴を消去する。

 

ちなみにコントロールキーを離した時はonkeyupで監視し、同じくバックグラウンドに
状態を保存します。これで「コントロールキーを押しながらアイコンをクリックした時」という条件 が成立します。


これをしておかないと、コントロールキーを一度押せば、いつでも発火するようになってしまう。

 

こんなとこでしょうか、メッセージ周りをもう少し融通きかせて欲しいもんです。
これで何を作ったかは、次のエントリーで。

【Chrome拡張機能】Google検索結果で邪魔なサイトをハイライト

以前作ったこちらの拡張機能を改善しました。

hiatama.hatenablog.com

 

こちらの機能は、グーグル画像検索でヒットしたサイトのURLをチェックし、嫌いなサイトを非表示にする機能だったのですが、まぁ消すまではしなくても良いだろう、ということで赤い枠で強調してくれるようにして使っています。

 

最初は画像検索だけに対応していたのですが、その後、動画検索にも適応させました。これにより、個人的に開きたくないニコニコ動画ツイッターの動画を事前に察知できるようにしました、あとは海外の怪しい動画サイトなども。

 

ここまで来たら、通常の検索にも適応させんべ、ということで試しました。

仕組みは似たようなもんです。

 

ただ、通常検索には、他のモードにあった「tbm=xxx」というキーワードがURLに表示されないので、消去法的に通常検索の状態を探知。

 

毎回面倒な、各要素のURL取得を経て、無事完成。

f:id:hiatama:20190423170434p:plain

 

↑このように、排除したい(ハイライトしたい)文字列を設定して、それにヒットすると赤枠で囲ってくれる、という動作になります。

 

中々快適なのですが、グーグルの仕様は結構頻繁に変更されるので、拡張機能がある日突然動かなくなったりするんですよね、あと同じような要素でも微妙にHTMLの名前の付け方なんかが違ったりして、完璧に動作させるのが難しい。

 

細かいことはあるにせよ、あとはUIを付けてブラウザ内データベースと連携させれば、公開しても良いんですけどね…そういう一手間がおっくうです。

 

追記:

あと、検索結果に出るウェブサイトの説明が長いな、と前から思っていたんですよね。いらないサイトをハイライトしたついでに、説明部分の文字列を取得して文字数制限をかけました。どうせ開きたくないサイトだから説明も1行くらい見られたら良いし。

【コマンドプロンプト】テキストファイルって素晴らしい

あまりブログを更新していませんが、普通に暮らしています。

 

音楽とプログラミングからはやや遠ざかり気味です。

プログラミングはちょいちょい拡張機能の手直しや、ブラウザ更新による動作不良を直したりします。自作の便利機能も充実し、あまり作りたいものもなし。

 

ところで、何か作業する時にメモ帳って本当に重宝します、ワードソフト開く起動時間の数秒が面倒なので、テキストファイルはメモ帳に限ります。

 

そんなわけで私のデスクトップにはメモを取ったテキストファイルが散乱しているのですが、新規のテキストファイルを作る時は、散乱している適当なテキストファイルをクリックして開く→メニューから新規作成、みたいなことしていたんですが、保存する時にファイル名を入力しなくてはいけなくて、面倒。

 

メモ帳のショートカットをデスクトップに置くのもなんか野暮だし、ファイル名を打つわずらわしさも残る。

 

バッチファイルで自動化してもらいましょう。

 

 

cd C:\Users\あなたのユーザー名\Desktop
type nul > new.txt
start new.txt
exit /B 0

 

これだけ。

これをテキストファイルに書いて、拡張子を「bat」にして、デスクトップに置いて必要な時にクリックするだけ。長年の無駄も検索するとすぐに解決します、プログラミングって素晴らしいですね。

 

上のコードの動作は

 

・現在地をデスクトップに指定する(Windows7の場合です)

・「new.txt」というファイルを作る、空のテキストファイルがデスクトップに作成される

・「new.txt」を開く

・終了

 

以上です。

ファイル名も決めてくれるので、保存時にファイル名を打つ手間もありません。ま、これで最低限の動作が確保できましたが、もう一度このバッチファイルをクリックすると「new.txt」が上書きされてしまうので、中身が消えてしまいます。

 

これを回避するには、作成した時間なんかをファイル名に組み込んでしまう。


set myTime=%date:~0,4%%date:~5,2%%date:~8,2%%time:~0,2%%time:~3,2%%time:~6,2%

 

これで変数「myTime」に日付が「20190131073055」という書式で保存されますので、ファイル作成の部分にこの変数を組み込む。

 

type nul > new%myTime%.txt

これで「new20190131073055」みたいなテキストファイルが作成されます。

 

私としては、ファイルの上書きを回避したかっただけなので、ここまで長いファイル名は不要、せいぜい何分何秒程度の精度で十分です。ちょちょっと修正してはい完了。

 

おしまい。

 

追記:

ネットの記事でPowerShellが改良される!とかいう記事を見かけました。PowerShell自体名前くらいしか知らなかったのですが、Windowsには標準で入っているそうで、なるほど所有していました。

今回のコマンドプロンプトの上位互換的な事が出来るらしい。まぁ単純なモノしか作らないので上位互換に縁はなさそうですが、ちょっとだけ触ってみるかも知れません。

【Chrome拡張機能】タブショートカットのアップデート

2018年末に書いたこの記事の機能と

hiatama.hatenablog.com

 

ずいぶん前に公開したこの機能

hiatama.hatenablog.com

 

動作させるための共通点みたいなものが多かったので、統合し、公開していたバージョンをアップデートしました。

 

なので、もしお使いの方がいたらその変化に気づいたことでしょう。

リンクのポップアップ機能は個人的にかなりオススメです。

 

インターフェース(と呼ぶほどのものではないけど)を少し改良し、

機能のオンオフを個別に出来るようにしました。

【Chrome拡張機能】リンクをマウスオーバーでURLをポップアップ表示

年始のヒマに合わせてクローム拡張機能を作りまくる日々。

え?もう普通の人は働いてるって? ソッスカ。

 

今回作ったのはリンクをマウスオーバーしたらURLをポップアップで表示してくれる機能、仕様感はイマイチ。

 

似たようなことはタブ操作の拡張機能でやったことあるんですけどね、

マウス操作を使った機能ってHTML要素によって、作動できないものがあるんですよね、確実に作動できない機能は公開しにくい。

 

とにかく設計としては、

・マウスオーバーでリンクのURLを取得

・マウスカーソルの近くに固定表示のDIVを埋め込む

・そのDIVにURLを書き込む、文字数制限アリ

・マウスアウトで表示を消す

こんな感じ、あまり難しくないですね。

 

URLの取得はmouseover(e)で要素を取得して、href情報を抜き出す。

注意が必要なのは、リンクに見せかけてマウスオーバーでゲットできる要素には「href情報」が付いていない場合がある。子ノードや親ノードにhrefが設定されていたりするので、条件分岐でもして狙ったURLを抜き出さないとダメ。

 

次、マウスカーソルの近くに固定表示のDIVを埋め込む。

ここが一番苦労しました、だからHTMLはキライなんだってば。

固定表示という言い方はたぶん正確じゃないと思いますが、ページスクロールに影響されない要素、の意味で書いています。

固定表示のボタンの作り方なんかを参考にして、それをjavascriptでゼロから生成する方法を試したのですが、css情報をjavascript側で書き込むなど、普段しないことが多かったので、ドキドキでした。

 

マウスカーソルの近くに表示しないといけないので、e.clientXやclientYでマウス座標を取得し、動的に数値を書き込む必要があったし、固定表示のやり方も知らないし、作業時間の大半はここでした。

 

無事、表示できたので、マウスアウトした時には、.remove()で生成した要素を消去します。作ったものを消すということもあまりしたことなかったですね。

 

さて、一応これで完成なのですが、イマイチ動作がもっさりしています。

マウスオーバーがうまく作動しない時があるっぽいのと、表示座標がずれる時があります。それにiframeのリンクは取得できない(これはウェブの仕様です)、この辺りが限界ですね。

 

この様な使用感 ↓

f:id:hiatama:20190104210901p:plain

 

↓ バグの様子。赤丸にカーソルを当てたのに、表示はズレています。

f:id:hiatama:20190104210903p:plain

e.clientXなどではないその他の座標情報を使ったら解決するかも?


あとURLが無駄に長いものも多いので、適当に文字制限を入れています。

見たいのは最初の方だけですもんね。

 

全く機能が作動しない時もあるし、表示がチラつく時があってちょっと信用できないなぁ、という印象。

 

この機能と同じようなものは、ブラウザの基本機能として画面左下にひっそりと表示されているのですが、わざわざ画面左下をチラ見するのが面倒でマウスに追随するようにしました。

 

以上。

 

追記:

作動にムラがある・表示位置がずれる問題共に、マウスオーバーではなくマウスムーブに変えることで改善しました。発火が不安定なら何度も発火させれば良いじゃない?の精神です。

 

 

 

【Chrome拡張機能】Googleの画像検索で邪魔なサイトをフィルター

新年一発目の拡張機能です。

この機能、前から作ろうと思ってたんですよね、年始のヒマに合わせて作ってしまいます。

 

Googleの画像検索した時に、Youtubeとかの動画のサムネが混ざったりして、うっかり動画サイトに飛んで後悔することってないですか? え?ない? あぁそう。

 

ということで、グーグル画像検索フィルターを作ってみました。これ中々良いですよ。他の検索機能に適応しても良いんですし。

 

グーグルの画像検索をした時に、URLを良く見てみると「tbm=isch」という文字列が紛れ込んでいます、動画ならtbm=vidですので、カテゴリーごとに決まっています。

 

現在のURLを window.location.href で取得して、上の「tbm=isch」が入っていたら機能を作動させます。

 

次は画像にくっついている要素をリストとして取得。こういうのが大変なんですよね。

 

f:id:hiatama:20190101210445p:plain

画像検索をすると 上の様な見た目になります。そこでブラウザのコンソールを開いて、一つ一つの要素がどのような構造で格納されているか調べ、URLを取得する。

 

調べた結果、全ての画像を格納している大きいDIVタグには「rg_s」というIDが振られているので、まずこれを取得して、その「子ノード」をリストとして持っておく。

 

var picbox = document.getElementById('rg_s');

var picbox_childNodes = picbox.childNodes;

 

↑ 別に分けて書かなくてもいいんですけどね。

まだこのリストの中には無駄な要素も入っていたので、ループかけて必要な要素だけを残し、次はURLが入っている要素を絞り込む。

 

ここでつまづいたのは、なんとそれぞれの画像に設定されているURL(href)はページを読み込んだ時点では公開されておらず、マウスオーバーした時に公開されるという仕様。HTML階層の深さも相まって、自分が間違った要素を指定しているのだとばかり思い、気づかなかったです。

 

じゃ、URL取得できないじゃん。ってことで別の情報を使うことに。

f:id:hiatama:20190101211437p:plain

こういうページ情報は取得できるので、この文字列を使います。

なんというか、先ほどの要素の階層を下って行った所に格納されています。

 

こんな感じ ↓

要素のリスト[i].childNodes[1].childNodes[1].innerHTML

煩雑でしょう。これだからHTMLはキライです。

ま、とにかくこれで画像ひとつひとつのタイトルやURLが取得できました。

 

次は、画像検索の時に出てきて欲しくないサイトのリスト、つまりフィルターを作っておきます。パッと思いつくのはYou○ubeやTw○tter あたりでしょうか、いや失礼。

 

あとは総当りでURLを検証して、フィルターに登録した文字列と一致した要素を消します。こういうのはループ内ループで総当りします。

 

要素のマッチには、

if(要素リスト[i].indexOf(フィルターの言葉) !== -1)

 

こんな感じでindexOfを使いました。

フィルターに登録した言葉がヒットした場合は、その位置情報が返ってきます、ヒットしなかった場合は-1が返って来るのでそれで判別します。

 

で、要素.style.display = 'none'; で消えます。バイバイ。

 

まぁ完全に消してしまったら不便なこともあるでしょうから、ハイライトしておく、とかにした方が良いかと思いました。

 

以上。

画像検索だけに絞らず、動画検索にも良いですね。

重たいから開きたくない動画サイトってあると思うので。

【Chrome拡張機能】文字をドラッグでオートコピー&右クリックでペースト

久しぶりにクローム拡張機能を作ろうと思います。

 

どこかで見かけた便利機能で「文字をハイライトしたらコピーする」というもの。その後、右クリックでペースト出来るようにしたらもう1つ便利だろう、ということでパパっと作ってみることに。

 

これが意外と苦労したんですよね、しかも現状使い物になっていない。

 

そもそも文字のコピー(右クリックでメニューからコピー、あるいはCtrl + cでコピーする機能)って別にブラウザだけで行うものでもないですよね、メモ帳に書いたものをコピーしたり、ブラウザ上のアドレスバーのURLをコピーしたり。

 

これらはクローム拡張機能でどうこうできる範疇を超えているわけで、ここに目をつけるのは筋違いと言うわけですね。

 

とにかく実装した範囲を記します。

 

「左クリックでドラッグした範囲をコピー」

これはすんなり行きました。

onmouseupイベントというのがあり、マウスボタンを離した時に発火してくれます。その中で、window.getSelection(); をすれば選択範囲の要素が取得できます。ここから選択範囲の文字列を取得するには更に、toString(); をします。

 

こんな感じ↓

let _selected = window.getSelection();

let selected = _selected.toString();

 

これでドラッグで選択した範囲の文字列が取得できます。

 

次、コピー。

document.execCommand('copy');

これだけ。ちょっと良く分かっていないのですが、何をコピーするか渡していなくてもonmouseupイベントの中で行えば、選択範囲をクリップボードにコピーしてくれます、ちょっと気持ち悪いですね。

 

とにかく、これでコピーは作動します。

ただし、これだとコピーするつもりがなくてもクリックするたびにコピーしようとするので、文字数制限や空文字対策をする必要があります。

 

クリップボードにコピーしたものを右クリックでペーストする」

こっちが問題でした。

コピーが簡単だったもんで、document.execCommand('paste'); とでもすればペーストしてくれるだろうと踏んでいましたが間違いでした。

こっちはどこにペーストするのか、指定をしないと作動しない感じでしょうか(まぁそりゃそうだわな)。

 

調べてみると、ペースト先の要素を取得し、.focus()したりしているコードを見つけました。でも、私が試してもうまく動作しないんですよね。falseが返って来てしまいます。←返ってくるだけマシです。

 

ちなみに、右クリックで何かを作動させるには、contextmenuに機能を追加する、ということになります。document.addEventListener()でcontextmenuを指定し、その中にコードを書いていくのですが、navigator.clipboard.readText(); を試してみるとうまく行きました。

 

でもね、ネットで拾ってきたコードを適当に試してるので何かわかってないんですよ。navigatorって何?って感じです。

 

とにかく動いたので気を良くしてテストしてたら、navigatorの意味がわかりました。

 

f:id:hiatama:20181231162126p:plain

どーん。これです、最悪。

 

サイトによってこの許可を求められます、これは致命的。

というわけでクロームの設定をいじってユーザーが常時クリップボードへのアクセスを許可しないとこの機能自体が無駄になります(そういう設定フラグがあるのかも知りません)。

 

やる気がなくなりました。

 

後は考えたことや気づいたことを箇条書きしておきます。

 

・調べていると、コピペはセキュリティの観点から許可に対して慎重らしい。拡張機能側で許可を書いている例も発見。

 

・document.execCommand('copy'); では許可を求められなかったのだから、ペーストも

許可なし? もしそうなら、狙った要素に作動させることが出来れば全て解決。

 

クリップボードに頼らず、変数に文字列を格納して擬似コピーペースト機能を作ればいいじゃん → クリップボードを通さない以上、ブラウザ外でコピーしたものはペースト出来ないのでイマイチ。

 

クリップボードを通さない場合、同じタブの中だけしかコピーペーストができないのでそれでは無意味、変数の中味を共有するには、ストレージとかバックグラウンドページを使う必要がありちょい面倒、だけどやる価値あり。

 

・それでも最初に書いたように、アドレスバーなどは拡張機能でいじれない範囲なので(たぶん)機能として中途半端だと気づく。

 

・ペーストする時に、消したい文字を範囲選択してそこにペーストして上書きすることってありません? あれが出来なくなります。ドラッグを解除した瞬間に消したいはずの文字が新たにコピーされてしまうからです。選択範囲をした状態で左マウスボタンを離さず右クリックしたら回避できましたが...ちょっとなぁ。

 

以上。

まぁいつも通り、自分だけで使えばいいや。

許可が求められる navigatorは論外だけど、変数を使った擬似コピーペースト機能でも使い道ある。

 

少なくともdocument.execCommand('copy') の方に問題はない、ちゃんとクリップボードにコピーされるので、同時に内容を変数に確保、右クリックでのペーストはnavigatorを通さず、変数の内容を 要素.target.value で直接入力する仕組みにします。

もちろん Ctrl + v でもペーストが出来るので問題なし。

 

あとはdocument.execCommand('paste'); の方をもう少し調べてみるのと、バックグラウンドページを使った方法も完成させよう。

 

それでは2018年も終わり。良いお年を。 

 

追記:

調べて色々試したところ、ストレージと変数を使って擬似コピペ機能を使うのが手軽でした。ブラウザ以外からコピーしたものには対応できていませんが、これもタブ機能を調べれば対処できそうです。あとはアドレスバーへのアクセスだけど...これはたぶん無理。