# Mappia reference > The whole reference, concatenated. Individual pages: https://mappia.earth/llms.txt # Section: Writing a query ## Where to find it: layers, settings and links > Everything you change in a Mappia map is written in a layer, before the list of layers, or in the map's link. Find the place first: it tells you which part of the API reference to open. Everything you change in a Mappia map is written in one of three places: **in a layer**, **before the list of layers**, or **in the map's link**. Find the place first. It tells you where to look in the [API reference](/api/). This page is the map of that reference, written for someone who has done the [tutorial](/tutorial/). ## 1. Three places ```javascript ExtjsUtils.CONFIGURATION.setOptions({ backgroundSelector: true }) && // 2. before the list: the whole map [ { // 1. in a layer: this layer only name: "CSR:altimetria", title: "Elevation", styles: "altimetria_1", opacity: 0.6, visibility: true, }, ]; ``` ```text https://maps.csr.ufmg.br/calculator/?queryid=123&tools=measure&options=scale 3. in the link: this link only ``` 1. **In a layer** `{ }` - layer properties. They change that layer only. 2. **Before the list, joined with `&&`** - query settings. They change the whole map, for as long as this query is applied. 3. **In the map's link** - link parameters. They change how this one link opens the map. ## 2. In a layer: layer properties A layer is one entry of the list, between `{ }`. Its properties are read once, when the layer is created. To change a layer later, call its methods (below). ### The kind of layer decides which keys work `source` sets the kind of a layer. Some keys work on several kinds: `name`, `title`, `visibility`, `opacity`. Others belong to one kind: | Kind | `source` | Typical keys | API groups | |---|---|---|---| | Published map | none (the same as `"local"`), or a server's key | `styles`, `extents`, `startLegendOpen` | [Layer properties](/api/#category_LayersProperties), [Published maps: styles from QGIS](/api/#category_QGIS) | | Calculated layer | `"calculate"` | `expression`, `beforeCalc`, `operation`, `categorical` | [Layer callbacks: functions you write](/api/#category_LayersFunctions), [Calculated layers: methods (this.)](/api/#category_LayerInternal), [Calculated layers: raw maps and operation tokens](/api/#category_RawMaps) | | File layer | `"file"` | `type`, `json`, `url`, `loadData`, `fromProj`, `defaultStyle`, `onClick` | [File layers: data](/api/#category_FileLayer), [File layers: style, events, drawing](/api/#category_VectorLayer) | | Tile layer | `"xyz"` | `url` with `${z}`, `${x}`, `${y}` | [Tile layers (xyz)](/api/#category_XYZLayer) | [More layer properties](/api/#category_ConfigLayer) holds the rest: scale limits, `toggleGroup`, the layout of the layer's row. When a key seems to do nothing, check that your kind of layer reads it - see [Pitfalls](/reference/pitfalls/). ### The panel and the row buttons **Calculated, file and tile layers** have a panel, which shows the text and widgets of `descriptionHtml`, and buttons on their row, set with `paramsButtonConfig`. A **published map** has neither: its row shows its legend, its styles and an opacity slider, and those two keys are ignored. ```javascript { title: "Land above an elevation", name: "CSR:altimetria", source: "calculate", paramsButtonConfig: [{ type: "query", pressed: true }], // the panel starts open descriptionHtml: "{{slider|id=minimum|minValue=0|maxValue=2000|value=1000}}", } ``` Look in [Row buttons (paramsButtonConfig)](/api/#category_paramsButtonConfigProperties) for the buttons. Widgets are in the **Panel widgets** section: start with [Markup rules for every widget](/api/#category_MarkupSyntax), then the group of your tag, such as [slider](/api/#category_Slider). The [widget markup language](/reference/markup-widgets/) explains them. ### Two kinds of functions - **Functions you write.** The platform calls them: `expression` for each pixel, `beforeCalc` before each calculation, and your own functions in `functions`, called by buttons. Look in [Layer callbacks: functions you write](/api/#category_LayersFunctions). - **Functions the layer already has.** You call them with `this.` inside your functions: `this.setCalculateLegend(...)`, `this.getInputs()`. Look in [Calculated layers: methods (this.)](/api/#category_LayerInternal). A file layer keeps both kinds - `onClick`, `onHover` and its methods - in [File layers: style, events, drawing](/api/#category_VectorLayer). ```javascript beforeCalc: function (inputs) { // you write it; the platform calls it this.setCalculateLegend([ // the layer has it; you call it { color: [192, 57, 43], value: 1, title: "Above " + inputs.id["minimum"] + " m" }, ]); }, expression: function (layersVals, inputs) { // you write it; it runs for each pixel return layersVals[0] >= inputs[0] ? 1 : this.nullValue; }, ``` Inside these functions, `this` is the layer. `expression` is the exception: it runs in a separate worker, and there `this` is the calculation ([Calculated layers: this inside expression](/api/#category_ValuesCalculation)). Write `function`s, not arrow functions: an arrow function has no `this` of its own. When each function runs is in the [execution model](/reference/execution-model/). The platform's helpers that your functions call, `ExtjsUtils.NAME.member(...)`, are in part 6. ## 3. In a group: group properties A group is an entry with `elements`. It organises layers: - `title`, on a group at the top level of the list, makes an entry of the top menu; - `viewTitle` makes a heading in the layer panel; - `defaultProperties` holds layer properties and passes them to the layers inside. Look in [Group properties](/api/#category_GroupProperties) and [Group callbacks (viewTitle groups)](/api/#category_GroupFunctions). How groups nest is in [the layer and group model](/reference/layer-and-group-model/). `group: "background"` looks like a group, but it is a layer property: it makes that layer a basemap. ## 4. Before the list: query settings Calls joined with `&&` before the list change the **whole map**. They last until another query is applied. Each call returns `true`, so the expression goes on to the list ([how a query is evaluated](/reference/query-language/)). | Call | What it sets | Look in | |---|---|---| | `ExtjsUtils.QUERY.addRemoteWMSServer({ ... })` | Another map server for your layers | [QUERY · setup calls and the running query](/api/#category_QUERY), [Server definition (addRemoteWMSServer)](/api/#category_SourceConfig) | | `ExtjsUtils.QUERY.setQueryGlobalProperties({ ... })` | Values and functions the whole query shares, and `runNow` | [QUERY · setup calls and the running query](/api/#category_QUERY) | | `ExtjsUtils.CONFIGURATION.setOptions({ ... })` | Map-wide behaviour: `keepOnLeave`, `defaultFromProj`, `backgroundSelector` | [CONFIGURATION · query-wide settings (setOptions)](/api/#category_CONFIGURATION) | | `ExtjsUtils.PROJECTION.setProjectionOptions([ ... ])` | Extra coordinate systems, and the choices offered when a reader uploads a file | [PROJECTION · CRS codes and upload choices](/api/#category_PROJECTION) | This is what "configuration" means in `ExtjsUtils.CONFIGURATION`: settings for the whole query, not for one layer. ## 5. In the link: link parameters The address that opens a saved map takes parameters, each `&name=value`. They belong to the page, not to the query: another link can open the same saved query with other buttons. | Parameter | Example | Look in | |---|---|---| | `queryid`, `lang`, `extent`, `visiblelayers` | `?queryid=123&lang=eng` | [Link parameters (?name=value)](/api/#category_URLProperties) | | `tools` | `&tools=measure,legend` | [Toolbar buttons (tools=)](/api/#category_URLTools) | | `options` | `&options=scale,capabilities` | [Page options (options=)](/api/#category_URLOptions) | The `tools` of a link are toolbar buttons. They are not the widgets of a layer's panel. Listing tools replaces the default set of optional buttons. A page that shows the map in an iframe and talks to it uses [MappiaIO · your page and the map](/api/#category_MappiaIO); see [embedding a map](/reference/embedding-and-messages/). ## 6. Where to look in the API | You are writing | Section | Groups | |---|---|---| | A key of a layer | Layers: what you write in a layer | [Layer properties](/api/#category_LayersProperties), [More layer properties](/api/#category_ConfigLayer) | | A function of a layer | Layers: what you write in a layer | [Layer callbacks: functions you write](/api/#category_LayersFunctions) | | A row button, in `paramsButtonConfig` | Layers: what you write in a layer | [Row buttons (paramsButtonConfig)](/api/#category_paramsButtonConfigProperties), [Row button callbacks](/api/#category_paramsButtonConfigFunctions) | | A key one kind of layer reads, or a `this.` method | Kinds of layer: what each source adds | [Calculated layers: methods (this.)](/api/#category_LayerInternal), [File layers: data](/api/#category_FileLayer), [Tile layers (xyz)](/api/#category_XYZLayer)... | | A key of a group | Groups: what you write in a group | [Group properties](/api/#category_GroupProperties) | | A widget, `{{slider}}`, in `descriptionHtml` | Panel widgets | [Markup rules for every widget](/api/#category_MarkupSyntax), then one group per tag | | A call before the list | Query setup: calls before the layer list | [QUERY](/api/#category_QUERY), [CONFIGURATION](/api/#category_CONFIGURATION), [PROJECTION](/api/#category_PROJECTION) | | `ExtjsUtils.NAME.member(...)` in a function | ExtjsUtils helpers (A-Z) | the group named like `NAME`: [ALERTIFY · messages and questions](/api/#category_Alertify), [LAYER · find layers, extents, legends, pixels](/api/#category_Layer), [JS · the map and the app](/api/#category_JS)... | | A parameter of the link | Map links and embedding | [Link parameters](/api/#category_URLProperties), [Toolbar buttons](/api/#category_URLTools), [Page options](/api/#category_URLOptions) | ## 7. The same setting in two places A few settings can be written in two places. These are the cases checked in the code. There is no general rule, so do not guess for other settings. | Setting | Written where | What happens | |---|---|---| | Metadata button | `hideMetadata` on a layer; `options=hidemetadata` in the link | Either one hides it. A layer cannot bring it back when the link hides it. On calculated, file and tile layers, the button exists only with a `paramsButtonConfig` entry of `type: "metadata"`. | | Download button | A `paramsButtonConfig` entry of `type: "download"` (published maps have the button already); `options=disabledownload` in the link | The link wins: it removes the button. | | Which layers start visible | `visibility` on each layer; `visiblelayers` or `options=onlyfirstvisible` in the link | The link wins when it is there: the layers start hidden, then `visiblelayers=2` shows the first two, `-1` the last one and `0` none. Without it, or with `visiblelayers=custom`, each layer's `visibility` applies. | | Mouse wheel when the map is inside an iframe | `setOptions({ keepOnLeave })` in the query; `options=keeponleave` in the link | The query wins. Only the editor page reads the link option (without it, the editor uses `false`). The calculator ignores it and uses `true`. | | A key in `defaultProperties` | A group's `defaultProperties`; the same key on the layer | The layer's own value wins. Between nested groups, the nearer group wins. | | The coordinate system of a file layer's data | `fromProj` on the layer; `crs` in the data; `setOptions({ defaultFromProj })` in the query; `defaultFromProj` in the link | See below. | The coordinate system of a file layer is chosen in this order: - **GeoJSON** (in `json`, or `type: "geojsonurl"`): the layer's `fromProj`, then the data's `crs`, then a guess from the first coordinate. Numbers within ±180 and ±90 mean longitude and latitude (EPSG:4326). Larger numbers, up to about 20 million, mean Web Mercator metres (EPSG:3857). Only when the guess fails does the query's `defaultFromProj` apply, then the link's, then EPSG:900913. - **CSV and lists of plain objects**: the layer's `fromProj`, then the query's `defaultFromProj`, then the link's, then EPSG:900913. So a GeoJSON in UTM metres with no `crs` is read as Web Mercator, even with `setOptions({ defaultFromProj: "EPSG:31983" })`. Give such a layer its own `fromProj`. ## 8. Older names you will meet Some API texts are older than the tutorial and use other names for the same things: | In older API texts | In the tutorial | |---|---| | Legend Window | the layer panel, on the left | | the group's sub menu, Group List | the top menu | | composed layer, Composed | a calculated layer (`source: "calculate"`) | | `source: 'local'` | a published map; the same as writing no `source` | | Query section, query panel, "Exibir Consulta" | a layer's panel (`descriptionHtml`), opened by its query button | | VectorLayer | a file layer (`source: "file"`) | | tool, inside `descriptionHtml` | a panel widget | ## 9. How to look something up 1. Decide where you would write it: in a layer, in a group, before the list, or in the link. 2. For a layer, note its kind (its `source`). The table in part 2 names its groups. 3. On the [API page](/api/), type the name, or part of it, in *Filter members*: `setOptions`, `fromproj`. Capitals do not matter. 4. To read a whole list at once, open the [property catalogue](/reference/property-catalogue/) (the keys of layers and groups, as tables) or the [widget catalogue](/reference/widget-catalogue/) (each widget and its parameters). 5. Many API examples put the layer inside a group (`title`, `color`, `elements`). The key works the same in a plain list, as in the tutorial. 6. If a key does nothing, check the kind of layer (part 2), then [Pitfalls](/reference/pitfalls/). ## How a query is evaluated > A query is plain JavaScript - one expression whose value is the list of layers to show. This page is the contract around it: how the platform evaluates it, where state lives, and which parts of it run in a worker instead of on the page. A **query** is the text that defines one Mappia map: which layers it shows, how they are grouped, which widgets the user gets, and what arithmetic runs over the pixels. A query is stored on the server under a numeric id (`?queryid=417`) or handed to a page at runtime by its parent document. **There is no Mappia language.** A query is plain JavaScript, evaluated by the browser. What the platform adds is an **API**: the objects, the layer and group properties, the widgets and the callbacks that this reference declares — the layer and group properties in [the property catalogue](/reference/property-catalogue/), the widgets in [the widget catalogue](/reference/widget-catalogue/), and all of it, generated from the platform source, in the [API reference](/api/). What this page describes is the *contract* around that JavaScript: it is evaluated as a single expression, part of it runs in a worker rather than on the page, and state does not survive a re-apply. Almost every surprise a query author meets comes from one of those three facts. ## 1. One expression, one value The platform does not run a query as a program. It evaluates it as a single expression, equivalent to: ```javascript true && ( your query text ) ``` and keeps **the value the expression produced**. That value must be an array of layer definitions. The smallest complete query is therefore one line: ```javascript [{ name: "CSR:estados" }]; ``` Two consequences follow, and they explain most "my query did nothing" reports: | If you write | What happens | |---|---| | A top-level statement (`var x = 1; [ … ]`) | A syntax error inside the expression. The map falls back to its default background and the array is never read. | | An expression whose value is not an array (a function declaration, an assignment, a `console.log`) | The query is discarded as "no layers", with the same visible result. | So state and setup cannot be introduced with statements. They are introduced with operators — which is what the next section is about. ## 2. The `&&` chain: setup before the value Several platform calls exist to be used as the left-hand side of `&&`. Each performs a side effect and returns `true`, so the expression continues and still ends with the layer array: ```javascript ExtjsUtils.CONFIGURATION.setOptions({ keepOnLeave: true }) && [ { name: "CSR:estados", visibility: true }, ]; ``` | Call | Side effect | Use it when | |---|---|---| | `ExtjsUtils.CONFIGURATION.setOptions({…})` | Query-level behaviour: mouse-wheel policy when embedded, the default projection for vector data, the background picker | The map needs behaviour that is not a layer property | | `ExtjsUtils.QUERY.setQueryGlobalProperties({…})` | Copies each key onto `window` for the lifetime of this query | You need named functions or shared state (see §3) | | `ExtjsUtils.QUERY.setMappiaIoCallback(fn)` | Registers the handler for messages sent by the parent document | The map is embedded and the parent talks to it | | `ExtjsUtils.QUERY.decorate({…})` | Page chrome: `header`, `footer`, `run`; any other key is installed as a CSS rule | Branded or stripped-down pages | | `ExtjsUtils.QUERY.addRemoteWMSServer({…})` | Registers extra WMS endpoints before the layers that use them are read | Layers come from a server outside the default catalogue | | `ExtjsUtils.PROJECTION.setProjectionOptions({…})` | Adds coordinate systems to the upload dialog | Users upload data in an unusual CRS | Chain only what the map needs. A query that opens with five setup calls it does not use is harder to read and no more capable than `[{ name: "…" }]`. Two details worth knowing: - **Order matters where data depends on it.** `addRemoteWMSServer` must come before the array that references its layers, otherwise those layers are skipped with a "source not found by name" message in the console. - **Setup calls do not run during a syntax check.** When the editor only parses a query to validate it, side-effect calls are suppressed; only the layer array is produced. Code that must run exactly once after setup belongs in `runNow` (§3), not in a bare call. ## 3. Where state lives A query is re-evaluated whenever it is applied again — by the editor, by the parent document, by a user pressing *Apply*. Anything held in a top-level variable is lost, and top-level variables are not even syntactically available (§1). All shared state goes through one call: ```javascript ExtjsUtils.QUERY.setQueryGlobalProperties({ PALETTE: ["#ffffcc", "#c2e699", "#78c679", "#238443"], toTitle: function (name) { return name.replace(/_/g, " "); }, handleParentMessage: function (msg) { /* … */ }, }) && [ /* layers */ ]; ``` - Each key becomes a property of `window` until the next query replaces it. - A name that already exists on `window` and was not created by a query is **refused**, with "Global variable can't be redefined" in the console. Choose names that cannot collide with the platform's own globals. - Exactly one name has a meaning to the platform: **`runNow`**. If the query defines it, the platform calls it once, after the globals are registered. Everything else is a private name that only your own query code reads. - A `global: { … }` object on a group or on a layer is an equivalent, narrower way to declare globals while that node is being interpreted. ## 4. Names, and where a layer comes from A layer definition identifies its data by `name`: ```javascript [{ name: "CSR:estados", visibility: true }] ``` That name is looked up in the catalogue the platform already knows (its WMS capabilities). A name that is not in the catalogue produces no layer — and this is the single most common reason a query that "worked last year" shows an empty map: the published layer was renamed or withdrawn. Layers from elsewhere need their server registered first (`addRemoteWMSServer`), and layers that are not WMS at all (a GeoJSON file, an XYZ tile service, an uploaded CSV) declare a `source` or a `type` instead. The layer and group vocabulary is a chapter of its own: [the layer and group model](/reference/layer-and-group-model/). ## 5. Functions inside a query Layer definitions hold functions: what to do before a calculation, what to draw for a legend, what a button does. Three rules cover all of them. **5.1 `this` is the layer, so use a regular function.** The platform calls these callbacks with `this` bound to the layer (or, for tree callbacks, to the node). An arrow function keeps the `this` of the surrounding scope, where none of the layer's methods exist: ```javascript // correct beforeCalc: function (inputs) { this.changeLayers([{ index: 0, name: inputs.id["pick"] }]); } // broken: this.changeLayers is undefined beforeCalc: (inputs) => { this.changeLayers(/* … */); } ``` This applies to `beforeCalc`, `afterCalc`, `onVisibilityChange`, `onInputsReady`, the entries of a layer's `functions` map, widget `handler` / `toggleHandler`, vector callbacks such as `onClick` / `onHover` / `loadData`, and the group callbacks. **5.2 A handler named by a string is resolved in a fixed order.** Widgets take their callbacks as text (`{{button|handler=applyFilter}}`). The platform resolves that name: 1. the layer's own `functions` map — `functions: { applyFilter: function () { … } }`; 2. a global of that name (typically one declared with `setQueryGlobalProperties`); 3. failing both, the string itself is evaluated: a string starting with `function` becomes that function, and any other text is treated as the *body* of a function. Prefer (1). It keeps the callback next to the layer it belongs to, and it cannot collide with anything else on the page. **5.3 `expression` is not evaluated on the page.** A calculated layer's `expression` is serialized with `toString()` and rebuilt inside a WebWorker, where the page does not exist: no closures over your variables, no `window`, no DOM, no platform objects. ```javascript // broken: `factor` and `document` do not exist in the worker expression: function (layersVals) { return layersVals[0] * factor; } // broken: inputs.id is undefined in the worker expression: function (layersVals, inputs) { return layersVals[0] * inputs.id["factor"]; } // correct: the widget values arrive as a plain array, in the order the widgets appear expression: function (layersVals, inputs) { return layersVals[0] * inputs[0]; } ``` Inside `expression` you have: `layersVals` (the pixel values of the layers, in order), `inputs`, and `this`, which is the calculation object — so `this.isNumeric(v)`, `this.getValueFromLegend(...)` and `this.nullValue` are available. **`inputs` is a plain array inside `expression`.** On the page, `inputs` also carries a map by widget id — `inputs.id["factor"]` — but the inputs reach the worker as JSON, and JSON keeps only an array's elements, so that map is gone there. Read values by **position**: `inputs[0]` is the first input widget in `descriptionHtml`, `inputs[1]` the second, and so on (labels, buttons and checkboxes are not inputs and take no position). Name-based access, `inputs.id[ID]`, works in `beforeCalc`, `onInputsReady`, `afterCalc` and the `functions` map, which all run on the page. Anything else must be computed in `beforeCalc` and passed in. How that works, and when each callback runs, is the next chapter: [the execution model](/reference/execution-model/). ## 6. Widgets are text, not JavaScript Interface elements are written as markup inside a layer's `descriptionHtml`, in double braces, parameters separated by pipes: ```javascript descriptionHtml: "Year {{slider|id=year|minValue=2000|maxValue=2024|value=2020}}" ``` This is a second, smaller language with its own escaping and parameter conventions, and it has its own chapter: [the widget markup language](/reference/markup-widgets/). ## 7. Which JavaScript is available A query is evaluated by the browser's own `eval`, so the language available is whatever the visitor's browser supports — `let`, template literals, arrow functions (outside the `this`-bound callbacks of §5.1), destructuring. There is no transpilation step and no "write ES5" rule. The real constraints are the three above: one expression (§1), no page context inside `expression` (§5.3), and regular functions where `this` matters (§5.1). ## 8. A complete query, annotated ```javascript ExtjsUtils.QUERY.setQueryGlobalProperties({ // Shared helper, reachable from every callback below. labelFor: function (value) { return value + " m"; }, }) && ExtjsUtils.CONFIGURATION.setOptions({ backgroundSelector: true }) && [ // A background layer: same array, marked by its group. { name: "mapnik", source: "osm", group: "background", visibility: true }, // A named group with one calculated layer inside it. { viewTitle: "Elevation", color: "#8b0000", elements: [ { title: "Terrain above the threshold", name: "CSR:altimetria", source: "calculate", visibility: true, descriptionHtml: "Minimum {{slider|id=threshold|minValue=0|maxValue=2000|value=800}}", // Runs on the page: may read the map, the DOM, other layers. beforeCalc: function (inputs) { this.setCalculateLegend([ { color: [139, 0, 0], value: 1, title: window.labelFor(inputs.id["threshold"]) }, ]); }, // Runs in a worker: only layersVals, inputs and this. expression: function (layersVals, inputs) { return layersVals[0] >= inputs[0] ? 1 : this.nullValue; // inputs[0]: the slider }, }, ], }, ]; ``` ## 9. When a query does not work | Symptom | Almost always | |---|---| | Only the default background appears | The expression threw, or its value was not an array (§1) | | A layer silently missing | Its `name` is not in the catalogue, or its server was registered after the array (§4) | | `this.something is not a function` | An arrow function where the platform binds `this` (§5.1) | | A value is `undefined` only inside `expression` | It came from a closure, the DOM or a global; pass it through `inputs` (§5.3) | | Works once, breaks when re-applied | State kept outside `setQueryGlobalProperties` (§3) | | "Global variable can't be redefined" | A global name collides with an existing page global (§3) | The console is the primary instrument: the platform logs the reason it skipped a layer or refused a global. A longer list, including properties that look meaningful but are ignored, is in [pitfalls and properties that do nothing](/reference/pitfalls/). ## Execution model > What the platform does between reading a query and painting a tile — when each callback runs, what waits for what, and which code crosses into the calculation worker. A query is read once; the map it describes then keeps working for as long as the page is open. Knowing the order of what happens — and, above all, which code runs on the page and which runs in a worker — is what makes the difference between a query that behaves and one that intermittently shows nothing. ## 1. From text to layers ``` query text │ evaluated as one expression, value = array of definitions ▼ interpretation ── groups flattened into an ordered list of layers │ group defaults applied, group path remembered per layer ▼ one layer object per definition, by kind: ├─ catalogue map (WMS tiles, drawn as they arrive) ├─ calculated map (several maps + your expression, see §2) ├─ vector/file layer (GeoJSON, CSV, uploaded file) └─ tile service (XYZ / OSM basemap) │ ▼ layer panel, map, widgets declared in descriptionHtml ``` Interpretation is where a nested query becomes flat: a group (`viewTitle` with `elements`) contributes its own properties to each layer inside it and records the path that the layer panel shows. Within a group, entries keep the order you wrote them in, unless a `priority` reorders them (higher first). Nothing has been drawn yet at this point, and no calculation has run. ## 2. The cycle of a calculated map A calculated layer (`source: "calculate"`) names several maps at once and produces a new map from their pixels. Its cycle is the part of the platform most queries interact with: ``` widgets in descriptionHtml are created │ ▼ every input has a value ──────────► onInputsReady(inputs) │ ▼ beforeCalc(inputs) ← on the page: map, DOM, other layers │ ▼ tiles of each named map are fetched and decoded │ ▼ for every pixel: expression(layersVals, inputs) ← in a worker │ ▼ legend: legendColor(value) per distinct value, or the entries you set with setCalculateLegend │ ▼ afterCalc(...) ← on the page again │ ▼ painted ``` | Callback | Runs | Receives | Typical use | |---|---|---|---| | `onInputsReady` | Once every input of the layer has a value — including for layers that are not visible | `inputs` | Kick off work that needs the widgets, e.g. a first `generateNewLegend()` | | `beforeCalc` | Before each calculation round | `inputs` | Read widgets, swap the maps being read (`changeLayers`), set the legend, cancel the round | | `expression` | Once per pixel, in the worker | `layersVals`, `inputs`, `this` = the calculation object | The arithmetic itself | | `legendColor` | Once per distinct value produced | the value | Colour scale | | `afterCalc` | When the round finished - only for a layer with an `expression`: without one nothing is computed and `afterCalc` never runs | the results | Totals, notifying the parent page, enabling UI | `inputs` is the collected value of every widget declared in that layer's `descriptionHtml`, in declaration order, and can also be read on demand with `getInputs()`. ## 3. What crosses into the worker `expression` is the only part of a query that does not run on the page. It is turned into text with `toString()` and rebuilt inside a WebWorker, together with the pixel values and the plain widget values. | Crosses into the worker | Stays on the page | |---|---| | The source text of `expression` | Any variable it closed over — it becomes `undefined` | | `layersVals`: one value per named map, in `name` order | `window`, the DOM, the map, the platform objects | | `inputs`: the widget values as a **plain array**, in markup order | The name map `inputs.id` (JSON keeps only an array's elements), and widget values that are not plain data (a function, a table object, a manager's methods) | | `this`: the calculation object (`isNumeric`, `getValueFromLegend`, `nullValue`) | Your own helpers and globals | The practical rule: anything an expression needs that is not a pixel value must be computed in `beforeCalc` and handed over as an input — and read by position, `inputs[0]`, `inputs[1]`, never as `inputs.id[ID]`, which only exists on the page. A widget whose value is an object (a loaded CSV table, a picked point) is readable in `beforeCalc`, not inside `expression`; an `{{inputmanager}}` arrives as its plain `global` values (`inputs[0].global.key`). ## 4. What triggers a new round A calculated layer recalculates when: - a widget that is registered as an input reports its change event — a slider moved, a text field was typed in, a CSV finished downloading, a timeline stepped; - code calls `forceRecalc()` on an input manager, or `generateNewLegend()` on the layer; - the maps being read change (`changeLayers`, `setLayerOperation`, `setInsideLayerVisibility`); - the layer becomes visible again, or the map moves to tiles that have not been computed. Rounds are cancellable: `pauseAndStopCalculations()` stops the current one and suppresses new ones until `resumeCalculations()` is called once per pause. Queries that load an external resource before they can compute use this pair, so the user does not see a legend computed from half the data. ## 5. Waiting, and why a query must not assume Several things load independently: the layer catalogue, each layer's own resources, the widgets' files (a CSV, a JSON), the legend of a stored map. The platform keeps count of what is outstanding and holds the calculation until the count reaches zero, which is why `onInputsReady` exists and why `beforeCalc` may legitimately run later than you expect. Two consequences for a query author: - **Do not read another layer's data during interpretation.** At that moment the other layer may not exist yet. Read it in `onInputsReady`, in `beforeCalc`, or in a callback. - **A resource your own code fetches must be announced**, otherwise the platform may calculate without it. Widgets that download something (`{{loadcsv}}`, `{{loadjson}}`) do this for you; a hand-written `fetch` in a callback does not. ## 6. Tiles, zoom and decoded values Catalogue and calculated maps are tiled. Two behaviours surprise query authors: - **Beyond a layer's maximum zoom**, the platform keeps requesting the deepest tile it has and stretches it, instead of requesting a zoom the server does not publish. - **The values a calculated layer reads are decoded**, and how they are decoded is chosen per map with `operation`: the original cell value of the most central cell, the packed colour, an area-weighted sum or average, a maximum, a summed-area integral. The tokens are listed with the layer vocabulary in [the layer and group model](/reference/layer-and-group-model/); the decoding requires the map to be published with that operation available. When the same map appears more than once in `name` with different operations, each position in `layersVals` corresponds to one entry of the `name` list — the list is the contract between the query and the expression. ## 7. Re-applying a query Applying a query again — from the editor, or from a parent document — re-evaluates the text from scratch: globals are re-registered, layers are rebuilt, widgets are recreated. It does not preserve anything the previous evaluation left in a page variable. This is the reason shared state belongs in the query's globals, described in [the query language](/reference/query-language/). ## 8. Reading the console The platform narrates this pipeline. The messages worth recognising: | Message | Means | |---|---| | A layer is skipped with "source not found by name" | The layer's server was not registered before the array | | "Operation X is not defined for layer Y" | The map is not published with the decoding the query asked for | | "Global variable can't be redefined" | A query global collides with a page global | | A calculation that never finishes | Something is still counted as loading — usually a resource fetched without announcing it (§5) | # Section: Model ## The layer and group model > The vocabulary a query is written in — the kinds of layer, how groups nest them, how a calculated layer reads several maps at once, and where the full property list lives. Everything a query says is said about a **layer definition**: a plain object. Groups nest those objects and pass properties down to them. This page is the vocabulary: the kinds of layer that exist, what distinguishes them, and which property list applies to each. The exhaustive, generated list of properties lives in the [API reference](/api/) — this page is the map of it. ## 1. A layer definition ```javascript { name: "CSR:estados", // which map(s) — the only property with no default title: "States", // what the layer panel shows visibility: true, // starts visible opacity: 0.8, group: "background", // optional: a reserved slot, see §4 } ``` Two properties decide how everything else is read: | Property | Decides | |---|---| | `source` | Where the pixels come from: the catalogue, a calculation, a file, a tile service | | `name` | Which map, or — for a calculated layer — which maps, comma-separated, in order | ## 2. The kinds of layer | `source` | What it is | The properties that matter | Property group in the API reference | |---|---|---|---| | *(absent)* or `"local"` | One published map, drawn as WMS tiles | `styles`, `extents`, `minscale` / `maxscale`, `startLegendOpen`, `hideStyleChooser` | `LayersProperties`, `ConfigLayer` | | `"calculate"` | Several maps read together; your `expression` produces a new map from their pixels | `name` (list), `operation`, `expression`, `beforeCalc`, `legendColor`, `insideOpacity`, `categorical`, `maxZoom`, `otherNames` | `LayersProperties`, `ConfigLayer`, `LayersFunctions`, `LayerInternal` | | `"file"` | Vector features from a file, an inline object or your own loader — with `type` choosing which | `type`, `url`, `json`, `loadData`, `styleMap`, `onClick`, `onHover`, `cluster` | `FileLayer`, `VectorLayer` | | `"xyz"` | A tile service addressed by z/x/y | `url`, `name` | `XYZLayer` | | `"osm"`, `"google"`, `"arcgisrest"` | A ready-made basemap | `name` selects the variant (for example `mapnik`, `SATELLITE`) | `LayersProperties` | A layer registered through `addRemoteWMSServer` behaves as a catalogue layer; the registration says where its server is and whether it needs a proxy. Only calculated, file and tile (xyz) layers have a **panel** in the layer list: `descriptionHtml` (text and widgets), `paramsButtonConfig` (row buttons) and `exclusiveGroupDetails` are ignored on published maps, basemaps and servers added with `addRemoteWMSServer`, while `startLegendOpen` and `hideStyleChooser` work on published maps only. `maxZoom` set in the query is read only by calculated layers; a published map takes it from its catalogue entry. ### 2.1 `type`, for file layers `type` chooses how a `source: "file"` layer obtains its features (case-insensitive): | `type` | Source of the features | |---|---| | `load` | Your `loadData(inputs, config)` callback loads them; it must announce the load with the layer's `startLoadingLayer` / `endLoadingLayer` events | | `csv` | The CSV at `url`, one feature per line | | `json` | The inline `json` property: GeoJSON, or an array of plain objects | | `jsonurl` | JSON fetched from `url` (also the fallback for an unrecognised `type`) | | `geojsonurl` | GeoJSON fetched from `url` | | `empty` | No features; the query adds them later | A GeoJSON without a declared CRS is guessed from its first coordinate: EPSG:4326 when it looks like longitude/latitude, otherwise EPSG:3857. CSV and lists of plain objects use the query's `ExtjsUtils.CONFIGURATION.setOptions({ defaultFromProj })`, then the link's `defaultFromProj`, then the map projection. Declare `crs` in the GeoJSON, or `fromProj` on the layer, whenever the data is in anything else (UTM, for example) — a silent misalignment is the usual symptom. ### 2.2 `operation`, for calculated layers A calculated layer's `name` lists several maps; `operation` is a comma-separated list with **one token per map, in the same order**, saying how each map's pixels are turned into the numbers `expression` receives. An empty token leaves that map on the default. ```javascript { source: "calculate", name: "CSR:pop_density_estimate_2015,CSR:estados,CSR:pop_density_estimate_2015", operation: "average,,area", // map 1 averaged, map 2 default, map 3 as area } ``` | Token | The value `expression` receives | |---|---| | *(empty)* | The regular WMS image: the pixel's legend colour/category | | `raw` | The value of the most central original cell under the pixel | | `rgba` | The pixel's RGBA bytes packed into one integer | | `sum` / `average` | Area-weighted sum / mean of the cells under the pixel | | `max` / `min` | Largest / smallest cell at least partly under the pixel | | `integral` | Summed-area table: the sum over a rectangle from its four corners | | `areaintegral` | Summed-area table of the covered areas | | `area` | Original map area inside the pixel | | `cells` | Weighted count of original cells inside the pixel | Tokens are case- and whitespace-insensitive. Every token except the default and `rgba` requires the map to be **published with that operation available**; if it is not, the console reports `Operation X is not defined for layer Y` and the layer produces nothing. ## 3. Groups Groups come in two kinds, and nest. A top-level group with **`title`** and `elements` becomes an entry of the **top menu**, which lists all its layers for the reader to turn on (`GroupProperties.title`). A group with **`viewTitle`** and `elements` becomes a **heading in the layer panel**, above the layers of it that are on: ```javascript [ { viewTitle: "Boundaries", color: "#8b0000", openGroup: true, defaultProperties: { visibility: false, source: "local" }, elements: [ { title: "States", name: "CSR:estados", visibility: true }, { title: "Municipalities", name: "CSR:municipios" }, ], }, ] ``` | Property | Effect | |---|---| | `viewTitle` | The group's row in the layer panel; groups may nest by nesting `elements` | | `elements` | The layers, or further groups, inside it | | `defaultProperties` | Applied to every descendant that does not set the property itself | | `openGroup` | The `viewTitle` heading starts expanded (also available per layer, where it expands the layer's headings) | | `color` | The colour of the group's `viewTitle` heading; on a top-level group, also of its top-menu entry and of the rows of all its layers. A `color` written on a layer is replaced by its groups' colours | | `viewColor` | Accepted on a group, but it has no visible effect today | | `onClickViewGroup`, `onToggleViewGroup` | Called when the group row is clicked or toggled, with `this` = the node. These need a real group: attached to a layer that is not inside a `viewTitle`, they never fire | | `global` | Declares query globals while this group is interpreted | Interpretation flattens all of this into an ordered list of layers, each remembering its group path. Order inside a group is declaration order unless `priority` reorders it (higher first). ## 4. Reserved and special slots | Slot | Meaning | |---|---| | `group: "background"` | The layer is a basemap: it goes under everything and joins the background picker instead of the layer list | | `group: ""` | Ignored: only `"background"` is read. To let one of several layers be visible at a time, use `toggleGroup` | | `paramsButtonConfig` | Extra buttons on the layer's row — query, download, tooltip and toggle buttons; a bare object is treated as one entry of type `query`. Calculated, file and tile layers only | | `descriptionHtml` | The layer's panel content: free HTML plus the widget markup of [the widget markup language](/reference/markup-widgets/). Calculated, file and tile layers only | ## 5. Presentation properties, in one place These do not change what the layer computes, only how it appears. All are documented individually in the [API reference](/api/) under `LayersProperties` and `ConfigLayer`. Unless noted, they apply to every kind of layer: - **In the panel**: `title`, `startListed`, `hideListing`, `hideMetadata`, `hideLegendButton`, `showRemoveBtn`, `useLayerTooltip`, `customLayerClass`, `verticalMenu`; `startLegendOpen` and `hideStyleChooser` (published maps only); `description` (file and tile layers only); `thumbUrl` (published maps and tile layers only); `legendTitle` (calculated layers only). - **On the map**: `visibility`, `opacity`; `minscale`, `maxscale` and `hideTilePlaceholder` (published maps and calculated layers); `insideOpacity` and `maxZoom` (calculated layers only). The map's extent and attribution come from its catalogue entry, not from the query: limit the area with `extents`. - **In the legend of a calculated layer**: `categorical`, `categoricalPalette`, `maxQntEntries`, `showLoadingModal` (also on file layers). ## 6. How to find a property [Where to find it](/reference/where-to-look/) shows, for anything you want to change, where it is written (in a layer, in a group, before the layer list or in the map's link) and which part of the [API reference](/api/) lists it. If a property appears in an old query and does nothing, check [pitfalls and properties that do nothing](/reference/pitfalls/) before trusting it. ## Layer and group property catalogue > Every property a layer, a group or a layer-row button accepts, generated from the platform source: the declared API of a query's layer definitions. The complete property list of a layer definition, as the platform declares it. Which properties apply to which kind of layer is explained in the previous chapter; this is the exhaustive list, generated from the source. ## Layers: what you write in a layer ### LayersProperties — Layer properties Keys of a layer object: which map it shows (name, source, styles), how it looks (title, opacity, visibility) and how its row and panel behave. | Name | Type | Description | |---|---|---| | [`categorical`](/api/#LayersProperties.categorical) | `Boolean` | Switches the generated legend of a `source: 'calculate'` layer to categorical mode. When `true`, every distinct value returned by `expression()` becomes its own legend entry (values are grouped by value, never into ranges) and the colours come from… | | [`categoricalPalette`](/api/#LayersProperties.categoricalPalette) | `Array.>` | Colours of the legend entries of a categorical `source: 'calculate'` layer (see `categorical`), as an array of `[R, G, B]` triplets (0 to 255). The entries are assigned, in the sorted order of the values returned by `expression()`, spreading evenly over the… | | [`description`](/api/#LayersProperties.description) | `String` | Define the text that will be displayed when the mouse hover the Legend Window Title. This description applies when the 'source' of the map is 'xyz' or the Layer is a 'vector'. | | [`descriptionHtml`](/api/#LayersProperties.descriptionHtml) | `String` | Define the content that will be displayed at the Query section ("Exibir Consulta" button). This property accepts any string in HTML format. Besides that, you can also use predefined tools. Only calculated, file and tile (xyz) layers have this panel; on a… | | [`disabledAttributes`](/api/#LayersProperties.disabledAttributes) | `String` | Define which styles will be hidden in the Style Chooser Combobox from Layers that has the 'source' property as 'local'. You need to pass the name of a style as in the GetCapabilities() xml. They follow the pattern of the map name, underline (_) and then the… | | [`exclusiveGroupDetails`](/api/#LayersProperties.exclusiveGroupDetails) | `String` | Define a name for a Layer Details. Between all Layers with the same ‘exclusiveGroupDetails’ name, only one Layer can have its Legend open each time. | | [`extents`](/api/#LayersProperties.extents) | `Array.` | Define which tiles will be used to render the map. All the tiles that are within the 'extents' coordinates will be used to render the map. The extents must be in EPSG:4326 (coordinates in lat,long). Also, the array values need to be in the order: [minX, minY,… | | [`global`](/api/#LayersProperties.global) | `Object` | A second way to declare query globals from a layer: an object whose properties become temporary globals, passed to `ExtjsUtils.QUERY.setQueryGlobalProperties` while the layer is interpreted. The usual form is the… | | [`hideLegendButton`](/api/#LayersProperties.hideLegendButton) | `Boolean` | Hides the legend of the layer in its Legend Window. Set it to 'true' to hide it, 'false' to display it. It applies to every layer source: on a `local` layer it hides the "show legend" toggle button of the row; on a `calculate`, `file` or `xyz` layer it hides… | | [`hideListing`](/api/#LayersProperties.hideListing) | `Boolean` | Hides the layer from its group's menu at the top of the screen: the list that appears when the mouse is over the group title. Set it to `true` to leave the layer out of that menu; `false` (the default) lists it. | | [`hideMetadata`](/api/#LayersProperties.hideMetadata) | `Boolean` | If true, hides the metadata button in the Legend Window for this layer. The button is also hidden when the link has `options=hidemetadata`: either one hides it, and `hideMetadata: false` cannot bring it back. Calculated, file and tile (xyz) layers only have… | | [`hideStyleChooser`](/api/#LayersProperties.hideStyleChooser) | `Boolean` | Define if should hide the Combobox with the map possible styles that can be applied to a map in a Layer that has the 'source' 'local'. | | [`hideTilePlaceholder`](/api/#LayersProperties.hideTilePlaceholder) | `Boolean` | Removes the stretched placeholder tile that is shown while the real tiles load (the OpenLayers `resize` transition). Set it to `true` for layers whose content changes between loads, such as timeline or calculated maps, to avoid the previous image being… | | [`insideOpacity`](/api/#LayersProperties.insideOpacity) | `Array.` | Defines the opacity for the maps defined in the 'name' property. This property is an array of values which are the opacity that will be applied in the same order that the map was defined in the 'name' property. For example, the first value in the… | | [`legendTitle`](/api/#LayersProperties.legendTitle) | `String` | Defines the text that will be displayed at the top of the 'legendhtml tool' declared at the 'descriptionHtml' property | | [`maxQntEntries`](/api/#LayersProperties.maxQntEntries) | `Number` | Maximum number of legend entries generated from the values returned by `expression()` on a non-categorical `source: 'calculate'` layer; when there are more distinct values than this they are grouped into value ranges. The value is clamped to the length of the… | | [`name`](/api/#LayersProperties.name) | `String` | Defines the maps that will be a part of the Layer. Every map defined in here will be shown when the Layer is active. Besides that, all of their information can be used to calculate a new map combining their data. In this website you will find some of the maps… | | [`opacity`](/api/#LayersProperties.opacity) | `Numeric` | Define the opacity of the Layer. The opacity is a value between 0 and 1 that is a scale for its transparency. 0 is completely transparent. 1 is completely visible. | | [`otherNames`](/api/#LayersProperties.otherNames) | `String` | Defines additional maps to be available for the query, which will be listed in the filtered stored capabilities. Every map included in layer definition needs to be either in 'name' property or 'otherNames' property. PS: This property must be used along with… | | [`priority`](/api/#LayersProperties.priority) | `Number` | Defines the order of which map will be rendered on top of the others. Layers with higher 'priority' will always be rendered on top of the layers with lower 'priority'. | | [`showLoadingModal`](/api/#LayersProperties.showLoadingModal) | `Boolean` | Shows the "generating legend" loading mask visibly over the page while the layer is paused (calculating or loading a resource). By default the mask is an invisible overlay that only changes the cursor to "wait"; set it to `true` to make it visible. Only shown… | | [`showRemoveBtn`](/api/#LayersProperties.showRemoveBtn) | `Boolean` | Defines it the remove button at the top right of the Layer Legend Window show be displayed. Set it to 'true' to show it. Set it to 'false' to hide it. | | [`source`](/api/#LayersProperties.source) | `String` | Defines the source from where the maps declared at the name will be loaded from. The Source can be one of the following: - 'local': The maps in the name will be loaded from the CSR servers - 'calculate': The maps in the name gonna be used to calculate a new… | | [`startLegendOpen`](/api/#LayersProperties.startLegendOpen) | `Boolean` | Defines if the Legend Window should start or not. Set it to 'true' to make it start open. Set it to 'false' for it to start closed. Applies to published maps only (no `source`, `source: 'local'` or a server added with `addRemoteWMSServer`). Calculated, file… | | [`startListed`](/api/#LayersProperties.startListed) | `Boolean` | Define if the Layer should start with its Legend Window visible or not. This does not make the Layer visible on the map by itself. For that, you need to set the 'visibility' property to 'true'. 'startListed' just displays the Legend Window associated with the… | | [`styles`](/api/#LayersProperties.styles) | `String` | Defines which styles will be applied over the maps defined at the 'name' property. The styles are applied in the same order as the maps are declared in name. For example, if there are 3 maps in the 'name' property and 3 styles. The first style will be applied… | | [`thumbUrl`](/api/#LayersProperties.thumbUrl) | `String` | Define the thumbnail image that is displayed when the mouse hovers the Legend Window title. You can define any image you would like to display as the map thumbnail. You just need to pass its URL. | | [`title`](/api/#LayersProperties.title) | `String` | Defines the Title that will be displayed at the Legend Window in the top left corner of the screen and inside the Group List at the top center of the screen. | | [`updateAutomatically`](/api/#LayersProperties.updateAutomatically) | `Boolean` | Decides what happens when the reader changes an input of the layer's panel (a widget in `descriptionHtml`). `true`: the layer is calculated again at once. `false` (the default): a short countdown starts, with a button to refresh now, so several changes make… | | [`viewColor`](/api/#LayersProperties.viewColor) | `String` | HTML color to use on the group. | | [`visibility`](/api/#LayersProperties.visibility) | `Boolean` | Define if the Layer should start visible or not. Set it to 'true' for the Layer start visible. Otherwise, set it to 'false' and the Layer will start hidden. | Full descriptions, defaults and examples: [LayersProperties in the API reference](/api/#category_LayersProperties). ### ConfigLayer — More layer properties More keys of the same layer object: scale limits, grouping (group, toggleGroup, openGroup), the row's layout and, on calculated layers, how each map is read (operation). | Name | Type | Description | |---|---|---| | [`attribution`](/api/#ConfigLayer.attribution) | `String` | Recognizes someone as the platform author, showing in the "Powered by: {insert name}". | | [`customLayerClass`](/api/#ConfigLayer.customLayerClass) | `String` | Extra CSS class added to the row of the layer in the Legend Window and to its vertical options menu (see `verticalMenu`), so the layer can be styled with `ExtjsUtils.CSS.defineClass` or a stylesheet. The same key on a `viewTitle` group is added to the group… | | [`group`](/api/#ConfigLayer.group) | `String` | Only the value "background" does anything: it makes the layer a basemap, drawn under every other layer and listed in the background picker instead of the layer list. Any other value is ignored (it does not group layers: groups are `{ title, elements: [...] }`… | | [`maxExtent`](/api/#ConfigLayer.maxExtent) | `OpenLayers.Bounds` | Defines a geographical limit for a map rendering. | | [`maxZoom`](/api/#ConfigLayer.maxZoom) | `Numeric` | Defines the limit of the real max zoom of a given layer. When map zoom exceed this, the image is reused and stretched. | | [`maxscale`](/api/#ConfigLayer.maxscale) | `Numeric` | Defines the limit of the real max scale of a given layer. When the map scale value exceeds the defined one, the image is reused and stretched. | | [`metadataUrl`](/api/#ConfigLayer.metadataUrl) | `string\|null` | Defines the url to show custom layers metadata information. If empty, the default value is obtained from layer metadata from the WMS definition. PS: The linked domain must have CORS headers enabled. | | [`minscale`](/api/#ConfigLayer.minscale) | `Numeric` | Defines the limit of the real min scale of a given layer. When the map scale reaches a value lower than the defined one, the image is reused and compressed. | | [`openGroup`](/api/#ConfigLayer.openGroup) | `Boolean` | Defines if the group starts opened, even without any visible layers. Set it true to start open, false otherwise. PS: If one layer is visible, the group will start open. It works at both levels: on a `viewTitle` group it makes that group start expanded; on a… | | [`operation`](/api/#ConfigLayer.operation) | `String` | Defines how the pixels of each map of a `source: 'calculate'` layer are decoded into the values that `expression()` receives in `layersVals`. It is a comma-separated list with one token per map in `name`, in the same order; an empty token keeps that map on… | | [`shouldKeepRecord`](/api/#ConfigLayer.shouldKeepRecord) | `Boolean` | Defines what the 'X' (remove) button of the Legend Window does (see `showRemoveBtn`). When `true` the layer record is kept: the layer is only hidden and removed from the listing, so it can be listed again from the group menu at the top. When `false` the layer… | | [`toggleGroup`](/api/#ConfigLayer.toggleGroup) | `String` | Places a layer in a group of layers with mutually exclusive visibility. At most one layer of the same group will be visible, when one is shown, the others will be hidden. | | [`useLayerTooltip`](/api/#ConfigLayer.useLayerTooltip) | `Boolean\|Number` | If false, the layer tooltip is not shown. If a number, the layer tooltip is shown for the specified layer. (Only supported for layers with `source: "calculate"`) Otherwise follow tooltip default behavior that varies from map source | | [`verticalMenu`](/api/#ConfigLayer.verticalMenu) | `Boolean` | Uses the compact layout for the Legend Window of the layer: the secondary buttons (remove, metadata, download, zoom to extents) and a vertical opacity slider move into a small options menu opened by a gear button, instead of being drawn in the row with the… | Full descriptions, defaults and examples: [ConfigLayer in the API reference](/api/#category_ConfigLayer). ### LayersFunctions — Layer callbacks: functions you write 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. | Name | Type | Description | |---|---|---| | [`afterCalc`](/api/#LayersFunctions.afterCalc) | `function` | This function is executed right after the 'expression()' calculations. This function is only available for a Layer with a 'source' of type 'calculate' and that has defined the 'expression()' function. @param inputs {Array} The value of each input defined in… | | [`beforeCalc`](/api/#LayersFunctions.beforeCalc) | `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… | | [`expression`](/api/#LayersFunctions.expression) | `function` | 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. @param layerVals {Array.<LayerValues>} Is an array that has the… | | [`functions`](/api/#LayersFunctions.functions) | `Object` | Associate custom functions to handle events on layer callbacks such as button callbacks or any layer callbacks. These functions are scoped to the Layer and can be referenced by name on layer widget callbacks. Functions can also be accessed using… | | [`legendColor`](/api/#LayersFunctions.legendColor) | `function` | This function generates the color of each value/category of the calculated map generated by the 'expression()' function. The return value is the legend color that will be applied to the category. PS: This function callback is called in layer context. @param… | | [`onInputsReady`](/api/#LayersFunctions.onInputsReady) | `function` | This function is called when all inputs have been loaded and are ready. Even from Layers that aren’t visible. @param 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… | | [`onVisibilityChange`](/api/#LayersFunctions.onVisibilityChange) | `function` | This function is called whenever a Layer changes its visibility. Like, when the user toggle the value in the visibility button at the top right in the Legend Window. @param visibility {Boolean} It’s true if the Layer is visible or false otherwise. @param… | Full descriptions, defaults and examples: [LayersFunctions in the API reference](/api/#category_LayersFunctions). ### paramsButtonConfigProperties — Row buttons (paramsButtonConfig) paramsButtonConfig is a key of calculated, file and tile layers: an array with one object per button on the layer's row (query, legend, download, metadata...). These are the keys of each object; a bare object instead of an array is read as the query button. | Name | Type | Description | |---|---|---| | [`enableToggle`](/api/#paramsButtonConfigProperties.enableToggle) | `Boolean` | Makes the row button of a `paramsButtonConfig` entry that mirrors a widget (an entry with `associatedButtonID`) a toggle (`true`) or a plain push button (`false`). PS: Once the mirrored widget is found the platform sets it from that widget (a checkbox or a… | | [`hideBottomButton`](/api/#paramsButtonConfigProperties.hideBottomButton) | `Boolean` | Hides the text buttons at the bottom of the query and legend sections of the Legend Window ("Show query"/"Hide query" and "Show legend"/"Hide legend"). Set it to 'true' to hide them or 'false' to display them. It only works inside a `paramsButtonConfig` entry… | | [`hideButton`](/api/#paramsButtonConfigProperties.hideButton) | `Boolean` | Define if the associated button should be hidden. Set it to 'true' to hide the button or 'false' to show it. This property only applies to the type: 'query' | | [`iconCls`](/api/#paramsButtonConfigProperties.iconCls) | `String` | Define a class that will be added to the html in the associated button. This class can be one that has a image on it like: - 'gxp-icon-togglevisibility' is the icon of the Show/Hide Map Button (The first icon on the Legend Window, from left to right) -… | | [`pressed`](/api/#paramsButtonConfigProperties.pressed) | `Boolean` | Defines if the button should start pressed or not. Set it to 'true' for it to start pressed or 'false' for start unpressed. For example, the 'query' button type set as pressed will display the Query region (where the descriptionHtml content is) by default… | | [`toggleGroup`](/api/#paramsButtonConfigProperties.toggleGroup) | `String` | Defines a group for all the buttons that has the same toggleGroup name. From all the buttons on the same group, only one can be active at each time. Whenever another one is activated the previous one collapses. | | [`tooltip`](/api/#paramsButtonConfigProperties.tooltip) | `String` | Defines the help tooltip text that is displayed when the mouse hover the associated button. | | [`type`](/api/#paramsButtonConfigProperties.type) | `String` | Define which button will be affected by the configurations. The type can be one of the following: - 'query': The query button shows or hides the Query panel (where the descriptionHtml is drawn). - 'download': The download button is the one with a downward… | Full descriptions, defaults and examples: [paramsButtonConfigProperties in the API reference](/api/#category_paramsButtonConfigProperties). ### paramsButtonConfigFunctions — Row button callbacks Functions a row-button object can carry; the platform calls them when the button is pressed or toggled. | Name | Type | Description | |---|---|---| | [`handler`](/api/#paramsButtonConfigFunctions.handler) | `function` | Defines a function that will be called when the associated button is clicked. @param button {Object} is the button that was clicked by the mouse. @param clickEvent {MouseEvent} is the object that carries more information about the click event. | | [`toggleHandler`](/api/#paramsButtonConfigFunctions.toggleHandler) | `function` | This function is called whenever the associated button change its toggle state. PS: Using custom function, ignore the associatedButtonID "It doesnt have to even exists". @param button {Ext.Button} The button element that was clicked @param state {Boolean} The… | Full descriptions, defaults and examples: [paramsButtonConfigFunctions in the API reference](/api/#category_paramsButtonConfigFunctions). ## Kinds of layer: what each source adds ### QGIS — Published maps: styles from QGIS A published map's styles are made when it is published, from its QGIS style file; the automatic publication creates the same-looking style. A query picks one with styles. | Name | Type | Description | |---|---|---| | [`styles`](/api/#QGIS.styles) | `String` | Where a map's styles come from: they are not written in the query. A map is published with one or more styles, and when it is published from QGIS the layer's QGIS style is converted at publication time, so the classes, colours and legend labels the map shows… | Full descriptions, defaults and examples: [QGIS in the API reference](/api/#category_QGIS). ### RawMaps — Calculated layers: raw maps and operation tokens A raw map is published with each pixel's value instead of a colour. A calculated layer reads such a map with operation (raw, sum, average...) to get exact cell values; without operation it gets the value of the map's legend at each pixel. The colours are then applied in the browser. | Name | Type | Description | |---|---|---| | [`operations`](/api/#RawMaps.operations) | `Object` | Enumeration of the operations a map of a `source: 'calculate'` layer can be decoded with. This is what the `operation` layer key selects, one token per map in `name`; the tokens are the lower-case names below, matched case and whitespace insensitive. The… | Full descriptions, defaults and examples: [RawMaps in the API reference](/api/#category_RawMaps). ### FileLayer — File layers: data source: "file": where the features come from - json written in the query (the default type), type with a url, or type "load" with your own loadData. | Name | Type | Description | |---|---|---| | [`json`](/api/#FileLayer.json) | `Array.\|Object` | Inline data of a `source: 'file'` layer with `type: 'json'`. Either a GeoJSON object (FeatureCollection, Feature or a geometry; its projection is taken from `fromProj`, its `crs` or guessed from the coordinates) or an array of plain objects, each converted to… | | [`loadData`](/api/#FileLayer.loadData) | `function` | Custom loader of a `source: 'file'` layer with `type: 'load'`: `function(inputs, config)` called with the layer as `this`, receiving the current input values and the layer definition. Add the features yourself (`this.addFeatures`, `this.loadGeojson`, ...) and… | | [`onVisibilityChange`](/api/#FileLayer.onVisibilityChange) | `function` | Callback when layer visibility is changed. PS: Is not called for the initial visibility of the layer. | | [`type`](/api/#FileLayer.type) | `String` | Defines how a `source: 'file'` layer gets its features (case insensitive). One of: 'load': you load the data yourself in the `loadData` callback (`function(inputs, config)`, called with the layer as `this`). The callback must trigger… | | [`url`](/api/#FileLayer.url) | `String` | URL of the data of a `source: 'file'` layer, used by the types `csv` (a CSV file), `jsonurl` (a JSON array of plain objects) and `geojsonurl` (a GeoJSON file). Relative URLs are resolved against the Mappia page. Also available inside `loadData` as… | Full descriptions, defaults and examples: [FileLayer in the API reference](/api/#category_FileLayer). ### VectorLayer — File layers: style, events, drawing Keys and methods of a file layer: styles, clustering, click and hover callbacks (onClick, onHover), drawing (drawable), and the methods your functions call on this. | Name | Type | Description | |---|---|---| | [`activateDrawMode`](/api/#VectorLayer.activateDrawMode) | `function(mode) : Boolean` | Select polygon/line tool and enter edit mode when needed (split-button menu). @param mode {String} 'polygon' or 'line' — must be one of the layer's configured `drawModes`. | | [`applyFeatureChanges`](/api/#VectorLayer.applyFeatureChanges) | `function() : Boolean` | Finish sketch or deselect feature (triggers featureEditEnd when applicable). | | [`applyGeomOp`](/api/#VectorLayer.applyGeomOp) | `function(sourceGeoms, options) : Object` | Replace geometries on this **drawable VectorLayer** with id/attribute control via one options object. Only available on vector layers from ``VectorFileSource`` (e.g. ``drawable: true``). Implementation helpers live in {@link DrawableSplit.applyGeomOp}. @param… | | [`callFunction`](/api/#VectorLayer.callFunction) | `function(name, anyArguments) : *` | Calls one of the layer's own `functions` by name with the layer as `this`; falls back to a method of the layer with that name. Extra arguments are passed through to the function. @param name {String} Key of the `functions` object (or a layer method name).… | | [`cancelDrawing`](/api/#VectorLayer.cancelDrawing) | `function() : Boolean` | Cancel the in-progress sketch/edit without committing changes. | | [`cluster`](/api/#VectorLayer.cluster) | `Object` | AnimatedCluster options. Truthy object enables clustering even when `clusterDistance` is omitted. Zoom / map state is **not** passed into callbacks — read it yourself via `this.layer.map` (call scope is the strategy) or `ExtjsUtils.JS.getMap()`. | | [`clusterDistance`](/api/#VectorLayer.clusterDistance) | `Numeric` | Defines the minimum relative distance (in pixels) to clusterize points. Set 0 to never clusterize, or a value greater than 0 to set the minimum distance. For a membership key or dynamic distance, use {@link VectorLayer.cluster} instead (or together —… | | [`convertJsonEntryToFeature`](/api/#VectorLayer.convertJsonEntryToFeature) | `function(curObj, optionalGetLonLat) :…` | Converts a JsonObject into a Layer Feature (that can be added to layer). @param curObj {JsonObject} Object with properties. @param optionalGetLonLat {function} Optional function to get position coordinates from JSON. P.S.: Optional function to get X,Y values… | | [`coordinates`](/api/#VectorLayer.coordinates) | `Object` | Redefines the coordinate property names to {x, y}. PS: Used only if the 'VectorLayer.getVector' is not defined. | | [`defaultStyle`](/api/#VectorLayer.defaultStyle) | `Object` | Defines the default style that will be applied to the geometry. PS: Accepts 'context' and 'rules'. Property 'context': allows definition of functions. Property 'rules': allows definition of filters (only the geometries that fit into this rule will be… | | [`deselectFeature`](/api/#VectorLayer.deselectFeature) | `function() : Boolean` | Deselect the currently selected/edited feature without discarding it. | | [`drawable`](/api/#VectorLayer.drawable) | `Boolean\|Object` | Makes a vector layer editable: users can sketch, edit and delete polygon (optionally polygon+line) features, with configurable overlap resolution. Set to `true` for defaults, or an object to configure: - `maxGeomCount` {Number} — maximum number of features… | | [`fillGeometryLayer`](/api/#VectorLayer.fillGeometryLayer) | `function(config)` | Loads (or reloads) the layer's features from a data-loading config, following its `type` strategy: `load` calls `config.loadData`, `csv`/`jsonurl`/ `geojsonurl` fetch `config.url`, `json` uses the inline `config.json`, `empty` adds nothing. Unknown types fall… | | [`findFeatureById`](/api/#VectorLayer.findFeatureById) | `function(featureId) : OpenLayers.Feature.Vector\|null` | Find a feature by the id returned from ``getFeatureId`` (fid, id, or index). Prefer this over OpenLayers ``getFeatureById`` when callers use getFeatureId ids. @param featureId {String\|Number} Id as returned by `getFeatureId`. | | [`finishDrawing`](/api/#VectorLayer.finishDrawing) | `function() : Boolean` | Commit in-progress polygon sketch (same as double-click). | | [`fromProj`](/api/#VectorLayer.fromProj) | `String` | Defines the projection of the JSON (accepts only EPSG:4326 and EPSG:900913). | | [`generateNewLegend`](/api/#VectorLayer.generateNewLegend) | `function()` | Runs the layer's `beforeCalc(inputs)` again with the current input values. It is the supported way to force a vector layer to refresh whatever `beforeCalc` builds (styles, filters, charts) from outside a normal cycle, for example from `onVisibilityChange`;… | | [`getEditingFeatureId`](/api/#VectorLayer.getEditingFeatureId) | `function() : String\|Number\|null` | Feature id currently selected for vertex edit (drawable modify control), if any. | | [`getFeatureId`](/api/#VectorLayer.getFeatureId) | `function(feature) : String\|Number\|null` | Stable-enough id for a feature on this layer: ``fid``, then OpenLayers ``id``, otherwise the feature's index in ``layer.features`` (no synthetic attributes). @param feature {OpenLayers.Feature.Vector} Feature of this layer. | | [`getInputs`](/api/#VectorLayer.getInputs) | `function() : Array` | Returns the current value of every input tool declared in `descriptionHtml`, in declaration order (the same array the layer callbacks receive as `inputs`). Use it from callbacks that do not receive `inputs`, such as a `{{button}}` handler or… | | [`getLayerDefinedFunctionsByName`](/api/#VectorLayer.getLayerDefinedFunctionsByName) | `function(name) : function\|Undefined` | Gets the layer inner function. Define the layer inner function at VectorLayer. Ex: { name: 'CSR:map_name', function: { nameFunctionExample: function(){alert('a');} } } @param name {String} Function name | | [`getVector`](/api/#VectorLayer.getVector) | `function` | Defines the callback function to parse the layer data and get the geometry. Callback Function getVector function(attribute, config) @param attribute {Object} Object with attributes. @param config {Object} Layer config. | | [`hoverSelectedStyle`](/api/#VectorLayer.hoverSelectedStyle) | `Object` | Defines the style that will be applied to the geometry when the mouse hovers over a selected feature. Default hover selected style is the selected style PS: Accepts 'context' and 'rules'. Property 'context': allows definition of functions. Property 'rules':… | | [`hoverStyle`](/api/#VectorLayer.hoverStyle) | `Object` | Defines the style that will be applied to the geometry when mouse is hovering. PS: Accepts 'context' and 'rules'. Property 'context': allows definition of functions. Property 'rules': allows definition of filters (only the geometries that fit into this rule… | | [`llbbox`](/api/#VectorLayer.llbbox) | `OpenLayers.Bounds` | Bounds of the features currently on the layer, recomputed automatically after features are added or removed (and extended while drawing). Despite the name it is expressed in the map projection, not in lon/lat, so it can be passed straight to… | | [`loadGeojson`](/api/#VectorLayer.loadGeojson) | `function()` | Function to load geojson and draw on the layer. | | [`onAdded`](/api/#VectorLayer.onAdded) | `function()` | Called when the layer is on the map with its features loaded. If the layer is still fetching (`jsonurl` / `geojsonurl` / `csv` / async `load`), waits for that load to finish first so `this.features` / `this.getDataExtent()` are available (a failed load still… | | [`onBeforeFeatureChangeCallback`](/api/#VectorLayer.onBeforeFeatureChangeCallback) | `function` | Defines the callback function that is called before a layer feature is added, removed or edited. PS: If it returns false, the change operation is canceled. @param operationType {String} Receive the operation type: 'add' or 'remove' when adding or removing… | | [`onClick`](/api/#VectorLayer.onClick) | `function` | Defines the callback function to the click event on Layer. @param event {Object} The click event Object. @param source {VectorFileSource} Auxiliary functions to deal with Vector Layer. @param inputs {Array.<Object>} Array with all layer input values. | | [`onClickCfg`](/api/#VectorLayer.onClickCfg) | `function` | Defines the callback function to the Click Select controller. The additional parameters are listed in http://dev.openlayers.org/docs/files/OpenLayers/Control/SelectFeature-js.html. | | [`onFeatureChangeCallback`](/api/#VectorLayer.onFeatureChangeCallback) | `function` | Defines a function that is called after a layer feature is added, removed or edited. @param operationType {String} One of: ``'add'`` (features added in bulk, e.g. after loading data), ``'add1'`` (a single feature added interactively), ``'remove'`` (features… | | [`onHover`](/api/#VectorLayer.onHover) | `function` | Defines the callback function on 'Vector Layer' hover. @param evt {Object} Features. @param state {Boolean} True when hover starts, false when it ends. @param controller {Object} The controller itself. @param inputs {Object} Layer widget values. | | [`onInputsReady`](/api/#VectorLayer.onInputsReady) | `function` | Called when all inputs are ready on layer. | | [`onLoad`](/api/#VectorLayer.onLoad) | `function` | Defines the callback function to be called after the layer is loaded or added to a map. PS: You can use 'this' to access layer properties. @param widgetValues {Array} inputs for onLoad callback | | [`onSelectionToggle`](/api/#VectorLayer.onSelectionToggle) | `function` | Defines the callback function to the unselect feature. @param event {Object} The click event Object. @param source {VectorFileSource} Auxiliary functions to deal with Vector Layer. @param inputs {Array.<Object>} Array with all layer input values. | | [`popupCallback`](/api/#VectorLayer.popupCallback) | `function` | Not implemented for file layers: accepted but never called (see `popupTemplate`). Use `onClick`, which receives the clicked feature. @param attributes {Array} attributes for popupCallback @param inputs {Array} inputs for popupCallback | | [`popupTemplate`](/api/#VectorLayer.popupTemplate) | `String` | Not implemented for file layers: the value is accepted and kept on the layer, but nothing reads it, so no popup ever opens (the template belongs to the gxp feed sources this layer does not extend). Show a feature's attributes from `onClick` instead - for… | | [`resolveOverlap`](/api/#VectorLayer.resolveOverlap) | `function(editedGeoms, intersectingGeoms, options)` | Resolve overlaps between edited and existing polygons on this drawable VectorLayer. Uses ``drawable.onOverlap``: a single key applies immediately; an array prompts via ``ALERTIFY.confirmChoice`` (``merge`` / ``cut`` / ``keep``). @param editedGeoms… | | [`selectController`](/api/#VectorLayer.selectController) | `OpenLayers.Control.CustomSelectFeature` | The selection control created for the layer when `onClick`, `onSelectionToggle` or `onHover` is defined (undefined otherwise). It is the `OpenLayers.Control.CustomSelectFeature` instance, so you can call its `select(feature)`, `unselect(feature)`,… | | [`selectStyle`](/api/#VectorLayer.selectStyle) | `Object` | Defines the default style that will be applied to the selected geometry. PS: Accepts 'context' and 'rules'. Property 'context': allows definition of functions. Property 'rules': allows definition of filters (only the geometries that fit into this rule will be… | | [`setDrawing`](/api/#VectorLayer.setDrawing) | `function(enabled, callbackOnAdd)` | Defines drawing features on layers. PS: Function is available to the VectorLayer. @param enabled {Boolean} True to enable drawing, False otherwise. @param callbackOnAdd {function} Callback when a new feature is drew. P.S.: You can use 'this' to access layer… | | [`showLoadingModal`](/api/#VectorLayer.showLoadingModal) | `Boolean` | Shows the "generating legend" loading mask visibly over the page while the layer is paused (loading its data or another resource). By default the mask is an invisible overlay that only changes the cursor to "wait"; set it to `true` in the layer definition to… | | [`styleMap`](/api/#VectorLayer.styleMap) | `Object\|OpenLayers.StyleMap` | Customizes the layer visualization. PS: It is an advanced parameter, so it might be easier to use selectedStyle, defaultStyle and hoverStyle. PS2: The 'hover' style is applied on hover event. | | [`waitingRenderAndLoadAssync`](/api/#VectorLayer.waitingRenderAndLoadAssync) | `Number` | Number of asynchronous resources of the layer still loading (its own data for `csv`, `json`, `jsonurl`, `geojsonurl` and `load` types, plus `{{loadcsv}}`/`{{loadjson}}` inputs and any `startLoadingLayer` you trigger yourself). It is increased on… | Full descriptions, defaults and examples: [VectorLayer in the API reference](/api/#category_VectorLayer). ### XYZLayer — Tile layers (xyz) source: "xyz": tiles of a tile service, addressed by ${z}, ${x} and ${y} in url. | Name | Type | Description | |---|---|---| | [`name`](/api/#XYZLayer.name) | `String` | Defines a map identifier. This name should be unique. | | [`source`](/api/#XYZLayer.source) | `Object` | Adds a layer to store the source. @param layerCfg {LayerConfig} Layer XYZ configuration. LayerConfig { url: url, name: name, isBaseLayer: isBaseLayer, sphericalMercator: sphericalMercator } | | [`url`](/api/#XYZLayer.url) | `String` | Defines the url where the map can be fetched from. Use the ${x} ${y} ${z} as placeholder for x, y and z coordinates. | Full descriptions, defaults and examples: [XYZLayer in the API reference](/api/#category_XYZLayer). ## Groups: what you write in a group ### GroupProperties — Group properties Keys of a group object, written next to its elements: title or viewTitle, color, openGroup, defaultProperties... | Name | Type | Description | |---|---|---| | [`color`](/api/#GroupProperties.color) | `String` | Defines the Color of the group. This is the Color of the Title and some elements inside the sub menu on the top of the screen. | | [`customLayerClass`](/api/#GroupProperties.customLayerClass) | `String` | Extra CSS class added to the node of a `viewTitle` group in the Legend Window, so the group title and its rows can be styled with `ExtjsUtils.CSS.defineClass` or a stylesheet. Only groups with a `viewTitle` create a node; on a layer the same key styles the… | | [`defaultProperties`](/api/#GroupProperties.defaultProperties) | `Object` | Specifies properties that apply universally to all layers within a group, including nested subgroups and their respective layers. Priority is determined by specificity: a property defined at the layer level takes precedence, followed by properties defined in… | | [`elements`](/api/#GroupProperties.elements) | `Array.` | Defines the Layers that will be part of the Group. Each Layer can have multiple maps inside it. All maps inside a Layer will be shown together when that Layer is enabled. Besides that, all information about those maps can be used to calculate a new one using… | | [`global`](/api/#GroupProperties.global) | `Object` | A second way to declare query globals: an object whose properties become temporary globals, passed to `ExtjsUtils.QUERY.setQueryGlobalProperties` while the group is interpreted (before its layers). The usual form is the… | | [`openGroup`](/api/#GroupProperties.openGroup) | `Boolean` | Defines if the 'viewTitle' should start opening or collapse. Set it to 'true' for the 'viewTitle' start open or 'false' for it to start closed. This property only applies to a group that has the 'viewTitle' property defined. If the Group View has any visible… | | [`title`](/api/#GroupProperties.title) | `String` | Defines the Title of the group. The Title is shown at the sub menu on the top of the screen. | | [`viewTitle`](/api/#GroupProperties.viewTitle) | `String` | Define the Title of the View that will gather together the elements inside it (Groups or other Views). If an external View has in its elements another definition of a 'viewTitle', subviews will be created, like in the second example. | Full descriptions, defaults and examples: [GroupProperties in the API reference](/api/#category_GroupProperties). ### GroupFunctions — Group callbacks (viewTitle groups) Functions a viewTitle group can carry; the platform calls them when its heading in the layer panel is clicked or toggled. Inside them this is the heading's node. | Name | Type | Description | |---|---|---| | [`onClickViewGroup`](/api/#GroupFunctions.onClickViewGroup) | `function` | Called whenever the user clicks the title of a `viewTitle` group in the Legend Window. It belongs on a group that has `viewTitle`: the handler is bound to that group's tree node, so `this` is the node and `view.expanded` tells whether the group is open after… | | [`onToggleViewGroup`](/api/#GroupFunctions.onToggleViewGroup) | `function` | Called whenever a `viewTitle` group of the Legend Window is expanded or collapsed (by the user or by code). It belongs on a group that has `viewTitle`: the handler is bound to that group's tree node, so `this` is the node and `view.expanded` is `true` after… | Full descriptions, defaults and examples: [GroupFunctions in the API reference](/api/#category_GroupFunctions). # Section: Tools ## The widget markup language > The double-brace markup that puts sliders, buttons, pickers and loaders inside a layer's panel - every tag, the parameter grammar, how callbacks are resolved and what each widget's value holds. A layer's `descriptionHtml` is free HTML with one addition: text in double braces becomes an interface element. This is the language of that markup - a small one, with its own parameter grammar, its own escaping and its own rules for finding the function a widget should call. Widgets that collect a value also feed the layer's calculation, which is what makes a Mappia map interactive: a slider moved by the user re-runs the arithmetic over the pixels. The full parameter list of every widget is in the [API reference](/api/) under **Tools**; this page is the language and the behaviour around it. Use these tools inside a layer’s `descriptionHtml`. Parameters are pipe-separated: ```text {{toolName|param=value|other=value}} ``` HTML and multiple tools can be concatenated: ```javascript descriptionHtml: '

