您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Show tags in the transactions listing on Mint.com.
当前为
- // ==UserScript==
- // @name Mint.com tags display
- // @include https://*.mint.com/*
- // @description Show tags in the transactions listing on Mint.com.
- // @namespace com.warkmilson.mint.js
- // @author Mark Wilson
- // @version 1.0.1
- // @homepage https://github.com/mddub/mint-tags-display
- // @grant none
- // @noframes
- // ==/UserScript==
- //
- (function() {
- // tweak tag style: (default colors were chosen for consistency with Mint's theme)
- var TAG_STYLE = 'background: #0AC775; color: white; font-size: 10px; display: inline-block; margin-left: 4px; padding: 0 2px';
- var transIdToTags = {};
- var tagIdToName = {};
- function maybeIngestTransactionsList(response) {
- var json = window.JSON.parse(response);
- json['set'].forEach(function(item) {
- if(item['id'] === 'transactions') {
- item['data'].forEach(function(trans) {
- transIdToTags[trans['id']] = trans['labels'].map(function(label) { return label['name']; }).join(', ');
- trans['labels'].forEach(function(label) {
- tagIdToName[label['id']] = label['name'];
- });
- });
- }
- });
- }
- function maybeIngestTagsList(response) {
- var json = window.JSON.parse(response);
- if(json['bundleResponseSent']) {
- jQuery.each(json['response'], function(key, val) {
- if(val['responseType'] === 'MintTransactionService_getTagsByFrequency') {
- val['response'].forEach(function(tagData) {
- tagIdToName[tagData['id']] = tagData['name'];
- });
- }
- });
- }
- }
- function interceptTransactionEdit(data) {
- var transIds = [];
- var tagNames = [];
- data.split('&').forEach(function(pair) {
- var kv = pair.split('='), key = window.decodeURIComponent(kv[0]), val = window.decodeURIComponent(kv[1]);
- var tagId = key.match(/tag(\d+)/);
- if(tagId !== null && val === '2') {
- tagNames.push(tagIdToName[tagId[1]]);
- }
- // value is '1234:0' for a single transaction, '1234:0,2345:0' for multiple
- if(key === 'txnId') {
- transIds = val.split(',').map(function(tId) { return tId.split(':')[0]; });
- }
- });
- transIds.forEach(function(tId) {
- transIdToTags[tId] = tagNames.join(', ') || undefined;
- if(jQuery('#transaction-' + tId).length > 0) {
- updateRow('transaction-' + tId);
- }
- });
- }
- // update a transaction row using cached tag data
- function updateRow(rowId) {
- var $td = jQuery('#' + rowId).find('td.cat');
- var transId = rowId.split('-')[1];
- if(transIdToTags[transId]) {
- if($td.find('.gm-tags').length === 0) {
- $td.append('<span class="gm-tags" style="' + TAG_STYLE + '"></span>');
- }
- $td.find('.gm-tags').text(transIdToTags[transId]);
- } else {
- $td.find('.gm-tags').remove();
- }
- }
- (function(open) {
- XMLHttpRequest.prototype.open = function() {
- // Firefox and Chrome support this.responseURL, but Safari does not, so we need to store it
- var requestURL_ = arguments[1];
- // instrument all XHR responses to intercept the ones which may contain transaction listing or tag listing
- this.addEventListener("readystatechange", function() {
- if(this.readyState === 4 && requestURL_.match('getJsonData.xevent')) {
- maybeIngestTransactionsList(this.responseText);
- } else if(this.readyState === 4 && requestURL_.match('bundledServiceController.xevent')) {
- maybeIngestTagsList(this.responseText);
- }
- }, false);
- // instrument all XHR requests to intercept edits to transactions
- if(arguments[0].match(/post/i) && arguments[1].match('updateTransaction.xevent')) {
- var self = this, send = this.send;
- this.send = function() {
- interceptTransactionEdit(arguments[0]);
- send.apply(self, arguments);
- };
- }
- open.apply(this, arguments);
- };
- })(XMLHttpRequest.prototype.open);
- function observeDOM(target) {
- var observer;
- function handleMutations(mutations) {
- var rowIdsToUpdate = {};
- mutations.forEach(function(mutation) {
- var $target = jQuery(mutation.target);
- var $tr = jQuery(mutation.target).parents('tr').first();
- if(!$target.hasClass('gm-tags') && $tr.length && $tr.attr('id') && $tr.attr('id').indexOf('transaction-') === 0) {
- // when the transactions list changes, there will be multiple mutations per row (date column, amount column, etc.)
- rowIdsToUpdate[$tr.attr('id')] = true;
- }
- });
- observer.disconnect();
- for(var rowId in rowIdsToUpdate) {
- updateRow(rowId);
- }
- observe();
- }
- function observe() {
- observer = new MutationObserver(handleMutations);
- observer.observe(
- target,
- {subtree: true, childList: true, characterData: true}
- );
- }
- observe();
- }
- (function waitForTable() {
- var target = document.querySelector('#transaction-list-body');
- if(target === null) {
- setTimeout(waitForTable, 500);
- return;
- }
- // populate the table with tags after it first loads
- jQuery(target).find('tr').each(function(_, row) {
- updateRow(row.id);
- });
- observeDOM(target);
- })();
- })();