User:H0lySquirr3l: Difference between revisions

From VORE Station Wiki
Jump to navigation Jump to search
m (WIP tag update)
No edit summary
Line 67: Line 67:


'''Footnotes:'''
'''Footnotes:'''
<!-- TOC depth:6 withLinks:1 updateOnSave:0 orderedList:0 -->
- [NanoUI](#nanoui)
- [Introduction](#introduction)
- [Components](#components)
- [`ui_interact()`](#ui_interact)
- [`Topic()`](#topic)
- [Template (doT)](#template-dot)
- [Helpers](#helpers)
- [Link](#link)
- [displayBar](#displayBar)
- [doT](#dot)
- [Styling](#styling)
- [Contributing](#contributing)
<!-- /TOC -->
# NanoUI
## Introduction
### Credit goes to Neersighted of /tg/station for the styling and large chunks of content of this README.
NanoUI is one of the three primary user interface libraries currently in use
on Polaris (browse(), /datum/browser, NanoUI). It is the most complex of the three,
but offers quite a few advantages, most notably in default features.
NanoUI adds a `ui_interact()` proc to all atoms, which, ideally, should be called
via `interact()`; However, the current standardized layout is `ui_interact()` being
directly called from anywhere in the atom, generally `attack_hand()` or `attack_self()`.
The `ui_interact()` proc should not contain anything but NanoUI data and code.
Here is a simple example from
[poolcontroller.dm @ ParadiseSS13/Paradise](https://github.com/ParadiseSS13/Paradise/blob/master/code/game/machinery/poolcontroller.dm).
```
    /obj/machinery/poolcontroller/attack_hand(mob/user)
        ui_interact(user)
    /obj/machinery/poolcontroller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
        var/data[0]
        data["currentTemp"] = temperature
        data["emagged"] = emagged
        data["TempColor"] = temperaturecolor
        ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open)
        if(!ui)
            ui = new(user, src, ui_key, "poolcontroller.tmpl", "Pool Controller Interface", 520, 410)
            ui.set_initial_data(data)
            ui.open()
```
## Components
### `ui_interact()`
The `ui_interact()` proc is used to open a NanoUI (or update it if already open).
As NanoUI will call this proc to update your UI, you should include the data list
within it. On /tg/station, this is handled via `get_ui_data()`, however, as it would
take quite a long time to convert every single one of the 100~ UI's to using such a method,
it is instead just directly created within `ui_interact()`.
The parameters for `try_update_ui` and `/datum/nanoui/New()` are documented in
the code [here](https://github.com/PolarisSS13/Polaris/tree/master/code/modules/nano).
For:
`/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, var/datum/nanoui/master_ui = null, var/datum/topic_state/state = default_state)`
Most of the parameters are fairly self explanatory.
- `nuser` is the person who gets to see the UI window
- `nsrc_obj` is the thing you want to call Topic() on
- `nui_key` should almost always be `main`
- `ntemplate_filename` is the filename with `.tmpl` extension in /nano/templates/
- `ntitle` is what you want to show at the top of the UI window
- `nwidth` is the width of the new window
- `nheight` is the height of the new window
- `nref` is used for onclose()
- `master_ui` is used for UIs that have multiple children, see code for examples
- And finally, `state`.
The most interesting parameter here is `state`, which allows the object to choose the
checks that allow the UI to be interacted with.
The default state (`default_state`) checks that the user is alive, conscious,
and within a few tiles. It allows universal access to silicons. Other states
exist, and may be more appropriate for different interfaces. For example,
`physical_state` requires the user to be nearby, even if they are a silicon.
`inventory_state` checks that the user has the object in their first-level
(not container) inventory, this is suitable for devices such as radios;
`admin_state` checks that the user is an admin (good for admin tools).
```
    /obj/item/the/thing/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, force_open = 0)
        var/data[0]
        ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open = force_open)
        if(!ui)
            ui = new(user, src, ui_key, "template_name_here.tmpl", title, width, height)
            ui.set_initial_data(data)
            ui.open()
```
### `Topic()`
`Topic()` handles input from the UI. Typically you will recieve some data from
a button press, or pop up a input dialog to take a numerical value from the
user. Sanity checking is useful here, as `Topic()` is trivial to spoof with
arbitrary data.
The `Topic()` interface is just the same as with more conventional,
stringbuilder-based UIs, and this needs little explanation.
```
    /obj/item/weapon/tank/Topic(href, href_list)
        if(..())
            return 1
        if(href_list["dist_p"])
            if(href_list["dist_p"] == "custom")
                var/custom = input(usr, "What rate do you set the regulator to? The dial reads from 0 to [TANK_MAX_RELEASE_PRESSURE].") as null|num
                if(isnum(custom))
                    href_list["dist_p"] = custom
                    .()
            else if(href_list["dist_p"] == "reset")
                distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
            else if(href_list["dist_p"] == "min")
                distribute_pressure = TANK_MIN_RELEASE_PRESSURE
            else if(href_list["dist_p"] == "max")
                distribute_pressure = TANK_MAX_RELEASE_PRESSURE
            else
                distribute_pressure = text2num(href_list["dist_p"])
            distribute_pressure = min(max(round(distribute_pressure), TANK_MIN_RELEASE_PRESSURE), TANK_MAX_RELEASE_PRESSURE)
        if(href_list["stat"])
            if(istype(loc,/mob/living/carbon))
                var/mob/living/carbon/location = loc
                if(location.internal == src)
                    location.internal = null
                    location.internals.icon_state = "internal0"
                    usr << "<span class='notice'>You close the tank release valve.</span>"
                    if(location.internals)
                        location.internals.icon_state = "internal0"
                else
                    if(location.wear_mask && (location.wear_mask.flags & MASKINTERNALS))
                        location.internal = src
                        usr << "<span class='notice'>You open \the [src] valve.</span>"
                        if(location.internals)
                            location.internals.icon_state = "internal1"
                    else
                        usr << "<span class='warning'>You need something to connect to \the [src]!</span>"
```
### Template (doT)
NanoUI templates are written in a customized version of
[doT](https://olado.github.io/doT/index.html),
a Javascript template engine. Data is accessed from the `data` object,
configuration (not used in pratice) from the `config` object, and template
helpers are accessed from the `helper` object.
It is worth explaining that Polaris's version of doT uses custom syntax
for the templates. The `?` operator is split into `if`, `else if parameter`, and `else`,
instead of `?`, `?? paramater`, `??`, and the `=` operator is replaced with `:`. Refer
to the chart below for a full comparison.
#### Helpers
##### Link
`{{:helpers.link(text, icon, {'parameter': true}, status, class, id)}}`
Used to create a link (button), which will pass its parameters to `Topic()`.
* Text: The text content of the link/button
* Icon: The icon shown to the left of the link (http://fontawesome.io/)
* Parameters: The values to be passed to `Topic()`'s `href_list`.
* Status: `null` for clickable, a class for selected/unclickable.
* Class: Styling to apply to the link.
* ID: Sets the element ID.
Status and Class have almost the same effect. However, changing a link's status
from `null` to something else makes it unclickable, while setting a custom Class
does not.
Ternary operators are often used to avoid writing many `if` statements.
For example, depending on if a value in `data` is true or false we can set a
button to clickable or selected:
`{{:helper.link('Close', 'lock', {'stat': 1}, data.valveOpen ? null : 'selected')}}`
Available classes/statuses are:
* null (normal)
* selected
* disabled
* yellowButton
* redButton
* linkDanger
##### displayBar
`{{:helpers.displayBar(value, min, max, class, text)}}`
Used to create a bar, to display a numerical value visually. Min and Max default
to 0 and 100, but you can change them to avoid doing your own percent calculations.
* Value: Defaults to a percentage but can be a straight number if Min/Max are set
* Min: The minimum value (left hand side) of the bar
* Max: The maximum value (right hand side) of the bar
* Class: The color of the bar (null/normal, good, average, bad)
* Text: The text label for the data contained in the bar (often just number form)
As with buttons, ternary operators are quite useful:
`{{:helper.bar(data.tankPressure, 0, 1013, (data.tankPressure > 200) ? 'good' : ((data.tankPressure > 100) ? 'average' : 'bad'))}}`
#### doT
doT is a simple template language, with control statements mixed in with
regular HTML and interpolation expressions.
However, Polaris uses a custom version with a different syntax. Refer
to the chart below for the differences.
Operator    |  doT      |    equiv        |
|-----------|------------|-------------------|
|Conditional| ?          | if                |
|          | ??        | else              |
|          | ?? (param) | else if(param)  |
|Interpolate| =          | :                |
|^ + Encode | !          | >                |
|Evaluation | #          | #                |
|Defines    | ## #      | ## #              |
|Iteration  | ~ (param)  | for (param)      |
Here is a simple example from tanks, checking if a variable is true:
```
    {{if data.maskConnected}}
        <span>The regulator is connected to a mask.</span>
    {{else if}}
        <span>The regulator is not connected to a mask.</span>
    {{/if}}
```
The doT tutorial is [here](https://olado.github.io/doT/tutorial.html).
__Print Tag__
- The print tag outputs the given expression as text to the UI.
`{{:data.variable}}`
`{{:functioncall()}}`
(with escape):
`{{>expression }}`
__If Tag__
- The if tag displays content conditionally based on the provided expression being true.
- When combined with the else tag the if tag can also show content if the provided expression is false.
- The else tag can optionally have an expression provided (e.g. "`{{else expression2}}`"), giving it "elseif" functionality.
`{{if expression}} <expression true content> {{/if}}`
`{{if expression}} <expression true content> {{else}} <expression false content> {{/if}}`
`{{if expression1}} <expression1 true content> {{else expression2}} <expression2 true content> {{/if}}`
__For Tag__
- Loop through entries in an array; it can be associative (with keys) or numerical indexed, but you have to use some special syntax for assocative lists.
- Each time the `for` tag iterates though the array it sets a variable (default "value") to the data of the current entry (another variable, default "index", contains the index). An example of this is using the print tag to print the contents (e.g. `{{:value.key1}}` and `{{:value.key2}}`).
- If combined with an `empty` tag the for tag can display content when the array is empty.
Indexed:
`{{for array}} <list entry content> {{/for}}`
`{{for array}} <list entry content> {{empty}} <empty list content> {{/for}}`
Associative:
`{{for object:key:index}} <key, value> {{/for}}`
__Inclusion Tag__
- Include the contents of another template which has been added to the ui.
`{{#def.atmosphericScan}}`
- You first must have added a template to the ui server side in your DM code:
`ui.add_template("atmosphericScan", "atmospheric_scan.tmpl")`
- Then you can reference it in the main template.  The tag will be replaced by the contents of the named template.  All tags in the named template are evaluated as normal.
#### Styling
/tg/station has standardized styling, with specific article tags, and headers, and sections.
However, as the templates are already horrifying unstandardized, Polaris does not have any
particular styling standards.
The only real requirement is that it, A. Looks alrightish, and B. Functions properly. Try
to avoid snowflaking anything into the main CSS file, please.

Revision as of 15:01, 16 May 2020

This section or article is being updated. Certain details are subject to change. You can help this by contributing.

WIP IC Station Events Page.

Listed below should be a collection of the chronicles of Virgo station. We would like to implore you to offer any information you can about the shift to shit action of the station. From a first hand accounts with evidence to a simple vague rumor would be more than appreciated.

Timeline of Adephagi station operations.

2550:

2557:

An Exodus-class space station is purchased from an orbital shipyard in Tau Ceti, and is shipped to the Virgo-Erigone system.

January: The NSS Adephagia begins operation as the first Virgo Orbital Research Establishment (VORE-1) with Kessmia Mills as its first Captain. It is minimally crewed with only some heads of staff, even excluding a Head of Security.

February: VORE-1's crew exceeds 20 people for the first time.

March: An engineer from VORE-1 is knocked into orbit during an asteroid storm. He survives his injuries and ends up aboard the derelict remains of the Virgo Research Outpost, where he finds evidence of a conspiracy to kill the station's inhabitants, and that the alleged meteor storm was nothing but a cover-up. NanoTrasen blames Lead Supervisor Townes for the deaths and subsequent cover-up. SolGov issues a warrant for Townes's arrest. Townes disappears into hiding.

April: During a company celebration of VORE-1's success, James Townes returns from hiding alongside sympathizers from the Syndicate, and hijacks the NDV Brutus. In response, Captain Harmony Prechtl leads Operation Magnum, which results in the death of former Colonel Townes.

May: VORE-1 is intentionally destroyed in a code Delta nuclear detonation by Captain Jeremiah Acacius during an emergency caused by a xenobio slime infestation that got out of control and attained a hivemind-like sentience. VORE-2 is purchased and shipped in two weeks later, and replaces VORE-1. It is also an Exodus-class station, but with some modernization upgrades.

October: A crew from VG-Box outpost in the Tau Ceti system are somehow flown thousands of light years off course to the VORE-2 by mistake. The Red October Riot occurs, resulting in the complete loss of the VG-Box crew. The reason for the erroneous redirect to NSS Adephagia remains a mystery to this day. A memorial plaque is put up outside the VORE-1 bar in the aftermath of the incident.

December: Tal is annexed under SolGov's control, granting Sol Central passports to Sergals, and later Nevareans. These two races begin leaving Vilous to work for various corporations and businesses, including NanoTrasen.

2558:

The Redspace Crisis takes place. Between May and October, anomalous space-time rifts begin to appear in the Virgo-Erigone system, unleashing deadly creatures that terrorize the station's crew. A researcher aboard VORE-2 named Kisuke Gema spearheads research of the anomalies, and discovers a new field of inter-dimensional physics which becomes known as Redspace.

October: The Redspace Crisis ends with the destruction of a cultist citadel ship designed to open a massive gateway to the hellish creatures that had been invading the system. Captain Jeremiah Acacius is awarded the Medal of Exceptional Heroism by NanoTrasen for his role in the assault on the Citadel ship. Redspace anomalies in the sector decline sharply. Kisuke Gema is awarded with an honorary doctorate by the NanoTrasen Institute of Technology. He becomes the youngest member of the corporation with a doctorate.A lone image of the assault captured from the ships security system.

A lone image of the assault captured from the ships security system.
A lone image of the final assault during the Redspace Crisis, captured from the ships security system.

November: Chase Monroe re-emerges from a portal through time, appearing on the station.

2559:

Feb: The Space Nazi Incident begins. The USDF Jörmungandr is hijacked by an extremist organization called The Fourth Reich, which is commanded by Adolf Hitler look-alike who claims to have escaped 20th century Germany on Earth via time travel.

May: Chase Monroe and several V.O.R.E. crew members board a Nazi vessel threatening the Tajaran homeworld of Meralar with a planet-destroying Singularity Bomb. Chase Monroe activates the bomb prematurely aboard the ship in order to destroy it, and is killed in the implosion. Chase Monroe refused to have himself clone-scanned at any point prior to the incident, so his death was permanent. He is posthumously awarded the Medal of Extraordinary Heroism. NanoTrasen has created a documentary holofilm surrounding the exploits of Chase Monroe and the crew of the Adephagi. footage showcases the mission to investigate Syndicate-Nazi relations, the death of Sgt Chase Monroe, the Nazi retaliation and the 21 gun salute at Monroe's funeral. Sgt Monroe's Last Stand

June: USDF Admiral Glenn Pink conscripts V.O.R.E. crew members to aid in the recapture of his flagship, the USDF Jörmungandr. Operation Wolf Hunt brings an end to the Space Nazi Incident, and 'Hitler' is killed. ONI agents confiscate the body of the Nazi leader shortly afterwards.

December: The VORE-2 is retired and demolished in favor of VORE-3, which is an asteroid colony based on the blueprints of the Northern Star in the Vir system. Technical issues plague its deployment. NanoTrasen brings in a pair of experts from Kitsuhana Heavy Industries to oversee the technical development of the new station, which results in these issues being resolved.

Footnotes:

Disciple of the Honk Mother Chuckles LeFuck, performed a miracle of the weird. Compressing themselves out of existence through traveling up their own Ass. His last words being "CATCH YOU ON THE FLIPSIDE!"

2560:

2560:

January: Kitsuhana Heavy Industries sells Resleeving technology to NanoTrasen, intended to replace traditional flash-cloning. Medical trials of the new technology begin on VORE-3.

The role of Captain is retired from use aboard NanoTrasen facilities in favor of the term Station Administrator, and later, Colony Director.

2561:

October: VORE-3 is decommissioned in favor of the tether on Virgo-3B, which is opened for operation, and is designated as the NSB Adephagia (VORE-4).

September: The Auream Imperium reveals its self to humanity, arriving in the Virgo-Erigone system under the command of Livius Thraun. However, conspiracies claim that ONI had known about the Imperium long before their public appearance.

The terrorist organization 'Humanity First' has claimed responsibility for the attempted assassination of SolGov and Imperial VIPs during a first contact summit. but despite the incident, negotiations went off without further issues.

2562:

A Tesla engine prototype is built onto NSB Adephagia. Several accidents occur, causing insurance rates for the station to rise dramatically.

2563:

October: A high priority package containing a previously unknown alien species made its way to Virgo. After a struggle and disposal of the creature, an unknown disease infected a number of crewmembers. This disease seemed to cause deep genetic changes in its hosts, It was later called the Blood Moon Disease!


Footnotes:



- [NanoUI](#nanoui) - [Introduction](#introduction) - [Components](#components) - [`ui_interact()`](#ui_interact) - [`Topic()`](#topic) - [Template (doT)](#template-dot) - [Helpers](#helpers) - [Link](#link) - [displayBar](#displayBar) - [doT](#dot) - [Styling](#styling) - [Contributing](#contributing)

  1. NanoUI
    1. Introduction
      1. Credit goes to Neersighted of /tg/station for the styling and large chunks of content of this README.

NanoUI is one of the three primary user interface libraries currently in use on Polaris (browse(), /datum/browser, NanoUI). It is the most complex of the three, but offers quite a few advantages, most notably in default features.

NanoUI adds a `ui_interact()` proc to all atoms, which, ideally, should be called via `interact()`; However, the current standardized layout is `ui_interact()` being directly called from anywhere in the atom, generally `attack_hand()` or `attack_self()`. The `ui_interact()` proc should not contain anything but NanoUI data and code.

Here is a simple example from [poolcontroller.dm @ ParadiseSS13/Paradise](https://github.com/ParadiseSS13/Paradise/blob/master/code/game/machinery/poolcontroller.dm).

```

   /obj/machinery/poolcontroller/attack_hand(mob/user)
       ui_interact(user)
   /obj/machinery/poolcontroller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
       var/data[0]
       data["currentTemp"] = temperature
       data["emagged"] = emagged
       data["TempColor"] = temperaturecolor
       ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open)
       if(!ui)
           ui = new(user, src, ui_key, "poolcontroller.tmpl", "Pool Controller Interface", 520, 410)
           ui.set_initial_data(data)
           ui.open()

```


    1. Components
      1. `ui_interact()`

The `ui_interact()` proc is used to open a NanoUI (or update it if already open). As NanoUI will call this proc to update your UI, you should include the data list within it. On /tg/station, this is handled via `get_ui_data()`, however, as it would take quite a long time to convert every single one of the 100~ UI's to using such a method, it is instead just directly created within `ui_interact()`.

The parameters for `try_update_ui` and `/datum/nanoui/New()` are documented in the code [here](https://github.com/PolarisSS13/Polaris/tree/master/code/modules/nano).

For: `/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, var/datum/nanoui/master_ui = null, var/datum/topic_state/state = default_state)` Most of the parameters are fairly self explanatory.

- `nuser` is the person who gets to see the UI window
- `nsrc_obj` is the thing you want to call Topic() on
- `nui_key` should almost always be `main`
- `ntemplate_filename` is the filename with `.tmpl` extension in /nano/templates/
- `ntitle` is what you want to show at the top of the UI window
- `nwidth` is the width of the new window
- `nheight` is the height of the new window
- `nref` is used for onclose()
- `master_ui` is used for UIs that have multiple children, see code for examples
- And finally, `state`.

The most interesting parameter here is `state`, which allows the object to choose the checks that allow the UI to be interacted with.

The default state (`default_state`) checks that the user is alive, conscious, and within a few tiles. It allows universal access to silicons. Other states exist, and may be more appropriate for different interfaces. For example, `physical_state` requires the user to be nearby, even if they are a silicon. `inventory_state` checks that the user has the object in their first-level (not container) inventory, this is suitable for devices such as radios; `admin_state` checks that the user is an admin (good for admin tools).

```

   /obj/item/the/thing/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, force_open = 0)
       var/data[0]
       ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open = force_open)
       if(!ui)
           ui = new(user, src, ui_key, "template_name_here.tmpl", title, width, height)
           ui.set_initial_data(data)
           ui.open()

```

      1. `Topic()`

`Topic()` handles input from the UI. Typically you will recieve some data from a button press, or pop up a input dialog to take a numerical value from the user. Sanity checking is useful here, as `Topic()` is trivial to spoof with arbitrary data.

The `Topic()` interface is just the same as with more conventional, stringbuilder-based UIs, and this needs little explanation.

```

   /obj/item/weapon/tank/Topic(href, href_list)
       if(..())
           return 1
       if(href_list["dist_p"])
           if(href_list["dist_p"] == "custom")
               var/custom = input(usr, "What rate do you set the regulator to? The dial reads from 0 to [TANK_MAX_RELEASE_PRESSURE].") as null|num
               if(isnum(custom))
                   href_list["dist_p"] = custom
                   .()
           else if(href_list["dist_p"] == "reset")
               distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
           else if(href_list["dist_p"] == "min")
               distribute_pressure = TANK_MIN_RELEASE_PRESSURE
           else if(href_list["dist_p"] == "max")
               distribute_pressure = TANK_MAX_RELEASE_PRESSURE
           else
               distribute_pressure = text2num(href_list["dist_p"])
           distribute_pressure = min(max(round(distribute_pressure), TANK_MIN_RELEASE_PRESSURE), TANK_MAX_RELEASE_PRESSURE)
       if(href_list["stat"])
           if(istype(loc,/mob/living/carbon))
               var/mob/living/carbon/location = loc
               if(location.internal == src)
                   location.internal = null
                   location.internals.icon_state = "internal0"
                   usr << "You close the tank release valve."
                   if(location.internals)
                       location.internals.icon_state = "internal0"
               else
                   if(location.wear_mask && (location.wear_mask.flags & MASKINTERNALS))
                       location.internal = src
                       usr << "You open \the [src] valve."
                       if(location.internals)
                           location.internals.icon_state = "internal1"
                   else
                       usr << "You need something to connect to \the [src]!"

```

      1. Template (doT)

NanoUI templates are written in a customized version of [doT](https://olado.github.io/doT/index.html), a Javascript template engine. Data is accessed from the `data` object, configuration (not used in pratice) from the `config` object, and template helpers are accessed from the `helper` object.

It is worth explaining that Polaris's version of doT uses custom syntax for the templates. The `?` operator is split into `if`, `else if parameter`, and `else`, instead of `?`, `?? paramater`, `??`, and the `=` operator is replaced with `:`. Refer to the chart below for a full comparison.

        1. Helpers
          1. Link

`{{:helpers.link(text, icon, {'parameter': true}, status, class, id)}}`

Used to create a link (button), which will pass its parameters to `Topic()`.

  • Text: The text content of the link/button
  • Icon: The icon shown to the left of the link (http://fontawesome.io/)
  • Parameters: The values to be passed to `Topic()`'s `href_list`.
  • Status: `null` for clickable, a class for selected/unclickable.
  • Class: Styling to apply to the link.
  • ID: Sets the element ID.

Status and Class have almost the same effect. However, changing a link's status from `null` to something else makes it unclickable, while setting a custom Class does not.

Ternary operators are often used to avoid writing many `if` statements. For example, depending on if a value in `data` is true or false we can set a button to clickable or selected:

`{{:helper.link('Close', 'lock', {'stat': 1}, data.valveOpen ? null : 'selected')}}`

Available classes/statuses are:

  • null (normal)
  • selected
  • disabled
  • yellowButton
  • redButton
  • linkDanger
          1. displayBar

`Helpers.displayBar(value, min, max, class, text)`

Used to create a bar, to display a numerical value visually. Min and Max default to 0 and 100, but you can change them to avoid doing your own percent calculations.

  • Value: Defaults to a percentage but can be a straight number if Min/Max are set
  • Min: The minimum value (left hand side) of the bar
  • Max: The maximum value (right hand side) of the bar
  • Class: The color of the bar (null/normal, good, average, bad)
  • Text: The text label for the data contained in the bar (often just number form)

As with buttons, ternary operators are quite useful:

`{{:helper.bar(data.tankPressure, 0, 1013, (data.tankPressure > 200) ? 'good' : ((data.tankPressure > 100) ? 'average' : 'bad'))}}`


        1. doT

doT is a simple template language, with control statements mixed in with regular HTML and interpolation expressions.

However, Polaris uses a custom version with a different syntax. Refer to the chart below for the differences.

Operator | doT | equiv | |-----------|------------|-------------------| |Conditional| ? | if | | | ?? | else | | | ?? (param) | else if(param) | |Interpolate| = | : | |^ + Encode | ! | > | |Evaluation | # | # | |Defines | ## # | ## # | |Iteration | ~ (param) | for (param) |

Here is a simple example from tanks, checking if a variable is true:

```

   Template:If data.maskConnected
       The regulator is connected to a mask.
   Template:Else if
       The regulator is not connected to a mask.
   User:H0lySquirr3l/if

```

The doT tutorial is [here](https://olado.github.io/doT/tutorial.html).

__Print Tag__ - The print tag outputs the given expression as text to the UI.

`Data.variable` `Functioncall()`

(with escape):

`{{>expression }}`


__If Tag__ - The if tag displays content conditionally based on the provided expression being true. - When combined with the else tag the if tag can also show content if the provided expression is false. - The else tag can optionally have an expression provided (e.g. "`Template:Else expression2`"), giving it "elseif" functionality.

`Template:If expression <expression true content> User:H0lySquirr3l/if` `Template:If expression <expression true content> Template:Else <expression false content> User:H0lySquirr3l/if` `Template:If expression1 <expression1 true content> Template:Else expression2 <expression2 true content> User:H0lySquirr3l/if`

__For Tag__ - Loop through entries in an array; it can be associative (with keys) or numerical indexed, but you have to use some special syntax for assocative lists. - Each time the `for` tag iterates though the array it sets a variable (default "value") to the data of the current entry (another variable, default "index", contains the index). An example of this is using the print tag to print the contents (e.g. `Value.key1` and `Value.key2`). - If combined with an `empty` tag the for tag can display content when the array is empty.

Indexed: `Template:For array <list entry content> User:H0lySquirr3l/for` `Template:For array <list entry content> Template:Empty <empty list content> User:H0lySquirr3l/for`

Associative: `Template:For object:key:index <key, value> User:H0lySquirr3l/for`


__Inclusion Tag__ - Include the contents of another template which has been added to the ui. `{{#def.atmosphericScan}}`

- You first must have added a template to the ui server side in your DM code: `ui.add_template("atmosphericScan", "atmospheric_scan.tmpl")`

- Then you can reference it in the main template. The tag will be replaced by the contents of the named template. All tags in the named template are evaluated as normal.

        1. Styling

/tg/station has standardized styling, with specific article tags, and headers, and sections. However, as the templates are already horrifying unstandardized, Polaris does not have any particular styling standards.

The only real requirement is that it, A. Looks alrightish, and B. Functions properly. Try to avoid snowflaking anything into the main CSS file, please.