InputManager

Markup: {{inputmanager}}

Quick start

The example below, running in the Mappia calculator - click it to run it live. Full-size picture

  1. Run it

    Click the picture: the map opens right here and runs the example. Nothing is saved, and nothing to install.

  2. Try it
    • Click Woodland (above 50 t/ha): after the countdown, only the woodland is green and the legend reads Woodland.
    • Click Open savanna (below 10 t/ha) to go back to the open savanna.
  3. Make it yours

    Copy the query, change it - the key parameters are below - and run it again in the playground, or paste it into the Mappia editor to save it as your map.

Key parameters

ParameterExampleWhat it does
idpresetRequired. Names the store: inputs.id['preset'] on the page; inside expression, inputs[0].global (its position among the inputs).
setValuessetValues({ min: 50, max: 99999 })Stores the values and recalculates the layer. Pass true as second argument to store without recalculating.
setDefaultValuessetDefaultValues({ min: 0, max: 10 })Fills only keys that are still empty. Never overwrites, never recalculates: call it in onInputsReady.
getValuegetValue("title")Reads a stored value on the page. A stored 0, false or empty text comes back undefined: read .global.key instead.
forceRecalcforceRecalc()Recalculates the layer with the values already stored, for example after several silent setValues calls.

Every parameter, with its type and default, is in the reference at the end of this page.

Complete example

The query 35 lines · runs as is
// InputManager: a named bag of values that buttons and callbacks fill; setValues() recalculates
// the layer. On the page use getValue(); in expression() read the plain values from .global.
[
  {
    title: "Vegetation biomass presets",
    name: "CSR:bioma_cerrado_biomassa",
    source: "calculate",
    opacity: 0.85,
    visibility: true,
    paramsButtonConfig: [{ type: "query", pressed: true }],
    descriptionHtml:
      "{{inputmanager|id=preset}}" +
      "{{button|id=preset_open|text=Open savanna (below 10 t/ha)|handler=showOpen}}" +
      "{{button|id=preset_wood|text=Woodland (above 50 t/ha)|handler=showWoodland}}",
    functions: {
      showOpen: function () {
        this.getInputs().id["preset"].setValues({ min: 0, max: 10, title: "Open savanna" });
      },
      showWoodland: function () {
        this.getInputs().id["preset"].setValues({ min: 50, max: 99999, title: "Woodland" });
      },
    },
    onInputsReady: function (inputs) {
      inputs.id["preset"].setDefaultValues({ min: 0, max: 10, title: "Open savanna" });
    },
    beforeCalc: function (inputs) {
      var preset = inputs.id["preset"];
      this.setCalculateLegend([{ color: [39, 174, 96], value: 1, title: preset.getValue("title") }]);
    },
    expression: function (layersVals, inputs) {
      var range = inputs[0].global; // inputs[0]: the inputmanager - buttons are not inputs
      return layersVals[0] >= range.min && layersVals[0] <= range.max ? 1 : this.nullValue;
    },
  },
];

Customize it

Read it in each place

  • On the page (beforeCalc, afterCalc, onInputsReady, the functions): inputs.id["preset"].getValue("min") or inputs.id["preset"].global.min. In a handler that has no inputs, use this.getInputs().id["preset"].
  • Inside expression: inputs[0].global.min. The manager arrives as its plain global values, without methods, at its position among the input widgets. Buttons, checkboxes and labels take no position.

Two buckets: sent and page-only

By default setValues writes to global, which is sent to expression: keep it to numbers, text, arrays and plain objects. Pass true as the third argument to keep a value on the page only. That bucket may hold anything: an Ext component, a DOM element, a function, a timer, a chart you drew.

var store = this.getInputs().id["preset"];
store.setValues({ min: 50, max: 99999, title: "Woodland" }, true); // stored, no recalculation
store.setValues({ button: Ext.getCmp("preset_wood") }, true, true); // page only
store.forceRecalc();                                                  // one recalculation

getValue(key) looks in global first, then in the page-only bucket.

Fill it from anywhere

Any code on the page can write to it: a Button handler, as in the example; a Checkbox handler; a combobox onSelect; a map click callback. This is how widgets that are not inputs still drive a calculation.

Pitfalls

  • Inside expression, inputs.id and the methods do not exist. inputs[0].getValue("min") fails there; read inputs[0].global.min.
  • getValue treats a stored 0, false or "" as missing. Read .global.key when the value can be one of those.
  • Applying the query again rebuilds the widgets, so the store starts empty. Put starting values in setDefaultValues.
  • After setValues the layer waits about 2.5 seconds, showing a countdown button, before it recalculates. Set updateAutomatically: true on the layer to recalculate right away.

Real maps that use it

