forked from AmineB/ycombinator-keys
		
	Rewrite
This commit is contained in:
		| @@ -1,54 +0,0 @@ | ||||
| let selectedId = -1; | ||||
|  | ||||
| document.onkeypress = function(evt) { | ||||
|     evt = evt || window.event; | ||||
|     var charCode = evt.keyCode || evt.which; | ||||
|     var charStr = String.fromCharCode(charCode); | ||||
|     switch(charStr) { | ||||
|         case 'j': | ||||
|             handlePrevious() | ||||
|             selectedId = selectedId + 1; | ||||
|             highlightSelected(); | ||||
|         break; | ||||
|         case 'k': | ||||
|             if (selectedId > 0) { | ||||
|                 handlePrevious() | ||||
|                 selectedId = selectedId - 1; | ||||
|             } | ||||
|             highlightSelected(); | ||||
|         break; | ||||
|         case 'h': | ||||
|             document.querySelectorAll(".itemlist tbody tr td.subtext .clicky")[selectedId].click(); | ||||
|             highlightSelected(); | ||||
|         break | ||||
|         case 'r': | ||||
|             location.reload() | ||||
|         case 'o': | ||||
|             targetBlankClickAndReset(document.querySelectorAll(".itemlist tbody tr.athing td.title a")[selectedId]) | ||||
|         break; | ||||
|         case 'c': | ||||
|             targetBlankClickAndReset(document.querySelectorAll(".itemlist tbody tr td.subtext a:not(.clicky):not(.hnuser)")[selectedId]); | ||||
|         break; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| function highlightSelected() { | ||||
|     if (selectedId != -1) { | ||||
|         document.querySelectorAll(".itemlist tbody tr.athing")[selectedId].style.boxShadow = "0px 0px 10px 4px rgba(0,0,0,0.73)"; | ||||
|     } | ||||
| } | ||||
|  | ||||
| function handlePrevious() { | ||||
|     if (selectedId != -1) { | ||||
|         document.querySelectorAll(".itemlist tbody tr.athing")[selectedId].style.boxShadow = "initial"; | ||||
|     } | ||||
| } | ||||
|  | ||||
| function targetBlankClickAndReset(el) { | ||||
|     el.target = "_blank"; | ||||
|     setTimeout(() => { | ||||
|         el.click(); | ||||
|         el.target = ""; | ||||
|     }) | ||||
| } | ||||
|  | ||||
							
								
								
									
										122
									
								
								keyboard-watcher.user.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								keyboard-watcher.user.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| // ==UserScript== | ||||
| // @name        ycombinator-keys | ||||
| // @namespace   https://gitea.amine-bouabdallaoui.fr/AmineB/ycombinator-keys | ||||
| // @license     gpl-3.0-only | ||||
| // @match       *://news.ycombinator.com/* | ||||
| // @icon        https://gitea.amine-bouabdallaoui.fr/AmineB/ycombinator-keys/raw/branch/main/icons/48.png | ||||
| // @grant       none | ||||
| // @version     4 | ||||
| // @author      AmineB | ||||
| // @description Ycombinator keyboard nav. | ||||
| // @downloadURL https://gitea.amine-bouabdallaoui.fr/AmineB/ycombinator-keys/raw/branch/main/keyboard-watcher.user.js | ||||
| // @updateURL   https://gitea.amine-bouabdallaoui.fr/AmineB/ycombinator-keys/raw/branch/main/keyboard-watcher.user.js | ||||
| // ==/UserScript== | ||||
| // jshint esversion: 11 | ||||
|  | ||||
| globalThis.document.styleSheets[0].insertRule('tbody tr.athing>td.title>span.titleline>a:focus,tbody tr.athing.comtr a.togg.clicky:focus{outline: none}') | ||||
|  | ||||
| const requery = () => globalThis.document.querySelectorAll('tbody tr.athing') | ||||
| let | ||||
| 	query = requery(), | ||||
| 	selected = -1, | ||||
| 	lastCollapsed | ||||
| const | ||||
| 	input = new Set() | ||||
| 		.add('INPUT') | ||||
| 		.add('TEXTAREA'), | ||||
| 	// This is a Firefox only option. For some reason older versions of Firefox can't set outline: none. | ||||
| 	focusInvisible = { __proto__: null, focusVisible: false }, | ||||
| 	isComment = () => query[selected].classList.contains('comtr'), | ||||
| 	highlightSelected = () => { | ||||
| 		query[selected].style.boxShadow = '0px 0px 10px 4px rgba(0,0,0,0.73)' | ||||
|  | ||||
| 		isComment() ? | ||||
| 			// Drawing the boxShadow on this selector isn't visible enough. | ||||
| 			query[selected].querySelector('a.togg.clicky')?.focus(focusInvisible) | ||||
| 			: | ||||
| 			// Focuses link without re-query. | ||||
| 			query[selected].lastChild.firstChild.firstChild.focus(focusInvisible) | ||||
| 	}, | ||||
| 	keydown = event => { | ||||
| 		if (!input.has(event.target.tagName)) | ||||
| 			switch (event.key) { | ||||
| 				case 'j': | ||||
| 					const lastIndex = query.length - 1 | ||||
| 					if (selected === lastIndex) | ||||
| 						return | ||||
|  | ||||
| 					if (selected !== -1) | ||||
| 						query[selected].style.boxShadow = '' | ||||
|  | ||||
| 					let hiddenChain = 0 | ||||
| 					while (selected < lastIndex) { | ||||
| 						const hidden = query[++selected].classList.contains('noshow') | ||||
| 						hiddenChain = hiddenChain * hidden + hidden | ||||
|  | ||||
| 						if (!hidden) { | ||||
| 							lastCollapsed = query[selected].classList.contains('coll') ? selected : undefined | ||||
| 							break | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 					selected -= hiddenChain * (selected - hiddenChain === lastCollapsed) | ||||
| 					highlightSelected() | ||||
| 					return | ||||
| 				case 'k': | ||||
| 					if (selected <= 0) | ||||
| 						return | ||||
|  | ||||
| 					query[selected].style.boxShadow = '' | ||||
|  | ||||
| 					while (selected >= 0 && query[--selected].classList.contains('noshow')); | ||||
| 					highlightSelected() | ||||
| 					return | ||||
| 				case 'h': | ||||
| 					if (globalThis.location.pathname === '/hidden') | ||||
| 						for (const selector of query[selected].nextSibling.querySelectorAll('a')) | ||||
| 							if (selector.innerText === 'un-hide') { | ||||
| 								selector.click() | ||||
| 								break | ||||
| 							} | ||||
| 							else | ||||
| 								query[selected].nextSibling.querySelector('a.clicky.hider')?.click() | ||||
|  | ||||
| 					if (selected + 1 <= query.length) | ||||
| 						highlightSelected() | ||||
| 					return | ||||
| 				case 'c': | ||||
| 					globalThis.open('https://news.ycombinator.com/item?id=' + query[selected].id, '_self') | ||||
| 					return | ||||
| 				case 'C': | ||||
| 					globalThis.open('https://news.ycombinator.com/item?id=' + query[selected].id) | ||||
| 					return | ||||
| 				case 'r': | ||||
| 					if (!isComment()) | ||||
| 						return | ||||
| 					globalThis.open(query[selected].querySelector('div.reply a').href, '_self') | ||||
| 					return | ||||
| 				case 'R': | ||||
| 					if (!isComment()) | ||||
| 						return | ||||
| 					globalThis.open(query[selected].querySelector('div.reply a').href) | ||||
| 					return | ||||
| 				case 'u': | ||||
| 					globalThis.open((isComment() ? query[selected] : query[selected].nextSibling).querySelector('a.hnuser').href, '_self') | ||||
| 					return | ||||
| 				case 'U': | ||||
| 					globalThis.open((isComment() ? query[selected] : query[selected].nextSibling).querySelector('a.hnuser').href) | ||||
| 			} | ||||
| 	}, | ||||
| 	listen = () => globalThis.document.addEventListener('keydown', keydown) | ||||
|  | ||||
| listen() | ||||
|  | ||||
| // This allows for compatibility with automatic pagination scripts. | ||||
| new globalThis.MutationObserver(mutations => { | ||||
| 	for (const mutation of mutations) | ||||
| 		if (mutation.type === 'childList') { | ||||
| 			globalThis.document.removeEventListener('keydown', keydown) | ||||
| 			query = requery() | ||||
| 			return listen() | ||||
| 		} | ||||
| }).observe(globalThis.document.body, { __proto__: null, childList: true, subtree: true }) | ||||
| @@ -1,21 +1,24 @@ | ||||
| { | ||||
|  | ||||
|   "manifest_version": 2, | ||||
|   "name": "Ycombinator keyboard navigation", | ||||
|   "version": "1", | ||||
|  | ||||
|   "description": "Navigate ycombinator with your keyboard", | ||||
|  | ||||
|   "icons": { | ||||
|     "48": "icons/48.png" | ||||
|   }, | ||||
|    | ||||
|   "content_scripts": [ | ||||
|     { | ||||
|       "matches": ["*://*.ycombinator.com/*"], | ||||
|       "js": ["keyboard-watcher.js"] | ||||
|     } | ||||
|   ] | ||||
|  | ||||
| 	"manifest_version": 3, | ||||
| 	"name": "Ycombinator keyboard navigation", | ||||
| 	"version": "4", | ||||
| 	"description": "Navigate ycombinator with your keyboard", | ||||
| 	"icons": { | ||||
| 		"48": "icons/48.png" | ||||
| 	}, | ||||
| 	"content_scripts": [ | ||||
| 		{ | ||||
| 			"matches": [ | ||||
| 				"*://news.ycombinator.com/*" | ||||
| 			], | ||||
| 			"js": [ | ||||
| 				"keyboard-watcher.user.js" | ||||
| 			] | ||||
| 		} | ||||
| 	], | ||||
| 	"browser_specific_settings": { | ||||
| 		"gecko": { | ||||
| 			"id": "{8baac415-d606-422e-89a6-2122747c54dc}" | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										7
									
								
								web-ext-config.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								web-ext-config.mjs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| export default { | ||||
| 	__proto__: null, | ||||
| 	ignoreFiles: [ | ||||
| 		"README.md", | ||||
| 		"LICENSE" | ||||
| 	] | ||||
| } | ||||
		Reference in New Issue
	
	Block a user