// ==UserScript== // @name ๐Ÿญ๏ธ MouseHunt - Item Links // @version 1.2.4 // @description Add links to the MouseHunt wiki, MHCT looter, MHDB, and Markethunt for items. // @license MIT // @author bradp // @namespace bradp // @match https://www.mousehuntgame.com/* // @icon https://brrad.com/mouse.png // @grant none // @downloadURL none // ==/UserScript== /** * Add styles to the page for our added elements. */ const addStyles = () => { const style = document.createElement('style'); style.innerHTML = ` .mh-item-info-text { margin-left: 10px; margin-right: 10px; font-size: 12px !important; font-weight: 300 !important; } .mh-item-info-text-item-popup { padding-top: 2px; text-align: right; }`; document.head.appendChild(style); }; /** * Return an anchor element with the given text and href. * * @param {string} text Text to use for link. * @param {string} href URL to link to. * * @return {string} HTML for link. */ const makeLink = (text, href) => { href = href.replace(/\s/g, '_'); return `${ text }`; }; /** * Return a node with links after grabbing the item ID and name from the page. * * @param {Object} args Arguments to use for the links. * @param {string} args.id CSS selector for the item ID. * @param {string} args.name CSS selector for the item name. * @param {string} args.class CSS class to add to the node. * * @return {false|string} False if no item ID or name found, otherwise HTML for links. */ const getLinksNode = (args) => { const itemInfo = document.querySelector(args.id); if (! itemInfo) { return false; } const itemID = itemInfo.getAttribute('data-item-id'); const itemName = document.querySelector(args.name).textContent; if (! itemID || ! itemName) { return false; } const existingText = document.querySelector('.mh-item-info-text'); if (existingText) { existingText.remove(); } const newText = document.createElement('span'); newText.classList.add('mh-item-info-text'); if (args.class) { newText.classList.add(args.class); } // Add link to the wiki. newText.innerHTML = makeLink('Wiki', `https://mhwiki.hitgrab.com/wiki/index.php/${ itemName }`); // Link to MHCT, either converter or looter. const isConvertible = document.querySelector(args.id + ' .itemView-action.convertible'); newText.innerHTML += ' ยท '; newText.innerHTML += (isConvertible && isConvertible.innerText) ? makeLink('MHCT Converter', `https://www.mhct.win/converter.php?item=${ itemID }&timefilter=all_time`) : makeLink('MHCT Looter', `https://www.mhct.win/loot.php?item=${ itemID }&timefilter=all_time`); // Link to mhdb. const mhdbName = itemName.replace(/'/g, ''); newText.innerHTML += ' ยท ' + makeLink('mhdb', `https://dbgames.info/mousehunt/items/${ mhdbName }`); // Link to markethunt. const isTradable = document.querySelectorAll('.itemView-sidebar-checklistItem.checked'); if (args.forceType === 'marketplace' || (isTradable && isTradable.length === 2)) { newText.innerHTML += ' ยท ' + makeLink('Markethunt', `https://markethunt.vsong.ca/index.php?item_id=${ itemID }`); } return newText; }; /** * Append text to a node, either before or after another node. * * @param {Object} args Arguments to use for the text. * @param {string} args.parent CSS selector for the parent node. * @param {string} args.child CSS selector for the child node. * @param {string} args.content Text to append. * * @return {Node} The node that was appended to. */ const appendText = (args) => { const append = document.querySelector(args.parent); if (! append) { return false; } if (args.child) { const child = document.querySelector(args.child); if (child) { return append.insertBefore(args.content, child); } } else { return append.appendChild(args.content); } return false; }; /** * Add links to the marketplace page for an item. */ const addMarketplaceLinks = () => { appendText({ parent: '.marketplaceView-item-titleActions', child: '.marketplaceView-userGold', content: getLinksNode({ id: '.marketplaceView-item.view', name: '.marketplaceView-item-titleName', forceType: 'marketplace', }) }); }; /** * Add links to the item popup for an item. */ const addItemPopupLinks = () => { appendText({ parent: '.itemView-header-name', content: getLinksNode({ id: '.itemViewContainer', name: '.itemView-header-name span', class: 'mh-item-info-text-item-popup' }), }); }; /** * Fix item qty bug - see https://greasyfork.org/en/scripts/445926-mousehunt-item-quantity-fix */ const fixItemQtyBug = () => { const urlParam = 'i.php?id='; if (window.location.href.indexOf(urlParam) === -1) { return; } const qty = document.querySelector('.itemView-sidebar-quantity'); if (! (qty && qty.textContent.indexOf('You Own:') !== -1)) { return; } const itemName = document.querySelector('.itemViewContainer').getAttribute('data-item-type'); if (! itemName) { return; } hg.views.ItemView.show(itemName); // eslint-disable-line no-undef }; /** * On load, inject styles. */ $(document).ready(function () { // eslint-disable-line no-undef addStyles(); fixItemQtyBug(); }); /** * On ajax refresh, add the links if needed. */ $(document).ajaxComplete(function (_event, _xhr, options) { // eslint-disable-line no-undef if (options.url.indexOf('managers/ajax/users/marketplace.php') !== -1) { addMarketplaceLinks(); } else if (options.url.indexOf('managers/ajax/users/userInventory.php') !== -1) { addItemPopupLinks(); } return true; });