Loading
  • 21 Aug, 2019

  • By, Wikipedia

Template:Calculator

This template is for creating interactive calculators. It requires the calculator gadget. The calculator works by default. You can opt out at: Preferences > Gadgets > Template Gadgets > Enables javascript Calculator template. All pages using this system are added to Category:Pages using gadget Calculator.

You can use this template multiple times on a page to make input widgets, with some of the widgets using also the results of other widgets, like a spreadsheet cell that does a computation based on results of computations in other cells.

You can use {{Calculator label}} to mark text as a label for a calculator widget.

Statistics for this template are available at graphite

Examples

Here is a simple example to multiply two numbers. We invoke two calculator templates with no formula that act as input fields. We then invoke a third instance which has a formula for multiplying the other two cells. Note that formulas only take affect after the user interacts, so all cells need a default to use as initial value before user interaction.

{{calculator|id=a|default=2|size=4}} × {{calculator|id=b|default=2|size=4}} = {{calculator|id=c|formula=a*b|default=4|type=plain}}

produces:

2 × 2 = 4

{{calculator|id=km|type=number|size=9|default=1.609344|formula=miles*1.609344}} km = 
{{calculator|id=miles|type=number|size=9|default=1|formula=km/1.609344}} miles 

produces:

1.609344 km = 1 miles


BMI calculator metric

You can put widgets inside a wikitable.

{| class="wikitable" style = "float: left; margin-left:15px;"
|+ Metric
|-
| {{calculator label|Weight|for=weightkg}} || {{calculator|id=weightkg|size=3|default=80}} kg
|-
| {{calculator label|Height|for=heightcm}} || {{calculator|id=heightcm|size=3|default=160}} cm
|-
| BMI || '''{{calculator|id=bmimetric|type=plain|formula=round(weightkg/pow(heightcm/100,2))|default=31|style=min-width:3ch;display:inline-block}} kg/m<sup>2</sup>'''
|}
Metric
Weight 80 kg
Height 160 cm
BMI 31 kg/m

BMI calculator imperial

You can also put widgets inside an HTML table.

<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/m

Other

Buttons

When pressed, the {{calculator button}} updates a form field.

{{calculator button|contents=Click me!|for=buttoncount|formula=buttoncount+1|type=default}} 

The button has been clicked {{calculator|type=plain|default=0|id=buttoncount}} times.

Click me!

The button has been clicked 0 times.

Labels

A {{calculator label}}

  1. adds a text label to a calculator widget, improving its accessibility. Screen readers will use labels when informing the user which text box they have focused on.
  2. when clicked, give focus to the input widget, especially helpful for small widgets
  3. selects/deselects a checkbox/radio target.
{{calculator|type=checkbox|id=checklabelex}} {{calculator label|label=Please click this label|for=checklabelex}}

Please click this label

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.

Keep in mind that the formula is recalculated only when the user interacts with the calculator. Prior to any user interaction, the "default" parameter to the calculator template is shown even if it is different from what the formula would give initially. Thus you should set the default parameter to what you expect the result of computing the formula will be.

Supported operators

Operators supported include: +, -, *, ×, /, ÷, % (percent is the modulo operator). Exponentiation must use the pow() function.

Math functions

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', 'clz32'

These have the same definition as in javascript. In particular, that means that log() is log base-e. The exception is round, for which we use our own definition.

Additional functions

The following additional functions are supported which are not from javascript Math library:

