// ==UserScript==
// @name Google Search Sidebar
// @namespace http://tampermonkey.net/
// @version 2.0
// @description Add a foldable sidebar and scroll bottoms on Google Search for easier information filtering
// @author Kamiya Minoru
// @icon https://www.google.com/favicon.ico
// @match https://www.google.com/*
// @match https://www.google.com.tw/*
// @match https://www.google.co.jp/*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
const userLang = navigator.language || navigator.userLanguage;
const i18n = {
'zh-TW': {
languageSection: '語言過濾 …',
timeSection: '時間過濾 …',
advancedSearch: '進階搜尋',
languages: {
any: '不限語言搜尋',
zhTW: '以繁體中文搜尋',
zh: '以中文搜尋',
ja: '以日文搜尋',
en: '以英文搜尋'
},
times: {
any: '不限時間',
hour: '過去1小時',
day: '過去24小時',
week: '過去7天',
month: '過去1個月',
months3: '過去3個月',
year: '過去1年',
years3: '過去3年'
}
},
'ja': {
languageSection: ' 言語フィルター …',
timeSection: ' 期間フィルター',
advancedSearch: '検索オプション',
languages: {
any: '言語指定なし',
zhTW: '繁体中国語で検索',
zh: '中国語で検索',
ja: '日本語で検索',
en: '英語で検索'
},
times: {
any: '期間指定なし',
hour: '1時間以内',
day: '24時間以内',
week: '1週間以内',
month: '1か月以内',
months3: '3か月以内',
year: '1年以内',
years3: '3年以内'
}
},
'en': {
languageSection: 'Language Filter …',
timeSection: 'Time Filter',
advancedSearch: 'Advanced Search',
languages: {
any: 'Any Language',
zhTW: 'Traditional Chinese',
zh: 'All Chinese',
ja: 'Japanese',
en: 'English'
},
times: {
any: 'Any Time',
hour: 'Past Hour',
day: 'Past 24 Hours',
week: 'Past Week',
month: 'Past Month',
months3: 'Past 3 Months',
year: 'Past Year',
years3: 'Past 3 Years'
}
}
};
function getLocale() {
if (i18n[userLang]) {
return i18n[userLang];
}
const primaryLang = userLang.split('-')[0];
if (i18n[primaryLang]) {
return i18n[primaryLang];
}
return i18n['en'];
}
const locale = getLocale();
const languageFilters = [
{ text: locale.languages.any, param: '&lr=' },
{ text: locale.languages.zhTW, param: '&lr=lang_zh-TW' },
{ text: locale.languages.zh, param: '&lr=lang_zh' },
{ text: locale.languages.ja, param: '&lr=lang_ja' },
{ text: locale.languages.en, param: '&lr=lang_en' }
];
const timeFilters = [
{ text: locale.times.any, param: '&tbs=' },
{ text: locale.times.hour, param: '&tbs=qdr:h' },
{ text: locale.times.day, param: '&tbs=qdr:d' },
{ text: locale.times.week, param: '&tbs=qdr:w' },
{ text: locale.times.month, param: '&tbs=qdr:m' },
{ text: locale.times.months3, param: '&tbs=qdr:m3' },
{ text: locale.times.year, param: '&tbs=qdr:y' },
{ text: locale.times.years3, param: '&tbs=qdr:y3' }
];
// advanced search
function createAdvancedSearchLink() {
const link = document.createElement('a');
link.textContent = locale.advancedSearch;
link.href = getAdvancedSearchUrl();
link.style.cssText = `
display: block;
color: #1a73e8;
text-decoration: none;
font-size: 14px;
padding: 5px;
margin-top: 0px;
background: #ecedef;
border-radius: 8px;
text-align: center;
transition: background-color 0.2s;
`;
link.addEventListener('mouseover', () => {
link.style.backgroundColor = '#1a73e8';
link.style.color = '#FFFFFF';
});
link.addEventListener('mouseout', () => {
link.style.backgroundColor = '#ecedef';
link.style.color = '#1a73e8';
});
return link;
}
function createFilterSection(title, filters, collapsible = false, defaultExpanded = false) {
const section = document.createElement('div');
section.style.cssText = `
margin: 3px 0;
padding: 3px;
background: #ecedef;
border-radius: 8px;
`;
const titleElement = document.createElement('h3');
titleElement.textContent = title;
titleElement.style.cssText = `
margin: 0 0 2px 0;
padding-top: 5px;
font-size: 14px;
color: #202124;
font-weight: 500;
cursor: ${collapsible ? 'pointer' : 'default'};
text-align: center;
`;
section.appendChild(titleElement);
const linkContainer = document.createElement('div');
linkContainer.style.cssText = `
display: flex;
flex-direction: column;
gap: 3px;
${collapsible && !defaultExpanded ? 'display: none;' : ''}
`;
filters.forEach(filter => {
const link = document.createElement('a');
link.textContent = filter.text;
link.href = getCurrentUrlWithParam(filter.param);
link.style.cssText = `
color: #888888;
text-decoration: none;
font-size: 12px;
padding: 2px 2px;
border-radius: 8px;
transition: background-color 0.2s, color 0.2s;
`;
const urlParams = new URL(window.location.href).searchParams;
if (urlParams.get('lr') === filter.param.replace('&lr=', '') ||
urlParams.get('tbs') === filter.param.replace('&tbs=', '')) {
link.style.color = '#1a73e8';
link.style.fontWeight = 'bold';
}
link.addEventListener('mouseover', () => {
link.style.backgroundColor = '#1a73e8';
link.style.color = '#FFFFFF';
});
link.addEventListener('mouseout', () => {
if (urlParams.get('lr') !== filter.param.replace('&lr=', '') &&
urlParams.get('tbs') !== filter.param.replace('&tbs=', '')) {
link.style.color = '#888888';
link.style.backgroundColor = 'transparent';
}
});
linkContainer.appendChild(link);
});
section.appendChild(linkContainer);
if (collapsible) {
titleElement.addEventListener('click', () => {
linkContainer.style.display = linkContainer.style.display === 'none' ? 'flex' : 'none';
});
}
return section;
}
function getCurrentUrlWithParam(param) {
const url = new URL(window.location.href);
// Preserve existing parameters
const existingParams = new URLSearchParams(url.search);
// Remove existing language or time parameters if "any" is selected
if (param.includes('lr=')) {
existingParams.delete('lr');
}
if (param.includes('tbs=')) {
existingParams.delete('tbs');
}
// Add new parameters
if (param) {
const cleanParam = param.startsWith('&') ? param.substring(1) : param;
const [key, value] = cleanParam.split('=');
if (value) {
existingParams.set(key, value);
} else {
existingParams.delete(key);
}
}
url.search = existingParams.toString();
return url.toString();
}
function getAdvancedSearchUrl() {
const url = new URL('https://www.google.com/advanced_search');
const currentParams = new URLSearchParams(window.location.search);
return url.toString();
}
// sidebar position
const observer = new MutationObserver((mutations, obs) => {
const searchResults = document.getElementById('search');
if (searchResults) {
const sidebar = document.createElement('div');
sidebar.style.cssText = `
position: fixed;
top: 23px;
left: 7px;
width: 160px;
z-index: 1000;
`;
sidebar.appendChild(createFilterSection(locale.languageSection, languageFilters, true, window.location.href.includes('&lr=')));
sidebar.appendChild(createFilterSection(locale.timeSection, timeFilters, true, window.location.href.includes('&tbs=')));
sidebar.appendChild(createAdvancedSearchLink());
document.body.appendChild(sidebar);
obs.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
})();
(function() {
'use strict';
function createScrollButton(innerHTML, onClick) {
var button = document.createElement('div');
button.innerHTML = innerHTML;
button.style.width = '30px';
button.style.height = '34px';
button.style.cursor = 'pointer';
button.style.backgroundColor = 'transparent';
button.style.color = 'grey';
button.style.textAlign = 'center';
button.style.fontSize = '30px';
button.style.borderRadius = '0px';
button.style.userSelect = 'none';
button.style.marginBottom = '0px';
button.style.opacity = '0.2';
button.style.transition = 'all 0s';
button.style.filter = 'drop-shadow(0 0 0 grey)';
button.addEventListener('click', onClick);
button.addEventListener('mouseover', function() {
button.style.opacity = '1';
button.style.filter = 'drop-shadow(0 0 2px grey)';
button.style.color = '#FFF';
});
button.addEventListener('mouseout', function() {
button.style.opacity = '0.1';
button.style.filter = 'drop-shadow(0 0 0 grey)';
button.style.color = 'grey';
});
return button;
}
// scroll bar
function addScrollButtonsToSidebar() {
const sidebar = document.querySelector('div[style*="position: fixed"]');
if (!sidebar) return;
const scrollContainer = document.createElement('div');
scrollContainer.style.cssText = `
position: absolute;
top: 3px;
left: 130px;
display: flex;
flex-direction: column;
align-items: center;
margin-top: 0px;
`;
scrollContainer.appendChild(createScrollButton('⇑', function() {
window.scrollTo({ top: 0, behavior: 'instant' });
}));
scrollContainer.appendChild(createScrollButton('⇡', function() {
window.scrollBy({ top: -window.innerHeight, behavior: 'instant' });
}));
scrollContainer.appendChild(createScrollButton('⇣', function() {
window.scrollBy({ top: window.innerHeight, behavior: 'instant' });
}));
scrollContainer.appendChild(createScrollButton('⇓', function() {
window.scrollTo({ top: document.body.scrollHeight, behavior: 'instant' });
}));
sidebar.appendChild(scrollContainer);
}
const observer = new MutationObserver((mutations, obs) => {
const sidebar = document.querySelector('div[style*="position: fixed"]');
if (sidebar) {
addScrollButtonsToSidebar();
obs.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
})();