Intro

' + '{{label|text=Year:}}' + '{{slider|id=year|minValue=2000|maxValue=2020|value=2010}}' + '{{button|id=run|text=Run|handler=onRun}}' ``` Open the query panel with `paramsButtonConfig: [{ type: 'query', pressed: true }]` when the user must see the tools. **Input order:** tools that act as inputs (slider, textfield, combobox, timeline, zoomlevel, pickpoint, hoverpixel, summedarea, areaintegral, loadcsv, loadjson, filefield, inputmanager, window) feed `expression` / `beforeCalc` / `afterCalc` as `inputs[0]`, `inputs[1]`, … in **markup order**. When they have an `id` they are also `inputs.id[ID]` — **on the page only** (`beforeCalc`, `onInputsReady`, `afterCalc`, `functions`): inside `expression` the inputs arrive as a JSON copy of the array, which drops the `id` map, so `expression` must use positions. `button`, `checkbox`, `label`, `legendhtml`, `opacityslider`, `livecomposedsplit` are **not** inputs. **Callback names** (`handler=`, `toggleHandler=`, `runOnClick=`, `runOnHover=`, `onMark=`, `onPlayToggle=`, `_onChange=`, …) resolve in this order: **(1)** `layer.functions[name]` → **(2)** a global `window[name]` (from `setQueryGlobalProperties`) → **(3)** the text itself evaluated as a function (a full `function(){…}` or a bare statement body). `this` inside is the layer (exceptions per widget below). `{{combobox|onSelect=}}` skips step 2. Prefer `functions: { onRun: function() { … } }` on the layer. --- ## Catalog (all `Mark.create` tags) | Tag | Purpose | Key params (see `api.json` → Tools → group for the full list) | |-----|---------|-------------------------------------------| | `label` | Static text / HTML | `text`, `html` (verbatim up to next `\|`), `cls`, `style`, `forId` | | `button` | Click / toggle action | `id`, `text`, `handler` / `toggleHandler`, `enableToggle`, `pressed`, `hidden`. `toggle=` is an alias moved to `toggleHandler`; with `enableToggle=true` and no `toggleHandler`, `handler` becomes the toggle handler | | `checkbox` | Boolean switch — **not an input**: `handler(checkbox, checked)` runs on every toggle (also once with `false` when the layer is removed) | `id`, `text`, `checked`, `handler`, `labelBefore`, `iconCls`; runtime `Ext.getCmp(id).toggle(state?)`, `setBoxLabel(txt)` | | `textfield` | Single-line text / number input | `id`, `value`, `fieldLabel`, `isnumeric` (validator only — value stays a string), `hideLabel`, `afteredit` | | `combobox` | Select from list | `id`, `data` (`[["value"], …]` - one value per entry, shown as is), `fieldLabel`, `editable`, `hideLabel`, `onSelect(combo, record, index)` | | `slider` | Numeric range input | `id`, `minValue`, `maxValue`, `value` / `values` (range), `increment`, `plugins=tip={0}%`, `gradient`, `backgroundColors` | | `opacityslider` | Layer opacity | `value` (only when the layer has no `opacity`), `inverse`, `complementaryLayer`, `changeVisibility` | | `legendhtml` | Inline map legend | `reverseLegend`, `filterLayers`, `legendId`, `preventClick`, `useScaleParameter`, `autoWidth` | | `timeline` | Play through style / scenario steps | `id`, `steps`, `nextStepInterval`, `preloadTiles`, `onPlayToggle` (**must return truthy** — a falsy return vetoes the play/stop), `fieldLabel`; many runtime methods (`setSteps`, `getValue`, `startAnimationStep`, …) | | `livecomposedsplit` | Split-screen compare of two composed styles | `displayNames`, `layerNames`, `baseName`, `leftDefault`, `rightDefault`, `id`, `layout` (`compact`\|`inline`) | | `window` | Floating Ext window | `id`, `title`, `text`/`html`, `startVisible`, `width`, `height`, `x`, `y`, `items`, `onBeforeHide`, `ignoreVisibility` | | `filefield` | Local file picker | `id`, `fieldLabel`, `ignoreUpdate`, `_on=` for any Ext field event in `eventNames` (`_onChange=onSelectFile`, case-insensitive) | | `loadcsv` | Load remote CSV → `CsvTable` | `id`, `url`, `cors`, `removeEmptyLines`; `trim` is accepted but **ignored by the parser** (trim cells yourself) | | `loadjson` | Load remote JSON | `id`, `url`, `cors` | | `pickpoint` | Click map → feature attributes per layer | `id`, `checked`, `onefeature`, `geometryColor`, `onMark` (≡ `runOnClick`; `onMark` wins), `runOnHover`, `lat`/`lon`, `markLayerInd`, `notify`, `unselect` | | `hoverpixel` | Pixel value under cursor / on click | `id`, `text`, `runOnHover`, `runOnClick`, `runOnHoverOutside`, `runOnClickOutside`, `checked`, `notify` — moving/clicking does **not** recalculate the layer | | `summedarea` | Draw polygon → sum raster values | `id`, `text`, `runOnClick(layersValues, inputs, feature)`, `notify`, `unselect`. Its `inputs.id[ID]` value is **never filled** — use the callback | | `areaintegral` | Two clicks → rectangle sum via summed-area (`integral`) maps | `id`, `text`, `runOnClick(layersValues, inputs, boundingBox, pixel, lastInfo)`, `notify`, `unselect`, `iconCls`, `labelBefore`. Was broken for a long time - it registered its input under a name that did not exist and never set `lastInfo` - and now works | | `inputmanager` | Named bag of values for callbacks | `id`; runtime `getValue`, `setValues(obj, cancelUpdate, local)`, `setDefaultValues(obj, local)`, `forceRecalc()` | | `zoomlevel` | Hidden input = current map zoom | `id` (required; renders nothing) | Also allowed in `descriptionHtml`: raw **HTML** (not a `{{…}}` tag). --- ## Markup syntax (all tools) — `api.json` → Tools → `MarkupSyntax` | Rule | Effect | |------|--------| | `param=value` | Numbers become JS numbers; `param=` (empty) is `""`; anything else stays a string (`true` is the string `"true"`, truthy). Arrays/objects (`data`, `steps`, `values`, `filterLayers`) are parsed by the tool as JSON | | `param=false` | Rewritten to `param=` (falsy) — the only way to switch off a default-true flag (`unselect=false`, `notify=false`) | | `\|isnumeric\|` | Bare key = `""`, except the special keys (`isnumeric`) | | `a=b=c` | Nested object `{a: {b: c}}` — `plugins=tip={0}%` (slider tip), `scope=getid=ID` | | `\=` | Literal `=` inside a value (URLs with query strings); double the backslash inside a JS string. `html=` is exempt (verbatim) | | `cls=` | Repeating `cls` **concatenates** (no separator); other repeated keys keep the last value | | `getid=ID` | Reference an element created **earlier** in the same description; `getid=ID\|getid=on_=` attaches an Ext listener to it (`this` = that element; evaluated directly, no `functions`/globals lookup) | | `function=` | A function from raw text (`param=function=` to assign it); rarely needed — callback params already accept names or inline text | ## Input values — what `inputs.id[ID]` holds and what triggers a recalculation From the `.value` entries in `api.json` (read the entry for details): | Widget | `inputs.id[ID]` holds | Layer recalculates on | |---|---|---| | `slider` | number, or `[lower, upper]` with `values` | slider `change` (thumb released / set from code) | | `textfield` | the raw text (**string**, even with `isnumeric` — `parseFloat` it) | every `keyup` | | `combobox` | selected `data` value as a string (first entry initially) | `select` | | `timeline` | key of the current step (first element of the `steps` entry, string) | `change` (thumb moved, animation) — after the step style is applied | | `zoomlevel` | current zoom (number) | map `moveend`, only when the zoom changed | | `loadcsv` | `ExtjsUtils.CSV.CsvTable` (header = row 0); `undefined` until loaded | resource `waitend` — the layer waits, so `beforeCalc` can rely on it | | `loadjson` | parsed JSON (object/array; `[]` on empty body) | resource `waitend` | | `pickpoint` | the `PointAttributeManager` (`getAttributes(mapIndex)`, `searchAttribute`, `getPointPos`, `getLastEvent`, `removeAll`, …) — holds map features: extract plain values in `beforeCalc`, never send to `expression` | `onmark` (after every click, once all layers' feature info arrived) | | `hoverpixel` | `lastInfo` `{click: {lon, lat}, hover: {lon, lat}}` (EPSG:4326, `null` before first event; updated in place, so always current when read) | **nothing** — registered on `forceupdatelayer`, which nothing fires; react in `runOnClick`/`runOnHover` | | `summedarea` | an array meant for the last sums — **stays empty** (never filled); use `runOnClick` | `forceupdatelayer` of the switch (`Ext.getCmp(id).items.get(0).forceUpdateLayer()`) | | `areaintegral` | `layersValues` of the last rectangle (one sum per inner layer; updated in place) | `forceupdatelayer` — not fired by the tool; call `forceUpdateLayer()` inside `runOnClick` | | `inputmanager` | the manager (`getValue`, `setValues`, `setDefaultValues`, `forceRecalc`, `.global` bucket). Only `global` reaches `expression`; `local=true` values may hold DOM/Ext objects | its `change` — fired by `setValues` (unless `cancelUpdate`) and `forceRecalc` | | `filefield` | a **getter function**: `inputs.id[ID]()` → the `File` or `undefined` | input `change` (new file) unless `ignoreUpdate=true` | | `window` | handle `{getIds, getWindow, getButton, getContainer}` (components — not for `expression`), stored under the **button's id**: `inputs.id[btnID]`, not the markup `id` (set `btnID` to know it) | once, on window `afterrender` | | `opacityslider` | not an input (`value` = initial opacity %) | — | Caveats worth repeating: `LoadCsv.trim` is a no-op; `SummedArea.value` is never filled; `Hoverpixel` never recalculates by itself (`lastInfo` is still always current); `Timeline.onPlayToggle` must return truthy (a bare statement body returns `true`). --- ## How to choose a tool | Need | Prefer | |------|--------| | Show text / HTML | `label` or raw HTML | | User runs a named function | `button` (+ `functions`) | | Numeric parameter for `expression` | `slider` or `textfield\|isnumeric=true` | | Discrete choice | `combobox\|data=…` | | Boolean switch that runs code | `checkbox` (+ `handler`; store the state with an `inputmanager` if `expression` needs it) | | Opacity control | `opacityslider` | | Show legend in panel | `legendhtml` | | Animate styles over time | `timeline` | | Compare two composed styles live | `livecomposedsplit` | | Click map for value / geometry | `pickpoint` | | Continuous pixel read | `hoverpixel` | | Area sum / integral | `summedarea` / `areaintegral` | | Upload local file | `filefield` | | Fetch remote CSV/JSON | `loadcsv` / `loadjson` | | Extra floating UI | `window` | --- ## Minimal patterns (copy / adapt) ### Button + handler ```javascript { title: 'Demo', name: 'CSR:estados', source: 'calculate', visibility: true, paramsButtonConfig: [{ type: 'query', pressed: true }], descriptionHtml: '{{button|id=say_hi|text=Say hi|handler=onHi}}', functions: { onHi: function() { ExtjsUtils.ALERTIFY.log('hi'); } } } ``` ### Slider as `expression` input ```javascript { title: 'Threshold', name: 'CSR:altimetria', source: 'calculate', visibility: true, paramsButtonConfig: [{ type: 'query', pressed: true }], descriptionHtml: '{{slider|id=thr|minValue=0|maxValue=100|value=50}}', expression: function(layerVals, inputs) { var thr = inputs[0]; return layerVals[0] > thr ? 1 : undefined; } } ``` ### Combobox ```text {{combobox|id=month|fieldLabel=Month|data=[["Jan"],["Feb"]]|editable=false}} ``` `data` is a list of one-element arrays: each value is both what the list shows and what the input holds. A second element (`["01", "Jan"]`) is ignored - the store has a single `value` field. ### Timeline ```text {{timeline|id=lu_tl|nextStepInterval=1000|steps=[["01","January"],["02","February"]]}} ``` Pairs with composed / calculate layers that change styles per step. See `api.json` → Timeline (`onPlayToggle`, `preloadTiles`, …). ### Pickpoint / hoverpixel ```text {{pickpoint|id=pick|fieldLabel=Pick|checked=false|onefeature=true|onMark=onPicked}} {{hoverpixel|id=hp|text=Value|runOnHover=onHoverValue|runOnClick=onClickValue}} ``` ```javascript functions: { onPicked: function (evt) { /* evt.type 'add'|'remove', evt.features[layerIdx][i].data; this = the pickpoint checkbox, this.value = PointAttributeManager */ }, onHoverValue: function (layerVals, inputs, coordinates, mouseEvt, lastCoordinates) { /* this = layer */ }, onClickValue: function (layerVals, inputs, coordinates, clickEvt, lastCoordinates) { /* this = layer */ } } ``` `pickpoint` recalculates the layer after every click (`onmark`); `hoverpixel` never does — use the callbacks (they receive the map values) or force a recalculation. ### Checkbox (handler, not an input) ```text {{checkbox|id=show_details|text=Show details|checked=true|handler=onToggleDetails}}{{inputmanager|id=state}} ``` ```javascript functions: { onToggleDetails: function (checkbox, checked) { this.getInputs().id["state"].setValues({ details: checked }); // recalculates the layer } } ``` ### Area integral (two-click rectangle; needs maps published with the `integral` operation) ```text {{areaintegral|id=integral_tool|text=Sum a rectangle|runOnClick=onAreaSummed}} ``` ```javascript functions: { onAreaSummed: function (layersValues, inputs, boundingBox, pixel, lastInfo) { // boundingBox = [minLon, minLat, maxLon, maxLat] (EPSG:4326); lastInfo = {first:{lon,lat}, second:{lon,lat}} ExtjsUtils.ALERTIFY.log("Sum: " + layersValues[0]); Ext.getCmp("integral_tool").items.get(0).forceUpdateLayer(); // only if beforeCalc must see inputs.id["integral_tool"] } } ``` `summedarea` is the free-polygon sibling: `runOnClick(layersValues, inputs, feature)`; its `inputs` value is never filled. ### Opacity + legend ```text {{opacityslider}}{{legendhtml|reverseLegend=false}} ``` ### Live composed split Requires a calculated layer built from two styles of the same map (often the same name twice with two `styles` entries). The parameters are listed in the [API reference](/api/) under **Tools -> LiveComposedSplit**. ```text {{livecomposedsplit|id=split1|displayNames=A,B|layerNames=style_a,style_b|baseName=CSR:estados|leftDefault=A|rightDefault=B}} ``` ### Window ```text {{window|id=help_win|title=Help|text=Read me|startVisible=false|width=320|height=200}} ``` ### File / CSV / JSON ```text {{filefield|fieldLabel=Load SHP|id=loadshp|_onChange=onSelectFile}} {{loadcsv|id=tbl|url=https://example.com/data.csv?v\=2|removeEmptyLines=true|cors=true}} {{loadjson|id=cfg|url=https://example.com/config.json}} ``` With stable `id`s, the layer's callbacks read **`inputs.id["tbl"]`** (a CSV table object), **`inputs.id["cfg"]`** (parsed JSON) and **`inputs.id["loadshp"]()`** (the selected file). When each of these becomes available, and why a layer waits for them, is described in [the execution model](/reference/execution-model/). ### Zoom level (hidden input) ```text {{zoomlevel|id=z}} ``` `inputs.id["z"]` = current zoom (number); refreshed when the map stops moving, and it recalculates the layer only when the zoom actually changed. ### Timeline with a play veto ```text {{timeline|id=tl|steps=[["1990","1990"],["2000","2000"]]|onPlayToggle=onPlay}} ``` ```javascript functions: { onPlay: function (pressed, layer, timeline, playBtn) { return !window.stillLoading; } // falsy = veto } ``` --- ## Authoring checklist 1. Put tools only in `descriptionHtml` (not as top-level QUERY keys). 2. Use the exact tag from the catalog (`livecomposedsplit`, not `LiveComposedSplit`). 3. Give interactive tools stable `id`s when other code or inputs must find them. 4. Wire `handler` / `toggleHandler` / `runOnClick` names to `functions: { … }` on the same layer (regular `function`, not arrows — `this` is the layer). 5. Remember **input order** for `expression(layerVals, inputs)`, and that only plain data reaches `expression`. 6. For a side-by-side comparison use `livecomposedsplit`; there is no second split API. 7. Prefer `api.json` → Tools → `` when a parameter’s type/default is unclear; `.value` says what the input holds. 8. Panels with several widgets, the layer-row buttons (`paramsButtonConfig`) and page chrome belong to [the layer and group model](/reference/layer-and-group-model/). 9. An unknown tag fails silently: the element is simply not created, and the console shows `{{MARKUP}} INVALID OBJECT NAME`. ## Widget catalogue > Every widget the markup accepts, with its parameters, its runtime methods and the shape of the value it contributes to a calculation - generated from the platform source. Every tag the widget markup accepts, as the platform declares it. A widget's parameters are written inside its braces (`{{slider|id=year|minValue=2000}}`); the entries below are that parameter list, plus the methods and the input value each widget exposes to a layer's callbacks. How the markup itself is parsed - escaping, nested keys, handler resolution - is in the previous chapter. ## MarkupSyntax — Markup rules for every widget Rules shared by every tool written inside descriptionHtml as {{tool\|param=value\|param2=value2}}: how parameters are parsed, the values they accept and the special parameters (getid, function, on_<event>, isnumeric, cls, key=false, nested a=b=c, escaped \= ) available to all tools. Function-valued parameters (handler, runOnClick, runOnHover, onSelect, ...) are resolved in this order: a key… | Name | Type | Description | |---|---|---| | [`cls`](/api/#MarkupSyntax.cls) | `String` | `cls=` adds CSS classes to the created element. Unlike other keys, repeating it concatenates the values (with no separator — start the second one with a space, or list all classes in a single `cls`). | | [`defaultParsing`](/api/#MarkupSyntax.defaultParsing) | `String\|Number` | How a plain `param=value` is converted before reaching the tool: a value that looks like a number (`10`, `-4.5`, `1e3`) becomes a JavaScript number, an empty value (`param=`) becomes the empty string (falsy), and anything else stays a string — tools that need… | | [`escapedEquals`](/api/#MarkupSyntax.escapedEquals) | `String` | Write `\=` to put a literal `=` inside a value; a bare `=` would start a nested key (see `nestedKeys`). Needed above all in URLs with query strings. Inside a JavaScript string remember to double the backslash (`'\\='`). The value of `html=` is exempt:… | | [`falseValue`](/api/#MarkupSyntax.falseValue) | `Boolean` | `param=false` is rewritten to `param=` (an empty, falsy value) before parsing, because the literal text `"false"` would otherwise be a truthy string. Use it to switch off a boolean parameter whose default is true (`unselect=false`, `notify=false`,… | | [`function`](/api/#MarkupSyntax.function) | `function` | `function=` stores a function whose body is the given text (`function () { }`), evaluated with no `try/catch` and no lookup in the layer `functions`. Use the nested form `param=function=` to assign it to a parameter (a top-level `function=`… | | [`getid`](/api/#MarkupSyntax.getid) | `Object` | `getid=ID` gives access to an element created EARLIER in the same description (by any tag with that `id`). At the top level (`\|getid=slider1\|`) the element is stored in the tool config under `getid`; the common use is to attach a listener to it with… | | [`html`](/api/#MarkupSyntax.html) | `String` | `html=` is the one key whose value is taken verbatim up to the next `\|`: `=` characters inside it are kept and no nesting happens. Used by `label` and `window`. | | [`isnumeric`](/api/#MarkupSyntax.isnumeric) | `Boolean` | `\|isnumeric\|` (or `isnumeric=true`) installs a validator that only accepts numeric text — the field is marked invalid with the localized "must be a number" message otherwise. Meant for `textfield`. Note that the input value is still delivered as a string;… | | [`nestedKeys`](/api/#MarkupSyntax.nestedKeys) | `Object` | `a=b=c` creates a nested object: the tool receives `{a: {b: c}}`. The innermost `key=value` is parsed with the same rules as a top-level one, so the special keys work at any depth — `plugins=tip=...` builds a slider tip plugin, `scope=getid=ID` assigns an… | | [`on_event`](/api/#MarkupSyntax.on_event) | `function` | `on_=` adds a listener for an Ext event (`change`, `select`, `afteredit`, `toggle`...) on an element referenced with `getid` — the form is `getid=ID\|getid=on_=`; it cannot be used on the tag's own element. `` is either a full… | | [`tip`](/api/#MarkupSyntax.tip) | `Object` | `tip=` builds an `Ext.slider.Tip` whose text is `String.format(format, thumbValue, value of thumb 0, value of thumb 1...)`, so `{0}` is the dragged thumb value. It must be assigned to a slider's `plugins` with the nested form `plugins=tip=`; a… | Full descriptions, defaults and examples: [MarkupSyntax in the API reference](/api/#category_MarkupSyntax). ## HTML — Free HTML Any HTML is possible to be added to the layer description. | Name | Type | Description | |---|---|---| | [`content`](/api/#HTML.content) | `String` | Free HTML inside a layer's `descriptionHtml`: everything that is not a `{{tag}}` is passed through to the panel untouched, so a description can carry headings, images, links, tables and the container elements a chart or a custom control needs. Widgets and… | Full descriptions, defaults and examples: [HTML in the API reference](/api/#category_HTML). ## AreaIntegral — areaintegral · sum inside a rectangle (input) Two clicks on the map define a rectangle; the tool sums the map values inside it using summed-area (integral) maps, so it only works with maps published with the 'integral' operation. Callback parameters (layersValues {Array[Number]}, inputs {Array}, boundingBox {Array[Number]} in EPSG:4326, pixel {x,y}, lastInfo {first, second}) Usage: {{areaintegral\|runOnClick=onAreaSummed}} | Name | Type | Description | |---|---|---| | [`getLayerValues`](/api/#AreaIntegral.getLayerValues) | `function(mousePoint, layer) : Array.\|null` | Reads the composed map at one screen position: one value per inner layer (decoded from the tile colours through the legend, null cells read as 0) plus one extra entry with the layer `expression` result for those values. The tool samples the four corners of… | | [`iconCls`](/api/#AreaIntegral.iconCls) | `String` | Defines the CSS class of the toggle switch icon; replace the default to restyle the switch. | | [`id`](/api/#AreaIntegral.id) | `String` | Defines the id of the tool: the key used in `inputs.id[ID]` and the id of the container component (`Ext.getCmp(id)`; the switch itself is `Ext.getCmp(id).items.get(0)`). Generated when omitted. | | [`labelBefore`](/api/#AreaIntegral.labelBefore) | `Boolean` | Set true to render the `text` label before (left of) the toggle switch instead of after it. | | [`notify`](/api/#AreaIntegral.notify) | `Boolean` | Set false to suppress the notification shown when the tool is activated. | | [`runOnClick`](/api/#AreaIntegral.runOnClick) | `function` | Defines the callback run after the second click closes the rectangle, with the sums computed. Called as `runOnClick(layersValues, inputs, boundingBox, pixel, lastInfo)` with `this` = the layer: `layersValues` has one summed value per inner layer (see… | | [`text`](/api/#AreaIntegral.text) | `String` | Defines the text shown next to the toggle switch. | | [`unselect`](/api/#AreaIntegral.unselect) | `Boolean` | Only changes the activation message (`true`: one selection expected, `false`: several); the tool always deactivates itself after the second click. | | [`value`](/api/#AreaIntegral.value) | `Array.` | Value stored in `inputs.id[ID]`: the `layersValues` array of the tool — one summed value per inner layer of the composed map for the last rectangle (empty before the first one). The array is updated in place after the second click, so… | Full descriptions, defaults and examples: [AreaIntegral in the API reference](/api/#category_AreaIntegral). ## Button — button · push or toggle button Create a simple button to user interact with the map. | Name | Type | Description | |---|---|---| | [`enableToggle`](/api/#Button.enableToggle) | `Boolean` | Defines the button type as toggle. Set true to use as toggle, false otherwise. PS: When its true the callback is 'toggleHandler', otherwise the callback is 'handler'. | | [`fieldLabel`](/api/#Button.fieldLabel) | `String` | Defines the button label. | | [`handler`](/api/#Button.handler) | `function` | Defines the callback function on button click event. This should be used when the enableToggle property is false. `this` inside the callback is the layer. The value is resolved in this order: (1) a key of the layer `functions` object with that name; (2) a… | | [`hidden`](/api/#Button.hidden) | `Boolean` | Set true to create the button hidden (Ext `hidden` config); show it later with `Ext.getCmp(id).show()`. This is one example of the pass-through: every other `Ext.Button` config (`iconCls`, `tooltip`, `cls`, `width`, `disabled`, `scale`...) written in the… | | [`id`](/api/#Button.id) | `String` | Defines the id to identify the object. | | [`pressed`](/api/#Button.pressed) | `Boolean` | Defines the button initial state. Set it true to start pressed (only if enableToggle = true), false otherwise. | | [`text`](/api/#Button.text) | `String` | Defines the button text. | | [`toggle`](/api/#Button.toggle) | `function` | Alias of `toggleHandler`: a function given as `toggle=` is moved to `toggleHandler` (unless one is already defined), so the Ext `toggle()` method of the button is never overwritten. Prefer `toggleHandler`. | | [`toggleHandler`](/api/#Button.toggleHandler) | `function` | Defines the callback function on button toggle event. This should be used when the enableToggle property is true. `this` inside the callback is the layer. The value is resolved in this order: (1) a key of the layer `functions` object with that name; (2) a… | Full descriptions, defaults and examples: [Button in the API reference](/api/#category_Button). ## Checkbox — checkbox · on/off, calls a function A checkbox that calls a function of the layer when toggled. It is not registered as an input: read its state inside the handler. Usage: {{checkbox\|text=Show details\|handler=onToggleDetails}} | Name | Type | Description | |---|---|---| | [`checked`](/api/#Checkbox.checked) | `Boolean` | Set true to start checked. `handler` is not run for the initial state. | | [`fieldLabel`](/api/#Checkbox.fieldLabel) | `String` | Defines a label at the left of the whole field (Ext `fieldLabel`), in addition to the `text` shown next to the switch. `hideLabel=true` removes it and its reserved space. | | [`forceUpdateLayer`](/api/#Checkbox.forceUpdateLayer) | `function()` | Fires the `forceupdatelayer` event of the widget. For the map-interaction tools registered as inputs (summedarea, areaintegral) this is the event the layer listens to, so calling it marks the input as changed and recalculates the layer with the values… | | [`handler`](/api/#Checkbox.handler) | `function` | Defines the callback run whenever the checkbox is checked or unchecked (by the user or by `toggle()`). Called as `handler(checkbox, checked)` with `this` = the layer. The value is resolved in this order: a key of the layer `functions` object, then a global… | | [`iconCls`](/api/#Checkbox.iconCls) | `String` | Defines the CSS class of the toggle switch icon; replace the default to restyle the switch. | | [`id`](/api/#Checkbox.id) | `String` | Defines the id of the checkbox component (`Ext.getCmp(id)`), e.g. to call `toggle()` or `setBoxLabel()` from a button. Generated when omitted. | | [`inputValue`](/api/#Checkbox.inputValue) | `String` | Defines the DOM `value` attribute of the underlying `` (useful inside an HTML form). | | [`labelBefore`](/api/#Checkbox.labelBefore) | `Boolean` | Set true to render the `text` before (left of) the toggle switch instead of after it. | | [`notify`](/api/#Checkbox.notify) | `Boolean` | Accepted for parity with the map-picking switches (pickpoint, hoverpixel...), where it controls the activation notification. A plain checkbox shows no notification, so the value has no effect here. | | [`setBoxLabel`](/api/#Checkbox.setBoxLabel) | `function(boxLabel)` | Changes the text shown next to the checkbox (the markup `text` parameter) after it was rendered. Available on every checkbox-style tool (checkbox, pickpoint, hoverpixel, summedarea, areaintegral); get the component with `Ext.getCmp(id)`. @param boxLabel… | | [`text`](/api/#Checkbox.text) | `String` | Defines the text shown next to the toggle switch (the checkbox `boxLabel`). | | [`toggle`](/api/#Checkbox.toggle) | `function(forceState)` | Checks or unchecks the checkbox from code, running its `handler` as if the user had clicked it. Without an argument the current state is inverted. Get the component with `Ext.getCmp(id)`. @param forceState {Boolean} `true` to check, `false` to uncheck; omit… | | [`unselect`](/api/#Checkbox.unselect) | `Boolean` | Accepted for parity with the map-picking switches, where it selects the activation message. A plain checkbox never unchecks itself, so the value has no effect here. | Full descriptions, defaults and examples: [Checkbox in the API reference](/api/#category_Checkbox). ## Combobox — combobox · pick from a list (input) It creates an input of ComboBox tool where the value is selectable from a list. Usage: '{{combobox}}' or examples. | Name | Type | Description | |---|---|---| | [`data`](/api/#Combobox.data) | `Array.>` | Defines the data that will be displayed in the Combobox. | | [`editable`](/api/#Combobox.editable) | `Boolean` | Determines if the Combobox is editable. That is, if it allows the user to type inside the input field. Set it true to allow it, false otherwise. | | [`fieldLabel`](/api/#Combobox.fieldLabel) | `String` | Defines a label for the Combobox. It will be shown at the left of the Combobox, by default. | | [`getValue`](/api/#Combobox.getValue) | `function() : String` | Returns the currently selected value (the text of the chosen `data` entry). Call it on the component (`Ext.getCmp(id)` or a `getid=` reference); `inputs.id[ID]` already holds the same value. | | [`hideLabel`](/api/#Combobox.hideLabel) | `Boolean` | Defines if the label of the Combobox should be displayed. Set true to hide the label, false to show it. | | [`id`](/api/#Combobox.id) | `String` | Defines the id to identify the object. | | [`labelStyle`](/api/#Combobox.labelStyle) | `String` | Defines the style of the label. You can use CSS to style the label element. | | [`onSelect`](/api/#Combobox.onSelect) | `function` | Defines a callback run when the user picks an entry. It receives the Ext `select` event arguments `(combo, record, index)` — read the chosen text with `record.get('value')` — and `this` is the layer. The value is resolved as a key of the layer `functions`… | | [`setValue`](/api/#Combobox.setValue) | `function(value)` | Selects an entry from code. Pass one of the `data` values; it does not fire `select`, so call `forceRecalc()` on an InputManager (or fire the event) when the layer must be recalculated. @param value {String} One of the values listed in `data`. | | [`value`](/api/#Combobox.value) | `String` | Value stored in `inputs.id[ID]` (and `inputs[i]`): the selected entry of `data` as a string (the first entry is selected initially). The layer recalculates on the combobox `select` event (user choice). | | [`width`](/api/#Combobox.width) | `Number` | Defines the width of the combobox in pixels. | Full descriptions, defaults and examples: [Combobox in the API reference](/api/#category_Combobox). ## FileField — filefield · open a local file (input) Tool that allows handle and local files. PS: This object cannot be sent to 'expression'. Usage: {{filefield\|fieldLabel=loadshp\|id=loadshp\|_onChange=function(){alert('changed')}}} | Name | Type | Description | |---|---|---| | [`eventNames`](/api/#FileField.eventNames) | `Array.` | Defines the list of events by name. Use this property to define callback functions to any of the following events. | | [`fieldLabel`](/api/#FileField.fieldLabel) | `String` | Defines the label shown at the left of the file input (Ext `fieldLabel`). `hideLabel=true` removes the label and its reserved space; other `Ext.form.Field` configs are passed through unchanged. | | [`hideLabel`](/api/#FileField.hideLabel) | `Boolean` | Set true to hide the label element and the space reserved for it. | | [`id`](/api/#FileField.id) | `String` | Defines the id of the input; it is the key used in `inputs.id[ID]` and the id of the Ext field (`Ext.getCmp(id)`), so it must be unique in the page. | | [`ignoreUpdate`](/api/#FileField.ignoreUpdate) | `Boolean` | Defines if it should ignore the widget change event. If it's false, it dispatches the update event at every file selection. | | [`inputType`](/api/#FileField.inputType) | `String` | The HTML input type. It is always forced to `file` by the tool, so a value written in the markup is ignored (documented only to explain why it cannot be changed). | | [`value`](/api/#FileField.value) | `function` | Value stored in `inputs.id[ID]`: not the file itself but a getter function. Call it — `inputs.id[ID]()` — to obtain the selected `File` (the first entry of the DOM `files` list) or `undefined` when nothing is selected. It is a function so the value can never… | Full descriptions, defaults and examples: [FileField in the API reference](/api/#category_FileField). ## Hoverpixel — hoverpixel · value under the mouse (input) Create a tool to instantly inspect pixel under mouse. The value of the map can also be used as input for another functions. Usage: {{hoverpixel}} | Name | Type | Description | |---|---|---| | [`checked`](/api/#Hoverpixel.checked) | `Boolean` | Defines if the hoverPixel should start enabled. Set true to start enabled, false otherwise. | | [`fieldLabel`](/api/#Hoverpixel.fieldLabel) | `String` | Define the text that will be displayed at the left of the toggler | | [`getLayerValues`](/api/#Hoverpixel.getLayerValues) | `function(evt, layer) : Array.\|null` | Reads the values of the composed map under a mouse event: one value per inner layer (from the legend colours of the rendered tiles) plus one extra entry with the result of the layer `expression` for those values. This is the `layerVals` argument of… | | [`hideLabel`](/api/#Hoverpixel.hideLabel) | `Boolean` | Defines if the label of the HoverPixel should be displayed. Set true to hide the label, false to show it. | | [`iconCls`](/api/#Hoverpixel.iconCls) | `String` | Defines the CSS class of the toggle switch icon; replace the default to restyle the switch. | | [`id`](/api/#Hoverpixel.id) | `String` | Defines the id to identify the object. | | [`labelBefore`](/api/#Hoverpixel.labelBefore) | `Boolean` | Set true to render the `text` label before (left of) the toggle switch instead of after it. | | [`labelStyle`](/api/#Hoverpixel.labelStyle) | `String` | Defines the style of the label at the HoverPixel toggler. You can use CSS to style the label element. | | [`notify`](/api/#Hoverpixel.notify) | `Boolean` | Set false to suppress the notification shown when the tool is activated ("click on the map..."). | | [`runOnClick`](/api/#Hoverpixel.runOnClick) | `function` | Defines a callback when the user clicks on the map. It passes the following parameters for the callback function: handleOnClick(layerVals, inputs, coordinates, clickEvent, lastCoordinates) @param layerVals {Array} Array with the values of the maps at the… | | [`runOnClickOutside`](/api/#Hoverpixel.runOnClickOutside) | `function` | True to run the callback function even when clicking outside of the layer, False to disable. (Default False) | | [`runOnHover`](/api/#Hoverpixel.runOnHover) | `function` | Defines a callback when the user hovers the map. It passes the following parameters for the callback function: handleOnClick(layerVals, inputs, coordinates, clickEvent, lastCoordinates) @param layerVals {Array} Array with the values of the maps at the pixel… | | [`runOnHoverOutside`](/api/#Hoverpixel.runOnHoverOutside) | `function` | True to run the callback function even when hovering outside of the layer, False to disable. (Default False) | | [`text`](/api/#Hoverpixel.text) | `String` | Define the text that will be displayed at the right of the toggler | | [`unselect`](/api/#Hoverpixel.unselect) | `Boolean` | Only changes the activation message: with the default `true` it says a single point is expected, with `false` several. The hoverpixel is never deactivated automatically after a click. | | [`value`](/api/#Hoverpixel.value) | `Object` | Value stored in `inputs.id[ID]`: the `lastInfo` object `{click, hover}` with the coordinates (`{lon, lat}` in EPSG:4326, or `null` before the first event) of the last click and of the last mouse move while the tool is active. The object is updated in place,… | Full descriptions, defaults and examples: [Hoverpixel in the API reference](/api/#category_Hoverpixel). ## InputManager — inputmanager · values kept for your functions (input) 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}}' | Name | Type | Description | |---|---|---| | [`forceRecalc`](/api/#InputManager.forceRecalc) | `function()` | Force a legend map recalculation. | | [`getValue`](/api/#InputManager.getValue) | `function(key) : *` | Get the stored value by his property name, if it does not exists returns null. @param key {String} Stored property name. | | [`id`](/api/#InputManager.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). | | [`setDefaultValues`](/api/#InputManager.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. PS: Auxiliary function to make easy wrinting the script (typically called in `onInputsReady` or at the start… | | [`setValues`](/api/#InputManager.setValues) | `function(obj, cancelUpdate, local)` | 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… | | [`value`](/api/#InputManager.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 the `global` bucket where the stored properties live… | Full descriptions, defaults and examples: [InputManager in the API reference](/api/#category_InputManager). ## Label — label · text Create a simple label element to display some text. Usage: {{label\|}} | Name | Type | Description | |---|---|---| | [`cls`](/api/#Label.cls) | `String` | Extra CSS class(es) added to the `