Random Value Input

Random Value Input

Random Value Input

BrasilPec - Beef cattle intensification scenarios

BrasilPec - Beef cattle intensification scenarios

Fip Cerrado project

Fip Cerrado project

Mitigation option project

Mitigation option project

Reference: the parameters used here

Generated from the platform source. Every entry, searchable, is in the API reference; the raw data is api.json. Open an entry for its description, parameters and example; # links to it.

inputmanager · values kept for your functions (input)

InputManager6 entries

Written in a layer's descriptionHtml as {{inputmanager|parameter=value|...}}

Tool to store local variables to be used in others functions callbacks.
PS: DOM elements cannot be used in 'expression' context, because them cannot be sent to WebWorkers (javascript language limitation).
Usage: '{{inputmanager}}'
View the complete InputManager API here.

forceRecalc

function()# Force a legend map recalculation.

Force a legend map recalculation.

getValue

function(key) : *# Get the stored value by his property name, if it does not exists returns null.

Get the stored value by his property name, if it does not exists returns null.

key String
Stored property name.

Returns Desired stored property when it exists or null otherwise.

id

String# Defines the id of the input; it is the key used to reach the manager in inputs.id[ID] (required, the tool renders nothing visible).

Defines the id of the input; it is the key used to reach the manager in inputs.id[ID] (required, the tool renders nothing visible).

|id=state|

setDefaultValues

function(obj, local)# Set default values to the stored elements, these values are used before any other value is defined and never update or replace another stored values.

Set default values to the stored elements, these values are used before any other value is defined and never update or replace another stored values.

PS: Auxiliary function to make easy wrinting the script (typically called in onInputsReady or at the start of beforeCalc). PS: This function never fire layer update.

obj Object
Default values properties.
local Boolean
True when the properties should be store locally (and not sent to expression WebWorkers callbacks).
inputs.id['state'].setDefaultValues({year: 2020, scenario: 'base'});

setValues

function(obj, cancelUpdate, local)# Stores object properties for later usage.

Stores object properties for later usage.

PS: If has name property collision the older is replaced. PS: Values go to one of two buckets of the manager: global (the default — serialized and sent to expression, so it must hold plain JSON-compatible data) or _local_ (with local=true — kept in the browser only, may hold DOM elements, Ext components, functions or circular objects). getValue(key) looks in global first, then in _local_.

obj Object
Object with the properties to be stored.
cancelUpdate Boolean
False if this change must cause layer recalculation, True otherwise.
local Boolean
True to store the property locally, False otherwise. The local properties aren't sent to 'expression' calbacks. (i.e. If a element is recursive or have DOM elements, it must local avoid stringify errors on 'expression' callbacks)
inputs.id['state'].setValues({year: 2020});                      // recalculates the layer
inputs.id['state'].setValues({lastInterval: cur}, true, true);  // silent, browser-only

value

Object# Value stored in inputs.id[ID]: the manager object itself, with getValue(key), setValues(obj, cancelUpdate, local), setDefaultValues(obj, local) and forceRecalc() (listed in this group) and …

Value stored in inputs.id[ID]: the manager object itself, with getValue(key), setValues(obj, cancelUpdate, local), setDefaultValues(obj, local) and forceRecalc() (listed in this group) and the global bucket where the stored properties live (inputs.id[ID].global.key is a shortcut for getValue). The layer recalculates on its own change event, which setValues (unless cancelled) and forceRecalc trigger. Only the global bucket reaches expression (WebWorker); values stored with local=true are kept in a bucket that is not serialized and can therefore hold DOM/Ext references.

{{inputmanager|id=state}}
beforeCalc: function(inputs) {
    var year = inputs.id['state'].getValue('year') || 2020;
}

Highcharts · charts

Highcharts1 entry
Highcharts is a library used to easly create interactive charts.
Usage: (Highcharts.chart(DOM_ID, {});)
Highcharts JS has a complete set of examples and a nice documentation that can be accessed here.

chart

function(renderTo, options) : Object# Highcharts is loaded by the calculator and editor pages, so a query can call Highcharts.chart(...) without loading anything: put a container in the layer's descriptionHtml and create the chart …

Written as Highcharts.chart

Highcharts is loaded by the calculator and editor pages, so a query can call Highcharts.chart(...) without loading anything: put a container in the layer's descriptionHtml and create the chart once the panel exists - in onInputsReady, in beforeCalc or in a widget handler - then update it as results arrive instead of recreating it. ExtjsUtils.HIGHCHART.getById(id) gives the chart back from the container's id, which is what makes the update possible from another callback.

The bundled build covers the standard chart types plus highcharts-more. Extra modules are loaded on demand with AsyncLoader.loadScriptOnce (see the Sankey entry).