and
Logical 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. See bitand() for bitwise and
bool
Return 0 if value is very close to 0 or NaN, otherwise 1
coalesce
return the first argument that is not NaN.
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.
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.
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.
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.
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.
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.
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 comparison. The last two arguments are optional and default to 1 and 0 respectively.
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.
index
Allows treating variables like an array with an index evaluated at runtime. index( foo, 2+3 ) is the same as foo5. The first argument must be an identifier (Nested index() is not allowed). The second argument must evaluate to an integer greater than or equal to 0. If either of these two arguments are invalid, NaN is returned. The third argument is returned if the arguments are valid but the result references a variable that does not exist. If unspecified the third argument defaults to NaN.
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
or
Logical 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
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.
xor
Logical exclusive or. Can only take 2 arguments, always return 1 or 0.
switch
The first argument is compared to the second argument, if it is ≤ the second argument, then return the third. Otherwise compare the first argument with the fourth argument, if ≤ return the fifth argument, and so forth. If it is not ≤ to any of the even arguments, and there are an even number of arguments return the last argument, otherwise return NaN. For example if foo is 5 then switch(foo,2,10,4,20,5,30,7,80,-1) returns 30.
radiogroup
Return the value of the radio group specified by the first argument. Unlike most functions, this does not take a field identifier but a radio group name. The value of the radio group is the value of whichever element of the radio group is currently checked (or NaN if none are). The value of a checked radio button is either the value of the formula if it was checked by a formula, or the value parameter if it was checked by a human.
bitand
Treat all args as 32 bit 2's complement integer and bitwise AND them together. Equivalent to the & operator in javascript and most programming languages. Can take any number of arguments.
bitor
Treat all args as 32 bit 2's complement integer and bitwise OR them together. Equivalent to the | operator in javascript and most programming languages. Can take any number of arguments.
bitxor
Treat all args as 32 bit 2's complement integer and bitwise XOR (exclusive or) them together. Equivalent to the ^ operator in javascript and most programming languages. Can take any number of arguments.
bitnot
Treat argument as a 32 bit 2's complement integer and bitwise NOT it. Equivalent to the ~ operator in javascript and most programming languages. Can take only 1 argument.
bitleftshift
Treat first argument as 32 bit 2's complement integer and shift it left by the amount specified in second argument. Equivalent to << in javascript.
bitlogicrightshift
Treat first argument as 32 bit 2's complement integer and shift it right (logically) by the amount specified in second argument. Equivalent to >>> in javascript.
bitarithrightshift
Treat first argument as 32 bit 2's complement integer and shift it right (arithmetically) by the amount specified in second argument. Equivalent to >> in javascript.
if
Opposite of ifzero(). If the first argument is true then return the second, otherwise the third.
getclick
This function only works in buttons. It is designed to allow implementing image maps. If the first argument is x return the x offset in pixels of where in the element the user clicked, and similar for y. If the first argument is percentx then return the x coordinate as a percentage and similar for percenty. Note if the user clicks on a border, the result may be negative or greater than 100%.
timer
Determine if a repeating button has been activated. If no arguments will return 1 if any repeating button is active, 0 otherwise. If there is a first argument, then that is the id of the button to check. The second argument is the value to return if the button is active. The third is the value to return if it is not active.
timeriterations
How many iterations the button has done so far. If no arguments, then any button, otherwise the first one is which button to check.
timertime
How much time has passed between when the button was pressed and the most latest iteration was executed. First optional argument is the id of the button to check.

Numbers

Numbers can be

  • integers
  • decimals
  • scientific notation. For example: 1, 2.84543, 3.12E6, -5, 3.45×10⁻⁴⁵

Supported constants

Scoping

If the calculator 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. Please note that labels are not affected by scoping and will likely go to whatever the next element in the document is with the correct id.

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:

scopedfield: 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

Instead of using the css classes directly, you can also use the {{Calculator ifenabled}} with the scoped parameter.

Mapping

Calculator formulas only work with numbers. However you can use mappings to convert numbers into text when they enter or leave the system. This allows for a very limited form of text input and output.

A mapping is a JSON object linking text strings to numbers. If the user inputs a specific (case-sensitive but whitespace trimmed) string on the list, it gets converted to the specified number. If a number is being outputted, it is checked to see if that number is in the mapping.

Mappings only work for text, plain and select. The values in the mapping object must have a JSON number type, except for the special values "default", "NaN", "Infinity" and "-Infinity" which must be strings. Mapping values are plain text - no wikitext formatting is allowed.

For example:

{{calculator label|
	label=What is your favourite Encyclopedia?
	|for=encyc
}}
{{calculator
	|id=encyc
	|type=text
	|mapping={
		"Wikipedia": 1,
		"WikiPedia": 1,
		"wikipedia": 1,
		"Encyclopædia Britannica": 2,
		"Encyclopaedia Britannica": 2,
		"Britannica": 2,
		"britannica": 2,
		"Encarta": 3,
		"encarta": 3,
		"Nupedia": 4,
		"nupedia": 4
	}
}}
{{calculator
	|formula=encyc
	|type=plain
	|mapping={
		"I haven&apos;t heard of that": "default",
		"I love Wikipedia too!": 1,
		"I guess it is ok": 2,
		"I wish I kept my CD.": 3,
		"rip": 4
	}
}}

Makes:

What is your favourite Encyclopedia?

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. See {{Calculator-hideifzero}} for an example.
  • You can target the data-calculator-field-value attribute. 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)

Some examples:

Adjust color of border:  30

Superimpose an image with coordinates based on a calculator widget:

Height: 178 cm.  Waist: 155 cm.

Codex

It is possible to make widgets be in MediaWiki (Codex) style instead of OS style. You can use most codex widgets that have a CSS-only version. See https://doc.wikimedia.org/codex/latest/components/demos/

Many codex style widgets have separate templates. When making a label, the {{Calculator label}} template has a parameter to output a codex style label

