Hacker News Plus

3 min read Original article ↗
// ==UserScript== // @name HN Plus // @match https://*.ycombinator.com/* // @grant none // @version 2.1 // @author overflowy // @description Adds favicons to HN links and navigation menu for less known sections // @inject-into content // ==/UserScript== // Add favicons functionality var favicons = document.getElementsByClassName("favicon"); if (!(favicons.length > 0)) { const articleLinks = document.querySelectorAll(".titleline > a"); for (let link of articleLinks) { const domain = new URL(link.href).hostname; const imageUrl = `https://icons.duckduckgo.com/ip3/${domain}.ico`; const imgEl = document.createElement("img"); imgEl.src = imageUrl; imgEl.className = "favicon"; imgEl.width = 14; imgEl.height = 14; imgEl.style.paddingRight = "0.25em"; imgEl.style.paddingLeft = "0.25em"; link.style.alignItems = "center"; link.style.display = "inline-flex"; link.style.justifyContent = "center"; link.prepend(imgEl); } } // Add navigation menu function createNavigationMenu() { // Look for the submit link in the main navigation const submitLink = document.querySelector('.pagetop a[href="submit"]'); if (!submitLink) return; // Create the menu button styled like other HN links const menuButton = document.createElement('a'); menuButton.href = '#'; menuButton.textContent = 'extra'; menuButton.style.cssText = 'color: #000000; text-decoration: none;'; // Create the dropdown menu const dropdown = document.createElement('div'); dropdown.className = 'hn-dropdown'; dropdown.style.cssText = ` position: absolute; top: 100%; left: 0; background: #f6f6ef; border: 1px solid #ff6600; z-index: 1000; display: none; min-width: 120px; margin-top: 2px; font-size: 10pt; `; const menuItems = [ { url: 'https://news.ycombinator.com/shownew', label: 'shownew' }, { url: 'https://news.ycombinator.com/pool', label: 'pool' }, { url: 'https://news.ycombinator.com/best', label: 'best' }, { url: 'https://news.ycombinator.com/asknew', label: 'asknew' }, { url: 'https://news.ycombinator.com/bestcomments', label: 'bestcomments' }, { url: 'https://news.ycombinator.com/active', label: 'active' }, { url: 'https://news.ycombinator.com/noobcomments', label: 'newcomments' }, { url: 'https://news.ycombinator.com/noobstories', label: 'newstories' }, { url: 'https://news.ycombinator.com/newest', label: 'newest' } ]; menuItems.forEach((item, index) => { const menuItem = document.createElement('a'); menuItem.href = item.url; menuItem.textContent = item.label; menuItem.style.cssText = ` display: block; padding: 4px 8px; color: #000000; text-decoration: none; font-size: 10pt; ${index < menuItems.length - 1 ? 'border-bottom: 1px solid #ff6600;' : ''} `; menuItem.onmouseover = function() { this.style.backgroundColor = '#ffffff'; }; menuItem.onmouseout = function() { this.style.backgroundColor = 'transparent'; }; dropdown.appendChild(menuItem); }); // Create a wrapper for positioning const wrapper = document.createElement('span'); wrapper.style.position = 'relative'; wrapper.style.display = 'inline'; wrapper.appendChild(menuButton); wrapper.appendChild(dropdown); // Find the separator after submit and insert our menu let nextNode = submitLink.nextSibling; while (nextNode && nextNode.nodeType === 3 && nextNode.textContent.trim() === '') { nextNode = nextNode.nextSibling; } // Insert separator and the menu button after submit const separator = document.createTextNode(' | '); submitLink.parentNode.insertBefore(separator, nextNode); submitLink.parentNode.insertBefore(wrapper, nextNode); // Toggle menu visibility menuButton.addEventListener('click', function(e) { e.preventDefault(); dropdown.style.display = dropdown.style.display === 'none' ? 'block' : 'none'; }); // Close menu when clicking outside document.addEventListener('click', function(e) { if (!wrapper.contains(e.target)) { dropdown.style.display = 'none'; } }); } createNavigationMenu();