您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Proving that it's important
当前为
// ==UserScript== // @name Esketit - Add Net Return to Statement // @namespace http://esketit.com/ // @version 2025-06-09 // @description Proving that it's important // @author rs232 // @match https://*esketit.com/investor/account-statement // @icon https://www.google.com/s2/favicons?sz=32&domain_url=https%3A%2F%2Fwww.esketit.com // @grant none // ==/UserScript== (function() { 'use strict'; // Helper: parse a currency string (e.g. "€2 089,10") to a number. function parseCurrency(value) { return parseFloat(value.replace('€', '').replace(/\s/g, '').replace(',', '.')) || 0; } // Calculate Net Return from the 5 rows in the Summary table. function calculateNetReturn() { const rows = [ "Interest received", "Bonus received", "Referral bonus received", "Secondary market income", "Secondary market expense" ]; let total = 0; rows.forEach(rowLabel => { const row = document.evaluate( `//tr[td[text()='${rowLabel}']]`, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; if (row) { const valueCell = row.querySelector('td:nth-child(2)'); if (valueCell) { const valueText = valueCell.textContent.replace('€', '').replace(/\s/g, '').replace(',', '.'); total += parseCurrency(valueText); } } }); return total; } // Update the Net Return row below the Closing Balance row. function addNetReturnRow() { const closingBalanceRow = document.evaluate( "//tr[td[text()='Closing balance']]", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; if (closingBalanceRow) { const netReturn = calculateNetReturn(); const formattedNetReturn = `€${netReturn.toFixed(2).replace('.', ',').replace(/\B(?=(\d{3})+(?!\d))/g, '.')}`; let netReturnRow = document.getElementById('net-return-row'); if (!netReturnRow) { netReturnRow = document.createElement('tr'); netReturnRow.id = 'net-return-row'; netReturnRow.setAttribute('data-v-344f568a', ''); closingBalanceRow.parentNode.insertBefore(netReturnRow, closingBalanceRow.nextSibling); } netReturnRow.innerHTML = ` <td data-v-344f568a="" style="font-weight: bold; color: green;">Net return</td> <td data-v-344f568a="" style="text-align: right; font-weight: bold; color: green;">${formattedNetReturn}</td> `; // Always display the Net Return row with a pale green background. netReturnRow.style.backgroundColor = "#e6ffe6"; // Colorize the Summary rows after updating the Net Return value. colorizeSummaryRows(); } else { console.warn("Closing Balance row not found."); } } // Colorizes each Summary row: // - For "Interest received", "Bonus received", "Referral bonus received", and "Secondary market income": // if their value > 0, set the label and value text to green and the row background to a pale green. // - For "Secondary market expense": if its value is negative, set the label and value text to red and the row background to a pale red. // - For "Sold on secondary market": set the label and value text to dark amber and the row background to a light amber. function colorizeSummaryRows() { const greenRows = [ "Interest received", "Bonus received", "Referral bonus received", "Secondary market income" ]; greenRows.forEach(label => { const row = document.evaluate( `//tr[td[text()='${label}']]`, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; if (row) { const valueCell = row.querySelector('td:nth-child(2)'); if (valueCell) { const value = parseCurrency(valueCell.textContent); if (value > 0) { row.querySelector('td:nth-child(1)').style.color = "green"; row.querySelector('td:nth-child(2)').style.color = "green"; row.style.backgroundColor = "#e6ffe6"; // pale green background } else { row.querySelector('td:nth-child(1)').style.color = ""; row.querySelector('td:nth-child(2)').style.color = ""; row.style.backgroundColor = ""; } } } }); // For "Secondary market expense" const redLabel = "Secondary market expense"; const redRow = document.evaluate( `//tr[td[text()='${redLabel}']]`, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; if (redRow) { const valueCell = redRow.querySelector('td:nth-child(2)'); if (valueCell) { const value = parseCurrency(valueCell.textContent); if (value < 0) { redRow.querySelector('td:nth-child(1)').style.color = "red"; redRow.querySelector('td:nth-child(2)').style.color = "red"; redRow.style.backgroundColor = "#ffe6e6"; // pale red background } else { redRow.querySelector('td:nth-child(1)').style.color = ""; redRow.querySelector('td:nth-child(2)').style.color = ""; redRow.style.backgroundColor = ""; } } } // For "Sold on secondary market" const amberLabel = "Sold on secondary market"; const amberRow = document.evaluate( `//tr[td[text()='${amberLabel}']]`, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; if (amberRow) { const valueCell = amberRow.querySelector('td:nth-child(2)'); if (valueCell) { const value = parseCurrency(valueCell.textContent); if (value > 0) { amberRow.querySelector('td:nth-child(1)').style.color = "#FF8F00"; // dark amber text amberRow.querySelector('td:nth-child(2)').style.color = "#FF8F00"; amberRow.style.backgroundColor = "#FFECB3"; // light amber background } else { amberRow.querySelector('td:nth-child(1)').style.color = ""; amberRow.querySelector('td:nth-child(2)').style.color = ""; amberRow.style.backgroundColor = ""; } } } } // Debounce helper to avoid multiple rapid recalculations. let recalcTimeout; function scheduleRecalculation() { if (recalcTimeout) clearTimeout(recalcTimeout); recalcTimeout = setTimeout(addNetReturnRow, 50); } // Monitor the value cells for changes. function monitorValueChanges() { const rows = [ "Interest received", "Bonus received", "Referral bonus received", "Secondary market income", "Secondary market expense" ]; rows.forEach(rowLabel => { const row = document.evaluate( `//tr[td[text()='${rowLabel}']]`, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; if (row) { const valueCell = row.querySelector('td:nth-child(2)'); if (valueCell) { const observer = new MutationObserver(scheduleRecalculation); observer.observe(valueCell, { childList: true, characterData: true, subtree: true }); } } }); } // On page load, add the Net Return row and start monitoring. window.addEventListener('load', () => { addNetReturnRow(); monitorValueChanges(); }); })();