Template Example
{{Calculator codex text}}
Label textShort description text
42
{{Calculator codex radio}}
This is a group of options
First optionAdditional text describing the first option
Second optionAdditional text describing the first option
Third option
{{Calculator codex checkbox}}
First optionAdditional text describing the first option
{{Calculator codex toggle}}
My toggleAdditional text describing the toggle
{{calculator|type=select|class=cdx-select}}
{{Calculator button}} default progressive destructive

default progressive destructive

See the individual template doc pages for all the options.

Fallback

Users who do not have the gadget enabled in their preferences 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:

This text is only shown if the gadget is disabled

Alternatively, you can use the {{Calculator ifenabled}} template to do this.

When using this template you should always be sure it still looks good even if the gadget is unavailable. You should test what the page looks like under print preview, as well as with ?safemode=1 appended to the url (Which is similar to what someone using the mobile app would see). You can use http://bawolff.net/wiki-nojs.htm to test what a page looks like with no javascript at all.

Best practices

Calculator templates have a lot of power, which means the template author has more responsibility to create good templates.

The calculator template cannot be displayed for everyone. People without javascript or people using a screen reader will likely get a very different experience. You should aim to have equivalent content, or failing that, graceful degradation, for such users. You can use {{calculator ifenabled}} to help with this. Generally most calculator fields will show their default value if no javascript is enabled.

  • Always check the page rendering in different modes:
    • Does the template look ok in dark mode
    • Does the template look ok with javascript disabled (Test by adding ?safemode=1 to end of the url). Keep in mind that users of the Wikipedia app will see something very similar to what it looks like with javascript disabled.
    • Does the page look ok in print preview.
    • Does the page look ok on narrow screens, such as what a mobile phone would have. You can use media queries with template styles to adjust the display depending on how wide the screen is.
    • Does the template read ok if using a screen reader (Many screen readers are free to download if you need to test).
      • One thing that can help with screen readers is to set appropriate values for the role and aria-live parameters. This can tell screen readers whether to read out content that has recently changed. Most calculator templates default to an aria-live value of polite (type=passthru defaults to no aria-live), but you can override this. If you are showing something to the user a little at a time, use role=log to tell the screen reader that new content is expected to come. Be sure to set aria-live=off if you use calculator to display some data that is unimportant and should not be read out automatically on change. See mdn for more info
      • Every input widget should have a corresponding {{calculator label}}. This is one of the most important thing to do for accessibility. If you cannot do that for some reason, or the label would not make sense when read out, you should use the aria-label option to provide an alternative label for screen readers.
  • Substituting form elements may cause page reflows, which are ugly and bad for performance. If possible try setting explicit width/height with css to prevent page reflows, if applicable. This is especially important if the calculator element is near the beginning of the page.

Template arguments

For all types

id
The id for this field, English characters only, used in formulas of other fields. It must be unique on the page. Can be omitted if the field is not used as a value in any formulas.
default
The starting value
formula
The formula to calculate this field. See above for what is supported
placeholder
Placeholder text that shows up light grey when there is no input
readonly
Make field read only
size
how big to make the input box (In terms of number of letters that can fit in the box)
style
Custom CSS to use for the element.
class
Extra class to add to the element
class-live
CSS class to add only if the gadget is active on the page. Added after widgets are processed.
aria-live
Controls how screen readers read out this field if it changes when not being focused. Default is "polite" or "off" depending on field type. Can set to "off" if you don't want a screen reader to read the field when it changes.
type
Type of field. Currently supported are number, text, plain, radio, checkbox, range, select hidden, passthru.
checkbox 1 Wet
0 Big
hidden Not visible, does not take space. Useful for intermediate results in formulas.
number 80
passthru Is not visibly changed but the css class changes based on the formula This does nothing by itself but can be combined with templatestyles, see {{calculator-hideifzero}} for an example.
plain 2
radio 1 Metric
0 Imperial

See also: Calculator_label.

text 160
range 160 160
select
Checkbox, hidden, passthru and radio can be useful in combination with TemplateStyles to hide and show fields, see Template:Body_roundness_index, Template:Body roundness index/styles.css and template:Calculator-hideifzero for examples. See also the #Codex section above for how these field types can look different in Codex mode.

For number and range type only

max
Max number allowed (number type only)
min
Min number allowed (number type only)
step
How big the interval is for type=number and type=range inputs. Can be a number or the value "any"

For radio type only

name
When using type=radio, the name of the radio group. Only one radio field in a group with the same name may be checked at once. In formulas, you can use this with the radiogroup() function.

For radio, checkbox

value
What is the value of this control. When checked by a human (but not when checked by a formula), the field will have this value
checked
Mark this field as checked by default. Overrides default parameter.

For select

mapping
What items to have in the select field. JSON object mapping field names as strings to numbers. Can be up to two layers deep. e.g. { "item1": 1, "item3": 3, "invalid": "NaN", "Group of options": { "suboptiona": 1.1 } }
value
Which item to have selected initially. Same as default except not outputted for non-javascript users.

