
【Script】NotebookLM:ソースをフィルタリング #NotebookLM
こんにちは!一歩です!(自己紹介はこちら)
(既に活用済みの方向けです)
NotebookLMでは、ソースのチェックボックスを外すことで、チェックが付いているソースのみ参照した回答が可能ですが、
現状はあまり使い勝手が良くありません。。。
(いずれ改善されると思いますが)
ソースを最大300件登録できますが、スクロールしてチェックを外すのは現実的ではないですよね。
そこで簡単なScriptを用意しました!
後ほど拡張機能に取り込みますが、お試し版として使ってみてください!
取り込み済です!
利用方法
1.ブラウザの開発者ツールを起動する。
※ ブラウザによってメニュー名は異なりますが、
Chromeは「検証」
Edgeは「開発者ツールで調査する」です。
2.コンソールに以下Scriptを貼り付けてEnterで実行(コンソールが表示されていない場合、「Esc」キーを押下。キーボードの一番左上あたりにあると思います)
3.ソースエリアに入力欄が表示されます。

4.文字を入力。ソースのタイトルでフィルタリングされます。

チャット欄の右側の表示で個数が変わっていれば成功です。
そのままチャットで質問してみてください(_ _)

Script
(function() {
'use strict';
// ソースパネルのセレクタ
const sourcePanel = document.querySelector('.source-panel');
if (!sourcePanel) {
console.log('ソースパネルが見つかりません');
return;
}
// 既にフィルターが追加されていれば削除(テスト用に再実行できるように)
const existingFilter = document.getElementById('source-filter-input');
if (existingFilter) {
existingFilter.closest('.filter-container').remove();
}
// 「すべてのソースを選択」の行を見つける
const selectAllRow = document.querySelector('.row:has(.header-title-muted)');
if (!selectAllRow) {
console.log('「すべてのソースを選択」の行が見つかりません');
return;
}
// フィルターコンテナ作成
const filterContainer = document.createElement('div');
filterContainer.className = 'filter-container';
filterContainer.style.margin = '0 0 8px 0';
filterContainer.style.padding = '0 8px';
// 入力ラッパー作成
const inputWrapper = document.createElement('div');
inputWrapper.className = 'filter-input-wrapper';
inputWrapper.style.position = 'relative';
inputWrapper.style.display = 'flex';
inputWrapper.style.alignItems = 'center';
filterContainer.appendChild(inputWrapper);
// 検索アイコン作成
const searchIconWrapper = document.createElement('div');
searchIconWrapper.style.position = 'absolute';
searchIconWrapper.style.left = '10px';
searchIconWrapper.style.top = '50%';
searchIconWrapper.style.transform = 'translateY(-50%)';
searchIconWrapper.style.pointerEvents = 'none';
searchIconWrapper.style.color = '#666';
// SVG要素を作成
const svgNS = "http://www.w3.org/2000/svg";
const svg = document.createElementNS(svgNS, "svg");
svg.setAttribute("width", "16");
svg.setAttribute("height", "16");
svg.setAttribute("viewBox", "0 0 24 24");
svg.setAttribute("fill", "none");
svg.setAttribute("stroke", "currentColor");
svg.setAttribute("stroke-width", "2");
svg.setAttribute("stroke-linecap", "round");
svg.setAttribute("stroke-linejoin", "round");
// サークル要素を作成
const circle = document.createElementNS(svgNS, "circle");
circle.setAttribute("cx", "11");
circle.setAttribute("cy", "11");
circle.setAttribute("r", "8");
svg.appendChild(circle);
// ライン要素を作成
const line = document.createElementNS(svgNS, "line");
line.setAttribute("x1", "21");
line.setAttribute("y1", "21");
line.setAttribute("x2", "16.65");
line.setAttribute("y2", "16.65");
svg.appendChild(line);
searchIconWrapper.appendChild(svg);
inputWrapper.appendChild(searchIconWrapper);
// 入力欄作成
const filterInput = document.createElement('input');
filterInput.id = 'source-filter-input';
filterInput.type = 'text';
filterInput.placeholder = 'ソースをフィルター...';
filterInput.style.width = '100%';
filterInput.style.padding = '8px 8px 8px 32px';
filterInput.style.border = '1px solid #ddd ';
filterInput.style.borderRadius = '4px';
filterInput.style.fontSize = '14px';
filterInput.style.outline = 'none';
inputWrapper.appendChild(filterInput);
// クリアボタン作成
const clearButton = document.createElement('button');
clearButton.id = 'source-filter-clear';
clearButton.textContent = '×';
clearButton.style.position = 'absolute';
clearButton.style.right = '8px';
clearButton.style.background = 'none';
clearButton.style.border = 'none';
clearButton.style.cursor = 'pointer';
clearButton.style.fontSize = '18px';
clearButton.style.color = '#999';
clearButton.style.display = 'none';
inputWrapper.appendChild(clearButton);
// フィルター入力欄を「すべてのソースを選択」の上に挿入
selectAllRow.parentNode.insertBefore(filterContainer, selectAllRow);
// チェックボックスの状態を変更し、すべての可能なイベントを発火させる関数
function setCheckboxStateAndTriggerEvents(checkbox, checked) {
if (!checkbox) return;
// 既に希望の状態ならば何もしない
if (checkbox.checked === checked) return;
// 値を変更
checkbox.checked = checked;
// チェックボックスのクラスを更新
const checkboxParent = checkbox.closest('.mat-mdc-checkbox');
if (checkboxParent) {
if (checked) {
checkboxParent.classList.add('mat-mdc-checkbox-checked');
} else {
checkboxParent.classList.remove('mat-mdc-checkbox-checked');
}
}
// イベントを発火させる
try {
// 1. change イベント
const changeEvent = new Event('change', { bubbles: true });
checkbox.dispatchEvent(changeEvent);
// 2. inputイベント
const inputEvent = new Event('input', { bubbles: true });
checkbox.dispatchEvent(inputEvent);
// 3. clickイベント
const clickEvent = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
});
checkbox.dispatchEvent(clickEvent);
} catch (e) {
console.warn('イベント発火中にエラー:', e);
}
console.log(`チェックボックス状態変更: ${checked ? '選択' : '解除'}`);
}
// 消去ボタンのイベントリスナー
clearButton.addEventListener('click', function() {
filterInput.value = '';
clearButton.style.display = 'none';
filterSources(''); // フィルターをクリア
});
// 入力イベントのリスナー
filterInput.addEventListener('input', function() {
const searchText = this.value.trim();
// 消去ボタンの表示制御
if (searchText) {
clearButton.style.display = 'block';
} else {
clearButton.style.display = 'none';
}
// ソースのフィルタリング
filterSources(searchText);
});
// フィルタリング機能
function filterSources(searchText) {
// すべてのソースコンテナを取得
const sourceContainers = document.querySelectorAll('.single-source-container');
let visibleCount = 0;
// 表示・非表示を設定(チェックボックスはまだ触らない)
sourceContainers.forEach(container => {
// ソースのタイトルを取得
const titleElement = container.querySelector('.source-title');
if (!titleElement) return;
const title = titleElement.textContent.trim();
const matchesFilter = !searchText || title.toLowerCase().includes(searchText.toLowerCase());
// フィルタに一致するかどうかで表示/非表示を切り替え
if (matchesFilter) {
container.style.display = '';
visibleCount++;
} else {
container.style.display = 'none';
}
});
// 非表示になったソースのみチェックを外す
sourceContainers.forEach(container => {
if (container.style.display === 'none') {
const checkbox = container.querySelector('input[type="checkbox"]');
if (checkbox && checkbox.checked) {
// 非表示のソースのチェックだけを外す
setCheckboxStateAndTriggerEvents(checkbox, false);
}
}
});
// 「すべてのソースを選択」チェックボックスの状態を更新
updateSelectAllCheckbox();
// フィルター結果がない場合の表示
showNoResultsMessage(visibleCount === 0 && searchText !== '');
console.log(`フィルタリング: ${visibleCount} 件表示`);
}
// 「すべてのソースを選択」チェックボックスの状態を更新
function updateSelectAllCheckbox() {
const selectAllCheckbox = document.querySelector('.select-checkbox-all-sources input[type="checkbox"]');
if (!selectAllCheckbox) return;
// 表示されているソースのチェックボックスをすべて取得
const visibleSourceCheckboxes = Array.from(document.querySelectorAll('.single-source-container'))
.filter(container => container.style.display !== 'none')
.map(container => container.querySelector('input[type="checkbox"]'))
.filter(Boolean);
// 表示されているソースが1つもない場合は何もしない
if (visibleSourceCheckboxes.length === 0) return;
// すべてがチェックされているかどうか確認
const allChecked = visibleSourceCheckboxes.every(checkbox => checkbox.checked);
// 「すべてのソースを選択」チェックボックスの状態を更新(既に同じ状態なら何もしない)
if (selectAllCheckbox.checked !== allChecked) {
selectAllCheckbox.checked = allChecked;
// クラスを更新
const checkboxParent = selectAllCheckbox.closest('.mat-mdc-checkbox');
if (checkboxParent) {
if (allChecked) {
checkboxParent.classList.add('mat-mdc-checkbox-checked');
} else {
checkboxParent.classList.remove('mat-mdc-checkbox-checked');
}
}
}
}
// 「すべてのソースを選択」チェックボックスの機能を拡張
const selectAllCheckbox = document.querySelector('.select-checkbox-all-sources input[type="checkbox"]');
if (selectAllCheckbox) {
// 元のクリックイベントハンドラを保存
const originalOnClick = selectAllCheckbox.onclick;
// 新しいクリックイベントハンドラを設定
selectAllCheckbox.onclick = function(e) {
// 元のイベントを呼び出し
if (typeof originalOnClick === 'function') {
originalOnClick.call(this, e);
}
// もし元のイベントによって状態が変わったら、それを元に戻す
// (ダブルクリック防止)
setTimeout(() => {
const isChecked = this.checked;
// 表示されているソースのみチェック状態を変更
const sourceContainers = document.querySelectorAll('.single-source-container');
sourceContainers.forEach(container => {
if (container.style.display !== 'none') {
const checkbox = container.querySelector('input[type="checkbox"]');
if (checkbox && checkbox.checked !== isChecked) {
setCheckboxStateAndTriggerEvents(checkbox, isChecked);
}
}
});
}, 0);
};
}
// 検索結果がない場合のメッセージを表示/非表示
function showNoResultsMessage(show) {
// 既存のメッセージがあれば削除
const existingMessage = document.getElementById('no-results-message');
if (existingMessage) {
existingMessage.remove();
}
if (show) {
// 検索結果がない場合のメッセージを作成して表示
const scrollArea = document.querySelector('.scroll-area-desktop');
if (scrollArea) {
const messageElement = document.createElement('div');
messageElement.id = 'no-results-message';
messageElement.textContent = '検索結果がありません';
messageElement.style.padding = '16px';
messageElement.style.textAlign = 'center';
messageElement.style.color = '#666';
scrollArea.appendChild(messageElement);
}
}
}
console.log('ソースフィルターが正常に追加されました!');
})();最後までお読みいただき、ありがとうございます!
何か1つでも参考になれば幸いです!
オススメマガジン
オススメ拡張機能
人生を豊かにするおすすめ書籍はこちら!
#GPT #Felo #Gemini #Claude #NotebookLM
#IT #プログラミング #AI #エンジニア #RPA #PowerAutomate #PowerAutomateDesktop #Javascript #CSS #HTML #プログラマー
#アプリ #ツール #業務改善 #効率化 #業務効率化 #自動化 #時短 #システム #システムエンジニア #便利ツール #テクノロジー #Youtube #ソース #ソース追加 #一括 #URL #ブックマークレット
#JavaScript #プログラミング #Web開発 #エンジニア #IT #技術 #便利ツール #効率化 #ライフハック #生産性向上 #時短術 #Note #note #ノート #ウェブ制作 #クリエイティブ #AI #Javascript #CSS #HTML #プログラマー #アプリ #ツール #業務改善 #効率化 #業務効率化 #自動化 #時短 #システム #システムエンジニア #便利ツール #テクノロジー
#カスタマイズ #拡張機能 #ライフハック #PC仕事術 #スクレイピング
#リンク収集ツール #Chrome拡張機能 #ウェブ効率化 #デジタルマーケティング #リサーチツール #クリップボード #リンク管理 #情報収集 #ブログ運営 #コンテンツ制作 #ウェブ調査 #業務効率化 #個人開発 #生産性向上 #ウェブスクレイピング #データ収集 #作業自動化
- #note
- #AI
- #youtube
- #Gemini
- #Claude
- #創作大賞2025
- #業務効率化
- #エンジニア
- #プログラミング
- #IT
- #アプリ
- #ライフハック
- #テクノロジー
- #自動化
- #個人開発
- #技術
- #業務改善
- #システム
- #ノート
- #効率化
- #ツール
- #生産性向上
- #クリエイティブ
- #時短
- #notebookLM
- #デジタルマーケティング
- #JavaScript
- #ブログ運営
- #システムエンジニア
- #情報収集
- #時短術
- #HTML
- #コンテンツ制作
- #プログラマー
- #GPT
- #css
- #ソース
- #RPA
- #カスタマイズ
- #便利ツール
- #Web開発
- #スクレイピング
- #拡張機能
- #chrome拡張機能
- #PowerAutomate
- #URL
- #ウェブ制作
- #PowerAutomateDesktop
- #Felo
- #ddd
- #データ収集
- #一括
- #ブックマークレット
- #クリップボード
- #リサーチツール
- #作業自動化
- #ウェブスクレイピング
- #リンク管理
- #PC仕事術
- #ウェブ調査
- #リンク収集ツール
- #ウェブ効率化
- #ソース追加