// ==UserScript== // @name BrainTools: Custom Menu Links // @namespace brainslug.torn.utility // @version 0.3.2 // @description Inject custom menu links inspired by torntools // @author Brainslug [2323221] // @match https://www.torn.com/* // @icon https://www.google.com/s2/favicons?domain=torn.com // @downloadURL https://raw.githubusercontent.com/br41nslug/torn-brainscripts/main/scripts/custom-menu-links.user.js // @updateURL https://raw.githubusercontent.com/br41nslug/torn-brainscripts/main/scripts/custom-menu-links.user.js // @grant GM_addStyle // ==/UserScript== /** * This list configures which items will be added to the menu. * An item may contain the following settings: * label: This is the text in the link * after/before: Where the link will be inserted (available choices below) * target: The page you are linking to. For torn pages only the "/bazaar.php" part is needed but for external pages you need the full "https://example.com" domain. * icon: For lack of a better solution yet this is plain html to be injected. The icons i used here with the exception of the bazaar were taken from the city map list. * newTab: true/false defaults to false, whether to open a new tab when you click the link */ const customLinks = [ { label: "Raceway", after: "home", target: "/page.php?sid=racing", icon: '' }, { label: "Item Market", before: "items", target: "/imarket.php", icon: '' }, { label: "Bazaar", after: "items", target: "/bazaar.php#/manage", icon: '' }, { label: "Pharmacy", before: "city", target: "/shops.php?step=pharmacy", icon: '' }, { label: "Travel Agency", after: "hall_of_fame", target: "/travelagency.php", icon: '' }, ]; /** * Torn Menu Items: * - home * - items * - city * - job * - gym * - properties * - education * - crimes * - missions * - newspaper * - jail * - hospital * - casino * - forums * - hall_of_fame * - my_faction * - recruit_citizens * - competitions */ const tag = tagName => (attrs={}) => { const elem = document.createElement(tagName); if ( !! attrs.text) elem.innerText = attrs.text; if ( !! attrs.html) elem.innerHTML = attrs.html; if (tagName == 'a') { if ( !! attrs.href) elem.href = attrs.href; if ( !! attrs.target) elem.target = attrs.target; } if ( !! attrs.cls) { if (Array.isArray(attrs.cls)) attrs.cls.forEach(c => elem.classList.add(c)); else elem.classList.add(attrs.cls); } if ( !! attrs.children) attrs.children.forEach(child => elem.append(child)); return elem; }; const watchNav = (linkname, timeout=50, retries=50) => new Promise((resolve, reject) => { let count = 0; const interval = setInterval(() => { const $elem = unsafeWindow.document['querySelector']('#nav-'+linkname); if ( !! $elem) { clearInterval(interval); return resolve($elem); } if (count >= retries) { clearInterval(interval); console.error(`Max retries(${retries}) reached for "#nav-${linkname}"!`); return reject(); } count++; }, timeout); }); const findClass = (cls, elem) => { let result = ''; elem.classList.forEach(className => cls.test(className) && (result = className)); if (result === '') console.error('[BrainTools]', 'class not found!', cls, elem); return result; }; const injectLink = (link, elem) => elem.parentNode.insertBefore(tag`div`({ cls: ['brain-link', findClass(/^area-desktop_/, elem)], children: [tag`div`({ cls: findClass(/^area-row_/, elem.children[0]), children: [tag`a`({ cls: findClass(/^desktopLink_/, elem.children[0].children[0]), href: link.target, target: !! link.newTab ? '_blank' : '_self', children: [ tag`span`({ cls: 'icon', html: link.icon || '', }), tag`span`({ cls: findClass(/^linkName_/, elem.children[0].children[0].children[1]), text: link.label, }), ] })] })] }), !! link.before ? elem : elem.nextSibling); // inject links customLinks.forEach(link => { if ((! link.before && ! link.after) || ! link.target || ! link.label) return console.error('[BrainTools]', 'Bad link configured', link); const selector = !! link.before ? link.before : link.after; watchNav(selector).then(element => { console.info('[BrainTools]', 'Injecting custom link', link.label, link.target); injectLink(link, element); }); }); // inject styles GM_addStyle(` .brain-link a .icon { float: left; width: 34px; height: 23px; display: -webkit-box; display: -ms-flexbox; display: flex; align-items: center; justify-content: center; flex-direction: row; margin-left: 0; } `);