Configurer - Custom control¶
Un custom control est une interface permettant à l’utilisateur d’interagir avec une couche. Le customcontrol est affiché dans le bloc de légende associée à la couche concernée.
Un custom control est associé à une seule couche et est constitué de deux fichiers html + javascript. Ces deux fichiers doivent obligatoirement être nommé comme l” id de la couche associée.
Syntaxe
<layer id="moncustom"
customcontrol="true"
customcontrolpath="chemin_vers_fichiers">
</layer>
Paramètres custom control
customcontrol: paramètre qui indique si mviewer doit charger un customcontrol. valeurs : true || false. Défaut = false.customcontrolpath: paramètre qui indique où mviewer doit charger le customcontrol. Si ce paramètre n’est pas renseigné, le customcontrol est recherché dans le répertoire racine customcontrols.
Exemple
<layer id="heatmap"
name="Earthquakes Heatmap"
visible="true"
url="demo/heatmap/customlayer.js"
queryable="true"
type="customlayer"
customcontrol="true"
customcontrolpath="demo/heatmap/control"
legendurl="demo/heatmap/legend.png"
opacity="1"
expanded="true"
attribution=""
metadata=""
metadata-csw="">
</layer>
Cas pratique : customcontrol pour avoir plusieurs filtres sur une couche¶
Ce customcontrol permet d’avoir la possibilité de filtrer une couche type WMS sur plusieurs attributs comme ceci :
Création du customcontrol
Comme détaillé dans la page Développer un customControl, un customcontrol est composé de 2 fichiers. Dans le cas du filtre sur plusieurs atttributs d’une couche WMS, vous trouverez les fichiers dans le dossier /demo/filtres_multiples/customcontrol. Les 2 fichiers doivent avoir le même nom que l’id de la couche appelée dans mviewer.
Ici le fichier HTML qui s’affichera en dessous de la légende :
<div class="form cql-filter-list">
<label>Filtre sur 2 champs</label>
<style>
.form.cql-filter-list {
outline: 2px dashed gray;
display: inline-table;
padding-bottom: 20px;
padding-top: 4px;
outline-offset: 5px;
}
#layers-container .form.cql-filter-list .form-group label {
font-family: "roboto", Arial, Sans-serif;
font-style: italic;
padding-left: 17px;
}
.form.cql-filter-list>label {
font-family: "roboto_bold", Arial, Sans-serif;
}
</style>
</div>
Et ici le fichier javascript. Pour l’utiliser sur une de ces couches, il faudra modifier l’id de la couche (ici lycee) par l’id de votre donnée.
1//Modifier lycee par l'id de votre couche
2mviewer.customControls.lycee = (function () {
3const _idlayer = "lycee";
4const _layer = mviewer.getLayer(_idlayer);
5let noFilterLabel = "All";
6let logicalOperator = "AND";
7
8return {
9 init: function () {
10 // mandatory - code executed when panel is opened
11 const _html = [];
12 //Check for xml config ccfilters
13 let filters = [];
14 if (_layer.ccfilters && _layer.ccfilters.filter) {
15 //Convert filter to Array if is not Array (Fix one filter bug)
16 if (!Array.isArray(_layer.ccfilters.filter)) {_layer.ccfilters.filter = [_layer.ccfilters.filter]}
17 //Configuration
18 if (_layer.ccfilters.logicaloperator) { logicalOperator = _layer.ccfilters.logicaloperator; }
19 if (_layer.ccfilters.nofilterlabel) { noFilterLabel = _layer.ccfilters.nofilterlabel; }
20 filters = _layer.ccfilters.filter.map(function(f) { return {
21 'label' : f.label,
22 'field' : f.field,
23 'values' : f.values.split(","),
24 'multiple': (f.multiselection && f.multiselection == "true")
25 }
26 });
27 } else {
28 console.log(`Le customcontrol ${_idlayer} n'a pu être initialisé car la conf xml est incomplète (propriété ccfilters)`)
29 }
30 filters.forEach(function(f) {
31 const options = f.values.map(function(v) {return `<option ${f.multiple?'selected':''}>${v}</option>`});
32 if (!f.multiple) {
33 options.unshift(`<option>${noFilterLabel}</option>`);
34 }
35 const select = `<div class="form-group">
36 <label for="${_idlayer}-${f.field}">${f.label} :</label>
37 <div class="col-md-10 col-md-offset-1">
38 <select ${f.multiple?'multiple':''} placeholder="${f.label}" id="${_idlayer}-${f.field}" data-source="${f.field}" class="form-control cql-filter" onchange="mviewer.customControls.${_idlayer}.filter(this);">
39 ${options.join("")}
40 </select>
41 </div>
42 </div>`;
43 _html.push(select);
44 });
45 document.querySelector(".cql-filter-list>style").insertAdjacentHTML("afterend", _html.join("\n"));
46
47 },
48
49 filter: function(element) {
50 const _filter = [];
51 element.closest(".cql-filter-list").querySelectorAll(".cql-filter").forEach(function(q) {
52 const values = Array.from(q.selectedOptions).map(({ value }) => value);
53 if (values.length == 1) {
54 // Filtres avec choix unique
55 const value = values[0];
56 if (value != noFilterLabel) {
57 _filter.push(`${q.dataset.source} = '${value.replace("'", "''")}'`);
58 }
59 } else {
60 // Filtres avec choix multiple
61 const list = []
62 values.forEach(function(value) {
63 list.push(`'${value.replace("'", "''")}'`)
64 })
65 _filter.push(`${q.dataset.source} in (${list.join(',')})`);
66 }
67
68 });
69 console.log(_filter);
70 const layer = _layer.layer;
71 const _source = layer.getSource();
72 const params = _source.getParams();
73 params.t = new Date().getMilliseconds();
74 if (_filter.length > 0) {
75 const cql_filter = _filter.join(` ${logicalOperator} `);
76 params.CQL_FILTER = cql_filter;
77 } else {
78 params.CQL_FILTER = "1=1";
79 }
80 _source.updateParams(params);
81
82 },
83
84 destroy: function () {
85 // mandatory - code executed when panel is closed
86 },
87};
88})();
Paramétrage dans le XML
Une fois le customcontrol créé, il va falloir l’appeler dans votre application. Tout d’abord en ajoutant les options customcontrol et customcontrolpath puis les paramètres du customcontrol, ici contenus dans ccfilters.
<layer id="lycee" name="Lycées" visible="true" tiled="false"
searchable="false" queryable="true" expanded="true"
infoformat="application/vnd.ogc.gml" featurecount="20"
customcontrol="true" customcontrolpath="demo/filtres_multiples/customcontrols"
url="https://ows.region-bretagne.fr/geoserver/rb/wms"
attribution="Source: Région Bretagne"
metadata="https://kartenn.region-bretagne.fr/geonetwork/srv/fre/catalog.search#/metadata/99e78163-ce9a-4eee-9ea0-36afc2a53d25"
metadata-csw="https://kartenn.region-bretagne.fr/geonetwork/srv/eng/csw?SERVICE=CSW&VERSION=2.0.2&REQUEST=GetRecordById&elementSetName=full&ID=99e78163-ce9a-4eee-9ea0-36afc2a53d25" >
<ccfilters logicaloperator="and" nofilterlabel="Toutes">
<filter label="Réseau" field="reseau_lib" values="Agricole,Education nationale,Maritime" multiselection="true"/>
<filter label="Secteur" field="secteur_li" values="Privé sous contrat avec l'éducation nationale,Public" multiselection="true"/>
</ccfilters>
<template url="https://kartenn.region-bretagne.fr/kartoviz/apps/region/global/templates/global.lycee.mst"></template>
</layer>