User:TedSwippet/Interactive calculator

 "use strict";

var twr = { fields: [ {id: 'l1tw',  label: 'L1TW:',  init: 3.9,  valid:/^[\d\.]+%?$/, format: '{}%'}, {id: 'l2tw',  label: 'L2TW:',  init: 30,   valid:/^[\d\.]+%?$/, format: '{}%'}, {id: 'yield', label: 'Yield:', init: 2,    valid:/^[\d\.]+%?$/, format: '{}%'}, {id: 'ter',   label: 'TER:',   init: 0.08, valid:/^[\d\.]+%?$/, format: '{}%'}, {id: 'result', label: 'TWR =', format: '{}%'} ], compute: function(v) { if (v.yield * (1 - v.l1tw/100) >= v.ter) v.result = (v.yield * v.l1tw/100) + ((v.yield * (1 - v.l1tw/100) - v.ter) * v.l2tw/100); else v.result = NaN; v.result = v.result.toFixed(4); } };

var calc_v1 = { name: 'calc_v1',

generate: function(handler, model, prefix) { var styles = { field: 'border-style: solid; border-width: 1px; background-color: #ffffff', button: 'border-style: solid; border-width: 1px; background-color: #dcdcdc; padding: 4px; cursor: pointer' };   var invoke = handler.name + ".calculate('" + prefix + "')"; var fields = model.fields;

var table = '[table id="' + prefix + 'table" class="wikitable"][tbody]' + '[tr]'; for (var field of fields) { if ('init' in field) { var init = field.format.replace('{}', field.init); table += '[td]' + field.label + ' ' + '[input type="text" style="' + styles.field + '" size="6" id="' + prefix + field.id + '"' + ' value="' + init + '" onchange="' + invoke + '" /]' + '[/td]'; }   }    field = fields[fields.length - 1]; table += '[/tr][tr]' + '[td][button style="' + styles.button + '" onclick="' + invoke + '"]Calculate[/button][/td]' + '[td]' + field.label + ' ' + '[input type="text" style="' + styles.field + '" size="6" id="' + prefix + field.id + '" readonly]' + '[/td]' + '[/tr]' + '[/tbody][/table]'; table = table.replace(/\[/g, '<').replace(/\]/g, '>'); if ('log' in calc_v1) console.log(table); return table; },

calculate: function(prefix) { var model = window.calc_persistent[prefix]; var fields = model.fields;

var get_values = function { var values = {}; for (var field of fields) { var value = document.getElementById(prefix + field.id).value; if (value.trim.match(field.valid)) values[field.id] = parseFloat(value); else values[field.id] = NaN; }     return values; };

var set_values = function(values) { var formats = {}; for (var field of fields) formats[field.id] = field.format; for (var id in values) { var value = values[id]; if (!isNaN(value)) value = formats[id].replace('{}', value); else value = 'Error!'; document.getElementById(prefix + id).value = value; }   };

var values = get_values; model.compute(values); if ('log' in calc_v1) console.table(values); set_values(values); } };

var registrar = { register: function (handler, model) { var write = function(string) { var scripts = document.getElementsByTagName('script'); var self = scripts[scripts.length - 1]; self.insertAdjacentHTML('beforebegin', string); }

if (!('calc_persistent' in window)) window.calc_persistent = {counter: 1};

var prefix = handler.name + '-' + window.calc_persistent.counter++ + '-'; window.calc_persistent[prefix] = model;

write(handler.generate(handler, model, prefix)); } };

registrar.register(calc_v1, twr); {{Documentation|content= This template calculates a Tax Withholding Ratio (TWR) for an ETF when held by a US nonresident alien, from values entered into the page by the user. The definition of TWR is:

TWR = (Yield × L1TW) + ((Yield × (1 - L1TW) - TER) × L2TW)

Where:
 * L1TW: Percentage of tax withholding by a security's home country on dividends distributed by that security to the fund (Level 1).
 * L2TW: Percentage of tax withholding by the country where the fund is domiciled on the dividends distributed to the investor by the fund (Level 2).
 * Yield: Annual yield of the fund.
 * TER: The fund's Total Expense Ratio.

This template uses JavaScript to provide live in-page calculations. The computed TWR is updated on pressing the 'Calculate' button, or when the user changes any of the input values.

Usage
Invoke with:

This template takes no arguments. The default input values are currently hardcoded. This template may be transcluded multiple times on a single page.

Examples
}}