Template:Calculator
This template is for creating interactive calculators. It requires the calculator gadget.
You can use this template multiple times on a page to make input widgets, with some of the widgets having formulas based on other widgets, like a spreadsheet
Example
{{calculator|id=a|default=2|size=4}} × {{calculator|id=b|default=2|size=4}} = {{calculator|id=c|formula=a*b|default=4|size=8|readyonly=true|type=text}}
produces:
2 × 2 = 4
BMI calculator metric
{| class="wikitable" style = "float: left; margin-left:15px;"
|+ Metric
|-
| {{Calculator label|Weight|for=weightkg}} || {{calculator|id=weightkg|size=3}} kg
|-
| {{calculator label|Height|for=heightkg}} || {{calculator|id=heightcm|size=3}} cm
|-
| BMI || '''{{calculator|id=bmimetric|type=plain|formula=round(weightkg/pow(heightcm/100,2))|style=min-width:3ch;display:inline-block}} kg/m<sup>2</sup>'''
|}
| Weight | kg |
| Height | cm |
| BMI | kg/m2 |
BMI calculator imperial
You can put widgets inside tables:
<table class="wikitable">
<tr><td>Imperial</td></tr>
<tr><td>Weight</td><td>{{calculator|id=weight|size=3}} lbs</td></tr>
<tr><td>Height</td><td>{{calculator|id=heightFeet|size=1}} feet {{calculator|id=heightInches|size=2}} inches</td></tr>
<tr><td>BMI</td><td>'''{{calculator|id=bmi|type=plain|formula=round(100*weight*703/pow(heightFeet*12+heightInches,2))/100}} kg/m<sup>2</sup>'''</td></tr>
</table>
| Imperial | |
| Weight | lbs |
| Height | feet inches |
| BMI | kg/m2 |
Other
Formula
Formulas use normal math syntax, with english words representing other input boxes. e.g. sin(1+foo*2) would multiply the foo box by 2, add 1 and take the sine of the whole thing. All calculations are done using IEEE 754 double precision floating point numbers.
Operators supported include: +, -, *, ×, /, ÷, % (percent is the modulo operator). Exponentiation must use the pow() function.
Math functions supported include: 'abs', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'cos', 'cosh', 'exp', 'floor', 'hypot', 'log', 'log10', 'log2', 'max', 'min', 'pow', 'random', 'sign', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc'
These have the same definition as in javascript. In particular, that means that log() is log base-e. The exception is round, which we use our own definition of
The following additional functions are supported which are not from javascript Math library:
- ifzero - if first argument is epsilon away from zero, return second argument, otherwise third argument. The last two arguments are optional and default to 1 and 0 respectively.
- ifnan - if first argument is not a number (NaN), return second argument, otherwise third argument. The last two arguments are optional and default to 1 and 0 respectively.
- iffinite - if the first argument is finite return second argument, otherwise return third argument. The last two arguments are optional and default to 1 and 0 respectively.
- coalesce - return the first argument that is not NaN.
- ifpositive - if first argument is ≥ 0 return second, otherwise return third. (Note this does not account for floating point rounding. You can use this if you need precise control over the comparision) The last two arguments are optional and default to 1 and 0 respectively.
- ifequal - If first and second argument are the same, accounting for floating point error. The last two arguments are optional and default to 1 and 0 respectively.
- round - A round function. Unlike javascript round(), this implements round half away from zero ("commercial rounding"). It takes an optional second argument to say how many decimal digits to rount to. e.g. round( 3.125, 2 ) = 3.13, round( -3.125, 2 ) = -3.13.
- jsround - Use javascript round. This does round half towards positive infinity with a precision of 0. See mdn docs
- not - return 1 if value is very close to 0 or NaN, otherwise 0
- bool - return 0 if value is very close to 0 or NaN, otherwise 1
- and - and of all arguments (can take more than 2). This operator short circuits like lua, and returns first false argument. Wrap in bool() if you want a 1 or a 0
- or - or of all arguments (can take more than 2). This operator short circuits like lua, and returns first true argument. Wrap in bool() if you want a 1 or a 0
- xor - Exclusive or. Can only take 2 arguments, always return 1 or 0.
- ifless - return third or fourth argument depending on if first argument is < second argument. Comparison is fuzzy to account for floating point error. Use ifpositive() if you don't want that. The last two arguments are optional and default to 1 and 0 respectively.
- iflessorequal - return third or fourth argument depending on if first argument is <= second argument. Comparison is fuzzy to account for floating point error. Use ifpositive() if you don't want that. The last two arguments are optional and default to 1 and 0 respectively.
- ifgreater - return third or fourth argument depending on if first argument is > second argument. Comparison is fuzzy to account for floating point error. Use ifpositive() if you don't want that. The last two arguments are optional and default to 1 and 0 respectively.
- ifgreaterorequal - return third or fourth argument depending on if first argument is >= second argument. Comparison is fuzzy to account for floating point error. Use ifpositive() if you don't want that. The last two arguments are optional and default to 1 and 0 respectively.
- ifbetween - return either fourth or fifth argument depending on if the first argument is between the second or third argument. Comparison is not fuzzy. The last two arguments are optional and default to 1 and 0 respectively.
- index - Array like indirect references. Get the value of the variable formed by concatenating the first argument with the evaluated value of the second. For example
index( foo, 2+3 )is the same as writing foo5. Second argument must be a finite value >= 0. Returns third argument if the field being referenced doesn't exist or NaN if there is no third argument. Returns NaN if first or second argument are invalid.
Numbers can be integers, decimals or scientific notation. For example: 1, 2.84543, 3.12E6, -5, 3.45×10⁻⁴⁵
The following constants are supported: Infinity, -Infinity, NaN, pi, π, EPSILON
At the moment, relational operators like ≤ or ≠ and IF statements are not supported. This might be added in a future version if needed. This can be worked around by using ifzero and ifpositive functions.
Scoping
If the calcuator widgets are contained within an element with the class calculator-container, then the ids are scoped to this element. This allows you to use the same ids multiple times on the same page without them interfering with each other. If the scoping element has the attribute data-calculator-refresh-on-load="true", then the calculator widgets are refreshed on first page load before the user interacts with it.
For example:
<div class="calculator-container" data-calculator-refresh-on-load="true">
{{calculator label|scopedfield:}} {{calculator|type=text|id=scopedfield|default=3.14}}<br>
This formula is updated before user interaction: {{calculator|type=plain|formula=scopedfield|default=No value}}
</div>
This formula is not updated because it is in a different scope: {{calculator|type=plain|formula=scopedfield|default=No value}}
Produces the following:
3.14
This formula is updated before user interaction: No value
This formula is not updated even after user interaction because it is in a different scope: No value
CSS
You can use CSS to adjust the display, either via TemplateStyles or inline styles.
- For checkboxes and radio buttons, you can use the :checked pseudo selector. This can be very useful when combined with sibling css selectors (~) or :has()
- You can look for the class names calculator-value-true and calculator-value-false. This is especially useful with the passthru type of field.
- You can target the
data-calculator-field-valueattribute. e.g. #calculator-field-fieldidhere[calculator-field-scopedfield^="3."] would select the field if it is >= 3.0 and < 4.0. - You can use css variables for more complex calculations (Only in inline styles)
Adjust color of border: 30
Fallback
Users who do not have the gadget enabled or have JS disabled, will not see the input boxes. Instead they will just see the default value for each box. With a good choice of default, this can be sufficient.
For example, if you have ''sin({{calculator|id=sine|type=text|default=0.5|size=4}}π)={{calculator|type=plain|default=1.00|decimals=2|formula=sin(sine*π)|id=sineres}}'' to make sin(0.5π)=1.00, the non-js user will lose the interactivity, but they will still see the equation.
If you want more sophisticated fallbacks, you can use the calculatorgadget-enabled and calculatorgadget-fallback CSS classes.
<div class="calculatorgadget-enabled" style="display:none">This text is only shown if the gadget is enabled. {{calculator|type=text|size=20|default=100|id=xyz}} </div>
<div class="calculatorgadget-fallback">This text is only shown if the gadget is disabled</div>
Which produces:
Codex
If you want to make the widgets use MediaWiki's style, you can follow the CSS only instructions at https://doc.wikimedia.org/codex/latest/components/demos/ (This might require a newer version of mediawiki than medwiki uses)
e.g.
<div class="cdx-checkbox">
<div class="cdx-checkbox__wrapper">{{calculator|id=mycheckbox|type=checkbox|class-live=cdx-checkbox__input}}
<span class="cdx-checkbox__icon"></span>
<div class="cdx-checkbox__label cdx-label">{{calculator label|for=mycheckbox|class=cdx-label__label|label=<span class="cdx-label__label__text"> Checkbox 1 </span>}}</div>
</div>
</div>
makes:
<div class="cdx-text-input">{{calculator|id=mytextfield|type=text|class-live=cdx-text-input__input|default=42}}</div>
Makes <div class="cdx-radio">
<div class="cdx-radio__wrapper">
{{calculat|id=radiobutton|class-live=cdx-radio__input|type=radio|name=radiobuttongroup}}
<!-- Empty span that will be styled to look like a radio input. -->
<span class="cdx-radio__icon"></span>
<div class="cdx-radio__label cdx-label">
<!-- Label with `for` attribute matching the input's id. -->
{{calculator label|class=cdx-label__label|for=radiobutton|label=<span class="cdx-label__label__text"> Radio 1 </span>}}
</div>
</div>
</div>
Makes:
Template arguments
Note: Not all arguments work on all input types.
- id
- The id for this field, used in formulas of other fields (Has to be english characters)
- default
- The starting value
- readonly
- Make field read only
- formula
- The formula to calculate this field. See below for what is supported
- type
- Type of field. Currently supported are plain (Just plain text), number, text, radio, checkbox, range (A slider), hidden, passthru (Do not change text, only add css classes).
- size
- how big to make the input box (In terms of number of letters that can fit in the box)
- max
- Max number allowed (number type only)
- min
- Min number allowed (number type only)
- placeholder
- Placeholder text that shows up light grey when there is no input
- step
- How big the interval is for type=number inputs
- style
- Custom CSS to use for the element.
- name
- When using type=radio, the name of the radio group.
- precision
- Format field to this many significant digits. (Only works type=plain and type=text)
- exponential-precision
- Format field to this many significant digits in scientific notation. (Only works type=plain and type=text)
- decimals
- Format field to this many decimal digits. (Only works type=plain and type=text)
- NaN-text
- Use this text instead of NaN when result is not a number (Only works type=plain and type=text)
- class
- Classes to add to the element (These classes are added regardless of if js/gadget is enabled)
- class-live
- Classes to add only once gadget is activated
Add a calculator widget to the page. Like a spreadsheet you can refer to other widgets in the same page.
| Parameter | Description | Type | Status | |
|---|---|---|---|---|
| id | id | The id for this input. This is used to reference it in formula of other calculator templates | String | required |
| type | type | What type of input box
| String | required |
| formula | formula | Formula to calculate this field
| String | suggested |
| readonly | readonly | Make input box readonly to user input | Boolean | optional |
| size | size | Size of input box (How many characters it will fit) | Number | optional |
| max | max | max number allowed (type=number inputs only) | Number | optional |
| min | min | min number allowed (type=number inputs only) | Number | optional |
| placeholder | placeholder | Text to put as a placeholder in empty input | String | optional |
| step | step | How much to increment a type=number input box
| Number | optional |
| default | default | Default value for this field | String | suggested |
| style | style | CSS to style the input element with | String | optional |
| name | name | For type=radio what group to assign the radio button to | Unknown | optional |
| precision | precision | Format to this many significant digits, using decimal notation except for really large numbers [Only applies to type=number or type=plain]
| Number | optional |
| exponential-precision | exponential-precision | Format to this many significant digits, using scientific notation [Only applies to type=number or type=plain]
| Number | optional |
| decimals | decimals | Format to a fixed number of decimal digits [Only applies to type=number or type=plain]
| Number | optional |
| NaN-text | NaN-text | Use this text instead of NaN to signify "not a number". Only applies to format=plain or format=text. Plaintext only; wikitext is not supported
| String | optional |
| class | class | Space separated list of additional classes | String | optional |
| class-live | class-live | Space separated list of additional classes to only apply if gadget is enabled | Unknown | optional |