renderTo String
Id of the container element declared in descriptionHtml.
options Object
The Highcharts configuration object.

Returns The chart instance.

descriptionHtml: '<div id="emissions_chart" style="height:220px"></div>',
functions: {
    drawChart: function (values) {
        var chart = ExtjsUtils.HIGHCHART.getById('emissions_chart');
        if (chart) { chart.series[0].setData(values); return; }
        Highcharts.chart('emissions_chart', {
            chart: { type: 'column' },
            title: { text: 'Emissions by year' },
            xAxis: { categories: ['2020', '2021', '2022'] },
            series: [{ name: 'Mt', data: values }]
        });
    }
}

QUERY · setup calls and the running query

QUERY1 entry
ExtjsUtils.QUERY: calls before the list (setQueryGlobalProperties, addRemoteWMSServer, decorate, setMappiaIoCallback) and changes to the running query from your functions (addLayer, removeLayer, postMessage).
View the complete Query API here.

runOnceLayerVisible

function(layer, callback)helper# Runs callback once the given layer becomes visible.

Written as ExtjsUtils.QUERY.runOnceLayerVisible

Runs callback once the given layer becomes visible. If the layer is already visible the callback runs immediately; otherwise it waits for the layer's first visibilitychanged event and then unregisters itself. The callback is invoked with the layer as this. Typically used inside a layer's onLoad/runNow code to defer work (charts, legends) until the user actually turns the layer on.

layer OpenLayers.Layer
Layer whose visibility is awaited.
callback function
Function called once with the layer as this.
ExtjsUtils.QUERY.runOnceLayerVisible(ExtjsUtils.LAYER.getLayerByName("CSR:estados"), function() {
  console.log("Layer is now visible:", this.name);
});

Layer callbacks: functions you write

LayersFunctions2 entries
Functions you write in a layer and the platform calls: expression, afterCalc and legendColor on calculated layers; beforeCalc, onInputsReady, onVisibilityChange and the functions map on calculated and file layers. Inside them this is the layer - except in expression, see Kinds of layer.

beforeCalc

function= nullcallback# This function is executed before any calculation is made in the 'expression()' function.

This function is executed before any calculation is made in the 'expression()' function. It runs on calculated layers (source: 'calculate'), even when there is no 'expression()', and on file layers (source: 'file'), where it runs again whenever an input changes or a resource finishes loading (see VectorLayer.generateNewLegend).

inputs Array
The value of each input defined in the descriptionHtml. The order of the values is the same as the inputs (i.e. the first input in the descriptionHtml is inputs[0], the second is inputs[1] and so on).
[
  {
     title: 'Example of beforeCalc function',
     color: '#FFA500',
     elements: [
        {
           title: 'This beforeCalc function will show a message at the bottom right of the screen',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           paramsButtonConfig: [
              {
                 type: 'query',
                 pressed: true
              },
           ],
           descriptionHtml:
              '{{label|text=The beforeCalc function will be called after every user interaction before any calculation}}'
              +
              '{{textfield|fieldLabel=Enter your name|id=textInput|labelStyle=text-align:center;}}',
           beforeCalc: function(inputs) {
              let inputValue = inputs[0];
              ExtjsUtils.ALERTIFY.log('Hello ' + inputValue + '!');
           },
        },
     ],
  },
]

expression

function= nullcallback# This function is executed for every pixel in the map.

This function is executed for every pixel in the map. It can be used to process the information of all maps in the Layer to create a new one. This function is called regularly to update the map.

layerVals Array.<LayerValues>
Is an array that has the value associated with the current pixel for each map defined in the 'name' property. The values order is the same as the one in ‘name’. For example, if in the 'name' property we have 'name: CSR:geologia,CSR:altimetria' the layerVals[0] has the value for the 'CSR:geologia' map and the layerVals[1] has the value for the 'CSR:altimetria'.
inputs Array
The value of each input defined in the descriptionHtml. The order of the values is the same as the inputs (i.e. the first input in the descriptionHtml is inputs[0], the second is inputs[1] and so on).

Returns Value of each processed pixel.

[
  {
     title: 'Example of expression function',
     color: '#FFA500',
     elements: [
        {
           title: 'This Layer is the result of the calculation of two maps',
           name: 'CSR:geologia,CSR:altimetria',
           source: 'calculate',
           legendTitle: 'All geologys above 800m',
           visibility: true,
           expression: function(layerVals, inputs) {
              let geologyValue = layerVals[0];
              let altitudeValue = layerVals[1];

              // Hide all values lower than 800
              if (altitudeValue < 800) {
                 return undefined;
              }

              return geologyValue;
           },
        },
     ],
  },
]