// ==UserScript== // @name @_Ninji insect tracker // @description This userscript allows tracking caught and catchable insects on @_Ninji's website page about 1.2.0 update of AC:NH that list impacts on insects spawns. // @version 2.1 // @author github.com/EnzDev // @match https://wuffs.org/acnh/insects120.html // @grant GM.setValue // @grant GM.getValue // @noframes // @run-at document-end // // Icon is @_Ninji profile pic // @icon https://pbs.twimg.com/profile_images/1222542119367299073/zHIcvDtZ_400x400.jpg // // @namespace http://enzomallard.fr/userscripts // ==/UserScript== // Get the current month const month = (new Date()).toLocaleDateString('en-US', { month: 'short' }).toLowerCase() // Tool to create a node with object of attributes const makeNode = ((type, attrs) => { let node = document.createElement(type); let attributes = Object.entries(attrs).forEach(([t, v]) => node.setAttribute(t, v)); return node; }) // Update thr storage when the input change const updateStorage = (e)=>{ let input = e.target GM.setValue(input.value, input.checked ? 1 : 0) updateStyleForTr(input.parentElement.parentElement) } const getState = async (name) => { let state = await GM.getValue(name, 0) return state === 1 ? true : false } const updateStyleForTr = (tr) => { if(tr.firstChild.firstChild.checked) { tr.classList.add("caught") } else { tr.classList.remove("caught") } if(tr.getElementsByClassName(month)[0].textContent != "") { tr.classList.add("available") } else { tr.classList.remove("available") } } // Immitate browser $$ function const $$ = (it) => Array.from(document.querySelectorAll(it)) // Create the checkboxes for each insect $$("tbody tr").splice(1).forEach(async (tr) => { let d = makeNode("td",{}) let name = tr.getElementsByClassName("insectname")[0].innerText let checkbox = makeNode("input", {"type":"checkbox", "value":name}) checkbox.checked = await getState(name) checkbox.onchange = updateStorage d.append(checkbox) tr.insertBefore(d, tr.firstChild) if(checkbox.checked) { tr.classList.add("caught") } }) // Add a space for the header const head = $$("tbody tr")[0] head.insertBefore(makeNode("th", {}), head.firstChild) // Remove old values $$("s").forEach(it => it.remove()) // Set new values as main text $$("b").forEach(it => { it.parentElement.innerText = it.innerText }) // If the month have a textContent, it is available $$(`.${month}`).forEach((month) => { if(month.textContent != "") month.parentElement.classList.add("available") }) // Stylling const styleEl = document.createElement("style") styleEl.appendChild(document.createTextNode("")) document.head.appendChild(styleEl) const sheet = styleEl.sheet; const pairMonthRule = (rules) => ["jan","mar","may","jul","sep","nov"] .map(month => `${rules} .${month}`) .join(", ") sheet.insertRule('tbody > tr:nth-child(5n+1) > td { border-bottom: solid 5px #666; }') // caught && not available => lightgreen sheet.insertRule(`.caught:not(.available) { background: lightgreen !important; }`) sheet.insertRule(`${pairMonthRule('.caught:not(.available)')} { background: #cfc !important; }`) // caught && available => lightblue sheet.insertRule(`.caught.available { background: lightblue !important; }`) sheet.insertRule(`${pairMonthRule('.caught.available')} { background: #def !important; }`) // available && not caught => lightcoral sheet.insertRule(`.available:not(.caught) { background: lightcoral !important; }`) sheet.insertRule(`${pairMonthRule('.available:not(.caught)')} { background: #faa !important; }`)