Template:Interactive calculator/doc

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.

Technical notes
The JavaScript code is split into two parts. The piece that defines the wanted inputs and the calculation done on them is in the  pseudo-namespace. The rest of it,, is just 'plumbing' to create and update screen elements.

Main approach

 * defines the input fields (id, name, initial value, validator pattern, and output format), and a single output (result) field. The result must be the last listed, and have no initial value or pattern. It defines the calculation that generates the result. It also holds a unique name for this set of data (see Code reusability below).
 * On loading the page,  creates an HTML table element containing input fields and a 'Calculate' button, from data in  . It adds this to the DOM, at the script location. Elements in the table are tagged with an ID that is unique to this invocation.
 * On update of an input field or click on 'Calculate',  is called. This validates the inputs, runs the required calculation, then updates all the fields. Invalid inputs generate NaN, displayed as 'Error!'.

Multiple transclusion

 * Support for more than one transclusion in a page is provided by generating unique identifiers for html input and output elements. On update or 'Calculate',  receives an argument indicating which transclusion instance was activated. From this, it can deduce which input and output elements to update.
 * The unique identifiers are created by placing a counter in  and sharing   globally among scripts by attaching it to the global page object . Sequence numbers increment on each transclusion.

Code reusability

 * A single instance of  can support multiple instances of transclusion. This is a requirement, since it is effectively redefined each time.
 * It can also support multiple different models, where  is one of many possible models. This allows the code to be quickly repurposed into a different type of calculator. For example, the following model will create a monthly compound interest calculator:
 * On update or 'Calculate',  receives an argument indicating which model the active instance is using.
 * For multiple calculators of different types to coexist on a single page, the pseudo-namespace names for the models must be globally unique. Otherwise, the differing definitions will clash when combined. (There is no problem where multiple identical definitions occur on a single page.) Separate models'  properties must also be unique; simplest is to always make   the same as the model pseudo-namespace.

Portability

 * The current code uses the minimum required set of JavaScript features. It consciously avoids any features that might not be present in some older browsers.
 * MediaWiki's Mobile frontend/skin creates CSS styles that do not display well with  and   HTML elements. To improve things, these elements are explicitly styled to appear broadly similar in both Desktop and Mobile views.

Coding restrictions

 * MediaWiki does not "play well" with  elements. Several aspects of this code are designed to avoid triggering MediaWiki into replacing text inside the script that will either stop it working, or at worst render it into invalid JavaScript syntax. The current known problem areas are:
 * Conditional expressions. MediaWiki will convert  into  . This is no longer syntactically valid JavaScript. Workround is to remove the spaces around the '?' and ':', but this creates poor code readability.
 * Ampersand. MediaWiki will convert  into  . This is no longer syntactically valid JavaScript. Workround is to use nested conditionals.
 * Some HTML tags. MediaWiki may entirely remove a selection of HTML tags from inside the script, even when within quoted strings. For example,  turns into the empty string,  . Likewise   and  ' . The result is syntactically valid, but will fail to execute properly. The current implementation tackles this by using '[' and ']' to enclose tags, and then globally replacing them with '<' and '>' on output. This is simple, but rather clumsy.