ブラウザを使っていると、知りたいワードをマウスで範囲選択して、それをマウスジェスチャーなどで検索に掛ける機会は結構あると思います。しかしその機能、普段webページでは出来るのに、メモパネルの範囲選択からは出来ないと思った事は無いでしょうか?
この記事では、それを可能にする方法の紹介と、さらにVivaldiでは検索の機能が充実しているので、それらを使った応用的な検索方法を紹介したいと思います。
「選択した文字列の検索」は使えない
マウスジェスチャーで登録している人も多いと思われるこの「選択した文字列の検索」。webページ上の文字列なら使えるのですが、なぜかメモパネルの文字列の選択からは使えません。
そこで、コマンドチェインで、メモパネルの選択文字列を1度「コピー」し、アドレス欄や検索欄に「貼り付けて移動」を行う事が、それを可能にする方法となります。
アドレス欄と検索欄は、どちらを使っても検索は出来ます。お好きな方を使ってもらえばよいのですが、自分は「アドレス欄」をおススメします。なぜなら、urlをコピーした場合も、アドレス欄への貼り付けならそのまま該当ページに飛べるからです。アドレス欄からの検索をする場合は、以下の設定が必要です。
「設定」→「検索」→「検索オプション」から「アドレス蘭から検索を行う」にチェックを入れて下さい。
登録エンジンで検索:通常版
では、実際にコマンドチェインの紹介をしていきましょう。まずは、1番オーソドックスなものから。
- 5番の「アドレス欄にフォーカス」を入れなくても上手く作動するかもしれません。その時は、5番と一緒に6番の「遅延」も抜いてしまってOKです。
- 各「遅延」のパラメータは、各自環境に合わせて調整してみて下さい。
- 「新しいタブ」では、設定により「空白ページを開く」が前提です。
別のエンジンで検索:text型(おススメ)
さて、ここからが本題(笑)
色々検索をしていると、時には、登録エンジンとは別のエンジンで検索したい事ってありますよね?Vivaldiでは、その手の検索方法はよく出来ていて、検索エンジンのニックネームを使う方法や、メインの検索エンジンにDockDockGoを登録している人は、!bang も使えます。両者に共通して言えることは、「検索エンジンのニックネーム(または!bang)」と「検索ワード」を空白でつなげてアドレス蘭(または検索欄)に打ち込み検索する。ということです。
つまり、最終的にアドレス欄に貼り付けたいこの「ニックネーム+空白+検索ワード」をどこかで、どうにかして、作ってやらないといけないのです。基本的にはJavaScriptでやるのですが、方法として考えているのが、textのコピペを駆使する方法と、次に紹介するAPIを使う方法があります。
まあ、キーボードでポチポチ打ち込んでもいいんですが、どうせなら、ワンアクションでラクにやりたいですよね?(笑)
↓6番「現在のタブでリンクを開く」のコマンドパラメータ
javascript: (() => { const e = ['ニックネーム ']; const i = Math.floor(Math.random() * e.length); const copyFrom01 = document.createElement("textarea"); const bodyElm = document.getElementsByTagName("body")[0]; bodyElm.appendChild(copyFrom01); copyFrom01.focus(); copyFrom01.textContent = e[i]; copyFrom01.setSelectionRange(copyFrom01.value.length, copyFrom01.value.length); function allSelect() { setTimeout(() => { copyFrom01.setSelectionRange(0, copyFrom01.value.length); }, 1, { once: true }); } copyFrom01.addEventListener('paste', allSelect, { once: true }); copyFrom01.addEventListener('blur', () => { bodyElm.removeChild(copyFrom01); }, false); })()
- 2行目[‘ニックネーム ‘]の様に、ニックネーム末尾に空白を入れて下さい。
- 変数eの配列インデックスを、変数iで指定しています。
- コマンドチェイン内の各「遅延」は、各自環境に合わせ、調整して下さい。
- 「新しいタブ」では、設定により「空白ページを開く」が前提です。
↓参考サイト
尚、「現在のタブでリンクを開く」などのパラメータにJavaScriptを組み込む方法は、↓
でも書きましたが、簡単におさらいすると、
①、コード全体を、()=>{コード全体} や function(){コード全体} とし、関数にする
②、①を、更に即時関数で挟む、つまりこうする (①)()
③、②の先頭に、javascript: を足す、つまりこうする javascript:②
text型のメリットとデメリット
この型のメリットを上げるとすると、新規タブで比較的すぐに開ける「空白ページ」を指定しておくことで、一定のスピードと効率を得られる事ですね。反対にデメリットを上げるとすれば、空白ページ内でテキストエリアや範囲選択がチョロチョロと目障りな点でしょうか。こういった目障りな点が目立たなくなる良い方法があると良いのですが…
ClipboardAPIを使う方法
そこで登場するのが、このClipboardAPIを利用する方法です。これを使うことで、クリップボードの内容を、直接読み込んだり書き込んだり出来るようになります。具体的にどういう構想かというと、
- arr[1]に、クリップボードを読み込みんだ値を代入する
- arr[0]に、ニックネーム(末尾に空白付き)を代入する
- arrをjoin(”)する
- 3.の値を、クリップボードへ書き込む
- アドレス欄へ「貼り付けて移動」で検索する
先ほどの目障りな点も解消され、一見、何の問題も無さそうにスムーズに行きそうですが、やってみると、色々な問題点が。どういった問題点があるかというと…
クリップボードへアクセスの許可問題
このAPIなんと、使用した時、新しいサイト毎に許可をしてやらないといけなくなるという問題点があります。1度許可したサイトでは、もう許可の必要がなくなるのですが…しかしながら、「検索する」ということは、様々なサイトを新しく訪れていくということです。この問題、なんとかならないものか…
新規サイト毎にコレが出るのは、少々ウザい感じがしますねぇ…(笑)
空白ページでClipboardAPIが作動しない
ならば、いつも「新しいタブ」で開く空白ページでコレをやればよいと思ったのですが、なんと、空白ページでは、ClipboardAPIが作動しないという問題点が。自分自身が、APIの事をよく理解してないせいもあるのでしょうけどね…
ああ…空白ページでクリップボードの読み書きが出来たら最高だったのに(笑)
それでも色々とやった結果、分かった事も出ました。それは…
クリップボードへの書き込みは許可がいらない
クリップボードからの読み込みは、readText()。書き込みは、writeText()。
このwriteText()、(書き込みの方)は、許可が出ないみたいですね。但し、空白ページでは相変わらずAPIそのものが作動しませんが(笑)そこで、readText()は使わない方法で、構想を練ってみるのも面白いですね。
- 検索ワードを普通に「コピー」する
- 同ページ内にtextareaを作成、そこに普通に「貼り付け」する
- arr[1]に、textarea.value の値を代入する
- arr[0]に、ニックネーム(末尾に空白付き)を代入する
- arrをjoin(”)する
- 5.の値を、クリップボードへwriteText()する
- アドレス欄へ「貼り付けて移動」で検索する
なんか、無理やり感が凄い(笑)
っていうか、目障りな点が解消されてない…わざわざtextareaを作るなら、上で紹介している「text型」でもいいような…まあ、せっかくだから、コマンドチェインやコードも一応載せておきますね(笑)
別のエンジンで検索:ClipboardAPI型
↓3番「現在のタブでリンクを開く」のコマンドパラメータ
javascript: (() => { const e = ['ニックネーム ']; const i = Math.floor(Math.random() * e.length); const w = [null, null]; const x = window.pageXOffset; const y = window.pageYOffset; let searchWord; const copyFrom01 = document.createElement("textarea"); const bodyElm = document.getElementsByTagName("body")[0]; bodyElm.appendChild(copyFrom01); copyFrom01.focus(); function joinWord() { setTimeout(async () => { w[0] = e[i]; w[1] = copyFrom01.value; searchWord = w.join(''); await navigator.clipboard.writeText(searchWord); bodyElm.removeChild(copyFrom01); scrollTo(x, y); }, 1, { once: true }); } copyFrom01.addEventListener('paste', joinWord, { once: true }); })()
- 2行目[‘ニックネーム ‘]の様に、ニックネーム末尾に空白を入れて下さい。
- 変数eの配列インデックスを、変数iで指定しています。
- コマンドチェイン内の各「遅延」は、各自環境に合わせ、調整して下さい。
- 「新しいタブ」では、設定により「空白ページを開く」が前提です。
asyncとawaitについて
クリップボードを読み書きするreadText()とwriteText()。コードを実行すると分かるのですが、これらが発動した瞬間は、実際の読み書きがまだ完了していない状態でコード自体が先に進んでしまうので、思ったような挙動になりません。
したがって、14行目からの関数をasyncにし、関数内のwriteText()はawaitで待ってから、その先のコードが進むようになっています。
↓参考サイト
イベント、copy、paste、cutについて
同じような理由で、イベントのcopy、paste、cutについて、これらが発動した瞬間は、実際の読み書きがまだ完了していない状態でコード自体が先に進んでしまうので、思ったような挙動になりません。したがって、14行目からsetTimeoutにし、待ち時間を「1」入れることで、問題の解消をしています。
まとめ
いかがだったでしょうか?今回の考えた方法では、まだ少し不満点もあるので、もう少し練ってみて、よい方法が見つかれば、また紹介したいです。
それでは!
コメント