Skip to content

Instantly share code, notes, and snippets.

@piouc
Last active June 23, 2020 03:17
Show Gist options
  • Save piouc/898d6ac71efa88a9162cbf7502740a6a to your computer and use it in GitHub Desktop.
Save piouc/898d6ac71efa88a9162cbf7502740a6a to your computer and use it in GitHub Desktop.
google search keyboard control
// ==UserScript==
// @name google search keyboard controll
// @namespace dev.piou.google_search_controll
// @version 1.1
// @author piouc
// @include /^https?:\/\/www\.google\.(com|co\.jp)\/search/
// @run-at document-end
// @grant GM.openInTab
// ==/UserScript==
(() => {
'use strict'
const blackList = [
/^https?:\/\/matome.naver.jp\//,
/^https?:\/\/www.sejuku.net\//
]
// insert style
const style = document.createElement('style')
document.head.appendChild(style)
style.sheet.insertRule('.g.focus .rc > .r h3, .g.focus .otisdd {outline: 1px dashed #f84; color: #f84}', 0)
style.sheet.insertRule('.g.hide {display: none}', 0)
// utils
function loopIncrement(v, l){
return v < l ? v + 1 : 0
}
function loopDecrement(v, l){
return v > 0 ? v - 1 : l
}
let _selectedIndex = null
const _results = Array.from(document.querySelectorAll('*:not(.kno-kp) .g')).map(el => {
const r = el.querySelector('.r')
if(r){
const a = el.querySelector('.r > a, .r > g-link > a') || r.nextElementSibling.querySelector('a')
if(blackList.some(reg => reg.test(a.href))) {
el.classList.add('hide')
} else {
return {element: el, url: a.href}
}
}
}).filter(obj => obj)
const url = window.location.href
document.addEventListener('keydown', e => {
/**
* [Tab] focus next link
* [Tab + Shift] focus previous link
*/
if(e.key === 'Tab' && !e.ctrlKey){
e.preventDefault()
if(_selectedIndex === null){
_selectedIndex = 0
} else {
_selectedIndex = (e.shiftKey ? loopDecrement : loopIncrement)(_selectedIndex, _results.length - 1)
}
const element = _results[_selectedIndex].element
const pos = element.getBoundingClientRect()
const viewportHeight = document.documentElement.clientHeight
// unforcus all elements
Array.from(document.getElementsByClassName('focus')).forEach(el => el.classList.remove('focus'))
// forcus selected element
element.classList.add('focus')
// scroll as required
if(pos.top < 0){
element.scrollIntoView({block: 'start'})
} else if(pos.bottom > viewportHeight){
element.scrollIntoView({block: 'end'})
}
return
}
/**
* [Enter] Open selected link in new tab
* [Enter + Command] Open selected link in current Tab
*/
if(e.key === 'Enter' && _selectedIndex !== null && e.target.tagName !== 'INPUT') {
console.log('Enter', _results[_selectedIndex])
e.preventDefault()
if(e.metaKey){
location.href = _results[_selectedIndex].url
} else {
GM.openInTab(_results[_selectedIndex].url, false)
}
return
}
/**
* [Escape] Unfocus
*/
if(e.key === 'Escape'){
e.preventDefault()
_selectedIndex = null
// unforcus all elements
Array.from(document.getElementsByClassName('focus')).forEach(el => el.classList.remove('focus'))
return
}
/**
* [Control + E] Search English sites
*/
if(e.key === 'e' && e.ctrlKey && !url.match('lr=lang_en')){
e.preventDefault()
const reg = /lr=lang_\w{2}/
window.location.assign(url.match(reg) ? url.replace(reg, 'lr=lang_en') : url + '&lr=lang_en')
return
}
/**
* [Control + J] Search Japanese sites
*/
if(e.key === 'j' && e.ctrlKey && !url.match('lr=lang_ja')){
e.preventDefault()
const reg = /lr=lang_\w{2}/
window.location.assign(url.match(reg) ? url.replace(reg, 'lr=lang_ja') : url + '&lr=lang_ja')
return
}
})
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment