API

Where to look. What you write in a layer is under Layers and Kinds of layer; in a group, under Groups; before the list, joined with &&, under Query setup; in the link, under Map links and embedding. Functions your code calls are the ExtjsUtils helpers, or the layer's own methods (this., under Kinds of layer).

property: a key you write · callback: a function you write and the platform calls · method: a function the layer has, called on this · helper: ExtjsUtils.NAME.member · setting: applies to the whole query · link parameter: ?name=value of a map link

Find anything: press / and type a name (opacity), the way code writes it (ExtjsUtils.ALERTIFY.confirmChoice, this.setCalculateLegend, {{slider, ?queryid) or a few words; Enter opens the entry. Every entry has a link (#) you can share. Not sure where something lives? Read Where to find it: layers, settings and links.

Layers: what you write in a layer

A layer is one entry of the query's list, between { }. Its source sets its kind: no source (a published map), "calculate", "file" or "xyz". The groups below are the keys and functions you write in a layer, and the buttons of its row.
Not every key works on every kind: calculated, file and tile layers have a panel (descriptionHtml) and row buttons (paramsButtonConfig), a published map does not. Each entry says when it is limited to some kinds; what one kind adds is under Kinds of layer.
A layer that shows one published map:
Example
[
   {
      // The Layer name
      title: 'My first layer!',

      // The map that will be shown
      name: 'CSR:altimetria',

      // Flag to make the map show on start
      visibility: true,
   },
]

Layer properties

LayersProperties31 entries
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.

categorical

Boolean= falseproperty# Switches the generated legend of a source: 'calculate' layer to categorical mode.

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. When false the values are grouped into at most maxQntEntries ranges coloured with the sequential (blue to red) palette. Use it when the expression returns classes (land use, geology, ...) instead of a continuous number.

[
  {
     title: 'Categorical result',
     color: '#FFA500',
     elements: [
        {
           title: 'One legend entry per geology class',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           updateAutomatically: true,
           categorical: true,
           expression: function(layersVals, inputs) {
              return layersVals[0];
           },
        },
     ],
  },
]

categoricalPalette

Array.<Array.<Number>>= 300 built-in coloursproperty# Colours of the legend entries of a categorical source: 'calculate' layer (see categorical), as an array of [R, G, B] triplets (0 to 255).

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 palette. When omitted a built-in 300-colour palette is used. The palette length is also the upper limit for maxQntEntries.

[
  {
     title: 'Custom categorical colours',
     color: '#FFA500',
     elements: [
        {
           title: 'Geology classes with a four colour palette',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           updateAutomatically: true,
           categorical: true,
           categoricalPalette: [[43, 3, 192], [126, 222, 20], [243, 99, 6], [34, 67, 2]],
           expression: function(layersVals, inputs) {
              return layersVals[0];
           },
        },
     ],
  },
]

description

String= 'XYZ Title' or 'Vector Title'property# Define the text that will be displayed when the mouse hover the Legend Window Title.

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'.

[
  {
     title: 'Example of description for XYZ map',
     color: '#666699',
     elements: [
        {
           title: 'This is the Layer Legend Window Title, hover me!',
           name: 'planet:planet',
           source: 'xyz',
           url: 'https://tiles.planet.com/basemaps/v1/planet-tiles/planet_medres_visual_2021-09_mosaic/gmap/${z}/${x}/${y}.png?api_key=PLAK78456687760442eaa3d3da16aaac5f2d',
           visibility: true,
           description: 'Hover the Layer Title',
        },
     ],
  },
]

descriptionHtml

String= string.emptyproperty# Define the content that will be displayed at the Query section ("Exibir Consulta" button).

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 published map (no source, source: 'local' or a server added with addRemoteWMSServer) it is ignored.

[
  {
     title: 'Example of descriptionHTML',
     color: '#FFA500',
     elements: [
        {
           title: 'This Layer has a custom descriptionHTML',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           paramsButtonConfig: [
              {
                 type: 'query',
                 pressed: true
              },
           ],
           descriptionHtml:
              '<p>You can use HTML tags</p>'
              +
              '{{label|text=Or the tools from Mappia:}}'
              +
              '{{button|text=I\'m a button from Mappia}}',
        },
     ],
  },
]

See also You can find more information about the tools available for use in: Tools Section.

disabledAttributes

String= nullproperty# Define which styles will be hidden in the Style Chooser Combobox from Layers that has the 'source' property as 'local'.

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 number of the style. (<map_name>_<number>). You can hide more than one style. For this you only need to separate their names by commas.

[
  {
     title: 'Example of disabledAttributes',
     color: '#666699',
     elements: [
        {
           title: 'This Layer hides the styles \'Mapa geológico\' and \'Tempo geológico\' from the styles choose combobox',
           name: 'CSR:geologia',
           source: 'local',
           visibility: true,
           // geologia_2 is the style 'Tempo geológico'
           // geologia_1 is the style 'Mapa geológico'
           // The 'disabledAttributes' property is used to hide the styles from the styles chooser combobox
           // All styles that are hidden must be separated by commas
           disabledAttributes: 'geologia_2,geologia_1',
        },
     ],
  },
]

exclusiveGroupDetails

String= string.emptyproperty# Define a name for a Layer Details.

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.

[
  {
     viewTitle: 'Only one Legend can be open each time',
     title: 'Example of exclusiveGroupDetails',
     color: '#666699',
     elements: [
        {
           title: 'Layer 1',
           name: 'CSR:estados',
           source: 'calculate',
           exclusiveGroupDetails: 'ExampleName',
           visibility: true,
        },
        {
           title: 'Layer 2',
           name: 'CSR:rios_principais',
           source: 'calculate',
           exclusiveGroupDetails: 'ExampleName',
           visibility: true,
        },
        {
           title: 'Layer 3',
           name: 'CSR:geologia',
           source: 'calculate',
           exclusiveGroupDetails: 'ExampleName',
           visibility: true,
        },
     ],
  },
]

extents

Array.<Numeric>= Array.emptyproperty# Define which tiles will be used to render the map.

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, maxX, maxY].

// Play around with the maps visibility to check the regions defined by the extents.
[
  {
     title: 'Example of extents',
     color: '#FFA900',
     elements: [
        {
           title: 'Restricted extents',
           name: 'CSR:altimetria',
           visibility: true,
           // Follows the order [minX, minY, maxX, maxY]
           extents: [-48.5, -14.5, -46.0, -13.0],
        },
        {
           title: 'Restricted extents 2',
           name: 'CSR:altimetria',
           visibility: true,
           // Follows the order [minX, minY, maxX, maxY]
           extents: [-43.9, -19.8, -43.1, -18.9],
        },
        {
           title: 'This Layer displays the hole map',
           name: 'CSR:altimetria',
           // This extents render the whole world.
           extents: [-180.0000, -90.0000, 180.0000, 90.0000],
           startListed: true,
        },
     ],
  },
]

global

Objectproperty# 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.

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 ExtjsUtils.QUERY.setQueryGlobalProperties({...}) && [...] chain at the top of the query; the production survey found no query using this key (zero users).

[
  {
     title: 'Group',
     elements: [
        {
           title: 'Layer with its own globals',
           name: 'CSR:estados',
           source: 'local',
           visibility: true,
           global: {
              statesLoaded: function() { ExtjsUtils.ALERTIFY.log('States ready'); }
           }
        }
     ]
  }
]

hideLegendButton

Boolean= falseproperty# Hides the legend of the layer in its Legend Window.

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 the generated legend container (with the legend title and the opacity slider) and the "show legend" button at the bottom of the query section, so only the descriptionHtml remains.

[
  {
     title: 'Hiding the Legend Button',
     color: '#FFA500',
     elements: [
        {
           title: 'The Layer Legend Button will be hidden',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           hideLegendButton: true,
           descriptionHtml:
              '{{label|text=The legend button is hidden, only the descriptionHtml is visible}}',
        },
     ],
  },
]

hideListing

Boolean= falseproperty# 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.

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.

[
  {
     title: 'A Group with 3 Layers, but one is hidden',
     color: '#FFA500',
     elements: [
        {
           title: 'Map of the altitude in Brazil',
           name: 'CSR:altimetria',
           source: 'local',
        },
        {
           title: 'This Layer will be hidden at the Group list',
           name: 'CSR:rios_principais',
           source: 'local',
           hideListing: true,
        },
        {
           title: 'Map of the geology in Brazil',
           name: 'CSR:geologia',
           source: 'local',
        },
     ],
  },
]

hideMetadata

Boolean= falseproperty# If true, hides the metadata button in the Legend Window for this layer.

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 this button when their paramsButtonConfig has a {type: 'metadata'} entry.

[
  {
     title: 'Hiding the metadata button',
     color: '#FFA500',
     elements: [
        {
           title: 'This Layer has no metadata button',
           name: 'CSR:geologia',
           source: 'local',
           visibility: true,
           hideMetadata: true,
        },
     ],
  },
]

hideStyleChooser

Boolean= falseproperty# 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'.

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'.

[
  {
     title: 'Example with hidden style Combobox',
     color: '#FFA500',
     elements: [
        {
           title: 'Map of the geology in Brazil',
           name: 'CSR:geologia',
           source: 'local',
           visibility: true,
           startLegendOpen: true,
           hideStyleChooser: true,
        },
     ],
  },
]

hideTilePlaceholder

Boolean= falseproperty# Removes the stretched placeholder tile that is shown while the real tiles load (the OpenLayers resize transition).

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 stretched before the new one appears. Applies to local and calculate layers; a composed layer also passes it on to the maps replaced with changeLayers.

[
  {
     title: 'No stretched tiles while loading',
     color: '#FFA500',
     elements: [
        {
           title: 'Map of the geology in Brazil',
           name: 'CSR:geologia',
           source: 'local',
           visibility: true,
           hideTilePlaceholder: true,
        },
     ],
  },
]

insideOpacity

Array.<Numeric>= [1, 1, 1, ...]property# Defines the opacity for the maps defined in the 'name' property.

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 'insideOpacity' array will define the opacity for the first map defined in the 'name' property, the second value is the opacity for the second map, and so on. The opacity value is a number between 0 and 1. 0 being transparent and 1 opaque.

[
  {
     title: 'Example of insideOpacity',
     color: '#666699',
     elements: [
        {
           name: 'CSR:estados,CSR:rios_principais,CSR:geologia',
           source: 'calculate',
           // The values are applied to the layers in the same order as they are defined in the name property. So the CSR:estados map has the opacity of 0.5, the CSR:rios_principais map has the opacity of 1, and the CSR:geologia map has the opacity of 0.7.
           insideOpacity: [0.5, 1, 0.7],
           visibility: true,
        },
     ],
  },
]

legendTitle

String= string.emptyproperty# Defines the text that will be displayed at the top of the 'legendhtml tool' declared at the 'descriptionHtml' property

Defines the text that will be displayed at the top of the 'legendhtml tool' declared at the 'descriptionHtml' property

[
  {
     title: 'Example custom legend title',
     color: '#FFA500',
     elements: [
        {
           title: 'Map of the geology in Brazil',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           legendTitle: 'This is a custom legend title',
           descriptionHtml:
              '{{legendhtml}}',
        },
     ],
  },
]

maxQntEntries

Number= 18property# 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.

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 active palette. PS: the automatic grouping currently always uses the built-in limit of 18, so a custom value is kept on the layer but does not change the generated legend. Use setCalculateLegend() when you need full control over the legend entries.

{
   name: 'CSR:altimetria',
   source: 'calculate',
   maxQntEntries: 10,
   expression: function(layersVals, inputs) {
      return layersVals[0];
   },
}

name

String= string.emptyproperty# Defines the maps that will be a part of the Layer.

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 that can be used: http://maps.csr.ufmg.br/geonetwork/srv/por/search. You can find their name at the section "Visão geral do mapa" under its image. Those maps have the prefix "CSR:" before their names. Maps can also be uploaded by you. For that, you just need to define the 'source' property as 'file'.

[
  {
     title: 'A Group with two maps',
     color: '#FFA500',
     elements: [
        {
           title: 'This Layer has two maps!',
           // Each map is separated by commas
           // The first map is CSR:rios_principais that have the rivers of Brazil
           // The second map is CSR:estados that show the states of Brazil
           name: 'CSR:rios_principais,CSR:estados_cf',
           visibility: true,
        },
     ],
  },
]

opacity

Numeric= 1property# Define the opacity of the Layer.

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.

[
 {
   title: 'Example of opacity in a Layer',
   color: '#666699',
   elements: [
     {
       title: 'This Layer has its opacity set to 50% of the original visibility',
       name: 'CSR:geologia',
       source: 'local',
       visibility: true,
       opacity: 0.5,
     },
   ],
 },
]

otherNames

Stringproperty# Defines additional maps to be available for the query, which will be listed in the filtered stored capabilities.

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 the 'capabilities' url option, which filters the 'GetCapabilities' response with only the maps included in layer definition. (Performance Optimization, faster loading). PS2: This property is only needed outside of the editor mode.

{
     name: "CSR:estados,CSR:airports",
     otherNames: "CSR:municipios,CSR:rodovias",
     beforeCalc: function(layerVals, inputVals) {
         this.changeLayers([{name: 'CSR:municipios', styles: fMapName + "_1", index: 0},
             {name: 'CSR:rodovias', styles: 'rodovias_1', index: 1}]);
     }
  }

  Function 'changeLayers' needs the definition of the 4 maps: 'estados', 'airports', 'municipios' and 'rodovias'.
  If the 'otherNames' is not defined, only the maps defined at 'name' property will be available.
Applies to calculated layers (`source: 'calculate'`), the ones that swap maps with `changeLayers`.

priority

Number= 0property# Defines the order of which map will be rendered on top of the others.

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'.

[
  {
     title: 'At the bottom will be the geology, then the states and at top the rivers',
     color: '#FFA500',
     elements: [
        {
           title: 'Map of the states in Brazil',
           name: 'CSR:estados',
           source: 'local',
           priority: 2,
           visibility: true,
        },
        {
           title: 'Map of the rivers in Brazil',
           name: 'CSR:rios_principais',
           source: 'local',
           priority: 3,
           visibility: true,
        },
        {
           title: 'Map of the geology in Brazil',
           name: 'CSR:geologia',
           source: 'local',
           priority: 1,
           visibility: true,
        },
     ],
  },
]

showLoadingModal

Boolean= falseproperty# Shows the "generating legend" loading mask visibly over the page while the layer is paused (calculating or loading a resource).

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 while the layer is visible. Applies to calculate and file layers.

[
  {
     title: 'Visible loading mask',
     color: '#FFA500',
     elements: [
        {
           title: 'A slow calculation with a visible loading mask',
           name: 'CSR:altimetria',
           source: 'calculate',
           visibility: true,
           updateAutomatically: true,
           showLoadingModal: true,
           expression: function(layersVals, inputs) {
              return layersVals[0];
           },
        },
     ],
  },
]

showRemoveBtn

Boolean= falseproperty# Defines it the remove button at the top right of the Layer Legend Window show be displayed.

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.

[
  {
     title: 'Hiding the remove button',
     color: '#FFA500',
     elements: [
        {
           title: 'The \'X\' button at the top right of this Layer removes this map',
           name: 'CSR:rios_principais',
           source: 'local',
           visibility: true,
        },
        {
           title: 'There is no button to remove the this map',
           name: 'CSR:estados',
           source: 'local',
           visibility: true,
           showRemoveBtn: false,
        },
     ],
  },
]

source

String= 'local'property# Defines the source from where the maps declared at the name will be loaded from.

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 map in the expression() function and the result will be displayed as the Layer

  • 'file': The map will be loaded from a file or other custom source. For this, you need to define the file type in the 'type' property and the file where the map should be loaded. For example, for a JSON file, you also need to define the 'json' property.

  • 'xyz': The map will be loaded from an url by the XYZ protocol. The url property is required for this type of source. You can find more informations about the XYZ protocol at: https://developers.planet.com/docs/basemaps/tile-services/xyz/

// Example of how to load a map with the local source
[
  {
     title: 'Map rendered by a local source',
     color: '#666699',
     elements: [
        {
           title: 'Map with local source',
           name: 'CSR:paises',
           source: 'local',
           visibility: true,
        },
     ],
  },
]
// Example of how to load a map with the calculated source
[
  {
     title: 'Map rendered based on calculation',
     color: '#666699',
     elements: [
        {
           title: 'Filtering a part of the map',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           updateAutomatically: true,
           expression: function(layersVals, inputs) {
              // layerVals have the value of the legend applied in every pixel of the map
              let mapValue = layersVals[0];

              // Remove every type of relief that is not 'Mantiqueira'
              if(mapValue != 'Mantiqueira') { // If the pixel is not 'Mantiqueira'
                 return undefined; // Don't show the pixel
              }

              // If the pixel is 'Mantiqueira', return the value of the pixel
              return mapValue;
           },
        },
     ],
  },
]
// Example of how to load a map with the file source
[
  {
     title: 'Map rendered based on file source',
     color: '#FFA500',
     elements: [
        {
           title: 'Map with file source',
           name: 'example:map_file_source',
           source: 'file',
           visibility: true,
           // The map is rendered based on the GeoJSON below
           // The GeoJSON needs to be in EPSG:3857
           json: JSON.stringify(
              {
                 "type": "Polygon",
                 "crs": {
                    "type": "name",
                    "properties": {
                       "name": "EPSG:3857"
                    }
                 },
                 "coordinates": [
                    [
                       [
                          -625570.6,
                          6465993.0,
                       ],
                       [
                          -305006.9,
                          6696510.8,
                       ],
                       [
                          -546330.2,
                          6768547.6,
                       ],
                       [
                          -445478.6,
                          7053093.0,
                       ],
                       [
                          -279794.0,
                          7056694.8,
                       ],
                       [
                          -359034.5,
                          7337638.4,
                       ],
                       [
                          -211359.0,
                          7485313.8,
                       ],
                       [
                          62380.8,
                          6955843.3,
                       ],
                       [
                          220861.7,
                          6909019.4,
                       ],
                       [
                          91195.5,
                          6700112.6,
                       ],
                       [
                          213658.1,
                          6682103.4,
                       ],
                       [
                          -625570.6,
                          6465993.0,
                       ],
                    ],
                 ],
              }
           ),
        },
     ],
  },
]
// Example of how to load a map with the XYZ source
// The XYZ source is used to load a map from a URL that contains the &lcub;z&rcub;, &lcub;x&rcub; and &lcub;y&rcub; placeholders
// The &lcub;z&rcub; is the zoom level, &lcub;x&rcub; is the longitude and &lcub;y&rcub; is the latitude
[
  {
     title: 'Map rendered by a XYZ source',
     color: '#666699',
     elements: [
        {
           title: 'Base map loaded by XYZ source',
           // The name of the map that will be added. This name must be unique
           name: 'planet:planet',
           source: 'xyz',
           // The url of the map that will be loaded. The $&lcub;z&rcub;, $&lcub;x&rcub; and $&lcub;y&rcub; placeholders will be replaced by the map library
           url: 'https://tiles.planet.com/basemaps/v1/planet-tiles/planet_medres_visual_2021-09_mosaic/gmap/$&lcub;z&rcub;/$&lcub;x&rcub;/$&lcub;y&rcub;.png?api_key=PLAK78456687760442eaa3d3da16aaac5f2d',
           visibility: true,
        },
     ],
  },
]

startLegendOpen

Boolean= falseproperty# Defines if the Legend Window should start or not.

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 and tile (xyz) layers ignore it: their details already start open, and paramsButtonConfig: [{type: 'query', pressed: true}] makes them start on the layer's panel instead.

[
  {
     title: 'The Legend Window the Layer will start open',
     color: '#FFA500',
     elements: [
        {
           title: 'This Layer Legend Window will start open',
           name: 'CSR:geologia',
           source: 'local',
           startLegendOpen: true,
           visibility: true,
        },
     ],
  },
]

startListed

Boolean= falseproperty# Define if the Layer should start with its Legend Window visible or not.

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 Layer.

[
  {
     title: 'The Legend Window of the third Layer will start visible',
     color: '#FFA500',
     elements: [
        {
           title: 'Map of the altitude in Brazil',
           name: 'CSR:altimetria',
           source: 'local',
        },
        {
           title: 'Map of the rivers in Brazil',
           name: 'CSR:rios_principais',
           source: 'local',
        },
        {
           title: 'This Layer Legend Window will start visible, but is not map',
           name: 'CSR:geologia',
           source: 'local',
           startListed: true,
        },
     ],
  },
]

styles

String= string.emptyproperty# Defines which styles will be applied over the maps defined at the 'name' property.

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 to the first map, the second to the second map, and so on. A style's Mappia identifier is the map name without its namespace plus _ and an index (estados published with two styles gives estados_0 and estados_1), and the styles a map really offers are the ones its published capabilities declare: open the layer's style chooser in the interface to see and pick them, or read the Style entries of the map in the WMS capabilities. Styles are created when the map is published (a QGIS style file is converted at publication time), not by the query. PS: Styles are separated by comma, one per map in name, in the same order.

[
  {
     title: 'Example of style',
     color: '#666699',
     elements: [
        {
           name: 'CSR:precip_monthly_average,CSR:precip_monthly_average',
           // The first style 'precip_monthly_average_1' is applied to the first map 'precip_monthly_average' and the second style 'precip_monthly_average_2' is applied to the second map 'precip_monthly_average'
           styles: 'precip_monthly_average_1,precip_monthly_average_2',
           // The source needs to be calculate to apply the style
           source: 'calculate',
           visibility: true,
        },
     ],
  },
]
{
       ...,
         name: 'CSR:municipios',
         style: 'municipios_0',
       ...
  }
{
       ...,
         name: 'CSR:estados,CSR:geologia',
         style: 'estados_0,geologia_1',
       ...
  }

thumbUrl

String= undefinedproperty# Define the thumbnail image that is displayed when the mouse hovers the Legend Window title.

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: 'Example of thumbUrl',
     color: '#FFA900',
     elements: [
        {
           title: 'There is a puppy hidden in here! Hover me! <3',
           name: 'CSR:altimetria',
           visibility: true,
           thumbUrl: 'https://fastly.picsum.photos/id/237/200/300.jpg?hmac=TmmQSbShHz9CdQm0NkEjx1Dyh_Y984R9LpNrpvH2D_U',
        },
     ],
  },
]

title

String= 'layer_name' The default value is the layer name.property# 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.

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.

[
  {
     title: 'The title of the Group shows up at the top center of the screen and has a List inside it.',
     color: '#FFA500',
     elements: [
        {
           title: 'The title of the Layer is shown at the Legend Window and inside the menu of the Group name.',
           name: 'CSR:capitals',
           visibility: true,
        },
     ],
  },
]

updateAutomatically

Boolean= falseproperty# Decides what happens when the reader changes an input of the layer's panel (a widget in descriptionHtml).

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 one calculation. The layer is drawn either way. Applies to calculated and file layers.

[
 {
   title: 'The map will be automatically calculated',
   color: '#666699',
   elements: [
     {
       title: 'This layer is showing just one type of relief',
       name: 'CSR:geologia',
       source: 'calculate',
       visibility: true,
       updateAutomatically: true,
       expression: function(layersVals, inputs) {
         // layerVals have the value of the legend applied in every pixel of the map
         let mapValue = layersVals[0];

         // Remove every type of relief that is not 'Mantiqueira'
         if(mapValue != 'Mantiqueira') { // If the pixel is not 'Mantiqueira'
             return undefined; // Don't show the pixel
         }

         // If the pixel is 'Mantiqueira', return the value of the pixel
         return mapValue;
       },
     },
   ],
 },
]

viewColor

Stringproperty# HTML color to use on the group.

HTML color to use on the group.

[{
viewColor: "#FFFFFF",
viewTitle: "DADOS BASE",
color: "#FF000F",
elements: [
  {name: 'CSR:AMAZONIA_limite', showRemoveBtn: false, visibility: true,
    hideListing: true, startListed: true, priority: 10000}
]}]

visibility

Boolean= falseproperty# Define if the Layer should start visible or not.

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.

[
 {
   title: 'Example of visibility in a Layer',
   color: '#666699',
   elements: [
     {
       title: 'This layer will start visible',
       name: 'CSR:geologia',
       source: 'local',
       visibility: true,
     },
   ],
 },
]

More layer properties

ConfigLayer14 entries
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).

attribution

Stringproperty# Recognizes someone as the platform author, showing in the "Powered by: {insert name}".

Recognizes someone as the platform author, showing in the "Powered by: {insert name}".

customLayerClass

String= string.emptyproperty# 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.

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 node instead (GroupProperties.customLayerClass).

[
  {
     title: 'Styled layer row',
     color: '#FFA500',
     elements: [
        {
           title: 'This row has a custom background',
           name: 'CSR:geologia',
           source: 'local',
           visibility: true,
           customLayerClass: 'highlighted-layer',
        },
     ],
  },
]

group

Stringproperty# 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.

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: [...] } objects). To let only one of several layers be visible at a time, use toggleGroup.

[{visibility: true, group: "background", name: "CSR:planet_brasil_2024", priority: 5}]

maxExtent

OpenLayers.Boundsproperty# Defines a geographical limit for a map rendering.

Defines a geographical limit for a map rendering.

maxZoom

Numericproperty# Defines the limit of the real max zoom of a given layer.

Defines the limit of the real max zoom of a given layer. When map zoom exceed this, the image is reused and stretched.

maxscale

Numericproperty# Defines the limit of the real max scale of a given layer.

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

string|nullproperty# Defines the url to show custom layers metadata information.

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

Numericproperty# Defines the limit of the real min scale of a given layer.

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

Boolean= falseproperty# Defines if the group starts opened, even without any visible layers.

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 layer it expands every viewTitle ancestor of the layer (see GroupProperties.openGroup).

operation

String= string.emptyproperty# Defines how the pixels of each map of a source: 'calculate' layer are decoded into the values that expression() receives in layersVals.

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 the default decoding (for example 'raw,,sum' leaves the second map on the default). Tokens are case and whitespace insensitive. The accepted tokens (see RawMaps.operations for the full description of each one) are:

  • (empty or unknown): NORMAL, the regular WMS image, each pixel is a legend colour/category.
  • raw: the value of the most centred original cell of the region covered by the pixel.
  • rgba: the RGBA bytes of the pixel packed as one integer.
  • sum: area-weighted sum of the covered cells.
  • average: area-weighted mean of the covered cells.
  • max / min: largest / smallest cell at least partially covered.
  • 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 covered region.
  • cells: weighted count of original cells inside the covered region. Every token other than the default and rgba requires the map to be published as a Raw Map offering that operation; otherwise the console logs Error: Operation X is not defined for layer Y.
[
  {
     title: 'Population from raw maps',
     color: '#FFA500',
     elements: [
        {
           title: 'Total population of each pixel',
           // The same raw map is stacked twice, read with two different operations,
           // and the states map keeps the default decoding (empty token).
           name: 'CSR:pop_density_estimate_2015,CSR:estados,CSR:pop_density_estimate_2015',
           operation: 'average,,area',
           source: 'calculate',
           visibility: true,
           updateAutomatically: true,
           descriptionHtml: '{{hoverpixel}}',
           expression: function(layersVals, inputs) {
              var density = layersVals[0]; // people per km2 (area-weighted mean)
              var stateName = layersVals[1]; // legend value of the regular WMS map
              var areaKm2 = layersVals[2]; // area of the original cells covered by this pixel
              return density * areaKm2;
           },
        },
     ],
  },
]

shouldKeepRecord

Boolean= trueproperty# Defines what the 'X' (remove) button of the Legend Window does (see showRemoveBtn).

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 is removed from the map for good.

[
  {
     title: 'Removing a layer for good',
     color: '#FFA500',
     elements: [
        {
           title: 'The X button removes this map from the query',
           name: 'CSR:rios_principais',
           source: 'local',
           visibility: true,
           shouldKeepRecord: false,
        },
     ],
  },
]

toggleGroup

Stringproperty# Places a layer in a group of layers with mutually exclusive visibility.

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.

[{name: "CSR:estados": toggleGroup:"political_division"},
{name: "CSR:paises": toggleGroup:"political_division"}
]

useLayerTooltip

Boolean|Numberproperty# If false, the layer tooltip is not shown.

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

Boolean= falseproperty# 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 …

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 horizontal opacity slider. Usually used together with customLayerClass.

[
  {
     title: 'Compact Legend Window',
     color: '#FFA500',
     elements: [
        {
           title: 'The layer options are in a vertical menu',
           name: 'CSR:geologia',
           source: 'local',
           visibility: true,
           verticalMenu: true,
           customLayerClass: 'my-compact-layer',
        },
     ],
  },
]

Layer callbacks: functions you write

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

afterCalc

function= nullcallback# This function is executed right after the 'expression()' calculations.

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.

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

beforeCalc

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

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

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

expression

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

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

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

Returns Value of each processed pixel.

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

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

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

functions

Object= null# Associate custom functions to handle events on layer callbacks such as button callbacks or any layer callbacks.

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 this.functions['<function_name>'].

[
  {
     title: 'Example of functions property',
     color: '#666699',
     elements: [
        {
           title: 'Click the button to see a message',
           name: 'CSR:geologia',
           group: 'Query',
           source: 'calculate',
           visibility: true,
           paramsButtonConfig: [
              { 
                 type:'query',
                 pressed: true,
              },
           ],
           descriptionHtml:
              '{{button|id=test_button|text=Click me!|handler=handleTestButtonClick}}',
           functions: {
              handleTestButtonClick: function() {
                 ExtjsUtils.ALERTIFY.log('Button clicked!');
              },
           },
        },
     ],
  },
]

legendColor

functioncallback# This function generates the color of each value/category of the calculated map generated by the 'expression()' 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.

color Array.<Numeric>
Array with three numbers (0 to 255) that define the RGB color of the original legend.
inputs Array.<Object>
The value of each input defined in the descriptionHtml. The order of the values is the same as the inputs (i.e. the first input in the descriptionHtml is inputs[0], the second is inputs[1] and so on).
lastValue String
The last legend value that had its color calculated.
currentValue String
The actual legend value that it's being calculated.
ruleIndex Numeric
The index of the actual legend value that it’s being calculated. I.e. The first legend value is 0, the second is 1, and so on.

Returns The new color to the value in [R,G,B] format.

[
  {
     title: 'Example of legendColor',
     color: '#666699',
     elements: [
        {
           title: 'The legendColor function will generate a custom color for each category, based on its value',
           name: 'CSR:altimetria',
           source: 'calculate',
           updateAutomatically: true,
           visibility: true,
           expression: function(layersVals, inputs) {
              return layersVals[0];
           },
           // This create a custom colors palette for the legend of the result map from the 'expression' function
           legendColor: function(color, inputs, lastValue, currentValue, ruleIndex) {
              let red = 0;
              let green = currentValue * 255 / 1830;
              let blue = 0;
              
              return [red, green, blue];
           },
        },
     ],
  },
]

onInputsReady

function= nullcallback# This function is called when all inputs have been loaded and are ready.

This function is called when all inputs have been loaded and are ready. Even from Layers that aren’t visible.

inputs Array
The value of each input defined in the descriptionHtml. The order of the values is the same as the inputs (i.e. the first input in the descriptionHtml is inputs[0], the second is inputs[1] and so on).
[
  {
     title: 'Example of onInputsReady function',
     color: '#666699',
     elements: [
        {
           title: 'This Layer shows the starting value of the text input field',
           name: 'CSR:geologia',
           group: 'Query',
           source: 'calculate',
           visibility: true,
           paramsButtonConfig: [
              { 
                 type:'query',
                 pressed: true,
              },
           ],
           descriptionHtml: 
              '{{textfield|id=textInput|fieldLabel=Message|value=I love maps!|labelStyle=text-align:center;}}',
           onInputsReady: function(inputs) {
              let textInputValue = inputs[0];
              ExtjsUtils.ALERTIFY.log('The text input initial value is: ' + textInputValue);
           },
        },
     ],
  },
]

onVisibilityChange

function= nullcallback# This function is called whenever a Layer changes its visibility.

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.

visibility Boolean
It’s true if the Layer is visible or false otherwise.
inputs Object
The value of each input defined in the descriptionHtml. The order of the values is the same as the inputs (i.e. the first input in the descriptionHtml is inputs[0], the second is inputs[1] and so on).
[
  {
     title: 'Example of callback when changing the visibility',
     color: '#FFA500',
     elements: [
        {
           title: 'The function onVisibilityChange will be called when the visibility of this layer changes.',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           paramsButtonConfig: [
              {
                 type:"query",
                 pressed: true
              },
           ],
           descriptionHtml:
              '{{label|text=You can change the map visibility by clicking at the eye icon on the top of this window}}',
           onVisibilityChange: function(state, inputs) {
              if(state) {
                 ExtjsUtils.ALERTIFY.log('The layer is now visible');
              }
              else {
                 ExtjsUtils.ALERTIFY.log('The layer is now hidden');
              }
           },
        },
     ],
  },
]

Row buttons (paramsButtonConfig)

paramsButtonConfigProperties8 entries
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.

enableToggle

Boolean= trueproperty# 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).

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 toggle button makes it a toggle), so your value only counts while the widget does not exist.

paramsButtonConfig: [{ type: 'associated', associatedButtonID: 'my_button', enableToggle: false }]

hideBottomButton

Boolean= falseproperty# 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").

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 of type: 'query' (or in the bare object form of paramsButtonConfig, which is treated as the query entry); a hideBottomButton written directly on the layer or in a group's defaultProperties is ignored.

[
  {
     title: 'Example of paramButtonConfig hideBottomButton property',
     color: '#FFA500',
     elements: [
        {
           title: 'The buttons at the bottom of the Legend Window are hidden',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           descriptionHtml:
              '{{label|text=There are no buttons in here}}',
           paramsButtonConfig: [
              {
                 type: 'query',
                 hideBottomButton: false,
              },
           ],
        },
     ],
  },
]

hideButton

Boolean= falseproperty# Define if the associated button should be hidden.

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'

[
  {
     title: 'Example of paramButtonConfig hideButton property',
     color: '#FFA500',
     elements: [
        {
           title: 'The query button in hidden',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           paramsButtonConfig: [
              { 
                 type: 'query',
                 hideButton: true,
              },
           ],
        },
     ],
  },
]

iconCls

String= string.emptyproperty# Define a class that will be added to the html in the associated button.

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)
  • 'gxp-icon-removelayers' is the icon of the Remove Layer Button (The second icon on the Legend Window, from left to right)
  • 'gxp-icon-parameters-expand' is the icon of the Show Query Button (The third icon on the Legend Window, from left to right)
  • 'gxp-icon-legend-expand' is the icon of the Show Legend Button (The forth icon on the Legend Window, from left to right)
  • 'gxp-icon-downloadmapbutton' is the icon of the Download Button (The fifth icon on the Legend Window, from left to right)
[
  {
     title: 'Example of paramButtonConfig iconCls property',
     color: '#A020F0',
     elements: [
        {
           title: 'The query button is the download icon:',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           descriptionHtml:
              '{{label|text=Here is the query region}}',
           paramsButtonConfig: [
              { 
                 type: 'query',
                 tooltip: 'This is actually the query button',
                 // Here you can add any class you choose
                 iconCls: 'gxp-icon-downloadmapbutton',
              },
           ],
        },
     ],
  },
]

pressed

Boolean= falseproperty# Defines if the button should start pressed or not.

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 instead of the Legend region. This property applies only to the types: 'query',

[
  {
     title: 'Example of paramButtonConfig pressed property',
     color: '#A020F0',
     elements: [
        {
           title: 'The param button config set the query button to be pressed at the start',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           descriptionHtml:
              '{{label|text=The region of the descriptionHtml will start opened}}',
           paramsButtonConfig: [
              { 
                 type: 'query',
                 pressed: true,
              },
           ],
        },
     ],
  },
]

toggleGroup

String= string.emptyproperty# Defines a group for all the buttons that has the same toggleGroup name.

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.

[
  {
     title: 'Example of paramButtonConfig toogleGroup',
     color: '#FFA500',
     elements: [
        {
           title: 'Layer 1',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           descriptionHtml:
              '{{label|text=This is the description of Layer 1. Only one can be open each time.}}',
           paramsButtonConfig: [
              { 
                 type: 'query',
                 toggleGroup: 'Group1',
              },
           ],
        },
        {
           title: 'Layer 2',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           descriptionHtml:
              '{{label|text=This is the description of Layer 2. Only one can be open each time.}}',
           paramsButtonConfig: [
              { 
                 type: 'query',
                 toggleGroup: 'Group1',
              },
           ],
        },
        {
           title: 'Layer 3',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           descriptionHtml:
              '{{label|text=This is the description of Layer 3. Only one can be open each time.}}',
           paramsButtonConfig: [
              { 
                 type: 'query',
                 toggleGroup: 'Group1',
              },
           ],
        },
     ],
  },
]

tooltip

String= string.emptyproperty# Defines the help tooltip text that is displayed when the mouse hover the associated button.

Defines the help tooltip text that is displayed when the mouse hover the associated button.

[
  {
     title: 'Example of paramButtonConfig tooltip property',
     color: '#A020F0',
     elements: [
        {
           title: 'The query button is the third of the buttons at the right:',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           descriptionHtml:
              '{{label|text=Hover the query button. That is the third button from left to right.}}',
           paramsButtonConfig: [
              { 
                 type: 'query',
                 pressed: true,
              },
           ],
        },
     ],
  },
]

type

String= 'query'property# Define which button will be affected by the configurations.

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 arrow. This button allows the user to download the dataset. It also defines which Layer should be downloaded when more than one Layer is shown by its internal layer index.

  • 'metadata': The metadata button is the one with a script icon. This button displays a popup with more information about the maps used in the actual Layer. You can make it show one of the inside composite Layer by his index.

  • 'associated': Creates a custom button that is linked to another button defined in the descriptionHtml. When one is pressed the other is also pressed.

paramsButtonConfig is normally an array of entries and each entry must declare its type (an entry without type is ignored). It may also be a single object instead of an array: it is then treated as one entry of type: 'query' (unless the object declares another type). PS: The properties are aditional, so the common must always be present, and for each type his corresponding property must be added.

// Example on how to use the query type paramsButtonConfig
[
  {
     title: 'Example of paramButtonConfig types',
     color: '#FFA500',
     elements: [
        {
           title: 'This Layer has custom buttons on the Legend Window',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           startLegendOpen: true,
           descriptionHtml:
              '{{label|text=The third button is the Query type}}',
           paramsButtonConfig: [
              { 
                 type: 'query',
                 tooltip: 'This is the query button',
                 pressed: true,
                 handler: function handleClick(button, clickEvent)  {
                    ExtjsUtils.ALERTIFY.log('You\'ve clicked the query button');
                 },
              },
           ],
        },
     ],
  },
]
// Example on how to use the metadata type paramsButtonConfig 
[
  {
     title: 'Example of paramButtonConfig types',
     color: '#FFA500',
     elements: [
        {
           title: 'This Layer has custom buttons on the Legend Window',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           startLegendOpen: true,
           descriptionHtml:
              '{{label|text=The third button is the metadata type}}',
           paramsButtonConfig: [
              { 
                 type: 'query',
                 pressed: true,
              },
              { 
                 type: 'metadata',
                 tooltip: 'This is the metadata button',
                 handler: function handleClick(button, clickEvent)  {
                    ExtjsUtils.ALERTIFY.log('You\'ve clicked the metadata button');
                 },
              },
           ],
        },
     ],
  },
]
// Example on how to use the download type paramsButtonConfig 
[
  {
     title: 'Example of paramButtonConfig types',
     color: '#FFA500',
     elements: [
        {
           title: 'This Layer has custom buttons on the Legend Window',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           startLegendOpen: true,
           descriptionHtml:
              '{{label|text=The last  button is the download type}}',
           paramsButtonConfig: [
              { 
                 type: 'query',
                 pressed: true,
              },
              { 
                 type: 'download',
                 tooltip: 'This is the download button',
                 handler: function handleClick(button, clickEvent)  {
                    ExtjsUtils.ALERTIFY.log('You\'ve clicked the download button');
                 },
              },
           ],
        },
     ],
  },
]
// Example on how to use the associated type paramsButtonConfig
[
  {
     title: 'Example of paramButtonConfig types',
     color: '#FFA500',
     elements: [
        {
           title: 'This Layer has custom buttons on the Legend Window',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           startLegendOpen: true,
           descriptionHtml:
              '{{label|text=The third button is the associated type}}'
              +
              '{{button|id=test_button|text=This is the custom associated button|enableToggle=true}}',
           paramsButtonConfig: [
              { 
                 type: 'query',
                 pressed: true,
              },
              { 
                 type: 'associated',
                 tooltip: 'This is the custom button',
                 associatedButtonID: 'test_button',
                 // The handler only triggers for the Legend Window button (not the descriptionHtml associatedButton)
                 handler: function handleClick(button, clickEvent)  {
                    ExtjsUtils.ALERTIFY.log('You\'ve clicked the custom button');
                 },
              },
           ],
        },
     ],
  },
]

Row button callbacks

paramsButtonConfigFunctions2 entries
Functions a row-button object can carry; the platform calls them when the button is pressed or toggled.

handler

functioncallback# Defines a function that will be called when the associated button is clicked.

Defines a function that will be called when the associated button is clicked.

button Object
is the button that was clicked by the mouse.
clickEvent MouseEvent
is the object that carries more information about the click event.
[
  {
     title: 'Example of callback when clicking in a Legend Window button',
     color: '#A020F0',
     elements: [
        {
           title: 'The handleClick function will be called when the query button is clicked',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           paramsButtonConfig: [
              { 
                 type: 'query',
                 handler: function handleClick(button, clickEvent) {
                    ExtjsUtils.ALERTIFY.log('You clicked the query button');
                 },
              },
           ],
        },
     ],
  },
]

toggleHandler

function= nullcallback# This function is called whenever the associated button change its toggle state.

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".

button Ext.Button
The button element that was clicked
state Boolean
The next state of the button, true means pressed
[
  {
     title: 'Example of paramButtonConfig toogleHandler',
     color: '#FFA500',
     elements: [
        {
           title: 'Layer 1',
           name: 'CSR:geologia',
           source: 'calculate',
           visibility: true,
           paramsButtonConfig: [
              { 
                 type: 'query',
                 toggleHandler: function handleToggle(button, state) {
                    let queryButtonState = state ? 'pressed' : 'unpressed';
                    console.log(`Layer 1 query button is: ${queryButtonState}`);
                 },
              },
           ],
        },
     ],
  },
]

Kinds of layer: what each source adds

source chooses the kind of a layer: a published map (no source, "local", or the key of a server registered with addRemoteWMSServer), a calculated layer ("calculate"), a file layer ("file") or a tile layer ("xyz"). Each group below belongs to one kind: the keys only that kind reads, and the methods its layer object has at run time - what this is inside its functions.

Published maps: styles from QGIS

QGIS1 entry
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.

styles

String# Where a map's styles come from: they are not written in the query.

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 online are the ones set in QGIS. Each converted style becomes a Mappia style identifier - the map name without its namespace, plus _ and an index - and those identifiers are what a query selects with the styles property, what the layer's style chooser lists, and what the legend renders.

So changing how a map looks is a publication step, not a query change: restyle it in QGIS, publish again, and reference the style from the query.

{
       ...,
         name: 'CSR:estados',
         styles: 'estados_0',
       ...
  }

Calculated layers: raw maps and operation tokens

RawMaps1 entry
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.

operations

Object# Enumeration of the operations a map of a source: 'calculate' layer can be decoded with.

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 values are integers; getFromString(token) and getName(value) convert between the two forms.

  • NORMAL (0, an empty or unknown token): a regular WMS image, each cell is a legend colour/category and not a Raw Map.
  • RAW (1, raw): each resulting cell has the value of the most centred original cell of the aggregated region.
  • RGBA (2, rgba): each resulting cell is an integer packing the RGBA bytes of the pixel (input and output are integers).
  • SUM (3, sum): each resulting cell is the weighted sum of the cells of the covered region, the weight being the covered fraction of each cell (VALUE * COVERED_PERCENTAGE).
  • AVERAGE (4, average): each resulting cell is the weighted mean of the cells of the covered region.
  • MAX (5, max): the greatest cell at least partially covered by the region.
  • MIN (6, min): the smallest cell at least partially covered by the region.
  • INTEGRAL (7, integral): summed-area table, so the sum inside any rectangle is obtained from its four corner cells only.
  • AREAINTEGRAL (8, areaintegral): summed-area table of the covered areas (no further description in the source).
  • AREA (9, area): each cell carries the original map area inside the aggregated region, so totals can be computed at any scale with full precision.
  • CELLS (10, cells): weighted count of the original cells inside the region. Every operation other than NORMAL and RGBA requires the map to be published as a Raw Map that offers it.
LayerWorkerUtils.MapOperations.getFromString('sum'); // 3 (LayerWorkerUtils.MapOperations.SUM)
LayerWorkerUtils.MapOperations.getName(3); // 'SUM'

Calculated layers: methods (this.)

LayerInternal14 entries
Methods of a calculated layer that your functions call on this - this.setCalculateLegend in beforeCalc, this.changeLayers to switch its maps, this.getInputs... They are not keys you write in the layer.

callFunction

function(name, anyArguments) : *method# Calls one of the layer's own functions by name with the layer as this.

Written as this.callFunction

Calls one of the layer's own functions by name with the layer as this. Extra arguments are passed through to the function.

name String
Key of the layer's functions object.
anyArguments *
Arguments forwarded to the function.

Returns Whatever the function returns.

this.callFunction('getAssociatedLayer'); // or this.callFunction('getAssociatedLayer', 'param1', 2, [], {}, 'param5');

changeLayers

function(newConfigs, force)method# Replaces an internal layer at a given index.

Written as this.changeLayers

Replaces an internal layer at a given index. PS: It's highly recommended to pass multiple configurations in an array, instead of calling this function multiple times in the same callback.

newConfigs Array|Object
One or more layers configurations with a property 'index' indicating the replacing layer. Each config object must contain at least the following properties: [{name: 'MAP_FULL_NAME', styles: 'MAP_STYLE', index: 'MAP_INDEX_TO_CHANGE'}, ... ]
force Boolean
Force redraw even if no change is done when the layer is the same.
{
     name: "CSR:rodovias,CSR:municipios",
     otherNames: "CSR:roads",
     beforeCalc: function(layerVals, inputVals) {
         this.changeLayers([{name: 'CSR:roads', styles: fMapName + "_1", index: 0}]);
     }
  }

generateNewLegend

function()method# Schedules a new legend: cancels the calculations in progress, runs beforeCalc(inputs) with the current input values and, when every tile is loaded and the layer is not paused, recalculates the map and its legend.

Written as this.generateNewLegend

Schedules a new legend: cancels the calculations in progress, runs beforeCalc(inputs) with the current input values and, when every tile is loaded and the layer is not paused, recalculates the map and its legend. It is the supported way to force the layer to refresh itself from outside a normal calculation cycle (for example from onVisibilityChange or a {{button}} handler).

onVisibilityChange: function(visible, inputs) {
   if (visible && !this.isCalculationPaused()) {
      this.generateNewLegend();
   }
}

getInputs

function() : Arraymethod# Returns the current value of every input tool declared in descriptionHtml, in declaration order (the same array beforeCalc, expression and afterCalc receive as inputs).

Written as this.getInputs

Returns the current value of every input tool declared in descriptionHtml, in declaration order (the same array beforeCalc, expression and afterCalc receive as inputs). A value can be a simple one (number, string) or a complex object (a CSV table, a picked point, ...). Use it from callbacks that do not receive inputs, such as a {{button}} handler.

Returns The input values in the order the tools are declared.

functions: {
   onClickButton: function() {
      var inputs = this.getInputs();
      ExtjsUtils.ALERTIFY.log('First input: ' + inputs[0]);
   }
}

getInsideLayers

function() : Array.<OpenLayers.Layer.WMS>method# Returns the OpenLayers WMS layers that compose this layer, one per map in name and in the same order (a copy of the internal array, so changing it does not affect the layer).

Written as this.getInsideLayers

Returns the OpenLayers WMS layers that compose this layer, one per map in name and in the same order (a copy of the internal array, so changing it does not affect the layer).

Returns The inside layers.

var firstMapName = this.getInsideLayers()[0].params.LAYERS;

getLayerDefinedFunctionsByName

function(name) : function|undefinedmethod# Returns one of the functions declared in the layer's functions object by its name (the same functions that markup tools reference by name, e.g. handler=onClick).

Written as this.getLayerDefinedFunctionsByName

Returns one of the functions declared in the layer's functions object by its name (the same functions that markup tools reference by name, e.g. handler=onClick). Composed-layer twin of VectorLayer.getLayerDefinedFunctionsByName; the returned function is not bound, so call it with .call(this, ...) from a layer callback to keep the layer as this.

name String
Key of the layer's functions object.

Returns The function, or undefined when there is no function with that name.

{
   name: 'CSR:geologia',
   source: 'calculate',
   functions: {
      onClick: function(feature, inputs) { ExtjsUtils.ALERTIFY.log('clicked'); }
   },
   beforeCalc: function(inputs) {
      this.getLayerDefinedFunctionsByName('onClick').call(this, null, inputs);
   },
}

getLegendEntries

function() : Array.<{color: Array.<Number>, title: String, isNull: Boolean}>method# Returns the entries of the legend currently applied to the calculated map, in legend order.

Written as this.getLegendEntries

Returns the entries of the legend currently applied to the calculated map, in legend order. Each entry has the [R, G, B] colour of the pixels, the title shown in the legend (the value itself when no title was defined) and whether it represents the null value of the map. Returns an empty array before the first legend is generated. Use it to build a custom legend (e.g. an HTML gradient) or to map a colour back to its category.

Returns The legend entries.

afterCalc: function(inputs) {
   var html = this.getLegendEntries().map(function(entry) {
      return '<span style="background: rgb(' + entry.color.join(',') + ')">' + entry.title + '</span>';
   }).join('');
}

getVisibleLayerIndexes

function() : Array.<Number>method# Returns the indexes (positions in the name list) of the composing maps that are currently visible, in ascending order.

Written as this.getVisibleLayerIndexes

Returns the indexes (positions in the name list) of the composing maps that are currently visible, in ascending order. Useful inside beforeCalc/expression when some of the inside maps were toggled with setInsideLayerVisibility().

Returns Indexes of the visible inside maps.

beforeCalc: function(inputs) {
   var visible = this.getVisibleLayerIndexes(); // e.g. [0, 2]
}

isCalculationPaused

function() : Booleanmethod# Returns calculation status.

Written as this.isCalculationPaused

Returns calculation status. True if calculations are paused, false otherwise.

Returns Calculation is paused

pauseAndStopCalculations

function()method# Cancels the calculations in progress and pauses the start of new ones (the "generating legend" indicator is shown while paused).

Written as this.pauseAndStopCalculations

Cancels the calculations in progress and pauses the start of new ones (the "generating legend" indicator is shown while paused). Call it when something the expression depends on starts loading, and resumeCalculations() when it is done. The pause is cumulative: every call needs a matching resumeCalculations() before the layer calculates again (isCalculationPaused() tells the state).

onInputsReady: function(inputs) {
   var layer = this;
   layer.pauseAndStopCalculations();
   ExtjsUtils.REQUEST.get('https://maps.csr.ufmg.br/theme/app/data/example.json', function(resp) {
      layer.myData = JSON.parse(resp.responseText);
      layer.resumeCalculations(); // redraws with the loaded data
   });
}

resumeCalculations

function(qnt)method# Undoes pauseAndStopCalculations().

Written as this.resumeCalculations

Undoes pauseAndStopCalculations(). Call it whenever a resource finished loading; when the last pending pause is released the layer is redrawn (which recalculates it).

qnt Number
How many pauses to release at once. 0 releases nothing and never redraws; omitted means 1.
this.resumeCalculations();

setCalculateLegend

function(legendEntries)method# Defines the legend of the calculated map yourself, which also skips the automatic legend calculation for this cycle.

Written as this.setCalculateLegend

Defines the legend of the calculated map yourself, which also skips the automatic legend calculation for this cycle. It is meant to be called inside beforeCalc, the moment right before a new legend would be computed, but it can also be called from a tool callback (e.g. a {{button}} handler). When the given entries equal the current legend nothing is redrawn.

legendEntries Array.<{color: Array.<Number>, value: *, title: String}>
Legend entries sorted by value in ascending order (entries out of order are ignored). color is the [R, G, B] colour of the entry, value the highest value that maps to it, title the label shown in the legend.
beforeCalc: function(inputs) {
   this.setCalculateLegend([
      {color: [0, 0, 255], value: 500, title: 'Up to 500 m'},
      {color: [255, 255, 0], value: 1000, title: 'From 500 m to 1000 m'},
      {color: [255, 0, 0], value: 3000, title: 'Above 1000 m'},
   ]);
}

setInsideLayerVisibility

function(visibility, layerIndex)method# Shows or hides the maps that compose the layer (the ones listed in name) without touching the layer itself.

Written as this.setInsideLayerVisibility

Shows or hides the maps that compose the layer (the ones listed in name) without touching the layer itself. Pass layerIndex to change one map only, omit it to change all of them. The platform hides every inside map when the layer has an expression() (only the calculated result is shown) and shows them all otherwise; use this to reveal one of the source maps behind a calculated result.

visibility Boolean
True to show the map(s), false to hide them.
layerIndex Number
Index of the map in the name list; when omitted every inside map is changed.
afterCalc: function(inputs) {
   this.setInsideLayerVisibility(true, 0); // show the first source map under the calculated result
}

setLayerOperation

function(layerIndex, operation)method# Sets the decoding operation of one of the maps of the composed layer (the same tokens accepted by the operation layer key, e.g. 'raw', 'sum', 'average'; '' or null means the default decoding).

Written as this.setLayerOperation

Sets the decoding operation of one of the maps of the composed layer (the same tokens accepted by the operation layer key, e.g. 'raw', 'sum', 'average'; '' or null means the default decoding). The platform calls it from the operation key at creation; when called at runtime the new operation is only used after the map legends are read again (for example when changeLayers replaces a map).

layerIndex Number
Index of the map in the name list (0 based).
operation String
Operation token, or ''/null for the default decoding.
this.setLayerOperation(1, 'sum');

Calculated layers: this inside expression

ValuesCalculation7 entries
Inside expression, this is the calculation, which runs in a separate worker - not the layer: this.nullValue, this.isNumeric(value)... Page globals are not there. The same helpers are reachable as ValuesCalculation.prototype.<method>.

calcTilesValues

function(imageDataTiles, inputs) : Array.<(Number|String)>method# Internal — the pixel loop of a calculate layer: for every pixel of the tile it reads one value per inner map (colour looked up in the map's legend, or the raw cell value for raw/sum/... …

Written as this.calcTilesValues

Internal — the pixel loop of a calculate layer: for every pixel of the tile it reads one value per inner map (colour looked up in the map's legend, or the raw cell value for raw/sum/... operations) and calls the layer's expression(layersVals, inputs) with them. Pixels that are null in every map become this.nullValue without calling the expression. The expression is invoked with this bound to this ValuesCalculation instance, which is why this.isNumeric(v) works inside an expression (ValuesCalculation.prototype.isNumeric(v) also works). Tenant code never calls this directly; the layer worker does.

imageDataTiles Array.<Uint8ClampedArray>
One ImageData data array per inner map, for the same tile position (without the result tile).
inputs Array
The layer's input values, in the order defined for the layer (what expression receives as its second argument).

Returns One result per pixel, in the tile's pixel order.

getColorFromInt

function(value) : Array.<Number>method# Unpacks the four RGBA bytes packed in a 32-bit integer: byte 0 (lowest) is red, byte 1 green, byte 2 blue and byte 3 alpha.

Written as this.getColorFromInt

Unpacks the four RGBA bytes packed in a 32-bit integer: byte 0 (lowest) is red, byte 1 green, byte 2 blue and byte 3 alpha. This is the packing the rgba map operation uses, where a pixel colour travels as one integer (the layer worker paints such results with getNonNullColorFromInt). Inside an expression function this is the ValuesCalculation instance, so this.getColorFromInt(v) works there; ValuesCalculation.prototype.getColorFromInt(v) also works, anywhere.

value Number
The packed RGBA integer.

Returns [r, g, b, a], each component in 0..255.

ValuesCalculation.prototype.getColorFromInt(0xFF0080FF); // [255, 128, 0, 255]
expression: function(layersVals, inputs) {
    var rgba = this.getColorFromInt(layersVals[0]); // an inner map with operation: "rgba"
    return rgba[3] === 0 ? this.nullValue : (rgba[0] + rgba[1] + rgba[2]) / 3; // grey level
}

getNonNullColorFromInt

function(value, nullValues) : Array.<Number>|nullmethod# getColorFromInt with a null check: returns this.nullColor (null) when the packed integer is one of the values listed in nullValues, and the unpacked [r, g, b, a] otherwise.

Written as this.getNonNullColorFromInt

getColorFromInt with a null check: returns this.nullColor (null) when the packed integer is one of the values listed in nullValues, and the unpacked [r, g, b, a] otherwise. Handy when a map encodes "no data" as one or more specific colours. Inside an expression function this is the ValuesCalculation instance, so this.getNonNullColorFromInt(v, nulls) works there; ValuesCalculation.prototype.getNonNullColorFromInt(v, nulls) also works, anywhere.

value Number
The packed RGBA integer (see getColorFromInt).
nullValues Array.<Number>
Packed integers that should be treated as null.

Returns [r, g, b, a], or null when value is in nullValues.

expression: function(layersVals, inputs) {
    var rgba = this.getNonNullColorFromInt(layersVals[0], [0, 0xFFFFFFFF]);
    return rgba === null ? this.nullValue : rgba[0];
}

getValueFromLegend

function(legend) : Number|String|nullmethod# Turns a legend label into the value that best represents it — the same conversion the calculation applies to every map legend before the expression sees layersVals.

Written as this.getValueFromLegend

Turns a legend label into the value that best represents it — the same conversion the calculation applies to every map legend before the expression sees layersVals. A numeric label ("12", "1,5", "1.000") becomes that number (a single comma is read as the decimal separator, "1.000"/"1,000" as thousands), a range ("10 - 20", "10 – 20", "10 to 20") becomes its midpoint, a leading comparison operator ("> 800", "<= 5", "&gt; 800") is stripped first, and any other text ("Floresta") is returned unchanged. An empty label returns null. Use it to interpret legend titles you read with ExtjsUtils.LAYER.getLayerLegend the same way the layer does. Inside an expression function this is the ValuesCalculation instance, so this.getValueFromLegend(label) works there; ValuesCalculation.prototype.getValueFromLegend(label) also works, anywhere. To mark a pixel transparent, pass/return this.nullValue.

legend String
The legend title to interpret.

Returns The number the label represents, the label itself when it is not numeric, or null when it is empty.

ValuesCalculation.prototype.getValueFromLegend("10 - 20");   // 15
ValuesCalculation.prototype.getValueFromLegend("> 800");     // 800
ValuesCalculation.prototype.getValueFromLegend("1,5");       // 1.5
ValuesCalculation.prototype.getValueFromLegend("Floresta");  // "Floresta"

isNumeric

function(value) : Booleanmethod# Tells whether a value represents a number: a Number, or a String that is a plain decimal/exponential number ("12", "-3.5", "1e3").

Written as this.isNumeric

Tells whether a value represents a number: a Number, or a String that is a plain decimal/exponential number ("12", "-3.5", "1e3"). Map values read from a legend can be either a number or the legend's text (e.g. "Floresta"), so use this in an expression before doing arithmetic on layersVals[i]. Inside an expression function this is the ValuesCalculation instance, so this.isNumeric(v) works there; ValuesCalculation.prototype.isNumeric(v) also works, anywhere.

value String|Number
The value to test.

Returns true when the value is numeric, false otherwise.

[{
    name: "CSR:cultivo_cafe_cafe",
    source: "calculate",
    expression: function(layersVals, inputs) {
        // layersVals[0] may be a legend label instead of a number
        return this.isNumeric(layersVals[0]) ? layersVals[0] * inputs[0] : this.nullValue;
    }
}]

nullValue

Number# The value that stands for "no data" in a calculation: NaN.

Written as this.nullValue

The value that stands for "no data" in a calculation: NaN. Return this.nullValue from an expression to leave the pixel transparent, and compare against it (with isNaN) when an inner map's value may be null. Inside an expression function this is the ValuesCalculation instance, so this.nullValue is the way to reach it there (ValuesCalculation.prototype.nullValue works anywhere).

expression: function(layersVals, inputs) {
    if (isNaN(layersVals[0]) || layersVals[0] < inputs[0]) {
        return this.nullValue; // transparent pixel
    }
    return layersVals[0];
}

simplifyLegend

function(n) : Number|Stringmethod# Returns a shorter representation of a numeric value for display in a legend: values with an absolute value below 0.005 are written in exponential notation with 2 decimals, other values below 1 are …

Written as this.simplifyLegend

Returns a shorter representation of a numeric value for display in a legend: values with an absolute value below 0.005 are written in exponential notation with 2 decimals, other values below 1 are kept to 3 significant digits and everything else is rounded to 2 decimals. Non-numeric values are returned unchanged. Useful inside afterCalc or legendTitle code that formats the legend entries of a calculated layer. Inside an expression function this is the ValuesCalculation instance, so this.simplifyLegend(n) works there (and ValuesCalculation.prototype.simplifyLegend(n) works anywhere).

n Number|String
The value to simplify.

Returns The simplified value (a string when exponential notation or toPrecision was used), or n itself when it is not numeric.

ValuesCalculation.prototype.simplifyLegend(0.001234); // "1.23e-3"
ValuesCalculation.prototype.simplifyLegend(0.4567);   // "0.457"
ValuesCalculation.prototype.simplifyLegend(1234.5678); // 1234.57

Calculated layers: legend reader

JsonLegendReader7 entries
Reads the JSON legends of the maps of a Composed layer, reachable as layer.jsonLegendReader. Prefer ExtjsUtils.LAYER.getLayerLegend for the common case.

getJsonLegend

function(layer) : Array.<Object>|undefined# Returns the loaded legend entries of a map: an array of {color: [r, g, b], title} objects in legend order, or undefined while the legend has not been loaded (or failed).

Returns the loaded legend entries of a map: an array of {color: [r, g, b], title} objects in legend order, or undefined while the legend has not been loaded (or failed). This is the documented route to a map's legend — it accepts the layer object itself and is what ExtjsUtils.LAYER.getLayerLegend(composedLayer, index) uses; the inner jsonLegends.getJsonLegend(id) needs the unique id instead.

layer OpenLayers.Layer|String
The layer object (an inner map of a Composed layer, typically), or its unique id.

Returns The legend entries {color: Array<Number>, title: String}, or undefined when not loaded.

// inside afterCalc / onInputsReady of a Composed layer (this === the layer)
var entries = this.jsonLegendReader.getJsonLegend(this.layers[0]) || [];
entries.forEach(function(entry) {
    console.log(entry.title, ExtjsUtils.HTML.rgbToColorStyle(entry.color));
});

getLayerOperationCellType

function(layer, operation) : Number# Returns the cell type (LayerWorkerUtils.CellTypes: INT32, UINT32, FLOAT32) the calculation must use to decode a map under a given operation, as declared by the map's description metadata.

Returns the cell type (LayerWorkerUtils.CellTypes: INT32, UINT32, FLOAT32) the calculation must use to decode a map under a given operation, as declared by the map's description metadata. Falls back to INT32 when the map does not declare the operation (see hasOperation). Mostly informational for query authors; the calculation calls it itself.

layer OpenLayers.Layer|String
The layer object, or its unique id.
operation Number
The operation, one of LayerWorkerUtils.MapOperations.

Returns The cell type, one of LayerWorkerUtils.CellTypes.

var cellType = layer.jsonLegendReader.getLayerOperationCellType(layer.layers[0], LayerWorkerUtils.MapOperations.RAW);
console.log(cellType === LayerWorkerUtils.CellTypes.FLOAT32);

getLayerUniqueId

function(layer) : String# Returns the key under which the reader stores a layer's legend: the string itself when given a string, the layer's id (assigned by Ext.id) when given a WMS layer object, and an empty string for …

Returns the key under which the reader stores a layer's legend: the string itself when given a string, the layer's id (assigned by Ext.id) when given a WMS layer object, and an empty string for anything else (a layer without params). Use it to build the id the jsonLegends manager methods expect.

layer OpenLayers.Layer|String
The layer object, or an id already.

Returns The layer's unique id.

var id = layer.jsonLegendReader.getLayerUniqueId(layer.layers[0]);
var loaded = layer.jsonLegendReader.jsonLegends.wasLoaded(id);

getLegend

function(layer, color) : String# Looks up the legend title of a colour in a map's legend: the title of the entry whose [r, g, b] equals the first three components of color.

Looks up the legend title of a colour in a map's legend: the title of the entry whose [r, g, b] equals the first three components of color. Returns an empty string when the map has no legend loaded, the colour is not in it, or color has fewer than three components. This is what turns a pixel colour read from an inner map into its class name (e.g. for a tooltip); for the Composed layer's own calculated legend use ExtjsUtils.LEGENDS.getColorTitle(layer, r, g, b) instead.

layer OpenLayers.Layer|String
The layer object, or its unique id.
color Array.<Number>
The colour to look up, [r, g, b] or [r, g, b, a].

Returns The legend title, or "" when there is none.

var title = layer.jsonLegendReader.getLegend(layer.layers[0], [0, 128, 0]); // "Floresta"

hasOperation

function(layerID, operationType) : Boolean# Tells whether a map supports a given decoding operation (see RawMaps.operations): the normal and rgba operations are always supported (they only need the WMS image), the others (raw, sum, …

Tells whether a map supports a given decoding operation (see RawMaps.operations): the normal and rgba operations are always supported (they only need the WMS image), the others (raw, sum, average, ...) only when the map's description metadata declares a cell type for them. Useful to check, after the legends loaded, whether an operation you plan to set on a layer will actually work.

layerID OpenLayers.Layer|String
The layer object, or its unique id.
operationType Number
The operation, one of LayerWorkerUtils.MapOperations (e.g. LayerWorkerUtils.MapOperations.RAW).

Returns true when the map supports the operation.

var supportsRaw = layer.jsonLegendReader.hasOperation(layer.layers[0], LayerWorkerUtils.MapOperations.RAW);

jsonLegends

Object# The legend store of the reader, keyed by layer unique id (see getLayerUniqueId: a layer's id, e.g. layer.layers[0].id for an inner map of a Composed layer).

The legend store of the reader, keyed by layer unique id (see getLayerUniqueId: a layer's id, e.g. layer.layers[0].id for an inner map of a Composed layer). Queries reach it as layer.jsonLegendReader.jsonLegends and mostly call getJsonLegend(id); prefer the outer getJsonLegend(layer) or ExtjsUtils.LAYER.getLayerLegend(layer, index) when you hold the layer object. Its four methods: getJsonLegend(layerUniqueId) → Array<{color: [r, g, b], title: String}>|undefined — the loaded legend entries (undefined while not loaded or after remove); setJsonLegend(layerUniqueId, legendArray) — stores a legend array for that id; wasLoaded(layerUniqueId) → Boolean — whether a legend (even an empty one) is stored; remove(layerUniqueId) — forgets the stored legend, so it is fetched again next time.

// colour of the legend entry whose title matches a value, for a Composed layer's first map
function getLegendColor(composedLayer, title) {
    var entries = composedLayer.jsonLegendReader.jsonLegends.getJsonLegend(composedLayer.layers[0].id) || [];
    for (var i = 0; i < entries.length; i++) {
        if (entries[i].title === title) return ExtjsUtils.HTML.rgbToColorStyle(entries[i].color);
    }
    return null;
}

setLayerLegend

function(layer, legendContent)# Stores the legend of a layer from its JSON content, replacing whatever the reader had for it.

Stores the legend of a layer from its JSON content, replacing whatever the reader had for it. The platform calls it when a legend request finishes; a query can call it to inject a legend for a map that has none (or to override the server's), e.g. before a calculate layer reads the legend values. A string is evaluated as JSON.

layer OpenLayers.Layer|String
The layer object, or its unique id (see getLayerUniqueId).
legendContent String|Array.<Object>
The legend: an array of {color: [r, g, b], title: String} entries, or that array as JSON text.
layer.jsonLegendReader.setLayerLegend(layer.layers[0], [
    {color: [0, 128, 0], title: "Floresta"},
    {color: [255, 255, 0], title: "Agricultura"}
]);

File layers: data

FileLayer5 entries
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.

json

Array.<Object>|Object# Inline data of a source: 'file' layer with type: 'json'.

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 a feature with convertJsonEntryToFeature (see coordinates/getVector). A JSON string is also accepted.

{
   name: 'CSR:inline_points',
   source: 'file',
   type: 'json',
   fromProj: 'EPSG:4326',
   json: [
      {name: 'Belo Horizonte', lon: -43.94, lat: -19.92},
      {name: 'Brasilia', lon: -47.88, lat: -15.79},
   ],
}

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.

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 trigger startLoadingLayer before and endLoadingLayer after every asynchronous load, so the layer knows when the data is ready (onInputsReady/onLoad depend on it).

{
   name: 'CSR:filtered_file',
   source: 'file',
   type: 'load',
   url: 'https://maps.csr.ufmg.br/theme/app/data/example.geojson',
   loadData: function(inputs, config) {
      var layer = this;
      layer.events.triggerEvent('startLoadingLayer');
      ExtjsUtils.REQUEST.get(config.url, function(resp) {
         var geojson = JSON.parse(resp.responseText);
         geojson.features = geojson.features.filter(function(feat) {
            return feat.properties.area > 100;
         });
         layer.loadGeojson(geojson);
         layer.events.triggerEvent('endLoadingLayer');
      }, function() {
         layer.events.triggerEvent('endLoadingLayer');
      }, false, layer);
   },
}

onVisibilityChange

function# Callback when layer visibility is changed.

Callback when layer visibility is changed.

PS: Is not called for the initial visibility of the layer.

[{...
 onVisibilityChange: function(visibilityChangeEvent) {

   alert("layer visibility changed");
 }
}]

Layer scope and evt as parameter.

type

String= "json"# Defines how a source: 'file' layer gets its features (case insensitive).

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 this.events.triggerEvent('startLoadingLayer') before and this.events.triggerEvent('endLoadingLayer') after each load (the calls are cumulative). 'csv': fetches the CSV file at url; each line becomes a feature through convertJsonEntryToFeature (see coordinates/getVector). 'json': uses the inline json data: a GeoJSON object (FeatureCollection, Feature or geometry) or an array of plain objects converted with convertJsonEntryToFeature. 'jsonurl': fetches an array of plain objects from url and converts each one with convertJsonEntryToFeature. 'geojsonurl': fetches a GeoJSON file from url (projection detected from its crs, fromProj or the coordinates). 'empty': creates no feature; the usual choice for layers that are drawn into or filled later with loadGeojson/addFeatures.

When omitted the type is 'json'; an unknown value falls back to 'jsonurl'.

[
  {
     title: 'Vector layers',
     color: '#FFA500',
     elements: [
        {
           title: 'Municipalities from a GeoJSON file',
           name: 'CSR:municipalities_file',
           source: 'file',
           type: 'geojsonurl',
           url: 'https://maps.csr.ufmg.br/theme/app/data/example.geojson',
           visibility: true,
        },
        {
           title: 'Empty layer to draw on',
           name: 'CSR:drawing_file',
           source: 'file',
           type: 'empty',
           visibility: true,
        },
     ],
  },
]

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).

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 config.url for type: 'load'.

{
   name: 'example_points',
   source: 'file',
   type: 'jsonurl',
   // shipped with the platform: [{"lon":-50, "lat":-10, "name":"name1"}, ...]
   url: '/theme/app/data/points_example.json',
   coordinates: {x: 'lon', y: 'lat'},
}

File layers: style, events, drawing

VectorLayer44 entries
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.

activateDrawMode

function(mode) : Boolean# Select polygon/line tool and enter edit mode when needed (split-button menu).

Select polygon/line tool and enter edit mode when needed (split-button menu).

mode String
'polygon' or 'line' — must be one of the layer's configured drawModes.

Returns true if the mode was activated (entering edit mode if not already active); false if mode isn't in the layer's drawModes.

applyFeatureChanges

function() : Boolean# Finish sketch or deselect feature (triggers featureEditEnd when applicable).

Finish sketch or deselect feature (triggers featureEditEnd when applicable).

Returns true if a sketch was finished or a feature was deselected; false if there was no active modify control.

applyGeomOp

function(sourceGeoms, options) : Object# Replace geometries on this drawable VectorLayer with id/attribute control via one 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}.

sourceGeoms Array.<OpenLayers.Geometry>
Features selected by feature.geometry identity.
options Object|function
If a function, treated as { operation: fn }.
options.operation String|function
'difference' | 'intersection' | 'keep' or function(sourceGeom, sourceFeature) => Geometry[].
options.with OpenLayers.Geometry
Operand for difference / intersection.
options.attributes String|function
'keep' | 'empty' or function(sourceAttrs, pieceIndex, pieceCount) => Object.
options.preserveId Boolean
First piece of each source keeps OpenLayers id/fid.
// Cut overlaps (difference) — ``layer`` must be a drawable VectorLayer
  layer.applyGeomOp(intersecting, {
    operation: 'difference', with: editedUnion
  });
  // Clip to CAR (intersection)
  layer.applyGeomOp(outsideGeoms, {
    operation: 'intersection', with: carGeometry
  });
  // Custom pieces + empty attrs
  layer.applyGeomOp(geoms, {
    operation: function(g) { return [myTransform(g)]; },
    attributes: 'empty'
  });

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.

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.

name String
Key of the functions object (or a layer method name).
anyArguments *
Arguments forwarded to the function.

Returns Whatever the function returns; undefined when no function was found.

{...
  functions: {
    FUNCTION_NAME: function(parameter1) {
      var layer = this;
      console.log(this, parameter1);
    }
  },
  beforeCalc: function () {
    this.callFunction('FUNCTION_NAME', 'parameter1');
  }
}

cancelDrawing

function() : Boolean# Cancel the in-progress sketch/edit without committing changes.

Cancel the in-progress sketch/edit without committing changes.

Returns true if a sketch was cancelled; false if there was no active modify control.

cluster

Object# AnimatedCluster options.

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().

cluster: {
  distance: function() {
    return this.layer.map.getZoom() > 14 ? 40 : 80;
  },
  clusterKey: function(feature) {
    var zoom = this.layer.map.getZoom();
    if (zoom <= 10) return feature.attributes.regiao;
    if (zoom <= 14) return feature.attributes.bairro;
    return null; // distance only
  },
  clusterGeometry: function(cluster) {
    var key = cluster.attributes.clusterKey;
    var zoom = this.layer.map.getZoom();
    if (zoom <= 10 && REGION_GEOMS[key]) return REGION_GEOMS[key];
    if (zoom <= 14 && BAIRRO_GEOMS[key]) return BAIRRO_GEOMS[key];
    return this.defaultClusterGeometry(cluster); // hull / point
  },
  minClusterPolygonPx: 28
}

clusterDistance

Numeric# Defines the minimum relative distance (in pixels) to clusterize points.

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 — cluster options win; clusterDistance fills default distance). PS: When filters are applied, you can use the property 'count' on 'VectorLayer.styleMap' property to check how many points exists in the current cluster.

(Standalone doc comment: the value is read inside strategies below, which carries the cluster block, so this one is named explicitly.)

convertJsonEntryToFeature

function(curObj, optionalGetLonLat) : OpenLayers.Feature.Vector# Converts a JsonObject into a Layer Feature (that can be added to layer).

Converts a JsonObject into a Layer Feature (that can be added to layer).

curObj JsonObject
Object with properties.
optionalGetLonLat function
Optional function to get position coordinates from JSON. P.S.: Optional function to get X,Y values from Obj. (By default Longitude and Latitude use fields: lon and lat) function optionalGetLonLat(curObj) returns OpenLayers.LonLat curObj: Object with JSON properties. This function receive the 'curObj' and expects to returns the object properties.

Returns Returns the Feature from JsonObj.

coordinates

Object# Redefines the coordinate property names to {x, y}.

Redefines the coordinate property names to {x, y}. PS: Used only if the 'VectorLayer.getVector' is not defined.

coordinates: {
              'x': 'lon',
              'y': 'lat'
          }

defaultStyle

Object# Defines the default style that will be applied to the geometry.

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 displayed).

Look at some examples at: http://dev.openlayers.org/examples/

defaultStyle: {color: '${getColor}', context: {getColor: function(attr){return 'green';} }

deselectFeature

function() : Boolean# Deselect the currently selected/edited feature without discarding it.

Deselect the currently selected/edited feature without discarding it.

Returns true if a feature was deselected; false if there was no active modify control or nothing was selected.

drawable

Boolean|Object# Makes a vector layer editable: users can sketch, edit and delete polygon (optionally polygon+line) features, with configurable overlap resolution.

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 allowed on the layer.
  • onFeaturesChange {Function(evt)} — fires on any feature-set change
        (add/remove/clear/load); evt.type identifies the cause.
  • onGeomLimitReached {Function} — called when a draw attempt would exceed maxGeomCount.
  • onEditToggle {Function(active, detail)} — sketch/edit mode turned on or off.
        detail: { active, editingIntent, reason }, reason is 'toggle' (user/tenant)
        or 'visibility' (layer show/hide).
  • onDrawingStatusChange {Function(detail)} — fine-grained sketch/edit state for UI.
        detail.status: 'off'|'ready'|'drawing'|'drawing_line'|'feature_selected'|'vertex_drag',
        plus drawMode, canFinishDrawing, canApplyFeatureChanges, sketchPointCount,
        selectedFeature.
  • drawModes {Array<String>} — ['polygon'] (default) or ['polygon','line'],
        the sketch tools available in edit mode. Alias: drawingTypes.
  • drawingHints {String|Boolean} — false|true|'toolbar'|'bar'|'both',
        lightweight on-map edit guidance.
  • onOverlap {String|Array<String>} — a single action key (applied without prompt)
        or an ordered list of keys to prompt for when a new/edited feature overlaps
        another. Defaults to merge/cut/keep ({@link DrawableSplit.OVERLAP_ACTIONS}).
        Applied by layer.resolveOverlap.
  • buttons {Object} — layer-row toolbar overrides: edit, clear, removeLast, loadFile.

Exposed at runtime as layer.drawableController — see VectorLayer.activateDrawMode, VectorLayer.finishDrawing, VectorLayer.cancelDrawing, VectorLayer.deselectFeature, VectorLayer.applyFeatureChanges.

[{
  name: "CSR:file_draw", source: "file", type: "empty",
  drawable: {
    maxGeomCount: 5,
    drawModes: ['polygon', 'line'],
    onOverlap: ['merge', 'cut', 'keep'],
    onDrawingStatusChange: function(detail) { console.log(detail.status); },
    onEditToggle: function(active, detail) { console.log(active, detail.reason); }
  }
}]

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 …

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 back to jsonurl. This is what the platform calls with the layer definition; call it yourself to swap the data at runtime.

config GeometryLayerConfig
Data-loading configuration.
layer.fillGeometryLayer({
    url: 'https://maps.csr.ufmg.br/theme/app/data/conab/limite_macroregioes.geojson',
    type: 'load',
    loadData: function(inputs, config) {
        var layer = this;
        function featFilterCb(feat){
            return ['31', '35'].indexOf(feat.properties.geocodigo.toString().substring(0, 2)) !== -1;
        }
        layer.events.triggerEvent('startLoadingLayer');
        ExtjsUtils.REQUEST.get(config.url, function(resp) {
            var jsonObjects = JSON.parse(resp.responseText);
            jsonObjects.features = jsonObjects.features.filter(featFilterCb);
            layer.addFeatures(layer.convertGeojson2Features(jsonObjects));
            layer.events.triggerEvent('endLoadingLayer');
        }, function() {
            layer.events.triggerEvent('endLoadingLayer');
        }, false, layer);
    }
})

findFeatureById

function(featureId) : OpenLayers.Feature.Vector|null# Find a feature by the id returned from getFeatureId (fid, id, or index).

Find a feature by the id returned from getFeatureId (fid, id, or index). Prefer this over OpenLayers getFeatureById when callers use getFeatureId ids.

featureId String|Number
Id as returned by getFeatureId.

Returns The matching feature, or null.

finishDrawing

function() : Boolean# Commit in-progress polygon sketch (same as double-click).

Commit in-progress polygon sketch (same as double-click).

Returns true if a sketch was committed; false if there was no active modify control.

fromProj

String# Defines the projection of the JSON (accepts only EPSG:4326 and EPSG:900913).

Defines the projection of the JSON (accepts only EPSG:4326 and EPSG:900913).

EPSG:900913

generateNewLegend

function()# Runs the layer's beforeCalc(inputs) again with the current input values.

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; the platform calls it itself when a resource finishes loading. Guard it with isCalculationPaused() and waitingRenderAndLoadAssync so it does not run while data is still loading.

onVisibilityChange: function(evt) {
   if (this.getVisibility() && !this.isCalculationPaused() && this.waitingRenderAndLoadAssync == 0) {
      this.generateNewLegend();
   }
}

getEditingFeatureId

function() : String|Number|null# Feature id currently selected for vertex edit (drawable modify control), if any.

Feature id currently selected for vertex edit (drawable modify control), if any.

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).

Stable-enough id for a feature on this layer: fid, then OpenLayers id, otherwise the feature's index in layer.features (no synthetic attributes).

feature OpenLayers.Feature.Vector
Feature of this layer.

Returns Its fid, id or index; null when it is not on the layer.

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).

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 onFeatureChangeCallback.

Returns The input values in the order the tools are declared.

var firstInput = this.getInputs()[0];

getLayerDefinedFunctionsByName

function(name) : function|Undefined# Gets the layer inner function.

Gets the layer inner function.

Define the layer inner function at VectorLayer. Ex: {
  name: 'CSR:map_name',
  function: {
    nameFunctionExample: function(){alert('a');}
  } }

name String
Function name

getVector

function# Defines the callback function to parse the layer data and get the geometry.

Defines the callback function to parse the layer data and get the geometry. Callback Function getVector function(attribute, config)

attribute Object
Object with attributes.
config Object
Layer config.

Returns Return or the lat long point or the vector with the complex geometry.

hoverSelectedStyle

Object# Defines the style that will be applied to the geometry when the mouse hovers over a selected feature.

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': allows definition of filters (only the geometries that fit into this rule will be displayed). PS2: Hover Select depends on both 'onHover' and 'onClick' properties to work.

Look at some examples at: http://dev.openlayers.org/examples/

[{color: '${getColor}', context: {getColor: function(attr){return 'green';} }]

hoverStyle

Object# Defines the style that will be applied to the geometry when mouse is hovering.

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 will be displayed). PS2: Hover depends on 'onHover' property that allows to hovering.

Look at some examples at: http://dev.openlayers.org/examples/

[{color: '${getColor}', context: {getColor: function(attr){return 'green';} }]

llbbox

OpenLayers.Bounds# Bounds of the features currently on the layer, recomputed automatically after features are added or removed (and extended while drawing).

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 map.zoomToExtent. Read-only; undefined until the first feature is added.

onLoad: function(inputs) {
   if (this.llbbox) {
      app.mapPanel.map.zoomToExtent(this.llbbox);
   }
}

loadGeojson

function()# Function to load geojson and draw on the layer.

Function to load geojson and draw on the layer.

onAdded

function()# Called when the layer is on the map with its features loaded.

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 calls it). this is the layer.

AddedEvent {
    element: {DOM} 'DOM element of the layer',
    layer: {OpenLayers.Layer.Vector} 'Javascript Object of the layer',
    map: {Map} 'MapPanel where the layer was added.',
    type: {String} 'Type of the event ( added )' }

onAdded: function(evt) {
    var bounds = this.getDataExtent();
    if (bounds) ExtjsUtils.JS.getMap().zoomToExtent(bounds);
}

onBeforeFeatureChangeCallback

function# Defines the callback function that is called before a layer feature is added, removed or edited.

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.

operationType String
Receive the operation type: 'add' or 'remove' when adding or removing respectively.
arrFeatures Array
Array of features affected.
{
     ...,
     onBeforeFeatureChangeCallback: function(operationType, arrFeatures) {
         
     },
     ...
}

onClick

function# Defines the callback function to the click event on Layer.

Defines the callback function to the click event on Layer.

event Object
The click event Object.
source VectorFileSource
Auxiliary functions to deal with Vector Layer.
inputs Array.<Object>
Array with all layer input values.
{
     ...,
     onClick: function (feature) {
    console.log(feature.attributes);
         console.log("Triggered click event!");
     },
     ...
}
[{
  name:"CSR:FileGeojson",
  source: "file",
  type: "geojsonurl",
  url: "/theme/app/data/fip_interativo/amazonia/amazonia_municipios.geojson",
  onClick: function(feature, layerSource, inputs, toggleStatus) {
    console.log(arguments);
  }
}]

onClickCfg

function# Defines the callback function to the Click Select controller.

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

function# Defines a function that is called after a layer feature is added, removed or edited.

Defines a function that is called after a layer feature is added, removed or edited.

operationType String
One of: 'add' (features added in bulk, e.g. after loading data), 'add1' (a single feature added interactively), 'remove' (features removed), 'editend' (a drawable-layer sketch/edit was committed), 'editvertex' (a vertex was dragged/modified while editing).
arrFeatures Array
Array of features affected.
detail Object
Optional context. For editend: { drawMode: 'polygon'|'line' }.
{
     ...,
     onFeatureChangeCallback: function (operationType, arrFeatures) {
         
     },
     ...
}

onHover

function# Defines the callback function on 'Vector Layer' hover.

Defines the callback function on 'Vector Layer' hover.

evt Object
Features.
state Boolean
True when hover starts, false when it ends.
controller Object
The controller itself.
inputs Object
Layer widget values.
{
     ...,
     onHover: function (evt, state, controller, inputs) {
         console.log(state ? "Started": "Ended");
     },
     ...
}
[{
  name:"CSR:FileGeojson",
  source: "file",
  type: "geojsonurl",
  url: "/theme/app/data/fip_interativo/amazonia/amazonia_municipios.geojson",
  onHover: function(feature, state, controller, inputs) {
    console.log(feature.attributes);
    console.log(arguments);
  }
}]

onInputsReady

function# Called when all inputs are ready on layer.

Called when all inputs are ready on layer.

onLoad

function# Defines the callback function to be called after the layer is loaded or added to a map.

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.

widgetValues Array
inputs for onLoad callback
{
     ...,
     onLoad: function (widgetValues) {
         print(this.title) // prints the layer title
     },
     ...
}

onSelectionToggle

function# Defines the callback function to the unselect feature.

Defines the callback function to the unselect feature.

event Object
The click event Object.
source VectorFileSource
Auxiliary functions to deal with Vector Layer.
inputs Array.<Object>
Array with all layer input values.
[{
  name:"CSR:FileGeojson",
  source: "file",
  type: "geojsonurl",
  url: "/theme/app/data/fip_interativo/amazonia/amazonia_municipios.geojson",
  onSelectionToggle: function(feature, layerSource, inputs, toggleStatus) {
    console.log(feature.attributes);
    alert(toggleStatus);
  }
}]

popupCallback

function# Not implemented for file layers: accepted but never called (see popupTemplate).

Not implemented for file layers: accepted but never called (see popupTemplate). Use onClick, which receives the clicked feature.

attributes Array
attributes for popupCallback
inputs Array
inputs for popupCallback
{
     ...,
     popupCallback: function (attributes, inputs) {
         
     },
     ...
}

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).

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 example with ExtjsUtils.ALERTIFY.log or ExtjsUtils.TooltipHelper.CreateTooltipOnPosition.

onClick: function (feature) { ExtjsUtils.ALERTIFY.log("<b>" + feature.attributes.name + "</b>"); }

resolveOverlap

function(editedGeoms, intersectingGeoms, options)# Resolve overlaps between edited and existing polygons on this drawable VectorLayer.

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).

editedGeoms Array.<OpenLayers.Geometry>
Geometries just drawn or edited.
intersectingGeoms Array.<OpenLayers.Geometry>
Existing geometries they overlap.
options Object
Optional overrides.
options.onOverlap String|Array.<String>
Override controller onOverlap.
options.message String
Prompt text.
options.onComplete function
After the chosen action (or no-op).
drawableLayer.resolveOverlap(editedGeoms, intersectingGeoms, {
    onComplete: function() { drawableLayer.callFunction('validateGeometries'); }
  });

selectController

OpenLayers.Control.CustomSelectFeature= undefined# The selection control created for the layer when onClick, onSelectionToggle or onHover is defined (undefined otherwise).

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), unselectAll(), activate()/deactivate() from layer callbacks, e.g. to select a feature found with findFeatureById.

functions: {
   selectFirst: function() {
      if (this.selectController && this.features.length) {
         this.selectController.unselectAll();
         this.selectController.select(this.features[0]);
      }
   }
}

selectStyle

Object# Defines the default style that will be applied to the selected geometry.

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 displayed). PS2: Selected depends on 'onClick' property that allows to select.

Look at some examples at: http://dev.openlayers.org/examples/

[{color: '${getColor}', context: {getColor: function(attr){return 'green';} }]

setDrawing

function(enabled, callbackOnAdd)# Defines drawing features on layers.

Defines drawing features on layers. PS: Function is available to the VectorLayer.

enabled Boolean
True to enable drawing, False otherwise.
callbackOnAdd function
Callback when a new feature is drew. P.S.: You can use 'this' to access layer properties. P.S.2: The callback function receives 2 parameters: - vectorLayer: Current layer. - drawEvent: The info of the added polygon.
this.setDrawing(false, function (vectorLayer, drawEvent) {})

showLoadingModal

Boolean= false# Shows the "generating legend" loading mask visibly over the page while the layer is paused (loading its data or another resource).

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 make it visible. Only shown while the layer is visible. The same key exists for calculate layers (LayersProperties.showLoadingModal).

{
   name: 'CSR:my_points',
   source: 'file',
   type: 'geojsonurl',
   url: 'https://maps.csr.ufmg.br/theme/app/data/example.geojson',
   showLoadingModal: true,
}

styleMap

Object|OpenLayers.StyleMap# Customizes the layer visualization.

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.

StyleMap{[default, select, hover, selectedHover]: Style {rules:[Rule,], context: {getRadius: function() {return Math.random()}}}

waitingRenderAndLoadAssync

Number= 0# 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 …

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 startLoadingLayer/startLoadingResource and decreased on endLoadingLayer/endLoadingResource; onInputsReady fires when it reaches 0. Read-only: use it as a guard before refreshing the layer.

if (this.waitingRenderAndLoadAssync == 0) { this.generateNewLegend(); }

File layers: click and hover control

CustomSelectFeature16 entries
The select/hover control created for vector layers with onClick/onHover callbacks, reachable as layer.selectController. Extends OpenLayers.Control.SelectFeature.

click

Boolean= false# Select on click.

Select on click. When true, clicking a feature selects it (select), clicking a selected one again unselects it when toggle is set, and clicking outside unselects all when clickout is set. The platform sets it for layers with onClick / onSelectionToggle. When false, select/unselect are no-ops.

clickFeature

function(feature)# Internal — feature-handler callback run when a feature is clicked (only registered when click is true): toggles the feature off when it was selected and toggle is set, otherwise unselects the …

Internal — feature-handler callback run when a feature is clicked (only registered when click is true): toggles the feature off when it was selected and toggle is set, otherwise unselects the others (unless multiple) and selects it. Tenant code normally does not call it; call select/unselect instead.

feature OpenLayers.Feature.Vector
The clicked feature.

clickoutFeature

function(feature)# Internal — feature-handler callback run when the user clicks outside a previously clicked (selected) feature: unselects everything when the clickout option is set.

Internal — feature-handler callback run when the user clicks outside a previously clicked (selected) feature: unselects everything when the clickout option is set. Tenant code normally does not call it.

feature OpenLayers.Feature.Vector
The feature that was selected before the click.

defaultStyle

String= "default"# Name of the StyleMap render intent used to draw a feature that is neither hovered nor selected (getFeatureCurrentStyle returns it in that case).

Name of the StyleMap render intent used to draw a feature that is neither hovered nor selected (getFeatureCurrentStyle returns it in that case).

getFeatureCurrentStyle

function(feature, hovered) : String# Returns the name of the StyleMap render intent a feature should be drawn with right now, given whether it is selected (in layer.selectedFeatures) and whether it is hovered: selectHoverStyle when …

Returns the name of the StyleMap render intent a feature should be drawn with right now, given whether it is selected (in layer.selectedFeatures) and whether it is hovered: selectHoverStyle when both, selectedStyle when only selected, hoverStyle when only hovered, defaultStyle otherwise. Useful when redrawing a feature yourself (layer.drawFeature(feature, style)) after changing its attributes.

feature OpenLayers.Feature.Vector
The feature to inspect.
hovered Boolean
Whether the mouse is currently over the feature.

Returns The render intent name, e.g. "select".

feature.attributes.value = newValue;
layer.drawFeature(feature, layer.selectController.getFeatureCurrentStyle(feature, false));

highlight

function(feature)# Highlights a feature as if the mouse were over it, without selecting it: redraws it with hoverStyle (or selectHoverStyle when it is selected) and fires the control's …

Highlights a feature as if the mouse were over it, without selecting it: redraws it with hoverStyle (or selectHoverStyle when it is selected) and fires the control's beforefeaturehighlighted/featurehighlighted events — which, on a file layer, run the onHover callback with state true. Use it to mirror a hover coming from a list or chart outside the map; call unhighlight to revert.

feature OpenLayers.Feature.Vector
The feature to highlight.
// highlight a municipality when its row is hovered in a table
layer.selectController.highlight(layer.findFeatureById(rowId));

hover

Boolean= false# Highlight on mouse over and unhighlight on mouse out (without selecting).

Highlight on mouse over and unhighlight on mouse out (without selecting). The platform sets it for layers with onHover; the featurehighlighted / featureunhighlighted events of the control fire the layer's onHover callback.

hoverStyle

String= "hover"# Name of the StyleMap render intent used to draw a hovered, unselected feature.

Name of the StyleMap render intent used to draw a hovered, unselected feature. It matches the VectorLayer.hoverStyle entry of the layer's styleMap.

multiple

Boolean= false# Allows more than one selected feature at a time: with false selecting a feature unselects the previous one.

Allows more than one selected feature at a time: with false selecting a feature unselects the previous one. Pass it through onClickCfg: {multiple: true}.

outFeature

function(feature)# Internal — feature-handler callback run when the mouse leaves a feature (only registered when hover is true): unhighlights it, redrawing with defaultStyle or, if it is selected, …

Internal — feature-handler callback run when the mouse leaves a feature (only registered when hover is true): unhighlights it, redrawing with defaultStyle or, if it is selected, selectedStyle; when another select control had highlighted the feature before, that control's highlight is restored instead. Tenant code normally does not call it; call unhighlight instead.

feature OpenLayers.Feature.Vector
The feature the mouse left.

overFeature

function(feature)# Internal — feature-handler callback run when the mouse enters a feature (only registered when hover is true): highlights it, redrawing with hoverStyle or, if it is selected, selectHoverStyle.

Internal — feature-handler callback run when the mouse enters a feature (only registered when hover is true): highlights it, redrawing with hoverStyle or, if it is selected, selectHoverStyle. Tenant code normally does not call it; call highlight instead.

feature OpenLayers.Feature.Vector
The feature under the mouse.

select

function(feature)# Selects a feature programmatically, exactly as a click would: adds it to layer.selectedFeatures, redraws it with selectedStyle (or selectHoverStyle while hovered), fires the layer's …

Selects a feature programmatically, exactly as a click would: adds it to layer.selectedFeatures, redraws it with selectedStyle (or selectHoverStyle while hovered), fires the layer's beforefeatureselected/featureselected events and calls the onSelect option — so a file layer's onClick/onSelectionToggle callback runs too. Does nothing when the control was created with click: false. Use it to select a feature from a list or a parent-page message; unselectAll() (inherited) clears the selection.

feature OpenLayers.Feature.Vector
The feature to select (must belong to the control's layer).
// select the feature whose attribute matches, from a tenant global called by a button
var layer = ExtjsUtils.LAYER.getLayerByName("CSR:municipios");
var feature = layer.findFeatureById(featureId);
if (feature) {
    layer.selectController.unselectAll();
    layer.selectController.select(feature);
}

selectHoverStyle

String= "selectedHover"# Name of the StyleMap render intent used to draw a feature that is selected AND hovered.

Name of the StyleMap render intent used to draw a feature that is selected AND hovered. It matches the VectorLayer.hoverSelectedStyle entry of the layer's styleMap.

selectedStyle

String= "selected"# Name of the StyleMap render intent used to draw a selected feature that is not hovered.

Name of the StyleMap render intent used to draw a selected feature that is not hovered. The platform passes "select" for file layers (the VectorLayer.selectStyle entry of the layer's styleMap); this is the stock default otherwise.

unhighlight

function(feature)# Removes the hover highlight of a feature: redraws it with the feature's own style if it has one, else the layer's style, else defaultStyle (or selectedStyle when it is selected), and fires …

Removes the hover highlight of a feature: redraws it with the feature's own style if it has one, else the layer's style, else defaultStyle (or selectedStyle when it is selected), and fires the control's featureunhighlighted event — which, on a file layer, runs the onHover callback with state false. When several select controls highlighted the feature, the previous control's highlight is kept.

feature OpenLayers.Feature.Vector
The feature to unhighlight.
layer.selectController.unhighlight(layer.findFeatureById(rowId));

unselect

function(feature)# Unselects a feature programmatically: removes it from layer.selectedFeatures, redraws it with defaultStyle (or hoverStyle while hovered), fires the layer's featureunselected event and calls …

Unselects a feature programmatically: removes it from layer.selectedFeatures, redraws it with defaultStyle (or hoverStyle while hovered), fires the layer's featureunselected event and calls the onUnselect option — so a file layer's onSelectionToggle callback runs with its unselect status. Does nothing when the control was created with click: false.

feature OpenLayers.Feature.Vector
The feature to unselect.
var selected = layer.selectedFeatures.slice();
selected.forEach(function(feature) { layer.selectController.unselect(feature); });

File layers: vertex editing control

CustomModifyFeature5 entries
The vertex-editing control of drawable vector layers, reachable as layer.drawableController.modifyFeatureControl. Extends OpenLayers.Control.ModifyFeature.

Drawing

Object# Pure drawing/status constants and helpers of the modify control (no control instance needed), reachable as OpenLayers.Control.CustomModifyFeature.Drawing.

Pure drawing/status constants and helpers of the modify control (no control instance needed), reachable as OpenLayers.Control.CustomModifyFeature.Drawing. What a query uses from it is DRAWING_STATUS, the enum of the detail.status values that drawable.onDrawingStatusChange(detail) reports: OFF: "off" (not editing), READY: "ready" (editing active, nothing sketched or selected), DRAWING: "drawing" (a polygon sketch is in progress), DRAWING_LINE: "drawing_line" (a line sketch is in progress), FEATURE_SELECTED: "feature_selected" (an existing feature is selected for editing) and VERTEX_DRAG: "vertex_drag" (a vertex of the selected feature is being dragged). It also holds DRAW_MODES (POLYGON: "polygon", LINE: "line", the detail.drawMode values), the default Portuguese STATUS_LABELS per status, MIN_POLYGON_SKETCH_POINTS (4) / MIN_LINE_SKETCH_POINTS (2) and minSketchPointsForMode(drawMode). Compare against the constants instead of hard-coding the strings.

drawable: {
    onDrawingStatusChange: function(detail) {
        var S = OpenLayers.Control.CustomModifyFeature.Drawing.DRAWING_STATUS;
        finishButton.setDisabled(!(detail.status === S.DRAWING || detail.status === S.DRAWING_LINE) || !detail.canFinishDrawing);
        applyButton.setDisabled(detail.status !== S.FEATURE_SELECTED);
    }
}

buildStatusDetail

function() : Object# Builds the current drawing/edit status of the control on demand — the same detail object drawable.onDrawingStatusChange(detail) receives, so a host UI can read the state at any moment (e.g. when …

Builds the current drawing/edit status of the control on demand — the same detail object drawable.onDrawingStatusChange(detail) receives, so a host UI can read the state at any moment (e.g. when it is first shown) instead of waiting for the next change. Fields: status (one of CustomModifyFeature.Drawing.DRAWING_STATUS, never "off" here — the control only exists while editing), drawMode, isDrawing, featureSelected, vertexDrag, selectedFeature (the OpenLayers.Feature.Vector or null), sketchPointCount, canFinishDrawing, canDeselectFeature, canApplyFeatureChanges and canCancelDrawing. Reachable as layer.drawableController.modifyFeatureControl.buildStatusDetail().

Returns The status detail object described above.

var detail = layer.drawableController.modifyFeatureControl.buildStatusDetail();
if (detail.canApplyFeatureChanges) {
    layer.drawableController.applyFeatureChanges();
}

getActiveDrawMode

function() : String# The geometry mode new sketches use on this control: "polygon" (default) or "line" (only when the layer's drawable.drawModes includes it), i.e. one of CustomModifyFeature.Drawing.DRAW_MODES.

The geometry mode new sketches use on this control: "polygon" (default) or "line" (only when the layer's drawable.drawModes includes it), i.e. one of CustomModifyFeature.Drawing.DRAW_MODES. Reachable as layer.drawableController.modifyFeatureControl.getActiveDrawMode(); the same value arrives as detail.drawMode in onDrawingStatusChange.

Returns "polygon" or "line".

var control = layer.drawableController.modifyFeatureControl;
if (control.getActiveDrawMode() === OpenLayers.Control.CustomModifyFeature.Drawing.DRAW_MODES.LINE) {
    console.log("next sketch cuts polygons along a line");
}

getSelectedFeatureId

function() : String|Number|null# Id of the feature currently selected for editing.

Id of the feature currently selected for editing.

isFeatureSelected

function() : Boolean# Whether a feature of the layer is currently selected for editing on this control (its vertices are shown and draggable).

Whether a feature of the layer is currently selected for editing on this control (its vertices are shown and draggable). Reachable as layer.drawableController.modifyFeatureControl.isFeatureSelected(); use getSelectedFeatureId() to know which one.

Returns true while a feature is selected for editing.

var control = layer.drawableController.modifyFeatureControl;
if (control.isFeatureSelected()) {
    console.log("editing feature " + control.getSelectedFeatureId());
}

Tile layers (xyz)

XYZLayer3 entries
source: "xyz": tiles of a tile service, addressed by ${z}, ${x} and ${y} in url.

name

String# Defines a map identifier.

Defines a map identifier. This name should be unique.

[
 ...
     {
        source: "xyz",
        name:"XYZ:map_name",
     }
 ...
]

source

Object# Adds a layer to store the source.

Adds a layer to store the source.

layerCfg LayerConfig
Layer XYZ configuration. LayerConfig { url: url, name: name, isBaseLayer: isBaseLayer, sphericalMercator: sphericalMercator }

url

String# Defines the url where the map can be fetched from.

Defines the url where the map can be fetched from. Use the ${x} ${y} ${z} as placeholder for x, y and z coordinates.

"https://tiles.planet.com/basemaps/v1/planet-tiles/planet_medres_visual_2021-09_mosaic/gmap/${z}/${x}/${y}.png?api_key=b24ae87a99624d2cbd8ed6aeb9703280"

Groups: what you write in a group

A group holds layers, or other groups, in its elements. A top-level group with title is an entry of the top menu that lists its layers, each with a switch; a group with viewTitle is a heading in the layer panel. defaultProperties passes layer properties to every layer inside that does not set them itself.
Not the same as the layer key group, of which only group: "background" does something (it makes the layer a basemap).
Two groups, each an entry of the top menu:
Example
[
   {
      title: 'My first Group!',
      color: '#A020F0',
      elements: [
         {
            title: 'Layer 1 of group 1',
            name: 'CSR:batimetria',
            visibility: true,
         },
      ],
   },
   {
      title: 'My second Group!!',
      color: '#FFA900',
      elements: [
         {
            title: 'Layer 1 of group 2',
            name: 'CSR:altimetria',
            visibility: true,
         },
      ],
   },
]

Group properties

GroupProperties8 entries
Keys of a group object, written next to its elements: title or viewTitle, color, openGroup, defaultProperties...

color

String= string.emptyproperty# Defines the Color of the group.

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.

[
   {
      title: 'My orange group',
      color: '#FFA500',
   },
]

customLayerClass

String= string.emptyproperty# 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.

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 layer row instead (ConfigLayer.customLayerClass).

[
  {
     viewTitle: 'Styled group',
     viewColor: '#FFA500',
     title: 'Group 1',
     color: '#666699',
     customLayerClass: 'highlighted-group',
     elements: [
        {
           title: 'Layer 1',
           name: 'CSR:estados',
           source: 'local',
           startListed: true,
        },
     ],
  },
]

defaultProperties

Object= {}property# Specifies properties that apply universally to all layers within a group, including nested subgroups and their respective layers.

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 the nearest group, and so forth.

[
  {
     title: 'Example of defaultProperties',
     color: '#FFA500',
     defaultProperties: {
        source: 'local',
        visibility: true,
        opacity: 0.7,
     },
     elements: [
        {
           title: 'Layer 1',
           name: 'CSR:geologia',
        },
        {
           title: 'Layer 2',
           name: 'CSR:rios_principais',
        },
        {
           title: 'Layer 3',
           name: 'CSR:estados',
           // Any internal redefinition will override the defaultProperties
           visibility: false,
        },
     ],
  },
]

elements

Array.<Layers>= Array.emptyproperty# Defines the Layers that will be part of the Group.

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 custom functions that can be writen in JavaScript.

[
  {
     title: 'A group with Layers!',
     color: '#FFA500',
     elements: [
        // Define your Layers here
     ],
  },
]

See also To learn more about Layers and it’s properties, check their documentation at: Layer Section.

global

Objectproperty# 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).

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 ExtjsUtils.QUERY.setQueryGlobalProperties({...}) && [...] chain at the top of the query; the production survey found no query using this key (zero users).

[
  {
     title: 'Group with its own globals',
     global: {
        formatArea: function(value) { return ExtjsUtils.NUMBER.abbreviateNumber(value) + ' ha'; }
     },
     elements: [
        { title: 'Layer 1', name: 'CSR:estados', source: 'local', visibility: true }
     ]
  }
]

openGroup

Boolean= falseproperty# Defines if the 'viewTitle' should start opening or collapse.

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 Layers or any Layer has the 'openGroup' property set to 'true', the Group View will start open. It works at both levels: on the viewTitle group it makes the group start expanded, on a layer it expands every viewTitle ancestor of that layer.

[
  {
     viewTitle: 'This Group View will start opened',
     viewColor: '#FFFFFF',
     title: 'Group 1',
     color: '#666699',
     openGroup: true,
     elements: [
        {
           title: 'Layer 1',
           name: 'CSR:estados',
           source: 'calculate',
           startListed: true,
        },
     ],
  },
  {
     viewTitle: 'This Group View will start closed',
     viewColor: '#FFFFFF',
     title: 'Group 2',
     color: '#666699',
     elements: [
        {
           title: 'Layer 2',
           name: 'CSR:rios_principais',
           source: 'calculate',
           startListed: true,
        },
     ],
  },
]

title

String= string.emptyproperty# Defines the Title of the group.

Defines the Title of the group. The Title is shown at the sub menu on the top of the screen.

[
   {
     title: 'My new group!',
   },
]

viewTitle

String= string.emptyproperty# Define the Title of the View that will gather together the elements inside it (Groups or other Views).

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.

// Exemple 1: View with a Layers inside it
[
  {
     viewTitle: 'This View has a Group 3 Layers',
     title: 'This is a Group with 3 Layers',
     color: '#5BA300',
     elements: [
        {
           title: 'Layer 1',
           name: 'CSR:estados',
           source: 'local',
           opacity: 0.5,
           visibility: true,
        },
        {
           title: 'Layer 2',
           name: 'CSR:rios_principais',
           source: 'local',
           opacity: 0.5,
           visibility: true,
        },
        {
           title: 'Layer 3',
           name: 'CSR:geologia',
           source: 'local',
           opacity: 0.65,
           visibility: true,
        },
     ],
  },
]
// Exemple 2: View with others 'viewTitle' defined inside it
[
  {
     // This is the definition of the View
     viewTitle: 'This External View has 2 others Inner Views inside it, each with 1 Group that has 1 Layer',
     title: 'This View has 2 Groups, each with 1 Layer',
     color: '#0073E6',
     elements: [
        {
           title: 'Group 1',
           // This 'viewTitle' will create a division in the menu that shows when the mouse hovers the navigation bar option 'This View has 2 Groups, each with 1 Layer' 
           viewTitle: 'Inner View with Group 1',
           color: '#E6308A',
           elements: [
              {
                 title: 'Group 1 - Layer 1',
                 name: 'CSR:altimetria',
                 source: 'local',
                 visibility: true,
              },
           ],
        },
        {
           title: 'Group 2',
           // This 'viewTitle' will create a division in the menu that shows when the mouse hovers the navigation bar option 'This View has 2 Groups, each with 1 Layer'
           viewTitle: 'Inner View with Group 2',
           color: '#B51963',
           elements: [
              {
                 title: 'Group 2 - Layer 1',
                 name: 'CSR:batimetria',
                 source: 'local',
                 visibility: true,
              },
           ],
        },
     ],
  },
]

Group callbacks (viewTitle groups)

GroupFunctions2 entries
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.

onClickViewGroup

function= nullcallback# Called whenever the user clicks the title of a viewTitle group in the Legend Window.

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 the click. When declared on a layer instead of a group, it is attached to the layer's nearest viewTitle ancestor (once per layer that declares it); on a flat layer with no viewTitle ancestor it is bound to the invisible root node, i.e. it never fires.

view Ext.tree.TreeNode
The tree node of the group that was clicked (view.expanded, view.text, view.childNodes).
clickEvent Ext.EventObject
The click event, with details such as the mouse position.
[
  {
     viewTitle: 'Example View (Click me!)',
     viewColor: '#FFA500',
     title: 'Click the view to change its state',
     color: '#666699',
     openGroup: true,
     onClickViewGroup: function handleClickViewGroup(view, clickEvent) {
        let viewState = (view.expanded ? 'open' : 'closed');
        ExtjsUtils.ALERTIFY.log('The ' + view.text + ' is ' + viewState );
     },
     elements: [
        {
           title: 'Layer 1',
           name: 'CSR:estados',
           source: 'local',
           startListed: true,
        },
     ],
  },
]

onToggleViewGroup

function= nullcallback# Called whenever a viewTitle group of the Legend Window is expanded or collapsed (by the user or by code).

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 an expand and false after a collapse. When declared on a layer instead of a group, it is attached to the layer's nearest viewTitle ancestor (once per layer that declares it); on a flat layer with no viewTitle ancestor it is bound to the invisible root node, i.e. it never fires. A typical use is hiding the layers of the collapsed group and restoring them on expand.

view Ext.tree.TreeNode
The tree node of the group whose state changed (view.expanded, view.text, view.childNodes).
[
  {
     viewTitle: 'Example View (Click me!)',
     viewColor: '#FFA500',
     title: 'Click the view to change its state',
     color: '#666699',
     openGroup: true,
     onToggleViewGroup: function handleToggleViewGroup(view) {
        let viewState = (view.expanded ? 'open' : 'closed');
        ExtjsUtils.ALERTIFY.log('The ' + view.text + ' is ' + viewState );
     },
     elements: [
        {
           title: 'Layer 1',
           name: 'CSR:estados',
           source: 'local',
           startListed: true,
        },
     ],
  },
]

Panel widgets

Controls written inside the descriptionHtml of a calculated, file or tile layer, as {{tag|param=value|param2=value}}: sliders, lists, buttons, windows. A widget with an id becomes an input of the layer's functions. Not the toolbar buttons of a map link (tools=, under Map links and embedding).
The markup rules shared by every widget come first; each widget also has a page with a live example under the Tools tab.
Examples:
Example
{
    ...,
    descriptionHtml: '{{toolIdentifier|paramName=paramValue}}',
    ...
}

{
    ...,
    descriptionHtml: '{{button|id=btn_id|enableToggle=false}}' + '{{opacityslider}}',
    ...
}

Markup rules for every widget

MarkupSyntax11 entries
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 of the layer 'functions' object, then a global with that name (setQueryGlobalProperties), then the text itself evaluated as a function (a body, or a full 'function(){...}' expression).

cls

String# cls=<class> adds CSS classes to the created element.

cls=<class> 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).

{{label|cls=slider_label bold|text=0%}}

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 …

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 arrays or objects (data, steps, values, filterLayers, backgroundColors) parse the string themselves as JSON. true/false are NOT converted: param=true is the string "true" (truthy) and param=false is rewritten to an empty value (see falseValue). A parameter written without = (|pressed|) also gets the empty string, except for the special keys listed in this group (isnumeric). The same parameter written twice keeps the last value (cls and on_<event> accumulate instead).

{{slider|id=s|minValue=0|maxValue=100|value=20|fieldLabel=Deforestation}}

escapedEquals

String# Write \= to put a literal = inside a value; a bare = would start a nested key (see nestedKeys).

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: everything after its first = is kept as is.

{{loadcsv|id=csv|url=/wmtp/calc/areacategorical/?layers\=CSR:estados&styles\=1}}

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.

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, hideLabel=false). Only a false at the very end of the parameter is rewritten.

{{pickpoint|id=pick|unselect=false|notify=false}}

function

function# function=<body> stores a function whose body is the given text (function () { <body> }), evaluated with no try/catch and no lookup in the layer functions.

function=<body> stores a function whose body is the given text (function () { <body> }), evaluated with no try/catch and no lookup in the layer functions. Use the nested form param=function=<body> to assign it to a parameter (a top-level function= only sets a function key); escape any = in the body as \=. Rarely needed: the callback parameters of the tools (handler, runOnClick, onSelect...) already accept function names or inline text.

{{button|id=b|text=Log|handler=function=console.log('clicked')}}

getid

Object# getid=ID gives access to an element created EARLIER in the same description (by any tag with that id).

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 getid=ID|getid=on_<event>=... (see on_event), or the nested param=getid=ID to hand the element to a parameter (scope=getid=btn). Order matters: the referenced tag must appear before the one using getid.

{{slider|id=perc_slider|value=20}}{{label|id=perc_label|text=20%|getid=perc_slider|getid=on_change=Ext.getCmp('perc_label').setText(this.getValue() + '%')}}

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.

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.

{{label|html=<a href="https://maps.csr.ufmg.br/?queryid=1">open</a>}}

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.

|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; convert it with parseFloat.

{{textfield|id=soy_value|value=43|isnumeric|fieldLabel=Value (US$/Ton)}}

nestedKeys

Object# a=b=c creates a nested object: the tool receives {a: {b: c}}.

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 element created earlier, listeners=on_change=... is not needed because getid/on_<event> already cover the common case.

{{slider|id=s|plugins=tip={0}% of the area}}

on_event

function# on_<event>=<code> adds a listener for an Ext event (change, select, afteredit, toggle...) on an element referenced with getid — the form is getid=ID|getid=on_<event>=<code>; it cannot …

on_<event>=<code> adds a listener for an Ext event (change, select, afteredit, toggle...) on an element referenced with getid — the form is getid=ID|getid=on_<event>=<code>; it cannot be used on the tag's own element. <code> is either a full function(...) {...} or a statement body; it is evaluated directly (no lookup in the layer functions or in globals) and runs with this = the referenced element and the event's own arguments. Several on_ listeners may be attached to the same element.

{{textfield|id=price|isnumeric}}{{label|id=price_lbl|getid=price|getid=on_afteredit=Ext.getCmp('price_lbl').setText('US$ ' + this.getRawValue())}}

tip

Object# tip=<format> 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.

tip=<format> 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=<format>; a top-level tip= is stored in the config but not used by the slider.

{{slider|id=perc_slider|plugins=tip={0}% of the area|increment=5}}

Free HTML

HTML1 entry
Any HTML is possible to be added to the layer description.

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 …

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 HTML mix freely in the same string, and the HTML around a widget is rendered before the widget is created, so an element declared here can already be referenced by an id.

Two things to keep in mind. Inside a {{tag|...}} the pipe separates parameters, so HTML that must live in a parameter goes in html= (verbatim to the end of the value) or has its = escaped as \\=. And the description is written inside a JavaScript string in the query, so quotes have to be escaped or alternated as usual.

descriptionHtml:
  '<h3>Deforestation</h3>' +
  '<p>Pick the minimum area to highlight.</p>' +
  '{{slider|id=threshold|minValue=0|maxValue=100|value=20}}' +
  '<div id="chart_area" style="height:220px"></div>'

areaintegral · sum inside a rectangle (input)

AreaIntegral9 entries

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

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}}

getLayerValues

function(mousePoint, layer) : Array.<Number>|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.

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 the rectangle with it and combines them as a summed-area table (sum = minXY + maxXY - minXmaxY - maxXminY), which is why the maps must be published with the integral operation. Returns null when the layer is hidden or the position is outside the map data.

mousePoint Object
Absolute screen position {x, y} to sample.
layer OpenLayers.Layer.Composed
The composed layer to read (normally the tool's own layer).

Returns [value of layer 0, ..., value of layer n-1, expression result], or null.

iconCls

String= cmn-toggle-icon# Defines the CSS class of the toggle switch icon; replace the default to restyle the switch.

Defines the CSS class of the toggle switch icon; replace the default to restyle the switch.

|iconCls=my-toggle-icon|

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)).

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.

|id=integral_tool|

labelBefore

Boolean= false# Set true to render the text label before (left of) the toggle switch instead of after it.

Set true to render the text label before (left of) the toggle switch instead of after it.

|labelBefore=true|

notify

Boolean= true# Set false to suppress the notification shown when the tool is activated.

Set false to suppress the notification shown when the tool is activated.

|notify=false|

runOnClick

function# Defines the callback run after the second click closes the rectangle, with the sums computed.

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 getLayerValues), inputs is layer.getInputs(), boundingBox is [minLon, minLat, maxLon, maxLat] in EPSG:4326, pixel the {x, y} of the second click and lastInfo the {first, second} {lon, lat} of the two clicks. The name is resolved as a key of the layer functions object, then as a global function, then as inline function text. The tool deactivates itself after the callback.

|runOnClick=onAreaSummed|
functions: {
    onAreaSummed: function(layersValues, inputs, boundingBox, pixel, lastInfo) {
        ExtjsUtils.ALERTIFY.log('Sum inside ' + boundingBox.join(', ') + ': ' + layersValues[0]);
    }
}

text

String# Defines the text shown next to the toggle switch.

Defines the text shown next to the toggle switch.

|text=Sum a rectangle|

unselect

Boolean= true# Only changes the activation message (true: one selection expected, false: several); the tool always deactivates itself after the second click.

Only changes the activation message (true: one selection expected, false: several); the tool always deactivates itself after the second click.

|unselect=false|

value

Array.<Number># 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).

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 beforeCalc/expression always read the latest sums. The input is registered on the forceupdatelayer event of the switch, which the tool does not fire by itself: react inside runOnClick, or call Ext.getCmp(id).items.get(0).forceUpdateLayer() there to recalculate the layer with the new sums.

{{areaintegral|id=integral_tool|runOnClick=onAreaSummed}}
functions: {
    onAreaSummed: function(layersValues, inputs) {
        Ext.getCmp('integral_tool').items.get(0).forceUpdateLayer(); // beforeCalc will see inputs.id['integral_tool']
    }
}

button · push or toggle button

Button9 entries

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

Create a simple button to user interact with the map.
This button is created from Button.Configs.
Only some properties are listed in API here.

enableToggle

Boolean= false# Defines the button type as toggle.

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'.

|enableToggle=true|

fieldLabel

String# Defines the button label.

Defines the button label.

|fieldLabel=A button|

handler

function= undefined# Defines the callback function on button click event.

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 global function with that name (e.g. defined with setQueryGlobalProperties); (3) otherwise the text itself is evaluated as a function — either a full function(){...} expression or a plain statement body. With enableToggle=true and no toggleHandler, handler is used as the toggle handler.

button Ext.Button
The button element that was clicked.
clickEvent EventObject
An event object carrying information about the click event.
|handler=onExportClick|
|handler = function (button, clickEvent){
 console.log(button, clickEvent);
}|

hidden

Boolean= false# Set true to create the button hidden (Ext hidden config); show it later with Ext.getCmp(id).show().

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 markup is handed to the button unchanged.

|hidden=true|

id

String# Defines the id to identify the object.

Defines the id to identify the object.

|id=exemple_button|

pressed

Boolean= false# Defines the button initial state.

Defines the button initial state. Set it true to start pressed (only if enableToggle = true), false otherwise.

|pressed=true|

text

String# Defines the button text.

Defines the button text.

|text=Click On Me|

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.

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.

|enableToggle=true|toggle=onToggleDetails|

toggleHandler

function= undefined# Defines the callback function on button toggle event.

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 global function with that name (e.g. defined with setQueryGlobalProperties); (3) otherwise the text itself is evaluated as a function — either a full function(){...} expression or a plain statement body.

button Ext.Button
The button element that was clicked.
state Boolean
The next state of the button, true means pressed.
|enableToggle=true|toggleHandler=onToggleDetails|
|toggleHandler = function (button, pressed){
 console.log(button, pressed);
}|

checkbox · on/off, calls a function

Checkbox13 entries

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

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}}
This tool is created from Ext.form.Checkbox.
Only customized properties are listed here.

checked

Boolean= false# Set true to start checked.

Set true to start checked. handler is not run for the initial state.

|checked=true|

fieldLabel

String# Defines a label at the left of the whole field (Ext fieldLabel), in addition to the text shown next to the switch.

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.

|fieldLabel=Options|

forceUpdateLayer

function()# Fires the forceupdatelayer event of the widget.

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 currently stored in inputs.id[ID].

Ext.getCmp('sum_tool').items.get(0).forceUpdateLayer();

handler

function# Defines the callback run whenever the checkbox is checked or unchecked (by the user or by toggle()).

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 function with that name, then the text itself evaluated as a function (a full function(){...} or a statement body). The checkbox is not a layer input: read checked here and act (e.g. setValues on an InputManager, changeLayers...). It is also called once with checked=false when the widget is removed together with its layer.

|handler=onToggleDetails|
functions: {
    onToggleDetails: function(checkbox, checked) {
        this.getInputs().id['state'].setValues({details: checked});
    }
}

iconCls

String= cmn-toggle-icon# Defines the CSS class of the toggle switch icon; replace the default to restyle the switch.

Defines the CSS class of the toggle switch icon; replace the default to restyle the switch.

|iconCls=my-toggle-icon|

id

String# Defines the id of the checkbox component (Ext.getCmp(id)), e.g. to call toggle() or setBoxLabel() from a button.

Defines the id of the checkbox component (Ext.getCmp(id)), e.g. to call toggle() or setBoxLabel() from a button. Generated when omitted.

|id=show_details|

inputValue

String# Defines the DOM value attribute of the underlying <input type="checkbox"> (useful inside an HTML form).

Defines the DOM value attribute of the underlying <input type="checkbox"> (useful inside an HTML form).

|inputValue=details|

labelBefore

Boolean= false# Set true to render the text before (left of) the toggle switch instead of after it.

Set true to render the text before (left of) the toggle switch instead of after it.

|labelBefore=true|

notify

Boolean= true# Accepted for parity with the map-picking switches (pickpoint, hoverpixel...), where it controls the activation notification.

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

function(boxLabel)# Changes the text shown next to the checkbox (the markup text parameter) after it was rendered.

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).

boxLabel String
New label text (HTML allowed).
Ext.getCmp('my_checkbox').setBoxLabel('Show details (3)');

text

String# Defines the text shown next to the toggle switch (the checkbox boxLabel).

Defines the text shown next to the toggle switch (the checkbox boxLabel).

|text=Show details|

toggle

function(forceState)# Checks or unchecks the checkbox from code, running its handler as if the user had clicked it.

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).

forceState Boolean
true to check, false to uncheck; omit to invert the current state.
Ext.getCmp('show_details').toggle(false); // uncheck

unselect

Boolean= true# Accepted for parity with the map-picking switches, where it selects the activation message.

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.

combobox · pick from a list (input)

Combobox11 entries

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

It creates an input of ComboBox tool where the value is selectable from a list.
Usage: '{{combobox}}' or examples.
This button is created from Ext.form.ComboBox for customized properties click on API here.

data

Array.<Array.<String>>= undefined# Defines the data that will be displayed in the Combobox.

Defines the data that will be displayed in the Combobox.

|data = [["Val_1"], ["Val_2"],..]|

editable

Boolean= false# Determines if the Combobox is editable.

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.

|editable=true|

fieldLabel

String# Defines a label for the Combobox.

Defines a label for the Combobox. It will be shown at the left of the Combobox, by default.

|fieldLabel=This is the field label|

getValue

function() : String# Returns the currently selected value (the text of the chosen data entry).

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.

Returns The selected value.

var region = Ext.getCmp('region_combo').getValue();

hideLabel

Boolean= false# Defines if the label of the Combobox should be displayed.

Defines if the label of the Combobox should be displayed. Set true to hide the label, false to show it.

|hideLabel=true|

id

String# Defines the id to identify the object.

Defines the id to identify the object.

|id=legend_combobox|

labelStyle

String# Defines the style of the label.

Defines the style of the label. You can use CSS to style the label element.

|labelStyle=font-weight: bold; color: red;|

onSelect

function# Defines a callback run when the user picks an entry.

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 object or, failing that, the text itself is evaluated as a function (a body or a full function(){...}); unlike the other callbacks it does NOT look for a global (setQueryGlobalProperties) function of that name. PS: the layer is recalculated on select anyway; use onSelect for side effects such as changing layers or updating a window.

|onSelect=onRegionSelected|
functions: {
    onRegionSelected: function(combo, record, index) {
        this.changeLayers({name: 'CSR:' + record.get('value'), index: 0});
    }
}

setValue

function(value)# Selects an entry from code.

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.

value String
One of the values listed in data.
Ext.getCmp('region_combo').setValue('Protected Areas');

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).

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).

{{combobox|id=region_combo|fieldLabel=Region|data=[['Municipalities'],['Protected Areas']]}}
beforeCalc: function(inputs) {
    var region = inputs.id['region_combo']; // 'Municipalities' or 'Protected Areas'
}

width

Number= 190# Defines the width of the combobox in pixels.

Defines the width of the combobox in pixels.

|width=250|

filefield · open a local file (input)

FileField7 entries

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

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')}}}

eventNames

Array.<string># Defines the list of events by name.

Defines the list of events by name. Use this property to define callback functions to any of the following events.

['added', 'afterrender', 'beforedestroy', 'beforehide', 'beforerender', 'beforeshow', 'beforestaterestore',
'beforestatesave', 'blur', 'change', 'destroy', 'disable', 'enable', 'focus', 'hide', 'invalid', 'move', 'removed', 'render',
'resize', 'show', 'specialkey', 'staterestore', 'statesave', 'valid']

fieldLabel

String# Defines the label shown at the left of the file input (Ext fieldLabel).

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.

|fieldLabel=Load a shapefile (.zip)|

hideLabel

Boolean= false# Set true to hide the label element and the space reserved for it.

Set true to hide the label element and the space reserved for it.

|hideLabel=true|

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.

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.

|id=loadshp|

ignoreUpdate

Boolean= false# Defines if it should ignore the widget change event.

Defines if it should ignore the widget change event. If it's false, it dispatches the update event at every file selection.

inputType

String= file# The HTML input type.

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

function# Value stored in inputs.id[ID]: not the file itself but a getter 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 be serialized to the calculation WebWorker (expression); read it in beforeCalc, in a _onchange= callback or in a button handler. The layer recalculates on the change event of the input (a new file chosen) unless ignoreUpdate=true.

{{filefield|fieldLabel=loadshp|id=loadshp|_onChange=onSelectFile}}
functions: {
    onSelectFile: function() {
        var file = this.getInputs().id['loadshp']();
        if (file) ExtjsUtils.GEOJSON.shapefile2GeojsonAsync(file, {layer: this, fromProj: 'EPSG:4326'});
    }
}

hoverpixel · value under the mouse (input)

Hoverpixel16 entries

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

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}}

checked

Boolean= false# Defines if the hoverPixel should start enabled.

Defines if the hoverPixel should start enabled. Set true to start enabled, false otherwise.

|checked = true|

fieldLabel

String# Define the text that will be displayed at the left of the toggler

Define the text that will be displayed at the left of the toggler

|text=This is the label text|

getLayerValues

function(evt, layer) : Array.<Number>|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.

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 runOnClick/runOnHover; call it from code (Ext.getCmp(id).items.get(0).getLayerValues(evt, layer)) to sample the map from any mouse event. Returns null when the layer is hidden, the legend is not loaded yet, or the mouse is outside the map data (all layers null/transparent).

evt MouseEvent
Mouse event with the screen position to sample.
layer OpenLayers.Layer.Composed
The composed layer to read (normally the tool's own layer).

Returns [value of layer 0, ..., value of layer n-1, expression result], or null.

hideLabel

Boolean= false# Defines if the label of the HoverPixel should be displayed.

Defines if the label of the HoverPixel should be displayed. Set true to hide the label, false to show it.

|hideLabel=true|

iconCls

String= cmn-toggle-icon# Defines the CSS class of the toggle switch icon; replace the default to restyle the switch.

Defines the CSS class of the toggle switch icon; replace the default to restyle the switch.

|iconCls=my-toggle-icon|

id

String# Defines the id to identify the object.

Defines the id to identify the object.

|id=exemple_hover_pixel|

labelBefore

Boolean= false# Set true to render the text label before (left of) the toggle switch instead of after it.

Set true to render the text label before (left of) the toggle switch instead of after it.

|labelBefore=true|

labelStyle

String# Defines the style of the label at the HoverPixel toggler.

Defines the style of the label at the HoverPixel toggler. You can use CSS to style the label element.

|labelStyle=font-weight: bold; color: red;|

notify

Boolean= true# Set false to suppress the notification shown when the tool is activated ("click on the map...").

Set false to suppress the notification shown when the tool is activated ("click on the map...").

|notify=false|

runOnClick

function= undefined# Defines a callback when the user clicks on the map.

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)

layerVals Array
Array with the values of the maps at the pixel that was clicked.
inputs Array
Array with the values of the inputs defined in the descriptionHtml.
coordinates OpenLayers.LonLat
The point that was clicked, in the map's projection (Web Mercator, metres) despite the names: lon is x and lat is y. For degrees, transform it: coordinates.clone().transform(ExtjsUtils.JS.getMap().getProjectionObject(), new OpenLayers.Projection("EPSG:4326")) (lastCoordinates below already holds degrees, of the previous click and hover).
clickEvent MouseEvent
Mouse event that triggered the function.
lastCoordinates Object
Object with the last coordinates (latitude, longitude) from the last click and the last hover events. lastCoordinates = { click: { lat: // Latitude of the last click lon: // Longitude of the last click }, hover: { lat: // Latitude of the last hover lon: // Longitude of the last hover } }
|handleOnClick: function(layerVals, inputs, coordinates, clickEvent, lastCoordinates) {
     var degrees = coordinates.clone().transform(ExtjsUtils.JS.getMap().getProjectionObject(), new OpenLayers.Projection("EPSG:4326"));
     ExtjsUtils.ALERTIFY.log("Latitude: " + degrees.lat.toFixed(3) + " Longitude: " + degrees.lon.toFixed(3));
}|

runOnClickOutside

function# True to run the callback function even when clicking outside of the layer, False to disable.

True to run the callback function even when clicking outside of the layer, False to disable. (Default False)

runOnHover

function= undefined# Defines a callback when the user hovers the map.

Defines a callback when the user hovers the map.

It passes the following parameters for the callback function: handleOnClick(layerVals, inputs, coordinates, clickEvent, lastCoordinates)

layerVals Array
Array with the values of the maps at the pixel that was hovered.
inputs Array
Array with the values of the inputs defined in the descriptionHtml.
coordinates OpenLayers.LonLat
The point that was hovered, in the map's projection (Web Mercator, metres) despite the names: lon is x and lat is y. For degrees, transform it: coordinates.clone().transform(ExtjsUtils.JS.getMap().getProjectionObject(), new OpenLayers.Projection("EPSG:4326")) (lastCoordinates below already holds degrees, of the previous click and hover).
mouseMoveEvent MouseEvent
Mouse event that triggered the function.
lastCoordinates Object
Object with the last coordinates (latitude, longitude) from the last click and the last hover events. lastCoordinates = { click: { lat: // Latitude of the last click lon: // Longitude of the last click }, hover: { lat: // Latitude of the last hover lon: // Longitude of the last hover } }
|handleOnHover: function(layerVals, inputs, coordinates, mouseMoveEvent, lastCoordinates) {
     ExtjsUtils.ALERTIFY.log("Latitude: " + coordinates.lat + " Longitude: " + coordinates.lon);
}|

runOnHoverOutside

function# True to run the callback function even when hovering outside of the layer, False to disable.

True to run the callback function even when hovering outside of the layer, False to disable. (Default False)

text

String# Define the text that will be displayed at the right of the toggler

Define the text that will be displayed at the right of the toggler

|text=This is the example text|

unselect

Boolean= true# Only changes the activation message: with the default true it says a single point is expected, with false several.

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.

|unselect=false|

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 …

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, so it is always current when read in beforeCalc/expression; it is also the last argument of runOnClick/runOnHover (inside the callback it still holds the previous event — the current one is written right after the callback returns; use the coordinates argument for the current position). The input is registered on the forceupdatelayer event of the widget, which nothing fires by itself — moving the mouse or clicking does not recalculate the layer. React inside runOnClick/runOnHover (which also receive the map values) or trigger the recalculation yourself (e.g. forceRecalc() on an InputManager).

{{hoverpixel|id=hover_tool|text=Inspect values|runOnClick=onMapClick}}
functions: {
    onMapClick: function(layerVals, inputs, coords, evt, lastInfo) {
        console.log(coords, lastInfo.click, inputs.id['hover_tool'] === lastInfo); // current, previous, true
    }
}

inputmanager · values kept for your functions (input)

InputManager6 entries

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

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

forceRecalc

function()# Force a legend map recalculation.

Force a legend map recalculation.

getValue

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

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

key String
Stored property name.

Returns Desired stored property when it exists or null otherwise.

id

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

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

|id=state|

setDefaultValues

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

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

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

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

setValues

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

Stores object properties for later usage.

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

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

value

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

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

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

label · text

Label6 entries

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

Create a simple label element to display some text.
Usage: {{label|}}
This label is created from Ext.form.Label.
Only some properties are listed here.

cls

String# Extra CSS class(es) added to the <label> element.

Extra CSS class(es) added to the <label> element.

{{label|cls=slider_label|text=0%}}

forId

String# Defines the id of the form field the label is for (rendered as the for attribute of the <label>), so clicking the label focuses that field.

Defines the id of the form field the label is for (rendered as the for attribute of the <label>), so clicking the label focuses that field.

{{label|text=Price (US$)|forId=soy_value}}{{textfield|id=soy_value|isnumeric}}

html

String# Defines the content of the label as raw HTML (not escaped).

Defines the content of the label as raw HTML (not escaped). Everything after html= up to the next | is the value, so it may contain = characters. text wins when both are given.

{{label|cls=slider_label|html=0% <b>...</b> 100%|id=scale_label}}

id

String# Defines the id of the label component (Ext.getCmp(id)), needed to change its text from code or to reference it with getid= in another tag.

Defines the id of the label component (Ext.getCmp(id)), needed to change its text from code or to reference it with getid= in another tag. Generated when omitted.

{{label|id=deforestation_label|text=20%}}

style

String# Inline CSS applied to the <label> element.

Inline CSS applied to the <label> element. Any other Ext.form.Label/Ext.Component config (hidden, width...) is passed through unchanged.

{{label|text=Total|style=font-weight: bold; color: #336699;}}

text

String# Defines the text of the label.

Defines the text of the label. It is HTML-escaped, so use html when markup is needed. Update it later with Ext.getCmp(id).setText(text) (typically from an on_change= listener of a slider or textfield through getid=).

{{label|id=deforestation_label|text=Deforestation: 20%}}

legendhtml · legend of the calculated map

LegendHtml7 entries

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

Create a tool with the map legends at any place of the query description.
Usage: '{{legendhtml}}'

autoWidth

Boolean= true# Set true (default) to let the legend panel take the width of its container; set false to give it a fixed width.

Set true (default) to let the legend panel take the width of its container; set false to give it a fixed width.

|autoWidth=false|width=250|

filterLayers

Array.<Number>= null# Defines an array of indexes of layers to be included in map legend (from 0 to quantity of layers).

Defines an array of indexes of layers to be included in map legend (from 0 to quantity of layers). If not defined, all layer legends are shown by default. Otherwise, only the listed indexes are included.

Ex: A composed layer with three maps: name: "CSR:estados,CSR:roads,CSR:municipalities", If 'filterLayers=[0,1]' is defined in the layer object only the legends of 'CSR:estatdos' and 'CSR:roads' are shown.

|filterLayers = [1,2]|

id

String# Defines the id of the legend panel component (Ext.getCmp(id)), e.g. to show()/hide() it or to find the legend entries inside it.

Defines the id of the legend panel component (Ext.getCmp(id)), e.g. to show()/hide() it or to find the legend entries inside it. Generated when omitted. Other GeoExt.WMSLegend/Ext.Panel configs (cls, style, hidden, useScaleParameter, autoWidth...) are passed through.

|id=main_legend|

legendId

String= null# Defines the legend container id.

Defines the legend container id. You can use this id to toggle each legend filter individually.

|legendId=WIDGET_OBJECT_ID|

preventClick

Boolean= false# Defines if the user can filter the maps categories by clicking on the legend.

Defines if the user can filter the maps categories by clicking on the legend. Set it true to ignore the legend click, false otherwise.

|preventClick = true|

reverseLegend

Boolean= false# Defines if it should sort the legend on the decreasing order.

Defines if it should sort the legend on the decreasing order. Set it true to use the decreasing order, false otherwise.

|reverseLegend = true|

useScaleParameter

Boolean= false# Set true to request a new legend image from the server whenever the map scale changes (GeoServer SCALE parameter), for styles that depend on the scale.

Set true to request a new legend image from the server whenever the map scale changes (GeoServer SCALE parameter), for styles that depend on the scale. Off by default: the legend is generated once and reused, which is faster and keeps the click-to-filter behaviour stable.

|useScaleParameter=true|

livecomposedsplit · split-screen comparison

LiveComposedSplit16 entries

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

Compare two styles of a Composed layer with a live split-screen slider on the map.

The layer must be a Composed layer (typically the same WMS layer twice in `name` with two `styles`). Put the tool in `descriptionHtml`, open the query panel, choose left/right styles, then press Compare to show a draggable vertical divider.

Required parameters: displayNames, layerNames (same order and length). Recommended: id, baseName, leftDefault, rightDefault. Optional: layout=compact (default, stacked for the layer card) or layout=inline (legacy single row).

Usage: {{livecomposedsplit|id=...|displayNames=...|layerNames=...|baseName=...|leftDefault=...|rightDefault=...}}

applySelectedStyles

function()# Pushes the two selected styles to the composed layer (changeLayers with the left style on child 0 and the right style on child 1) and makes both children visible.

Pushes the two selected styles to the composed layer (changeLayers with the left style on child 0 and the right style on child 1) and makes both children visible. Called when Compare is pressed; after calling it yourself use refreshActiveSplit() so the divider clips the new child divs.

Ext.getCmp('precip_split_container').applySelectedStyles();

baseName

String# WMS layer name used with each style (e.g. CSR:precip_monthly_average).

WMS layer name used with each style (e.g. CSR:precip_monthly_average). Defaults to layer.params.LAYERS when omitted.

|baseName=CSR:precip_monthly_average|

cls

String# Extra CSS class for the Compare toggle button (replaces the default clickable; the class live-composed-split-compare is always added).

Extra CSS class for the Compare toggle button (replaces the default clickable; the class live-composed-split-compare is always added).

|cls=my-compare-button|

composedLayerName

String# Name of the Composed layer to split.

Name of the Composed layer to split. If omitted, the first OpenLayers.Layer.Composed on the map is used.

|composedLayerName=CSR:precip_monthly_average|

destroySplitControl

function()# Removes the split divider control from the map for good (it is recreated on the next Compare press).

Removes the split divider control from the map for good (it is recreated on the next Compare press). The panel calls it when its layer is removed; call it to force a clean state. It does not restore the single-style view — press the Compare button off (toggle(false)) for the normal close.

Ext.getCmp('precip_split_container').destroySplitControl();

displayNames

String# Comma-separated labels shown in the left/right combo boxes (required).

Comma-separated labels shown in the left/right combo boxes (required).

|displayNames=January,February,March,April,May,June,July,August,September,October,November,December|

id

String# Id of the Compare button (wrapper id is id + "_container").

Id of the Compare button (wrapper id is id + "_container").

|id=my_composed_split|

isComparisonActive

function() : Boolean# Tells whether the split comparison is currently shown on the map (Compare pressed and the divider active).

Tells whether the split comparison is currently shown on the map (Compare pressed and the divider active). Get the panel with Ext.getCmp(id + '_container'), where id is the markup id.

Returns true while the two styles are being compared.

if (Ext.getCmp('precip_split_container').isComparisonActive()) { ... }

layerNames

String# Comma-separated WMS style names aligned with displayNames (required).

Comma-separated WMS style names aligned with displayNames (required). When Compare is pressed, the composed layer switches to the selected pair.

|layerNames=precip_monthly_average_1,precip_monthly_average_2,...|

layout

String= compact# Presentation inside the layer query panel. compact (default): stacked fields that fit the ~300px layer card. inline: horizontal row (legacy Left / Right / Compare on one line).

Presentation inside the layer query panel. compact (default): stacked fields that fit the ~300px layer card. inline: horizontal row (legacy Left / Right / Compare on one line).

|layout=inline|

leftDefault

String# Initial left combo value; must be one of displayNames.

Initial left combo value; must be one of displayNames.

|leftDefault=January|

refreshActiveSplit

function()# Re-applies the selected styles and re-clips the split after the composed layer's children were replaced (e.g. by your own changeLayers call), keeping the divider position.

Re-applies the selected styles and re-clips the split after the composed layer's children were replaced (e.g. by your own changeLayers call), keeping the divider position. Does nothing while the comparison is not active.

Ext.getCmp('precip_split_container').refreshActiveSplit();

rightDefault

String# Initial right combo value; must be one of displayNames (and different from left).

Initial right combo value; must be one of displayNames (and different from left).

|rightDefault=August|

setComparisonEditingEnabled

function(enabled)# Enables or disables the right-side combo and the swap button.

Enables or disables the right-side combo and the swap button. The panel calls it itself (only the left combo is editable while idle; both unlock when comparing); call it to lock the choice while data loads.

enabled Boolean
true to allow changing the right side and swapping, false to lock them.
Ext.getCmp('precip_split_container').setComparisonEditingEnabled(false);

swapSides

function()# Exchanges the left and right styles (combos and map) and re-clips the split, keeping the divider where it is.

Exchanges the left and right styles (combos and map) and re-clips the split, keeping the divider where it is. Does nothing while the comparison is not active — what the swap button does.

Ext.getCmp('precip_split_container').swapSides();

text

String= Compare Layers# Label on the Compare toggle button (before the split is active).

Label on the Compare toggle button (before the split is active).

|text=Compare Monthly Data|

loadcsv · load a CSV table (input)

LoadCsv14 entries

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

Describes the API to read and manipulate ExtjsUtils.CSV.CsvTable files from URL.

columnNameToInd

function(columnName) : Number# Get the index of a column with the 'columnName' name.

Get the index of a column with the 'columnName' name.

columnName String
Column name to search for.

Returns When it exists returns the column index, otherwise -1.

columnNamesToIndexes

function(columnNames) : Array.<Number># Resolves column names to column indexes: every string entry is looked up in the header (-1 when absent) and every numeric entry is kept as it is.

Resolves column names to column indexes: every string entry is looked up in the header (-1 when absent) and every numeric entry is kept as it is. A single value is accepted in place of the array. This is what getLines/createIndexes do with their columns argument.

columnNames Array.<(String|Number)>|String|Number
Column names and/or indexes.

Returns The column indexes, in the same order.

inputs.id["fire_csv"].columnNamesToIndexes(["Year", 2]); // e.g. [1, 2]

cors

Boolean= false# Downloads the CSV through the Mappia CORS proxy; use it for servers that do not send CORS headers.

Downloads the CSV through the Mappia CORS proxy; use it for servers that do not send CORS headers.

|cors=true|

createIndexes

function(columns)# Create indexes for faster search.

Create indexes for faster search.

PS: Indexes are used to faster results on "getLines" calls, apply only when all [columns] are indexes.

columns Array
(Optional) Array of indexes/names of the filtered columns.
{...
    beforeCalc: function(inputs) {
        inputs.id['CSV_WIDGET_EXAMPLE_ID'].createIndexes(['Key', 'Year']);
        alert(inputs.id['CSV_WIDGET_EXAMPLE_ID'].getLines(['Key','Year'], [100, 2020]).length);
    }
}

getColunsInd

function() : Array.<String># Returns a copy of the header row — the column names, in order — so query code can discover columns instead of hard-coding indexes.

Returns a copy of the header row — the column names, in order — so query code can discover columns instead of hard-coding indexes. The name is a historical typo of getColumnsInd, kept for compatibility (the platform and many queries call it by this spelling; there is no correctly spelled alias).

Returns Copy of the header row.

var headers = inputs.id["fire_csv"].getColunsInd(); // ["Municipality", "Year", "Fires"]
var iFires = headers.indexOf("Fires");

getLineCount

function() : Number# Number of data lines in the table (the header line is not counted).

Number of data lines in the table (the header line is not counted).

Returns How many data lines the CSV has.

var csv = inputs.id["fire_csv"];
for (var i = 0; i < csv.getLineCount(); i++) total += parseFloat(csv.getValue(2, i));

getLines

function(columns, values, includeHeader) : Array.<Array.<String>># Returns the lines (arrays of cell strings) whose cells in columns equal the corresponding entries of values.

Returns the lines (arrays of cell strings) whose cells in columns equal the corresponding entries of values. Columns may be given by index or by header name; to filter on several columns give one value per column, e.g. getLines([1, "Year"], ["Park A", 2024]). Values are compared as strings (the CSV is always text). Called with no arguments it returns every data line (header skipped) — a common idiom. When all filtered columns were indexed with createIndexes the lookup uses the index instead of scanning every line.

columns Array.<(String|Number)>
Indexes and/or names of the columns to filter on.
values Array
One value per entry of columns.
includeHeader Boolean
True to also return the header line when it matches (only in the scanning path, i.e. without indexes).

Returns The matching lines; all data lines when no filter is given.

var csv = inputs.id["fire_csv"];
var rows2024 = csv.getLines(["Year"], [2024]);      // by header name
var rowsParkA = csv.getLines([0, "Year"], ["Park A", 2024]); // two columns
var allRows = csv.getLines();                         // every data line

getValue

function(column, line, includeHeader) : String# Get a value by the matrix index and column.

Get a value by the matrix index and column.

column Number
Column index (First index is 0).
line Number
Line index (First index is 0).
includeHeader boolean
True to include the header line in the matrix index, False to ignore.

Returns Get the cell value.

id

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

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

|id=emissions_csv|

removeEmptyLines

boolean= false# Ignore the empty lines, removing them from the parsed CSV.

Ignore the empty lines, removing them from the parsed CSV. True to remove the empty lines from the CSV.

setValue

function(column, line, value)# Change a cell value by its cell index.

Change a cell value by its cell index.

column Numeric
Column index.
line Numeric
Line index to change (ignore the header information when it exists).
value *
New value to replace the older value.

trim

Boolean= false# Requests that cell values be trimmed of surrounding whitespace.

Requests that cell values be trimmed of surrounding whitespace. The flag is accepted and forwarded to the CSV parser, but the current parser ignores it (cells are stored as written, quotes removed), so trim values yourself when needed. Kept for compatibility with existing queries.

|trim=true|

url

String# Defines the URL of the CSV file to download (required).

Defines the URL of the CSV file to download (required). Relative URLs are resolved against the Mappia host, so backend endpoints such as /wmtp/calc/... work; escape = inside query strings as \=. The layer waits for the download before calculating.

|url=/theme/app/data/emissoesco2.csv|
|url=/wmtp/calc/areacategorical/?layers\=CSR:estados&styles\=1|

value

ExtjsUtils.CSV.CsvTable# Value stored in inputs.id[ID]: an ExtjsUtils.CSV.CsvTable wrapping the parsed file (first row = header).

Value stored in inputs.id[ID]: an ExtjsUtils.CSV.CsvTable wrapping the parsed file (first row = header). Read it with the CsvTable methods listed in this group (getLines, getValue, columnNameToInd, createIndexes, getLineCount...). It is undefined until the download finishes: the layer waits for the resource and recalculates on its waitend event, so beforeCalc/expression can rely on it being loaded.

{{loadcsv|id=emissions_csv|url=/theme/app/data/emissoesco2.csv|removeEmptyLines=true}}
beforeCalc: function(inputs) {
    var csv = inputs.id['emissions_csv'];          // columns: percentage, carbon_loss
    var rows = csv.getLines(0, '25');               // rows whose first column equals 25
}

loadjson · load JSON (input)

LoadJson4 entries

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

Tool to load a remote JSON and use it with map, this object can store string, values and functions.
Usage: {{loadjson}}

cors

Boolean= false# Loads the JSON through the Mappia CORS proxy (for servers without CORS headers).

Loads the JSON through the Mappia CORS proxy (for servers without CORS headers).

|cors=true|

id

String# Defines an id for the stored info on layerInputs.

Defines an id for the stored info on layerInputs.

|id=window-div-id|
on javascript: layer.getInputs().id["NAME_DEFINED_HERE"]

url

String# Defines the url to load the json from.

Defines the url to load the json from.

|url=https://maps.csr.ufmg.br/theme/app/data/conab/limites_municipios_conab.geojson|

value

Object|Array# Value stored in inputs.id[ID]: the parsed JSON (JSON.parse of the response body — an object or an array; an empty response gives []).

Value stored in inputs.id[ID]: the parsed JSON (JSON.parse of the response body — an object or an array; an empty response gives []). It is undefined until the download finishes: the layer waits for the resource and recalculates on its waitend event, so beforeCalc/expression can rely on it being loaded.

{{loadjson|id=limits|url=https://maps.csr.ufmg.br/theme/app/data/example.geojson}}
beforeCalc: function(inputs) {
    var geojson = inputs.id['limits'];
    console.log(geojson.features.length);
}

opacityslider · layer opacity

OpacitySlider8 entries

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

Create a slider to change the map opacity.
Usage: '{{opacityslider}}'

aggressive

Boolean= false# Set true to apply the opacity while the thumb is being dragged instead of only when it is released.

Set true to apply the opacity while the thumb is being dragged instead of only when it is released.

|aggressive=true|

changeVisibility

Boolean= false# Set true to let the slider also control the layer visibility: the layer is hidden when the slider reaches minValue and shown again when it leaves it.

Set true to let the slider also control the layer visibility: the layer is hidden when the slider reaches minValue and shown again when it leaves it. The layer must be visible when the slider is created.

|changeVisibility=true|

complementaryLayer

OpenLayers.Layer# A second layer that is hidden when the slider reaches maxValue (GeoExt option to fade between two layers).

A second layer that is hidden when the slider reaches maxValue (GeoExt option to fade between two layers). GeoExt expects a layer object here, which the markup cannot express (a string is not resolved to a layer), so this option is only usable from code; documented for completeness.

id

String# Defines the id of the slider component (Ext.getCmp(id)), e.g. to read getValue() or to hide() it.

Defines the id of the slider component (Ext.getCmp(id)), e.g. to read getValue() or to hide() it. Generated when omitted. Every parameter of the tool is passed to GeoExt.LayerOpacitySlider / Ext.slider.SingleSlider unchanged (width, cls, vertical, hidden...).

|id=opacity|

inverse

Boolean= false# Set true to make the slider work with transparency instead of opacity (100 = fully transparent).

Set true to make the slider work with transparency instead of opacity (100 = fully transparent).

|inverse=true|

maxValue

Number= 100# Defines the maximum value of the slider (opacity percent at the right end).

Defines the maximum value of the slider (opacity percent at the right end).

|maxValue=90|

minValue

Number= 0# Defines the minimum value of the slider (opacity percent at the left end).

Defines the minimum value of the slider (opacity percent at the left end).

|minValue=10|

value

Number= 100# Defines the initial slider value (opacity in percent).

Defines the initial slider value (opacity in percent). It is only used when the layer has no opacity yet (opacity not set on the layer): otherwise the slider starts at the layer's current opacity.

|value=50|

pickpoint · pick a point on the map (input)

PickPoint33 entries

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

Creates an input that allows users to interact with the real cell or feature value at any position.

The returned values are from the original mal to the selected point,
in case of RASTER is returned a cell value, in case of shapefile the geometry is returned too.
Usage: {{pickpoint}}

checked

Boolean= false# Defines if Pickpoint should start selected.

Defines if Pickpoint should start selected. Set it true to start it enabled, false otherwise.

|checked = false|

fieldLabel

String# Sets the label for the 'pickpoint' button widget.

Sets the label for the 'pickpoint' button widget.

'Pick a point coordinate (Lat,Lon)'

geometryColor

String= undefined# If defined sets a color to use when drawing a geometry by this tool.

If defined sets a color to use when drawing a geometry by this tool. Otherwise a random color will be used at each interaction.

|geometryColor=#FF00FF|

getAttributes

function(mapIndex) : Array.<Object># Returns the attributes of every selected point for one of the layers of the composed map: one object per selection (in click order) holding the feature data of that layer, or {} when the click …

Returns the attributes of every selected point for one of the layers of the composed map: one object per selection (in click order) holding the feature data of that layer, or {} when the click hit nothing on it (e.g. a raster). This is the usual way to read the selection in beforeCalc.

mapIndex Number
0-based index of the layer inside the composed layer (name order).

Returns Attribute objects of the selected features on that layer.

beforeCalc: function(inputs) {
    var picked = inputs.id['property_pick'].getAttributes(1);
    var names = picked.map(function(attrs) { return attrs.Name; });
}

getLastEvent

function() : OpenLayers.Event|null# Returns the map click event handled by the last selection (its type is set to add or remove), or null before the first click.

Returns the map click event handled by the last selection (its type is set to add or remove), or null before the first click. Use evt.xy for the pixel and ExtjsUtils.COORDINATE.getLatLong(evt) for the coordinate.

Returns The last handled click event.

var evt = inputs.id['property_pick'].getLastEvent();

getPointPos

function() : Array.<Number># Returns the geographic position of the last clicked point (the marker), in the map's desired projection (normally EPSG:4326 — longitude, latitude).

Returns the geographic position of the last clicked point (the marker), in the map's desired projection (normally EPSG:4326 — longitude, latitude).

Returns [x, y] — longitude and latitude of the last click.

var lonLat = inputs.id['property_pick'].getPointPos(); // [-56.07, -4.04]

iconCls

String= cmn-toggle-icon# Defines the CSS class of the toggle switch icon; replace the default to restyle the switch.

Defines the CSS class of the toggle switch icon; replace the default to restyle the switch. labelBefore=true places the text before the switch, and inputValue sets the DOM value of the checkbox input (both passed through to the checkbox).

|iconCls=my-toggle-icon|

id

String# Defines the id of the tool (required).

Defines the id of the tool (required). It is the key used in inputs.id[ID] and the id of the checkbox component (Ext.getCmp(id)), so it must be unique in the page.

|id=property_pick|

inputValue

String# Defines the DOM value attribute of the underlying checkbox input (useful when the tool is inside an HTML form).

Defines the DOM value attribute of the underlying checkbox input (useful when the tool is inside an HTML form). It does not affect what inputs.id[ID] holds.

|inputValue=pick|

label

String# Defines a text template drawn on the map next to each selected feature.

Defines a text template drawn on the map next to each selected feature. ${attr} placeholders are replaced by the attribute values of the clicked feature (vector layers only; a raster cell has no attributes). Without it no label is drawn.

|label=Region ${Name}|

labelBefore

Boolean= false# Set true to render the text label before (left of) the toggle switch instead of after it.

Set true to render the text label before (left of) the toggle switch instead of after it.

|labelBefore=true|

lat

Number= 0# Defines the initial latitude (EPSG:4326, decimal degrees) of the marker shown when the tool is activated, before any click.

Defines the initial latitude (EPSG:4326, decimal degrees) of the marker shown when the tool is activated, before any click. Use it with lon; default 0.

|lat=-4.0396|lon=-56.07422|

lon

Number= 0# Defines the initial longitude (EPSG:4326, decimal degrees) of the marker shown when the tool is activated, before any click.

Defines the initial longitude (EPSG:4326, decimal degrees) of the marker shown when the tool is activated, before any click. Use it with lat to start on a point of interest; default 0.

|lat=-4.0396|lon=-56.07422|

markLayerInd

Number# Defines by layer index which one to draw its geometry when a click event happens.

Defines by layer index which one to draw its geometry when a click event happens. (0-indexed)

|markLayerInd = 0|

movePoint

function(evt)# Moves the marker of the last click to the position of a map mouse event.

Moves the marker of the last click to the position of a map mouse event. The tool calls it on every click; call it yourself only to relocate the marker from a synthetic event.

evt OpenLayers.Event
Map mouse event carrying the pixel position in evt.xy.
this.getInputs().id['property_pick'].movePoint(evt);

notify

Boolean= true# Set false to prevent the notify messages from appear (the "click on the map..." notification shown when the tool is activated).

Set false to prevent the notify messages from appear (the "click on the map..." notification shown when the tool is activated).

|notify=false|

onMark

function# Callback function called after clicking on a feature with this 'pickpoint' widget, once the feature info of every layer of the composed map has been received.

Callback function called after clicking on a feature with this 'pickpoint' widget, once the feature info of every layer of the composed map has been received. this is the pickpoint checkbox (or scope), so this.value is the PointAttributeManager. The name is resolved as a key of the layer functions object, then as a global function, then as inline function text.

eventAndProperties Object
A object with {mouse, type, features} passed into the callback function: - mouse: {PointerEvent} The mouse click event. - type: {String} 'add' when the click selected features, 'remove' when it unselected them. - features: {Array<Array<Object>>} One array per layer of the composed map with the feature(s) found at the click (empty on removal).
{ ...
 "descriptionHtml": "{{pickpoint|id=ANY_UNIQUE_ID|onMark=onMarkCallback}}",
  functions: {
    onMarkCallback: function(event) {
      for (var iLayer=0; iLayer < event.features.length; iLayer++) {
        for (var iFeature=0; iFeature < event.features[iLayer].length; iFeature++) {
          console.log(event.features[iLayer][iFeature].data);
        }
      }
    }
  }
 ...
 }

onefeature

boolean# Defines if PickPoint should keep only the last feature selected.

Defines if PickPoint should keep only the last feature selected. Set it true to keep only the last one, false otherwise.

|onefeature = false|

pointVisibility

Boolean= true# Defines if Pickpoint should show where the last click was.

Defines if Pickpoint should show where the last click was. Set it true to show, false otherwise.

|pointVisibility = false|

removeAll

function()# Clears the whole selection: every selected feature is removed from the map and from the list returned by getAttributes.

Clears the whole selection: every selected feature is removed from the map and from the list returned by getAttributes. Typical use: a "Clear" button handler, followed by a recalculation.

functions: {
    clearSelection: function() {
        this.getInputs().id['property_pick'].removeAll();
    }
}

removeAttribute

function(index)# Removes one selection (by its position in the getAttributes list) from the map and from the selection list.

Removes one selection (by its position in the getAttributes list) from the map and from the selection list. An invalid index changes nothing.

index Number
0-based index of the selection to remove (same order as getAttributes).
var pick = inputs.id['property_pick'];
for (var i = pick.getAttributes(1).length - 1; i >= 0; i--) {
    if (!pick.getAttributes(1)[i].Name) pick.removeAttribute(i);
}

runOnClick

function# Alias of onMark, kept so the pickpoint accepts the same callback name as the other map tools (hoverpixel, summedarea, areaintegral).

Alias of onMark, kept so the pickpoint accepts the same callback name as the other map tools (hoverpixel, summedarea, areaintegral). When both are written, onMark wins. See {@link PickPoint.onMark} for the callback signature.

|runOnClick=onMarkCallback|

runOnHover

function# Defines a callback function to run when clicking at the map.

Defines a callback function to run when clicking at the map.

Defines a callBack with following parameters function(mouseEvt, coordinates) --mouseEvt: {MouseEvent} Mouse hover event. --coordinates: {Openlayers.LatLon} Coordinate of the cursor over the map. PS: Can access the layer itself using the 'this' keyword.

runOnHoverOutside

function# True to run the callback function even when hovering outside of the layer, False to disable.

True to run the callback function even when hovering outside of the layer, False to disable. (Default False)

scope

Object# Defines the object used as this inside the onMark/runOnClick callback.

Defines the object used as this inside the onMark/runOnClick callback. By default it is the pickpoint checkbox component (so this.value is the PointAttributeManager). From the markup it can only reference an element created earlier in the same description, with the nested getid form.

|scope=getid=report_btn|

searchAttribute

function(mapIndex, propName, value) : Object|null# Finds, among the selected features of one layer, the first whose attribute propName equals value and returns its attributes.

Finds, among the selected features of one layer, the first whose attribute propName equals value and returns its attributes. Useful to check whether a given feature is already selected.

mapIndex Number
0-based index of the layer inside the composed layer.
propName String
Name of the attribute to compare.
value *
Value the attribute must have (compared with ==).

Returns The attributes of the matching selection, or null when none matches.

var found = inputs.id['property_pick'].searchAttribute(1, 'Code', '3106200');

setFeatureVisibility

function(state, feature)# Adds a feature to, or removes it from, the auxiliary vector layer where the tool draws its selections.

Adds a feature to, or removes it from, the auxiliary vector layer where the tool draws its selections. Lets a callback draw extra geometries (an OpenLayers.Feature.Vector) with the selection, or hide one of the selected features without forgetting it.

state Boolean
true to add (show) the feature, false to remove it.
feature OpenLayers.Feature.Vector|Array.<OpenLayers.Feature.Vector>
Feature(s) to add or remove.
inputs.id['property_pick'].setFeatureVisibility(true, new OpenLayers.Feature.Vector(geometry));

setPointVisibility

function(state)# Shows or hides the marker drawn at the last clicked position (the same marker controlled by the pointVisibility parameter).

Shows or hides the marker drawn at the last clicked position (the same marker controlled by the pointVisibility parameter).

state Boolean
true to show the marker, false to hide it.
inputs.id['property_pick'].setPointVisibility(false);

text

String# Defines the text shown next to the toggle.

Defines the text shown next to the toggle. When omitted the label shows the coordinate of the last click, (lat, lon), and is updated at every click.

|text=Click on the map to select an area|

toggle

function(forceState)# Activates or deactivates the pick mode from code (same as clicking the switch): the map cursor, the click listeners and the marker follow the new state.

Activates or deactivates the pick mode from code (same as clicking the switch): the map cursor, the click listeners and the marker follow the new state. Call it on the checkbox component (Ext.getCmp(id)). Without an argument the state is inverted.

forceState Boolean
true to activate picking, false to deactivate; omit to invert.
Ext.getCmp('property_pick').toggle(true);

togglePoint

function(pointFeatures, evt) : Object# Adds a set of features (one array per layer of the composed map, as returned by GetFeatureInfo) to the selection, or removes it when the same features were already selected.

Adds a set of features (one array per layer of the composed map, as returned by GetFeatureInfo) to the selection, or removes it when the same features were already selected. With onefeature=true the previous selection is cleared first. The tool calls it after every click; the returned object is what onMark receives.

pointFeatures Array.<Array.<OpenLayers.Feature.Vector>>
Features found at the click, indexed by layer.
evt OpenLayers.Event
The click event that originated the selection.

Returns {mouse, type, features} — the event, 'add' or 'remove', and the features added (empty on removal).

unselect

Boolean= true# Defines if Pickpoint will be automatically disabled after each click.

Defines if Pickpoint will be automatically disabled after each click. Set it true to automatically disable, false otherwise (write unselect= or unselect=false to keep the tool active for several clicks).

|unselect = true|

value

Object# Value stored in inputs.id[ID]: the PointAttributeManager of the tool, the object that keeps the selected features.

Value stored in inputs.id[ID]: the PointAttributeManager of the tool, the object that keeps the selected features. Read it with getAttributes(mapIndex), searchAttribute(...), getPointPos(), getLastEvent(), and change it with removeAll(), removeAttribute(index), setPointVisibility(state), setFeatureVisibility(state, feature) (all listed in this group). The layer recalculates on the widget onmark event, fired after every click once the feature info of all layers arrived — so beforeCalc always sees the updated selection. The object holds map features, so do not send it to expression (WebWorker); extract plain values in beforeCalc.

{{pickpoint|id=property_pick|text=Select a property|markLayerInd=1|unselect=}}
beforeCalc: function(inputs) {
    var codes = inputs.id['property_pick'].getAttributes(1).map(function(a) { return a.Code; });
    this.changeLayers({name: 'CSR:properties', styles: codes.length ? 'highlight' : '', index: 1});
}

slider · number or range (input)

Slider17 entries

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

Tool that allows users to create a slider that the user can drag and change its value as map input.

backgroundColors

Array.<String># Array of colors of background slider values, to define background slider color based in slider value.

Array of colors of background slider values, to define background slider color based in slider value. The values are defined from most to minimum with two properties each:

  • color: {String} CSS color definition for the current interval. i.e. 'red','black','#FF0000', '#000000'.
  • startValue: {Numeric} If defined define the initial value which above will apply this color, otherwise use theminimum slider value as default.

Ex.:
 backgroundColors: [
     {
         // Define background color to red when slider has value above 75.
         color: "red",
         startValue: 75
     },
     {
         // Define background color starting from value 0.
         // That results two intervals, from 0 to 75 as blue, and from 76 to 100 as red.
         color: "blue",
         startValue: 0
     }
 ]

cls

String# Extra CSS class(es) added to the slider element (appended to the default clickable).

Extra CSS class(es) added to the slider element (appended to the default clickable).

|cls=my_slider|

disabled

Boolean= false# Set true to render the slider disabled (Ext disabled); enable it later with Ext.getCmp(id).enable().

Set true to render the slider disabled (Ext disabled); enable it later with Ext.getCmp(id).enable().

|disabled=true|

fieldLabel

String# Defines the label shown at the left of the slider (Ext fieldLabel).

Defines the label shown at the left of the slider (Ext fieldLabel).

|fieldLabel=Deforestation (%)|

getValue

function() : Number# Returns the current value of a single-thumb slider.

Returns the current value of a single-thumb slider. Call it on the component (Ext.getCmp(id) or a getid= reference), not on inputs.id[ID], which already holds the plain value.

Returns The current slider value.

var v = Ext.getCmp('deforestation_slider').getValue();

getValues

function() : Array.<Number># Returns the value of every thumb; use it for range sliders created with values=[lo, hi].

Returns the value of every thumb; use it for range sliders created with values=[lo, hi].

Returns One value per thumb, in thumb order.

var range = Ext.getCmp('interval_slider').getValues(); // [lo, hi]

gradient

Boolean= false# Set true to blend the backgroundColors into a continuous gradient along the filled part of the slider (each colour fading into the next from its startValue).

Set true to blend the backgroundColors into a continuous gradient along the filled part of the slider (each colour fading into the next from its startValue). With the default false each interval is a solid colour, with a short blend only around the thumb. Has no effect without backgroundColors.

|backgroundColors=[{color: "green", startValue: 0}, {color: "red", startValue: 50}]|gradient=true|

hideLabel

Boolean= false# Set true to hide the label and the space reserved for it (Ext hideLabel).

Set true to hide the label and the space reserved for it (Ext hideLabel).

|hideLabel=true|

id

String# Defines the id to identify the object.

Defines the id to identify the object.

|id=example_slider|

increment

Number# Defines the step of each increment or decrement in the actual value of the slider when being dragged.

Defines the step of each increment or decrement in the actual value of the slider when being dragged.

|increment = 10|

maxValue

Number# Defines the maximum value of the slider.

Defines the maximum value of the slider.

|maxValue = 100|

minValue

Number# Defines the minimum value of the slider.

Defines the minimum value of the slider.

|minValue = 0|

setValue

function(value, animate)# Sets the slider value from code.

Sets the slider value from code. Firing the change event (the default) also updates inputs.id[ID] and recalculates the layer. For a range slider pass the thumb index first: setValue(index, value).

value Number
New value (clamped to minValue/maxValue).
animate Boolean
Set false to move the thumb without animation.
Ext.getCmp('deforestation_slider').setValue(20);

thumbStyle

String= null# Defines extra CSS class(es) added to the slider thumb (the draggable handle), to restyle it.

Defines extra CSS class(es) added to the slider thumb (the draggable handle), to restyle it.

|thumbStyle=x-slider-thumb-cut|

value

Number# Defines the initial value of the slider (default 100).

Defines the initial value of the slider (default 100).

At runtime the same value is what inputs.id[ID] (and inputs[i]) holds in beforeCalc/expression: a number, or an array [lower, upper] when the values range form is used. The layer recalculates on the slider change event (thumb released or value set from code).

|value = 100|
beforeCalc: function(inputs) {
    var threshold = inputs.id['deforestation_slider']; // number
}

values

Array.<Number># Defines the slider interval limits.

Defines the slider interval limits. If defined, the slider will be displayed as a range slider. It's return at the 'inputs' parameter will be a array of two values.

|values = [0, 250]|
|beforeCalc: function(inputs) {
   let lowerValue = inputs[0][0]; // The value of the left drag
   let upperValue = inputs[0][1]; // The value of the right drag
}|

width

Number# Defines the slider width in pixels.

Defines the slider width in pixels. Any other Ext.slider.SingleSlider config (cls, fieldLabel, hideLabel, disabled, style, keyIncrement...) is also passed through unchanged.

|width=200|

summedarea · sum inside a drawn area (input)

SummedArea10 entries

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

Create an input of summation in any arbitrary area.

CallBack parameters (context {OpenLayers.Layer}, layersValues {Array[Number]}, inputs {[Object]}, feature {Geometry})
runOnClick {Function} Callback called exactly after sum the map region.,

PS: 'layersValues' return the sum of each internal layer and an adittional value which is the sum of all pixels of resulting layer.

description

function(name, config, layer, parameters) : Ext.Container# Creates an input of summatory in any arbitrary area.

Creates an input of summatory in any arbitrary area.

CallBack parameters (context {OpenLayers.Layer}, layersValues {Array[Number]}, inputs {[Object]}, feature {Geometry}) runOnClick {Function} Callback called exactly after sum the map region.,

PS: 'layersValues' return the sum of each internal layer and an adittional value which is the sum of all pixels of resulting layer.

name String
Input name "summedarea".
config Object
Properties to customize the element.
layer OpenLayers.Layer
Layer which the widget is defined.
parameters Array
Array de parametros antes do processamento para o input.

Returns Returns an instance of summedarea Input.

getSummedLayerValues

function(layer, feature) : Array# Sums, for each inner layer of the composed map, the values of the rendered cells that fall inside a polygon (values decoded from the tile colours through the layer legend, null cells skipped).

Sums, for each inner layer of the composed map, the values of the rendered cells that fall inside a polygon (values decoded from the tile colours through the layer legend, null cells skipped). This is what runOnClick receives as layersValues; call it from code (Ext.getCmp(id).items.get(0).getSummedLayerValues(layer, feature)) to sum any polygon feature. The returned array has one sum per inner layer followed by two extra entries: the number of cells read from the last layer and an array with the count of non-null cells of every layer.

layer OpenLayers.Layer.Composed
The composed layer whose tiles are read (normally the tool's own layer).
feature OpenLayers.Feature.Vector
Polygon feature delimiting the area to sum.

Returns [sum layer 0, ..., sum layer n-1, cellCount, [nonNull layer 0, ..., nonNull layer n-1]].

iconCls

String= cmn-toggle-icon# Defines the CSS class of the toggle switch icon; replace the default to restyle the switch.

Defines the CSS class of the toggle switch icon; replace the default to restyle the switch.

|iconCls=my-toggle-icon|

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)).

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.

|id=sum_tool|

labelBefore

Boolean= false# Set true to render the text label before (left of) the toggle switch instead of after it.

Set true to render the text label before (left of) the toggle switch instead of after it.

|labelBefore=true|

notify

Boolean= true# Set false to suppress the notification shown when the tool is activated.

Set false to suppress the notification shown when the tool is activated.

|notify=false|

runOnClick

function# Defines the callback run when the user finishes drawing the polygon (double-click closes it), with the values already summed.

Defines the callback run when the user finishes drawing the polygon (double-click closes it), with the values already summed. Called as runOnClick(layersValues, inputs, feature) with this = the layer: layersValues is the array described in getSummedLayerValues, inputs is layer.getInputs() and feature the drawn OpenLayers.Feature.Vector polygon. The name is resolved as a key of the layer functions object, then as a global function, then as inline function text. The tool deactivates itself after the callback.

|runOnClick=onClickSum|
functions: {
    onClickSum: function(layersValues, inputs, feature) {
        ExtjsUtils.ALERTIFY.log('Sum of layer 0: ' + layersValues[0] + ' (' + layersValues[layersValues.length - 1][0] + ' cells)');
    }
}

text

String# Defines the text shown next to the toggle switch.

Defines the text shown next to the toggle switch.

|text=Sum an area|

unselect

Boolean= true# Only changes the activation message (true: one selection expected, false: several); the tool always deactivates itself after a polygon is summed.

Only changes the activation message (true: one selection expected, false: several); the tool always deactivates itself after a polygon is summed.

|unselect=false|

value

Array.<Number># Value stored in inputs.id[ID]: an array meant to hold the last layersValues (one sum per inner layer, see getSummedLayerValues).

Value stored in inputs.id[ID]: an array meant to hold the last layersValues (one sum per inner layer, see getSummedLayerValues). In the current implementation the tool does not copy the sums into it after drawing — it stays empty — so read the results in runOnClick and store what you need with an InputManager (setValues). The input is registered on the forceupdatelayer event of the switch (Ext.getCmp(id).items.get(0).forceUpdateLayer() recalculates the layer).

{{summedarea|id=sum_tool|runOnClick=onClickSum}}{{inputmanager|id=sums}}
functions: {
    onClickSum: function(layersValues, inputs, feature) {
        inputs.id['sums'].setValues({areaSum: layersValues[0]}); // recalculates the layer
    }
}

textfield · text box (input)

Textfield9 entries

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

Tool that allows the user to input a single line of text.
Usage: '{{textfield}}'
This tool is created from Ext.form,TextField.
Only customized properties are listed here.

afteredit

Event# Event fired once the field loses focus (blur) and its text differs from the value it had when editing started; the listener receives the TextField.

Event fired once the field loses focus (blur) and its text differs from the value it had when editing started; the listener receives the TextField. Unlike keyup it fires a single time per edit, so use it for expensive reactions. Attach it with on_afteredit= through a getid= reference, or from code with Ext.getCmp(id).on('afteredit', fn).

{{textfield|id=soy_value|isnumeric}}{{label|getid=soy_value|getid=on_afteredit=console.log(this.getRawValue())}}
Ext.getCmp('soy_value').on('afteredit', function(field) { console.log(field.getRawValue()); });

fieldLabel

String# Defines the TextField label.

Defines the TextField label.

|fieldLabel = This is the field label|

getRawValue

function() : String# Returns the text currently in the field, unprocessed (this is what inputs.id[ID] holds).

Returns the text currently in the field, unprocessed (this is what inputs.id[ID] holds). Call it on the component (Ext.getCmp(id)).

Returns The raw text of the input element.

var text = Ext.getCmp('soy_value').getRawValue();

hideLabel

Boolean= false# Defines if it should completely hide the label element (label and separator) of the TextField.

Defines if it should completely hide the label element (label and separator) of the TextField. That is, if this property is set to true, the label will be hidden. Otherwise, the label will be shown by default. PS: Since the label will be shown by default, even if you do not specify a fieldLabel, the space for it will still be reserved so that the TextField will line up with other fields that do have labels. This space will be removed if you define it to be hidden.

|hideLabel = true|

id

String# Defines the id to identify the object.

Defines the id to identify the object.

|id=example_text_field|

isnumeric

boolean# Defines the TextField content as numeric only.

Defines the TextField content as numeric only.

|isnumeric=true|

setRawValue

function(value)# Replaces the text of the field from code.

Replaces the text of the field from code. It does not fire keyup, so call forceRecalc() on an InputManager (or fire the event) when the layer must be recalculated with the new text.

value String
New text for the field.
Ext.getCmp('soy_value').setRawValue('43');

style

String# Defines the TextField style properties.

Defines the TextField style properties. You can use CSS style rules to customize it.

|style = color:black;|

value

String# Defines the initial value to the TextField content.

Defines the initial value to the TextField content.

At runtime inputs.id[ID] (and inputs[i]) holds the current text exactly as typed (getRawValue(), always a string — convert it with parseFloat when isnumeric is used). The layer recalculates on every keyup (each keystroke); the widget also fires afteredit when the field loses focus with a changed value.

|value = text|
beforeCalc: function(inputs) {
    var price = parseFloat(inputs.id['soy_value']) || 0;
}

timeline · scenarios over time (input)

Timeline31 entries

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

Display a spatial scenarios changes in a timeline.

fieldLabel

String# Defines a label for the Timeline.

Defines a label for the Timeline. It will be shown at the left of the button to hide the tiemline, by default.

|fieldLabel=This is the field label|

getCurrentLayerStyle

function() : String# Returns the WMS style currently applied to the layer (layer.params.STYLES), or an empty string for the default style.

Returns the WMS style currently applied to the layer (layer.params.STYLES), or an empty string for the default style.

Returns The active style name.

var style = Ext.getCmp('years_tl').getTimeline().getCurrentLayerStyle();

getDesiredVisibility

function() : Boolean# Returns the visibility the timeline has, or will have when its layer becomes visible: true may be returned while the panel is actually hidden because the layer is hidden.

Returns the visibility the timeline has, or will have when its layer becomes visible: true may be returned while the panel is actually hidden because the layer is hidden.

Returns true when the timeline is (or will be) shown together with the layer.

var shown = Ext.getCmp('years_tl').getTimeline().getDesiredVisibility();

getMainThumb

function() : Ext.slider.Thumb# Returns the main (middle) thumb of the slider — the one that selects the current step; its value is the 0-based step index.

Returns the main (middle) thumb of the slider — the one that selects the current step; its value is the 0-based step index. The outer thumbs (thumbs[0], thumbs[2]) bound the animation range.

Returns The main thumb; read the step index from .value.

var stepIndex = Ext.getCmp('years_tl').getTimeline().getMainThumb().value;

getMaxThumbValue

function() : Number# Returns the position of the right (max) thumb: the last step index the animation reaches.

Returns the position of the right (max) thumb: the last step index the animation reaches.

Returns 0-based step index of the max thumb.

var last = Ext.getCmp('years_tl').getTimeline().getMaxThumbValue();

getMinThumbValue

function() : Number# Returns the position of the left (min) thumb: the step index the animation restarts from.

Returns the position of the left (min) thumb: the step index the animation restarts from.

Returns 0-based step index of the min thumb.

var first = Ext.getCmp('years_tl').getTimeline().getMinThumbValue();

getStyleFromValue

function(value) : String|Object|undefined# Returns the style of a step key or, when the key has no style of its own, the style of the nearest previous key (numeric keys are compared as numbers, text keys by position in steps).

Returns the style of a step key or, when the key has no style of its own, the style of the nearest previous key (numeric keys are compared as numbers, text keys by position in steps).

value String|Number
A step key.

Returns The style (name or {style, name} object), or undefined when no previous step has one.

var style = Ext.getCmp('years_tl').getTimeline().getStyleFromValue('2014');

getTimeline

function() : GeoExt.TimelinePanel# Returns the timeline panel driven by this button.

Returns the timeline panel driven by this button. The markup id identifies the button, so this is the way to reach the panel methods (getValue, updateMainThumbValue, startAnimationStep, setSteps...).

Returns The timeline panel (null after the button was destroyed).

var timeline = Ext.getCmp('years_tl').getTimeline();
timeline.updateMainThumbValue(0); // first step

getValue

function() : String# Returns the key of the step currently selected by the main thumb (the same value the layer receives in inputs.id[ID]).

Returns the key of the step currently selected by the main thumb (the same value the layer receives in inputs.id[ID]).

Returns The current step key (first element of the steps entry).

var year = Ext.getCmp('years_tl').getTimeline().getValue(); // '2010'

getValueFromStyle

function(style) : Number# Returns the step key whose style is the given one (the last match when several steps share a style), or the first step key when the style is empty or unknown.

Returns the step key whose style is the given one (the last match when several steps share a style), or the first step key when the style is empty or unknown. The key is returned through parseInt, so it is meaningful for numeric keys only (text keys give NaN).

style String
A style name as used in steps.

Returns The numeric step key.

var year = Ext.getCmp('years_tl').getTimeline().getValueFromStyle('style_2010'); // 2010

hidden

Boolean= false# Set true to hide the "Show/Hide timeline" button rendered in the layer description (the standard Ext hidden config, so Ext.getCmp(id).show() reveals it).

Set true to hide the "Show/Hide timeline" button rendered in the layer description (the standard Ext hidden config, so Ext.getCmp(id).show() reveals it). The timeline panel itself is still created and its initial visibility follows renderHidden; use it when the timeline is driven by a paramsButtonConfig button or by code instead. Any other Ext.Button config is passed through.

|hidden=true|

hideLabel

Boolean= false# Defines if the label of the timeline should be displayed.

Defines if the label of the timeline should be displayed. Set true to hide the label, false to show it.

|hideLabel=true|

id

String# Defines the id to identify the object.

Defines the id to identify the object. It is the key used in inputs.id[ID] and the id of the show/hide button component: Ext.getCmp(id) returns the button and Ext.getCmp(id).getTimeline() the timeline panel (see the methods listed in this group).

|id=exemple_timeline|

nextAnimationStep

function()# Advances the timeline one step (main thumb + 1), applying the style of the new step to the layer and firing change; does nothing when the main thumb is already at the max thumb.

Advances the timeline one step (main thumb + 1), applying the style of the new step to the layer and firing change; does nothing when the main thumb is already at the max thumb. Useful for a custom "next" button.

Ext.getCmp('years_tl').getTimeline().nextAnimationStep();

nextStepInterval

Number= 2100# Defines the duration of the interval between steps of the timeline in milliseconds.

Defines the duration of the interval between steps of the timeline in milliseconds.

|nextStepInterval=1000|

onPlayToggle

function# Defines the callback function called when the play/stop button is toggled, BEFORE the animation starts or stops.

Defines the callback function called when the play/stop button is toggled, BEFORE the animation starts or stops. It must return a truthy value: returning false/nothing cancels the start/stop (use it as a veto, e.g. while data is loading). pressed is true when the animation is about to start.

The value is resolved as a key of the layer functions object, then as a global function with that name, then as inline function text (function(...){...}; a plain statement body also works and returns true).

pressed Boolean
True if the button was pressed (animation about to start), False otherwise.
layer Object
The layer associated to this timeline.
timeline Object
The timeline panel.
playBtn Object
The play/stop button.
|onPlayToggle=onPlayToggle|
|onPlayToggle = function (pressed, layer, timeline, playBtn) {
     console.log("The timeline is about to " + (pressed ? "start" : "stop"));
     return true; // required, a falsy return cancels the toggle
}|

playing

Boolean= false# true while the animation is running (between play and stop/end).

true while the animation is running (between play and stop/end). Read it on the panel (Ext.getCmp(id).getTimeline().playing) to know whether to call startAnimationStep() or stopAnimation().

if (!Ext.getCmp('years_tl').getTimeline().playing) Ext.getCmp('years_tl').getTimeline().startAnimationStep();

preloadTiles

Boolean= false# Defines if the timeline should preload the tiles of the next steps to get smoother transitions.

Defines if the timeline should preload the tiles of the next steps to get smoother transitions. Set it true to preload, false otherwise.

|preloadTiles = true|

renderHidden

Boolean= false# Defines the timeline initial visibility.

Defines the timeline initial visibility. Set it true to start with the timeline hidden, false otherwise.

|renderHidden = true|

setCurrentLayerStyle

function(style)# Applies a style to the layer the way a step does: a style name, or a {style, name} object that also switches the WMS layer name (the object form of a steps entry).

Applies a style to the layer the way a step does: a style name, or a {style, name} object that also switches the WMS layer name (the object form of a steps entry). For a composed layer the first inner layer is updated and the legend is rebuilt. The slider is not moved (use updateMainThumbValue).

style String|Object
Style name ('' for the default) or {style: 'name', name: 'CSR:layer'}.
Ext.getCmp('years_tl').getTimeline().setCurrentLayerStyle({style: 'estados_2', name: 'CSR:estados'});

setDesiredVisibility

function(visible) : GeoExt.TimelinePanel# Shows or hides the timeline panel while keeping it consistent with the layer: when the layer is hidden the panel stays hidden and the requested state is remembered, to be applied as soon as the layer becomes visible.

Shows or hides the timeline panel while keeping it consistent with the layer: when the layer is hidden the panel stays hidden and the requested state is remembered, to be applied as soon as the layer becomes visible. Prefer it over show()/hide(); the show/hide button follows the panel automatically.

visible Boolean
true to show the timeline (once the layer is visible), false to hide it.

Returns The panel, for chaining.

Ext.getCmp('years_tl').getTimeline().setDesiredVisibility(true);

setMaxThumbValue

function(value)# Moves the right (max) thumb, limiting the animation to the steps up to that index (no animation, no change event).

Moves the right (max) thumb, limiting the animation to the steps up to that index (no animation, no change event).

value Number
0-based step index for the max thumb.
Ext.getCmp('years_tl').getTimeline().setMaxThumbValue(5);

setMinThumbValue

function(value)# Moves the left (min) thumb, making the animation start from that step index (no animation, no change event).

Moves the left (min) thumb, making the animation start from that step index (no animation, no change event).

value Number
0-based step index for the min thumb.
Ext.getCmp('years_tl').getTimeline().setMinThumbValue(2);

setSteps

function(steps)# Replaces the steps of the timeline and redraws it (labels, slider range and current step).

Replaces the steps of the timeline and redraws it (labels, slider range and current step). Unlike the markup steps parameter this takes the already-built object: keys are the step labels, values the style name or a {style, name} object. Use it to change the available periods at runtime (e.g. after a combobox selection).

steps Object
Map of step key to style: {'1990': 'style_1990', '2000': {style: 's2000', name: 'CSR:layer'}}.
Ext.getCmp('years_tl').getTimeline().setSteps({2000: 'style_2000', 2010: 'style_2010'});

startAnimationStep

function()# Starts (or resumes) the animation from the current step: each step is shown for nextStepInterval milliseconds after the layer finished loading it, up to the max thumb, where the animation stops by itself.

Starts (or resumes) the animation from the current step: each step is shown for nextStepInterval milliseconds after the layer finished loading it, up to the max thumb, where the animation stops by itself. When the main thumb is already at the max thumb it restarts from the min thumb. Same as pressing the play button, except that onPlayToggle is not consulted.

Ext.getCmp('years_tl').getTimeline().startAnimationStep();

steps

Array.<Array.<(String|Object)>># Defines the timeline change steps.

Defines the timeline change steps.

|steps=[["step_0"], ["step_1"], ["step_2"]]|
|steps=[['Nome', {style:"step_0_style",name:"CSR:estados"}], ['Região', {style:"step_1_style",name:"CSR:estados"}], ['Geocódigo', {style:"step_2_style",name:"CSR:estados"}]]|
|steps=[['Nome', 'step_0'], ['Região', 'step_1'], ['Geocódigo', 'step_2']]|
|steps=[{1990: "layer_style0", 1991: "layer_style1", 1992: "layer_style2"}, 1993: "layer_style3"}]|

stopAnimation

function()# Stops the running animation (cancels the pending step timer, releases the play button and hides the slider tip).

Stops the running animation (cancels the pending step timer, releases the play button and hides the slider tip). The current step is kept. Safe to call when nothing is playing.

Ext.getCmp('years_tl').getTimeline().stopAnimation();

toggleTimelineVisibility

function(forceState)# Shows or hides the timeline panel from code — what clicking the button does.

Shows or hides the timeline panel from code — what clicking the button does. Without an argument the current (desired) visibility is inverted. The panel only appears while the layer is visible; the requested state is remembered otherwise (see setDesiredVisibility).

forceState Boolean
true to show the timeline, false to hide it; omit to invert.
Ext.getCmp('years_tl').toggleTimelineVisibility(true);

updateLayer

function(value)# Applies to the layer the style of a step key, without moving the slider.

Applies to the layer the style of a step key, without moving the slider. When the key has no step of its own the style of the nearest previous numeric key is used (steps {2010: "s1", 2015: "s2"} and value 2014 keep/apply "s1"); nothing happens when that style is already active. Called by the slider on every change; call it yourself to preview a step, then updateMainThumbValue() to sync the thumb.

value String|Number
A step key (first element of a steps entry).
Ext.getCmp('years_tl').getTimeline().updateLayer('2010');

updateMainThumbValue

function(value)# Moves the main thumb to a step index (0-based position in steps), applying that step's style to the layer and firing change — the programmatic way to select a step.

Moves the main thumb to a step index (0-based position in steps), applying that step's style to the layer and firing change — the programmatic way to select a step. Without an argument it re-syncs the thumb with the layer's current style using getValueFromStyle (used when another tool changes the style). The min/max thumbs are pushed outwards when the index falls outside the current range.

value Number
Step index; omit to sync the thumb with the layer's current style.
Ext.getCmp('years_tl').getTimeline().updateMainThumbValue(2); // third step

value

String# Value stored in inputs.id[ID] (and inputs[i]): the key of the current step — the first element of the selected steps entry (e.g. "1990" or "January"), as a string.

Value stored in inputs.id[ID] (and inputs[i]): the key of the current step — the first element of the selected steps entry (e.g. "1990" or "January"), as a string. It changes whenever the main thumb moves (drag, click or animation) and the layer recalculates on the widget change event, after the layer style of the step was applied. The same change event is fired on the button (Ext.getCmp(id).on('change', function(button, value) {...})).

{{timeline|id=years_tl|nextStepInterval=1500|steps=[['1990', 'style_1990'], ['2000', 'style_2000'], ['2010', 'style_2010']]}}
beforeCalc: function(inputs) {
    var year = parseInt(inputs.id['years_tl'], 10);
}

window · floating window (input)

Window22 entries

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

Tool that allows to show contents in an interactive floating window.
It can only be shown when the layer is visible.
This tool is created from Ext.Window.

btnID

String# Defines the id of the button that controls the window visibility.

Defines the id of the button that controls the window visibility.

|btnID = window-button-id|

getButton

function() : Ext.Button# Returns the show/hide toggle Ext.Button (id btnID), e.g. to toggle(true), setText() or hide() it.

Returns the show/hide toggle Ext.Button (id btnID), e.g. to toggle(true), setText() or hide() it.

Returns The toggle button component.

this.getInputs().id['report_btn'].getButton().setText('Hide report');

getContainer

function() : Ext.Container# Returns the content container (Ext.Container, id id) inside the window.

Returns the content container (Ext.Container, id id) inside the window. Use update(html) to replace its HTML, or add()/doLayout() to place Ext components in it.

Returns The content container of the window.

this.getInputs().id['report_btn'].getContainer().update('<p>' + text + '</p>');

getIds

function() : Array.<String># Returns the ids of the three components created by the tool, in the order [windowID, id (content div), btnID].

Returns the ids of the three components created by the tool, in the order [windowID, id (content div), btnID].

Returns [windowId, containerId, buttonId].

var ids = this.getInputs().id['report_btn'].getIds(); // ['report_win', 'report_div', 'report_btn']

getWindow

function() : Ext.Window# Returns the floating Ext.Window (use it for show(), hide(), setTitle(), setSize(), setPosition()...).

Returns the floating Ext.Window (use it for show(), hide(), setTitle(), setSize(), setPosition()...). Prefer getButton().toggle() to change visibility so the button stays in sync.

Returns The window component (it is destroyed together with the layer).

this.getInputs().id['report_btn'].getWindow().setTitle('Report - ' + year);

height

number# Defines the floating window initial height.

Defines the floating window initial height.

|height = 600px|

html

String# Defines the initial HTML content of the window's container div.

Defines the initial HTML content of the window's container div. Because the parser treats everything after html= as the value, the content may contain = characters; it cannot contain | or }}. For content built at runtime, write into the container instead (inputs.id[ID].getContainer().update(html) or Ext.getCmp(id).update(html)).

|html=<div class="report">Loading...</div>|

id

String# Defines an id for the div contained in the floating window (where the content can be drawn).

Defines an id for the div contained in the floating window (where the content can be drawn).

|id = window-div-id|

ignoreVisibility

Boolean# Defines if the window should ignore the layer visibility state.

Defines if the window should ignore the layer visibility state. By default, the window visibility state is the same as the layer's. Set true to ignore the layer visibility state, false otherwise.

PS: The 'ignoreVisibility' is not compatible with the 'associatedButtonID' property. When both are used together, the ignoreVisibility value is ignored.

|ignoreVisibility = false|

items

Array# Not supported: the tool always creates its own single content container (the div identified by id), so any items written in the markup are discarded.

Not supported: the tool always creates its own single content container (the div identified by id), so any items written in the markup are discarded. Put content in with html=, or render into the container from code (Ext.getCmp(id) / inputs.id[ID].getContainer()).

onBeforeHide

function# Defines a callback function to be called before hiding the floating window.

Defines a callback function to be called before hiding the floating window.

layer Object
Scope of the layer
data Array
[window, button, windowConfig] window: Window object; button: Button created; windowConfig: Window object configuration
|onBeforeHide = function (layer, [window, button, windowConfig]){
 console.log(layer);
 console.log([window, button, windowConfig]);
}|

resize

function# Defines the callback function to be called when the floating window is resized.

Defines the callback function to be called when the floating window is resized.

|resize = function (){
 console.log("I was resized!");
}|

startVisible

Boolean# Defines if the window should start visible or not.

Defines if the window should start visible or not. Set true if it should, false otherwise.

|startVisible = false|

text

string= Show/Hide Window# Defines the window button text.

Defines the window button text.

|text = I am a button|

title

String= Window# Defines the floating window's title.

Defines the floating window's title.

|title = Title of the Window|

toggle

function(pressed)# Shows or hides the floating window from code by pressing/releasing its toggle button — the same as the user clicking it, so onBeforeHide still runs.

Shows or hides the floating window from code by pressing/releasing its toggle button — the same as the user clicking it, so onBeforeHide still runs. Call it on the button: inputs.id[ID].getButton().toggle(state) or Ext.getCmp(btnID).toggle(state). Without an argument the state is inverted.

pressed Boolean
true to show the window, false to hide it; omit to invert.
this.getInputs().id['report_window'].getButton().toggle(true);

underButtons

Boolean# Defines where the floating window will be positioned in relation to the buttons panel.

Defines where the floating window will be positioned in relation to the buttons panel. Set true to position the window under the right buttons panel, false otherwise.

|underButtons = false|

value

Object# Value stored in inputs.id[btnID] - under the show/hide button's id, not the markup id, so set btnID to read it (without one the key is an automatic id): a small handle object with the methods …

Value stored in inputs.id[btnID] - under the show/hide button's id, not the markup id, so set btnID to read it (without one the key is an automatic id): a small handle object with the methods getIds(), getWindow(), getButton() and getContainer() to reach the three Ext components of the tool (the floating window, its content div and the show/hide button). The input is registered on the window afterrender event, so it triggers one recalculation when the window is first rendered; it never changes afterwards. The handle contains component references, so do not use it inside expression (WebWorker) — read it in beforeCalc or in button/window callbacks.

{{window|id=report_div|btnID=report_btn|windowID=report_win|title=Report|startVisible=true}}
beforeCalc: function(inputs) {
    var wnd = inputs.id['report_btn'];
    wnd.getContainer().update('<b>Total:</b> ' + total);
    wnd.getButton().toggle(true);
}

width

number# Defines the floating window initial width.

Defines the floating window initial width.

|width = 600px|

windowID

String# Defines the window id.

Defines the window id.

|windowID = window-id|

x

Number# Defines the initial absolute X position of the window, in pixels from the left edge of the page.

Defines the initial absolute X position of the window, in pixels from the left edge of the page. A negative value counts from the right edge instead: the window's right side is placed at viewportWidth + x (e.g. x=-10 leaves a 10px margin on the right).

PS: Overwritten when 'underButtons' is used (or when neither x nor y is given).

|x=-115|y=103|

y

Number# Defines the initial absolute Y position of the window, in pixels from the top of the page.

Defines the initial absolute Y position of the window, in pixels from the top of the page. A negative value counts from the bottom edge instead: the window's bottom side is placed at viewportHeight + y (e.g. y=-20 leaves a 20px margin at the bottom).

PS: Overwritten when 'underButtons' is used (or when neither x nor y is given).

|x=20|y=-20|

zoomlevel · current zoom (input)

ZoomLevel2 entries

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

A hidden input whose value is the current map zoom level; the layer recalculates whenever the zoom changes.
Usage: {{zoomlevel|id=zoom}} then inputs.id['zoom'] in beforeCalc/expression

id

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

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

|id=zoom|

value

Number# Value stored in inputs.id[ID] (and inputs[i]) for beforeCalc/expression: the current map zoom level as a number.

Value stored in inputs.id[ID] (and inputs[i]) for beforeCalc/expression: the current map zoom level as a number. It is refreshed on the map moveend event and only triggers a recalculation when the zoom actually changed (panning is ignored).

{{zoomlevel|id=zoom}}
beforeCalc: function(inputs) {
    var zoom = inputs.id['zoom'];
    this.changeLayers({name: zoom > 10 ? 'CSR:municipalities' : 'CSR:estados', index: 0});
}

Query setup: calls before the layer list

Calls written before the list of layers and joined to it with &&. They change the whole map - settings, globals, extra map servers, coordinate systems - until another query is applied. Each returns true, so the list after && is still read.
A query-wide setting and a registered server before the list:
Example
ExtjsUtils.CONFIGURATION.setOptions({ keepOnLeave: false }) &&
ExtjsUtils.QUERY.addRemoteWMSServer({
  prodes: { url: "https://terrabrasilis.dpi.inpe.br/geoserver/prodes-legal-amz/ows?" },
}) && [
  { name: "yearly_deforestation", source: "prodes", title: "Deforestation (INPE)", visibility: true },
];

QUERY · setup calls and the running query

QUERY40 entries
ExtjsUtils.QUERY: calls before the list (setQueryGlobalProperties, addRemoteWMSServer, decorate, setMappiaIoCallback) and changes to the running query from your functions (addLayer, removeLayer, postMessage).

PathDescription

functionhelper# Internal — constructor of the objects the interpreter stores in each layer's path and viewPath arrays to describe the group (or view) the layer belongs to, one entry per nesting level.

Written as ExtjsUtils.QUERY.PathDescription

Internal — constructor of the objects the interpreter stores in each layer's path and viewPath arrays to describe the group (or view) the layer belongs to, one entry per nesting level. new PathDescription(groupNode, layerIndex, cfg): groupNode is the group definition object (its title is used) or a bare title string; layerIndex is the position of the layer in the flattened definition; cfg is copied as the group's configuration. Instances expose getTitle() (group/view title), getCfg() (copy of the group definition) and getDefinitionIndex() (the layer index). Tenant code normally does not build these — QUERY.addLayer with a group object does it — but a hand-built layer record can set path: [new ExtjsUtils.QUERY.PathDescription("My group", 0, null)] to appear under a group in the layer tree.

groupNode Object|String
Group definition object (its title is used) or the title itself.
layerIndex Number
Index of the layer in the flattened query definition.
cfg Object
Group configuration to copy into the descriptor (may be null).
var pathEntry = new ExtjsUtils.QUERY.PathDescription("Remote layers", 0, null);
pathEntry.getTitle(); // "Remote layers"

addLayer

function(cfg) : Array.<GeoExt.data.LayerRecord>helper# Adds layers to the map at runtime from the same definitions used in the query array.

Written as ExtjsUtils.QUERY.addLayer

Adds layers to the map at runtime from the same definitions used in the query array. cfg may be a single layer definition, an array of definitions, or a full group object ({viewTitle, title, color, elements: [...]}) whose elements are then shown grouped in the layer tree. The definition goes through the regular query parse pipeline (group defaults, path/viewPath, priority order) with the current query's globals kept, so functions inside it (handlers, styleMap callbacks) still work. Side-effect APIs such as addRemoteWMSServer or decorate cannot be embedded in a definition object: register remote sources before calling addLayer, otherwise a layer whose source is unknown is skipped with "Source not found by name" in the console. Typically called from a setMappiaIoCallback handler or a button handler to inject layers on demand.

cfg Object|Array.<Object>
One layer definition, an array of definitions, or a group object with elements.

Returns The layer records added to the map (skipped definitions are omitted).

// Single layer
ExtjsUtils.QUERY.addLayer({ name: "CSR:estados", title: "States", visibility: true });
// A whole group, shown under its own view/title in the layer tree
ExtjsUtils.QUERY.addLayer({
  viewTitle: "Data sources",
  title: "Boundaries",
  color: "#0073E6",
  elements: [
    { name: "CSR:estados", title: "States", visibility: true },
    { name: "CSR:municipios", title: "Municipalities", visibility: false }
  ]
});

addNewLayerAsBackground

function(layerDefinition, hideBackgroundLayers)helper# Adds a layer and uses it as the background map: the definition gets group: "background", visibility: true and a very low priority (so it stays under every other layer) and is added with QUERY.addLayer.

Written as ExtjsUtils.QUERY.addNewLayerAsBackground

Adds a layer and uses it as the background map: the definition gets group: "background", visibility: true and a very low priority (so it stays under every other layer) and is added with QUERY.addLayer. By default the current background layers are hidden first. A bare layer name string is accepted as the definition.

layerDefinition Object|String
Layer definition properties, or just the layer name.
hideBackgroundLayers Boolean
Hide the existing background layers before adding the new one.
ExtjsUtils.QUERY.addNewLayerAsBackground({"name": "CSR:paises"})
ExtjsUtils.QUERY.addNewLayerAsBackground("CSR:paises", false)

addRemoteWMSServer

function(wmsDefinitions) : Booleanhelper# Registers extra WMS servers as layer sources for the current query.

Written as ExtjsUtils.QUERY.addRemoteWMSServer

Registers extra WMS servers as layer sources for the current query. Each key of wmsDefinitions becomes a source id: a layer selects it with source: "<id>" and uses the layer name published by that server's capabilities as name. Chain it with && before the layer array so the sources exist when the layers are created. Skipped in "just eval" mode.

Source definition properties:

  • url {String} URL of the WMS (mandatory unless ptype is given).
  • cors {Boolean} Route the requests through the Mappia CORS proxy (/cors/)
       for servers without CORS headers.
  • updateWMS {Boolean} Bypass the proxy cache (/cors/direct/) to get fresh content.
  • storage {String} Rewrites url for hosted layer stores: "github" (raw
       GitHub content, cache-busted), "jsdelivr" (jsDelivr CDN, append @VERSION
       to the URL to force an update; releases: https://help.github.com/en/articles/creating-releases),
       "remote" (no rewrite). All storage values append /getCapabilities.xml?.
  • ptype {String} Source plugin type, default "gxp_customwmscsource".
  • onLoad {Function} Called when the source capabilities are loaded.
  • onError {Function} Called when the source fails to load.

With ?options=capabilities (calculator only) every URL is replaced by the per-query filtered capabilities endpoint.

wmsDefinitions Object
Map of source id to source definition.

Returns Always true, so the call can be chained with && QUERY_DESCRIPTION.

ExtjsUtils.QUERY.addRemoteWMSServer({
 geoinfo: {
  url: "http://geoinfo.cnps.embrapa.br/geoserver/wms?SERVICE=WMS&",
  cors: true
 },
 ibge: {
  url: "https://geoservicos.ibge.gov.br/geoserver/CCAR/wms?",
  cors: true
 },
 gitHub: {
   url: "https://github.com/asfixia/CustomWMS@0.1",
   storage: "github",
   updateWMS: true,
   cors: true
 }
})
&&
[
  { name: "CCAR:BC250_Trecho_Rodoviario_L", source: "ibge", visibility: true },
  { name: "my_layer", source: "gitHub" }
]

clearQueryGlobalProperties

function()helper# Internal — undoes every side effect of the current query: deletes the globals it created, destroys its remote WMS sources, resets the stored settings, the query configuration (CONFIGURATION), the …

Written as ExtjsUtils.QUERY.clearQueryGlobalProperties

Internal — undoes every side effect of the current query: deletes the globals it created, destroys its remote WMS sources, resets the stored settings, the query configuration (CONFIGURATION), the dynamic CSS rules, the header/footer decoration and the projection options. Called by the platform before a new query is loaded; tenant code normally does not call it.

ExtjsUtils.QUERY.clearQueryGlobalProperties();

decorate

function(pageProperties) : Booleanhelper# Decorates the page for the current query: header logo and top-bar style, a footer, and arbitrary CSS rules.

Written as ExtjsUtils.QUERY.decorate

Decorates the page for the current query: header logo and top-bar style, a footer, and arbitrary CSS rules. Exactly three keys are reserved:

  • header {Object}: logo: {src, style} puts an image in the top bar's logo container
       (style is an object of CSS properties applied to the container); topbar: {style} styles
       the top bar itself.
  • footer {Object}: html is the footer content, style an object of CSS properties for it;
       the footer container is shown and pinned to the bottom of the page.
  • run {Function}: called once, after the header/footer are applied — the place for
       arbitrary code that must run when the query is decorated. Every other key is passed to CSS.defineClass(key, value) as a CSS rule: the key is the selector and the value the rule body (a string such as "display: none;" or an object of CSS properties). So an accidental extra key becomes a CSS rule — do not put code under a made-up key, use run. Everything is removed when another query loads, and the whole call is a no-op while the query is only being parsed. Chain it with && before the layer array.
pageProperties Object
header, footer, run, plus selector: "css rules" pairs.

Returns Always true, so the call can be chained with && QUERY_DESCRIPTION.

ExtjsUtils.QUERY.decorate({
  header: {
    logo: { src: "https://example.org/logo.png", style: { "padding-left": "10px" } },
    topbar: { style: { "background-color": "#1b5e20" } }
  },
  footer: { html: "<b>Source:</b> my institution", style: { "text-align": "center" } },
  run: function() { console.log("decorated"); },
  ".x-tree-node-anchor": "font-size: 14px;"
}) && QUERY_DESCRIPTION

describeQueryError

function(exception) : Objecthelper# Internal — turns an exception thrown while evaluating a query into {name, message, line?, column?}, the position read from the stack of the evaluated code (Chrome <anonymous>:L:C, Firefox …

Written as ExtjsUtils.QUERY.describeQueryError

Internal — turns an exception thrown while evaluating a query into {name, message, line?, column?}, the position read from the stack of the evaluated code (Chrome <anonymous>:L:C, Firefox eval:L:C) and given in the query text - on its first line the evaluation wrapper's prefix is taken off the column. A SyntaxError usually has no position (the browser does not give one for evaluated code). Tenant code normally does not call it.

exception Error
The exception thrown by evaluateQueryDescription.

Returns The description.

var described = ExtjsUtils.QUERY.describeQueryError(new ReferenceError("x is not defined"));

evaluateQueryDescription

function(queryDescription) : Array|*helper# Internal — evaluates the query source text as a JavaScript expression (eval) and returns its value.

Written as ExtjsUtils.QUERY.evaluateQueryDescription

Internal — evaluates the query source text as a JavaScript expression (eval) and returns its value. This is the step where ExtjsUtils.QUERY.setQueryGlobalProperties(...) && [...] chains actually run. An empty description evaluates to [{'name':'CSR:empty'}]. Tenant code normally does not call it.

queryDescription String
Query source text.

Returns The evaluated value; a valid query yields an array.

var parsed = ExtjsUtils.QUERY.evaluateQueryDescription("[{ name: 'CSR:estados' }]");

failedSources

Array.<String># Reserved list for the remote WMS sources that failed to load.

Written as ExtjsUtils.QUERY.failedSources

Reserved list for the remote WMS sources that failed to load. The platform currently does not populate it (a failed source is simply removed from remoteSources and logged).

getJustEvalFlag

function() : Booleanhelper# Internal — returns the justEval flag; a side-effect API checks it to skip its work while a query is only being parsed.

Written as ExtjsUtils.QUERY.getJustEvalFlag

Internal — returns the justEval flag; a side-effect API checks it to skip its work while a query is only being parsed. Tenant code normally does not call it, although a custom global function with side effects may use it the same way.

Returns True while the query is being evaluated only for parsing.

if (!ExtjsUtils.QUERY.getJustEvalFlag()) applyMySideEffect();

getMappiaMessage

function(wrappedJsMsg) : Object|String|nullhelper# Internal — extracts the Mappia payload from a raw window "message" event: returns event.data.mappia_iframe, JSON-parsed when possible (a plain string is returned as is), or null when the event …

Written as ExtjsUtils.QUERY.getMappiaMessage

Internal — extracts the Mappia payload from a raw window "message" event: returns event.data.mappia_iframe, JSON-parsed when possible (a plain string is returned as is), or null when the event does not carry a mappia_iframe field (i.e. it was not sent through MappiaIO / QUERY.postMessage). Used by queryState.initMessageHandler; tenant code normally does not call it.

wrappedJsMsg MessageEvent
The DOM message event received on window.

Returns The parsed payload, or null when the event is not a Mappia message.

window.addEventListener("message", function(evt) {
  var msg = ExtjsUtils.QUERY.getMappiaMessage(evt);
  if (msg) console.log("Mappia message", msg);
});

getStoredQuerySettings

function() : Objecthelper# Internal — returns the arguments the current query passed to the side-effect APIs, keyed by function name (see globalQueryStoredSettings).

Written as ExtjsUtils.QUERY.getStoredQuerySettings

Internal — returns the arguments the current query passed to the side-effect APIs, keyed by function name (see globalQueryStoredSettings). The editor and the offline-maps tool use it to re-read the query's remote sources; tenant code normally does not call it.

Returns Stored settings, e.g. { addRemoteWMSServer: {...}, decorate: {...} }.

var remoteStores = ExtjsUtils.QUERY.getStoredQuerySettings().addRemoteWMSServer || {};

globalQueryStoredSettings

Object# Arguments the current query passed to the side-effect APIs, keyed by function name ("setQueryGlobalProperties", "addRemoteWMSServer", "decorate"), merged per key.

Written as ExtjsUtils.QUERY.globalQueryStoredSettings

Arguments the current query passed to the side-effect APIs, keyed by function name ("setQueryGlobalProperties", "addRemoteWMSServer", "decorate"), merged per key. The editor and the offline-maps tool read it back through getStoredQuerySettings; it is reset when another query loads.

ExtjsUtils.QUERY.globalQueryStoredSettings.decorate // the object passed to QUERY.decorate

interpretDescription

function(queryDescriptionObj) : Array.<Object>helper# Internal — flattens the normalized query tree (old group syntax) into the ordered array of layer definitions the map is built from.

Written as ExtjsUtils.QUERY.interpretDescription

Internal — flattens the normalized query tree (old group syntax) into the ordered array of layer definitions the map is built from. Each layer receives the properties represented by the tree: path/viewPath (arrays of PathDescription, one per nesting level), color and viewColor (arrays of group colours, default #000000), visibility (default false), source (default "local") and definitionOrder; the global key of every group and layer is applied through setQueryGlobalProperties. The result is sorted by priority (descending) and reversed so that the first definition ends up on top of the map. Tenant code normally does not call it.

queryDescriptionObj Array
Normalized query array, as returned by parseQueryDefinition.

Returns Flat, ordered array of layer definitions (empty when the input is falsy).

var layers = ExtjsUtils.QUERY.interpretDescription(ExtjsUtils.QUERY.parseQueryDefinition(queryText, true));

justEval

Boolean# When true the query is being evaluated only to be parsed/validated: addRemoteWMSServer, decorate, CONFIGURATION.setOptions and the runNow hook become no-ops.

Written as ExtjsUtils.QUERY.justEval

When true the query is being evaluated only to be parsed/validated: addRemoteWMSServer, decorate, CONFIGURATION.setOptions and the runNow hook become no-ops. Set by parseQueryObject and read through getJustEvalFlag.

lastQueryError

Object|null= null# The error of the last query applied through MappiaIO (RUN_QUERY_APPLY), or null when it evaluated to a list of layers: {name, message, line?, column?} - line and column in the query text as the page sent it.

Written as ExtjsUtils.QUERY.lastQueryError

The error of the last query applied through MappiaIO (RUN_QUERY_APPLY), or null when it evaluated to a list of layers: {name, message, line?, column?} - line and column in the query text as the page sent it. Reset at the start of every apply; it is what the page receives as mappia__queryError just before mappia__queryApplied.

// inside the map page: why did the last query apply nothing?
console.log(ExtjsUtils.QUERY.lastQueryError); // {name: "ReferenceError", message: "TITLE is not defined", line: 3, column: 12}

layerLoading

SharedCounter# Counter of layer resources (files, GeoJSON, CSV, composed children) still loading for the current query.

Written as ExtjsUtils.QUERY.layerLoading

Counter of layer resources (files, GeoJSON, CSV, composed children) still loading for the current query. It is recreated at the start of every query load. layerLoading.addZeroCallback(fn) fires fn when all layer loads finish — this is the standard "wait until the layers are loaded" hook for tenant code (the platform uses the same hook to zoom to the layers' extent and fire QUERY_LOADED). The callback stays registered unless it returns false, and only fires on a transition to zero, so check getCount() first when nothing may be loading.

ExtjsUtils.QUERY.setQueryGlobalProperties({
  runNow: function() {
    ExtjsUtils.QUERY.layerLoading.addZeroCallback(function() {
      console.log("All layers of the query are loaded");
    });
  }
}) && QUERY_DESCRIPTION

loadCurrentQuery

function(map, queryDescription, afterLoadCallback) : Array.<Object>|nullhelper# Internal — loads a whole query into the application, replacing the current one: clears the previous query's globals, remote sources, CSS and decoration, removes every non-default layer, parses …

Written as ExtjsUtils.QUERY.loadCurrentQuery

Internal — loads a whole query into the application, replacing the current one: clears the previous query's globals, remote sources, CSS and decoration, removes every non-default layer, parses queryDescription (when it is a string), waits for the remote sources (sourceLoading) and then creates the layers; once layerLoading reaches zero it zooms to the layers' extent (unless the URL has extent), calls afterLoadCallback and fires QUERY_LOADED. Wrapped in queryState.startWaiting("loadCurrentQuery"). This is what the viewer, the editor and a RUN_QUERY_APPLY message use; tenant code normally does not call it.

map GeoExplorer
The application instance (ExtjsUtils.JS.getApp()), despite the parameter name.
queryDescription String|Array.<Object>
Query source text, or an already parsed query array.
afterLoadCallback function
Called after the layers were sent to load (also on failure).

Returns The parsed query definition on success, null when it failed to parse.

ExtjsUtils.QUERY.loadCurrentQuery(ExtjsUtils.JS.getApp(), "[{ name: 'CSR:estados' }]", function() { console.log("loaded"); });

normalizeLayersWithNoGroup

function(queryDescription) : Arrayhelper# Internal — moves every top-level layer that is not inside a group into a default group (title Lang.maps, i.e. "Maps", color #000000) appended at the end, so that the interpreter only ever sees …

Written as ExtjsUtils.QUERY.normalizeLayersWithNoGroup

Internal — moves every top-level layer that is not inside a group into a default group (title Lang.maps, i.e. "Maps", color #000000) appended at the end, so that the interpreter only ever sees groups at the top level. Works on the old (array-per-group) syntax and mutates the array in place. Tenant code normally does not call it.

queryDescription Array
Parsed query in the old group syntax.

Returns The same array, now containing only groups.

ExtjsUtils.QUERY.normalizeLayersWithNoGroup([{ name: "CSR:estados" }]);
// => [[{ title: "Maps", color: "#000000" }, { name: "CSR:estados" }]]

parseQueryDefinition

function(queryDescription, keepGlobalProperties) : Array.<Object>|nullhelper# Internal — parses and validates query source text: returns the normalized query array (parseQueryObject) or null when the text does not evaluate to a non-empty array or throws (the error is logged to the console).

Written as ExtjsUtils.QUERY.parseQueryDefinition

Internal — parses and validates query source text: returns the normalized query array (parseQueryObject) or null when the text does not evaluate to a non-empty array or throws (the error is logged to the console). Unless keepGlobalProperties is true the previous query's globals, remote sources, CSS and decoration are cleared before parsing; they are always cleared when the query turns out to be invalid. Used by the viewer/editor to load a query and by QUERY.addLayer (with keepGlobalProperties); tenant code normally does not call it.

queryDescription String
Query source text.
keepGlobalProperties Boolean
True to keep the current query's globals and side effects instead of clearing them first.

Returns The normalized query array, or null when the query is invalid.

var parsed = ExtjsUtils.QUERY.parseQueryDefinition("[{ name: 'CSR:estados' }]", true);

parseQueryObject

function(queryDescription, justEval) : Arrayhelper# Internal — turns the query source text into the normalized array the interpreter expects: evaluateQueryDescription → parseToOldGroupSyntax → normalizeLayersWithNoGroup → setGroupDefaults.

Written as ExtjsUtils.QUERY.parseQueryObject

Internal — turns the query source text into the normalized array the interpreter expects: evaluateQueryDescription → parseToOldGroupSyntax → normalizeLayersWithNoGroup → setGroupDefaults. With justEval true the justEval flag is raised during the evaluation, which makes side-effect APIs (addRemoteWMSServer, decorate, CONFIGURATION.setOptions, runNow) no-ops so the query can be validated without touching the page; the previous flag value is restored afterwards. Tenant code normally does not call it.

queryDescription String
Query source text.
justEval Boolean
True to only parse the query, suppressing its side-effect calls.

Returns Normalized query array in the old group syntax.

var parsed = ExtjsUtils.QUERY.parseQueryObject("[{ name: 'CSR:estados' }]", true);

parseToNewGroupSyntax

function(queryDescription) : Arrayhelper# Internal — converts a parsed query from the old group syntax (a group is an array whose first element holds the group properties and the remaining elements are its layers) to the new syntax (a group …

Written as ExtjsUtils.QUERY.parseToNewGroupSyntax

Internal — converts a parsed query from the old group syntax (a group is an array whose first element holds the group properties and the remaining elements are its layers) to the new syntax (a group is an object with an elements array). Only the first level is converted. Tenant code normally does not call it.

queryDescription Array
Parsed query in the old (array-per-group) format.

Returns Query with each group as {title, color, ..., elements: [...]}.

ExtjsUtils.QUERY.parseToNewGroupSyntax([[{ title: "Group" }, { name: "CSR:estados" }]]);
// => [{ title: "Group", elements: [{ name: "CSR:estados" }] }]

parseToOldGroupSyntax

function(queryDescription) : Arrayhelper# Internal — converts a parsed query from the new group syntax (a group is an object with an elements array) to the old syntax the interpreter works with (a group is an array whose first element …

Written as ExtjsUtils.QUERY.parseToOldGroupSyntax

Internal — converts a parsed query from the new group syntax (a group is an object with an elements array) to the old syntax the interpreter works with (a group is an array whose first element holds the group properties and the remaining elements are its layers). Nested groups are converted recursively; elements without elements are left untouched. Tenant code normally does not call it.

queryDescription Array
Parsed query, possibly mixing both group syntaxes.

Returns Query with every group as [groupProps, layer, layer, ...].

ExtjsUtils.QUERY.parseToOldGroupSyntax([{
  title: "Group 1", color: "#FF0000",
  elements: [{ name: "CSR:layer_name_1" }, { name: "CSR:layer_name_2" }]
}]);
// => [[{ title: "Group 1", color: "#FF0000", elements: null }, { name: "CSR:layer_name_1" }, { name: "CSR:layer_name_2" }]]

queryState

Object# Internal — coordinates the "apply a query" cycle with the postMessage protocol used by the editor/calculator pages and by embedding sites (MappiaIO).

Written as ExtjsUtils.QUERY.queryState

Internal — coordinates the "apply a query" cycle with the postMessage protocol used by the editor/calculator pages and by embedding sites (MappiaIO). It counts the operations still in progress (startWaiting/endWaiting) and queues incoming messages while any is active, so an applyQuery message or a MappiaIO message is never handled in the middle of a query load. Its members are documented under QueryState. Tenant code normally does not use it.

remoteSources

Array.<String># Ids of the remote WMS sources registered by the current query with addRemoteWMSServer (loaded or still loading).

Written as ExtjsUtils.QUERY.remoteSources

Ids of the remote WMS sources registered by the current query with addRemoteWMSServer (loaded or still loading). A source that fails to load is removed from it. Cleared when another query loads.

ExtjsUtils.QUERY.remoteSources.indexOf("ibge") >= 0

removeLayer

function(layerName) : Booleanhelper# Removes from the map the layer with the given name (matched against the OpenLayers layer name or its WMS LAYERS param).

Written as ExtjsUtils.QUERY.removeLayer

Removes from the map the layer with the given name (matched against the OpenLayers layer name or its WMS LAYERS param). Use it together with QUERY.addLayer to swap layers at runtime.

layerName String
Full layer name, e.g. "CSR:estados".

Returns True when the layer was removed, false otherwise.

ExtjsUtils.QUERY.removeLayer("CSR:estados");

removeLayerByReference

function(curLayer) : Booleanhelper# Removes a layer from the map given its layer record (as returned by QUERY.addLayer) or its OpenLayers layer object.

Written as ExtjsUtils.QUERY.removeLayerByReference

Removes a layer from the map given its layer record (as returned by QUERY.addLayer) or its OpenLayers layer object. Failures (e.g. a Google layer whose API did not initialise) are caught and logged, returning false.

curLayer GeoExt.data.LayerRecord|OpenLayers.Layer
Layer record or OpenLayers layer to remove.

Returns True if the layer was removed, false otherwise.

var records = ExtjsUtils.QUERY.addLayer({ name: "CSR:estados" });
// later
ExtjsUtils.QUERY.removeLayerByReference(records[0]);

removeRemoteWMSServers

function(serverId)helper# Internal — destroys one remote WMS source registered by the query (by id) or, without an argument, all of them, removing them from remoteSources, app.layerSources and app.sources.

Written as ExtjsUtils.QUERY.removeRemoteWMSServers

Internal — destroys one remote WMS source registered by the query (by id) or, without an argument, all of them, removing them from remoteSources, app.layerSources and app.sources. Called when a source fails to load and when another query loads; tenant code normally does not call it.

serverId String
Id of the source to remove (the key used in addRemoteWMSServer); omit to remove all.
ExtjsUtils.QUERY.removeRemoteWMSServers("ibge");

resetQueryDecoration

function()helper# Internal — removes the page decoration applied by QUERY.decorate: clears the logo container of the top bar and empties and hides the footer container.

Written as ExtjsUtils.QUERY.resetQueryDecoration

Internal — removes the page decoration applied by QUERY.decorate: clears the logo container of the top bar and empties and hides the footer container. Part of clearQueryGlobalProperties; tenant code normally does not call it.

ExtjsUtils.QUERY.resetQueryDecoration();

resetStoredGlobalQuerySettings

function()helper# Internal — empties globalQueryStoredSettings.

Written as ExtjsUtils.QUERY.resetStoredGlobalQuerySettings

Internal — empties globalQueryStoredSettings. Part of clearQueryGlobalProperties; tenant code normally does not call it.

ExtjsUtils.QUERY.resetStoredGlobalQuerySettings();

runNow

function()# The query's startup hook.

The query's startup hook. The query does not call this: it defines a global named runNow through setQueryGlobalProperties({ runNow: function() {...} }) and the platform calls it once, right after the globals of that call are registered (i.e. before the layer array is evaluated) and never again for the same query (runNow.already guards it). It is skipped while the query is only being parsed (justEval). Use it for one-time setup such as ZOOM.limitZoomLevel, registering layerLoading.addZeroCallback, custom controls or redirects. Because it runs before the layers exist, use layerLoading/QUERY_LOADED for work that needs them.

ExtjsUtils.QUERY.setQueryGlobalProperties({
  runNow: function() {
    ExtjsUtils.ZOOM.limitZoomLevel(17);
    ExtjsUtils.QUERY.layerLoading.addZeroCallback(function() { console.log("layers loaded"); });
  }
}) && QUERY_DESCRIPTION

runOnceLayerVisible

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

Written as ExtjsUtils.QUERY.runOnceLayerVisible

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

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

setBaseLayerVisibility

function(visibility)helper# Set baselayer visibility.

Written as ExtjsUtils.QUERY.setBaseLayerVisibility

Set baselayer visibility.

Legacy helper: hides all backgrounds then sets the last one's visibility. Prefer per-layer visibility when loading a query (OpenLayers.BackgroundSelector applies each background's own visibility flag via applyVisibilitiesFromQuery).

visibility Boolean
The visibility applied to the last background layer.
ExtjsUtils.QUERY.setBaseLayerVisibility(false);

setGroupDefaults

function(queryDescriptionObj) : Arrayhelper# Internal — applies each group's defaultProperties to every layer and subgroup inside it (recursively, with Ext.applyIf, so a value set on the layer itself or on a nearer group wins).

Written as ExtjsUtils.QUERY.setGroupDefaults

Internal — applies each group's defaultProperties to every layer and subgroup inside it (recursively, with Ext.applyIf, so a value set on the layer itself or on a nearer group wins). See GroupProperties.defaultProperties for the tenant-facing behaviour. Works on the old (array-per-group) syntax and mutates it in place. Tenant code normally does not call it.

queryDescriptionObj Array
Parsed query in the old group syntax.

Returns The same array with the defaults applied.

ExtjsUtils.QUERY.setGroupDefaults([[{ title: "G", defaultProperties: { opacity: 0.5 } }, { name: "CSR:estados" }]]);
// the layer now has opacity: 0.5

setJustEvalFlag

function(status)helper# Internal — sets the justEval flag, which makes the query's side-effect APIs (addRemoteWMSServer, decorate, CONFIGURATION.setOptions, runNow) no-ops while a query is only being parsed.

Written as ExtjsUtils.QUERY.setJustEvalFlag

Internal — sets the justEval flag, which makes the query's side-effect APIs (addRemoteWMSServer, decorate, CONFIGURATION.setOptions, runNow) no-ops while a query is only being parsed. Tenant code normally does not call it.

status Boolean
New value of the flag.
ExtjsUtils.QUERY.setJustEvalFlag(true);

setMappiaIoCallback

function(onMsgCallback) : Booleanhelper# Registers the function that receives the messages the parent window (embedding site or the MappiaIO library) sends to this Mappia page/iframe with postMessage({mappia_iframe: ...}).

Written as ExtjsUtils.QUERY.setMappiaIoCallback

Registers the function that receives the messages the parent window (embedding site or the MappiaIO library) sends to this Mappia page/iframe with postMessage({mappia_iframe: ...}). The callback gets the payload already unwrapped and JSON-parsed (an object or a string); protocol messages are filtered out, and messages received while a query is loading are queued and delivered afterwards. Registering posts CONFIRM_QUERY_LISTENING back to the parent, so the host knows it can start sending. A string with a function body is accepted as the callback. Use MappiaIO.postMessage to answer the parent.

onMsgCallback function
Callback function(jsStr) receiving the payload (Object|String) sent by the parent window.

Returns Always true, so the call can be chained with && QUERY_DESCRIPTION.

ExtjsUtils.QUERY.setMappiaIoCallback(function(msg) {
  if (msg && msg.type === "geojson") {
    ExtjsUtils.QUERY.addLayer({ name: "Received", source: "file", type: "json", json: msg.geojson, visibility: true });
    ExtjsUtils.QUERY.postMessage({ type: "loaded" });
  }
}) && QUERY_DESCRIPTION

setMessageCallback

function(callbackFunction) : Booleanhelper# Internal — alias of QUERY.setMappiaIoCallback: registers the function that receives the messages posted by the parent window (MappiaIO).

Written as ExtjsUtils.QUERY.setMessageCallback

Internal — alias of QUERY.setMappiaIoCallback: registers the function that receives the messages posted by the parent window (MappiaIO). Kept for older queries; new code should call setMappiaIoCallback directly.

callbackFunction function
Callback that receives the message sent by the parent window.

Returns Always true (same as setMappiaIoCallback).

ExtjsUtils.QUERY.setMessageCallback(function(msg) { console.log(msg); }) && QUERY_DESCRIPTION

setQueryGlobalProperties

function(globalProperties) : Booleanhelper# Defines globals for the query: every key of globalProperties becomes a window property (a value, an object or a function) that layer definitions, markup widgets (handler=, onMark=...) and …

Written as ExtjsUtils.QUERY.setQueryGlobalProperties

Defines globals for the query: every key of globalProperties becomes a window property (a value, an object or a function) that layer definitions, markup widgets (handler=, onMark=...) and other query code can reference by name. The names are recorded and the globals are deleted when another query loads. A key that already exists on window and was not created by the query is refused with "Global variable can't be redefined" in the console (the platform's own globals are protected; redefining one of the query's own keys is fine). runNow is the only key the platform itself invokes: right after the globals are registered QUERY.runNow is called once (see that entry). Chain it with && before the layer array so the globals exist when the layers are evaluated; QUERY_DESCRIPTION in the examples stands for that array.

globalProperties Object
Object whose keys become globals; each value may be a value, an object or a function.

Returns Always true, so the call can be chained with && QUERY_DESCRIPTION.

ExtjsUtils.QUERY.setQueryGlobalProperties({
  globalCount: 0,
  onLayerButton: function(btn) { console.log("clicked", btn); },
  runNow: function() { ExtjsUtils.ZOOM.limitZoomLevel(17); }
}) && [
  { name: "CSR:estados", visibility: true, descriptionHtml: "{{button|id=b1|text=Go|handler=onLayerButton}}" }
]

sourceLoading

SharedCounter# Counter of remote WMS sources (registered with addRemoteWMSServer) still loading their capabilities.

Written as ExtjsUtils.QUERY.sourceLoading

Counter of remote WMS sources (registered with addRemoteWMSServer) still loading their capabilities. It is recreated at the start of every query load, and the query's layers are only created once it drops to zero. sourceLoading.addZeroCallback(fn) fires fn when the last source finishes; the callback stays registered unless it returns false. The callback only fires on a transition to zero, so check getCount() first when nothing may be loading.

if (ExtjsUtils.QUERY.sourceLoading.getCount() === 0) onSourcesReady();
else ExtjsUtils.QUERY.sourceLoading.addZeroCallback(onSourcesReady);

storeGlobalQuerySettings

function(propertyName, value)helper# Internal — records the arguments a query passed to a side-effect API (setQueryGlobalProperties, addRemoteWMSServer, decorate) in globalQueryStoredSettings[propertyName], merging the keys of …

Written as ExtjsUtils.QUERY.storeGlobalQuerySettings

Internal — records the arguments a query passed to a side-effect API (setQueryGlobalProperties, addRemoteWMSServer, decorate) in globalQueryStoredSettings[propertyName], merging the keys of value into what was already stored under that name. Tenant code normally does not call it.

propertyName String
Name of the API whose arguments are stored.
value Object
Object whose keys are merged into the stored settings.
ExtjsUtils.QUERY.storeGlobalQuerySettings("decorate", { footer: { html: "..." } });

CONFIGURATION · query-wide settings (setOptions)

CONFIGURATION2 entries
ExtjsUtils.CONFIGURATION.setOptions({...}) && [ ... ] sets options of the whole query - keepOnLeave, defaultFromProj, backgroundSelector - until another query is applied. A layer's own settings are its properties.

DEFAULT_FROM_PROJ

String# Projection assumed for vector data (GeoJSON, CSV, JSON, shapefile) that carries no crs and whose layer sets no fromProj, when neither the query (CONFIGURATION.setOptions({ defaultFromProj })) …

Projection assumed for vector data (GeoJSON, CSV, JSON, shapefile) that carries no crs and whose layer sets no fromProj, when neither the query (CONFIGURATION.setOptions({ defaultFromProj })) nor the URL (?defaultFromProj=, options=defaultfromproj:CODE, options=nodefaultfromproj) says otherwise. It is the map projection (Web Mercator), so raw coordinates in metres load unchanged. Exposed as ExtjsUtils.CONFIGURATION.DEFAULT_FROM_PROJ. A file layer's GeoJSON is first guessed from its first coordinate (EPSG:4326 for lon/lat values, otherwise EPSG:3857), so for GeoJSON this default only applies when that guess fails.

setOptions

function(configurationOptions) : Booleanhelper# Defines query-level application configuration (iframe wheel behaviour, etc.).

Written as ExtjsUtils.CONFIGURATION.setOptions

Defines query-level application configuration (iframe wheel behaviour, etc.). Settings are stored with the query and cleared when another query loads.

configurationOptions Object
Query-level configuration options.
configurationOptions.keepOnLeave Boolean
When false, iframe mouseout blocks wheel until map click.
configurationOptions.defaultFromProj String|null|false
Default fromProj for CSV and JSON lists without crs (a file layer's GeoJSON first guesses EPSG:4326 or EPSG:3857 from its first coordinate; this default is used only when that guess fails). Precedence: this option, then the URL (?defaultFromProj=, options=defaultfromproj:CODE, options=nodefaultfromproj), then CONFIGURATION.DEFAULT_FROM_PROJ (EPSG:900913). null/false/"none" disables.
configurationOptions.backgroundSelector Boolean|Object
When true (or options object), show the floating background basemap picker after the query loads (platform OpenLayers.BackgroundSelector.sync).

Returns True for chaining with && QUERY_DESCRIPTION

ExtjsUtils.CONFIGURATION.setOptions({ keepOnLeave: false }) && QUERY_DESCRIPTION
ExtjsUtils.CONFIGURATION.setOptions({ defaultFromProj: 'EPSG:4674' }) && QUERY_DESCRIPTION
ExtjsUtils.CONFIGURATION.setOptions({ backgroundSelector: true }) && QUERY_DESCRIPTION

PROJECTION · CRS codes and upload choices

PROJECTION3 entries
ExtjsUtils.PROJECTION registers coordinate systems and normalises CRS codes, for the files a reader uploads. To say which CRS your own data is in, use fromProj on the file layer, or CONFIGURATION.setOptions({ defaultFromProj }).

normalizeCode

function(fullCodeName) : String|nullhelper# Normalizes a CRS name or code (a GeoJSON crs.properties.name, "EPSG:4674", "epsg4326", "urn:ogc:def:crs:OGC:1.3:CRS84", "SIRGAS 2000 / UTM zone 23S"...) to the canonical EPSG string OpenLayers uses.

Written as ExtjsUtils.PROJECTION.normalizeCode

Normalizes a CRS name or code (a GeoJSON crs.properties.name, "EPSG:4674", "epsg4326", "urn:ogc:def:crs:OGC:1.3:CRS84", "SIRGAS 2000 / UTM zone 23S"...) to the canonical EPSG string OpenLayers uses. Matching is case/whitespace-insensitive and covers the built-in definitions (WGS 84, SIRGAS 2000 and its UTM zones, Web Mercator — 900913 maps to EPSG:3857) plus the codes/patterns registered with setProjectionOptions. Returns null for an unknown CRS, so callers can fall back to a default projection.

fullCodeName String
CRS name or code as found in data files or user input.

Returns Canonical code such as "EPSG:4674", or null when it is not recognised.

ExtjsUtils.PROJECTION.normalizeCode("urn:ogc:def:crs:EPSG::4674"); // "EPSG:4674"
ExtjsUtils.PROJECTION.normalizeCode("EPSG:900913");                // "EPSG:3857"

resolveProjectionObject

function(projection, fallbackProjection) : OpenLayers.Projection|nullhelper# Resolves a projection given in any usual form — an EPSG string, an OpenLayers.Projection, or any object with getCode() — to a real OpenLayers.Projection.

Written as ExtjsUtils.PROJECTION.resolveProjectionObject

Resolves a projection given in any usual form — an EPSG string, an OpenLayers.Projection, or any object with getCode() — to a real OpenLayers.Projection. The code is normalised with normalizeCode first; when the input carries no usable code the fallbackProjection (typically the map projection) is returned instead of constructing new OpenLayers.Projection(<non-string>), which would throw "srsCode.indexOf is not a function" once Proj4js is loaded. Use it before geometry.transform(...) when the source projection comes from user data and may be missing.

projection String|OpenLayers.Projection|Object
Projection to resolve: EPSG code string, projection instance, or object exposing getCode().
fallbackProjection OpenLayers.Projection
Projection returned when projection has no usable code (e.g. the map projection).

Returns The resolved projection, the fallback, or null when neither is available.

var mapProj = ExtjsUtils.JS.getMap().getProjectionObject();
var fromProj = ExtjsUtils.PROJECTION.resolveProjectionObject(geojson.crs && geojson.crs.properties.name, mapProj);
feature.geometry.transform(fromProj, mapProj);

setProjectionOptions

function(projectionOptions, config) : Booleanhelper# Register projection options for the current query.

Written as ExtjsUtils.PROJECTION.setProjectionOptions

Register projection options for the current query. Each entry: { code, label?, proj4?, codes?, patterns? } — label defaults to code. The same list drives bare-.shp upload choices and custom CRS registration. Also lazy-loads theme proj4 definitions (SIRGAS) when entries are set.

projectionOptions Array|Object
Entries, or { projectionOptions, includeDefaults? }
config Object
When first arg is an array: { includeDefaults?: Boolean } includeDefaults: true merges IDE defaults (EPSG:4326, EPSG:4674, EPSG:3857) before tenant entries.

Returns True for chaining with && QUERY_DESCRIPTION { code, label?, proj4?, wkt?, codes?, patterns? } proj4 and wkt are alternative CRS definitions (bundled Proj4js uses proj4 internally).

// Full explicit list (no IDE defaults added):
ExtjsUtils.PROJECTION.setProjectionOptions([
  { code: "EPSG:4326", label: "WGS 84" },
  { code: "EPSG:4674", label: "SIRGAS 2000" },
  { code: "EPSG:5534", label: "SAD69 / UTM 22S",
    proj4: "+proj=utm +zone=22 +south +ellps=astral +units=m +no_defs",
    codes: ["5534"], patterns: ["sad69"] }
]) && QUERY_DESCRIPTION
// WKT instead of proj4:
ExtjsUtils.PROJECTION.setProjectionOptions([
  { code: "EPSG:5534", label: "SAD69 / UTM 22S", wkt: "PROJCS[...]", codes: ["5534"] }
]) && QUERY_DESCRIPTION
// Only add a custom CRS; upload list = IDE defaults + EPSG:5534:
ExtjsUtils.PROJECTION.setProjectionOptions([
  { code: "EPSG:5534", label: "SAD69 / UTM 22S", proj4: "...", codes: ["5534"] }
], { includeDefaults: true }) && QUERY_DESCRIPTION

Server definition (addRemoteWMSServer)

SourceConfig3 entries
Keys of a server object given to ExtjsUtils.QUERY.addRemoteWMSServer. Its url, cors, storage and updateWMS are described with QUERY.addRemoteWMSServer.

onError

function# Defines callback function to be called when the store failes to be loaded.

Defines callback function to be called when the store failes to be loaded.

onLoad

function# Defines callback function to be called when the store is successfully loaded.

Defines callback function to be called when the store is successfully loaded.

ptype

String= "gxp_customwmscsource"# The source plugin type of a layer source: the ptype key of a source definition given to ExtjsUtils.QUERY.addRemoteWMSServer, or of a sources entry of a saved map.

The source plugin type of a layer source: the ptype key of a source definition given to ExtjsUtils.QUERY.addRemoteWMSServer, or of a sources entry of a saved map. It defaults to "gxp_customwmscsource" (the platform's tiled WMS source, used whenever url is given without a ptype); the other registered types are the gxp plugins ("gxp_googlesource", "gxp_osmsource", "gxp_arcrestsource", ...). The legacy aliases gx_wmssource, gx_olsource, gx_googlesource and gx_osmsource are still registered here so maps saved before version 2.3.2 (when those plugins were renamed) keep loading; do not use them in new queries.

ExtjsUtils.QUERY.addRemoteWMSServer({
    google: { ptype: "gxp_googlesource" },
    ibge: { url: "https://geoservicos.ibge.gov.br/geoserver/CCAR/wms?" } // ptype defaults to "gxp_customwmscsource"
}) && [
    { name: "HYBRID", source: "google", group: "background", visibility: true }
]

Map links and embedding

A saved query opens from a link: https://maps.csr.ufmg.br/calculator/?queryid=123. Save a query in the editor to get its number; saved queries are public, and only their author can update them.
The parameters of the link - language, toolbar buttons (tools=), page options (options=) - change how that link opens the map; the saved query stays the same. MappiaIO is for a page that embeds the map and talks to it.
Example
// Example link for sharing a map just with its visualization
https://maps.csr.ufmg.br/calculator/?queryid=473

// Example link for sharing a map with its Query visible
https://maps.csr.ufmg.br/editor/?queryid=473

Link parameters (?name=value)

URLProperties8 entries
Parameters of the link that opens a saved map: ?queryid=123&lang=eng&tools=...&options=... tools and options take the lists below.

definitions

String= 'live'link parameter# Loads the map's layer catalog (the WMS GetCapabilities the layers are built from) from a capabilities cache saved in this browser, instead of from the server.

Written as ?definitions=

Loads the map's layer catalog (the WMS GetCapabilities the layers are built from) from a capabilities cache saved in this browser, instead of from the server. definitions=live, like no parameter at all, loads the default catalog: the live one from the server (or, with options=capabilities, the query's own). Any other value is the name of a cache saved with ExtjsUtils.OFFLINE.downloadDefinitions({name}) (ExtjsUtils.OFFLINE.listDefinitions lists them); the service worker answers the catalog request from it, so the map also starts with the map server unreachable. Only the page opened with it is affected: other Mappia pages keep the live catalog. It needs the page controlled by the service worker: without one (the first visit, a hard reload) the page warns and loads the live catalog. A name with no saved cache also falls back to the live catalog. An empty value (definitions=) starts with an empty catalog, without any catalog request: the map does not wait for the server, and only layers that need no catalog record show. No service worker is needed for it. From code, ExtjsUtils.OFFLINE.useDefinitions(name) switches a running map.

// the map's catalog from the cache saved as "fazenda-42"
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&definitions=fazenda-42
// the live catalog, said explicitly
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&definitions=live
// starts with an empty catalog, at once
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&definitions=

extent

Array.<Number>= [-443.628,-16.847,-407.373,3.294]link parameter# Defines in which part of the world the map will start on load.

Written as ?extent=

Defines in which part of the world the map will start on load. The extents must be in EPSG:4326 (coordinates in lat,long). Also, the values need to be in the order: minX, minY, maxX, maxY, separated by comma with no spaces between them.

// Example of query in visualization mode
// This extents start the map center at Japan
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&extent=122,24,153,45
// Example of query in edit mode
// This extents will display the whole world
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&extent=-180.0000,-90.0000,180.0000,90.0000

lang

String= 'pt'link parameter# Define in which language the Mappia default messages and texts will be displayed.

Written as ?lang=

Define in which language the Mappia default messages and texts will be displayed. Actually, Mappia supports the following languages:

  • Portuguese (Brazil): pt
  • English: eng
// Example of query in visualization mode
// The default text will be displayed in portuguese
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&lang=pt
// Example of query in edit mode
// The default text will be displayed in english
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&lang=eng

map

string= string.emptylink parameter# Allow the user to define which 'local' maps to load on the URL.

Written as ?map=

Allow the user to define which 'local' maps to load on the URL. You need to pass the map name like in the ones passed at the 'name' property of a Layer with 'source' set as 'local'. This property only applies for visualization mode.

// Example of loading a map without any 'queryid' in visualization mode
https://maps.csr.ufmg.br/calculator/?map=CSR:geologia
// Example of loading two map without any 'queryid' in visualization mode
// and starting with them visible
https://maps.csr.ufmg.br/calculator/?map=CSR:geologia,CSR:estados&visiblelayers=2
// Example of loading a map without any 'queryid'
https://maps.csr.ufmg.br/?map=CSR:geologia

options

string= string.emptylink parameter# Allows the user to set some configurations when the map loads, like displaying a scale, how many Layers will start visible, etc…

Written as ?options=

Allows the user to set some configurations when the map loads, like displaying a scale, how many Layers will start visible, etc…

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&options=<options_list>
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&options=<options_list>

See also To learn more about the Options available and how to set them up, check their documentation at: URL Options Section.

queryid

Number= nulllink parameter# Define which Query will be loaded when the map loads.

Written as ?queryid=

Define which Query will be loaded when the map loads. Every saved Query at Mappia receives a Query id number. By adding that number to the 'queryid', you can select the query loaded by the link. You can find all Queries created at Mappia in the 'Query' button at the top left in the editor window. By hovering the button and selecting the 'Carregar Queries' option, a popup will show up with all the Queries created at Mappia. The older Queries are listed first.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=473
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=473

tools

string= 'All tools available'link parameter# Define which tools will be available for the user to interact with the map.

Written as ?tools=

Define which tools will be available for the user to interact with the map. Every tool listed here will be available for the user. If left empty, Mappia will display all tools for the user.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&tools=<tools_list>
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&tools=<tools_list>

See also To learn more about the Tools available and how to set them up, check their documentation at: URL Tools Section.

visiblelayers

Number|String= customlink parameter# How many layers start visible.

Written as ?visiblelayers=

How many layers start visible. When the parameter is present it overrides the 'visibility' of every layer: all layers start hidden, then this many are turned on, counted in query order.

  • A positive number N: the first N layers of the query start visible.

  • A negative number -N: the last N layers start visible.

  • 0: no layer starts visible.

  • custom: the same as leaving the parameter out: each layer's own 'visibility' decides.

Leaving it out (the default) lets each layer's 'visibility' decide; options=onlyfirstvisible is the same as visiblelayers=1. Any other text, null included, hides every layer.

// Example of query in visualization mode
// If the Layer has 3 Layers in the order: Layer1, Layer2 and Layer3,
// By setting 'visibelayers=2', the FIRST two Layers will start visible
// That is, the Layer1 and Layer2 will start visible
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&visiblelayers=2
// Example of query in edit mode
// If the Layer has 3 Layers in the order: Layer1, Layer2 and Layer3
// By setting 'visiblelayers=-2', the LAST two Layers will start visible
// That is, the Layer3 and Layer2 will start visible
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&visiblelayers=-2
// Example of query in edit mode
// By setting 'visiblelayers=0', no Layer will start visible when the map loads
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&visiblelayers=0
// Example of query in visualization mode
// By setting 'visiblelayers=custom', the Layers will start visible based on
// its 'visibility' property. Only if 'visibility: true', the Layer will start visible
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&visiblelayers=custom

Toolbar buttons (tools=)

URLTools9 entries
Values of tools=, separated by commas: the optional buttons of the map toolbar. Listing them replaces the default set; zoom and navigation are always there.
Example
// Example with all possible tools
https://maps.csr.ufmg.br/calculator/?queryid=474&tools=legend,measure,hovershowlegend,getfeature,customzoom,zoomextent,helpintro,metadata

customzoom

Boolean= truelink parameter# If listed, will display the "Zoom de seleção" button.

Written as tools=customzoom

If listed, will display the "Zoom de seleção" button. This button allows the user to drag the mouse to select a region to zoom in on the map.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&tools=customzoom
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&tools=customzoom

getfeature

Boolean= truelink parameter# If listed, will display the "Indentifica atributos da feição" button.

Written as tools=getfeature

If listed, will display the "Indentifica atributos da feição" button. This button, when active, allows the user to click at a specific point in the map and get the more informations of the point that was clicked.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&tools=getfeature
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&tools=getfeature

helpintro

Boolean= truelink parameter# Define if should display the Help Tutorial button.

Written as tools=helpintro

Define if should display the Help Tutorial button. This button opens a simple tutorial on how to use the Mappia features.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&tools=helpintro
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&tools=helpintro

hovershowlegend

Boolean= truelink parameter# If listed, will display the "Exibir da legenda da feição sob o mouse" button.

Written as tools=hovershowlegend

If listed, will display the "Exibir da legenda da feição sob o mouse" button. This button, when active, allows the user to see the map Legend value of where the mouse is hovering.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&tools=hovershowlegend
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&tools=hovershowlegend

legend

Boolean= truelink parameter# If listed, will display the Legend popup button.

Written as tools=legend

If listed, will display the Legend popup button. This button shows a popup with the Legend of the active layers.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&tools=legend
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&tools=legend

measure

Boolean= truelink parameter# If listed, will display the Ruler button.

Written as tools=measure

If listed, will display the Ruler button. This button allows the user to do measurements of distances in the map.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&tools=measure
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&tools=measure

metadata

Boolean= truelink parameter# If listed, will display the metadata button.

Written as tools=metadata

If listed, will display the metadata button. This button opens the description of the visible maps as published - source, date, scale and the other metadata recorded with each map.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&tools=metadata

none

Boolean= falselink parameter# If passed as the only value for the ‘tools’ property, no tool will be available for the user to interact with the map.

Written as tools=none

If passed as the only value for the ‘tools’ property, no tool will be available for the user to interact with the map.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&tools=none
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&tools=none

zoomextent

Boolean= truelink parameter# If listed, will display the "Zoom nos layer" button.

Written as tools=zoomextent

If listed, will display the "Zoom nos layer" button. The button that centers the screen at the actual visible layer.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&tools=zoomextent
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&tools=zoomextent

Page options (options=)

URLOptions10 entries
Values of options=, separated by commas, that change how the page opens the map. Some also exist as a layer key or a query setting; the guide Where to find it says which one wins.
Example
// Example with all possible options
https://maps.csr.ufmg.br/calculator/?queryid=474&options=capabilities,grid,scale,disabledownload,hidemetadata,overview,onlyfirstvisible

capabilities

Boolean= falselink parameter# If listed, will load only the maps defined in the 'name' property of the Layers.

Written as options=capabilities

If listed, will load only the maps defined in the 'name' property of the Layers. This can speed up the loading time of the Query.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&options=capabilities
// Example of query in editor mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&options=capabilities

disabledownload

Boolean= falselink parameter# If listed, will hide the “download” button of the Legend Window.

Written as options=disabledownload

If listed, will hide the “download” button of the Legend Window. The “download” button is the same one as the “paramButtonConfig” “download” type.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&options=disabledownload
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&options=disabledownload

grid

Boolean= falselink parameter# If listed, will display the parallel and meridian lines grid.

Written as options=grid

If listed, will display the parallel and meridian lines grid.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&options=grid
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&options=grid

hidemetadata

Boolean= falselink parameter# If listed, will hide the “metadata” button of the Legend Window.

Written as options=hidemetadata

If listed, will hide the “metadata” button of the Legend Window. The “metadata” button is the same one as the “paramButtonConfig” “metadata” type.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&options=hidemetadata
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&options=hidemetadata

hidestylechooser

Boolean= falselink parameter# If listed, hides the style chooser of every layer in the layer panel, so the reader sees each map only in the style the query selected.

Written as options=hidestylechooser

If listed, hides the style chooser of every layer in the layer panel, so the reader sees each map only in the style the query selected. The per-layer equivalent is the layer property hideStyleChooser.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&options=hidestylechooser

keeponleave

Boolean= truelink parameter# Controls mouse wheel zoom when the map is embedded in an iframe.

Written as options=keeponleave

Controls mouse wheel zoom when the map is embedded in an iframe.

Only applies when the page runs inside an iframe. When false, leaving the document (mouseout with destination HTML) blocks wheel zoom until the user clicks the map; wheel events over the viewport then show Lang.navigationWheelDisabled.

// Query-level setting (preferred for shared maps)
ExtjsUtils.CONFIGURATION.setOptions({ keepOnLeave: false }) && QUERY_DESCRIPTION
// Plugin config (tools array in calculator / composer)
{ ptype: "gxp_usabilityhelper", keepOnLeave: false }
// URL option (sets keepOnLeave via advToolsOptions; same as default true)
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&options=keeponleave

onlyfirstvisible

Boolean= falselink parameter# If listed, only the first Layer defined at the Query will be visible when the map loads.

Written as options=onlyfirstvisible

If listed, only the first Layer defined at the Query will be visible when the map loads.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&options=onlyfirstvisible
// Example of query in visualization mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&options=onlyfirstvisible

overview

Boolean= falselink parameter# If listed, will display a zoom out interactable window at the bottom right when the user zooms in the map.

Written as options=overview

If listed, will display a zoom out interactable window at the bottom right when the user zooms in the map.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&options=overview
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&options=overview

scale

Boolean= falselink parameter# If listed, will display the scale of the map at the bottom left.

Written as options=scale

If listed, will display the scale of the map at the bottom left.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&options=scale
// Example of query in edit mode
https://maps.csr.ufmg.br/editor/?queryid=<query_id>&options=scale

startopened

Boolean= falselink parameter# If listed, the layer panel (the Legend Window with the query's groups and layers) starts open when the map loads, instead of collapsed behind its button.

Written as options=startopened

If listed, the layer panel (the Legend Window with the query's groups and layers) starts open when the map loads, instead of collapsed behind its button. Use it when the layer list is part of what the page is for; leave it out to give the map the whole screen.

// Example of query in visualization mode
https://maps.csr.ufmg.br/calculator/?queryid=<query_id>&options=startopened

MappiaIO · your page and the map

MappiaIO10 entries
Connects your page to an embedded Mappia map: apply queries, send messages, receive the map's.
Connects your page to a Mappia map embedded in it, in both directions. Your page loads https://maps.csr.ufmg.br/mappia_io.js, connects with MappiaIO(iframe, true), loads queries with applyQuery, sends objects with send and receives with addOnMessageCallback. Inside the map, the query receives with ExtjsUtils.QUERY.setMappiaIoCallback and answers with ExtjsUtils.QUERY.postMessage. Your page's buttons, lists and forms can drive the map (filter, zoom, highlight, edit a record), and the map tells the page what the user clicked, hovered or drew.

MappiaIO

function(communicationTarget, keepAfterReady) : Object# Connects your page to a Mappia map in an iframe (or in a window you opened) and returns the connection: applyQuery loads a query into the map, send delivers an object to the query running there, …

Connects your page to a Mappia map in an iframe (or in a window you opened) and returns the connection: applyQuery loads a query into the map, send delivers an object to the query running there, addOnMessageCallback receives what the query sends back with ExtjsUtils.QUERY.postMessage. Load the library from the map server (<script src="https://maps.csr.ufmg.br/mappia_io.js">).

On creation it greets the map (mappia__checkDOM) until the map answers it is listening (mappia__confirmDOM); everything sent before that is queued and delivered in order, so applyQuery and send may be called right away. Messages travel through window.postMessage wrapped as {mappia_iframe: <JSON text>}, so the page and the map may be on different sites.

Do not open the map with noopener or noreferrer (on the iframe or in window.open): they cut the window link the messages travel on. window.open(url, "_blank", "width=1280,height=860") works; window.open(url, "_blank", "noopener,noreferrer") does not.

communicationTarget String|HTMLIFrameElement|Window
The map to talk to: the id of its iframe, the iframe element itself, or the window returned by window.open.
keepAfterReady Boolean
true keeps listening after the handshake - needed by any page that receives messages from the map or applies more than one query. With false the connection stops listening once the map has answered.

Returns The connection, whose methods return it again so calls can be chained.

<iframe id="mappia" src="https://maps.csr.ufmg.br/calculator/?lang=eng&options=scale"></iframe>
<script src="https://maps.csr.ufmg.br/mappia_io.js"></script>
<script>
  var mappia = MappiaIO("mappia", true);
  mappia.addOnMessageCallback(function (msg) { console.log("from the map:", msg); });
  mappia.applyQuery('[{ name: "CSR:estados", title: "States", visibility: true }]');
  mappia.send({ operation: "hello", message: "from the page" });
</script>

addOnMessageCallback

function(callback) : Object# Registers a function that receives every message from the map.

Registers a function that receives every message from the map. What the query posts with ExtjsUtils.QUERY.postMessage(object) arrives as that object; the platform's own notices arrive as strings starting with mappia__ - mappia__queryApplied once a query sent with applyQuery is in place, mappia__confirmQueryListening when a query registers its callback. Several functions may be registered; each gets every message, about 150 ms after it was posted. Needs a connection created with keepAfterReady true.

callback function
function (message), called for each message.

Returns The connection.

mappia.addOnMessageCallback(function (msg) {
  if (msg === "mappia__queryApplied") return showStatus("Map ready");
  if (msg && msg.operation === "city_clicked") showDetails(msg.message);
});

addOnRemoveCallback

function(callback) : Object# Registers a function run when remove stops the connection, to tidy up whatever the page attached to it.

Registers a function run when remove stops the connection, to tidy up whatever the page attached to it.

callback function
Called with no arguments.

Returns The connection.

addReadyCallback

function(callback) : Object# Runs callback once the map has answered the handshake - at once when it already has.

Runs callback once the map has answered the handshake - at once when it already has. The place to start a conversation that needs the map listening: apply the first query there, then send the page's starting state (filters, the record being edited...).

callback function
Called with no arguments.

Returns The connection.

mappia.addReadyCallback(function () {
  fetch("/my-map-query.js").then(function (r) { return r.text(); }).then(function (text) {
    mappia.applyQuery(text);
    mappia.send({ operation: "setFilters", message: currentFilters });
  });
});

applyQuery

function(queryContent) : Object# Loads a query into the map - the same text you would type in the Mappia editor, of any length and not saved on the server - replacing the layers the map shows.

Loads a query into the map - the same text you would type in the Mappia editor, of any length and not saved on the server - replacing the layers the map shows. The map confirms with the message mappia__queryApplied once the new layers are in place. A query that did not run (a syntax or runtime error, or a value that is not a list of layers) is confirmed too, but the message {action: "mappia__queryError", error: {name, message, line, column}} comes first. One connection can apply query after query; called before the handshake, it waits in the queue.

queryContent String
The query text.

Returns The connection (not a promise: listen for mappia__queryApplied).

mappia.addOnMessageCallback(function (msg) {
  if (msg && msg.action === "mappia__queryError") console.warn("The query did not run:", msg.error.message, "line", msg.error.line);
  else if (msg === "mappia__queryApplied") console.log("applied");
});
mappia.applyQuery('[{ name: "CSR:altimetria", title: "Elevation", visibility: true }]');

applyQueryFromUrl

function(queryUrl) : Promise.<Object># Fetches the query text at queryUrl and applies it as applyQuery does - for a query kept as a file in your own site or repository.

Fetches the query text at queryUrl and applies it as applyQuery does - for a query kept as a file in your own site or repository. The URL is read with fetch, so one on another site must allow cross-origin reads.

queryUrl String
Address of a file holding query text, such as [{ name: "CSR:estados" }].

Returns Resolves with the connection once the text was fetched and sent - not when the map applied it: wait for the mappia__queryApplied message for that.

mappia.applyQueryFromUrl("/queries/my-map.js");

isDomLoaded

function() : Boolean# Whether the map has answered the handshake.

Whether the map has answered the handshake. Until it has, send and applyQuery queue their messages and deliver them, in order, as soon as it answers.

Returns true once the map is listening.

postMessage

function(jsStr)helper# Sends a message to the Mappia/iframe, allowing communication between the Mappia/iframe and the parent window.

Written as ExtjsUtils.QUERY.postMessage

Sends a message to the Mappia/iframe, allowing communication between the Mappia/iframe and the parent window. (Compatible with MappiaIO library) The 'QUERY.setMappiaIoCallback' is responsible to interpret the sent message.

jsStr Object|String
Object to be sent from inside Mappia/iframe to parent window. Objects are JSON-stringified; the parent receives { mappia_iframe: jsStr }.
ExtjsUtils.QUERY.postMessage({a:1,b:2})

remove

function() : Object# Stops listening to the map and runs the functions registered with addOnRemoveCallback.

Stops listening to the map and runs the functions registered with addOnRemoveCallback. A connection created with keepAfterReady false calls it by itself right after the handshake; call it yourself when the page drops the map (a closed panel, a route change) so an old connection does not keep receiving messages.

Returns The connection.

send

function(message, forceSend) : Object# Delivers message to the query running in the map, which receives it in the function it registered with ExtjsUtils.QUERY.setMappiaIoCallback.

Delivers message to the query running in the map, which receives it in the function it registered with ExtjsUtils.QUERY.setMappiaIoCallback. The shape is yours to choose; by convention an object naming an operation and carrying a message, plus a requestId when the page waits for an answer. Objects travel as JSON (functions and dates do not survive); a message carrying a File or Blob ({operation: "import", file: file}) is sent as the object itself, so the file reaches the query intact. Never send strings starting with mappia__: the platform reserves them.

message Object|String
What to deliver to the query.
forceSend Boolean
Sends at once even before the handshake, skipping the queue. Pages normally leave it out.

Returns The connection.

mappia.send({ operation: "show_city", message: { name: "Belo Horizonte" } });
mappia.send({ operation: "list_cities", requestId: "r1" }); // the query answers with the same requestId

QUERY.queryState · apply-message queue (internal)

QueryState8 entries
Synchronisation between the parent page (mappia_io.js) and the query being applied: while a query is loading, incoming apply messages are queued and flushed when the wait counter reaches zero. Internal to the platform; listed so embed authors understand the sequence.
Usage: ExtjsUtils.QUERY.queryState

cancelWaiting

function(name)# Internal — releases the operation started with startWaiting(name) when it failed (e.g. the query did not parse).

Internal — releases the operation started with startWaiting(name) when it failed (e.g. the query did not parse). It currently behaves exactly like endWaiting(name): the counter is decremented and, at zero, the queued messages are still processed — they are not discarded. Tenant code normally does not call it.

name String
Identifier used in the matching startWaiting call.
ExtjsUtils.QUERY.queryState.cancelWaiting("myAsyncSetup");

endWaiting

function(name)# Internal — marks the end of the operation started with startWaiting(name).

Internal — marks the end of the operation started with startWaiting(name). Decrements the shared counter; when it reaches zero every queued message is processed in order (RUN_QUERY_APPLY messages apply their query, the others go to the MappiaIO callback). A name that is not active is rejected with a console error. Tenant code normally does not call it.

name String
Identifier used in the matching startWaiting call.
ExtjsUtils.QUERY.queryState.endWaiting("myAsyncSetup");

handleMessage

function(jsMsg)# Internal — entry point for a RUN_QUERY_APPLY message ({action, queryContent}).

Internal — entry point for a RUN_QUERY_APPLY message ({action, queryContent}). While waiting the message is queued; otherwise it is wrapped in a startWaiting/endWaiting pair so that it is applied through the queue right away. Tenant code normally does not call it.

jsMsg Object
Message object with action and queryContent.

initMessageHandler

function()# Internal — installs the window "message" listener that receives the parent page's postMessage calls and immediately posts CONFIRM_DOM_LOADED back.

Internal — installs the window "message" listener that receives the parent page's postMessage calls and immediately posts CONFIRM_DOM_LOADED back. Protocol messages (CHECK_DOM, CHECK_QUERY, RUN_QUERY_APPLY) are answered by the platform; any other message is queued while isWaiting() is true, otherwise it is delivered to the callback registered with QUERY.setMappiaIoCallback. Called once by the editor/calculator pages when they load; tenant code does not call it.

isWaiting

function() : Boolean# Internal — tells whether at least one operation registered with startWaiting is still running, i.e. whether incoming messages are being queued.

Internal — tells whether at least one operation registered with startWaiting is still running, i.e. whether incoming messages are being queued. Tenant code normally does not call it.

Returns True while the shared counter is greater than zero.

if (!ExtjsUtils.QUERY.queryState.isWaiting()) handleNow();

queueMessage

function(message)# Internal — appends a message to the queue that is flushed when the counter reaches zero.

Internal — appends a message to the queue that is flushed when the counter reaches zero. Meant to be called only while isWaiting() is true; a queued RUN_QUERY_APPLY message applies its query, any other message is delivered to the MappiaIO callback. Tenant code normally does not call it.

message *
Message payload as received from the parent window.

setQueryApplyHandler

function(handler)# Internal — replaces the default way a RUN_QUERY_APPLY message is applied (QUERY.loadCurrentQuery) with a custom handler; the editor uses it to load the received query text into its code panel …

Internal — replaces the default way a RUN_QUERY_APPLY message is applied (QUERY.loadCurrentQuery) with a custom handler; the editor uses it to load the received query text into its code panel instead of straight into the map. The handler runs once the map is loaded (or is deferred to AFTER_APP_LOADING) and receives (queryContent, notifyQueryApplied); it must call notifyQueryApplied() when done so the parent window gets CONFIRM_QUERY_APPLIED. Tenant code normally does not call it.

handler function
Function (queryContent, notifyQueryApplied) that applies the query.
ExtjsUtils.QUERY.queryState.setQueryApplyHandler(function(queryContent, notifyQueryApplied) {
  ExtjsUtils.QUERY.loadCurrentQuery(ExtjsUtils.JS.getApp(), queryContent, notifyQueryApplied);
});

startWaiting

function(name)# Internal — marks the start of an operation (a query load, the map loading) during which incoming messages must be queued instead of handled.

Internal — marks the start of an operation (a query load, the map loading) during which incoming messages must be queued instead of handled. Increments the shared counter under name; a name that is already active is rejected with a console error. Pair it with endWaiting(name) (success) or cancelWaiting(name) (failure). Tenant code normally does not call it.

name String
Identifier of the operation, e.g. "loadCurrentQuery".
ExtjsUtils.QUERY.queryState.startWaiting("myAsyncSetup");

ExtjsUtils helpers (A-Z)

Functions your own code calls - in a button handler, beforeCalc, runNow - as ExtjsUtils.NAMESPACE.member, sorted by namespace. Most used (tutorial step 8): ALERTIFY, LAYER, JS, ZOOM, REQUEST, GEOJSON, CSS.
QUERY, CONFIGURATION and PROJECTION are under Query setup; OFFLINE under Offline maps.

ExtjsUtils · top-level helpers

ExtjsUtils30 entries
Helpers defined directly on the ExtjsUtils object (not inside a namespace).
Usage: ExtjsUtils.<member>

ASSERTION_ENABLED

Boolean# When true, the console.assert checks spread through the platform code are evaluated (see dealWithAssertions); when false they are turned into console warnings.

Written as ExtjsUtils.ASSERTION_ENABLED

When true, the console.assert checks spread through the platform code are evaluated (see dealWithAssertions); when false they are turned into console warnings. Meant to be true only in development builds.

CancelEvent

function(evt)helper# Cancels the default browser action of a DOM event (preventDefault, or returnValue = false on old IE) — for instance to suppress the context menu or a link navigation.

Written as ExtjsUtils.CancelEvent

Cancels the default browser action of a DOM event (preventDefault, or returnValue = false on old IE) — for instance to suppress the context menu or a link navigation.

evt Event
The DOM event to cancel.
ExtjsUtils.addDomListener(document.getElementById('map'), 'contextmenu', ExtjsUtils.CancelEvent);

DomObserver

functionhelper# Ext plugin that binds plain DOM events (the ones the Ext component itself does not expose, such as contextmenu) to the component's element as soon as it renders.

Written as ExtjsUtils.DomObserver

Ext plugin that binds plain DOM events (the ones the Ext component itself does not expose, such as contextmenu) to the component's element as soon as it renders. Create it with an object mapping DOM event names to handlers function(evt, component) — or with { listeners: {...} } — and put the instance in the component's plugins array.

{
  xtype: 'gxp_fieldset',
  plugins: [
    new ExtjsUtils.DomObserver({
      contextmenu: function(evt, comp) {
        ExtjsUtils.CancelEvent(evt);
      }
    })
  ]
}

NodeMouseoverPlugin

functionhelper# Ext plugin for an Ext.tree.TreePanel that makes the tree fire mouseover and mouseout events for its nodes ((node, evt)), which Ext 3.4 does not provide out of the box.

Written as ExtjsUtils.NodeMouseoverPlugin

Ext plugin for an Ext.tree.TreePanel that makes the tree fire mouseover and mouseout events for its nodes ((node, evt)), which Ext 3.4 does not provide out of the box. Add an instance to the tree's plugins and listen to those events on the tree.

var tree = new Ext.tree.TreePanel({
  plugins: [new ExtjsUtils.NodeMouseoverPlugin()],
  listeners: {
    mouseover: function(node, evt) { console.log('over', node.text); },
    mouseout: function(node, evt) { console.log('out', node.text); }
  }
});

SliderZIndexFixer

functionhelper# Ext plugin that works around a GeoExt.LayerOpacitySlider bug: after each drag the slider thumb keeps a raised z-index, so the plugin resets the thumb's z-index on dragend to the value given to …

Written as ExtjsUtils.SliderZIndexFixer

Ext plugin that works around a GeoExt.LayerOpacitySlider bug: after each drag the slider thumb keeps a raised z-index, so the plugin resets the thumb's z-index on dragend to the value given to the constructor (default 0).

new GeoExt.LayerOpacitySlider({
  layer: layer,
  plugins: new ExtjsUtils.SliderZIndexFixer(0)
});

addDomListener

function(domObj, evtName, fn, useCapture)helper# Adds a DOM event listener, working across old and new browsers (addEventListener or attachEvent).

Written as ExtjsUtils.addDomListener

Adds a DOM event listener, working across old and new browsers (addEventListener or attachEvent). The usual query use is addDomListener(window, 'mousemove', fn) to track the element under the mouse for a floating popup. Remove it later with removeDomListener passing the very same function.

domObj EventTarget
DOM object to listen on (an element, document or window).
evtName String
DOM event name, without the on prefix (e.g. 'mousemove', 'click').
fn function
Event callback; receives the DOM event.
useCapture Boolean
Register in the capture phase. Only honoured when domObj is window, document or document.body; other targets always use the bubbling phase.
ExtjsUtils.addDomListener(window, 'mousemove', function(evt) {
  window.lastHoveredElement = evt.target;
});

addListenerToConfig

function(config, eventName, callback, scope) : Objecthelper# Adds a listener to an Ext config object's listeners[eventName] without losing a listener that is already there: when one exists, the new callback runs first and then the previous one, both …

Written as ExtjsUtils.addListenerToConfig

Adds a listener to an Ext config object's listeners[eventName] without losing a listener that is already there: when one exists, the new callback runs first and then the previous one, both receiving the event arguments. Creates the listeners object when missing.

config Object
Ext component config object to modify.
eventName String
Name of the Ext event (e.g. 'afterrender', 'click').
callback function
Listener to add.
scope Object
this for callback; defaults to the event's own scope.

Returns The same config object, modified.

var cfg = { xtype: 'button', text: 'Go', listeners: { click: function() { console.log('first'); } } };
ExtjsUtils.addListenerToConfig(cfg, 'click', function() { console.log('added'); });
// clicking now logs "added" then "first"

bboxTransform

function(layerBBox, fromProjection, toProjection) : OpenLayers.Boundshelper# Reprojects a bounding box from one projection to another and returns it as a new OpenLayers.Bounds (the input is never modified).

Written as ExtjsUtils.bboxTransform

Reprojects a bounding box from one projection to another and returns it as a new OpenLayers.Bounds (the input is never modified). The source projection defaults to lon/lat ("EPSG:4326"), which is what WMS capabilities bounding boxes use.

layerBBox OpenLayers.Bounds|Array.<Number>
The bounding box to reproject: an OpenLayers.Bounds or a [left, bottom, right, top] array.
fromProjection String|OpenLayers.Projection
Projection the bounding box is currently in.
toProjection String|OpenLayers.Projection
Projection to convert to (e.g. the map projection, app.mapPanel.map.getProjection()).

Returns A new bounds object in toProjection.

// lon/lat box of Minas Gerais into the map projection, then zoom to it
var bounds = ExtjsUtils.bboxTransform([-51.1, -22.9, -39.9, -14.2], "EPSG:4326", app.mapPanel.map.getProjection());
app.mapPanel.map.zoomToExtent(bounds);

dealWithAssertions

function()helper# Wraps console.assert so the assertions left in the platform code follow ASSERTION_ENABLED (read once, when this runs): when enabled they go through the native console.assert; when disabled …

Written as ExtjsUtils.dealWithAssertions

Wraps console.assert so the assertions left in the platform code follow ASSERTION_ENABLED (read once, when this runs): when enabled they go through the native console.assert; when disabled every console.assert call is turned into a console.warn of its arguments instead. Called once when this file is initialised; a query has no reason to call it.

ExtjsUtils.ASSERTION_ENABLED = false;
ExtjsUtils.dealWithAssertions(); // from now on console.assert only warns

deepCompare

function(objA, objB, customCompare) : Booleanhelper# Deep equality of two values: every property is compared recursively (arrays, nested objects, dates, regular expressions and functions — the latter by their source text — with cycle protection).

Written as ExtjsUtils.deepCompare

Deep equality of two values: every property is compared recursively (arrays, nested objects, dates, regular expressions and functions — the latter by their source text — with cycle protection). An optional hook lets you decide the comparison of any pair of values yourself. Useful to detect whether a layer definition or an inputs object actually changed.

objA *
First value to compare.
objB *
Second value to compare.
customCompare function
Hook function(x, y) called for every pair of values (the roots first, then each nested property) before the default comparison. Return true (equal) or false (different) to decide, or undefined to let the default comparison run.

Returns true when the two values are deeply equal, false otherwise.

ExtjsUtils.deepCompare({ a: 1, b: [1, 2] }, { a: 1, b: [1, 2] }); // true
// Treat numbers closer than 0.001 as equal
ExtjsUtils.deepCompare(oldStats, newStats, function(x, y) {
  if (typeof x === 'number' && typeof y === 'number') return Math.abs(x - y) < 0.001;
});

default_background_map

Object# Layer definition of the platform's default basemap (OpenStreetMap Mapnik, from the osm source), used when a query declares no layer with group: "background": the platform then inserts this …

Written as ExtjsUtils.default_background_map

Layer definition of the platform's default basemap (OpenStreetMap Mapnik, from the osm source), used when a query declares no layer with group: "background": the platform then inserts this definition at the bottom of the query's layer list while the query is loaded. To use another basemap, declare your own group: "background" layer in the query instead of changing this object — production queries that mutate it at runtime (e.g. from runNow) were verified to have no effect, because it is read before the query code runs.

// The declarative way to replace the default basemap
[
  {
     title: 'Basemaps',
     elements: [
        { title: 'Google Hybrid', name: 'HYBRID', source: 'google', group: 'background', visibility: true }
     ]
  }
]

disableContextMenu

function(configObj) : Objecthelper# Disables the browser context menu (right click) on an Ext component by adding a DomObserver plugin that cancels the contextmenu event.

Written as ExtjsUtils.disableContextMenu

Disables the browser context menu (right click) on an Ext component by adding a DomObserver plugin that cancels the contextmenu event. Apply it to the component's config object before the component is created; it does nothing on an already built component (one that has on).

configObj Object
Config object of the Ext component to be created.

Returns The same config object, with the context-menu-cancelling plugin added.

var panel = new Ext.Panel(ExtjsUtils.disableContextMenu({ html: 'No right click here' }));

getBodyHeight

function() : Numberhelper# Returns the full height of the page document in pixels (the largest of the body/document scroll, offset and client heights), including the part that is scrolled out of view.

Written as ExtjsUtils.getBodyHeight

Returns the full height of the page document in pixels (the largest of the body/document scroll, offset and client heights), including the part that is scrolled out of view.

Returns The document height in pixels.

var pageHeight = ExtjsUtils.getBodyHeight();

getButtonScale

function(strict) : Stringhelper# Returns the Ext button scale to use so buttons are usable both on desktop and on touch devices: 'large' on mobile (CHECK.isMobile()), 'medium' otherwise.

Written as ExtjsUtils.getButtonScale

Returns the Ext button scale to use so buttons are usable both on desktop and on touch devices: 'large' on mobile (CHECK.isMobile()), 'medium' otherwise.

strict Boolean
Currently unused; the check always uses the non-strict CHECK.isMobile().

Returns 'large' or 'medium', ready for an Ext button scale config.

new Ext.Button({ text: 'Apply', scale: ExtjsUtils.getButtonScale() });

getDesiredProjection

function() : Stringhelper# Returns the "desired" output projection for coordinates shown to users: longitude/latitude, "EPSG:4326".

Written as ExtjsUtils.getDesiredProjection

Returns the "desired" output projection for coordinates shown to users: longitude/latitude, "EPSG:4326". Use it as the target projection when converting a clicked map position into coordinates a person will read. It is not the map projection — see getFromProjection.

Returns The projection code "EPSG:4326".

// Longitude/latitude of a map click, ready to be displayed
var lonLat = ExtjsUtils.COORDINATE.getLatLong(evt, ExtjsUtils.getDesiredProjection());

getElementsByClassName

function(className, tag, elm) : Array.<HTMLElement>helper# Cross-browser getElementsByClassName: returns the elements carrying all the given class names (space separated), optionally restricted to a tag name and to the descendants of an element.

Written as ExtjsUtils.getElementsByClassName

Cross-browser getElementsByClassName: returns the elements carrying all the given class names (space separated), optionally restricted to a tag name and to the descendants of an element. Uses the native method, querySelectorAll, XPath or a manual scan depending on the browser, and always returns a real array. Original polyfill by Robert Nyman, refactored by Tubal Martin.

className String
One or more class names, separated by spaces (all must be present).
tag String
Tag name to restrict the result to (e.g. 'div'); any tag when omitted.
elm HTMLElement
Element to search under; the whole document when omitted.

Returns The matching elements (empty when none).

ExtjsUtils.getElementsByClassName('legend-entry selected', 'div').forEach(function(el) {
  el.style.fontWeight = 'bold';
});

getFromProjection

function() : Stringhelper# Returns the map projection code, "900913" (Spherical Mercator, the projection every layer is rendered in).

Written as ExtjsUtils.getFromProjection

Returns the map projection code, "900913" (Spherical Mercator, the projection every layer is rendered in). This is a different concept from CONFIGURATION.DEFAULT_FROM_PROJ — the projection assumed for vector/GeoJSON input that declares no CRS — even though both happen to be the same projection.

Returns The map projection code "900913".

// Reproject a lon/lat bounding box into map units
var bounds = ExtjsUtils.bboxTransform([-50, -20, -40, -10], "EPSG:4326", ExtjsUtils.getFromProjection());

getFunction

function(definition) : functionhelper# Always returns a callable function from a "function definition".

Written as ExtjsUtils.getFunction

Always returns a callable function from a "function definition". A function is returned as is (its closure is kept); a string is resolved first as the name of a global function (window[name]) and, failing that, evaluated as function source (a function(...) {...} literal or a statement body) through Mark.getFunction; anything else yields a no-op function. This is the resolution the markup widgets apply to string parameters such as handler= in {{button|handler=myGlobalFunction}}.

definition function|String|*
A function, the name of a global function, function source code, or anything else (no-op).

Returns The resolved function; never undefined.

window.sayHi = function() { ExtjsUtils.ALERTIFY.log("Hi"); };
ExtjsUtils.getFunction("sayHi")();                          // calls window.sayHi
ExtjsUtils.getFunction("function() { return 42; }")();       // 42
ExtjsUtils.getFunction(undefined)();                          // does nothing

getLayerExtent

function(layer) : OpenLayers.Boundshelper# Deprecated alias of ExtjsUtils.LAYER.getLayerExtent: returns the extent of a layer in the map projection (its WMS lon/lat bounding box reprojected), falling back to the layer's or the map's maxExtent.

Written as ExtjsUtils.getLayerExtent

Deprecated alias of ExtjsUtils.LAYER.getLayerExtent: returns the extent of a layer in the map projection (its WMS lon/lat bounding box reprojected), falling back to the layer's or the map's maxExtent. Kept because many queries still call it; new code should call ExtjsUtils.LAYER.getLayerExtent directly.

layer OpenLayers.Layer
The layer whose extent is wanted.

Returns The layer extent in the map projection.

// Zoom the map to a layer (e.g. from a layer's onVisibilityChange)
app.mapPanel.map.zoomToExtent(ExtjsUtils.getLayerExtent(layer), true);

getRandomColor

function(asArray) : String|Array.<Number>helper# Generates a random colour, either as an HTML hex string ("#rrggbb") or as an [r, g, b] array.

Written as ExtjsUtils.getRandomColor

Generates a random colour, either as an HTML hex string ("#rrggbb") or as an [r, g, b] array. Handy as a fallback colour when a legend value has no colour of its own.

asArray Boolean
true to get the colour as an [r, g, b] array (0-255 components) instead of a hex string.

Returns The generated colour: a "#rrggbb" string, or [r, g, b] when asArray is true.

var hex = ExtjsUtils.getRandomColor();      // "#3fa2c1"
var rgb = ExtjsUtils.getRandomColor(true);  // [63, 162, 193]

invertArray

function(arr) : Arrayhelper# Returns a new array with the elements of arr in reverse order.

Written as ExtjsUtils.invertArray

Returns a new array with the elements of arr in reverse order. Note that the input array is consumed in the process (its elements are popped one by one), so it is left empty afterwards — pass a copy (arr.slice()) when you still need the original.

arr Array
The array to reverse; emptied by the call.

Returns A new array with the elements in reverse order.

var reversed = ExtjsUtils.invertArray(names.slice()); // 'names' is kept intact

isLittleEndian

Boolean# true when the machine is little-endian, false when big-endian.

Written as ExtjsUtils.isLittleEndian

true when the machine is little-endian, false when big-endian. Computed once at load time (through a typed-array check); relevant when reading raw pixel/typed-array data.

var byteOrder = ExtjsUtils.isLittleEndian ? "little-endian" : "big-endian";

isValidBBox

function(BBox) : Booleanhelper# Tells whether a bounds object is usable: its width and height are numbers (not NaN), which is what a failed reprojection or a malformed capabilities bounding box produces.

Written as ExtjsUtils.isValidBBox

Tells whether a bounds object is usable: its width and height are numbers (not NaN), which is what a failed reprojection or a malformed capabilities bounding box produces.

BBox OpenLayers.Bounds
The bounds to validate.

Returns true when width and height are valid numbers, false otherwise.

var bounds = ExtjsUtils.bboxTransform(layer.llbbox, undefined, app.mapPanel.map.getProjection());
if (ExtjsUtils.isValidBBox(bounds)) app.mapPanel.map.zoomToExtent(bounds);

latinLowerString

function(s) : Stringhelper# Lower-cases a string and strips Latin accents (á→a, ç→c, ã→a, æ→ae, ...).

Written as ExtjsUtils.latinLowerString

Lower-cases a string and strips Latin accents (á→a, ç→c, ã→a, æ→ae, ...). Useful to compare or search user text and layer titles regardless of accents and case.

s String
The string to normalise.

Returns The string in lower case without accented characters.

ExtjsUtils.latinLowerString("Mata Atlântica"); // "mata atlantica"

layerBoundsIsVisible

function(layer) : Booleanhelper# Tells whether any part of a layer's maximum extent (layer.getMaxExtent()) intersects the area currently shown by the map.

Written as ExtjsUtils.layerBoundsIsVisible

Tells whether any part of a layer's maximum extent (layer.getMaxExtent()) intersects the area currently shown by the map.

layer OpenLayers.Layer
Layer to test.

Returns true when the layer extent intersects the current map view, false otherwise.

if (!ExtjsUtils.layerBoundsIsVisible(layer)) app.mapPanel.map.zoomToExtent(ExtjsUtils.LAYER.getLayerExtent(layer));

removeDomListener

function(domObj, evtName, fn)helper# Removes a DOM event listener previously added with addDomListener (removeEventListener or detachEvent, whichever the browser supports).

Written as ExtjsUtils.removeDomListener

Removes a DOM event listener previously added with addDomListener (removeEventListener or detachEvent, whichever the browser supports). The callback must be the exact function reference that was registered.

domObj EventTarget
DOM object the listener was added to.
evtName String
DOM event name, without the on prefix.
fn function
The callback to remove (must be the same function passed to addDomListener).
function onMove(evt) { console.log(evt.pageX, evt.pageY); }
ExtjsUtils.addDomListener(window, 'mousemove', onMove);
// ...later
ExtjsUtils.removeDomListener(window, 'mousemove', onMove);

scrollIntoView

function(container, item, padding)helper# Scrolls an Ext container so that item becomes visible, keeping padding pixels between the item and the top border of the scrollable area instead of leaving it glued to the edge.

Written as ExtjsUtils.scrollIntoView

Scrolls an Ext container so that item becomes visible, keeping padding pixels between the item and the top border of the scrollable area instead of leaving it glued to the edge. Inspired by Ext's Element.scrollIntoView.

container Ext.Panel
Scrollable Ext container; its body element is the one scrolled.
item HTMLElement|Ext.Element|String
Element (or element id) inside the container to bring into view.
padding Number
Distance in pixels to keep between the item and the container's top edge.
ExtjsUtils.scrollIntoView(legendPanel, 'legend-entry-12', 20);

toBounds

function(extent) : OpenLayers.Boundshelper# Turns any of the usual extent shapes into an OpenLayers.Bounds, without reprojecting: an OpenLayers.Bounds comes back as is, a [left, bottom, right, top] array (Bounds#toArray() order, what …

Written as ExtjsUtils.toBounds

Turns any of the usual extent shapes into an OpenLayers.Bounds, without reprojecting: an OpenLayers.Bounds comes back as is, a [left, bottom, right, top] array (Bounds#toArray() order, what offline area records and postMessage payloads carry) or a {left, bottom, right, top} object becomes a new one. Use it at the edge where an extent arrives from outside (a message, a stored record) before calling map functions.

extent OpenLayers.Bounds|Array.<Number>|Object
The extent, in any of the three shapes.

Returns The bounds, or null when extent is missing or lacks a side.

// an extent received from the parent page
var bounds = ExtjsUtils.toBounds(msg.message.extent); // [-5179428, -2460070, -5171880, -2455780]
if (bounds) ExtjsUtils.ZOOM.zoomToExtent(bounds);

touchDispatchMouseEvents

function(event, bubbleEvnt)helper# Turns a single-touch event (native touch or HammerJS pan/tap) into the equivalent mouse event — touchstart/panstart/tap → mousedown, touchmove/panmove → mousemove, …

Written as ExtjsUtils.touchDispatchMouseEvents

Turns a single-touch event (native touch or HammerJS pan/tap) into the equivalent mouse event — touchstart/panstart/tap → mousedown, touchmove/panmove → mousemove, touchend/panend → mouseup — and dispatches it on the touched element, so code written for the mouse also reacts to touch. The original touch event is cancelled and stopped. Multi-touch gestures and events coming from a real mouse are left untouched.

event TouchEvent|Object
The touch (or HammerJS) event to convert.
bubbleEvnt Boolean
true to let the simulated mouse event bubble up to window, false to dispatch it on the target only.
ExtjsUtils.addDomListener(panelEl, 'touchstart', function(evt) {
  ExtjsUtils.touchDispatchMouseEvents(evt, true);
});

unifyHammerEvent

function(hammerJsEvt) : Objecthelper# Normalises a HammerJS (or native touch) event in place so it can be handled like an Ext/ OpenLayers pointer event: fills touches/changedTouches from pointers/changedPointers, renames pinch* …

Written as ExtjsUtils.unifyHammerEvent

Normalises a HammerJS (or native touch) event in place so it can be handled like an Ext/ OpenLayers pointer event: fills touches/changedTouches from pointers/changedPointers, renames pinch* types to touch*, sets srcElement, computes the page position xy ([x, y], with an equals helper) and adds getXY() to the event and to its srcEvent.

hammerJsEvt Object
HammerJS event (or a native touch event) to normalise.

Returns The same event object, with the unified properties added.

hammer.on('panmove', function(evt) {
  var xy = ExtjsUtils.unifyHammerEvent(evt).getXY(); // [pageX, pageY]
});

ALERTIFY · messages and questions

Alertify10 entries
Messages, alerts and questions for the reader. Usage: ExtjsUtils.ALERTIFY

DISABLE_ALERT_NAME

String# Name of the stored option (COOKIE) that disables the notifications shown by Alertify.log; the "stop notifications" checkbox of the notification writes it and isEnabled/toggle read and write it.

Written as ExtjsUtils.ALERTIFY.DISABLE_ALERT_NAME

Name of the stored option (COOKIE) that disables the notifications shown by Alertify.log; the "stop notifications" checkbox of the notification writes it and isEnabled/toggle read and write it.

var muted = !!ExtjsUtils.COOKIE.readOption(ExtjsUtils.ALERTIFY.DISABLE_ALERT_NAME);

SPAM

Object# Spam filter used by Alertify.log: a message shown recently is not shown again until its spam time expires.

Written as ExtjsUtils.ALERTIFY.SPAM

Spam filter used by Alertify.log: a message shown recently is not shown again until its spam time expires. Members: isSpamMsg(msg) returns true when msg was shown within its spam window; addMsgToSpam(msg, time) registers a message for time milliseconds (log uses config.spamTime, default 10 s); EXPIRE_DATE maps the md5 of each message to its expiry timestamp. Messages are keyed by md5, so the same text counts as the same message. (Alertify.alert also calls it, but without a time, so alerts are effectively never muted.)

if (!ExtjsUtils.ALERTIFY.SPAM.isSpamMsg(msg)) {
    alertify.log(msg);
    ExtjsUtils.ALERTIFY.SPAM.addMsgToSpam(msg, 30000); // mute repeats for 30 s
}

alert

function(msg)helper# Shows an user non blocking alert.

Written as ExtjsUtils.ALERTIFY.alert

Shows an user non blocking alert.

PS: If layer is loading only the last message will be shown after load end.

msg String
Notification HTML content.

confirmChoice

function(html, choices, onChoice, config)helper# Modal for one or more labeled choices.

Written as ExtjsUtils.ALERTIFY.confirmChoice

Modal for one or more labeled choices.

  • 1 choice: invokes callback immediately (no modal).
  • 2 choices: alertify.confirm with custom ok/cancel labels; both invoke onChoice.
  • 3+ choices: alertify.confirm with a <select>; OK confirms selection;
      Cancel invokes config.onCancel when provided. Selecting an option auto-clicks OK
      when config.autoConfirmOnSelect is not false (default true).
html String
Message HTML.
choices Array.<(String|{label:String, value: *})>
Option labels or {label,value} objects.
onChoice function
function(value, index, choice) for a picked option.
config Object
Optional: okLabel, cancelLabel, onCancel, autoConfirmOnSelect.

isEnabled

function() : Booleanhelper# Tells whether notifications (Alertify.log) are enabled for this browser, i.e. the user has not ticked "stop notifications" (stored under DISABLE_ALERT_NAME).

Written as ExtjsUtils.ALERTIFY.isEnabled

Tells whether notifications (Alertify.log) are enabled for this browser, i.e. the user has not ticked "stop notifications" (stored under DISABLE_ALERT_NAME).

Returns True when notifications are enabled, false when the user disabled them.

if (!ExtjsUtils.ALERTIFY.isEnabled()) ExtjsUtils.ALERTIFY.log("Important!", {force: true});

isMapLoaded

function() : Booleanhelper# Tells whether the map has finished loading, i.e. whether log shows notifications immediately instead of queueing them.

Written as ExtjsUtils.ALERTIFY.isMapLoaded

Tells whether the map has finished loading, i.e. whether log shows notifications immediately instead of queueing them.

Returns True once setMapLoaded was called, false before.

if (ExtjsUtils.ALERTIFY.isMapLoaded()) ExtjsUtils.ALERTIFY.log("Data refreshed.");

log

function(msg, config)helper# Shows an user notification (if enabled).

Written as ExtjsUtils.ALERTIFY.log

Shows an user notification (if enabled).

PS: The messages before layer loading are delayed, when it finishes only the last message will be shown.

msg String
The message that will be displayed in the alert. It can be in HTML format.
config Object
Configuration parameters for the message. { force: {Boolean} Force to show notification even when disabled. func: {Callback} Callback function when the notification is clicked. onlyMsg: {Boolean} True to only show message and hide the close and the stop notifications, False otherwise. delay: {Numeric} Amout of time in milisseconds before the message hide. spamTime: {Numeric} Time the same message to be shown again is considered spam. (even with force = true). }

removePageLoader

function()helper# Fades out and removes the page loading overlay (#loader-container).

Written as ExtjsUtils.ALERTIFY.removePageLoader

Fades out and removes the page loading overlay (#loader-container). Called by setMapLoaded; call it directly only when the platform's own loading flow is bypassed.

ExtjsUtils.ALERTIFY.removePageLoader();

setMapLoaded

function()helper# Marks the map as loaded: flushes the notifications queued by log while the map was loading (only the last one is effectively visible, as one notification is shown at a time) and removes the page loader.

Written as ExtjsUtils.ALERTIFY.setMapLoaded

Marks the map as loaded: flushes the notifications queued by log while the map was loading (only the last one is effectively visible, as one notification is shown at a time) and removes the page loader. The platform calls it when the query finishes loading; query code does not normally need to.

ExtjsUtils.ALERTIFY.setMapLoaded();

toggle

function(state)helper# Enables or disables the notifications shown by Alertify.log for this browser (the setting is persisted with COOKIE).

Written as ExtjsUtils.ALERTIFY.toggle

Enables or disables the notifications shown by Alertify.log for this browser (the setting is persisted with COOKIE). Without an argument the current state is inverted. Messages logged with {force: true} are still shown when disabled.

state Boolean
True to enable, false to disable; omit to invert.
ExtjsUtils.ALERTIFY.toggle(false); // silence the platform notifications in this query

ASSYNC · async loops

ASSYNC3 entries
Sequential async iteration helpers (map, filter, reduce awaiting each callback).
Usage: ExtjsUtils.ASSYNC

filter

function(arrayLike, asyncFunction) : Promise.<Array>helper# Array.filter for async predicates, run sequentially: the predicate of each element is awaited before the next element is tested.

Written as ExtjsUtils.ASSYNC.filter

Array.filter for async predicates, run sequentially: the predicate of each element is awaited before the next element is tested.

arrayLike Array
Array (or array-like) to iterate.
asyncFunction function
async function(element, index) resolving to a truthy value to keep the element.

Returns Resolves to the elements that passed the predicate, in order.

var valid = await ExtjsUtils.ASSYNC.filter(layers, async function(layer) {
    return await layerHasData(layer);
});

map

function(arrayLike, asyncFunction) : Promise.<Array>helper# Array.map for async callbacks, run sequentially: each element waits for the previous callback's promise before the next one starts (unlike Promise.all(map(...)), which starts them all at once).

Written as ExtjsUtils.ASSYNC.map

Array.map for async callbacks, run sequentially: each element waits for the previous callback's promise before the next one starts (unlike Promise.all(map(...)), which starts them all at once). Use it to process items one at a time, e.g. a request per element.

arrayLike Array
Array (or array-like) to iterate.
asyncFunction function
async function(element, index) returning the mapped value (or a promise of it).

Returns Resolves to the mapped values, in order.

var areas = await ExtjsUtils.ASSYNC.map(features, async function(f) {
    return await fetchAreaFor(f.attributes.code);
});

reduce

function(arrayLike, asyncFunction, defaultVal) : Promise.<*>helper# Array.reduce for async reducers, run sequentially: each call receives the awaited result of the previous one.

Written as ExtjsUtils.ASSYNC.reduce

Array.reduce for async reducers, run sequentially: each call receives the awaited result of the previous one.

arrayLike Array
Array (or array-like) to iterate.
asyncFunction function
async function(accumulator, element, index) returning the next accumulator.
defaultVal *
Initial accumulator value.

Returns Resolves to the final accumulator.

var total = await ExtjsUtils.ASSYNC.reduce(codes, async function(sum, code) {
    return sum + await fetchAreaFor(code);
}, 0);

CHECK · type and browser checks

CHECK13 entries
Type and environment checks (mobile, browser support, value types).
Usage: ExtjsUtils.CHECK

browserSupported

function() : Booleanhelper# Tells whether the browser has everything the map calculations need: Web Workers, typed arrays (Uint8Array) and a WebGL context.

Written as ExtjsUtils.CHECK.browserSupported

Tells whether the browser has everything the map calculations need: Web Workers, typed arrays (Uint8Array) and a WebGL context.

Returns True on a supported browser, false otherwise.

if (!ExtjsUtils.CHECK.browserSupported()) ExtjsUtils.ALERTIFY.alert("Your browser cannot run this map.");

hasWebWorker

function() : Booleanhelper# Tells whether the browser supports Web Workers.

Written as ExtjsUtils.CHECK.hasWebWorker

Tells whether the browser supports Web Workers.

Returns True when window.Worker exists, false otherwise.

if (!ExtjsUtils.CHECK.hasWebWorker()) ExtjsUtils.ALERTIFY.log("Calculations will run in the main thread.");

isArray

function(arg) : Booleanhelper# Tells whether a value is an array (Ext.isArray).

Written as ExtjsUtils.CHECK.isArray

Tells whether a value is an array (Ext.isArray).

arg *
Value to check.

Returns True when arg is an array, false otherwise.

var list = ExtjsUtils.CHECK.isArray(value) ? value : [value];

isChrome

function() : Booleanhelper# Tells whether the browser is Google Chrome (Ext.isChrome).

Written as ExtjsUtils.CHECK.isChrome

Tells whether the browser is Google Chrome (Ext.isChrome).

Returns True on Chrome, false otherwise.

if (ExtjsUtils.CHECK.isChrome()) enableWebGLExtras();

isColor

function(arg) : Booleanhelper# Tells whether a string is a valid CSS colour (#rgb, rgb(...), a colour name, ...), using the browser's own parser.

Written as ExtjsUtils.CHECK.isColor

Tells whether a string is a valid CSS colour (#rgb, rgb(...), a colour name, ...), using the browser's own parser.

arg String
Colour to validate.

Returns True when the browser accepts the string as a colour.

ExtjsUtils.CHECK.isColor("#ff8800"); // true

isFunction

function(obj) : Booleanhelper# Tells whether a value is a function.

Written as ExtjsUtils.CHECK.isFunction

Tells whether a value is a function.

obj *
Value to check.

Returns True when obj is a function, false otherwise.

if (ExtjsUtils.CHECK.isFunction(config.onClick)) config.onClick(feature);

isFunctionString

function(str) : Booleanhelper# Tells whether a string holds JavaScript source that evaluates to a function (e.g. "function(a) { return a; }" or "a => a"), as stored in serialized layer definitions.

Written as ExtjsUtils.CHECK.isFunctionString

Tells whether a string holds JavaScript source that evaluates to a function (e.g. "function(a) { return a; }" or "a => a"), as stored in serialized layer definitions. The string is evaluated with new Function, so only pass trusted text.

str String
Source text to test.

Returns True when the text evaluates to a function, false otherwise (including syntax errors).

ExtjsUtils.CHECK.isFunctionString("function(inputs) { return 1; }"); // true

isMobile

function(strict) : Booleanhelper# Device-based mobile test: true when the browser exposes window.orientation (phones and tablets), optionally restricted to small screens.

Written as ExtjsUtils.CHECK.isMobile

Device-based mobile test: true when the browser exposes window.orientation (phones and tablets), optionally restricted to small screens. It does not change when the window is resized. This is different from MOBILE_UTILS.isMobile(), which follows the responsive CSS media query (viewport narrower than 768px) and therefore tells whether the mobile layout is currently active — use that one for layout decisions. Idea taken from Leaflet's Browser.js.

strict Boolean
True to also require a small screen (screen.width + screen.height < 800).

Returns True on a mobile device, false otherwise.

var touchDevice = ExtjsUtils.CHECK.isMobile();
var mobileLayout = MOBILE_UTILS.isMobile();

isObject

function(obj, acceptNullAsObject) : Booleanhelper# Tells whether a value is of type "object" (plain objects, arrays, dates...).

Written as ExtjsUtils.CHECK.isObject

Tells whether a value is of type "object" (plain objects, arrays, dates...). null also has type "object" in JavaScript, so it is rejected unless acceptNullAsObject is true.

obj *
Value to check.
acceptNullAsObject Boolean
True to also accept null.

Returns True when obj is an object (and not null, unless accepted).

if (ExtjsUtils.CHECK.isObject(config)) Ext.apply(defaults, config);

isOlderBrowser

function() : Booleanhelper# Tells whether the browser is an old one (roughly before 2014) by checking for Element.prototype.remove.

Written as ExtjsUtils.CHECK.isOlderBrowser

Tells whether the browser is an old one (roughly before 2014) by checking for Element.prototype.remove. Returns false on Chrome 23+, Edge 12+, Firefox 23+, Opera 15+ and Safari 7+; a false result does not guarantee full support (see browserSupported).

Returns True on an old browser, false otherwise.

if (ExtjsUtils.CHECK.isOlderBrowser()) ExtjsUtils.ALERTIFY.alert("Please update your browser.");

isString

function(arg) : Booleanhelper# Tells whether a value is a string (primitive or String object).

Written as ExtjsUtils.CHECK.isString

Tells whether a value is a string (primitive or String object).

arg *
Value to check.

Returns True when arg is a string, false otherwise.

var col = ExtjsUtils.CHECK.isString(column) ? csv.columnNameToInd(column) : column;

isWebkit

function() : Booleanhelper# Tells whether the browser is WebKit based (Chrome, Safari...; Ext.isWebKit).

Written as ExtjsUtils.CHECK.isWebkit

Tells whether the browser is WebKit based (Chrome, Safari...; Ext.isWebKit).

Returns True on a WebKit browser, false otherwise.

var cssPrefix = ExtjsUtils.CHECK.isWebkit() ? "-webkit-" : "";

msieversion

function() : Booleanhelper# Tells whether the browser is Internet Explorer (any version, including IE 11).

Written as ExtjsUtils.CHECK.msieversion

Tells whether the browser is Internet Explorer (any version, including IE 11).

Returns Truthy on Internet Explorer, false otherwise.

if (ExtjsUtils.CHECK.msieversion()) ExtjsUtils.ALERTIFY.alert("Please use a modern browser.");

COMPONENTS · row button builders

COMPONENTS1 entry
Builders of the buttons of a layer's row (associated buttons). Usage: ExtjsUtils.COMPONENTS

createAssociatedButton

function(btnConfig, defaultProperties) : Ext.Buttonhelper# Creates an Ext.Button that mirrors another button or checkbox of the interface — the "associated button" behind paramsButtonConfig entries with an associatedButtonID.

Written as ExtjsUtils.COMPONENTS.createAssociatedButton

Creates an Ext.Button that mirrors another button or checkbox of the interface — the "associated button" behind paramsButtonConfig entries with an associatedButtonID. The original component is looked up by id (btnConfig.associatedButtonID, a string or a function returning it) after render; when it is a toggle button or a checkbox the new button becomes a toggle kept in sync both ways, otherwise clicking the new button triggers the original's handler/click. Your own toggleHandler/handler in btnConfig replace the syncing ones. The platform calls this for the legend window; a query may call it to place such a button in its own HTML.

btnConfig Object
Ext.Button config: associatedButtonID plus any button option (text, iconCls, tooltip, pressed, enableToggle, handler, toggleHandler...). Its values win over defaultProperties.
defaultProperties Object
Defaults applied before btnConfig (typically pressed, toggleGroup, cls, iconCls); any key present in btnConfig overrides them.

Returns The new button, not yet rendered; add it to a container or call render.

var mirror = ExtjsUtils.COMPONENTS.createAssociatedButton({
  associatedButtonID: 'property_pick',   // id of an existing toggle button
  text: 'Pick a point'
}, { iconCls: 'gxp-icon-getfeatureinfo' });
mirror.render('my-toolbar-div');

COORDINATE · mouse position to lon/lat

COORDINATE2 entries
Coordinate helpers: mouse/pixel positions to longitude/latitude and polygon edge equations.
Usage: ExtjsUtils.COORDINATE

getLatLong

function(xy, fromProj) : OpenLayers.LonLathelper# Converts a pixel position on the map viewport into a map coordinate (OpenLayers.LonLat).

Written as ExtjsUtils.COORDINATE.getLatLong

Converts a pixel position on the map viewport into a map coordinate (OpenLayers.LonLat). Accepts either an OpenLayers/Ext mouse event (its xy pixel is used) or a plain {x, y} pixel object. The result is in the map projection; pass fromProj to get it transformed into that projection instead (e.g. "EPSG:4326" for longitude/latitude).

xy MouseEvent|Object
A mouse event carrying an xy pixel, or a {x, y} pixel position relative to the map viewport.
fromProj String|OpenLayers.Projection
Projection to transform the result into; omit to keep the map projection.

Returns The map coordinate under the pixel.

// Longitude/latitude under the mouse, from an OpenLayers click event
app.mapPanel.map.events.register('click', null, function(evt) {
  var lonLat = ExtjsUtils.COORDINATE.getLatLong(evt, "EPSG:4326");
  console.log(lonLat.lon, lonLat.lat);
});

getLineEquations

function(polygonFeature) : Array.<Object>helper# Computes the line equation of every edge of a polygon feature (each consecutive pair of vertices, closing back to the first).

Written as ExtjsUtils.COORDINATE.getLineEquations

Computes the line equation of every edge of a polygon feature (each consecutive pair of vertices, closing back to the first). Each edge is described as y = A*x + B by an object {A, B, x, y} — A the slope, B the intercept, x and y the [start, end] coordinates of the segment. The returned array also carries two helpers: getLineX(y, edge) and getLineY(x, edge), which solve the equation for one edge and handle vertical (A === Infinity) and horizontal (A === 0) segments. Used by the polygon rasterisation that finds the pixels of a layer inside a drawn area.

polygonFeature OpenLayers.Feature.Vector
Feature whose polygon geometry is processed.

Returns One {A, B, x, y} object per edge, plus the getLineX/getLineY helper functions attached to the array.

var edges = ExtjsUtils.COORDINATE.getLineEquations(drawnFeature);
var xAtY = edges.getLineX(-2300000, edges[0]); // x where the first edge crosses that y

CSS · query stylesheet rules

CSS6 entries
Inject, replace and remove CSS rules from a query. Rules defined here are removed when another query loads, so the customization never leaks between queries.
Usage: ExtjsUtils.CSS

defineClass

function(selector, rules)helper# Adds a CSS rule to the query's dynamic stylesheet — the main way a query restyles the interface (hide the top bar, recolour the legend, style its own HTML).

Written as ExtjsUtils.CSS.defineClass

Adds a CSS rule to the query's dynamic stylesheet — the main way a query restyles the interface (hide the top bar, recolour the legend, style its own HTML). The selector is any CSS selector and doubles as the rule's unique key: defining the same selector again replaces the previous rule. The rule is tracked and removed when another query loads, so the styling never leaks between queries; the page's static CSS is only overridden, never changed. Does nothing while the query is only being evaluated (justEval mode). QUERY.decorate forwards every key that is not header, footer or run to this function, so decorate({ '#topbar': 'display: none;' }) is the same call.

selector String
CSS selector the rule applies to, e.g. '#topbar' or '.legend-title, .legend-value'. Treated as an opaque key: no lookup is performed.
rules String|Object
The declarations only (no braces): a string such as "background-color: green; color: white;", or an object { 'background-color': 'green', color: 'white' }.
ExtjsUtils.CSS.defineClass('#topbar', 'background-color: #1a4d2e;');
ExtjsUtils.CSS.defineClass('.my-popup', { position: 'absolute', 'z-index': 10000, padding: '8px' });

hasClass

function(selector) : Booleanhelper# Tells whether a rule with exactly this selector exists in the query's dynamic stylesheet (i.e. was added with defineClass and not removed).

Written as ExtjsUtils.CSS.hasClass

Tells whether a rule with exactly this selector exists in the query's dynamic stylesheet (i.e. was added with defineClass and not removed). The selector is compared as a whole string; a comma-separated selector list is not split.

selector String
The selector used in defineClass.

Returns true when the rule exists, false otherwise.

if (!ExtjsUtils.CSS.hasClass('#topbar')) ExtjsUtils.CSS.defineClass('#topbar', 'display: none;');

importExternalCss

function(cssFile, id, shouldClear)helper# Loads an external stylesheet by appending a <link rel="stylesheet"> to the page head — for instance a font or an icon set the query's HTML needs.

Written as ExtjsUtils.CSS.importExternalCss

Loads an external stylesheet by appending a <link rel="stylesheet"> to the page head — for instance a font or an icon set the query's HTML needs. By default the link is tagged so it is removed when another query loads (like the rules of defineClass); pass shouldClear = false to keep it. Does nothing while the query is only being evaluated.

cssFile String
URL of the CSS file.
id String
id to give the generated <link> element.
shouldClear Boolean
true to remove the stylesheet when another query loads; false to keep it permanently.
ExtjsUtils.CSS.importExternalCss('https://fonts.googleapis.com/css?family=Roboto', 'roboto-font');

removeAllClasses

function()helper# Removes every dynamic CSS rule (defineClass) and every stylesheet imported with importExternalCss that was left removable.

Written as ExtjsUtils.CSS.removeAllClasses

Removes every dynamic CSS rule (defineClass) and every stylesheet imported with importExternalCss that was left removable. The platform calls it when another query loads (QUERY.clearQueryGlobalProperties); a query may call it to reset its own styling.

ExtjsUtils.CSS.removeAllClasses();

removeClass

function(selector)helper# Removes the rule(s) with exactly this selector from the query's dynamic stylesheet, undoing a defineClass.

Written as ExtjsUtils.CSS.removeClass

Removes the rule(s) with exactly this selector from the query's dynamic stylesheet, undoing a defineClass. The selector is the rule's key (compared as a whole string). Only dynamic rules are affected — the page's static CSS is never changed. Does nothing when the selector is not defined.

selector String
The selector used in defineClass.
ExtjsUtils.CSS.defineClass('#topbar', 'display: none;');
// ...later, show the top bar again
ExtjsUtils.CSS.removeClass('#topbar');

runAnimation

function(elm, animationCls, callback, scope)helper# Starts a CSS animation on an element by adding the class that defines it, then forces a redraw so the animation actually plays, and runs an optional callback right after it starts (about 10 ms later).

Written as ExtjsUtils.CSS.runAnimation

Starts a CSS animation on an element by adding the class that defines it, then forces a redraw so the animation actually plays, and runs an optional callback right after it starts (about 10 ms later). The class stays on the element; running different animations with the same class gives unexpected results.

elm Ext.Element
Element to animate (an Ext.Element, e.g. Ext.get('id')).
animationCls String
CSS class whose rules define the animation.
callback function
Called once the animation has started.
scope Object
this for the callback.
ExtjsUtils.CSS.defineClass('.blink', 'animation: blink 1s 3;');
ExtjsUtils.CSS.runAnimation(Ext.get('legend-entry-3'), 'blink');

CSV · read and join tables

CSV3 entries
CSV parsing and joining helpers. The table object returned by the loadcsv tool is documented under Tools > LoadCsv.
Usage: ExtjsUtils.CSV

CsvTable

function(matrix)helper# Constructor of the table object that wraps a parsed CSV matrix (header row first) and offers lookups by column name, filtering and indexing: new ExtjsUtils.CSV.CsvTable(matrix).

Written as ExtjsUtils.CSV.CsvTable

Constructor of the table object that wraps a parsed CSV matrix (header row first) and offers lookups by column name, filtering and indexing: new ExtjsUtils.CSV.CsvTable(matrix). The {{loadcsv|id=x|url=...}} widget returns one of these at inputs.id["x"]; its methods (getLines, getValue, columnNameToInd, createIndexes, getColunsInd, ...) are documented under Tools > LoadCsv. Build one yourself to wrap a CSV you fetched or joined with CSV.joinCSV.

matrix Array.<Array.<String>>
Rows of the CSV, the first row being the header (e.g. the output of ParseCSV).
var table = new ExtjsUtils.CSV.CsvTable(ParseCSV(xhr.responseText));
var iYear = table.columnNameToInd("Year");
var rows2024 = table.getLines([iYear], [2024]);

joinCSV

function(csvA, csvB, columnsA, columnsB) : Array.<Array.<String>>helper# Joins two CSV matrices (arrays of rows) on the values of the given key columns: every row of A is kept, in order, followed by the columns of its matching B row minus the key columns of B.

Written as ExtjsUtils.CSV.joinCSV

Joins two CSV matrices (arrays of rows) on the values of the given key columns: every row of A is kept, in order, followed by the columns of its matching B row minus the key columns of B. Example: A ["title", "value", "index"] and B ["Total", "Category", "Data"] joined with [2], [1] give ["title", "value", "index", "Total", "Data"]. Rows of A without a match are not padded reliably (they receive the cells of the previously matched row, or a single undefined cell for the first row), so make sure every key of A exists in B — header rows included, when both matrices carry one. Wrap the result in new ExtjsUtils.CSV.CsvTable(...) to query it.

csvA Array.<Array.<String>>
Rows of table A (header included when both tables have one).
csvB Array.<Array.<String>>
Rows of table B.
columnsA Array.<Number>
Indexes of the key columns of A.
columnsB Array.<Number>
Indexes of the matching key columns of B (same order as columnsA).

Returns The joined rows.

var legend = inputs.id["legend_csv"].getLines(undefined, undefined, true); // with header
var areas = inputs.id["area_csv"].getLines(undefined, undefined, true);
var joined = new ExtjsUtils.CSV.CsvTable(ExtjsUtils.CSV.joinCSV(legend, areas, [0], [1]));

readMapCsvToMatrix

function(csvContent, qntMaps) : Array.<Array.<Number>>helper# Parses a "category, value" CSV produced by a cross-tabulation of maps into a nested numeric matrix.

Written as ExtjsUtils.CSV.readMapCsvToMatrix

Parses a "category, value" CSV produced by a cross-tabulation of maps into a nested numeric matrix. Each pair of digits of the category code is one (1-based) map class index, read from the right: 201 is [02, 01], 1001 is [10, 01], so the value of line 201, 166311249 ends up at matrix[0][1] (class 1 of the last map, class 2 of the previous one). The header line is skipped. CSV format:

Category, Value
    201, 166311249
    205, 12311
    1001, 83696

csvContent String
Raw CSV text.
qntMaps Number
Number of maps (digit pairs) in the category code; when omitted, the number of non-empty columns of the header line.

Returns Nested matrix indexed by the class of each map (0-based).

var matrix = ExtjsUtils.CSV.readMapCsvToMatrix(xhr.responseText, 2);
var area = matrix[0][1]; // value of category "0201" (last map class 1, first map class 2)

DOMHelper · page elements

DOMHelper2 entries
DOM element helpers.
Usage: ExtjsUtils.DOMHelper

isDescendant

function(parent, child) : Booleanhelper# Tells whether the DOM element child is inside parent (at any depth).

Written as ExtjsUtils.DOMHelper.isDescendant

Tells whether the DOM element child is inside parent (at any depth). Typical use: in a timer that auto-closes a floating popup, check whether the element last hovered by the mouse is still part of the popup before hiding it.

parent HTMLElement
Candidate ancestor element.
child HTMLElement
Element to test.

Returns true when child is contained in parent, false otherwise.

var popup = document.getElementById('info-popup');
if (!ExtjsUtils.DOMHelper.isDescendant(popup, window.lastHoveredElement)) {
  popup.style.display = 'none';
}

removeElement

function(element)helper# Removes an element from the DOM together with all its children (old IE left the children behind).

Written as ExtjsUtils.DOMHelper.removeElement

Removes an element from the DOM together with all its children (old IE left the children behind). Accepts a plain DOM element or an Ext.Element (its dom is used). Does nothing when the element is not attached to the document.

element HTMLElement|Ext.Element
Element to remove completely.
ExtjsUtils.DOMHelper.removeElement(document.getElementById('my-popup'));

EVENTS · event lifecycles

EVENTS1 entry
Helpers to bind OpenLayers events to the lifecycle of Ext components.
Usage: ExtjsUtils.EVENTS

monExtOL

function(extObject, openlayersObj, evtNameOL, callback, scope)helper# Registers a listener on an OpenLayers object (map, layer, control...) that is automatically unregistered when the given Ext component is destroyed — the OpenLayers counterpart of Ext's mon, which …

Written as ExtjsUtils.EVENTS.monExtOL

Registers a listener on an OpenLayers object (map, layer, control...) that is automatically unregistered when the given Ext component is destroyed — the OpenLayers counterpart of Ext's mon, which does not work with OpenLayers event objects. Use it when a window or panel you create reacts to map events, so the handler does not outlive the component.

extObject Ext.Component
Ext component whose destroy event removes the listener.
openlayersObj Object
OpenLayers object exposing events (e.g. the map or a layer).
evtNameOL String
OpenLayers event name (e.g. 'moveend', 'visibilitychanged').
callback function
Listener called with the OpenLayers event.
scope Object
this for the callback.
var win = new Ext.Window({ title: 'Map info', html: '' });
ExtjsUtils.EVENTS.monExtOL(win, app.mapPanel.map, 'moveend', function() {
  win.body.update('Zoom: ' + app.mapPanel.map.getZoom());
});

FEATURE · build vector features

FEATURE1 entry
Helpers to build OpenLayers vector features for drawable/vector layers.
Usage: ExtjsUtils.FEATURE

fromGeometry

function(geometry, attrSource, options) : OpenLayers.Feature.Vectorhelper# Build a Vector from a geometry, taking user attributes from sourceFeature.

Written as ExtjsUtils.FEATURE.fromGeometry

Build a Vector from a geometry, taking user attributes from sourceFeature. Optionally copies OpenLayers id / fid so list↔map identity survives rebuilds.

geometry OpenLayers.Geometry
Geometry of the new feature.
attrSource OpenLayers.Feature.Vector
Attr (and id) source; omit for a brand-new feature.
options Object
Optional behaviour switches.
options.attributes Object
Explicit attrs (skips cloning from source).
options.copyId Boolean
Copy id/fid when sourceFeature is set.

Returns The new feature.

layer.addFeatures([ExtjsUtils.FEATURE.fromGeometry(newGeom, oldFeature)]);
  ExtjsUtils.FEATURE.fromGeometry(newGeom, oldFeature, { copyId: false });

GEOJSON · GeoJSON and shapefiles

GEOJSON3 entries
Functions to handle GEOJSON transformations.

geojson2Features

function(geojson, fromProj, toProj) : Array.<OpenLayers.Feature>helper# Parse Geojson to Layer.Feature.

Written as ExtjsUtils.GEOJSON.geojson2Features

Parse Geojson to Layer.Feature.

PS: fromProj is resolved by GEOJSON.getGeojsonProjection (GeoJSON crs, then
    the query/URL defaultFromProj, then CONFIGURATION.DEFAULT_FROM_PROJ). PS2: toProj defaults to the map projection (EPSG:900913). PS3: CRS outside EPSG:4326 / EPSG:3857 (e.g. SIRGAS EPSG:4674) requires
     PROJECTION.setProjectionOptions().

geojson Object|Array.<Object>
Geojson object or array of objects.
fromProj String
Original projection of Geojson object.
toProj String
To projection of Geojson object.

Returns Returns the array of parsed Features.

getGeojsonProjection

function(geojson, defaultFromProj) : String|nullhelper# Resolve source projection from a parsed GeoJSON object.

Written as ExtjsUtils.GEOJSON.getGeojsonProjection

Resolve source projection from a parsed GeoJSON object. OpenLayers.Format.GeoJSON.read does not read crs; geojson2Features only consults crs when fromProj is omitted. Checks top-level crs, then defaultFromProj, then the query/URL defaultFromProj setting, then CONFIGURATION.DEFAULT_FROM_PROJ (EPSG:900913) unless disabled.

geojson Object
Parsed GeoJSON
defaultFromProj String
Fallback when crs is absent

Returns EPSG code, or null when the default is disabled.

shapefile2GeojsonAsync

function(shpFile, paramOptions)helper# Parse shapefile to compatible Layer features.

Written as ExtjsUtils.GEOJSON.shapefile2GeojsonAsync

Parse shapefile to compatible Layer features. DBF file is optional.

PS:ParamOptions
  {
  callback: {Function} called when the shapefile is parsed, as function(geojson, data) with this = paramOptions.layer (geojson: the parsed GeoJSON; data: the whole parse result),
  fromProj: {String?} 'Projection name.' (EPSG:4326 or EPSG:900913),
  dbf: (Optional?)'DBF file to load along with shapefile.',
  limitCount: (Optional?)'Limit the amount of processed geometries'
  }

shpFile File
Shapefile content (Needs to be in projection EPSG:4326 or EPSG:900913.
paramOptions ParamOptions
Additional configuration for handling shapefile. ParamOptions { callback: {Function} called when the shapefile is parsed, as function(geojson, data) with this = paramOptions.layer (geojson: the parsed GeoJSON; data: the whole parse result), fromProj: {String?} 'Projection name.' (EPSG:4326 or EPSG:900913), dbf: (Optional?)'DBF file to load along with shapefile.', limitCount: (Optional?)'Limit the amount of processed geometries' }

GEOMETRY · union, intersection, validation

GEOMETRY45 entries
JSTS-backed geometry operations (union, intersection, validation) for OpenLayers 2.x geometries. Every operation accepts OpenLayers geometries, converts them to JTS, runs the JTS method and converts the result back. Usage: ExtjsUtils.GEOMETRY.<operation>(geometryA, geometryB); the JSTS library is loaded on demand by loadGeometryLibrary.

contains

function(aGeom, bGeom) : Booleanhelper# Tells whether aGeom contains bGeom entirely (no point of bGeom lies outside aGeom, and their interiors share at least one point).

Written as ExtjsUtils.GEOMETRY.contains

Tells whether aGeom contains bGeom entirely (no point of bGeom lies outside aGeom, and their interiors share at least one point). A polygon does not contain a point on its own boundary — use covers for that. Both geometries are required. Requires the JSTS library.

aGeom OpenLayers.Geometry
Container geometry.
bGeom OpenLayers.Geometry
Geometry to test.

Returns True when aGeom contains bGeom.

var inside = ExtjsUtils.GEOMETRY.contains(municipality.geometry, clickedPoint);

convexHull

function(aGeom) : OpenLayers.Geometryhelper# Smallest convex polygon containing the geometry.

Written as ExtjsUtils.GEOMETRY.convexHull

Smallest convex polygon containing the geometry. Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry.

Returns The convex hull (a Polygon; a Point/LineString for degenerate input).

var hull = ExtjsUtils.GEOMETRY.convexHull(multiPoint);

coveredBy

function(aGeom, bGeom) : Booleanhelper# Tells whether aGeom is covered by bGeom (every point of aGeom lies inside or on the boundary of bGeom); the inverse of covers.

Written as ExtjsUtils.GEOMETRY.coveredBy

Tells whether aGeom is covered by bGeom (every point of aGeom lies inside or on the boundary of bGeom); the inverse of covers. Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry to test.
bGeom OpenLayers.Geometry
Covering geometry.

Returns True when bGeom covers aGeom.

var fullyInside = ExtjsUtils.GEOMETRY.coveredBy(property.geometry, biome.geometry);

covers

function(aGeom, bGeom) : Booleanhelper# Tells whether aGeom covers bGeom: every point of bGeom lies inside or on the boundary of aGeom.

Written as ExtjsUtils.GEOMETRY.covers

Tells whether aGeom covers bGeom: every point of bGeom lies inside or on the boundary of aGeom. Like contains, but true as well for a point on the boundary. Requires the JSTS library.

aGeom OpenLayers.Geometry
Covering geometry.
bGeom OpenLayers.Geometry
Geometry to test.

Returns True when aGeom covers bGeom.

var onOrInside = ExtjsUtils.GEOMETRY.covers(municipality.geometry, clickedPoint);

crosses

function(aGeom, bGeom) : Booleanhelper# Tells whether the geometries cross: they share some but not all interior points and the intersection has a lower dimension than at least one of them (e.g. a line crossing a polygon boundary, two …

Written as ExtjsUtils.GEOMETRY.crosses

Tells whether the geometries cross: they share some but not all interior points and the intersection has a lower dimension than at least one of them (e.g. a line crossing a polygon boundary, two lines crossing at a point). Requires the JSTS library.

aGeom OpenLayers.Geometry
First geometry.
bGeom OpenLayers.Geometry
Second geometry.

Returns True when the geometries cross.

var roadCrossesRiver = ExtjsUtils.GEOMETRY.crosses(road.geometry, river.geometry);

difference

function(aGeom, bGeom) : OpenLayers.Geometry|nullhelper# Part of aGeom that is not covered by bGeom (A minus B).

Written as ExtjsUtils.GEOMETRY.difference

Part of aGeom that is not covered by bGeom (A minus B). Invalid polygons may throw a topology error — fix them with validate first. Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry to subtract from.
bGeom OpenLayers.Geometry
Geometry to subtract.

Returns The difference, or null when nothing remains.

var outsideReserve = ExtjsUtils.GEOMETRY.difference(property.geometry, reserve.geometry);

disjoint

function(aGeom, bGeom) : Booleanhelper# Tells whether the geometries have no point in common (the opposite of intersects).

Written as ExtjsUtils.GEOMETRY.disjoint

Tells whether the geometries have no point in common (the opposite of intersects). Requires the JSTS library.

aGeom OpenLayers.Geometry
First geometry.
bGeom OpenLayers.Geometry
Second geometry.

Returns True when the geometries are disjoint.

var farApart = ExtjsUtils.GEOMETRY.disjoint(a.geometry, b.geometry);

distance

function(aGeom, bGeom) : Numberhelper# Shortest distance between the two geometries (0 when they touch or intersect), in the units of their projection — map units for map geometries.

Written as ExtjsUtils.GEOMETRY.distance

Shortest distance between the two geometries (0 when they touch or intersect), in the units of their projection — map units for map geometries. Requires the JSTS library.

aGeom OpenLayers.Geometry
First geometry.
bGeom OpenLayers.Geometry
Second geometry.

Returns The minimum distance in projection units.

var d = ExtjsUtils.GEOMETRY.distance(clickedPoint, river.geometry);

equalsExact

function(aGeom, bGeom) : Booleanhelper# Tells whether the geometries are exactly equal: same type, same vertices in the same order (a strict, structural comparison).

Written as ExtjsUtils.GEOMETRY.equalsExact

Tells whether the geometries are exactly equal: same type, same vertices in the same order (a strict, structural comparison). Use equalsTopo for "same shape" and equalsNorm to ignore vertex order. Requires the JSTS library.

aGeom OpenLayers.Geometry
First geometry.
bGeom OpenLayers.Geometry
Second geometry.

Returns True when the geometries are structurally identical.

var unchanged = ExtjsUtils.GEOMETRY.equalsExact(original.geometry, edited.geometry);

equalsNorm

function(aGeom, bGeom) : Booleanhelper# Tells whether the geometries are exactly equal after normalizing both (canonical ring orientation, start vertex and part order), i.e. the same vertices regardless of their order.

Written as ExtjsUtils.GEOMETRY.equalsNorm

Tells whether the geometries are exactly equal after normalizing both (canonical ring orientation, start vertex and part order), i.e. the same vertices regardless of their order. Requires the JSTS library.

aGeom OpenLayers.Geometry
First geometry.
bGeom OpenLayers.Geometry
Second geometry.

Returns True when the normalized geometries are identical.

var sameRing = ExtjsUtils.GEOMETRY.equalsNorm(a.geometry, b.geometry);

equalsTopo

function(aGeom, bGeom) : Booleanhelper# Tells whether the geometries are topologically equal — they cover the same set of points, even with different vertices (e.g. a square and the same square with an extra collinear vertex).

Written as ExtjsUtils.GEOMETRY.equalsTopo

Tells whether the geometries are topologically equal — they cover the same set of points, even with different vertices (e.g. a square and the same square with an extra collinear vertex). Requires the JSTS library.

aGeom OpenLayers.Geometry
First geometry.
bGeom OpenLayers.Geometry
Second geometry.

Returns True when the geometries represent the same shape.

var sameShape = ExtjsUtils.GEOMETRY.equalsTopo(a.geometry, b.geometry);

findIntersecting

function(editedGeoms, candidateGeoms) : Array.<OpenLayers.Geometry>helper# Returns the candidates that intersect at least one of the edited geometries — e.g. to find which existing polygons a freshly drawn one overlaps before merging them.

Written as ExtjsUtils.GEOMETRY.findIntersecting

Returns the candidates that intersect at least one of the edited geometries — e.g. to find which existing polygons a freshly drawn one overlaps before merging them. The check is safeIntersects (topology errors are tolerated); null entries are ignored and the original OpenLayers objects are returned. Requires the JSTS library.

editedGeoms Array.<OpenLayers.Geometry>
Geometries to test against (e.g. the ones just drawn or modified).
candidateGeoms Array.<OpenLayers.Geometry>
Geometries to filter.

Returns The entries of candidateGeoms intersecting any of editedGeoms.

var touched = ExtjsUtils.GEOMETRY.findIntersecting([drawnFeature.geometry],
    layer.features.map(function(f) { return f.geometry; }));

geomJstsToOl2

function(jstsGeoms) : OpenLayers.Geometry|Array.<OpenLayers.Geometry>helper# Converts a JSTS geometry (or array of geometries) back to its OpenLayers equivalent, via a WKT round-trip.

Written as ExtjsUtils.GEOMETRY.geomJstsToOl2

Converts a JSTS geometry (or array of geometries) back to its OpenLayers equivalent, via a WKT round-trip. Empty JSTS geometries convert to null.

jstsGeoms Object|Array.<Object>
JSTS geometry or array of geometries to convert.

Returns The converted geometry (or array, matching the input shape); array entries are null for empty input geometries.

geomOl2ToJsts

function(olGeoms) : Object|Array.<Object>|nullhelper# Converts an OpenLayers geometry (or array of geometries) to its JSTS equivalent, via a WKT round-trip.

Written as ExtjsUtils.GEOMETRY.geomOl2ToJsts

Converts an OpenLayers geometry (or array of geometries) to its JSTS equivalent, via a WKT round-trip. Requires the JSTS library to already be loaded (see GEOMETRY.loadAdvancedGeometryLibrary / the ?options=geom URL option).

olGeoms OpenLayers.Geometry|Array.<OpenLayers.Geometry>
Geometry or array of geometries to convert.

Returns The converted JSTS geometry (or array, matching the input shape), or null if conversion failed.

getArea

function(aGeom) : Numberhelper# Area of a geometry (0 for points and lines), computed by JTS in the units of the geometry's projection — squared map units (Web Mercator meters, distorted away from the equator) for geometries taken from the map.

Written as ExtjsUtils.GEOMETRY.getArea

Area of a geometry (0 for points and lines), computed by JTS in the units of the geometry's projection — squared map units (Web Mercator meters, distorted away from the equator) for geometries taken from the map. Requires the JSTS library (see loadGeometryLibrary).

aGeom OpenLayers.Geometry
Geometry to measure.

Returns The area in squared projection units.

var areaM2 = ExtjsUtils.GEOMETRY.getArea(feature.geometry);

getCentroid

function(aGeom) : OpenLayers.Geometryhelper# Centroid (center of mass) of a geometry — may fall outside a concave polygon; use getInteriorPoint for a point guaranteed to be inside.

Written as ExtjsUtils.GEOMETRY.getCentroid

Centroid (center of mass) of a geometry — may fall outside a concave polygon; use getInteriorPoint for a point guaranteed to be inside. Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry.

Returns The centroid as an OpenLayers.Geometry.Point.

var center = ExtjsUtils.GEOMETRY.getCentroid(feature.geometry); // center.x, center.y

getEnvelope

function(aGeom) : OpenLayers.Geometryhelper# Bounding box of a geometry as a geometry: a rectangular Polygon (a Point or LineString for degenerate boxes).

Written as ExtjsUtils.GEOMETRY.getEnvelope

Bounding box of a geometry as a geometry: a rectangular Polygon (a Point or LineString for degenerate boxes). Use getEnvelopeInternal for the numeric bounds. Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry.

Returns The envelope geometry.

var bboxPolygon = ExtjsUtils.GEOMETRY.getEnvelope(feature.geometry);

getEnvelopeInternal

function(aGeom) : Objecthelper# Numeric bounding box of a geometry.

Written as ExtjsUtils.GEOMETRY.getEnvelopeInternal

Numeric bounding box of a geometry. Unlike the other operations this returns the raw JTS object, a jsts.geom.Envelope with getMinX(), getMinY(), getMaxX(), getMaxY(), getWidth(), getHeight(); for an OpenLayers bounds object use geometry.getBounds() instead. Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry.

Returns A jsts.geom.Envelope.

var env = ExtjsUtils.GEOMETRY.getEnvelopeInternal(feature.geometry); // env.getMinX()

getInteriorPoint

function(aGeom) : OpenLayers.Geometryhelper# A point guaranteed to lie inside the geometry (inside a polygon, on a line, one of the points of a multipoint) — the right anchor for a label or a popup, unlike the centroid.

Written as ExtjsUtils.GEOMETRY.getInteriorPoint

A point guaranteed to lie inside the geometry (inside a polygon, on a line, one of the points of a multipoint) — the right anchor for a label or a popup, unlike the centroid. Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry.

Returns An OpenLayers.Geometry.Point inside the geometry.

var anchor = ExtjsUtils.GEOMETRY.getInteriorPoint(feature.geometry);

getLength

function(aGeom) : Numberhelper# Length of a line, or perimeter of a polygon (0 for points), in the units of the geometry's projection.

Written as ExtjsUtils.GEOMETRY.getLength

Length of a line, or perimeter of a polygon (0 for points), in the units of the geometry's projection. Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry to measure.

Returns The length in projection units.

var perimeter = ExtjsUtils.GEOMETRY.getLength(feature.geometry);

getNumGeometries

function(aGeom) : Numberhelper# Number of component geometries: the parts of a multi-geometry or collection, 1 for a simple geometry.

Written as ExtjsUtils.GEOMETRY.getNumGeometries

Number of component geometries: the parts of a multi-geometry or collection, 1 for a simple geometry. Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry.

Returns How many parts the geometry has.

var parts = ExtjsUtils.GEOMETRY.getNumGeometries(multiPolygon);

getSRID

function(aGeom) : Numberhelper# Spatial reference id stored on the JTS geometry.

Written as ExtjsUtils.GEOMETRY.getSRID

Spatial reference id stored on the JTS geometry. Because every operation rebuilds the JTS geometry from WKT, this is always the JTS default (0): OpenLayers geometries carry no SRID and there is no way to set one through this API.

aGeom OpenLayers.Geometry
Geometry.

Returns The SRID (0).

ExtjsUtils.GEOMETRY.getSRID(feature.geometry); // 0

getUserData

function(aGeom) : *helper# User data stored on the JTS geometry.

Written as ExtjsUtils.GEOMETRY.getUserData

User data stored on the JTS geometry. Because every operation rebuilds the JTS geometry from WKT, this is always null: keep your data on the OpenLayers feature (feature.attributes) instead.

aGeom OpenLayers.Geometry
Geometry.

Returns The user data (null).

ExtjsUtils.GEOMETRY.getUserData(feature.geometry); // null

intersection

function(aGeom, bGeom) : OpenLayers.Geometry|nullhelper# Common part of the two geometries (A and B).

Written as ExtjsUtils.GEOMETRY.intersection

Common part of the two geometries (A and B). Invalid polygons may throw a topology error — fix them with validate first. Requires the JSTS library.

aGeom OpenLayers.Geometry
First geometry.
bGeom OpenLayers.Geometry
Second geometry.

Returns The intersection, or null when the geometries do not overlap.

var overlap = ExtjsUtils.GEOMETRY.intersection(property.geometry, reserve.geometry);

intersects

function(aGeom, bGeom) : Booleanhelper# Tells whether the geometries share at least one point (touching counts).

Written as ExtjsUtils.GEOMETRY.intersects

Tells whether the geometries share at least one point (touching counts). Throws a topology error on invalid input — safeIntersects (on JSTS geometries) or findIntersecting tolerate that. Requires the JSTS library.

aGeom OpenLayers.Geometry
First geometry.
bGeom OpenLayers.Geometry
Second geometry.

Returns True when the geometries intersect.

var hit = ExtjsUtils.GEOMETRY.intersects(drawnPolygon, feature.geometry);

isGeometryCollection

function(aGeom) : Booleanhelper# Tells whether the geometry is a heterogeneous GeometryCollection (not a MultiPolygon/ MultiLineString/MultiPoint).

Written as ExtjsUtils.GEOMETRY.isGeometryCollection

Tells whether the geometry is a heterogeneous GeometryCollection (not a MultiPolygon/ MultiLineString/MultiPoint). Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry.

Returns True for a GeometryCollection.

if (ExtjsUtils.GEOMETRY.isGeometryCollection(geom)) geom = geom.components[0];

isJstsGeometry

function(obj) : Booleanhelper# Tells whether a value is a JSTS geometry (duck-typed on getGeometryType, getBoundary and getEnvelopeInternal), as opposed to an OpenLayers geometry.

Written as ExtjsUtils.GEOMETRY.isJstsGeometry

Tells whether a value is a JSTS geometry (duck-typed on getGeometryType, getBoundary and getEnvelopeInternal), as opposed to an OpenLayers geometry. Useful when a function accepts both, e.g. before deciding whether to call geomJstsToOl2.

obj *
Value to check.

Returns True for a JSTS geometry object.

var ol = ExtjsUtils.GEOMETRY.isJstsGeometry(g) ? ExtjsUtils.GEOMETRY.geomJstsToOl2(g) : g;

isRectangle

function(aGeom) : Booleanhelper# Tells whether the geometry is an axis-aligned rectangle (a polygon with 5 vertices matching its envelope).

Written as ExtjsUtils.GEOMETRY.isRectangle

Tells whether the geometry is an axis-aligned rectangle (a polygon with 5 vertices matching its envelope). Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry.

Returns True for a rectangle.

var isBox = ExtjsUtils.GEOMETRY.isRectangle(drawnPolygon);

isSimple

function(aGeom) : Booleanhelper# Tells whether the geometry is simple in the OGC sense — no self-intersections or repeated points (a line that crosses itself is not simple).

Written as ExtjsUtils.GEOMETRY.isSimple

Tells whether the geometry is simple in the OGC sense — no self-intersections or repeated points (a line that crosses itself is not simple). Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry.

Returns True when the geometry is simple.

if (!ExtjsUtils.GEOMETRY.isSimple(line)) ExtjsUtils.ALERTIFY.log("The line crosses itself.");

isTopologyError

function(ex) : Booleanhelper# Tells whether an exception thrown by a geometry operation is a JTS TopologyException (invalid ring, self-intersection...), the kind of error that a zero-width buffer or validate usually fixes, as …

Written as ExtjsUtils.GEOMETRY.isTopologyError

Tells whether an exception thrown by a geometry operation is a JTS TopologyException (invalid ring, self-intersection...), the kind of error that a zero-width buffer or validate usually fixes, as opposed to a programming error that should propagate.

ex Error|Object
The caught exception (anything falsy returns false).

Returns True when the exception is a topology error.

try {
    result = ExtjsUtils.GEOMETRY.intersection(a, b);
} catch (ex) {
    if (!ExtjsUtils.GEOMETRY.isTopologyError(ex)) throw ex;
    result = ExtjsUtils.GEOMETRY.intersection(ExtjsUtils.GEOMETRY.validate(a, false), ExtjsUtils.GEOMETRY.validate(b, false));
}

isValid

function(aGeom) : Booleanhelper# Tells whether the geometry is valid in the OGC sense (closed rings, no self-intersecting rings, holes inside the shell...).

Written as ExtjsUtils.GEOMETRY.isValid

Tells whether the geometry is valid in the OGC sense (closed rings, no self-intersecting rings, holes inside the shell...). Invalid polygons make the set operations throw topology errors — fix them with validate. Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry.

Returns True when the geometry is valid.

var geom = ExtjsUtils.GEOMETRY.isValid(drawn) ? drawn : ExtjsUtils.GEOMETRY.validate(drawn, false);

loadAdvancedGeometryLibrary

function(callback) : Promise.<Boolean>helper# Loads the JSTS geometry library (/theme/app/js/jsts.min.js) once and resolves when it is available; every other GEOMETRY operation throws until it is loaded (the ?options=geom URL option loads it at startup).

Written as ExtjsUtils.GEOMETRY.loadAdvancedGeometryLibrary

Loads the JSTS geometry library (/theme/app/js/jsts.min.js) once and resolves when it is available; every other GEOMETRY operation throws until it is loaded (the ?options=geom URL option loads it at startup). An optional callback runs right after the load; when it returns a promise the returned promise waits for it. Safe to call several times.

callback function
Function to run once the library is loaded (may be async).

Returns Resolves to true when the library (and the callback) finished; rejects when the script cannot be loaded.

await ExtjsUtils.GEOMETRY.loadAdvancedGeometryLibrary();
var merged = ExtjsUtils.GEOMETRY.unionAll(features.map(function(f) { return f.geometry; }));

loadGeometryLibrary

function(callback) : Promise.<Boolean>helper# Alias of GEOMETRY.loadAdvancedGeometryLibrary: loads the JSTS library once and resolves when the geometry operations can be used.

Written as ExtjsUtils.GEOMETRY.loadGeometryLibrary

Alias of GEOMETRY.loadAdvancedGeometryLibrary: loads the JSTS library once and resolves when the geometry operations can be used.

callback function
Function to run once the library is loaded (may be async).

Returns Resolves to true when the library is loaded; rejects on a load failure.

ExtjsUtils.GEOMETRY.loadGeometryLibrary(function() {
    var hull = ExtjsUtils.GEOMETRY.convexHull(feature.geometry);
});

merge_intersects

function(ol2Geometries, mergeInvalid) : Array.<OpenLayers.Geometry>helper# Merges every set of mutually-intersecting geometries in the input array into a single geometry each, leaving non-intersecting geometries untouched.

Written as ExtjsUtils.GEOMETRY.merge_intersects

Merges every set of mutually-intersecting geometries in the input array into a single geometry each, leaving non-intersecting geometries untouched. Geometries are first clustered by bounding-box overlap (cheap) before the exact JSTS intersection/union work runs only within each cluster.

ol2Geometries Array.<OpenLayers.Geometry>
Geometries to merge.
mergeInvalid Boolean
When false, two invalid geometries in the same cluster are not merged with each other.

Returns The input geometries, with intersecting groups replaced by their union.

overlaps

function(aGeom, bGeom) : Booleanhelper# Tells whether the geometries overlap: same dimension, they share some interior points but neither contains the other (two partially overlapping polygons).

Written as ExtjsUtils.GEOMETRY.overlaps

Tells whether the geometries overlap: same dimension, they share some interior points but neither contains the other (two partially overlapping polygons). Requires the JSTS library.

aGeom OpenLayers.Geometry
First geometry.
bGeom OpenLayers.Geometry
Second geometry.

Returns True when the geometries partially overlap.

var partial = ExtjsUtils.GEOMETRY.overlaps(property.geometry, reserve.geometry);

safeIntersects

function(jstsA, jstsB) : Booleanhelper# Checks whether two JSTS geometries intersect, retrying with a zero-width buffer if the direct check throws a topology error.

Written as ExtjsUtils.GEOMETRY.safeIntersects

Checks whether two JSTS geometries intersect, retrying with a zero-width buffer if the direct check throws a topology error. Returns false (instead of throwing) if the retry also fails.

jstsA Object
First JSTS geometry.
jstsB Object
Second JSTS geometry.

Returns True if the geometries intersect.

safeSymDifference

function(jstsA, jstsB) : Objecthelper# Symmetric difference of two JSTS geometries (the area covered by exactly one of the two, i.e. union minus intersection), retrying with a zero-width buffer if the direct operation throws a topology error.

Written as ExtjsUtils.GEOMETRY.safeSymDifference

Symmetric difference of two JSTS geometries (the area covered by exactly one of the two, i.e. union minus intersection), retrying with a zero-width buffer if the direct operation throws a topology error.

jstsA Object
First JSTS geometry.
jstsB Object
Second JSTS geometry.

Returns The symmetric-difference JSTS geometry.

safeUnion

function(jstsA, jstsB) : Objecthelper# Union of two JSTS geometries, retrying with a zero-width buffer (a common fix for self-intersecting/invalid rings) if the direct union throws a topology error.

Written as ExtjsUtils.GEOMETRY.safeUnion

Union of two JSTS geometries, retrying with a zero-width buffer (a common fix for self-intersecting/invalid rings) if the direct union throws a topology error.

jstsA Object
First JSTS geometry.
jstsB Object
Second JSTS geometry.

Returns The unioned JSTS geometry.

symDifference

function(aGeom, bGeom) : OpenLayers.Geometry|nullhelper# Symmetric difference of the two geometries: the parts covered by exactly one of them (union minus intersection).

Written as ExtjsUtils.GEOMETRY.symDifference

Symmetric difference of the two geometries: the parts covered by exactly one of them (union minus intersection). Invalid polygons may throw a topology error — fix them with validate first. Requires the JSTS library.

aGeom OpenLayers.Geometry
First geometry.
bGeom OpenLayers.Geometry
Second geometry.

Returns The symmetric difference, or null when the geometries are equal.

var changed = ExtjsUtils.GEOMETRY.symDifference(before.geometry, after.geometry);

toText

function(aGeom) : Stringhelper# WKT (Well-Known Text) representation of the geometry, e.g. POLYGON ((...)), as written by JTS.

Written as ExtjsUtils.GEOMETRY.toText

WKT (Well-Known Text) representation of the geometry, e.g. POLYGON ((...)), as written by JTS. Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry.

Returns The WKT text.

var wkt = ExtjsUtils.GEOMETRY.toText(feature.geometry);

touches

function(aGeom, bGeom) : Booleanhelper# Tells whether the geometries touch: they share boundary points only, with no interior point in common (two neighbouring polygons sharing an edge).

Written as ExtjsUtils.GEOMETRY.touches

Tells whether the geometries touch: they share boundary points only, with no interior point in common (two neighbouring polygons sharing an edge). Requires the JSTS library.

aGeom OpenLayers.Geometry
First geometry.
bGeom OpenLayers.Geometry
Second geometry.

Returns True when the geometries touch without overlapping.

var neighbours = ExtjsUtils.GEOMETRY.touches(a.geometry, b.geometry);

union

function(aGeom, bGeom) : OpenLayers.Geometryhelper# Union of two geometries.

Written as ExtjsUtils.GEOMETRY.union

Union of two geometries. Accepts and returns OpenLayers geometries (JSTS conversion is handled internally).

aGeom OpenLayers.Geometry
First geometry.
bGeom OpenLayers.Geometry
Second geometry.

Returns The unioned geometry.

unionAll

function(geometries, options) : OpenLayers.Geometry|Object|nullhelper# Unions many geometries at once (OpenLayers or JSTS objects, mixed), skipping null and empty entries.

Written as ExtjsUtils.GEOMETRY.unionAll

Unions many geometries at once (OpenLayers or JSTS objects, mixed), skipping null and empty entries. Uses the JTS cascaded union, retrying with a zero-width buffer and then pairwise safeUnion when invalid geometries make it fail. Requires the JSTS library.

geometries Array
OL or JSTS geometry objects.
options Object
{returnJsts: true} returns the JSTS geometry instead of converting it back to OpenLayers.

Returns The union (OpenLayers geometry, or JSTS when returnJsts), or null when there was nothing to union.

var merged = ExtjsUtils.GEOMETRY.unionAll(layer.features.map(function(f) { return f.geometry; }));
if (merged) layer.addFeatures([new OpenLayers.Feature.Vector(merged)]);

validate

function(olGeom, splitMultipolygon) : OpenLayers.Geometry|Array.<OpenLayers.Geometry>|nullhelper# Fixes an invalid OpenLayers geometry (self-intersections, etc.) using JSTS, optionally splitting a fixed multipolygon back into separate polygon geometries.

Written as ExtjsUtils.GEOMETRY.validate

Fixes an invalid OpenLayers geometry (self-intersections, etc.) using JSTS, optionally splitting a fixed multipolygon back into separate polygon geometries.

olGeom OpenLayers.Geometry
Geometry to validate/fix.
splitMultipolygon Boolean
Split a resulting MultiPolygon into individual Polygon geometries instead of returning it as one MultiPolygon.

Returns The original geometry if already valid, a fixed geometry otherwise, an array when split, or null if the geometry couldn't be fixed.

within

function(aGeom, bGeom) : Booleanhelper# Tells whether aGeom lies within bGeom (the inverse of contains: every point of aGeom is inside bGeom and their interiors share a point).

Written as ExtjsUtils.GEOMETRY.within

Tells whether aGeom lies within bGeom (the inverse of contains: every point of aGeom is inside bGeom and their interiors share a point). Requires the JSTS library.

aGeom OpenLayers.Geometry
Geometry to test.
bGeom OpenLayers.Geometry
Container geometry.

Returns True when aGeom is within bGeom.

var insideState = ExtjsUtils.GEOMETRY.within(property.geometry, state.geometry);

HideInterface · keep visible when hidden

HideInterface1 entry
Registers components that must stay visible when the interface is hidden.
Usage: ExtjsUtils.HideInterface

add

function(comp) : *helper# Registers an Ext component (or config/element) with the "hide interface" tool — the button that hides the map's panels to leave only the image — so that the component is toggled together with the …

Written as ExtjsUtils.HideInterface.add

Registers an Ext component (or config/element) with the "hide interface" tool — the button that hides the map's panels to leave only the image — so that the component is toggled together with the platform's own interface. An id is assigned to the component when it has none. Returns the same object, so it can be used inline while building a config. Does nothing (returns undefined) when the HideInterface plugin is not loaded.

comp Ext.Component|Ext.Element|Object
Any Ext component, element or component config.

Returns The same comp, now with an id, or undefined when the tool is unavailable.

var panel = new Ext.Panel(ExtjsUtils.HideInterface.add({ html: "Legend", renderTo: Ext.getBody() }));

HIGHCHART, REGEX · charts and strings

Extjs3 entries
Chart lookup (ExtjsUtils.HIGHCHART) and string helpers (ExtjsUtils.REGEX). The interface itself is built with Ext JS 3.4.
View the full Extjs API 3.4 click here.
*Only the functions which where used in CSR projects are listed here.

escapeRegExp

function(str) : Stringhelper# Escapes the regular expression special characters of a string, so a user-typed value can be used inside new RegExp(...) literally.

Written as ExtjsUtils.REGEX.escapeRegExp

Escapes the regular expression special characters of a string, so a user-typed value can be used inside new RegExp(...) literally. The real call path is ExtjsUtils.REGEX.escapeRegExp(str). Escaped characters are '-', '[', ']', '/', '{', '}', '(', ')', '*', '+', '?', '.', '\', '^', '$', '|'.

str String
Expression to be escaped.

Returns String with all regex characters escaped.

var re = new RegExp(ExtjsUtils.REGEX.escapeRegExp("CSR:layer.name (v2)"), "i");

getHighchartById

function(id) : Object# Gets a Highcharts chart instance by the id of the DOM element it was rendered into (renderTo), so query code can update a chart created in descriptionHtml after the data arrives.

Gets a Highcharts chart instance by the id of the DOM element it was rendered into (renderTo), so query code can update a chart created in descriptionHtml after the data arrives. The real call path is ExtjsUtils.HIGHCHART.getById(id).

id String
Id of the DOM element the chart was rendered into.

Returns The Highcharts chart object, or null when no chart uses that element.

var chart = ExtjsUtils.HIGHCHART.getById("highchart-01");
if (chart) chart.series[0].setData([10, 20, 30]);

replaceAll

function(str, search, replacement) : String|Array.<String>helper# Replaces every occurrence of the plain substring search (no regular expression) by replacement.

Written as ExtjsUtils.REGEX.replaceAll

Replaces every occurrence of the plain substring search (no regular expression) by replacement. When str is an array of strings every entry is replaced in place and the same array is returned. The real call path is ExtjsUtils.REGEX.replaceAll(...).

str String|Array.<String>
A string, or an array of strings, whose terms are replaced.
search String
Substring to search for (literal, not a regex).
replacement String
Text that replaces each occurrence.

Returns The replaced string, or the same array when str is an array.

ExtjsUtils.REGEX.replaceAll("a-b-c", "-", "_"); // "a_b_c"
ExtjsUtils.REGEX.replaceAll(["x.y", "z.w"], ".", "/"); // ["x/y", "z/w"]

HTML · elements, colours, pixels

HTMLUtils18 entries
HTML, image and colour helpers: iframe detection, element positions, colour conversions and pixel reads.
Usage: ExtjsUtils.HTML

cache

Object# Cache of image contents keyed by URL: each entry is the base64 data URL of an image already loaded once (filled by the onLoad handler getReusableImg writes).

Written as ExtjsUtils.HTML.cache

Cache of image contents keyed by URL: each entry is the base64 data URL of an image already loaded once (filled by the onLoad handler getReusableImg writes). Query code may also fill it directly with getImageBase64.

ExtjsUtils.HTML.cache['/theme/app/img/legend.png'] = ExtjsUtils.HTML.getImageBase64(imgElement);

canvasWebGL

HTMLCanvasElement# The single off-screen <canvas> reused by every WebGL pixel read (getWebGLContext), so a context is not created per call.

Written as ExtjsUtils.HTML.canvasWebGL

The single off-screen <canvas> reused by every WebGL pixel read (getWebGLContext), so a context is not created per call.

var gl = ExtjsUtils.HTML.canvasWebGL.getContext('webgl');

changeImgColor

function(img, fromColor, toColor, canvas, originalData)helper# Replaces one colour of an image by another and writes the result back into the image (img.src becomes a data URL drawn on canvas).

Written as ExtjsUtils.HTML.changeImgColor

Replaces one colour of an image by another and writes the result back into the image (img.src becomes a data URL drawn on canvas). The originalData array keeps the untouched pixels: it is filled on the first call (pass an empty array) and, on later calls with the same array, the image is restored from it before the new colour is applied — so repeated calls with different toColors do not accumulate. Used to highlight a legend class in a legend image.

img HTMLImageElement
Image to modify (loaded and CORS-readable).
fromColor Array.<Number>
[r, g, b] colour to replace (exact match).
toColor Array.<Number>
[r, g, b] replacement colour.
canvas HTMLCanvasElement
Canvas used to redraw the image.
originalData Array.<Number>
Array holding the original pixel bytes; pass [] on the first call and the same array afterwards.
var original = [];
var canvas = document.createElement('canvas');
ExtjsUtils.HTML.changeImgColor(legendImg, [0, 128, 0], [255, 0, 0], canvas, original); // green -> red
ExtjsUtils.HTML.changeImgColor(legendImg, [0, 128, 0], [0, 0, 255], canvas, original); // green -> blue (red is gone)

colorStyleToRgb

function(color) : Array.<String>helper# Converts any colour the browser understands ("red", "#f80", "rgb(255, 136, 0)", "hsl(...)"...) into its RGB components, by letting the browser compute the style of a temporary element.

Written as ExtjsUtils.HTML.colorStyleToRgb

Converts any colour the browser understands ("red", "#f80", "rgb(255, 136, 0)", "hsl(...)"...) into its RGB components, by letting the browser compute the style of a temporary element. The components come back as strings (e.g. ["255", "136", "0"]).

color String
The colour in any CSS notation.

Returns The [r, g, b] components as strings (a fourth alpha component may be present for translucent colours).

ExtjsUtils.HTML.colorStyleToRgb('orange'); // ["255", "165", "0"]

getAbsolutePointFromLatLong

function(lonLat) : Objecthelper# Returns the page position (pixels relative to the document) where a map coordinate is currently drawn: the map pixel of the coordinate plus the offset of the map viewport.

Written as ExtjsUtils.HTML.getAbsolutePointFromLatLong

Returns the page position (pixels relative to the document) where a map coordinate is currently drawn: the map pixel of the coordinate plus the offset of the map viewport. The coordinate must be in the map projection. Use it to place HTML (a popup, a marker image) over a map location.

lonLat OpenLayers.LonLat
The map coordinate, in the map projection.

Returns {x, y} page position in pixels.

var lonLat = new OpenLayers.LonLat(-44.0, -19.9).transform("EPSG:4326", app.mapPanel.map.getProjection());
var point = ExtjsUtils.HTML.getAbsolutePointFromLatLong(lonLat);
popup.style.left = point.x + 'px';
popup.style.top = point.y + 'px';

getAbsolutePointFromMouseEvent

function(mouseEvt) : Objecthelper# Returns the page position of a mouse event (pageX/pageY, or clientX/Y plus the body scroll on old IE), never negative.

Written as ExtjsUtils.HTML.getAbsolutePointFromMouseEvent

Returns the page position of a mouse event (pageX/pageY, or clientX/Y plus the body scroll on old IE), never negative. This is the absolutePoint expected by LAYER.getLayerColorAtPoint and getRelativePositionToPoint.

mouseEvt MouseEvent
The DOM mouse event.

Returns {x, y} page position in pixels.

ExtjsUtils.addDomListener(window, 'mousemove', function(evt) {
  var point = ExtjsUtils.HTML.getAbsolutePointFromMouseEvent(evt);
  popup.style.left = (point.x + 10) + 'px';
  popup.style.top = (point.y + 10) + 'px';
});

getImageBase64

function(img) : Stringhelper# Returns the content of a loaded image as a PNG data URL (data:image/png;base64,...), drawing it on a reused 2D canvas.

Written as ExtjsUtils.HTML.getImageBase64

Returns the content of a loaded image as a PNG data URL (data:image/png;base64,...), drawing it on a reused 2D canvas. The image must be loaded and CORS-readable.

img HTMLImageElement
Loaded image element.

Returns The image as a base64 PNG data URL.

var dataUrl = ExtjsUtils.HTML.getImageBase64(document.getElementById('legend-img'));

getImageDataWithAlpha

function(img, fromX, fromY, width, height) : Uint8Arrayhelper# Copies a rectangle of an image as raw RGBA bytes through WebGL, keeping the exact alpha values (a 2D canvas returns alpha-premultiplied colours).

Written as ExtjsUtils.HTML.getImageDataWithAlpha

Copies a rectangle of an image as raw RGBA bytes through WebGL, keeping the exact alpha values (a 2D canvas returns alpha-premultiplied colours). Defaults to the whole image.

img HTMLImageElement
Loaded, CORS-readable image.
fromX Number
Column of the first pixel to copy.
fromY Number
Row of the first pixel to copy.
width Number
Width of the rectangle, in pixels.
height Number
Height of the rectangle, in pixels.

Returns 4 * width * height bytes: R, G, B, A per pixel, row by row.

var pixels = ExtjsUtils.HTML.getImageDataWithAlpha(tileImage); // whole tile
var transparentCount = 0;
for (var i = 3; i < pixels.length; i += 4) if (pixels[i] === 0) transparentCount++;

getIntermediateColor

function(color1, color2, weight) : Array.<Number>helper# Blends two colours with a weighted average: weight goes to the first colour and 1 - weight to the second.

Written as ExtjsUtils.HTML.getIntermediateColor

Blends two colours with a weighted average: weight goes to the first colour and 1 - weight to the second. Each colour may be an [r, g, b] array or any CSS colour string (converted with colorStyleToRgb). Handy to build a gradient between two legend colours.

color1 Array.<Number>|String
First colour.
color2 Array.<Number>|String
Second colour.
weight Number
Weight of the first colour, from 0 (only color2) to 1 (only color1).

Returns The blended colour as [r, g, b] (rounded 0-255 numbers).

var mid = ExtjsUtils.HTML.getIntermediateColor('#ff0000', '#0000ff', 0.5); // [128, 0, 128]
el.style.backgroundColor = ExtjsUtils.HTML.rgbToColorStyle(mid);

getPixelColorAtWebGL

function(x, y, img, xWidth, yHeight) : Uint8Arrayhelper# Reads the pixels of an image through WebGL (so the RGBA values are not alpha-premultiplied as a 2D canvas would make them): a window of xWidth x yHeight pixels whose top-left corner is (x, y), …

Written as ExtjsUtils.HTML.getPixelColorAtWebGL

Reads the pixels of an image through WebGL (so the RGBA values are not alpha-premultiplied as a 2D canvas would make them): a window of xWidth x yHeight pixels whose top-left corner is (x, y), defaulting to a single pixel. The image must be loaded and CORS-readable (map tiles are).

x Number
Column of the (first) pixel, relative to the image.
y Number
Row of the (first) pixel, relative to the image.
img HTMLImageElement
Image to read from.
xWidth Number
Width of the window to read, in pixels.
yHeight Number
Height of the window to read, in pixels.

Returns 4 * xWidth * yHeight bytes: R, G, B, A for each pixel, row by row.

var rgba = ExtjsUtils.HTML.getPixelColorAtWebGL(10, 20, tileImage); // Uint8Array [r, g, b, a]

getPixelColorLimitsWebGL

function(img, limits, bbox) : Uint8Arrayhelper# Reads, through WebGL, only the pixels of an image that fall inside per-row x-spans — the limits/bounds produced by LAYER.getLayerTilesFeatureIntersects for a tile.

Written as ExtjsUtils.HTML.getPixelColorLimitsWebGL

Reads, through WebGL, only the pixels of an image that fall inside per-row x-spans — the limits/bounds produced by LAYER.getLayerTilesFeatureIntersects for a tile. limits is indexed by row and holds the [start, end, start, end, ...] columns to keep (closed intervals); e.g. [[], [1, 3], [], [5, 5]] keeps columns 1-3 of row 1 and column 5 of row 3.

img HTMLImageElement
Image (tile) to read from.
limits Array.<Array.<Number>>
Per-row x-spans to keep, as described above.
bbox OpenLayers.Bounds
Row/column range to scan: left/right the columns, top/bottom the rows.

Returns The R, G, B, A bytes of the kept pixels, concatenated.

ExtjsUtils.LAYER.getLayerTilesFeatureIntersects(layer, feature).forEach(function(tile) {
  var rgba = ExtjsUtils.HTML.getPixelColorLimitsWebGL(tile.img, tile.limits, tile.bounds);
  console.log(rgba.length / 4, 'pixels inside the polygon on this tile');
});

getRelativePositionToPoint

function(absolutePoint, element) : Array.<Number>helper# Converts a page position into a position relative to an element's top-left corner: x is positive to the right of the element's left edge (negative to the left), y is positive below its top edge (negative above).

Written as ExtjsUtils.HTML.getRelativePositionToPoint

Converts a page position into a position relative to an element's top-left corner: x is positive to the right of the element's left edge (negative to the left), y is positive below its top edge (negative above). Defaults to the map viewport, which turns a mouse page position into a map pixel.

absolutePoint Object
Page position {x, y} in pixels (see getAbsolutePointFromMouseEvent).
element HTMLElement|Ext.Element
Reference element; defaults to the map viewport div.

Returns [x, y] relative to the element.

var point = ExtjsUtils.HTML.getAbsolutePointFromMouseEvent(evt);
var mapPixel = ExtjsUtils.HTML.getRelativePositionToPoint(point); // [x, y] inside the map
var lonLat = app.mapPanel.map.getLonLatFromPixel({ x: mapPixel[0], y: mapPixel[1] });

getReusableImg

function(url, attributes) : Stringhelper# Builds the HTML of an <img> tag meant to be loaded only once: the src is the base64 content kept in HTML.cache when the URL was already loaded, otherwise the URL itself plus an onLoad handler …

Written as ExtjsUtils.HTML.getReusableImg

Builds the HTML of an <img> tag meant to be loaded only once: the src is the base64 content kept in HTML.cache when the URL was already loaded, otherwise the URL itself plus an onLoad handler that stores the image in the cache for the next call. Extra attributes are appended verbatim. Note: the current implementation reads an undefined HTML.urlCache before appending the onLoad handler, so calling it throws a TypeError today; no production query uses it.

url String
URL of the image.
attributes String
Extra attributes to append to the tag, e.g. ' width="16" class="icon"'.

Returns The <img ...> HTML string.

var html = ExtjsUtils.HTML.getReusableImg('/theme/app/img/legend.png', ' class="legend-icon"');

getWebGLContext

function() : WebGLRenderingContexthelper# Returns the WebGL rendering context of the shared canvasWebGL canvas (trying the "webgl" and then the legacy "experimental-webgl" context names).

Written as ExtjsUtils.HTML.getWebGLContext

Returns the WebGL rendering context of the shared canvasWebGL canvas (trying the "webgl" and then the legacy "experimental-webgl" context names). null when the browser has no WebGL support — see CHECK.browserSupported.

Returns The WebGL context, or null when unavailable.

var gl = ExtjsUtils.HTML.getWebGLContext();
if (!gl) ExtjsUtils.ALERTIFY.alert('This browser cannot read map pixels');

hexToRgb

function(hex) : Array.<Number>|nullhelper# Converts a 6-digit hexadecimal colour ("#rrggbb", the # being optional) into an [r, g, b] array of 0-255 numbers.

Written as ExtjsUtils.HTML.hexToRgb

Converts a 6-digit hexadecimal colour ("#rrggbb", the # being optional) into an [r, g, b] array of 0-255 numbers. Short (#rgb) or invalid strings give null.

hex String
The colour in hexadecimal notation.

Returns [r, g, b], or null when the string is not a 6-digit hex colour.

ExtjsUtils.HTML.hexToRgb('#ff8800'); // [255, 136, 0]

isInsideIframe

function() : Booleanhelper# Tells whether the map page is embedded in another page (an iframe), which is how most tenant sites show a query.

Written as ExtjsUtils.HTML.isInsideIframe

Tells whether the map page is embedded in another page (an iframe), which is how most tenant sites show a query. Cross-origin embedding that blocks the check also counts as embedded. Use it to hide interface parts that only make sense when the map is opened on its own.

Returns true when running inside an iframe, false when opened directly.

if (ExtjsUtils.HTML.isInsideIframe()) ExtjsUtils.CSS.defineClass('#topbar', 'display: none;');

offset

function(element) : Objecthelper# Returns the position of an element relative to the whole page (document), taking the current scroll into account — unlike getBoundingClientRect, which is relative to the viewport.

Written as ExtjsUtils.HTML.offset

Returns the position of an element relative to the whole page (document), taking the current scroll into account — unlike getBoundingClientRect, which is relative to the viewport. Accepts a DOM element or an Ext.Element.

element HTMLElement|Ext.Element
Element to measure.

Returns {top, left, right} — page offsets in pixels of the element's top, left and right edges.

var pos = ExtjsUtils.HTML.offset(app.mapPanel.map.viewPortDiv);
console.log('map starts at', pos.left, pos.top);

rgbToColorStyle

function(color) : Stringhelper# Formats an [r, g, b] colour as the CSS string "rgb(r, g, b)".

Written as ExtjsUtils.HTML.rgbToColorStyle

Formats an [r, g, b] colour as the CSS string "rgb(r, g, b)". The usual companion of the legend entries (layer.getLegendEntries()[i].color is an [r, g, b] array) when painting HTML with a legend colour.

color Array.<Number>
The colour components [r, g, b] (a fourth element is ignored).

Returns The "rgb(r, g, b)" CSS colour.

var entry = layer.getLegendEntries()[0];
html += '<span style="color:' + ExtjsUtils.HTML.rgbToColorStyle(entry.color) + '">' + entry.title + '</span>';

INTROJS · guided tours

INTROJS5 entries
Guided tours (intro.js) for the interface.
Usage: ExtjsUtils.INTROJS

getStep

function(element, txt, position, step, tooltipClass, highlightClass, disableInteraction) : Objecthelper# Builds one Intro.js step object for loadAndRun.

Written as ExtjsUtils.INTROJS.getStep

Builds one Intro.js step object for loadAndRun. Only the fields that were given are set (position defaults to 'auto').

element HTMLElement
Element to highlight; omit for a step without a target (centered message).
txt String
Text/HTML shown in the step tooltip.
position String
Tooltip position: top, left, right, bottom, bottom-left-aligned, bottom-middle-aligned, bottom-right-aligned or auto.
step Number
Explicit step number (order); 0 is accepted.
tooltipClass String
Extra CSS class for the tooltip.
highlightClass String
Extra CSS class for the highlighted element.
disableInteraction Boolean
True to block clicks on the highlighted element during the step.

Returns The Intro.js step object.

var step = ExtjsUtils.INTROJS.getStep(document.getElementById("chart"), "Click a bar to filter the map.", "top");

getStepsFromDOM

function(parent) : Array.<Object>helper# Collects tour steps from the DOM: every visible element (larger than 13x13 px) with a data-intro attribute becomes a step, reading data-position, data-step, data-tooltipClass and data-highlightClass as well.

Written as ExtjsUtils.INTROJS.getStepsFromDOM

Collects tour steps from the DOM: every visible element (larger than 13x13 px) with a data-intro attribute becomes a step, reading data-position, data-step, data-tooltipClass and data-highlightClass as well. This is what loadAndRun does when no steps are given.

parent HTMLElement|Document
Root element to search under.

Returns The step objects, in DOM order.

var steps = ExtjsUtils.INTROJS.getStepsFromDOM(document.getElementById("mypanel"));

loadAndRun

function(steps, exitOnOverlayClick, startFunction)helper# Loads Intro.js (script and stylesheets, once) and starts a guided tour.

Written as ExtjsUtils.INTROJS.loadAndRun

Loads Intro.js (script and stylesheets, once) and starts a guided tour. Without steps the tour is built from every visible element carrying a data-intro attribute (getStepsFromDOM), wrapped in a welcome and a completion step. Steps whose element is not visible are skipped automatically and the tooltip is kept inside the viewport.

steps Array.<Object>
Intro.js step objects (see getStep); omit to build them from the DOM.
exitOnOverlayClick Boolean
Whether clicking the dark overlay closes the tour.
startFunction function
Receives the configured introJs instance instead of starting it right away (call intro.start() yourself).
ExtjsUtils.INTROJS.loadAndRun([
    ExtjsUtils.INTROJS.getStep(null, "Welcome to the fire history map."),
    ExtjsUtils.INTROJS.getStep(document.getElementById("legend"), "Colours show the number of fires.", "left")
]);

setHelpDescriptionDOM

function(dom, txt, position, priority) : HTMLElementhelper# Marks a DOM element as a tour step by setting its data-intro, data-position and (optionally) data-step attributes, so getStepsFromDOM/loadAndRun pick it up.

Written as ExtjsUtils.INTROJS.setHelpDescriptionDOM

Marks a DOM element as a tour step by setting its data-intro, data-position and (optionally) data-step attributes, so getStepsFromDOM/loadAndRun pick it up.

dom HTMLElement
Element to annotate.
txt String
Help text; nothing is set when empty.
position String
Tooltip position (see getStep); invalid values fall back to auto.
priority Number
Step order, stored as data-step.

Returns The same element.

ExtjsUtils.INTROJS.setHelpDescriptionDOM(document.getElementById("legend"), "Colours show the number of fires.", "left", 1);

setHelpDescriptionElement

function(cmpConfig, txt, position, priority) : Objecthelper# Attaches a help description to an Ext component config (not a rendered component): an afterrender listener is chained so that setHelpDescriptionDOM runs on the component element once it exists.

Written as ExtjsUtils.INTROJS.setHelpDescriptionElement

Attaches a help description to an Ext component config (not a rendered component): an afterrender listener is chained so that setHelpDescriptionDOM runs on the component element once it exists. Returns the same config, so it can be used inline. Throws when given an already rendered component.

cmpConfig Object
Ext component configuration object.
txt String
Help text; nothing is attached when empty.
position String
Tooltip position (see getStep); invalid values fall back to auto.
priority Number
Step order, stored as data-step.

Returns The same cmpConfig.

var btn = ExtjsUtils.INTROJS.setHelpDescriptionElement({xtype: "button", text: "Export"},
    "Downloads the current table as CSV.", "bottom", 3);

JS · the map and the app

JS3 entries
Access to the running application objects: the OpenLayers map, the GeoExplorer app and the layer sources.
Usage: ExtjsUtils.JS

getApp

function() : GeoExplorerhelper# Returns the application object (window.app, the GeoExplorer viewer): app.mapPanel holds the map and its layer store, app.layerSources the registered sources, app.tools the tools by id.

Written as ExtjsUtils.JS.getApp

Returns the application object (window.app, the GeoExplorer viewer): app.mapPanel holds the map and its layer store, app.layerSources the registered sources, app.tools the tools by id.

Returns The application instance.

var layerStore = ExtjsUtils.JS.getApp().mapPanel.layers;

getLayerSource

function(sourceId) : gxp.plugins.LayerSource|nullhelper# Returns a registered layer source by id — "local" (the Mappia GeoServer), the built-in "osm"/"google", or an id registered with QUERY.addRemoteWMSServer — or null when it does not exist (or is still not created).

Written as ExtjsUtils.JS.getLayerSource

Returns a registered layer source by id — "local" (the Mappia GeoServer), the built-in "osm"/"google", or an id registered with QUERY.addRemoteWMSServer — or null when it does not exist (or is still not created). Sources expose createLayerRecord(cfg) and, for WMS sources, the capabilities store.

sourceId String
Source id as used in a layer's source property.

Returns The source plugin, or null when unknown.

var src = ExtjsUtils.JS.getLayerSource("ibge");
if (src) console.log("IBGE source is registered");

getMap

function() : OpenLayers.Maphelper# Returns the OpenLayers map of the page (window.map when defined, otherwise app.mapPanel.map).

Written as ExtjsUtils.JS.getMap

Returns the OpenLayers map of the page (window.map when defined, otherwise app.mapPanel.map). Prefer it over the bare globals in query code: it works in the viewer, the editor and embedded pages alike.

Returns The current map.

ExtjsUtils.JS.getMap().zoomTo(6);

JSON · JSON that keeps functions

JSONUtils1 entry
JSON helpers that keep functions when serializing (used to store layer definitions).
Usage: ExtjsUtils.JSON

stringify

function(obj, maxDeep, indent, clearDataCallback) : String|undefinedhelper# Serializes an object to JavaScript source text, keeping what JSON.stringify drops: functions are written with their source (toString()), and numbers, booleans, arrays and nested objects are kept.

Written as ExtjsUtils.JSON.stringify

Serializes an object to JavaScript source text, keeping what JSON.stringify drops: functions are written with their source (toString()), and numbers, booleans, arrays and nested objects are kept. undefined/null values are omitted. The output is JavaScript (unquoted function bodies), meant to be evaluated again — it is how layer definitions with callbacks are stored — not strict JSON. Markup braces {{/}} inside strings are escaped.

obj Object
The object to serialize.
maxDeep Number
Maximum recursion depth, to stop on cyclic references.
indent Number
Number of spaces per indentation level (0 or omitted for none).
clearDataCallback function
function(curObj, curKey) returning true to skip the property curKey of curObj.

Returns The source text, or undefined for a null/undefined input.

var src = ExtjsUtils.JSON.stringify({name: "CSR:example_layer", functions: {onClick: function(p) { alert(p); }}}, 7, 2,
    function(obj, key) { return key === "cache"; });

LAYER · find layers, extents, legends, pixels

Layer28 entries
Find layers by name, read their extents, legends and pixel colours. Usage: ExtjsUtils.LAYER

filterRecordsProperties

function(records, properties) : Array.<Object>|Array.<(String|Number)>helper# Extracts properties from an array of layer records (or plain objects).

Written as ExtjsUtils.LAYER.filterRecordsProperties

Extracts properties from an array of layer records (or plain objects). With a single property name the result is a flat array of values; with several names each element is an object holding those properties. A single record or a single property name (not wrapped in an array) is accepted too.

records Array.<Ext.data.Record>|Ext.data.Record|Array.<Object>
Records (or objects) to read; a record's get(name) is used when available.
properties Array.<String>|String
Property name(s) to extract.

Returns One entry per record: the value itself for a single property, an object for several.

var records = ExtjsUtils.LAYER.getLayersRecords();
var names = ExtjsUtils.LAYER.filterRecordsProperties(records, 'name');            // ["CSR:estados", ...]
var pairs = ExtjsUtils.LAYER.filterRecordsProperties(records, ['name', 'title']); // [{name, title}, ...]

getActiveLayersDefinition

function() : Array.<GeoExt.data.LayerRecord>helper# Returns a copy of the layer records currently in the map (the map panel's layer store), in map order.

Written as ExtjsUtils.LAYER.getActiveLayersDefinition

Returns a copy of the layer records currently in the map (the map panel's layer store), in map order. Each record's data/json carries the layer definition as the query declared it, after the interpreter filled in its defaults, and record.getLayer() gives the OpenLayers layer.

Returns A new array with all the layer records.

ExtjsUtils.LAYER.getActiveLayersDefinition().forEach(function(record) {
  console.log(record.get('name'), record.get('group'));
});

getAllBackgroundLayerRecords

function() : Array.<GeoExt.data.LayerRecord>helper# Returns the layer records of every background map currently in the map's layer store — the layers declared with group: "background" (or flagged isBaseLayer), including the platform default basemap.

Written as ExtjsUtils.LAYER.getAllBackgroundLayerRecords

Returns the layer records of every background map currently in the map's layer store — the layers declared with group: "background" (or flagged isBaseLayer), including the platform default basemap. Use it to toggle basemaps from query code.

Returns The background layer records (empty when there is none).

// Hide every basemap
ExtjsUtils.LAYER.getAllBackgroundLayerRecords().forEach(function(record) {
  record.getLayer().setVisibility(false);
});

getLayerByName

function(fullLayerName) : OpenLayers.Layer|undefinedhelper# Returns the OpenLayers layer currently in the map whose name equals the given name, or undefined when no such layer is loaded.

Written as ExtjsUtils.LAYER.getLayerByName

Returns the OpenLayers layer currently in the map whose name equals the given name, or undefined when no such layer is loaded. A calculated layer (source: "calculate") is named on the map by the name declared in the query ('CSR:altimetria'); a plain map layer is named by its title. To find a plain layer by the map it shows, filter ExtjsUtils.JS.getMap().layers on layer.params.LAYERS === 'CSR:estados'.

fullLayerName String
The layer's name on the map: the query name of a calculated layer, the title of a plain one.

Returns The layer object, or undefined when it is not in the map.

var layer = ExtjsUtils.LAYER.getLayerByName('CSR:altimetria'); // a calculated layer
if (layer) layer.setVisibility(true);

getLayerColorAtPoint

function(layer, absolutePoint, layerOperation) : Uint8Array|nullhelper# Reads the colour a layer draws under a page position: looks through the layer's tile images for the one containing the point and reads that pixel through WebGL.

Written as ExtjsUtils.LAYER.getLayerColorAtPoint

Reads the colour a layer draws under a page position: looks through the layer's tile images for the one containing the point and reads that pixel through WebGL. Returns null when the point falls outside every tile or the pixel is a "null" colour for the layer operation (transparent / no data). This is what isOnHover uses.

layer OpenLayers.Layer
Layer whose tiles are inspected (an inner layer, not the composed one).
absolutePoint Object
Page position {x, y} in pixels (e.g. from HTML.getAbsolutePointFromMouseEvent).
layerOperation Object
The layer's MapOperations value, used to decide which colours mean "no data".

Returns The [R, G, B, A] pixel colour, or null when there is no colour at that point.

var point = ExtjsUtils.HTML.getAbsolutePointFromMouseEvent(evt);
var rgba = ExtjsUtils.LAYER.getLayerColorAtPoint(composedLayer.layers[0], point);
if (rgba) console.log('hovering colour', ExtjsUtils.HTML.rgbToColorStyle(rgba));

getLayerExtent

function(layer) : OpenLayers.Boundshelper# Returns the extent of a layer in the map projection.

Written as ExtjsUtils.LAYER.getLayerExtent

Returns the extent of a layer in the map projection. A vector layer with features gives their bounds; any other layer its llbbox (the lon/lat bounding box read from the WMS capabilities) reprojected. When the layer has no llbbox, or the reprojected box is invalid, it falls back to the layer's maxExtent (or the inner layer's maxExtent for a composed layer) and finally to the map's maxExtent. The layer may be given by name (layer.name or getMapName). Typical use: zoom the map to a layer.

layer OpenLayers.Layer|String
The layer (a composed layer or one of its inner layers), or its name.

Returns The layer extent in the map projection; null for a name not on the map.

// Zoom to a layer when it becomes visible
onVisibilityChange: function(visible) {
  if (visible) app.mapPanel.map.zoomToExtent(ExtjsUtils.LAYER.getLayerExtent(this), true);
}
// the bounding box of a property drawn by a vector layer
var bounds = ExtjsUtils.LAYER.getLayerExtent("CSR:show_car");

getLayerLegend

function(composedLayer, index) : Arrayhelper# Gets the associated layer legend content by its index.

Written as ExtjsUtils.LAYER.getLayerLegend

Gets the associated layer legend content by its index.

PS: The legend format is the same as expected by the composedLayer.setCalculateLegend function. Usage: this.setCalculateLegend(ExtjsUtils.LAYER.getLayerLegend(this, 0)); inside a calculated layer's beforeCalc.

composedLayer OpenLayers.Layer.Composed
Layer composed.
index Numeric
Index of the inside layer.

Returns Array with the legend entries [{color, value, title}, ...].

getLayerSource

function(layerName, onlyDescription) : Objecthelper# Finds the source (local, remote, a source registered by addRemoteWMSServer...) that serves a layer: first the source whose store contains a record with that name, then the source whose id …

Written as ExtjsUtils.LAYER.getLayerSource

Finds the source (local, remote, a source registered by addRemoteWMSServer...) that serves a layer: first the source whose store contains a record with that name, then the source whose id matches the name's workspace prefix (workspace:layer). Returns either the live source plugin or its description object.

layerName String
Full layer name, e.g. 'CSR:estados'.
onlyDescription Boolean
true to get a copy of the source description (the sources config: url, ptype, cors...), false/omitted to get the source plugin instance.

Returns The source plugin (e.g. a gxp.plugins.WMSSource) or its description, or an empty object {} when no source contains the layer.

var wmsUrl = ExtjsUtils.LAYER.getLayerSource('CSR:estados', true).url;

getLayerSourceNames

function() : Array.<String>helper# Returns the ids of every layer source currently registered in the application — the built-in ones (local, osm, google...) plus those added by the query (QUERY.addRemoteWMSServer).

Written as ExtjsUtils.LAYER.getLayerSourceNames

Returns the ids of every layer source currently registered in the application — the built-in ones (local, osm, google...) plus those added by the query (QUERY.addRemoteWMSServer). These ids are the storeName accepted by getLayersRecords and getStoreLayersNames.

Returns The source ids (empty before the application is ready).

ExtjsUtils.LAYER.getLayerSourceNames(); // ["local", "osm", "google", "remote", ...]

getLayerTilesFeatureIntersects

function(layer, feature) : Array.<Object>helper# Rasterises a polygon feature over the tiles of a layer and returns the tiles it intersects, each with the exact pixel spans inside the polygon (scan-line polygon fill, one entry per tile row).

Written as ExtjsUtils.LAYER.getLayerTilesFeatureIntersects

Rasterises a polygon feature over the tiles of a layer and returns the tiles it intersects, each with the exact pixel spans inside the polygon (scan-line polygon fill, one entry per tile row). This is the basis of the "values inside a drawn area" calculations; pass the result rows to HTML.getPixelColorLimitsWebGL to read the pixels.

layer OpenLayers.Layer
Layer whose tile images are tested.
feature OpenLayers.Feature.Vector
Polygon feature, in the layer projection.

Returns One {img, limits, bounds} per intersecting tile: img the tile image, limits an array indexed by tile row holding the [start, end, start, end, ...] x-spans inside the polygon, bounds an OpenLayers.Bounds with the row/column range covered (closed interval).

var tiles = ExtjsUtils.LAYER.getLayerTilesFeatureIntersects(composedLayer.layers[0], drawnFeature);
tiles.forEach(function(tile) {
  var pixels = ExtjsUtils.HTML.getPixelColorLimitsWebGL(tile.img, tile.limits, tile.bounds);
});

getLayerTilesInArea

function(layer, minBBOXx, minBBOXy, maxBBOXx, maxBBOXy) : Array.<Object>helper# Returns the tile images of a layer that overlap a rectangle given in page pixels, together with the part of each tile that lies inside the rectangle.

Written as ExtjsUtils.LAYER.getLayerTilesInArea

Returns the tile images of a layer that overlap a rectangle given in page pixels, together with the part of each tile that lies inside the rectangle. Useful to read the pixels of a screen region (e.g. a dragged box) from the layer tiles.

layer OpenLayers.Layer
Layer whose tile images are tested.
minBBOXx Number
Left edge of the rectangle, in page pixels.
minBBOXy Number
Top edge of the rectangle, in page pixels.
maxBBOXx Number
Right edge of the rectangle, in page pixels.
maxBBOXy Number
Bottom edge of the rectangle, in page pixels.

Returns One {img, minXY, maxXY} per overlapping tile: img the tile image, minXY/maxXY the [x, y] corners of the overlap relative to the tile.

var tiles = ExtjsUtils.LAYER.getLayerTilesInArea(composedLayer.layers[0], 100, 100, 400, 300);
tiles.forEach(function(tile) {
  var w = tile.maxXY[0] - tile.minXY[0], h = tile.maxXY[1] - tile.minXY[1];
  var pixels = ExtjsUtils.HTML.getPixelColorAtWebGL(tile.minXY[0], tile.minXY[1], tile.img, w, h);
});

getLayersRecords

function(layerName, storeName) : Array.<Ext.data.Record>|Ext.data.Record|nullhelper# Gets the store record of a layer from its full name ('CSR:estados'), searching every source store or only the one given by storeName.

Written as ExtjsUtils.LAYER.getLayersRecords

Gets the store record of a layer from its full name ('CSR:estados'), searching every source store or only the one given by storeName. The record holds the layer's capabilities data (title, abstract, styles, llbbox...). Called without layerName it returns the records of all the layers the source(s) offer.

layerName String
Full layer name to look for; omit to get every record.
storeName String
Source id to restrict the search to (see getLayerSourceNames); omit to search all sources.

Returns The record of layerName (null when not found in exactly one store), or the array of all records when layerName is omitted.

var record = ExtjsUtils.LAYER.getLayersRecords("CSR:estados");
if (record) console.log(record.get("title"), record.get("styles"));

// Every layer offered by the 'remote' source
var remoteRecords = ExtjsUtils.LAYER.getLayersRecords(undefined, "remote");

getLocalLayers

function(layersArray) : Array.<OpenLayers.Layer>helper# Filters an array of layers down to the visible WMS layers.

Written as ExtjsUtils.LAYER.getLocalLayers

Filters an array of layers down to the visible WMS layers. Composed (calculation) layers that have no expression are replaced by their inner layers, which go through the same test. The input array is not modified.

layersArray Array.<OpenLayers.Layer>
Layers to filter, typically app.mapPanel.map.layers.

Returns The visible WMS layers found.

var visibleWms = ExtjsUtils.LAYER.getLocalLayers(app.mapPanel.map.layers);

getMapName

function(layer) : Stringhelper# The stable name of a map layer: the WMS LAYERS it requests (e.g. "CSR:cultivo_cafe_cafe"), or layer.name for layers without one (vector, XYZ/OSM — "OSM Mapnik").

Written as ExtjsUtils.LAYER.getMapName

The stable name of a map layer: the WMS LAYERS it requests (e.g. "CSR:cultivo_cafe_cafe"), or layer.name for layers without one (vector, XYZ/OSM — "OSM Mapnik"). A WMS layer's own name is replaced by its display title once its capabilities load, so it cannot identify the map; this can. Offline areas record their maps (layerNames) under this name.

layer OpenLayers.Layer
The layer.

Returns The map name.

var names = app.mapPanel.map.layers.map(ExtjsUtils.LAYER.getMapName);

getPixelCoordinateSize

function(projection) : Objecthelper# Returns the size of one screen pixel in map units at the current zoom level, as the difference between the coordinates of pixels (0, 0) and (1, 1) expressed in the given projection.

Written as ExtjsUtils.LAYER.getPixelCoordinateSize

Returns the size of one screen pixel in map units at the current zoom level, as the difference between the coordinates of pixels (0, 0) and (1, 1) expressed in the given projection. Only meaningful for projections where the pixel size is constant across the view.

projection String|OpenLayers.Projection
Projection to express the size in (e.g. layer.projection); omit to use the map projection.

Returns {lon, lat} — width and height of a pixel in units of projection.

var px = ExtjsUtils.LAYER.getPixelCoordinateSize("EPSG:4326");
console.log("one pixel spans", px.lon, "degrees of longitude");

getSourceByName

function(sourceName) : Objecthelper# Returns the source plugin instance registered under an id (e.g. 'local'), whose store holds one record per layer the source offers.

Written as ExtjsUtils.LAYER.getSourceByName

Returns the source plugin instance registered under an id (e.g. 'local'), whose store holds one record per layer the source offers. undefined for an unknown id.

sourceName String
Source id, one of getLayerSourceNames().

Returns The source plugin (e.g. a gxp.plugins.WMSSource).

var localStore = ExtjsUtils.LAYER.getSourceByName('local').store;

getStorageBaseUrl

function(storageLayer) : Stringhelper# Builds the base URL of the pre-computed ("storage") responses of a WMS layer and style: the layer source URL (without its getCapabilities.xml suffix) followed by /<layer name without workspace>/<style name or 1>/.

Written as ExtjsUtils.LAYER.getStorageBaseUrl

Builds the base URL of the pre-computed ("storage") responses of a WMS layer and style: the layer source URL (without its getCapabilities.xml suffix) followed by /<layer name without workspace>/<style name or 1>/. Internal to the storage-backed calculations; listed for completeness.

storageLayer OpenLayers.Layer.WMS
WMS layer whose params.LAYERS and params.STYLES identify the stored responses.

Returns The base URL, ending with /.

var base = ExtjsUtils.LAYER.getStorageBaseUrl(layer); // ".../estados/1/"

getStoreLayerStylesFromName

function(layerName) : Array.<String>helper# Returns the names of the styles a layer is published with, read from the layer's store record (the WMS capabilities).

Written as ExtjsUtils.LAYER.getStoreLayerStylesFromName

Returns the names of the styles a layer is published with, read from the layer's store record (the WMS capabilities). Empty when the layer is unknown.

layerName String
Full layer name, e.g. 'CSR:estados'.

Returns The style names of the layer.

// Add every style of a remote layer as its own map entry
ExtjsUtils.LAYER.getStoreLayerStylesFromName('remote:landuse').forEach(function(style) {
  ExtjsUtils.QUERY.addLayer({ name: 'remote:landuse', title: style, styles: style, source: 'remote' });
});

getStoreLayersNames

function(storeName) : Array.<String>helper# Returns the full names of all the layers offered by the sources — every source, or only the one given by storeName.

Written as ExtjsUtils.LAYER.getStoreLayersNames

Returns the full names of all the layers offered by the sources — every source, or only the one given by storeName. Typical use: enumerate what a remote WMS server registered with QUERY.addRemoteWMSServer publishes, to add its layers to the map.

storeName String
Source id to restrict the listing to (see getLayerSourceNames); omit for all sources.

Returns The layer names ('workspace:layer').

ExtjsUtils.LAYER.getStoreLayersNames('remote').forEach(function(name) {
  ExtjsUtils.QUERY.addLayer({ name: name, title: name, source: 'remote', visibility: false });
});

getVisibleLayers

function(mapStores, sortTop) : Array.<OpenLayers.Layer>helper# Returns the visible WMS layers of the map (see getLocalLayers), by default ordered from the topmost layer down — i.e. the order in which they may be under the mouse.

Written as ExtjsUtils.LAYER.getVisibleLayers

Returns the visible WMS layers of the map (see getLocalLayers), by default ordered from the topmost layer down — i.e. the order in which they may be under the mouse.

mapStores Array.<OpenLayers.Layer>
Layers to search; defaults to all layers of the map.
sortTop Boolean
true/omitted to sort the result from the highest to the lowest z-index; false to keep the map order.

Returns The visible layers, topmost first unless sortTop is false.

var topLayer = ExtjsUtils.LAYER.getVisibleLayers()[0];

isBackgroundLayerOrRecord

function(recordOrLayer) : Booleanhelper# Tells whether a layer or a layer record is a background map.

Written as ExtjsUtils.LAYER.isBackgroundLayerOrRecord

Tells whether a layer or a layer record is a background map. Mappia basemaps are the layers declared with group: "background" (checked on the layer, on its json definition and on the record data); plain OpenLayers base layers (isBaseLayer) also count.

recordOrLayer OpenLayers.Layer|GeoExt.data.LayerRecord
The layer or layer record to test.

Returns true for a background map, false otherwise (also for null/undefined).

var overlays = app.mapPanel.map.layers.filter(function(layer) {
  return !ExtjsUtils.LAYER.isBackgroundLayerOrRecord(layer);
});

isOnHover

function(layer, mouseEvt) : Booleanhelper# Informs if the mouse is over the current layer.

Written as ExtjsUtils.LAYER.isOnHover

Informs if the mouse is over the current layer.

layer Layer|Composer
Layer to check if the mouse is over.
mouseEvt Event
The mouse event.

Returns Returns true if the mouse is over the 'layer', False otherwise.

layerExists

function(layerName) : Booleanhelper# Tells whether some source offers a layer with the given full name — i.e. whether getLayersRecords(layerName) finds a record.

Written as ExtjsUtils.LAYER.layerExists

Tells whether some source offers a layer with the given full name — i.e. whether getLayersRecords(layerName) finds a record. Useful to guard QUERY.addLayer against a name that is not published by any server.

layerName String
Full layer name, e.g. 'CSR:estados'.

Returns true when a source has the layer, false otherwise.

if (ExtjsUtils.LAYER.layerExists('CSR:estados')) ExtjsUtils.QUERY.addLayer({ name: 'CSR:estados', title: 'States' });

layerSourceRequireCORS

function(layerNameID) : Booleanhelper# Tells whether the source a layer comes from was registered with cors: true — i.e. its tiles must be fetched through the CORS proxy before their pixels can be read (remote WMS servers added with …

Written as ExtjsUtils.LAYER.layerSourceRequireCORS

Tells whether the source a layer comes from was registered with cors: true — i.e. its tiles must be fetched through the CORS proxy before their pixels can be read (remote WMS servers added with QUERY.addRemoteWMSServer).

layerNameID String
Full layer name ('workspace:layer').

Returns true when the layer source requires CORS, false otherwise (also when the layer is in no source).

// 'myserver' being a source registered with QUERY.addRemoteWMSServer
if (ExtjsUtils.LAYER.layerSourceRequireCORS('myserver:landuse')) console.log('tiles go through the CORS proxy');

loadWait

function(layer, url, success, failure, useCors)helper# Loads a URL while making a layer wait for it: the layer's startLoadingResource event is fired before the request and endLoadingResource after it, so the layer's calculations are on hold until the resource arrives.

Written as ExtjsUtils.LAYER.loadWait

Loads a URL while making a layer wait for it: the layer's startLoadingResource event is fired before the request and endLoadingResource after it, so the layer's calculations are on hold until the resource arrives. The success/failure callbacks run before the layer is notified. Use it from a layer's beforeCalc (or similar hooks) to fetch data the layer expression depends on.

layer OpenLayers.Layer
Layer that must wait for the resource.
url String
URL to load.
success function
Called with the response (XMLHttpRequest) on success.
failure function
Called on failure (no arguments).
useCors Boolean
true when the URL is on another host, to fetch it through the CORS proxy (REQUEST.getCORS) instead of REQUEST.get.
ExtjsUtils.LAYER.loadWait(this, '/wmtp/data/thresholds.json', function(resp) {
  window.thresholds = JSON.parse(resp.responseText);
}, function() {
  ExtjsUtils.ALERTIFY.log('Could not load the thresholds');
});

sortTopLayers

function(layersArray) : Array.<OpenLayers.Layer>helper# Sorts an array of layers so the ones drawn on top come first (decreasing z-index of the layer div).

Written as ExtjsUtils.LAYER.sortTopLayers

Sorts an array of layers so the ones drawn on top come first (decreasing z-index of the layer div). The array is sorted in place and also returned.

layersArray Array.<OpenLayers.Layer>
Layers to sort, e.g. the result of getLocalLayers.

Returns The same array, ordered from the topmost layer to the bottom one.

var topFirst = ExtjsUtils.LAYER.sortTopLayers(ExtjsUtils.LAYER.getLocalLayers(app.mapPanel.map.layers));

tileSize

Number# Expected size, in pixels, of the square tiles a WMS layer is drawn with (256).

Written as ExtjsUtils.LAYER.tileSize

Expected size, in pixels, of the square tiles a WMS layer is drawn with (256). Used by the pixel-reading helpers (getLayerTilesFeatureIntersects) to walk a layer's tile images.

var pixelsPerTile = ExtjsUtils.LAYER.tileSize * ExtjsUtils.LAYER.tileSize;

zoomMapsExtents

function(includeHidden, closest) : Array.<Number>helper# Zooms the map to the smallest extent containing every query layer: the union of the extents (getLayerExtent) of the local, file and remote layers that have a bounding box, skipping background …

Written as ExtjsUtils.LAYER.zoomMapsExtents

Zooms the map to the smallest extent containing every query layer: the union of the extents (getLayerExtent) of the local, file and remote layers that have a bounding box, skipping background layers and — unless includeHidden is true — hidden layers. Nothing happens when no layer qualifies. Commonly called from onToggleViewGroup to re-frame the map when a group is expanded.

includeHidden Boolean
true to also count layers that are not visible.
closest Boolean
true to zoom as close as possible even if parts of the extent fall outside the viewport; false/omitted to fit the whole extent on screen.

Returns The union extent as [left, bottom, right, top] in the map projection (all zeros when no layer qualified).

// In a group definition: re-frame the map on the visible layers when the group opens
onToggleViewGroup: function(view) {
  if (view.expanded) ExtjsUtils.LAYER.zoomMapsExtents(false);
}

LEGENDS · legend lookup

LEGENDS1 entry
Legend lookup helpers.
Usage: ExtjsUtils.LEGENDS

getColorTitle

function(layer, r, g, b) : String|nullhelper# Finds the legend entry of a layer whose colour is exactly (r, g, b) and returns its title — the way to map a pixel colour read from the map back to the legend class it represents.

Written as ExtjsUtils.LEGENDS.getColorTitle

Finds the legend entry of a layer whose colour is exactly (r, g, b) and returns its title — the way to map a pixel colour read from the map back to the legend class it represents. Works on layers exposing getLegendEntries() (composed/calculation layers).

layer OpenLayers.Layer
Layer whose legend entries are searched.
r Number
Red component of the colour (0-255).
g Number
Green component of the colour (0-255).
b Number
Blue component of the colour (0-255).

Returns The title of the legend entry with that colour, or null when no entry matches.

var rgba = ExtjsUtils.LAYER.getLayerColorAtPoint(layer.layers[0], ExtjsUtils.HTML.getAbsolutePointFromMouseEvent(evt));
if (rgba) console.log('Class under the mouse:', ExtjsUtils.LEGENDS.getColorTitle(layer, rgba[0], rgba[1], rgba[2]));

NUMBER · format numbers

Number2 entries
Format and abbreviate numbers. Usage: ExtjsUtils.NUMBER

abbreviateNumber

function(value, useFixed, abbreviateNumbers) : Number|Stringhelper# Auxiliary function to shorten the display of numbers.

Written as ExtjsUtils.NUMBER.abbreviateNumber

Auxiliary function to shorten the display of numbers.

PS: The number loses a little precision but becomes more meaningful.

value Number
Value to be displayed.
useFixed Number
If set it will limit the number of decimal places, otherwise it will use the default value.
abbreviateNumbers Array.<Number>
Number suffix name.

Returns Simplified value to be displayed. Can return a number or a string.

numericToString

function(value) : Stringhelper# Formats a number for display with toLocaleString() (thousands separator and decimal mark).

Written as ExtjsUtils.NUMBER.numericToString

Formats a number for display with toLocaleString() (thousands separator and decimal mark). It was written to follow the interface language (pt-br or en-IN), but the current implementation compares the value itself with the language codes, so for a number it always falls back to the browser's default locale.

value Number
Value to be represented as a string.

Returns The localized string representation of the value.

ExtjsUtils.NUMBER.numericToString(1234567.5); // "1.234.567,5" in a pt-BR browser

OBSERVABILITY · console events

OBSERVABILITY2 entries
Structured console events for diagnostics.
Usage: ExtjsUtils.OBSERVABILITY

event

function(eventName, payload, level)helper# Logs a structured diagnostic event to the console as [MappiaObservability] {event, ts, page_origin, payload} — with console.error when level is "error", console.warn otherwise — and …

Written as ExtjsUtils.OBSERVABILITY.event

Logs a structured diagnostic event to the console as [MappiaObservability] {event, ts, page_origin, payload} — with console.error when level is "error", console.warn otherwise — and forwards the same entry to window.__mappiaObservabilityHook(entry) when the host page defines that function. Useful to report tenant-side failures in a way the embedding site can collect.

eventName String
Dotted event name, e.g. "mappia.fetch.cors_blocked".
payload Object
Extra data attached to the entry (defaults to {}).
level String
"error" to log with console.error; anything else logs a warning.
ExtjsUtils.OBSERVABILITY.event("myquery.csv.load_failed", { url: csvUrl }, "error");

installFetchFailureHook

function()helper# Installs (once) a window "unhandledrejection" listener that turns unhandled fetch failures whose message mentions "failed to fetch", "cors" or "network error" into an …

Written as ExtjsUtils.OBSERVABILITY.installFetchFailureHook

Installs (once) a window "unhandledrejection" listener that turns unhandled fetch failures whose message mentions "failed to fetch", "cors" or "network error" into an OBSERVABILITY.event("mappia.fetch.cors_blocked", {message, page_origin, hint}, "error") entry, so CORS/network problems of cross-origin requests show up with a hint instead of a silent rejection. The platform calls it at start-up; calling it again is a no-op.

ExtjsUtils.OBSERVABILITY.installFetchFailureHook();

REQ_PARAMS · URL parameter parsers

REQ_PARAMS1 entry
Parsers for URL parameters with their own semantics (visiblelayers).
Usage: ExtjsUtils.REQ_PARAMS

getQntVisibleLayers

function() : Number|nullhelper# Reads the visiblelayers URL parameter, which overrides how many layers of the query start visible (see URLProperties.visiblelayers).

Written as ExtjsUtils.REQ_PARAMS.getQntVisibleLayers

Reads the visiblelayers URL parameter, which overrides how many layers of the query start visible (see URLProperties.visiblelayers). Values: a positive N shows the first N layers in query order (the top of the layer list); a negative -N shows the last N (the bottom of the list); 0 shows none; custom keeps the visibility each layer defines in the query (returns null). When the parameter is omitted the result is 1 if the URL has options=onlyfirstvisible, otherwise null (the query's own visibilities apply).

Returns Number of layers to show (positive from the top, negative from the bottom), or null to keep the query's own visibilities.

// ?visiblelayers=-2  -> the last two layers of the query start visible
var qnt = ExtjsUtils.REQ_PARAMS.getQntVisibleLayers(); // -2

REQUEST · page address and network

Request29 entries
The page address (its parameters and options=) and HTTP requests. Usage: ExtjsUtils.REQUEST

CORS_URL

String# Path of the server-side CORS proxy without caching (/cors/direct/).

Written as ExtjsUtils.REQUEST.CORS_URL

Path of the server-side CORS proxy without caching (/cors/direct/). Prefix a cross-origin URL with it when the response must always be fresh.

ExtjsUtils.REQUEST.get(ExtjsUtils.REQUEST.CORS_URL + "https://example.org/live.json", onOk, onFail);

CORS_URL_CACHED

String# Path of the server-side CORS proxy with caching (/cors/); getCORS prefixes the target URL with it.

Written as ExtjsUtils.REQUEST.CORS_URL_CACHED

Path of the server-side CORS proxy with caching (/cors/); getCORS prefixes the target URL with it. Use it to fetch a cross-origin resource that may be cached.

ExtjsUtils.REQUEST.get(ExtjsUtils.REQUEST.CORS_URL_CACHED + "https://example.org/data.json", onOk, onFail);

Response

function(success, url)helper# Constructor of the small object a file layer passes to its endLoadingLayer event (new ExtjsUtils.REQUEST.Response(success, url)), wrapping the outcome of the data request.

Written as ExtjsUtils.REQUEST.Response

Constructor of the small object a file layer passes to its endLoadingLayer event (new ExtjsUtils.REQUEST.Response(success, url)), wrapping the outcome of the data request. Instances expose getSuccess() (Boolean, true when the request succeeded) and getUrl() (String, the requested URL). Tenant code normally only reads it in the event listener.

success Boolean
True when the request succeeded, false on error.
url String
URL of the request.
layer.events.on({endLoadingLayer: function(response) {
    if (!response.getSuccess()) ExtjsUtils.ALERTIFY.log("Failed to load " + response.getUrl());
}});

abort

function(scope) : Numberhelper# Aborts every unfinished abortable request (getAbortable/getAbortables) started with the given scope.

Written as ExtjsUtils.REQUEST.abort

Aborts every unfinished abortable request (getAbortable/getAbortables) started with the given scope. The failed callback of each aborted request is invoked with wasAborted = true.

scope Object
The scope object the requests were registered with.

Returns How many requests were aborted.

var owner = {};
ExtjsUtils.REQUEST.getAbortable("/theme/app/data/totals.csv", onOk, onFail, false, owner);
// later, e.g. when the user changes the selection:
ExtjsUtils.REQUEST.abort(owner);

createRequestObject

function(url, success, failed, forceSynchronous, scope) : Objecthelper# Builds the request description consumed by getAbortables: an object exposing getURL(), getSuccess(), getFailed(), getForceSynchronous() and getScope().

Written as ExtjsUtils.REQUEST.createRequestObject

Builds the request description consumed by getAbortables: an object exposing getURL(), getSuccess(), getFailed(), getForceSynchronous() and getScope(). At least one of the two callbacks must be given.

url String
URL of the request.
success function
Success callback, called as success.call(scope, xhr, wasAborted).
failed function
Failure callback, called as failed.call(scope, xhr, wasAborted).
forceSynchronous Boolean
True (deprecated) to make the request synchronous.
scope Object
this for the callbacks; also the scope used by abort.

Returns The request object to pass to getAbortables.

var req = ExtjsUtils.REQUEST.createRequestObject("/theme/app/data/totals.csv", function(xhr) {
    this.totals = xhr.responseText;
}, null, false, this);

downloadFile

function(fileUrl)helper# Triggers a browser download of a file: creates a temporary <a download target="_blank"> pointing at the URL, clicks it and removes it.

Written as ExtjsUtils.REQUEST.downloadFile

Triggers a browser download of a file: creates a temporary <a download target="_blank"> pointing at the URL, clicks it and removes it. The suggested file name is the last segment of the URL. Typical use is a "download the data" button in a query.

fileUrl String
URL of the file to download.
ExtjsUtils.REQUEST.downloadFile("/theme/app/data/example_fire_history.csv");

get

function(url, success, failed, forceSynchronous, scope) : XMLHttpRequesthelper# Plain AJAX GET request.

Written as ExtjsUtils.REQUEST.get

Plain AJAX GET request. The usual way for query code to fetch a CSV/JSON/text resource from the Mappia server (/theme/app/data/..., a WFS GetFeature on the local GeoServer) or from any server that allows the page origin (CORS); cookies are sent on cross-origin calls. For servers without CORS headers use getCORS. Both callbacks receive the XMLHttpRequest as their only argument — read xhr.responseText.

url String
URL to load (relative to the page or absolute, including the protocol).
success function
Called with the XMLHttpRequest when the status is 200.
failed function
Called with the XMLHttpRequest on any other status.
forceSynchronous Boolean
True to make the request synchronous (deprecated), false for asynchronous.
scope Object
this for the success and failed callbacks.

Returns The request object (can be aborted with xhr.abort()).

var url = ExtjsUtils.REQUEST.getGeoserverBaseUrl() + "/wfs?service=WFS&version=1.0.0&request=GetFeature" +
    "&typename=CSR:example_layer&outputFormat=json&CQL_FILTER=code='" + code + "'";
ExtjsUtils.REQUEST.get(url, function(xhr) {
    var features = ExtjsUtils.GEOJSON.geojson2Features(JSON.parse(xhr.responseText));
    ExtjsUtils.ZOOM.zoomToExtent(features[0].geometry.getBounds());
}, function(xhr) {
    ExtjsUtils.ALERTIFY.alert("Request failed: " + xhr.status);
});

getAbortable

function(url, success, failed, forceSynchronous, scope) : XMLHttpRequesthelper# Same as get, but the request is registered under scope so it can be cancelled later with abort(scope).

Written as ExtjsUtils.REQUEST.getAbortable

Same as get, but the request is registered under scope so it can be cancelled later with abort(scope). The callbacks receive (xhr, wasAborted); when the request is aborted the failed callback runs with wasAborted = true. A scope is mandatory.

url String
URL to load.
success function
Called as success.call(scope, xhr, wasAborted) when the status is 200.
failed function
Called as failed.call(scope, xhr, wasAborted) on any other status or on abort.
forceSynchronous Boolean
True (deprecated) to make the request synchronous.
scope Object
Object identifying the owner of the request (used by abort) and this for the callbacks.

Returns The request object.

var owner = {};
ExtjsUtils.REQUEST.getAbortable("/theme/app/data/totals.csv", function(xhr) {
    showTotals(xhr.responseText);
}, function(xhr, wasAborted) {
    if (!wasAborted) ExtjsUtils.ALERTIFY.log("Could not load the totals.");
}, false, owner);
// ExtjsUtils.REQUEST.abort(owner) cancels it.

getAbortables

function(requestObjects, afterAll, afterScope) : Array.<XMLHttpRequest>helper# Runs a group of abortable GET requests (built with createRequestObject) and calls afterAll once every one of them has finished (success, failure or abort).

Written as ExtjsUtils.REQUEST.getAbortables

Runs a group of abortable GET requests (built with createRequestObject) and calls afterAll once every one of them has finished (success, failure or abort). Each request's own callbacks run first; afterAll receives the arguments of the last request to finish ([xhr, wasAborted]).

requestObjects Array.<Object>|Object
Request objects from createRequestObject (a single object is accepted).
afterAll function
Called after the last request finishes.
afterScope Object
this for afterAll; defaults to the scope of the last finished request.

Returns The request objects that were started.

var owner = {};
ExtjsUtils.REQUEST.getAbortables([
    ExtjsUtils.REQUEST.createRequestObject("/theme/app/data/a.csv", function(xhr) { this.a = xhr.responseText; }, null, false, owner),
    ExtjsUtils.REQUEST.createRequestObject("/theme/app/data/b.csv", function(xhr) { this.b = xhr.responseText; }, null, false, owner)
], function() {
    buildChart(owner.a, owner.b);
});

getBaseMappia

function() : Stringhelper# Returns the base URL of the Mappia server for platform endpoints such as /query/description/<id>/: an empty string (relative URLs) when the page is served from maps.csr.ufmg.br without a …

Written as ExtjsUtils.REQUEST.getBaseMappia

Returns the base URL of the Mappia server for platform endpoints such as /query/description/<id>/: an empty string (relative URLs) when the page is served from maps.csr.ufmg.br without a ?geoserver= override, otherwise the absolute https://maps.csr.ufmg.br. Not configurable at the moment.

Returns "" or "https://maps.csr.ufmg.br".

ExtjsUtils.REQUEST.get(ExtjsUtils.REQUEST.getBaseMappia() + "/query/description/1/", onLoad);

getCORS

function(url, success, failed, forceSynchronous) : XMLHttpRequesthelper# GET request to a cross-origin URL through the platform's cached CORS proxy (CORS_URL_CACHED + url), for servers that do not send CORS headers.

Written as ExtjsUtils.REQUEST.getCORS

GET request to a cross-origin URL through the platform's cached CORS proxy (CORS_URL_CACHED + url), for servers that do not send CORS headers. Both callbacks receive the XMLHttpRequest (read responseText). Ext's Ajax cannot be used for this because it adds an X-Requested-With header that breaks such requests.

url String
Full URL to load, including the protocol (https://...).
success function
Called with the XMLHttpRequest when the status is 200.
failed function
Called with the XMLHttpRequest on any other status.
forceSynchronous Boolean
True to make the request synchronous (deprecated).

Returns The request object.

ExtjsUtils.REQUEST.getCORS("https://example.org/api/property?code=" + code, function(xhr) {
    var data = JSON.parse(xhr.responseText);
}, function(xhr) {
    ExtjsUtils.ALERTIFY.log("Could not load the property data.");
});

getCommaSeparatedArguments

function(paramName) : Array.<String>helper# Reads a URL parameter that holds a comma-separated list and returns its items — the way ?options=, ?tools= and custom list parameters (?remotemap=a,b,c) are read.

Written as ExtjsUtils.REQUEST.getCommaSeparatedArguments

Reads a URL parameter that holds a comma-separated list and returns its items — the way ?options=, ?tools= and custom list parameters (?remotemap=a,b,c) are read.

paramName String
Name of the URL parameter.

Returns The items of the list; an empty array when the parameter is absent or empty.

// page opened as /calculator/?queryid=1&points=A,B,C
ExtjsUtils.REQUEST.getCommaSeparatedArguments("points"); // ["A", "B", "C"]

getGeoserverBaseUrl

function() : Stringhelper# Returns the GeoServer base URL in use by the local source (from the ?geoserver= URL parameter, default /geoserver), without a trailing slash — use it to build WFS/WMS requests against the same …

Written as ExtjsUtils.REQUEST.getGeoserverBaseUrl

Returns the GeoServer base URL in use by the local source (from the ?geoserver= URL parameter, default /geoserver), without a trailing slash — use it to build WFS/WMS requests against the same server the map layers come from.

Returns The GeoServer base URL.

var wfs = ExtjsUtils.REQUEST.getGeoserverBaseUrl() + "/wfs?service=WFS&version=1.0.0&request=GetFeature&typename=CSR:example&outputFormat=json";

getHost

function() : Stringhelper# Returns the origin of the current page — protocol plus host, without a trailing slash (e.g. 'https://maps.csr.ufmg.br') — for building absolute URLs to the same server.

Written as ExtjsUtils.REQUEST.getHost

Returns the origin of the current page — protocol plus host, without a trailing slash (e.g. 'https://maps.csr.ufmg.br') — for building absolute URLs to the same server.

Returns The page protocol and host.

var wfs = ExtjsUtils.REQUEST.getHost() + "/geoserver/wfs?service=WFS&request=GetFeature";

getMapObject

function(curDefinition, source) : Objecthelper# Builds a layer configuration object from the compact name;style;opacity string used by the ?map= URL parameter (see URLProperties.map): {name, source, styles, opacity} with styles/opacity …

Written as ExtjsUtils.REQUEST.getMapObject

Builds a layer configuration object from the compact name;style;opacity string used by the ?map= URL parameter (see URLProperties.map): {name, source, styles, opacity} with styles/opacity present only when given (both URL-decoded).

curDefinition String
Layer definition such as CSR:example_layer;example_style;0.8.
source String
Name of the layer source; the default local source when empty.

Returns A layer configuration ready for QUERY.addLayer.

ExtjsUtils.REQUEST.getMapObject("CSR:example_layer;example_style");
// {name: "CSR:example_layer", source: "local", styles: "example_style"}

getParameterByName

function(name) : Stringhelper# Reads a parameter of the page URL query string (?name=value), URL-decoded, with + turned into spaces.

Written as ExtjsUtils.REQUEST.getParameterByName

Reads a parameter of the page URL query string (?name=value), URL-decoded, with + turned into spaces. This is the standard way for a query to receive external input (a property code, a language, a colour) from the embedding page. The name match is case-insensitive.

name String
Name of the URL parameter.

Returns The decoded value, or an empty string when the parameter is absent.

// page opened as /calculator/?queryid=1&car=MG-1234567-ABCD
var car = ExtjsUtils.REQUEST.getParameterByName("car"); // "MG-1234567-ABCD"
if (car) loadProperty(car);

getProtocol

function() : Stringhelper# Returns the protocol of the current page, including the colon ('http:' or 'https:').

Written as ExtjsUtils.REQUEST.getProtocol

Returns the protocol of the current page, including the colon ('http:' or 'https:').

Returns The page protocol.

var url = ExtjsUtils.REQUEST.getProtocol() + "//maps.csr.ufmg.br/geoserver/wms";

getRelativeRootUri

function(relativeUrl) : Stringhelper# Resolves a path against the application root: takes the current page URL, strips the /calculator/ or /editor/ segment (and any .html file name) and appends relativeUrl.

Written as ExtjsUtils.REQUEST.getRelativeRootUri

Resolves a path against the application root: takes the current page URL, strips the /calculator/ or /editor/ segment (and any .html file name) and appends relativeUrl. Use it to load platform assets (/theme/app/...) from a page that lives in a sub-folder or on another host.

relativeUrl String
Path relative to the application root (leading slash optional).

Returns The absolute URL of the resource.

ExtjsUtils.REQUEST.getRelativeRootUri("/theme/app/js/jsts.min.js"); // "https://maps.csr.ufmg.br/theme/app/js/jsts.min.js"

isEditor

function() : Booleanhelper# Tells whether the current page is the query editor (/editor/) rather than the viewer (/calculator/), so query code can skip viewer-only decoration while being edited.

Written as ExtjsUtils.REQUEST.isEditor

Tells whether the current page is the query editor (/editor/) rather than the viewer (/calculator/), so query code can skip viewer-only decoration while being edited.

Returns True when the page is the editor, false otherwise.

if (!ExtjsUtils.REQUEST.isEditor()) ExtjsUtils.QUERY.decorate({noTop: true});

isHttps

function() : Booleanhelper# Tells whether the page is being served over HTTPS.

Written as ExtjsUtils.REQUEST.isHttps

Tells whether the page is being served over HTTPS.

Returns True when the page protocol is https:, false otherwise.

var scheme = ExtjsUtils.REQUEST.isHttps() ? "https://" : "http://";

isLocalUrl

function(url) : Booleanhelper# Identify if the 'url' is from the localhost or is from the maps.csr.ufmg.br domain.

Written as ExtjsUtils.REQUEST.isLocalUrl

Identify if the 'url' is from the localhost or is from the maps.csr.ufmg.br domain.

PS: If url is left blank it uses the current site url.

url String
String with the url to be checked.

Returns Returns true if the url is from localhost, otherwise it returns false.

ExtjsUtils.REQUEST.isLocalUrl() // true
ExtjsUtils.REQUEST.isLocalUrl("www.google.com") // false

mapHostGeoserverUrl

function(url) : Stringhelper# Forces a /geoserver/... GetMap (or similar) URL onto the map iframe's configured GeoServer (?geoserver= / getGeoserverBaseUrl(), default /geoserver on this origin).

Written as ExtjsUtils.REQUEST.mapHostGeoserverUrl

Forces a /geoserver/... GetMap (or similar) URL onto the map iframe's configured GeoServer (?geoserver= / getGeoserverBaseUrl(), default /geoserver on this origin). Capabilities OnlineResource often names https://maps.csr.ufmg.br/geoserver/... even when the calculator runs on another host — live tiles and OfflineAreas cache keys must use the map host, not that external absolute URL. Non-/geoserver URLs (OSM, remote WMS, GitHub stores) are returned unchanged.

url String
Absolute or relative WMS URL.

Returns URL under the map's GeoServer base, or the original URL.

ExtjsUtils.REQUEST.mapHostGeoserverUrl("https://maps.csr.ufmg.br/geoserver/wms?REQUEST=GetMap");
// on https://localhost → "https://localhost/geoserver/wms?REQUEST=GetMap"

mixedContentUrlFix

function(url) : Stringhelper# Rewrites an http://maps.csr.ufmg.br (or http://localhost) URL to the protocol and host of the current page, avoiding mixed-content and CORS errors when the page is served over HTTPS.

Written as ExtjsUtils.REQUEST.mixedContentUrlFix

Rewrites an http://maps.csr.ufmg.br (or http://localhost) URL to the protocol and host of the current page, avoiding mixed-content and CORS errors when the page is served over HTTPS. Other URLs are returned unchanged.

url String
URL of the request.

Returns The URL using the same protocol/host as the page.

ExtjsUtils.REQUEST.mixedContentUrlFix("http://maps.csr.ufmg.br/geoserver/wms"); // "https://maps.csr.ufmg.br/geoserver/wms" on an https page

onRequestError

function(response)helper# Generic failure handler for requests: shows a modal Ext.Msg.alert with the server's responseText, or the "server unreachable" message when there is none.

Written as ExtjsUtils.REQUEST.onRequestError

Generic failure handler for requests: shows a modal Ext.Msg.alert with the server's responseText, or the "server unreachable" message when there is none. Pass it as the failed callback of get/post when a plain error dialog is enough.

response Object
Response object (XMLHttpRequest or Ext response) of the failed request, when available.
ExtjsUtils.REQUEST.get("/theme/app/data/totals.csv", onOk, ExtjsUtils.REQUEST.onRequestError);

post

function(url, params, success, failed, forceSynchronous, scope)helper# AJAX POST of a form-encoded body: params is serialized with encodeURIComponent as application/x-www-form-urlencoded.

Written as ExtjsUtils.REQUEST.post

AJAX POST of a form-encoded body: params is serialized with encodeURIComponent as application/x-www-form-urlencoded. Cookies are sent on cross-origin calls. Both callbacks receive the XMLHttpRequest — typical use is sending a clicked coordinate or a form to an external report service from a layer onClick handler.

url String
URL to post to (relative or absolute, including the protocol).
params Object
Key/value pairs sent as the request body.
success function
Called with the XMLHttpRequest when the status is 200.
failed function
Called with the XMLHttpRequest on any other status.
forceSynchronous Boolean
True (deprecated) to make the request synchronous.
scope Object
this for the callbacks.
ExtjsUtils.REQUEST.post("https://example.org/report.php", {lat: lonLat.lat, lon: lonLat.lon}, function(xhr) {
    document.getElementById("report").innerHTML = xhr.responseText;
}, function(xhr) {
    ExtjsUtils.ALERTIFY.log("Report service unavailable.");
}, false, this);

removeHTTPProtocol

function(url) : Stringhelper# Strips a leading http: from a URL, turning it into a protocol-relative URL (//host/path) that follows the protocol of the page and avoids mixed-content blocks.

Written as ExtjsUtils.REQUEST.removeHTTPProtocol

Strips a leading http: from a URL, turning it into a protocol-relative URL (//host/path) that follows the protocol of the page and avoids mixed-content blocks.

url String
URL to rewrite.

Returns The URL without the http: prefix (unchanged when it had none).

ExtjsUtils.REQUEST.removeHTTPProtocol("http://maps.csr.ufmg.br/geoserver/wms"); // "//maps.csr.ufmg.br/geoserver/wms"

setGeoserverBaseUrl

function(url)helper# Sets the base URL of the GeoServer behind the local layer source (its WMS endpoint becomes url + "/wms").

Written as ExtjsUtils.REQUEST.setGeoserverBaseUrl

Sets the base URL of the GeoServer behind the local layer source (its WMS endpoint becomes url + "/wms"). The platform calls it at startup with the ?geoserver= URL parameter, defaulting to /geoserver; query code rarely needs it. The URL must not end with a slash nor point at a service (.../wms), otherwise an error is logged.

url String
GeoServer base URL, absolute (https://maps.csr.ufmg.br/geoserver) or relative to the root (/geoserver).
ExtjsUtils.REQUEST.setGeoserverBaseUrl("https://maps.csr.ufmg.br/geoserver");

tryHttps

function()helper# Redirects the page to its HTTPS version once: the attempt is remembered in COOKIE.TRY_HTTPS, so when the browser cannot reach the HTTPS site and comes back over HTTP it is not redirected again.

Written as ExtjsUtils.REQUEST.tryHttps

Redirects the page to its HTTPS version once: the attempt is remembered in COOKIE.TRY_HTTPS, so when the browser cannot reach the HTTPS site and comes back over HTTP it is not redirected again. Does nothing when already on HTTPS.

ExtjsUtils.REQUEST.tryHttps();

urlOptions

function(property) : Boolean# Tells whether a token is present in the options URL parameter, the comma-separated list of advanced page options (?options=scale,startopened,hidestylechooser, see URLOptions).

Tells whether a token is present in the options URL parameter, the comma-separated list of advanced page options (?options=scale,startopened,hidestylechooser, see URLOptions). The real call is ExtjsUtils.REQUEST.advToolsOptions("token"); query code uses it to react to custom tokens of its own.

property String
Option token to look for (exact, case-sensitive match).

Returns True when the token is present in ?options=, false otherwise.

// page opened as /calculator/?queryid=1&options=scale,startopened,compact
ExtjsUtils.REQUEST.advToolsOptions("startopened"); // true
if (ExtjsUtils.REQUEST.advToolsOptions("compact")) ExtjsUtils.QUERY.decorate({noTop: true});

TooltipHelper · tooltips

TooltipHelper3 entries
Functions to create tooltips on elements, at fixed positions and at mouse events.
Usage: ExtjsUtils.TooltipHelper

CreateTooltipOnPosition

function(title, contentHtml, position, additionalConfig) : Ext.Tooltiphelper# Create a tooltip at a fixed position.

Written as ExtjsUtils.TooltipHelper.CreateTooltipOnPosition

Create a tooltip at a fixed position.

If the position is the mouse event, the tooltip will be at the right side and below the pointer. If the position is a array[x,y] will anchor the top left at this point.

title String
Tooltip title.
contentHtml String
Tooltip HTML content.
position Event|Array.<Number>
Defines the top left position of the tooltip. Can be either a mouse event at or an array [x:Number, y:Number] with the cursor position.
additionalConfig Object
Additional configuration for the tooltip.

Returns A tooltip anchored at the given position.

CreateTooltipThumb

function(title, description, target, thumbUrl, showDelay) : Ext.ToolTiphelper# Creates a mouse-tracking Ext.ToolTip on a DOM element with a title, a text description (rendered in a <pre>) and an optional thumbnail image.

Written as ExtjsUtils.TooltipHelper.CreateTooltipThumb

Creates a mouse-tracking Ext.ToolTip on a DOM element with a title, a text description (rendered in a <pre>) and an optional thumbnail image. The tooltip ignores mouse events, so it never interferes with the hovered element, and is repositioned by onMoveFixPosition to stay beside the target and inside the viewport. The description is cut at the first sequence of three line breaks.

title String
Tooltip title (may be empty).
description String
Tooltip text.
target HTMLElement
Element that shows the tooltip on hover (the DOM element itself, not an id). Without it the tooltip is created unattached.
thumbUrl String
URL of an image shown above the text.
showDelay Number
Delay in milliseconds before the tooltip appears.

Returns The created tooltip.

var node = document.getElementById("field_area");
ExtjsUtils.TooltipHelper.CreateTooltipThumb("", "Area of the property in hectares.", node);

onMoveFixPosition

function(ttip, x, y)helper# move listener for an Ext.ToolTip that keeps it usable: when the tooltip has a target, it is placed to the left or right of that element (whichever side has room, or the side nearer to the …

Written as ExtjsUtils.TooltipHelper.onMoveFixPosition

move listener for an Ext.ToolTip that keeps it usable: when the tooltip has a target, it is placed to the left or right of that element (whichever side has room, or the side nearer to the mouse), and in any case it is pushed back inside the page when it would overflow the bottom or right edge. CreateTooltipThumb wires it automatically; use it as listeners: {move: ExtjsUtils.TooltipHelper.onMoveFixPosition} on tooltips you build yourself.

ttip Ext.ToolTip
The tooltip being moved.
x Number
New absolute x position of the tooltip (page coordinates).
y Number
New absolute y position of the tooltip (page coordinates).
new Ext.ToolTip({target: node, html: "Details", trackMouse: true,
    listeners: {move: ExtjsUtils.TooltipHelper.onMoveFixPosition}});

ZOOM · zoom the map

ZOOM2 entries
Functions to control zoom.

limitZoomLevel

function(zoomLvl)helper# Limits the map to a maximum zoom level: zooms out if the current zoom is above it and removes the deeper zoom levels from the map and its base layer.

Written as ExtjsUtils.ZOOM.limitZoomLevel

Limits the map to a maximum zoom level: zooms out if the current zoom is above it and removes the deeper zoom levels from the map and its base layer. Typically called from the query runNow hook.

zoomLvl Number
Highest zoom level (integer) the user may reach.
ExtjsUtils.QUERY.setQueryGlobalProperties({ runNow: function() { ExtjsUtils.ZOOM.limitZoomLevel(17); } }) && QUERY_DESCRIPTION

zoomToExtent

function(bounds, closest, maxZoom) : Numberhelper# Zooms the map to the given bounds (shortcut for app.mapPanel.map.zoomToExtent).

Written as ExtjsUtils.ZOOM.zoomToExtent

Zooms the map to the given bounds (shortcut for app.mapPanel.map.zoomToExtent). The bounds must be in the map projection (EPSG:900913); use ExtjsUtils.bboxTransform or OpenLayers.Bounds.transform to convert lon/lat first. maxZoom keeps a small extent (one property, one point) from landing on a zoom deeper than useful — e.g. deeper than the zoom an offline area was downloaded to. Nothing happens when bounds is missing.

bounds OpenLayers.Bounds|Array.<Number>|Object
Extent to show, in the map projection (any shape ExtjsUtils.toBounds accepts).
closest Boolean
True to pick the zoom level closest to the extent even if it does not fully contain it.
maxZoom Number
Deepest zoom to end at; omitted ⇒ no limit.

Returns The map zoom after the call.

var bounds = new OpenLayers.Bounds(-48, -20, -40, -14).transform("EPSG:4326", "EPSG:900913");
ExtjsUtils.ZOOM.zoomToExtent(bounds);
// fit a property, but not past zoom 16
ExtjsUtils.ZOOM.zoomToExtent(ExtjsUtils.LAYER.getLayerExtent("CSR:show_car"), false, 16);

Offline maps

Download named map areas (extent + zoom range) for offline use, with the WMS capabilities and legends they need, export/import them as zip packages and verify they are served from the cache.

OFFLINE · offline areas

OFFLINE59 entries
Offline area engine: one IndexedDB record and one Cache Storage bucket per area.
Usage: ExtjsUtils.OFFLINE
Runnable example: the offline-areas demo in the repository (examples/offline-areas-demo).

CONCURRENCY

Number# Default number of tile requests downloadArea keeps in flight at once (6).

Written as ExtjsUtils.OFFLINE.CONCURRENCY

Default number of tile requests downloadArea keeps in flight at once (6). Override per call with options.concurrency.

DB_NAME

String# Name of the IndexedDB database that keeps the offline area records: 'mappia_offline_areas'.

Written as ExtjsUtils.OFFLINE.DB_NAME

Name of the IndexedDB database that keeps the offline area records: 'mappia_offline_areas'. Informational — useful to find the records in the browser DevTools (Application → IndexedDB).

DB_VERSION

Number# Schema version of the area database (1).

Written as ExtjsUtils.OFFLINE.DB_VERSION

Schema version of the area database (1). Bumped by the platform when the record layout changes; never set it yourself.

MAX_TILES_PER_AREA

Number# Default cap on the number of tiles a single area may enumerate (20000).

Written as ExtjsUtils.OFFLINE.MAX_TILES_PER_AREA

Default cap on the number of tiles a single area may enumerate (20000). The tile count grows about 4x per zoom level, so this guardrail stops a pathological extent/zoom range before any tile is requested: downloadArea rejects with an "Area too large" error above it. Read it to show the limit in a UI, and pass options.maxTiles to downloadArea for a tighter or looser cap per call.

var count = ExtjsUtils.OFFLINE.estimateTileCountForLayers(extent, 10, 14);
if (count > ExtjsUtils.OFFLINE.MAX_TILES_PER_AREA) alert("Narrow the extent or the zoom range");

STORE_NAME

String# Name of the object store (inside DB_NAME) that holds one record per area, keyed by the area id: 'areas'.

Written as ExtjsUtils.OFFLINE.STORE_NAME

Name of the object store (inside DB_NAME) that holds one record per area, keyed by the area id: 'areas'.

activateLatestServiceWorker

function() : Promise.<Object>helper# Activates the newest installed service worker: asks a waiting/installing worker to skip waiting and the active one to claim the open pages, then waits (up to ~3 s) until none is left waiting.

Written as ExtjsUtils.OFFLINE.activateLatestServiceWorker

Activates the newest installed service worker: asks a waiting/installing worker to skip waiting and the active one to claim the open pages, then waits (up to ~3 s) until none is left waiting. A page loaded under an older worker still needs a reload before its requests reach the new one (needsReload). Never rejects.

Returns getServiceWorkerStatus() plus {ok: true, activated}, or {ok: false, error}.

ExtjsUtils.OFFLINE.activateLatestServiceWorker().then(function(sw) {
    if (sw.ok && sw.needsReload) location.reload();
});

checkStorageQuota

function() : Promise.<Object>helper# Reports the browser's storage quota for this origin (navigator.storage.estimate): how much is used, how much the browser grants and the difference.

Written as ExtjsUtils.OFFLINE.checkStorageQuota

Reports the browser's storage quota for this origin (navigator.storage.estimate): how much is used, how much the browser grants and the difference. It says nothing about a particular area — compare available with estimateAreaBytes before a download. Older browsers without the Storage API report {unknown: true}.

Returns {unknown: false, usage, quota, available} in bytes, or {unknown: true}.

ExtjsUtils.OFFLINE.checkStorageQuota().then(function(q) {
    if (!q.unknown) console.log(Math.round(q.available / 1048576) + " MB free of " + Math.round(q.quota / 1048576));
});

collectDefinitionUrls

function(layers) : Array.<String>helper# The definition URLs (not tiles) the given layers need to be redrawn without the network: each WMS layer's legend JSON (/geolegend/?...&isjson=true) and the getCapabilities.xml of every remote …

Written as ExtjsUtils.OFFLINE.collectDefinitionUrls

The definition URLs (not tiles) the given layers need to be redrawn without the network: each WMS layer's legend JSON (/geolegend/?...&isjson=true) and the getCapabilities.xml of every remote layer store registered with addRemoteWMSServer (storage stores only; cors stores are skipped, they go through the online proxy). The local WMS GetCapabilities is NOT in the list — downloadDefinitions prunes and caches it separately. Mostly informational; downloadDefinitions calls it for you.

layers Array.<Object>
Targets from getCacheableLayers.

Returns The URLs to cache as-is.

console.log(ExtjsUtils.OFFLINE.collectDefinitionUrls(ExtjsUtils.OFFLINE.getCacheableLayers()));

createAreaId

function() : Stringhelper# Generates a new unique area id ("area_<time>_<random>").

Written as ExtjsUtils.OFFLINE.createAreaId

Generates a new unique area id ("area_<time>_<random>"). downloadArea and importAreaFromZip call it when no id option is given; call it yourself when you need to know the id before starting a download (e.g. to report progress under it).

Returns A fresh area id.

var id = ExtjsUtils.OFFLINE.createAreaId();
ExtjsUtils.OFFLINE.downloadArea({id: id, name: "Fazenda", extent: extent, zoomMin: 10, zoomMax: 14});

deleteAllAreas

function(options) : Promise.<Number>helper# Deletes every offline area (bucket + record) and the definitions buckets those areas downloaded (definitionsId), then — once the service worker confirms its index no longer lists them — reloads the …

Written as ExtjsUtils.OFFLINE.deleteAllAreas

Deletes every offline area (bucket + record) and the definitions buckets those areas downloaded (definitionsId), then — once the service worker confirms its index no longer lists them — reloads the map's tiles once (not once per area). The "clear all" of an areas list: the capabilities caches saved by name (downloadDefinitions({name})) stay, for deleteDefinitions; and unlike resetAllOfflineData it keeps the serving policy and leaves the service worker registered.

options Object
How to delete.
options.reloadTiles Boolean
false to skip the tile reload.

Returns How many areas were deleted.

ExtjsUtils.OFFLINE.deleteAllAreas().then(function(count) { console.log(count + " areas deleted"); });

deleteArea

function(id, options) : Promise.<undefined>helper# Deletes an area completely: its Cache Storage bucket (all its tiles) and its IndexedDB record, and tells the service worker.

Written as ExtjsUtils.OFFLINE.deleteArea

Deletes an area completely: its Cache Storage bucket (all its tiles) and its IndexedDB record, and tells the service worker. The shared definitions bucket is not touched (other areas of the same query may use it; resetAllOfflineData clears it). Waits for the worker to confirm it rebuilt its index without the deleted bucket, then asks the map to request its tiles again (reloadMapTiles), so the screen shows the difference at once instead of at the next pan or zoom. Pass {reloadTiles: false} to skip that (e.g. deleting several areas right before an import replaces them — see importAreaFromZip's replaceAreaIds, which does this itself). Safe to call for an id that no longer exists.

id String
The area id.
options Object
{reloadTiles} — defaults to true.

Returns Resolves once both the cache and the record are gone.

ExtjsUtils.OFFLINE.deleteArea(areaId).then(function() { console.log("deleted"); });

deleteAreaRecord

function(id) : Promise.<undefined>helper# Deletes only the IndexedDB record of an area, leaving its tile cache in place.

Written as ExtjsUtils.OFFLINE.deleteAreaRecord

Deletes only the IndexedDB record of an area, leaving its tile cache in place. Normally you want deleteArea, which removes both.

id String
The area id.

Returns Resolves once the record is gone.

ExtjsUtils.OFFLINE.deleteAreaRecord(areaId);

deleteDefinitions

function(id) : Promise.<Boolean>helper# Deletes a definitions cache (its GetCapabilities and legends).

Written as ExtjsUtils.OFFLINE.deleteDefinitions

Deletes a definitions cache (its GetCapabilities and legends). A page still loading its catalog from it gets the live one from then on.

id String
The cache name or id (listDefinitions).

Returns true when the cache existed.

ExtjsUtils.OFFLINE.deleteDefinitions("fazenda-42");

describeCacheableLayers

function(layerNames) : Array.<Object>helper# One plain description per cacheable map — what a "which maps go offline" picker shows: {name, title, visible, kind, maxZoom, suggestedMaxZoom, metersPerCell, canLimitMaxZoom, llbbox}.

Written as ExtjsUtils.OFFLINE.describeCacheableLayers

One plain description per cacheable map — what a "which maps go offline" picker shows: {name, title, visible, kind, maxZoom, suggestedMaxZoom, metersPerCell, canLimitMaxZoom, llbbox}. name is the map name layerNames options take (ExtjsUtils.LAYER.getMapName); maxZoom the limit in force (getMaxZoom, null = none); suggestedMaxZoom/metersPerCell what suggestMaxZoom reads from the raster's cell size (null when it declares none); canLimitMaxZoom whether setMaxZoom applies (WMS maps, not XYZ/OSM basemaps); llbbox the lon/lat bounding box from the capabilities ([left, bottom, right, top], or null). Plain data, safe to postMessage. Call it after whenLayersReady.

layerNames Array.<String>
Only these maps (see selectCacheableLayers).

Returns The descriptions, one per map.

ExtjsUtils.OFFLINE.whenLayersReady().then(function() {
    ExtjsUtils.OFFLINE.describeCacheableLayers().forEach(function(map) {
        console.log(map.name + ": max zoom " + (map.maxZoom === null ? "none" : map.maxZoom));
    });
});

downloadArea

function(options) : Promise.<Object>helper# Downloads (or resumes) one offline area: every tile of the chosen layers over the extent and zoom range, one HTTP request per tile with a bounded concurrency, into the area's own Cache Storage bucket …

Written as ExtjsUtils.OFFLINE.downloadArea

Downloads (or resumes) one offline area: every tile of the chosen layers over the extent and zoom range, one HTTP request per tile with a bounded concurrency, into the area's own Cache Storage bucket — plus, unless includeDefinitions: false, the query's definitions (pruned GetCapabilities + legends) into their shared bucket, in parallel (see downloadDefinitions). The area record is saved as 'downloading' first and finished as 'ready', or 'partial' when aborted or when a tile/definition failed. Resumable: pass the same id again and tiles already in the cache are not re-fetched (with refresh: true they are, each replacing its stored copy — never a second one); with a different extent, zoom range or maps the area grows, and its record widens to cover both (e.g. one id per imóvel, downloaded again after it is re-drawn). The serving policy (see setServingPolicy) is forced to "NetworkOnly" for the download's duration — so every request really goes to the network, never gets answered by the worker from a bucket — and put back to whatever it was, once it settles. Rejects without any request when the estimated tile count exceeds maxTiles ("Area too large"). The engine works without a query id: queryId defaults to the page's ?queryid parameter and is only stored on the record. The service worker serves the cached tiles when the page is offline; use verifyAreaServed to check.

options Object
Area definition and download options.
options.name String
Display name of the area (defaults to the id).
options.extent OpenLayers.Bounds|Array.<Number>|Object
The area, in map units: an OpenLayers.Bounds, a [left, bottom, right, top] array or any {left, bottom, right, top} object (e.g. map.getExtent()).
options.zoomMin Number
The first zoom level to download.
options.zoomMax Number
The last zoom level to download (inclusive).
options.queryId String
Query id recorded on the area; defaults to the ?queryid URL parameter (may be empty — not required).
options.id String
Id of an existing area to resume/refresh; omitted ⇒ createAreaId().
options.layers Array.<Object>
Targets from getCacheableLayers to include; omitted ⇒ layerNames, or every cacheable map. Without it the download first waits for the query's layers (whenLayersReady).
options.layerNames Array.<String>
Map names to include (WMS LAYERS, or "OSM Mapnik") — see selectCacheableLayers. Rejects, before any request, when one of them is not on the map.
options.maxTiles Number
Tile-count cap for this call; defaults to MAX_TILES_PER_AREA.
options.concurrency Number
Parallel tile requests; defaults to CONCURRENCY.
options.signal AbortSignal
Aborts the download; what was fetched stays cached and the area ends 'partial'.
options.includeDefinitions Boolean
false to download tiles only.
options.refresh Boolean
true to fetch the tiles already stored again, overwriting them (e.g. updated imagery).
options.onProgress function
Called after each tile with {done, total, failed, bytes} (tiles only).

Returns The saved area record (see listAreas), with status 'ready' or 'partial'.

var map = ExtjsUtils.JS.getMap();
var controller = new AbortController();
ExtjsUtils.OFFLINE.downloadArea({
    name: "Fazenda Santa Clara",
    extent: map.getExtent(),
    zoomMin: map.getZoom(),
    zoomMax: map.getZoom() + 3,
    layers: ExtjsUtils.OFFLINE.getCacheableLayers(),
    signal: controller.signal,
    onProgress: function(p) { console.log(p.done + "/" + p.total + " tiles, " + p.failed + " failed"); }
}).then(function(area) {
    console.log("area " + area.id + " is " + area.status);
}).catch(function(err) {
    alert(err.message); // e.g. "Area too large: ~35000 tiles exceeds the 20000 cap..."
});
// controller.abort() cancels; the partial area can be resumed later with {id: area.id}

downloadAreaAsZip

function(options) : Promise.<Object>helper# Same result as downloadArea, but as ONE HTTP request instead of one per tile: POSTs the enumerated URL list ({urls: [...], entries: [{url, map}]}) to options.endpoint, a zip-building service …

Written as ExtjsUtils.OFFLINE.downloadAreaAsZip

Same result as downloadArea, but as ONE HTTP request instead of one per tile: POSTs the enumerated URL list ({urls: [...], entries: [{url, map}]}) to options.endpoint, a zip-building service that fetches every tile server-side and answers with a single .zip (a manifest.json with {entries: [{url, path, contentType, status}]} plus one file per fetched URL), then unpacks it straight into the area's cache (JSZip is lazy-loaded on first use). There is no default endpoint and none built into the platform — it is infrastructure a deployment opts into (a reference implementation, mappia-offline-zip-server, lives next to the offline-areas demo). Not resumable mid-download: it either completes or is retried from scratch; a URL the service could not fetch is counted as failed. Definitions are never sent to the endpoint: they are fetched (and the capabilities pruned) by the client, in parallel, unless includeDefinitions: false. Same NetworkOnly-for-the-duration policy switch as downloadArea (see its doc comment).

options Object
The same options as downloadArea (name, extent, zoomMin, zoomMax, queryId, id, layers, layerNames, maxTiles, signal, includeDefinitions, onProgress) plus the endpoint.
options.endpoint String
URL of the zip-building service (required; rejects without it).
options.onProgress function
Called with {phase, done, total, failed, bytes}: phase is 'requesting' while the POST is in flight (done stays 0), then 'unpacking' once per entry written to the cache.

Returns The saved area record (see listAreas), with status 'ready' or 'partial'.

ExtjsUtils.OFFLINE.downloadAreaAsZip({
    name: "Fazenda Santa Clara",
    extent: ExtjsUtils.JS.getMap().getExtent(),
    zoomMin: 11, zoomMax: 14,
    endpoint: "https://offline-zip.example.org/zip",
    onProgress: function(p) { console.log(p.phase, p.done + "/" + p.total); }
}).then(function(area) { console.log(area.status); });

downloadDefinitions

function(options) : Promise.<Object>helper# Downloads the "definitions" (not tiles) the query needs to redraw without the network: the local WMS GetCapabilities — pruned to the maps actually on the map with ExtjsUtils.CAPABILITIES.filterText …

Written as ExtjsUtils.OFFLINE.downloadDefinitions

Downloads the "definitions" (not tiles) the query needs to redraw without the network: the local WMS GetCapabilities — pruned to the maps actually on the map with ExtjsUtils.CAPABILITIES.filterText before it is cached (the full catalog is ~2500 layers; the pruned copy is the handful in use) — plus each layer's legend and every registered remote store's capabilities (collectDefinitionUrls, cached as-is). They go into their own shared cache bucket, separate from any area's tiles, because which maps the filter keeps depends on the whole active query, not on one area: several areas of the same query share one copy. The bucket id is derived from the in-use map names, so no queryid is required — the engine works without one. downloadArea and downloadAreaAsZip call it in parallel with the tiles unless includeDefinitions: false; call it directly to refresh definitions alone or to get their own progress.

Everything it downloads comes from the server, whatever the serving mode (setServingPolicy) — never from a cache, its own included — and while offline (navigator.onLine false, or the Offline preset's forceOffline) it rejects at once instead of trying.

Give it a name to keep a named capabilities cache the user controls: calling it again with the same name updates that cache; layerNames (or full: true) picks which catalog it keeps. A cached catalog is never used on its own: a page loads its catalog from it only when it asks — useDefinitions(name), or ?definitions=<name> on the map page URL — so different Mappia instances can use different caches, or the live catalog, side by side.

options Object
Download options.
options.name String
Name of the cache to create or update (see listDefinitions) — any name but "live", which means the live catalog; omitted ⇒ an id derived from the map names in use.
options.layerNames Array.<String>
Maps the cached GetCapabilities keeps; omitted ⇒ the maps on the map now.
options.full Boolean
true to keep the whole GetCapabilities, unfiltered (the full catalog, a few MB).
options.legends Boolean
false to skip the legends.
options.layers Array.<Object>
Targets from getCacheableLayers, scoping the legend/remote-capabilities list only (the GetCapabilities filter always covers the whole map); omitted ⇒ every cacheable layer.
options.signal AbortSignal
Aborts the pending requests; what was already cached stays.
options.requestTimeoutMs Number
Longest wait for each request; one that takes longer counts as failed and the rest go on.
options.onProgress function
Called after each request with {id, done, total, failed, bytes}.

Returns {id, name, full, cacheName, mapNames, done, failed, total, bytes} — id is the definitions bucket id also stored on the area as definitionsId.

ExtjsUtils.OFFLINE.downloadDefinitions({
    onProgress: function(p) { console.log("definitions " + p.done + "/" + p.total); }
}).then(function(result) {
    console.log(result.mapNames, result.failed === 0 ? "complete" : "partial");
});
// a named cache of this query's maps, then this page loads its catalog from it
ExtjsUtils.OFFLINE.downloadDefinitions({ name: "fazenda-42" }).then(function() {
    return ExtjsUtils.OFFLINE.useDefinitions("fazenda-42");
});

downloadLayers

function(layers, options) : Promise.<Object>helper# downloadArea from a list of layers: the area is worked out by planArea (maps, extent, zoom range and name derived from the layers, each overridable in options), then downloaded tile by tile — …

Written as ExtjsUtils.OFFLINE.downloadLayers

downloadArea from a list of layers: the area is worked out by planArea (maps, extent, zoom range and name derived from the layers, each overridable in options), then downloaded tile by tile — or, with options.endpoint, by downloadAreaAsZip. Every other option goes through as is (id, signal, onProgress, includeDefinitions, maxTiles, concurrency, …).

layers Array.<(String|OpenLayers.Layer)>
Layers by name or the layers themselves (see planArea).
options Object
planArea overrides (extent, zoomMin, zoomMax, name) plus any downloadArea option.
options.endpoint String
URL of a zip-building service: download with downloadAreaAsZip instead.

Returns The saved area record (see listAreas).

// one imóvel, ready for offline editing
ExtjsUtils.OFFLINE.downloadLayers(["CSR:show_car", "CSR:planet_brasil_2024", "CSR:cultivo_cafe_cafe"], {
    id: "imovel_" + imovelId
}).then(function(area) { console.log(area.name + " is " + area.status); });
// the same, but no deeper than zoom 15 and over an extent of your own
ExtjsUtils.OFFLINE.downloadLayers(["CSR:planet_brasil_2024"], { extent: [-5179428, -2460070, -5171880, -2455780], zoomMax: 15 });

effectiveZoom

function(target, z) : Numberhelper# The zoom a layer really requests tiles at when the map is at zoom z: z itself, unless the layer has a maxZoom limit it honours (ConfigLayer.maxZoom or layer.setMaxZoom), in which case every …

Written as ExtjsUtils.OFFLINE.effectiveZoom

The zoom a layer really requests tiles at when the map is at zoom z: z itself, unless the layer has a maxZoom limit it honours (ConfigLayer.maxZoom or layer.setMaxZoom), in which case every zoom above the limit collapses onto it — the map keeps asking for the max-zoom tile and stretches it. The estimate and the enumeration both go through this, which is why a maxZoom makes an offline area so much smaller.

target Object
A {layer, kind} entry from getCacheableLayers.
z Number
The map zoom level.

Returns The effective zoom, <= z.

var target = ExtjsUtils.OFFLINE.getCacheableLayers()[0];
console.log(ExtjsUtils.OFFLINE.effectiveZoom(target, 16)); // 13 for a layer limited to maxZoom 13

enumerateTileEntries

function(extent, zoomMin, zoomMax, layers) : Array.<Object>helper# enumerateTileUrls() with the map each tile belongs to: [{url, map}], where map is the layer's WMS LAYERS name (or its name for XYZ/OSM) — the folder the tile lands in when the area is exported as a zip.

Written as ExtjsUtils.OFFLINE.enumerateTileEntries

enumerateTileUrls() with the map each tile belongs to: [{url, map}], where map is the layer's WMS LAYERS name (or its name for XYZ/OSM) — the folder the tile lands in when the area is exported as a zip. A URL two layers share (a query listing the same map twice) appears once, under the first layer.

extent OpenLayers.Bounds|Array.<Number>|Object
The area, in map units: an OpenLayers.Bounds, a [left, bottom, right, top] array or any {left, bottom, right, top} object.
zoomMin Number
The first zoom level to cover.
zoomMax Number
The last zoom level to cover (inclusive).
layers Array.<Object>
Targets from getCacheableLayers; omitted ⇒ every cacheable layer on the map.

Returns Entries {url: String, map: String}; [] without a map.

var perMap = {};
ExtjsUtils.OFFLINE.enumerateTileEntries(extent, 10, 14).forEach(function(entry) {
    perMap[entry.map] = (perMap[entry.map] || 0) + 1;
});
console.log(perMap); // {"CSR:cultivo_cafe_cafe": 340, "mapnik": 340}

enumerateTileUrls

function(extent, zoomMin, zoomMax, layers) : Array.<String>helper# The unique tile URLs an area needs: every tile of every given layer, for every zoom in range, covering extent.

Written as ExtjsUtils.OFFLINE.enumerateTileUrls

The unique tile URLs an area needs: every tile of every given layer, for every zoom in range, covering extent. Each URL is asked from the live layer object (its own getURL), so it is byte-identical to what the map requests on its own; zooms above a layer's maxZoom are enumerated at the limit, exactly like the map behaves. This is the list estimateAreaBytes samples and downloadArea fetches; a large extent/zoom range makes it long, so check estimateTileCountForLayers first.

extent OpenLayers.Bounds|Array.<Number>|Object
The area, in map units: an OpenLayers.Bounds, a [left, bottom, right, top] array or any {left, bottom, right, top} object.
zoomMin Number
The first zoom level to cover.
zoomMax Number
The last zoom level to cover (inclusive).
layers Array.<Object>
Targets from getCacheableLayers; omitted ⇒ every cacheable layer on the map.

Returns The tile URLs, without duplicates; [] without a map.

var urls = ExtjsUtils.OFFLINE.enumerateTileUrls(extent, 10, 14, selectedLayers);
ExtjsUtils.OFFLINE.estimateAreaBytes(urls).then(function(estimate) {
    console.log(urls.length + " tiles, ~" + Math.round(estimate.estimatedBytes / 1048576) + " MB");
});

estimateArea

function(options) : Promise.<Object>helper# Everything to show before downloading an area, in one call, with the same map selection and cap downloadArea applies: first the rough tile count (estimateTileCountForLayers, pure arithmetic — an …

Written as ExtjsUtils.OFFLINE.estimateArea

Everything to show before downloading an area, in one call, with the same map selection and cap downloadArea applies: first the rough tile count (estimateTileCountForLayers, pure arithmetic — an oversized area costs no request) checked against the cap; then, under the cap, the exact tile count, a size estimated from a sample of real tile requests (estimateAreaBytes) and the storage quota (checkStorageQuota). Waits for the query's layers (whenLayersReady). Rejects, before any request, when one of layerNames is not on the map.

options Object
The area, as downloadArea takes it.
options.extent OpenLayers.Bounds|Array.<Number>|Object
The area, in map units: an OpenLayers.Bounds, a [left, bottom, right, top] array or any {left, bottom, right, top} object.
options.zoomMin Number
The first zoom level.
options.zoomMax Number
The last zoom level (inclusive).
options.layerNames Array.<String>
Maps to include (see selectCacheableLayers); omitted ⇒ every cacheable map.
options.layers Array.<Object>
Targets from getCacheableLayers, instead of layerNames.
options.maxTiles Number
The cap; defaults to MAX_TILES_PER_AREA.

Returns {layerNames, roughTileCount, tileCountWithoutMaxZoom, maxTiles, overCap}, plus — when not over the cap — {tileCount, sampledCount, estimatedBytes, quota}. tileCountWithoutMaxZoom is what the same area would cost if no map had a maxZoom limit: the difference to roughTileCount is what the limits save.

ExtjsUtils.OFFLINE.estimateArea({ extent: map.getExtent(), zoomMin: 12, zoomMax: 16 }).then(function(estimate) {
    if (estimate.overCap) alert("~" + estimate.roughTileCount + " tiles: narrow the area");
    else console.log(estimate.tileCount + " tiles, ~" + Math.round(estimate.estimatedBytes / 1048576) + " MB");
});

estimateAreaBytes

function(urls, sampleSize) : Promise.<Object>helper# Estimates an area's download size in bytes by really fetching a small sample of its tile URLs, measuring them and extrapolating by the total count — tile weight varies by imagery, zoom and source, so …

Written as ExtjsUtils.OFFLINE.estimateAreaBytes

Estimates an area's download size in bytes by really fetching a small sample of its tile URLs, measuring them and extrapolating by the total count — tile weight varies by imagery, zoom and source, so nothing short of asking the network is an estimate. Costs sampleSize requests. Distinct from checkStorageQuota, which reports the browser's free storage, not anything about this area; label the two separately in a UI.

urls Array.<String>
The tile URLs of the area, from enumerateTileUrls.
sampleSize Number
How many of the URLs (from the start of the list) to fetch.

Returns {tileCount, sampledCount, averageBytes, estimatedBytes} — sampledCount is the number of sample fetches that succeeded (0 ⇒ estimate is 0).

var urls = ExtjsUtils.OFFLINE.enumerateTileUrls(extent, 10, 14, selectedLayers);
Promise.all([ExtjsUtils.OFFLINE.estimateAreaBytes(urls, 8), ExtjsUtils.OFFLINE.checkStorageQuota()])
    .then(function(results) {
        var needed = results[0].estimatedBytes, quota = results[1];
        if (!quota.unknown && needed > quota.available) alert("Not enough storage for this area");
    });

estimateTileCount

function(extent, zoomMin, zoomMax) : Numberhelper# Number of tile-grid cells covering extent across the zoom range for ONE layer with NO zoom limit — pure arithmetic, no layer involved.

Written as ExtjsUtils.OFFLINE.estimateTileCount

Number of tile-grid cells covering extent across the zoom range for ONE layer with NO zoom limit — pure arithmetic, no layer involved. Use it for the raw grid size (e.g. to show how much a maxZoom saves); estimateTileCountForLayers is the one to use for the real cost, since it knows about each layer's limit.

extent OpenLayers.Bounds|Array.<Number>|Object
The area, in map units: an OpenLayers.Bounds, a [left, bottom, right, top] array or any {left, bottom, right, top} object.
zoomMin Number
The first zoom level to cover.
zoomMax Number
The last zoom level to cover (inclusive).

Returns The cell count, 0 without a map.

var extent = ExtjsUtils.JS.getMap().getExtent();
console.log(ExtjsUtils.OFFLINE.estimateTileCount(extent, 10, 14) + " cells per unlimited layer");

estimateTileCountForLayers

function(extent, zoomMin, zoomMax, layers) : Numberhelper# Upper bound on the tile requests an area would need for these layers over the zoom range, honouring each layer's maxZoom (zooms above it count once, at the limit).

Written as ExtjsUtils.OFFLINE.estimateTileCountForLayers

Upper bound on the tile requests an area would need for these layers over the zoom range, honouring each layer's maxZoom (zooms above it count once, at the limit). Still pure arithmetic — no URL is built — so run it first, before enumerating or fetching anything, to reject an oversized area cheaply: it is the same number downloadArea compares against MAX_TILES_PER_AREA.

extent OpenLayers.Bounds|Array.<Number>|Object
The area, in map units: an OpenLayers.Bounds, a [left, bottom, right, top] array or any {left, bottom, right, top} object.
zoomMin Number
The first zoom level to cover.
zoomMax Number
The last zoom level to cover (inclusive).
layers Array.<Object>
Targets from getCacheableLayers; omitted ⇒ every cacheable layer on the map.

Returns The estimated tile count, 0 without a map.

var extent = ExtjsUtils.JS.getMap().getExtent();
var rough = ExtjsUtils.OFFLINE.estimateTileCountForLayers(extent, 10, 14, selectedLayers);
if (rough > ExtjsUtils.OFFLINE.MAX_TILES_PER_AREA) {
    alert("Too large: ~" + rough + " tiles. Narrow the extent or the zoom range.");
}

exportAreaAsZip

function(id, options) : Promise.<Blob>helper# Packs an existing area — every tile currently in its cache — into one .zip Blob that is self-describing: a manifest.json (entries {url, path, map, contentType, status} plus an area block with …

Written as ExtjsUtils.OFFLINE.exportAreaAsZip

Packs an existing area — every tile currently in its cache — into one .zip Blob that is self-describing: a manifest.json (entries {url, path, map, contentType, status} plus an area block with the record's id, name, extent, zoom range, layer names and query id) and one file per tile, laid out one folder per map (<map>/<host>/<path>, e.g. mapnik/tile.openstreetmap.org/16/23456/37891.png). importAreaFromZip/importAreaFromUrl rebuild the area from it on another device without re-downloading a single tile — host the file anywhere. Tiles are stored uncompressed (they are PNG/JPEG already) and the zip is assembled in memory: fine for the thousands of tiles an area holds, not for hundreds of MB. Pair it with exportAreaFilename and saveBlobAsFile to hand the pack to the user.

id String
The area id.
options Object
Export options.
options.onProgress function
Called per tile with {phase: 'packing', done, total, failed, bytes}.

Returns The zip file; rejects when no area has that id.

ExtjsUtils.OFFLINE.getArea(areaId).then(function(area) {
    return ExtjsUtils.OFFLINE.exportAreaAsZip(areaId).then(function(blob) {
        ExtjsUtils.OFFLINE.saveBlobAsFile(blob, ExtjsUtils.OFFLINE.exportAreaFilename(area));
    });
});

exportAreaFilename

function(area) : Stringhelper# The file name a pack from exportAreaAsZip should be saved under: mappia-offline-area-<slug>.zip, where the slug is the area name (falling back to its id) lower-cased, accents stripped and …

Written as ExtjsUtils.OFFLINE.exportAreaFilename

The file name a pack from exportAreaAsZip should be saved under: mappia-offline-area-<slug>.zip, where the slug is the area name (falling back to its id) lower-cased, accents stripped and non-alphanumerics replaced by -.

area Object
The area record (only name/id are read).

Returns The file name, e.g. "mappia-offline-area-fazenda-santa-clara.zip".

ExtjsUtils.OFFLINE.exportAreaFilename({name: "Fazenda São João"}); // "mappia-offline-area-fazenda-sao-joao.zip"

exportDefinitionsAsZip

function(id) : Promise.<Blob>helper# Packs a definitions cache (listDefinitions) — its GetCapabilities and legends — into one .zip Blob: a manifest.json (format: 'mappia-offline-definitions', the cache's metadata as definitions, …

Written as ExtjsUtils.OFFLINE.exportDefinitionsAsZip

Packs a definitions cache (listDefinitions) — its GetCapabilities and legends — into one .zip Blob: a manifest.json (format: 'mappia-offline-definitions', the cache's metadata as definitions, and entries {url, path, contentType}) plus one file per entry. importDefinitionsFromZip saves it back on any device, where ?definitions=<id> or useDefinitions then loads the map's catalog from it without the server.

id String
The cache name or id.

Returns The zip file; rejects when no cache has that id.

ExtjsUtils.OFFLINE.exportDefinitionsAsZip("fazenda-42").then(function(blob) {
    ExtjsUtils.OFFLINE.saveBlobAsFile(blob, "mappia-capabilities-fazenda-42.zip");
});

getArea

function(id) : Promise.<(Object|null)>helper# Reads one area record by id (see listAreas for the record shape).

Written as ExtjsUtils.OFFLINE.getArea

Reads one area record by id (see listAreas for the record shape).

id String
The area id.

Returns The record, or null when no area has that id.

ExtjsUtils.OFFLINE.getArea(areaId).then(function(area) {
    if (!area) throw new Error("area not found: " + areaId);
    console.log(area.status);
});

getCacheableLayers

function() : Array.<Object>helper# Lists the layers currently on the map whose tiles can be cached for offline use, as {layer, kind} "targets" — the objects every other function here accepts as layers.

Written as ExtjsUtils.OFFLINE.getCacheableLayers

Lists the layers currently on the map whose tiles can be cached for offline use, as {layer, kind} "targets" — the objects every other function here accepts as layers. Two kinds: 'storage' (a CustomWMS layer served from a hosted layer store — addRemoteWMSServer with storage — recursing into a Composed layer's inner layers) and 'grid' (any other tiled OpenLayers.Layer.Grid: XYZ/OSM basemaps and plain named WMS layers such as CSR:cultivo_cafe_cafe). Excluded: calculate layers with an operation but no store (their requests depend on the viewport, not on a tile grid) and Google/Bing basemaps (their terms forbid caching). Filter the result to let the user pick which maps to include; the WMS name of a target is target.layer.params.LAYERS (target.layer.name for XYZ/OSM). Wait for whenLayersReady before calling it, or a {name: "CSR:..."} layer may not be on the map yet; selectCacheableLayers picks maps by name.

Returns Targets {layer: OpenLayers.Layer, kind: 'storage'|'grid'}, or [] without a map.

var targets = ExtjsUtils.OFFLINE.getCacheableLayers();
var selected = targets.filter(function(t) {
    var key = (t.layer.params && t.layer.params.LAYERS) || t.layer.name;
    return ["CSR:cultivo_cafe_cafe", "mapnik"].indexOf(key) !== -1;
});

getDefinitionsInUse

function() : String|nullhelper# The definitions cache this page loads its catalog from (useDefinitions or ?definitions=<name>), "" for the empty catalog it started with (?definitions=), or null for the live catalog.

Written as ExtjsUtils.OFFLINE.getDefinitionsInUse

The definitions cache this page loads its catalog from (useDefinitions or ?definitions=<name>), "" for the empty catalog it started with (?definitions=), or null for the live catalog.

Returns The cache id, "", or null.

console.log(ExtjsUtils.OFFLINE.getDefinitionsInUse() || "live catalog");

getMaxZoom

function(target) : Number|nullhelper# The zoom limit a layer currently honours (see effectiveZoom), or null when it has none.

Written as ExtjsUtils.OFFLINE.getMaxZoom

The zoom limit a layer currently honours (see effectiveZoom), or null when it has none. Shows the "real max zoom" in force for a layer — set in the query with ConfigLayer.maxZoom or at runtime with layer.setMaxZoom(n) on CustomWMS layers.

target Object
A {layer, kind} entry from getCacheableLayers.

Returns The max zoom, or null.

ExtjsUtils.OFFLINE.getCacheableLayers().forEach(function(t) {
    console.log(t.layer.name, ExtjsUtils.OFFLINE.getMaxZoom(t));
});

getOfflineReadiness

function(options) : Promise.<Object>helper# Whether this page is ready to work offline, as four checks, each {ok, ...}:

Written as ExtjsUtils.OFFLINE.getOfflineReadiness

Whether this page is ready to work offline, as four checks, each {ok, ...}:

  • worker: the current service worker controls the page (reason when not:
      'not-controlled', 'outdated' — reload the page, or 'disabled');
  • tiles: an area that is switched on and fully downloaded (status: 'ready')
      covers options.extent (any such area without one) — areaIds;
  • catalog: the map's catalog comes from a saved capabilities cache that exists
      (inUse, from getDefinitionsInUse; saved, the cache ids of listDefinitions);
  • serving: the serving policy answers from the downloads (any mode but
      NetworkOnly) — mode, forceOffline. ready is true when all four are; missing lists the keys that are not. Built from getServiceWorkerStatus, listAreas, listDefinitions, getDefinitionsInUse and getServingPolicy. Plain data, safe to postMessage.
options Object
What to check.
options.extent OpenLayers.Bounds|Array.<Number>|Object
The area that must be covered, in map units.

Returns {ready, missing, worker, tiles, catalog, serving}.

ExtjsUtils.OFFLINE.getOfflineReadiness({ extent: ExtjsUtils.LAYER.getLayerExtent("CSR:show_car") }).then(function(r) {
    console.log(r.ready ? "ready offline" : "missing: " + r.missing.join(", "));
});

getServiceWorkerStatus

function() : Promise.<Object>helper# The state of the page's service worker, for a status panel.

Written as ExtjsUtils.OFFLINE.getServiceWorkerStatus

The state of the page's service worker, for a status panel. registered, controlled (a worker answers this page's requests), controllerScriptURL, controllerIsCurrent (the controller is the active worker), the registration slots active/waiting/installing (their state, or null) with activeMeta/ waitingMeta/installingMeta ({state, scriptURL}), hasWaiting, needsReload (a newer worker waits, or an older one still controls the page — reload the page or iframe to run the newest), and from the worker's own answer: build (its build label, a hash of its code), offlineBuckets, servingPolicy, recentDebugEvents, workerScriptURL. Also carries the page's registration outcome (window.MappiaServiceWorkerSetup: enabled, localhost, error). Plain data, safe to postMessage. Never rejects.

Returns The status.

ExtjsUtils.OFFLINE.getServiceWorkerStatus().then(function(sw) {
    console.log(sw.controlled ? "worker " + sw.build : "no worker controls this page");
    if (sw.needsReload) console.log("reload to run the newest worker");
});

getServingPolicy

function() : Promise.<Object>helper# How the service worker answers map requests that hit (or miss) an offline bucket: {mode} with one of "CacheFirst" (default: bucket first, network on miss), "NetworkFirst" (live first, bucket …

Written as ExtjsUtils.OFFLINE.getServingPolicy

How the service worker answers map requests that hit (or miss) an offline bucket: {mode} with one of "CacheFirst" (default: bucket first, network on miss), "NetworkFirst" (live first, bucket when the network fails), "CacheOnly" (bucket / soft crop only — never the network), "NetworkOnly" (live only — never the bucket). Legacy kebab-case values (cache-first, …) are accepted and normalized. forceOffline: true makes the worker treat the network as down no matter what navigator.onLine says — every mode then behaves as it would with no network at all (an "Offline" preset is {mode: "CacheOnly", forceOffline: true}). Stored in Cache Storage (OfflineCacheKey.SETTINGS_CACHE_NAME); resetAllOfflineData clears it.

Returns {mode, forceOffline, updatedAt} — the default (forceOffline: false, updatedAt: null) when nothing was set yet.

ExtjsUtils.OFFLINE.getServingPolicy().then(function(policy) { console.log(policy.mode); });

importAreaFromUrl

function(url, options) : Promise.<Object>helper# importAreaFromZip for a pack hosted at a URL (a GitHub release asset, a raw file in a repository, any static host): one GET, then the unpack — zero tile requests.

Written as ExtjsUtils.OFFLINE.importAreaFromUrl

importAreaFromZip for a pack hosted at a URL (a GitHub release asset, a raw file in a repository, any static host): one GET, then the unpack — zero tile requests. The host must allow cross-origin reads (CORS) when it is not the platform's own origin; raw.githubusercontent.com and GitHub release assets do. The pack URL is recorded on the area as importedFrom.

url String
The pack URL.
options Object
The same options as importAreaFromZip (id, name, extent, zoomMin, zoomMax, layerNames, queryId, replaceAreaIds, signal, onProgress).
options.onProgress function
Called with {phase, done, total, failed, bytes}: phase is 'requesting' while the GET is in flight, then 'unpacking' per entry.

Returns The saved area record (see listAreas).

// step through properties one at a time, never keeping more than one area's tiles on disk
ExtjsUtils.OFFLINE.importAreaFromUrl("https://github.com/org/packs/releases/download/v1/fazenda-42.zip", {
    id: "current",
    replaceAreaIds: ["current"],
    onProgress: function(p) { console.log(p.phase, p.done + "/" + p.total); }
}).then(function(area) {
    ExtjsUtils.JS.getMap().zoomToExtent(OpenLayers.Bounds.fromArray(area.extent));
});

importAreaFromZip

function(zipBlob, options) : Promise.<Object>helper# Rebuilds an offline area from a pack produced by exportAreaAsZip (or any zip following the manifest contract) — "load the tile cache from this file instead of downloading every tile".

Written as ExtjsUtils.OFFLINE.importAreaFromZip

Rebuilds an offline area from a pack produced by exportAreaAsZip (or any zip following the manifest contract) — "load the tile cache from this file instead of downloading every tile". The area record comes from the pack's manifest.area and can be overridden by options; a pack without an area block still imports with whatever the options give. Re-importing a pack with the same id refreshes that area in place (entries are overwritten, never duplicated). Definitions are not part of a pack; run downloadDefinitions separately when the device needs them. See importAreaFromUrl for packs hosted on a server.

zipBlob Blob
The pack, e.g. from an <input type="file"> or a fetch().blob().
options Object
Import options.
options.id String
Area id to create/refresh; defaults to the pack's, else a new id.
options.name String
Area name; defaults to the existing/packed name, else the id.
options.extent Array.<Number>
[left, bottom, right, top] in map units; defaults to the packed extent.
options.zoomMin Number
Defaults to the packed value.
options.zoomMax Number
Defaults to the packed value.
options.layerNames Array.<String>
Map names the pack covers; defaults to the packed list.
options.queryId String
Defaults to the packed value.
options.replaceAreaIds Array.<String>
Ids of other areas to delete (cache + record) BEFORE unpacking — the "one property open at a time" tool: {id: 'current', replaceAreaIds: ['current']} never keeps more than one area's tiles on disk, freeing space before the new pack lands.
options.signal AbortSignal
Aborts the unpacking; the area ends 'partial'.
options.onProgress function
Called per entry with {phase: 'unpacking', done, total, failed, bytes}.
options.sourceUrl String
Recorded as importedFrom (set automatically by importAreaFromUrl).

Returns The saved area record (see listAreas).

// <input type="file" id="pack"> in the host page, forwarded as a Blob
ExtjsUtils.OFFLINE.importAreaFromZip(fileBlob, {
    name: "Fazenda Santa Clara",
    onProgress: function(p) { console.log(p.done + "/" + p.total); }
}).then(function(area) { console.log("imported", area.id, area.tileCount + " tiles"); });

importDefinitionsFromZip

function(zipBlob, options) : Promise.<Object>helper# Saves a capabilities pack from exportDefinitionsAsZip as a definitions cache, under its packed id or options.name (an existing cache of that id is replaced).

Written as ExtjsUtils.OFFLINE.importDefinitionsFromZip

Saves a capabilities pack from exportDefinitionsAsZip as a definitions cache, under its packed id or options.name (an existing cache of that id is replaced). Then ?definitions=<id> or useDefinitions(id) loads the map's catalog from it.

zipBlob Blob
The pack, e.g. from an <input type="file">.
options Object
Import options.
options.name String
The cache name; defaults to the packed one.

Returns The cache's metadata, as listDefinitions lists it.

ExtjsUtils.OFFLINE.importDefinitionsFromZip(fileBlob).then(function(definitions) {
    return ExtjsUtils.OFFLINE.useDefinitions(definitions.id);
});

listAreas

function() : Promise.<Array.<Object>>helper# Lists every offline area saved on this browser, as area records.

Written as ExtjsUtils.OFFLINE.listAreas

Lists every offline area saved on this browser, as area records. An area record is a plain object with id, name, extent ([left, bottom, right, top] in map units), zoomMin, zoomMax, layerNames (the WMS map names / basemap names it covers), queryId, status ('downloading', 'ready' or 'partial' — partial means aborted or some tile/definition failed), tileCount, failedCount, bytes, createdAt, updatedAt and, when definitions were downloaded, definitionsId, definitionsBytes, definitionsFailedCount; imported packs also carry importedFrom. This is what an "offline areas" list in a host page shows.

Returns The area records, in store order.

ExtjsUtils.OFFLINE.listAreas().then(function(areas) {
    areas.forEach(function(area) {
        console.log(area.name, area.status, area.tileCount + " tiles", Math.round(area.bytes / 1048576) + " MB");
    });
});

listDefinitions

function() : Promise.<Array.<Object>>helper# The definitions caches kept in this browser (see downloadDefinitions), each as its metadata: {id, name, full, mapNames, capabilitiesUrl, done, failed, bytes, updatedAt} (full: the whole …

Written as ExtjsUtils.OFFLINE.listDefinitions

The definitions caches kept in this browser (see downloadDefinitions), each as its metadata: {id, name, full, mapNames, capabilitiesUrl, done, failed, bytes, updatedAt} (full: the whole GetCapabilities, else only mapNames). Pass the id to useDefinitions, deleteDefinitions, or downloadDefinitions({name}) to update it.

Returns The caches, by name.

ExtjsUtils.OFFLINE.listDefinitions().then(function(list) {
    list.forEach(function(d) { console.log(d.name, d.full ? "full catalog" : d.mapNames.join(", ")); });
});

onMapCacheEvent

function(callback) : functionhelper# Subscribes to the service worker's live feed of how it answered the map's tile requests: one event per cache hit, coarser-zoom crop or miss ({build, mode, layers, requestZoom, cachedZoom, ...}, …

Written as ExtjsUtils.OFFLINE.onMapCacheEvent

Subscribes to the service worker's live feed of how it answered the map's tile requests: one event per cache hit, coarser-zoom crop or miss ({build, mode, layers, requestZoom, cachedZoom, ...}, sent by ServiceWorker.js), completed with what only the page knows — mapZoom, the map's current zoom, and layerMaxZoom, the layer's max-zoom limit when it has one (a layer limited to 15 asks for zoom-15 tiles while the map sits at 17). For a debug panel or a log. Nothing arrives while no worker controls the page.

callback function
Called with each event.

Returns Call it to unsubscribe.

var stop = ExtjsUtils.OFFLINE.onMapCacheEvent(function(event) {
    console.log(event.layers + " z" + event.requestZoom + " served from z" + event.cachedZoom);
});

openDb

function() : Promise.<IDBDatabase>helper# Opens (and on first use creates) the IndexedDB database of area records, caching the connection for the page.

Written as ExtjsUtils.OFFLINE.openDb

Opens (and on first use creates) the IndexedDB database of area records, caching the connection for the page. The record functions below call it for you; use it directly only for custom queries on the store.

Returns The open database.

ExtjsUtils.OFFLINE.openDb().then(function(db) { console.log(db.objectStoreNames.contains("areas")); });

planArea

function(layers, options) : Promise.<Object>helper# Works an offline area out from a list of layers — name what goes offline, and the rest is derived:

Written as ExtjsUtils.OFFLINE.planArea

Works an offline area out from a list of layers — name what goes offline, and the rest is derived:

  • the maps to download: the cacheable layers in the list (WMS, XYZ/OSM); when the
      list has none, every cacheable map on the map;
  • extent: the bounds of the features of the vector layers in the list (the
      imóvel drawn by CSR:show_car, say); without any, the current map view;
  • zoomMin: 0, so the area also shows zoomed out (the levels above the extent
      cost a few tiles each);
  • zoomMax: the deepest maxZoom among those maps (their detail ends there —
      getMaxZoom), or 2 levels below the zoom at which the extent fits the map when
      none has a limit;
  • name: the title of the first vector layer, else the map names. Any of them can be given in options instead (a missing, null or "" value is derived), e.g. a smaller zoomMax to limit the zoom or an extent of your own. Waits for the query's layers. Rejects when a listed layer is not on the map, or is neither cacheable nor a vector layer. The result is plain data (postMessage-safe) and is what downloadArea/estimateArea take — downloadLayers does both steps.
layers Array.<(String|OpenLayers.Layer)>
Layers by name (LAYER.getMapName or layer.name), or the layers themselves.
options Object
Values to use instead of the derived ones.
options.extent OpenLayers.Bounds|Array.<Number>|Object
The area, in map units.
options.zoomMin Number
The first zoom level.
options.zoomMax Number
The last zoom level (inclusive) — the zoom limit.
options.name String
Display name of the area.

Returns {layerNames, extent: [left, bottom, right, top], zoomMin, zoomMax, name}.

// the imóvel's maps, its extent, down to the maps' own max zoom
ExtjsUtils.OFFLINE.planArea(["CSR:show_car", "CSR:planet_brasil_2024", "CSR:cultivo_cafe_cafe"]).then(function(plan) {
    console.log(plan.name + ": zoom " + plan.zoomMin + "-" + plan.zoomMax + ", " + plan.layerNames.join(", "));
    return ExtjsUtils.OFFLINE.estimateArea(plan);
});

prepareOffline

function(layers, options) : Promise.<Object>helper# Gets this page ready to work offline over an area in one call — the steps getOfflineReadiness checks, in order: downloads the tiles of the area worked out from layers (downloadLayers, …

Written as ExtjsUtils.OFFLINE.prepareOffline

Gets this page ready to work offline over an area in one call — the steps getOfflineReadiness checks, in order: downloads the tiles of the area worked out from layers (downloadLayers, planArea overrides in options), saves the map's catalog under a name (downloadDefinitions: the maps in use, so the map can be rebuilt from it), switches this page to it (useDefinitions) and, when the serving policy is NetworkOnly, sets CacheFirst so the downloads are used. Needs the network; rejects at once offline. To open the map with the catalog next time, use ?definitions=<catalogName>.

layers Array.<(String|OpenLayers.Layer)>
Layers by name or the layers themselves (see planArea).
options Object
downloadLayers options (id, name, extent, zoomMin, zoomMax, …) plus:
options.catalogName String
The catalog's cache name; defaults to the area id.
options.onProgress function
Called with {phase: 'tiles'|'catalog'|'switching', ...} (done, total, failed, bytes while downloading).

Returns {area, catalog, readiness}: the area record, the downloadDefinitions result and getOfflineReadiness({extent}) at the end.

// the imóvel and its maps, ready for the field
ExtjsUtils.OFFLINE.prepareOffline(["CSR:show_car", "CSR:planet_brasil_2024", "CSR:cultivo_cafe_cafe"], {
    id: "imovel_42",
    onProgress: function(p) { console.log(p.phase, p.done, p.total); }
}).then(function(result) {
    console.log(result.readiness.ready ? "ready offline" : "missing: " + result.readiness.missing.join(", "));
});

reloadMapTiles

function(options) : Numberhelper# Asks the tiled layers on the map for their tiles again, so what the screen shows follows the current serving policy and bucket contents right away instead of at the next pan or zoom.

Written as ExtjsUtils.OFFLINE.reloadMapTiles

Asks the tiled layers on the map for their tiles again, so what the screen shows follows the current serving policy and bucket contents right away instead of at the next pan or zoom. Every tile URL gets a fresh _dc value, so the browser cannot answer from its own memory/HTTP cache and the service worker sees each request; OfflineCacheKey.normalize drops _dc, so the offline buckets still match. WMS layers (and the maps inside a Composed layer) carry it as a request parameter, XYZ/OSM basemaps on their URL template. Hidden layers only get the new URLs (they request them when shown). setServingPolicy calls this for you.

options Object
{layers} — the OpenLayers.Layers, or getCacheableLayers() targets, to reload; default: every layer on the map.

Returns How many layers were asked to reload.

ExtjsUtils.OFFLINE.reloadMapTiles();
// only the downloaded-area layers
ExtjsUtils.OFFLINE.reloadMapTiles({ layers: ExtjsUtils.OFFLINE.getCacheableLayers() });

resetAllOfflineData

function() : Promise.<undefined>helper# Full reset ("Reset offline data"): deletes every offline area (cache + record), every shared definitions bucket and — when a service worker controls the page — the app-shell/dynamic caches and the …

Written as ExtjsUtils.OFFLINE.resetAllOfflineData

Full reset ("Reset offline data"): deletes every offline area (cache + record), every shared definitions bucket and — when a service worker controls the page — the app-shell/dynamic caches and the worker registration itself (the worker's self-destruct path, waited for up to 3 s). The page keeps working online; reload it to register the worker again. Use it for a "clear all offline data" button.

Returns Resolves once everything is cleared.

ExtjsUtils.OFFLINE.resetAllOfflineData().then(function() { location.reload(); });

sanitizeAreaId

function(raw) : String|nullhelper# Turns a user/host-provided cache id into a safe Cache Storage / IndexedDB key segment ([a-z0-9_-], max 80).

Written as ExtjsUtils.OFFLINE.sanitizeAreaId

Turns a user/host-provided cache id into a safe Cache Storage / IndexedDB key segment ([a-z0-9_-], max 80). Empty input ⇒ null (caller should use createAreaId). The Cache Storage bucket is always OfflineCacheKey.areaCacheName(id) = mappia_offline_area_<id>; the same id is the IndexedDB record key.

raw String
Proposed id (e.g. "fazenda-santa-clara").

Returns Sanitized id, or null when nothing usable remains.

ExtjsUtils.OFFLINE.sanitizeAreaId("Fazenda Santa Clara!"); // "fazenda_santa_clara"

saveAreaRecord

function(area) : Promise.<Object>helper# Inserts or replaces an area record (keyed by area.id), stamping updatedAt.

Written as ExtjsUtils.OFFLINE.saveAreaRecord

Inserts or replaces an area record (keyed by area.id), stamping updatedAt. The download/import functions save the record themselves; call it to persist your own edits to a record, e.g. a renamed area.

area Object
The area record to store (see listAreas for its shape); mutated to set updatedAt.

Returns The same record, once written.

ExtjsUtils.OFFLINE.getArea(areaId).then(function(area) {
    area.name = "Talhão norte";
    return ExtjsUtils.OFFLINE.saveAreaRecord(area);
});

saveBlobAsFile

function(blob, filename)helper# Hands a Blob to the browser as a file download (a programmatic <a download> click).

Written as ExtjsUtils.OFFLINE.saveBlobAsFile

Hands a Blob to the browser as a file download (a programmatic <a download> click). Works from inside the embedding iframe as long as it is not sandboxed without allow-downloads; the Blob never has to cross postMessage.

blob Blob
The file content, e.g. the zip from exportAreaAsZip.
filename String
The suggested file name.
ExtjsUtils.OFFLINE.saveBlobAsFile(blob, "mappia-offline-area-fazenda.zip");

selectCacheableLayers

function(layerNames) : Array.<Object>helper# getCacheableLayers, one target per map name and optionally only the named maps — the selection downloadArea's layerNames makes.

Written as ExtjsUtils.OFFLINE.selectCacheableLayers

getCacheableLayers, one target per map name and optionally only the named maps — the selection downloadArea's layerNames makes. The map name is the WMS LAYERS (e.g. "CSR:planet_brasil_2024"), or layer.name for XYZ/OSM ("OSM Mapnik"); it is what an area's layerNames record. When a map is on the map twice (a query adding an OSM basemap the platform already shows), the visible copy is kept. Names not on the map are left out — compare the lengths to detect them.

layerNames Array.<String>
Map names to keep, in this order; omitted ⇒ every cacheable map.

Returns Targets {layer, kind} as getCacheableLayers returns them.

var targets = ExtjsUtils.OFFLINE.selectCacheableLayers(["CSR:planet_brasil_2024", "CSR:cultivo_cafe_cafe"]);

setAreaEnabled

function(id, enabled, options) : Promise.<Object>helper# Switches one downloaded area on or off for serving, keeping its tiles: off, the worker leaves that bucket out of its index, so nothing in it is answered from the cache (nor used for the coarser-zoom …

Written as ExtjsUtils.OFFLINE.setAreaEnabled

Switches one downloaded area on or off for serving, keeping its tiles: off, the worker leaves that bucket out of its index, so nothing in it is answered from the cache (nor used for the coarser-zoom crop) until it is switched on again — the way to keep several areas downloaded (e.g. the same extent at zoom 14-16 and at 11-13, as two areas) and choose which one is live to test. Stored on the record (area.enabled, undefined = on) and in the bucket's own metadata entry, where the worker reads it. Waits for the worker to confirm it rebuilt its index under the new state, then asks the map to request its tiles again (reloadMapTiles), so the screen shows the difference at once instead of at the next pan or zoom. Pass {reloadTiles: false} to only store the toggle.

id String
The area id.
enabled Boolean
true to serve it, false to switch it off.
options Object
{reloadTiles} — defaults to true.

Returns The saved record.

ExtjsUtils.OFFLINE.setAreaEnabled(areaId, false);

setMaxZoom

function(target, zoom) : Number|nullhelper# Sets — or, with null, clears — the "real max zoom" of a WMS map at runtime: past it the map keeps requesting the max-zoom tile and stretches it, so what the user sees and what an offline area …

Written as ExtjsUtils.OFFLINE.setMaxZoom

Sets — or, with null, clears — the "real max zoom" of a WMS map at runtime: past it the map keeps requesting the max-zoom tile and stretches it, so what the user sees and what an offline area downloads (zooms above the limit collapse onto it) change at once. A raster whose detail ends at some zoom (suggestMaxZoom) downloads far fewer tiles this way. XYZ/OSM basemaps cannot be limited (describeCacheableLayers → canLimitMaxZoom).

target Object|String
A {layer, kind} entry from getCacheableLayers, or the map name.
zoom Number|null
The deepest zoom to request, or null for no limit.

Returns The limit now in force (getMaxZoom).

ExtjsUtils.OFFLINE.setMaxZoom("CSR:planet_brasil_2024", 15);

setServingPolicy

function(policy) : Promise.<Object>helper# Sets the serving policy (see getServingPolicy), tells the worker — which applies it from the next request on, no page reload — and then asks the map to request its tiles again (reloadMapTiles), …

Written as ExtjsUtils.OFFLINE.setServingPolicy

Sets the serving policy (see getServingPolicy), tells the worker — which applies it from the next request on, no page reload — and then asks the map to request its tiles again (reloadMapTiles), so the screen shows the new mode at once instead of at the next pan or zoom. Pass reloadTiles: false to only store the policy (e.g. right before a download).

policy Object
{mode, forceOffline, reloadTiles} — mode is "CacheFirst", "NetworkFirst", "CacheOnly" or "NetworkOnly" (legacy kebab-case accepted); forceOffline (default false) makes the worker treat the network as down regardless of navigator.onLine — any call without it turns simulated offline back off; reloadTiles defaults to true.

Returns The stored policy {mode, forceOffline, updatedAt}.

ExtjsUtils.OFFLINE.setServingPolicy({ mode: "CacheFirst" });
// store only; the tiles on screen keep what they show
ExtjsUtils.OFFLINE.setServingPolicy({ mode: "NetworkOnly", reloadTiles: false });
// simulate being offline, without DevTools throttling
ExtjsUtils.OFFLINE.setServingPolicy({ mode: "CacheOnly", forceOffline: true });

showAreaOutline

function(extent) : Booleanhelper# Outlines an area on the map — a dashed rectangle, e.g. the extent about to be downloaded — or, with no extent, removes the outline.

Written as ExtjsUtils.OFFLINE.showAreaOutline

Outlines an area on the map — a dashed rectangle, e.g. the extent about to be downloaded — or, with no extent, removes the outline. One outline at a time, on a vector layer of its own kept out of the layer list.

extent OpenLayers.Bounds|Array.<Number>|Object|null
The area, in map units; null removes the outline.

Returns true when an outline is shown.

ExtjsUtils.OFFLINE.showAreaOutline(ExtjsUtils.LAYER.getLayerExtent("CSR:show_car"));

suggestMaxZoom

function(target) : Object|nullhelper# Suggests the finest zoom at which a raster layer still adds real detail, from the pixel size its GetCapabilities abstract declares (the platform's rasters carry a generated "Cell Width : N" line; …

Written as ExtjsUtils.OFFLINE.suggestMaxZoom

Suggests the finest zoom at which a raster layer still adds real detail, from the pixel size its GetCapabilities abstract declares (the platform's rasters carry a generated "Cell Width : N" line; e.g. a 29.04 m cell size gives zoom 13 on the Web Mercator series, so zoom 14+ is pure upsampling). Cell sizes below 1 are read as degrees and converted at the equator. It is a suggestion, not a setting: pass result.maxZoom to layer.setMaxZoom() (or put maxZoom in the layer config) to actually apply it, which shrinks the offline area (see effectiveZoom). The layer's capabilities record must be loaded (wait for the "local" source).

target Object|OpenLayers.Layer
A {layer, kind} entry from getCacheableLayers, or the layer itself.

Returns {cellSize, metersPerCell, maxZoom}, or null when the abstract declares no cell size.

ExtjsUtils.OFFLINE.getCacheableLayers().forEach(function(t) {
    var suggestion = ExtjsUtils.OFFLINE.suggestMaxZoom(t);
    if (suggestion && typeof t.layer.setMaxZoom === "function") t.layer.setMaxZoom(suggestion.maxZoom);
});

updateServiceWorker

function() : Promise.<Object>helper# Asks the server for a newer service worker script (registration.update()) and activates it (activateLatestServiceWorker).

Written as ExtjsUtils.OFFLINE.updateServiceWorker

Asks the server for a newer service worker script (registration.update()) and activates it (activateLatestServiceWorker). Never rejects.

Returns The activateLatestServiceWorker result plus {updated: true}, or {ok: false, error}.

ExtjsUtils.OFFLINE.updateServiceWorker().then(function(sw) {
    console.log(sw.ok ? "now on " + sw.build : sw.error);
});

useDefinitions

function(name) : Promise.<(String|null)>helper# Chooses where THIS page loads its catalog (the WMS GetCapabilities) from: a named definitions cache, or — with null or "live" — the live server.

Written as ExtjsUtils.OFFLINE.useDefinitions

Chooses where THIS page loads its catalog (the WMS GetCapabilities) from: a named definitions cache, or — with null or "live" — the live server. Only this page is affected: every other Mappia instance keeps its own choice. The catalog is reloaded at once, and the query's layers wait for it (QUERY.sourceLoading), so a query can make the choice in its && chain before its layer list — e.g. to start from a cached catalog when the map server is unreachable. To choose before the page's first catalog load, open the map page with ?definitions=<name> instead. Only the service worker answers from a cache, so a cache needs this page controlled by it.

name String|null
The cache name or id (listDefinitions), or null / "live" for the live catalog.

Returns Resolves with the choice once the catalog has reloaded; rejects, changing nothing, for a cache when no service worker controls this page.

// in a query: layers built from the cached catalog "fazenda-42"
ExtjsUtils.OFFLINE.useDefinitions("fazenda-42") && [
    { name: "CSR:cultivo_cafe_cafe", title: "Café", visibility: true }
]

verifyAreaServed

function(id, options) : Promise.<Object>helper# Proves an area is really served offline.

Written as ExtjsUtils.OFFLINE.verifyAreaServed

Proves an area is really served offline. It re-requests a sample of the URLs in the area's cache through the page's normal fetch path (bypassing the HTTP cache), so the service worker sees them like any tile request, and counts the responses the worker stamped as coming from this area's bucket. Without a controlling worker nothing can be served from the cache at all — controlled: false says so (on localhost the worker is off unless the service-worker config enables it, and a freshly registered worker only controls the page from its next load). It also checks coverage against the bucket's own metadata: re-enumerates the tiles the recorded extent, zoom range and layers imply — with the live layers, so the same query must be loaded — and reports which are missing from the cache.

id String
The area id.
options Object
Verification options.
options.sampleSize Number
How many cached URLs to re-request; 0 checks every entry.
options.signal AbortSignal
Aborts the sample requests.
options.coverage Boolean
false to skip the coverage re-enumeration.

Returns {id, cacheName, controlled, metadata, cachedEntries, checked, servedFromCache, servedByNetwork, failed, entries: [{url, status, servedFrom}], coverage: {layersFound, expected, present, missing, missingSample} | null}.

ExtjsUtils.OFFLINE.verifyAreaServed(areaId, {sampleSize: 30}).then(function(result) {
    if (!result.controlled) console.warn("no service worker controls this page yet");
    console.log(result.servedFromCache + "/" + result.checked + " served from the area cache");
    if (result.coverage) console.log(result.coverage.missing + " expected tiles missing");
});

whenLayersReady

function(timeoutMs) : Promisehelper# Resolves once the query's layers are on the map: the remote WMS sources the query registered have loaded their capabilities (QUERY.sourceLoading) and the layer files have loaded (QUERY.layerLoading).

Written as ExtjsUtils.OFFLINE.whenLayersReady

Resolves once the query's layers are on the map: the remote WMS sources the query registered have loaded their capabilities (QUERY.sourceLoading) and the layer files have loaded (QUERY.layerLoading). The page's own sources (the "local" catalog) are already loaded by then — the platform applies a query only after every source is ready. Call it before getCacheableLayers/selectCacheableLayers in code that runs right after a query is applied — earlier, a {name: "CSR:..."} layer may simply not be on the map yet and an area downloaded then would silently miss it. downloadArea and downloadAreaAsZip wait for it themselves unless given layers. Never rejects: after timeoutMs it resolves with whatever loaded.

timeoutMs Number
Longest wait, in milliseconds.

Returns Resolves (with no value) when the layers are ready or the time is up.

ExtjsUtils.OFFLINE.whenLayersReady().then(function() {
    console.log(ExtjsUtils.OFFLINE.getCacheableLayers().length + " cacheable layers");
});

CAPABILITIES · catalogue filter (options=capabilities)

CAPABILITIES3 entries
Prunes a WMS GetCapabilities document to the maps a query actually uses. It is what ?options=capabilities serves per query and what the offline engine caches.
Usage: ExtjsUtils.CAPABILITIES

filterDocument

function(xmlDoc, mapNames, projectionCode) : Documenthelper# Prunes a parsed WMS GetCapabilities Document in place so it only describes mapNames: every nested <Layer> not in the list is dropped (the kept ones are re-appended in the list's order), then …

Written as ExtjsUtils.CAPABILITIES.filterDocument

Prunes a parsed WMS GetCapabilities Document in place so it only describes mapNames: every nested <Layer> not in the list is dropped (the kept ones are re-appended in the list's order), then every WMS-C <TileSet> of another layer, then every top-level <SRS> no remaining layer (nor the map) uses. This is the same pruning the editor applies when a query is saved, and what the offline engine applies before caching the live capabilities.

xmlDoc Document
The parsed GetCapabilities XML document; it is mutated.
mapNames Array.<String>
WMS layer names to keep (see getMapNamesInUse).
projectionCode String
Map projection (e.g. "EPSG:900913"), kept in the SRS list even if no layer declares it.

Returns The same document, pruned.

var map = ExtjsUtils.JS.getMap();
var xmlDoc = new OpenLayers.Format.XML().read(capabilitiesXmlText);
ExtjsUtils.CAPABILITIES.filterDocument(xmlDoc, ExtjsUtils.CAPABILITIES.getMapNamesInUse(map), map.projection);

filterText

function(xmlText, mapNames, projectionCode) : Stringhelper# filterDocument() for XML text in and text out: parses xmlText, prunes it to mapNames and serializes the result back to a string.

Written as ExtjsUtils.CAPABILITIES.filterText

filterDocument() for XML text in and text out: parses xmlText, prunes it to mapNames and serializes the result back to a string. Handy when the capabilities came from a fetch/XHR response and must be stored or served as text again.

xmlText String
The raw GetCapabilities XML text.
mapNames Array.<String>
WMS layer names to keep (see getMapNamesInUse).
projectionCode String
Map projection (e.g. "EPSG:900913"), kept in the SRS list even if no layer declares it.

Returns The serialized, pruned document.

var map = ExtjsUtils.JS.getMap();
fetch(ExtjsUtils.REQUEST.getGeoserverBaseUrl() + "/wms?SERVICE=WMS&REQUEST=GetCapabilities&VERSION=1.1.1")
    .then(function(response) { return response.text(); })
    .then(function(xmlText) {
        var pruned = ExtjsUtils.CAPABILITIES.filterText(xmlText,
            ExtjsUtils.CAPABILITIES.getMapNamesInUse(map), map.projection);
        console.log(pruned.length + " bytes after pruning");
    });

getMapNamesInUse

function(map) : Array.<String>helper# Lists the WMS map names a map currently uses: each layer's LAYERS parameter (comma-separated, e.g. "CSR:a,CSR:b") plus its otherNames (LayersProperties.otherNames — maps the query needs at …

Written as ExtjsUtils.CAPABILITIES.getMapNamesInUse

Lists the WMS map names a map currently uses: each layer's LAYERS parameter (comma-separated, e.g. "CSR:a,CSR:b") plus its otherNames (LayersProperties.otherNames — maps the query needs at runtime but does not draw initially). Layers without a LAYERS parameter (XYZ/OSM/vector) contribute nothing. The result is unique, in first-seen order. Use it to know which maps a capabilities document must keep, or simply to enumerate the WMS maps on screen.

map OpenLayers.Map
The map whose layers are inspected (normally ExtjsUtils.JS.getMap()).

Returns Unique WMS layer names, e.g. ["CSR:estados", "CSR:cultivo_cafe_cafe"].

var names = ExtjsUtils.CAPABILITIES.getMapNamesInUse(ExtjsUtils.JS.getMap());
console.log(names); // ["CSR:estados", "CSR:cultivo_cafe_cafe"]

Other globals and libraries

Globals outside ExtjsUtils that a query can use: a vector overlay built from code (Ext.LayerAdditional), the script loader, the interface texts (Lang), mobile detection, and the bundled Highcharts library.

Ext.LayerAdditional · overlay layer built from code

LayerAdditional16 entries
A private vector layer kept out of the layer tree, for markers, highlights and geometry pushed from the parent page.
Usage: var overlay = new Ext.LayerAdditional({}, ExtjsUtils.JS.getMap()); overlay.createLayer(); overlay.addFeatures(features);

LayerAdditional

function(config, map)# new Ext.LayerAdditional(config, map) — a private vector overlay: an OpenLayers.Layer.Vector that is added to the map but deliberately kept out of the layer tree (displayInLayerSwitcher: false), …

Written as Ext.LayerAdditional

new Ext.LayerAdditional(config, map) — a private vector overlay: an OpenLayers.Layer.Vector that is added to the map but deliberately kept out of the layer tree (displayInLayerSwitcher: false), for markers, highlights, search results and geometry pushed in from a parent page. Use it when something must render on the map without becoming a user-visible, toggleable tree entry; for ordinary user-facing data prefer a declarative source: "file" layer. The backing layer is created lazily by createLayer() (or by drawFeature()), and features added before that are buffered and flushed on creation. It does not follow the visibility of any other layer on its own.

Constructor arguments: config — an object with the optional keys listeners (an Ext listeners object for the events below) and layerConfig (when given, the layer is created immediately with createLayer(layerConfig, layerConfig.async)); map — the OpenLayers.Map to draw on, normally ExtjsUtils.JS.getMap() / app.mapPanel.map.

Events (Ext.util.Observable): addedLayer — fired with {layer} right after the vector layer is created and added to the map; removedLayer — fired with {layer} by removeLayer() right after the layer is removed from the map.

Public properties: vectorLayer — the OpenLayers.Layer.Vector, null until created; map — the map given to the constructor.

config Object
Optional configuration: listeners and/or layerConfig as described above; pass {} for none.
map OpenLayers.Map
The map the overlay is drawn on.
// a reusable highlight overlay driven by parent-page messages
ExtjsUtils.QUERY.setQueryGlobalProperties({
    highlightLayer: null,
    ensureHighlightLayer: function() {
        if (!window.highlightLayer) {
            window.highlightLayer = new Ext.LayerAdditional({}, ExtjsUtils.JS.getMap());
            window.highlightLayer.createLayer({
                styleMap: new OpenLayers.StyleMap({
                    "default": new OpenLayers.Style({fillColor: "#ffcc33", fillOpacity: 0.35, strokeColor: "#ff6600", strokeWidth: 2, pointRadius: 6, graphicName: "circle"})
                })
            });
        }
        return window.highlightLayer;
    },
    showHighlight: function(geojson) {
        var overlay = window.ensureHighlightLayer();
        overlay.removeFeatures(); // no argument: clear everything
        overlay.addFeatures(ExtjsUtils.GEOJSON.geojson2Features(geojson));
    }
}) && ExtjsUtils.QUERY.setMappiaIoCallback(function(message) {
    if (message && message.type === "geojson") window.showHighlight(message.msg);
}) && [
    { name: "CSR:estados", title: "Estados", visibility: true }
]
// listen to the layer lifecycle
var overlay = new Ext.LayerAdditional({
    listeners: { addedLayer: function(evt) { console.log("created", evt.layer.id); } }
}, ExtjsUtils.JS.getMap());

addFeatures

function(features)# Adds one feature or an array of features to the overlay.

Adds one feature or an array of features to the overlay. When the layer does not exist yet the features are buffered and added as soon as createLayer runs, so it is safe to call in any order. Features must be in the map projection — build them with createPoint/createFeature, or convert GeoJSON with ExtjsUtils.GEOJSON.geojson2Features.

features OpenLayers.Feature.Vector|Array.<OpenLayers.Feature.Vector>
The feature(s) to add.
overlay.addFeatures(new OpenLayers.Feature.Vector(overlay.createPoint(-44.0, -20.5, "EPSG:4326"), {name: "Fazenda"}));

createFeature

function(geometries) : OpenLayers.Feature.Vector# Wraps one geometry, or an array of geometries (combined into an OpenLayers.Geometry.Collection), in a vector feature you can then style and add with drawFeature/addFeatures.

Wraps one geometry, or an array of geometries (combined into an OpenLayers.Geometry.Collection), in a vector feature you can then style and add with drawFeature/addFeatures.

geometries OpenLayers.Geometry|Array.<OpenLayers.Geometry>
The geometry, or several geometries drawn as one feature.

Returns The new feature (no attributes, no style).

var feature = overlay.createFeature(overlay.createPoint(-44.0, -20.5, "EPSG:4326"));
feature.attributes.name = "Fazenda";
overlay.addFeatures(feature);

createImageTile

function(bbox, projection) : OpenLayers.Feature.Vector|undefined# Builds a feature representing an image tile: a rectangle covering bbox plus a point at its centre, combined in one geometry collection.

Builds a feature representing an image tile: a rectangle covering bbox plus a point at its centre, combined in one geometry collection. Style it with externalGraphic (the image URL) and pointRadius (half the image size) to draw a picture at the centre of the box, e.g. a thumbnail or a symbol over an area. Returns undefined (and logs) when bbox does not have exactly four numbers.

bbox Array.<Number>
The tile bounds as [left, bottom, right, top].
projection String|OpenLayers.Projection
The projection bbox is expressed in.

Returns The tile feature, or undefined for an invalid bbox.

var tile = overlay.createImageTile([-44.1, -20.6, -43.9, -20.4], "EPSG:4326");
overlay.drawFeature(tile, {externalGraphic: "/theme/app/img/logo.png", pointRadius: 24, strokeColor: "#666666", fillOpacity: 0});

createLayer

function(layerConfig, async)# Creates the backing vector layer, once: the call is ignored when the layer already exists or its creation is pending, and the configuration of an existing layer is not updated.

Creates the backing vector layer, once: the call is ignored when the layer already exists or its creation is pending, and the configuration of an existing layer is not updated. The layer gets a generated id, displayInLayerSwitcher: false and the initialVisibility, is added to the map, addedLayer is fired and the features buffered by addFeatures are flushed into it. When layerConfig is omitted a built-in grey/white styleMap for points, lines and polygons is used. Creation is synchronous by default; pass async: true to defer it to a short timeout (useful when called from inside another map event).

layerConfig Object
OpenLayers.Layer.Vector options — typically {styleMap: new OpenLayers.StyleMap({...})}; omitted ⇒ the default style.
async Boolean
true to create the layer asynchronously (via setTimeout); false, the default, creates it immediately.
var overlay = new Ext.LayerAdditional({}, ExtjsUtils.JS.getMap());
overlay.createLayer({
    styleMap: new OpenLayers.StyleMap({
        "default": new OpenLayers.Style({fillColor: "${color}", fillOpacity: 0.4, strokeColor: "#333333", strokeWidth: 1}),
        "select": new OpenLayers.Style({strokeColor: "#ff0000", strokeWidth: 3})
    })
});

createPoint

function(x, y, projection) : OpenLayers.Geometry.Point# Creates a point geometry from coordinates given in projection and transforms it into the map projection, ready to be wrapped in a feature or used as a polygon vertex.

Creates a point geometry from coordinates given in projection and transforms it into the map projection, ready to be wrapped in a feature or used as a polygon vertex. For a longitude/latitude pair pass "EPSG:4326".

x Number
The horizontal coordinate (longitude for EPSG:4326).
y Number
The vertical coordinate (latitude for EPSG:4326).
projection String|OpenLayers.Projection
The projection x/y are expressed in (see resolveProjection).

Returns The point, in the map projection.

var marker = new OpenLayers.Feature.Vector(overlay.createPoint(-46.63, -23.55, "EPSG:4326"));
overlay.addFeatures(marker);

createPolygon

function(points) : OpenLayers.Geometry.Polygon# Creates a polygon geometry with a single ring whose vertices are the given points (in order; the ring is closed automatically).

Creates a polygon geometry with a single ring whose vertices are the given points (in order; the ring is closed automatically).

points Array.<OpenLayers.Geometry.Point>
The vertices, already in the map projection (e.g. from createPoint).

Returns The polygon.

var square = overlay.createPolygon([
    overlay.createPoint(-44.1, -20.4, "EPSG:4326"), overlay.createPoint(-43.9, -20.4, "EPSG:4326"),
    overlay.createPoint(-43.9, -20.6, "EPSG:4326"), overlay.createPoint(-44.1, -20.6, "EPSG:4326")
]);
overlay.drawFeature(overlay.createFeature(square), {fillColor: "#00ff00", fillOpacity: 0.2});

drawFeature

function(feature, style)# Styles and draws a feature in one call: creates the layer if needed (createLayer() with the default style), sets feature.style to style completed with OpenLayers' default symbolizer, and adds the feature.

Styles and draws a feature in one call: creates the layer if needed (createLayer() with the default style), sets feature.style to style completed with OpenLayers' default symbolizer, and adds the feature. A per-feature style set this way takes precedence over the layer's styleMap.

feature OpenLayers.Feature.Vector
The feature to draw (see createFeature).
style Object
OpenLayers symbolizer properties (fillColor, fillOpacity, strokeColor, strokeWidth, pointRadius, externalGraphic, label, ...); omitted ⇒ the layer's styleMap applies.
var point = overlay.createFeature(overlay.createPoint(-44.0, -20.5, "EPSG:4326"));
overlay.drawFeature(point, {pointRadius: 8, fillColor: "#ff0000", strokeColor: "#ffffff", strokeWidth: 2});

drawLatLongExtents

function(llbbox, color)# Draws a highlighted rectangle for a lon/lat bounding box — the way the interface outlines a layer's extent: two stacked rectangles, a wide white border with a translucent fill under a thin coloured border.

Draws a highlighted rectangle for a lon/lat bounding box — the way the interface outlines a layer's extent: two stacked rectangles, a wide white border with a translucent fill under a thin coloured border. Creates the layer if needed. Logs and does nothing when llbbox does not have exactly four numbers.

llbbox Array.<Number>
The bounds in EPSG:4326 as [left, bottom, right, top] (west, south, east, north), e.g. a record's llbbox.
color String
Fill colour (and, by default, the thin border colour #FFC000 is used).
var record = ExtjsUtils.LAYER.getLayersRecord("CSR:estados");
overlay.drawLatLongExtents(record.get("llbbox"), "#ff8800");

map

OpenLayers.Map# The OpenLayers.Map the overlay draws on, as given to the constructor.

The OpenLayers.Map the overlay draws on, as given to the constructor.

removeFeatures

function(features)# Removes features from the overlay — the given feature or array of features, or every feature when the argument is omitted (the usual "clear the highlight" call).

Removes features from the overlay — the given feature or array of features, or every feature when the argument is omitted (the usual "clear the highlight" call). Works before the layer exists too, by dropping them from the pending buffer.

features OpenLayers.Feature.Vector|Array.<OpenLayers.Feature.Vector>
The feature(s) to remove; omit to remove all.
overlay.removeFeatures();            // clear everything
overlay.removeFeatures(oneFeature);  // remove a single feature

removeLayer

function()# Removes the vector layer from the map (firing removedLayer), cancels a pending async creation and forgets the layer, so the next createLayer/drawFeature creates a fresh one.

Removes the vector layer from the map (firing removedLayer), cancels a pending async creation and forgets the layer, so the next createLayer/drawFeature creates a fresh one. To only clear the drawn features and keep the layer, use removeFeatures() instead.

overlay.removeLayer();

resolveProjection

function(projection) : OpenLayers.Projection# Normalizes a projection given as an EPSG string ("EPSG:4326"), an OpenLayers.Projection or any object with getCode() into an OpenLayers.Projection, falling back to the map projection when it is missing.

Normalizes a projection given as an EPSG string ("EPSG:4326"), an OpenLayers.Projection or any object with getCode() into an OpenLayers.Projection, falling back to the map projection when it is missing. Delegates to ExtjsUtils.PROJECTION.resolveProjectionObject; createPoint uses it, so you rarely need to call it yourself.

projection String|OpenLayers.Projection|Object
The projection to resolve; falsy ⇒ the map projection.

Returns The resolved projection object.

var proj = overlay.resolveProjection("EPSG:4326");
console.log(proj.getCode()); // "EPSG:4326"

setOverLayer

function(baseLayer)# Makes sure the overlay is stacked above baseLayer: moves the vector layer's index to at least that layer's index (map.setLayerIndex).

Makes sure the overlay is stacked above baseLayer: moves the vector layer's index to at least that layer's index (map.setLayerIndex). Call it after createLayer (or after starting an async creation); the reorder happens on a short timeout to work around an OpenLayers/Ext re-entrancy bug when called from inside an event, so it is not effective synchronously.

baseLayer OpenLayers.Layer
The layer that must end up below the overlay.
overlay.createLayer();
overlay.setOverLayer(ExtjsUtils.LAYER.getLayerByName("CSR:estados"));

setVisibility

function(state)# Shows or hides the overlay.

Shows or hides the overlay. Before the layer is created it only records the initial visibility the layer will be created with; afterwards it calls vectorLayer.setVisibility(state).

state Boolean
true to show the overlay, false to hide it.
overlay.setVisibility(!MOBILE_UTILS.isMobile());

vectorLayer

OpenLayers.Layer.Vector|null# The backing OpenLayers.Layer.Vector where the features are drawn.

The backing OpenLayers.Layer.Vector where the features are drawn. null until createLayer runs, then a real OpenLayers vector layer you may hand to other controls, e.g. new OpenLayers.Control.CustomSelectFeature(overlay.vectorLayer, {...}).

overlay.createLayer();
overlay.vectorLayer.events.register("featureselected", null, function(evt) { console.log(evt.feature); });

AsyncLoader · load scripts once

AsyncLoader1 entry
Load one or more external resources by its URL and call a callback function when it finishes.
array: {Array} A array of resource urls to load.
callback: Function that will be called when the load ends.
Usage: AsyncLoader.loadScriptOnce({Array}, {Function}}

loadScriptOnce

function(src, callback)# Loads one or more external resources by URL, each of them only once per page, and calls callback after every URL of the set has finished loading.

Loads one or more external resources by URL, each of them only once per page, and calls callback after every URL of the set has finished loading. A URL ending in .css is inserted as a <link rel="stylesheet">; any other URL is inserted as an async <script> tag (placed before the first script of the page). Use it inside a query to lazy-load libraries or data files (Highcharts modules, PapaParse, a pre-baked JS data file) right before the code that needs them.

Rules worth knowing: a URL that already finished loading is skipped, so repeated calls are cheap and safe; when nothing in the set still needs loading the callback runs synchronously, before this function returns; calls made with the same set of pending URLs share one loading queue, and all their callbacks run once that set completes; the callback receives no arguments.

src String|Array.<String>
A resource URL, or an array of URLs to load together.
callback function
Called (with no arguments) once every URL in src is loaded.
AsyncLoader.loadScriptOnce(["/theme/app/js/papaparse.min.js", "/theme/app/js/highcharts/latest/sankey.js"], function() {
    // both files are loaded (or were already loaded): safe to use Papa and Highcharts.seriesTypes.sankey
    drawSankeyChart();
});
AsyncLoader.loadScriptOnce("/theme/app/css/my-query-styles.css");

Lang · interface texts

Lang7 entries
The interface translation dictionary (pt-BR by default, English with ?lang=eng). Queries read the same strings the interface shows, e.g. Lang.maps.

LIST

Array.<String># The language codes the interface supports, in order: ['ptbr', 'eng'].

Written as Lang.LIST

The language codes the interface supports, in order: ['ptbr', 'eng']. The first one is the default when ?lang= is absent or unknown; the others are the accepted values of the lang URL parameter.

Lang.LIST.indexOf(ExtjsUtils.REQUEST.getParameterByName("lang")) !== -1

Lang

Object# The interface translation dictionary, a global object whose keys are the strings the interface shows (Lang.maps, Lang.showLayerLegend, Lang.clearTransition, Lang.expandChart, …

Written as Lang

The interface translation dictionary, a global object whose keys are the strings the interface shows (Lang.maps, Lang.showLayerLegend, Lang.clearTransition, Lang.expandChart, Lang.layerDetails, Lang.yes, Lang.cancel, ...). The values are Brazilian Portuguese by default; when the page is opened with ?lang=eng the entries of Lang.languages.eng are applied over them at load time (Lang.updateLang()), so a query that reads Lang.<key> gets the same wording the interface is using and follows the language switch for free. The key list is the object itself (this file); read a key, do not assign to it.

// a tenant button whose caption follows the interface language
descriptionHtml: '{{button|id=legendBtn|text=' + Lang.showLayerLegend + '}}'
var caption = Lang.getLang() === "eng" ? "Coffee area" : "Área de café";

formatMessage

function(content, params) : String# Fills the {placeholder} slots of a message template with the values of params: every {name} in content is replaced by params.name; a placeholder without a matching key is left as it is.

Written as Lang.formatMessage

Fills the {placeholder} slots of a message template with the values of params: every {name} in content is replaced by params.name; a placeholder without a matching key is left as it is. Several Lang messages are templates (e.g. Lang.invalidLayerName contains {layerName}), and a query can use the same mechanism for its own messages.

content String
The template text containing {name} placeholders (typically a Lang message).
params Object
Values keyed by placeholder name.

Returns The template with the placeholders replaced.

Lang.formatMessage(Lang.invalidLayerName, {layerName: "CSR:estados"});
// 'O nome do mapa "CSR:estados" é inválido ou o mapa não foi carregado corretamente.'
Lang.formatMessage("{count} features selected in {name}", {count: 3, name: "Minas Gerais"});

getLang

function() : String# Returns the language code the interface is currently using: "ptbr" (default) or "eng" when the page was opened with ?lang=eng.

Written as Lang.getLang

Returns the language code the interface is currently using: "ptbr" (default) or "eng" when the page was opened with ?lang=eng. Use it to pick language-specific content of your own (labels, URLs, number formats) consistently with the interface.

Returns The current language code, one of Lang.LIST.

var chartTitle = Lang.getLang() === "eng" ? "Deforestation by year" : "Desmatamento por ano";

lang

String# The language code currently applied, "ptbr" or "eng"; set by updateLang() at load time from the ?lang= URL parameter.

Written as Lang.lang

The language code currently applied, "ptbr" or "eng"; set by updateLang() at load time from the ?lang= URL parameter. Read it through Lang.getLang().

if (Lang.lang === "eng") { ... }

updateLang

function()# Applies the language requested by the ?lang= URL parameter: when it names a known translation (Lang.languages.eng) its entries are copied over the Lang keys, and Lang.lang is set to it; …

Written as Lang.updateLang

Applies the language requested by the ?lang= URL parameter: when it names a known translation (Lang.languages.eng) its entries are copied over the Lang keys, and Lang.lang is set to it; otherwise the default ptbr stays and Lang.lang is "ptbr". The platform calls it once at load time, before any interface text is rendered; a query does not need to call it, but calling it again is harmless.

Lang.updateLang();
console.log(Lang.getLang()); // "eng" when the URL has ?lang=eng

verifySupportedBrowser

function()# Shows the platform's "browser not supported" alert (Lang.browserNotSupported, via ExtjsUtils.ALERTIFY.alert) when ExtjsUtils.CHECK.browserSupported() says the current browser is too old; does nothing otherwise.

Written as Lang.verifySupportedBrowser

Shows the platform's "browser not supported" alert (Lang.browserNotSupported, via ExtjsUtils.ALERTIFY.alert) when ExtjsUtils.CHECK.browserSupported() says the current browser is too old; does nothing otherwise. The interface calls it at startup; a query may call it again before enabling a feature that needs a modern browser.

Lang.verifySupportedBrowser();

MOBILE_UTILS · mobile layout

MobileUtils1 entry
Mobile layout detection shared by the desktop and mobile interfaces (global MOBILE_UTILS).
Usage: MOBILE_UTILS.isMobile()

isMobile

function() : Boolean# Tells whether the interface is currently rendered in its mobile layout.

Written as MOBILE_UTILS.isMobile

Tells whether the interface is currently rendered in its mobile layout. It reads the --is-mobile CSS variable that the responsive stylesheet sets from a media query (1 when the viewport is narrower than 768px, 0 otherwise), so the answer follows the viewport size and changes when the window is resized — re-check it inside a resize handler when a layout decision depends on it. This is distinct from ExtjsUtils.CHECK.isMobile(), which is device based (user agent / orientation).

Returns true when the mobile layout is active.

function layoutCharts() {
    if (MOBILE_UTILS.isMobile()) {
        // narrow screen: stack the chart under the map
    } else {
        // wide screen: keep the chart beside the map
    }
}
layoutCharts();
ExtjsUtils.addDomListener(window, "resize", layoutCharts);

Highcharts · charts

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

chart

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

Written as Highcharts.chart

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

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

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

Returns The chart instance.

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

Sankey · flow charts (Highcharts module)

Sankey1 entry
Soon.

load

function() : undefined# A Sankey diagram - transitions between categories drawn as flows - is a Highcharts module rather than part of the bundled build, so it is loaded on demand before the chart is created.

A Sankey diagram - transitions between categories drawn as flows - is a Highcharts module rather than part of the bundled build, so it is loaded on demand before the chart is created. Once the module is in place, a Sankey is an ordinary Highcharts chart with type: 'sankey', whose data is a list of [from, to, weight] rows: one row per transition, which is exactly the shape a transition matrix produces.

Load it once, when the panel is ready, and draw inside the callback - the module is shared, so a second call with the same URL is free.

Returns Nothing; the chart is created in the callback.

AsyncLoader.loadScriptOnce('/theme/app/js/highcharts/latest/sankey.js', function () {
    Highcharts.chart('transitions_chart', {
        title: { text: 'Land use transitions' },
        series: [{
            type: 'sankey',
            keys: ['from', 'to', 'weight'],
            data: [['Forest', 'Pasture', 120], ['Pasture', 'Crop', 45]]
        }]
    });
});