For plain and text type

decimals
Format field to this many decimal 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)
NaN-text
Use this text instead of NaN when result is not a number (Only works type=plain and type=text)
precision
Format field to this many significant digits. (Only works type=plain and type=text)
mapping
Convert input and output between strings and numbers. Specify conversion as a JSON object. e.g. { "item1": 1, "item3": 3, "invalid": "NaN", "fallback string": "default" }

Add a calculator widget to the page. Like a spreadsheet you can refer to other widgets in the same page.

Template parameters[Edit template data]

ParameterDescriptionTypeStatus
idid

The id for this input. This is used to reference it in formula of other calculator templates

Stringrequired
typetype

What type of input box

Suggested values
plain number text radio checkbox passthru hidden range select
Stringrequired
formulaformula

Formula to calculate this field

Example
3*log(a)
Stringsuggested
classclass

CSS classes to add

Stringoptional
class-liveclass-live

CSS class to add only if gadget is active on the page

Stringoptional
decimalsdecimals

Format to a fixed number of decimal digits [Only applies to type=number or type=plain]

Example
2
Numberoptional
defaultdefault

Default value for this field

Stringsuggested
exponential-precisionexponential-precision

Format to this many significant digits, using scientific notation [Only applies to type=number or type=plain]

Example
2
Numberoptional
maxmax

max number allowed (type=number inputs only)

Numberoptional
minmin

min number allowed (type=number inputs only)

Numberoptional
namename

For type=radio what group to assign the radio button to

Unknownoptional
NaN-textNaN-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

Example
Invalid calculation
Stringoptional
placeholderplaceholder

Text to put as a placeholder in empty input

Stringoptional
precisionprecision

Format to this many significant digits, using decimal notation except for really large numbers [Only applies to type=number or type=plain]

Example
2
Numberoptional
readonlyreadonly

Make input box readonly to user input

Booleanoptional
sizesize

Size of input box (How many characters it will fit)

Numberoptional
stepstep

How much to increment a type=number input box

Example
2.5
Numberoptional
stylestyle

CSS to style the input element with

Stringoptional
aria-describedbyaria-describedby

id of an element that is describing this widget (but is not its label). Used by accessibility software.

Stringoptional
aria-labelledbyaria-labelledby

id of attribute that is the label for this element. Normally you should use the {{calculator label}} template instead.

Stringoptional
aria-labelaria-label

label for this calculator widget for accessibility software. Normally you should use {{calculator label}} instead.

Stringoptional
enterkeyhintenterkeyhint

What should enter key be labelled as on the virtual keyboard on mobile phones

Suggested values
enter go done next
Stringoptional
inputmodeinputmode

What type of virtual keyboard to use on mobile phones. Recommended values include text (normal keyboard) decimal (positive number) numeric (number). Other supported values include none (Do not show a keyboard), tel, search, email and url

Suggested values
text numeric decimal
Stringoptional
mappingmapping

A JSON object mapping strings to numbers to alter the display. Only works with type of plain, select or text. The values must be of type number, except for the strings "Infinity" "-Infinity", "default", and "NaN". For select type, can be two layers deep.

Example
{ "one": 1, "two": 2, "Other": "default" }
Stringoptional
rolerole

Aria role. This helps a screen reader understand how to understand the content. For example, role=alert means that it is an urgent alert that should be read out right away. role=marquee means something that changes often and should not be read out by the screen reader. role=log means something where there is new content that gets added to the end which should be told to the user. role=status means it is a status update that should be read out when it changes. Will only be applied if gadget is enabled. If using a role that has an implicit aria-live value (alert, marquee, log, status) you should set aria-live=inherit to prevent the default aria-live from overriding.

Stringoptional
aria-atomicaria-atomic

If content changes, screen readers should read out the entire thing, not just the part that changed

Suggested values
true false
Unknownoptional
aria-relevantaria-relevant

What type of content changes should be read out by screen readers

Unknownoptional
aria-livearia-live

Value for aria-live. This controls if the screen reader should read out changes even when the user is focused elsewhere. Note the default for most calculator widgets is "polite". Set to "inherit" to set no aria-live attribute.

Suggested values
polite inherit off assertive
Unknownoptional
valuevalue

For field types of radio, checkbox and select. Allow setting the default value for a form, including in cases where the field isn't checked by default. Unlike default this won't be shown as a fallback for users without javascript. Note: for radiobuttons and checkboxes the value of the form control will be the result of the formula if set by a formula, but this value if checked by a human.

Stringoptional
checkedchecked

Should the radio button or checkbox start off in checked state. Overrides default. Unlike default this won't affect fallback text for non-js users.

Stringoptional

See also