ブラウザのウインドウとタブが無限に増える問題
今は仕事でも趣味でも遊びでも、あらゆる情報をWebで集めるようになりました。
気がつくとものすごい数のウインドウが開いていて、それぞれのウインドウにたくさんのタブがあるという状態になっていたりします。
うっかりウインドウを閉じて消えちゃうと困るのでどこかに保存したいのですが、たくさんのURLを一時的にまとめて保存する、みたいな用途にブラウザのブックマークはあまり向いていません。
個人的にブックマークは将来使いそうなURLを保存したい場所です。
ブックマークが増えすぎると整理が追いつかなくて役に立たなくなっちゃうんですよね。一覧性も低いし、編集も面倒くさい。
調べ物で集まったURLはブックマーク以外のところに保存したいです。
最近のChromeにはタブグループとかいう機能があるみたいで、いちど試しに使ってみましたがどうもよく分かりませんでした。
できればウインドウ上のタブのタイトルとURLをリストアップして、Evernoteとかのクラウドに保存できたらいいなぁと思いました。
ナイスなChrome拡張機能が見つかった
Chromeには便利な拡張機能がたくさんあります。でも、そんな都合の良い拡張機能があるのかなと思ったら、やっぱりありました。
開いているウインドウの全タブのページタイトルとURLを取得するChrome拡張作った - Qiita
yukuduri/getTitleAndURLofALLTabs: Github
しかもソースコードと解説付きです。拡張機能の作り方も覚えたいと思っていたのでありがたい!
さっそくChromeにインストールしてみると見事に動きました(manifest.jsonのバージョンが古いという警告がでたので修正。後述)。
この機能拡張は、起動するとすぐにポップアップしたウインドウに全タブのタイトルとURLをリストアップしてくれます。
Copyボタンを押すとリストがクリップボートに入るので、Evernoteとかの保存したいところに貼り付けます。便利!
Chrome Store以外の拡張機能をインストールする
普通の機能拡張はChrome Storeからインストールしますが、ソースコードの入ったフォルダを直接読み込むこともできます。
まず、Chromeの環境設定で拡張機能を選びます。
右上のスイッチで「デベロッパーモード」をオンにします。
「パッケージ化されていない拡張機能を読み込む」をクリック
ソースコードの入ったフォルダを選択します。
拡張機能が追加されます。
ツールバーの拡張機能ボタンをクリックします。
get Title&URL of ALLTabsのピンをクリックしてツールバーにピン止めします。
ただ、この方法で登録した拡張機能は端末間の同期は働かないみたいです。まぁそうですよね。端末毎に登録しましょう。
あとはタブを保存したいウインドウ上でアイコンをクリックすれば、ポップアップに全タブのタイトルとURLが表示されます。copyボタンでクリップボードに入ります。
図はこのあと改造したものの画面で、オリジナルとはちょっと違います。
Evernote APIは難しいらしいので、Googleスプレッドシートに保存することにした
もともと、気になったWebサイトをEvernoteに保存していたので、拡張機能でリストアップしたページもEvernoteに自動保存できるといいなぁと思いました。
しかし、ちょっと検索してみるとJavascriptでEvernote APIを使うのは難しい的なことが書いてあったので、あっさり断念。
使い慣れたGoogleスプレッドシートにデータを自動保存することにしました。
やっていることはシンプルです。
機能拡張で集めた全タブのページタイトルとURLを二次元配列に入れてGoogle Apps Scriptで作ったWebアプリにPOSTします。GAS側は受け取ったデータをスプレッドシートに書き込みます。
スプレッドシート上のURLは自動的にリンクとして機能します。スプレッドシートからURLを開くことができます。
ソースコード
Google Spread Sheet対応版のソースコードはGithubのフォークにあります。jqueryは自分でDLしてsrcフォルダにいれてください。
コードの内容は以下のようなものです。
コード.js
Googleスプレッドシートに付属するコンテナバインドスクリプトです。
doPost()関数でPOSTアクセスのパラメーターからサイト名とURLの配列を取り出して、スプレッドシートに書き込みます。
ほぼ、この記事のテンプレートのままです。
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
function appendMultiRaws(array) {
var endOfSheetRow = Number(sheet.getLastRow()) + 1; //最終行の位置を取得
var lastColumn = array[0].length; //カラムの数を取得する
var lastRow = array.length; //行の数を取得する
sheet.getRange(endOfSheetRow, 1, lastRow, lastColumn).setValues(array);
}
function doPost(e) {
const reqParam = e.parameter;//パラメーターを取得
const data = JSON.parse(reqParam.data);
switch (reqParam.action) {//actionパラメーターの内容によって処理を分岐
case "append": //パラメーターをそのまま返すアクション
{
appendMultiRaws(data);
return ContentService.createTextOutput(JSON.stringify('done'));
}
break;
//以下、case文を必要なだけ書く
default:
{
const result = 'did nothing';
return ContentService.createTextOutput(JSON.stringify(result));
}
break;
}
}
popup.html
popup.htmlは、$ajaxを使うためにjqueryをリンクしています。
あらかじめ同じフォルダ内に"jquery-3.6.0.min.js"をダウンロードしておく必要があります。
ちなみにCDNへのリンクはエラーになりました。
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script src="getTitleAndURL.js"></script>
</head>
<body>
<script src="jquery-3.6.0.min.js"></script>
<h2>get Title&URL of ALLTabs & Post to GSS</h2>
<label>現在のウインドウのタブ数:<input id="numOfTabs" type="number" readonly></label><br><br>
<label>取得したタイトルとURL:<textarea id="txt"></textarea></label><br>
<button id="copy">copy</button>
</body>
</html>
getTitleAndURL.js
getTitleAndURL.jsでは、リストの表示形式を自分好みに変更しています。
テキスト形式のリスト作成と同時にGoogleスプレッドシートに投稿するための2次元配列も作成しています。
最後に$ajaxでGoogleスプレッドシートのWebアプリケーションにPOSTします。
END_POINTには自分のWebアプリケーションのURLを設定します。
const createTextFromTemplate = (title, url, template) => {
let txt = template;
txt = txt.replace(/%%title%%/g, title);
txt = txt.replace(/%%URL%%/g, url);
return txt;
}
const run = () => {
//現在のウインドウのタブをすべて取得
chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT }, (tabs) => {
let txt = '';
const delimiter = '\n'; //区切り文字
const template = '%%title%%' + delimiter + '%%URL%%'; //テンプレ
const tabList = [["",""]];//Google Spread Sheetへの投稿は一行空ける
document.querySelector('#numOfTabs').value = tabs.length;
tabs.forEach((tab, i) => {
if (i != 0) txt += (delimiter + delimiter); //最初は区切り文字不要
console.log(tab.title + " " + tab.url);
txt += createTextFromTemplate(tab.title, tab.url, template);
tabList.push([tab.title, tab.url]);
});
document.querySelector('#txt').value = txt;
postToGSS(tabList);
});
}
const copy = () => {
const copyText = document.querySelector('#txt');
copyText.select();
document.execCommand('copy');
}
const postToGSS = (data) => {
const END_POINT = "https://script.google.com/macros/s/------google web apps url--------/exec";
$.ajax({
type: "POST",
url: END_POINT,
dataType: "json",
data: { action: 'append', data: JSON.stringify(data) }
})
.then(
(result) => { // 成功した時の処理
console.log(JSON.stringify(result));
},
(error) => { // 失敗した時の処理
alert('Error:' + JSON.stringify(error));
}
);
}
window.addEventListener('load', () => {
run();
document.querySelector("#copy").addEventListener("click", copy);
})
manifest.json
拡張機能のmanifest.jsonはバージョン3対応に書き換えました。
manifest.jsonのことはよく分かっていないのですが、以下のガイドに従って改変しました。
Migrating to Manifest V3 - Chrome Developers
{
"name": "get Title&URL of ALLTabs",
"author": "yukuduri",
"version": "1.0.0",
"description": "開いているウインドウ内のすべてのタブのタイトルとURLを取得します。",
"icons": {
"16": "icon16.png",
"48": "icon48.png",
"128": "icon128.png"
},
"action":{
"default_icon": {
"19": "icon19.png"
},
"default_title": "get Title&URL of ALLTabs",
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"tabs",
"clipboardWrite"
],
"manifest_version": 3
}
使い方は同じ。とても便利。
拡張機能の使い方は元の拡張機能と変わりません。拡張機能のアイコンをクリックするとポップアップに全タブの内容が表示され、同時にGoogleスプレッドシートにも書き込まれます。
しばらく使っていますが、とても便利です。記録先がGoogleスプレッドシートなので、自由に補足説明とかを書き込めるので単なるブックマークよりも役にたちます。