input').val('');
- }
- }
- }
- }
- $(this).blur();
- return;
- });
- $('#locate-layer-'+layerName).combobox({
- "minLength": ('minLength' in locate) ? locate.minLength : 0,
- "position": { my : "right top", at: "right bottom" },
- "selected": function(evt, ui){
- if ( ui.item ) {
- var self = $(this);
- var uiItem = $(ui.item);
- window.setTimeout(function(){
- self.val(uiItem.val()).change();
- }, 1);
- }
- }
- });
- $('#locate-layer-'+layerName+' ~ span > input').attr('placeholder', placeHolder).val('');
- $('#locate-layer-'+layerName+' option[value=-1]').attr('label', placeHolder);
- $('#locate-layer-'+layerName+' ~ span > input').autocomplete('close');
- if ( ('minLength' in locate) && locate.minLength > 0 )
- $('#locate-layer-'+layerName).parent().addClass('no-toggle');
- if(mCheckMobile()){
- // autocompletion items for locatebylayer feature
- $('div.locate-layer select').show();
- $('span.custom-combobox').hide();
- }
- },'json');
- }
-
- function addLocateByLayer(){
- var locateByLayerList = [];
- for (var lname in config.locateByLayer) {
- if ('order' in config.locateByLayer[lname])
- locateByLayerList[config.locateByLayer[lname].order] = lname;
- else
- locateByLayerList.push(lname);
- }
- var locateContent = [];
- for (var l in locateByLayerList) {
- var lname = locateByLayerList[l];
- var lConfig = config.layers[lname];
- var html = '';
- html += '';
- html += '
';
- //constructing the select
- locateContent.push(html);
- }
- $('#locate .menu-content').html(locateContent.join('
'));
-
- var featureTypes = lizMap.mainLizmap.initialConfig.vectorLayerFeatureTypeList;
- if (featureTypes.length == 0) {
- config.locateByLayer = {};
- $('#button-locate').parent().remove();
- $('#locate-menu').remove();
- } else {
- for (const featureType of featureTypes) {
- var typeName = featureType.Name;
- var lname = lizMap.getNameByTypeName(typeName);
- if (!lname) {
- if (typeName in config.locateByLayer)
- lname = typeName
- else if ((typeName in shortNameMap) && (shortNameMap[typeName] in config.locateByLayer))
- lname = shortNameMap[typeName];
- else {
- for (var lbl in config.locateByLayer) {
- if (lbl.split(' ').join('_') == typeName) {
- lname = lbl;
- break;
- }
- }
- }
- }
-
- if (!(lname in config.locateByLayer))
- continue;
-
- var locate = config.locateByLayer[lname];
- locate['crs'] = featureType.SRS;
- loadProjDefinition(locate.crs, function () {
- new OpenLayers.Projection(locate.crs);
- });
- locate['bbox'] = featureType.LatLongBoundingBox;
- }
-
- // get joins
- for (var lName in config.locateByLayer) {
- var locate = config.locateByLayer[lName];
- if ('vectorjoins' in locate && locate['vectorjoins'].length != 0) {
- var vectorjoin = locate['vectorjoins'][0];
- locate['joinFieldName'] = vectorjoin['targetFieldName'];
- for (var jName in config.locateByLayer) {
- var jLocate = config.locateByLayer[jName];
- if (jLocate.layerId == vectorjoin.joinLayerId) {
- vectorjoin['joinLayer'] = jName;
- locate['joinLayer'] = jName;
- jLocate['joinFieldName'] = vectorjoin['joinFieldName'];
- jLocate['joinLayer'] = lName;
- jLocate['filterjoins'] = [{
- 'targetFieldName': vectorjoin['joinFieldName'],
- 'joinFieldName': vectorjoin['targetFieldName'],
- 'joinLayerId': locate.layerId,
- 'joinLayer': lName
- }];
- }
- }
- }
- }
-
- // get locate by layers features
- for (var lname in config.locateByLayer) {
- getLocateFeature(lname);
- }
- $('.btn-locate-clear').click(function () {
- lizMap.mainLizmap.map.clearHighlightFeatures();
- $('#locate select').val('-1');
- $('div.locate-layer span > input').val('');
-
- if (lizMap.lizmapLayerFilterActive) {
- lizMap.events.triggerEvent('lizmaplocatefeaturecanceled',
- { 'featureType': lizMap.lizmapLayerFilterActive }
- );
- }
- return false;
-
- });
- $('#locate-close').click(function () {
- $('.btn-locate-clear').click(); // deactivate locate and filter
- $('#button-locate').click();
- return false;
- });
- }
- }
-
/**
* PRIVATE function: createToolbar
* create the tool bar (collapse switcher, etc)
@@ -2708,37 +2259,6 @@ window.lizMap = function() {
},'json');
}
});
-
- // $.post( getFeatureUrlData['url'], getFeatureUrlData['options'], function(incomingData) {
- // const data = DOMPurify.sanitize(incomingData);
-
- // aConfig['featureCrs'] = 'EPSG:4326';
-
- // if (aConfig?.['alias'] && aConfig?.['types']) {
- // callFeatureDataCallBacks(poolId, data.features);
- // $('body').css('cursor', 'auto');
- // } else {
- // $.post(globalThis['lizUrls'].service, {
- // 'SERVICE':'WFS'
- // ,'VERSION':'1.0.0'
- // ,'REQUEST':'DescribeFeatureType'
- // ,'TYPENAME': ('typename' in aConfig) ? aConfig.typename : aName
- // ,'OUTPUTFORMAT':'JSON'
- // }, function(describe) {
-
- // aConfig['alias'] = describe.aliases;
- // aConfig['types'] = describe.types;
- // aConfig['columns'] = describe.columns;
-
- // callFeatureDataCallBacks(poolId, data.features);
-
- // $('body').css('cursor', 'auto');
-
- // },'json');
- // }
-
- // },'json');
-
return true;
}
@@ -2748,8 +2268,7 @@ window.lizMap = function() {
* @param proj
* @param zoomAction
*/
- function zoomToOlFeature( feature, proj, zoomAction ){
- zoomAction = typeof zoomAction !== 'undefined' ? zoomAction : 'zoom';
+ function zoomToOlFeature( feature, proj, zoomAction = 'action' ){
var format = new OpenLayers.Format.GeoJSON({
ignoreExtraDims: true
});
@@ -2758,11 +2277,11 @@ window.lizMap = function() {
feat.geometry.transform( proj, lizMap.map.getProjection() );
// Zoom or center to selected feature
- if( zoomAction == 'zoom' )
- map.zoomToExtent(feat.geometry.getBounds());
- if( zoomAction == 'center' ){
- var lonlat = feat.geometry.getBounds().getCenterLonLat()
- map.setCenter(lonlat);
+ if( zoomAction == 'zoom' ){
+ lizMap.mainLizmap.map.zoomToGeometryOrExtent(feat.geometry.getBounds().toArray());
+ } else if( zoomAction == 'center' ){
+ const lonlat = feat.geometry.getBounds().getCenterLonLat();
+ lizMap.mainLizmap.map.getView().setCenter([lonlat.lon, lonlat.lat]);
}
}
}
@@ -2773,9 +2292,7 @@ window.lizMap = function() {
* @param fid
* @param zoomAction
*/
- function zoomToFeature( featureType, fid, zoomAction ){
- zoomAction = typeof zoomAction !== 'undefined' ? zoomAction : 'zoom';
-
+ function zoomToFeature( featureType, fid, zoomAction = 'zoom' ){
getLayerFeature(featureType, fid, function(feat) {
var proj = new OpenLayers.Projection(config.layers[featureType].crs);
if( config.layers[featureType].featureCrs )
@@ -2866,10 +2383,6 @@ window.lizMap = function() {
if( !feat )
return false;
- // Remove map popup to avoid confusion
- if (lizMap.map.popups.length != 0)
- lizMap.map.removePopup( lizMap.map.popups[0] );
-
// Get popup content by FILTER and not with virtual click on map
var filter = '';
var qgisName = aName;
@@ -3828,10 +3341,6 @@ window.lizMap = function() {
}));
}
- if ('locateByLayer' in config) {
- addLocateByLayer();
- }
-
/**
* Event when layers have been added
* @event layersadded
@@ -3887,12 +3396,6 @@ window.lizMap = function() {
return false;
});
- // Show locate by layer
- if (!('locateByLayer' in config))
- $('#button-locate').parent().hide();
- else
- $('#button-locate').click();
-
// hide mini-dock if no tool is active
if ($('#mapmenu ul li.nav-minidock.active').length == 0) {
$('#mini-dock-content > .tab-pane.active').removeClass('active');
diff --git a/assets/src/legacy/switcher-layers-actions.js b/assets/src/legacy/switcher-layers-actions.js
index f4dff57c10..06b96aad11 100644
--- a/assets/src/legacy/switcher-layers-actions.js
+++ b/assets/src/legacy/switcher-layers-actions.js
@@ -413,20 +413,6 @@ var lizLayerActionButtons = function() {
if(mapProjection == 'EPSG:900913')
mapProjection = 'EPSG:3857';
- /*if( !( 'bbox' in itemConfig ) || !( mapProjection in itemConfig['bbox'] ) ){
- console.log('The layer bbox information has not been found in config');
- console.log(itemConfig);
- return false;
- }*/
-
- /*var lex = itemConfig['bbox'][mapProjection]['bbox'];
- var lBounds = new OpenLayers.Bounds(
- lex[0],
- lex[1],
- lex[2],
- lex[3]
- );*/
-
if ( !('extent' in itemConfig) ) {
console.log('The layer extent information has not been found in config');
console.log(itemConfig);
@@ -440,16 +426,6 @@ var lizLayerActionButtons = function() {
var lBounds = OpenLayers.Bounds.fromArray(itemConfig['extent']);
lBounds = lBounds.transform(itemConfig['crs'],mapProjection);
- // Reverse axis
- /*if (OpenLayers.Projection.defaults[mapProjection] &&
- OpenLayers.Projection.defaults[mapProjection].yx) {
- lBounds = new OpenLayers.Bounds(
- lex[1],
- lex[0],
- lex[3],
- lex[2]
- );
- }*/
lizMap.map.zoomToExtent( lBounds );
return false;
diff --git a/assets/src/modules/Lizmap.js b/assets/src/modules/Lizmap.js
index 456b332ffb..6152432872 100644
--- a/assets/src/modules/Lizmap.js
+++ b/assets/src/modules/Lizmap.js
@@ -25,6 +25,7 @@ import Legend from './Legend.js';
import Permalink from './Permalink.js';
import Search from './Search.js';
import Tooltip from './Tooltip.js';
+import LocateByLayer from './LocateByLayer.js';
import WMSCapabilities from 'ol/format/WMSCapabilities.js';
import WFSCapabilities from 'ol-wfs-capabilities';
@@ -167,6 +168,7 @@ export default class Lizmap {
this.legend = new Legend(this.state.layerTree);
this.search = new Search(this.map, this.lizmap3);
this.tooltip = new Tooltip();
+ this.locateByLayer = new LocateByLayer();
// Removed unusable button
if (!this.config['printTemplates'] || this.config.printTemplates.length == 0 ) {
diff --git a/assets/src/modules/LocateByLayer.js b/assets/src/modules/LocateByLayer.js
new file mode 100644
index 0000000000..45337eaee9
--- /dev/null
+++ b/assets/src/modules/LocateByLayer.js
@@ -0,0 +1,473 @@
+/**
+ * @module modules/LocateByLayer.js
+ * @name LocateByLayer
+ * @copyright 2024 3Liz
+ * @author BOISTEAULT Nicolas
+ * @license MPL-2.0
+ */
+
+import { mainLizmap } from '../modules/Globals.js';
+import DOMPurify from 'dompurify';
+
+import GeoJSON from 'ol/format/GeoJSON.js';
+
+/**
+ * @class
+ * @name LocateByLayer
+ */
+export default class LocateByLayer {
+ constructor() {
+ this._locateByLayerConfig = lizMap.config.locateByLayer;
+ const locateBtn = document.getElementById('button-locate');
+ if (mainLizmap.initialConfig.locateByLayer) {
+ this.addLocateByLayer();
+ document.querySelector('#mini-dock-content .active').classList.remove('active');
+ document.querySelector('#mapmenu .locate').classList.add('active');
+ document.getElementById('locate').classList.add('active');
+ } else {
+ locateBtn?.parentNode.classList.add('hide');
+ }
+ }
+
+ addLocateByLayer() {
+ var locateByLayerList = [];
+ for (var lname in this._locateByLayerConfig) {
+ if ('order' in this._locateByLayerConfig[lname])
+ locateByLayerList[this._locateByLayerConfig[lname].order] = lname;
+ else
+ locateByLayerList.push(lname);
+ }
+ var locateContent = [];
+ for (var l in locateByLayerList) {
+ var lname = locateByLayerList[l];
+ var lConfig = lizMap.config.layers[lname];
+ var html = '';
+ html += '';
+ html += '
';
+ //constructing the select
+ locateContent.push(html);
+ }
+ $('#locate .menu-content').html(locateContent.join('
'));
+
+ var featureTypes = lizMap.mainLizmap.initialConfig.vectorLayerFeatureTypeList;
+ if (featureTypes.length == 0) {
+ this._locateByLayerConfig = {};
+ $('#button-locate').parent().remove();
+ $('#locate-menu').remove();
+ } else {
+ for (const featureType of featureTypes) {
+ var typeName = featureType.Name;
+ var lname = lizMap.getNameByTypeName(typeName);
+ if (!lname) {
+ if (typeName in this._locateByLayerConfig)
+ lname = typeName
+ else if ((typeName in shortNameMap) && (shortNameMap[typeName] in this._locateByLayerConfig))
+ lname = shortNameMap[typeName];
+ else {
+ for (var lbl in this._locateByLayerConfig) {
+ if (lbl.split(' ').join('_') == typeName) {
+ lname = lbl;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!(lname in this._locateByLayerConfig))
+ continue;
+
+ var locate = this._locateByLayerConfig[lname];
+ locate['crs'] = featureType.SRS;
+ // loadProjDefinition(locate.crs, function () {
+ // new OpenLayers.Projection(locate.crs);
+ // });
+ locate['bbox'] = featureType.LatLongBoundingBox;
+ }
+
+ // get joins
+ for (var lName in this._locateByLayerConfig) {
+ var locate = this._locateByLayerConfig[lName];
+ if ('vectorjoins' in locate && locate['vectorjoins'].length != 0) {
+ var vectorjoin = locate['vectorjoins'][0];
+ locate['joinFieldName'] = vectorjoin['targetFieldName'];
+ for (var jName in this._locateByLayerConfig) {
+ var jLocate = this._locateByLayerConfig[jName];
+ if (jLocate.layerId == vectorjoin.joinLayerId) {
+ vectorjoin['joinLayer'] = jName;
+ locate['joinLayer'] = jName;
+ jLocate['joinFieldName'] = vectorjoin['joinFieldName'];
+ jLocate['joinLayer'] = lName;
+ jLocate['filterjoins'] = [{
+ 'targetFieldName': vectorjoin['joinFieldName'],
+ 'joinFieldName': vectorjoin['targetFieldName'],
+ 'joinLayerId': locate.layerId,
+ 'joinLayer': lName
+ }];
+ }
+ }
+ }
+ }
+
+ // get locate by layers features
+ for (var lname in this._locateByLayerConfig) {
+ this.getLocateFeature(lname);
+ }
+ $('.btn-locate-clear').click(function () {
+ lizMap.mainLizmap.map.clearHighlightFeatures();
+ $('#locate select').val('-1');
+ $('div.locate-layer span > input').val('');
+
+ if (lizMap.lizmapLayerFilterActive) {
+ lizMap.events.triggerEvent('lizmaplocatefeaturecanceled',
+ { 'featureType': lizMap.lizmapLayerFilterActive }
+ );
+ }
+ return false;
+
+ });
+ $('#locate-close').click(function () {
+ $('.btn-locate-clear').click(); // deactivate locate and filter
+ document.getElementById('button-locate')?.click();
+ return false;
+ });
+ }
+ }
+
+ /**
+ * Get features for locate by layer tool
+ * @param aName
+ */
+ getLocateFeature(aName) {
+ var locate = this._locateByLayerConfig[aName];
+
+ // get fields to retrieve
+ var fields = ['geometry',locate.fieldName];
+ // if a filter field is defined
+ if ('filterFieldName' in locate)
+ fields.push( locate.filterFieldName );
+ // check for join fields
+ if ( 'filterjoins' in locate ) {
+ var filterjoins = locate.filterjoins;
+ for ( var i=0, len=filterjoins.length; i {
+ var lConfig = lizMap.config.layers[aName];
+ locate['features'] = {};
+ if ( !data.features )
+ data = JSON.parse(data);
+ var features = data.features;
+ // if( locate.crs != 'EPSG:4326' && features.length != 0) {
+ // // load projection to be sure to have the definition
+ // loadProjDefinition( locate.crs, function() {
+ // locate.crs = 'EPSG:4326';
+ // });
+ // }
+
+ if ('filterFieldName' in locate) {
+ // create filter combobox for the layer
+ features.sort(function(a, b) {
+ var aProperty = a.properties[locate.filterFieldName];
+ var bProperty = b.properties[locate.filterFieldName];
+ if (isNaN(aProperty)) {
+ if (isNaN(bProperty)) { // a and b are strings
+ return aProperty.localeCompare(bProperty);
+ } else { // a string and b number
+ return 1; // a > b
+ }
+ } else {
+ if (isNaN(bProperty)) { // a number and b string
+ return -1; // a < b
+ } else { // a and b are numbers
+ return parseFloat(aProperty) - parseFloat(bProperty);
+ }
+ }
+ });
+ var filterPlaceHolder = '';
+ if ( 'filterFieldAlias' in locate && locate.filterFieldAlias!='')
+ filterPlaceHolder += locate.filterFieldAlias+' ';
+ else
+ filterPlaceHolder += locate.filterFieldName;
+ filterPlaceHolder +=' ('+ lConfig.title + ')';
+ var fOptions = '';
+ var fValue = '-1';
+ for (var i=0, len=features.length; i'+fValue+'';
+ }
+ }
+
+ // add filter values list
+ $('#locate-layer-'+layerName).parent().before('
');
+ // listen to filter select changes
+ document.getElementById('locate-layer-'+layerName+'-'+locate.filterFieldName).addEventListener("change", () => {
+ var filterValue = $(this).children(':selected').val();
+ this.updateLocateFeatureList( aName );
+ if (filterValue == '-1')
+ $('#locate-layer-'+layerName+'-'+locate.filterFieldName+' ~ span > input').val('');
+ $('#locate-layer-'+layerName+' ~ span > input').val('');
+ $('#locate-layer-'+layerName).val('-1');
+ this.zoomToLocateFeature(aName);
+ });
+ // add combobox to the filter select
+ $('#locate-layer-'+layerName+'-'+locate.filterFieldName).combobox({
+ position: { my : "right top", at: "right bottom" },
+ "selected": function(evt, ui){
+ if ( ui.item ) {
+ const self = this;
+ var uiItem = $(ui.item);
+ window.setTimeout(function(){
+ self.value = uiItem.val();
+ self.dispatchEvent(new Event('change'));
+ }, 1);
+ }
+ }
+ });
+
+ // add place holder to the filter combobox input
+ $('#locate-layer-'+layerName+'-'+locate.filterFieldName+' ~ span > input').attr('placeholder', filterPlaceHolder).val('');
+ $('#locate-layer-'+layerName+'-'+locate.filterFieldName+' ~ span > input').autocomplete('close');
+ }
+
+ // create combobox for the layer
+ features.sort(function(a, b) {
+ var aProperty = a.properties[locate.fieldName];
+ var bProperty = b.properties[locate.fieldName];
+ if (isNaN(aProperty)) {
+ if (isNaN(bProperty)) { // a and b are strings
+ return aProperty.localeCompare(bProperty);
+ } else { // a string and b number
+ return 1; // a > b
+ }
+ } else {
+ if (isNaN(bProperty)) { // a number and b string
+ return -1; // a < b
+ } else { // a and b are numbers
+ return parseFloat(aProperty) - parseFloat(bProperty);
+ }
+ }
+ });
+ var placeHolder = '';
+ if ('filterFieldName' in locate) {
+ if ( 'fieldAlias' in locate && locate.fieldAlias!='' )
+ placeHolder += locate.fieldAlias+' ';
+ else
+ placeHolder += locate.fieldName+' ';
+ placeHolder += '('+lConfig.title+')';
+ } else {
+ placeHolder = lConfig.title;
+ }
+ var options = '';
+ for (var i=0, len=features.length; i' + DOMPurify.sanitize(feat.properties[locate.fieldName]) + '';
+ }
+ document.getElementById('locate-layer-'+layerName).innerHTML = options;
+ // listen to select changes
+ document.getElementById('locate-layer-'+layerName).addEventListener("change", (event) => {
+ var val = event.target.value;
+ if (val == '-1') {
+ $('#locate-layer-'+layerName+' ~ span > input').val('');
+ // update to join layer
+ if ( 'filterjoins' in locate && locate.filterjoins.length != 0 ) {
+ var filterjoins = locate.filterjoins;
+ for (var i=0, len=filterjoins.length; i input').val('');
+ }
+ }
+ }
+ }
+ $(this).blur();
+ return;
+ });
+ $('#locate-layer-'+layerName).combobox({
+ "minLength": ('minLength' in locate) ? locate.minLength : 0,
+ "position": { my : "right top", at: "right bottom" },
+ "selected": function(evt, ui){
+ if ( ui.item ) {
+ const self = this;
+ var uiItem = $(ui.item);
+ window.setTimeout(function(){
+ self.value = uiItem.val();
+ self.dispatchEvent(new Event('change'));
+ }, 1);
+ }
+ }
+ });
+ $('#locate-layer-'+layerName+' ~ span > input').attr('placeholder', placeHolder).val('');
+ $('#locate-layer-'+layerName+' option[value=-1]').attr('label', placeHolder);
+ $('#locate-layer-'+layerName+' ~ span > input').autocomplete('close');
+ if ( ('minLength' in locate) && locate.minLength > 0 )
+ $('#locate-layer-'+layerName).parent().addClass('no-toggle');
+ if(lizMap.checkMobile()){
+ // autocompletion items for locatebylayer feature
+ $('div.locate-layer select').show();
+ $('span.custom-combobox').hide();
+ }
+ },'json');
+ }
+
+ /**
+ * Zoom to locate feature
+ * @param aName
+ */
+ zoomToLocateFeature(aName) {
+ // clear highlight layer
+ lizMap.mainLizmap.map.clearHighlightFeatures();
+
+ // get locate by layer val
+ var locate = this._locateByLayerConfig[aName];
+ var layerName = lizMap.cleanName(aName);
+ var val = $('#locate-layer-'+layerName).val();
+ if (val == '-1') {
+ // Trigger event
+ lizMap.events.triggerEvent('lizmaplocatefeaturecanceled', {'featureType': aName });
+ } else {
+ // zoom to val
+ const featGeoJSON = locate.features[val];
+ if( featGeoJSON.geometry){
+ const geom = (new GeoJSON()).readGeometry(featGeoJSON.geometry, {
+ dataProjection: 'EPSG:4326',
+ featureProjection: lizMap.mainLizmap.projection
+ });
+ // Show geometry if asked
+ if (locate.displayGeom == 'True') {
+ var getFeatureUrlData = lizMap.getVectorLayerWfsUrl( aName, null, null, null );
+ getFeatureUrlData['options']['PROPERTYNAME'] = ['geometry',locate.fieldName].join(',');
+ getFeatureUrlData['options']['FEATUREID'] = val;
+ // Get data
+ $.post( getFeatureUrlData['url'], getFeatureUrlData['options'], function(data) {
+ if ( !data.features ){
+ data = JSON.parse(data);
+ }
+ lizMap.mainLizmap.map.setHighlightFeatures(data.features[0], "geojson");
+ }).fail(function(){
+ lizMap.mainLizmap.map.setHighlightFeatures(feat, "geojson");
+ });
+ }
+ // zoom to extent
+ lizMap.mainLizmap.map.zoomToGeometryOrExtent(geom);
+ }
+
+ var fid = val.split('.')[1];
+
+ // Trigger event
+ lizMap.events.triggerEvent('lizmaplocatefeaturechanged',
+ {
+ 'featureType': aName,
+ 'featureId': fid
+ }
+ );
+ }
+ }
+
+ /**
+ * Get features for locate by layer tool
+ * @param aName
+ */
+ updateLocateFeatureList(aName) {
+ var locate = this._locateByLayerConfig[aName];
+ // clone features reference
+ var features = {};
+ for ( var fid in locate.features ) {
+ features[fid] = locate.features[fid];
+ }
+ // filter by filter field name
+ if ('filterFieldName' in locate) {
+ var filterValue = $('#locate-layer-' + lizMap.cleanName(aName) + '-'+locate.filterFieldName).val();
+ if ( filterValue != '-1' ) {
+ for (var fid in features) {
+ var feat = features[fid];
+ if (feat.properties[locate.filterFieldName] != filterValue)
+ delete features[fid];
+ }
+ } else
+ features = {}
+ }
+ // filter by vector joins
+ if ( 'vectorjoins' in locate && locate.vectorjoins.length != 0 ) {
+ var vectorjoins = locate.vectorjoins;
+ for ( var i=0, len =vectorjoins.length; i< len; i++) {
+ var vectorjoin = vectorjoins[i];
+ var jName = vectorjoin.joinLayer;
+ if ( jName in this._locateByLayerConfig ) {
+ var jLocate = this._locateByLayerConfig[jName];
+ var jVal = $('#locate-layer-' + lizMap.cleanName(jName)).val();
+ if ( jVal == '-1' ) continue;
+ var jFeat = jLocate.features[jVal];
+ for (var fid in features) {
+ var feat = features[fid];
+ if ( feat.properties[vectorjoin.targetFieldName] != jFeat.properties[vectorjoin.joinFieldName] )
+ delete features[fid];
+ }
+ }
+ }
+ }
+ // create the option list
+ const placeHolder = lizMap.config.layers[aName].title;
+ var options = '';
+ for (var fid in features) {
+ var feat = features[fid];
+ options += '';
+ }
+ // add option list
+ $('#locate-layer-'+ lizMap.cleanName(aName)).html(options);
+ }
+};
diff --git a/assets/src/modules/config/Options.js b/assets/src/modules/config/Options.js
index cde838a777..0710016077 100644
--- a/assets/src/modules/config/Options.js
+++ b/assets/src/modules/config/Options.js
@@ -29,6 +29,8 @@ const optionalProperties = {
'wmsMaxHeight': {type: 'number', default: 3000},
'wmsMaxWidth': {type: 'number', default: 3000},
'fixed_scale_overview_map': {type: 'boolean', default: true},
+ 'max_scale_points': {type: 'number', default: 5000},
+ 'max_scale_lines_polygons': {type: 'number', default: 5000},
'use_native_zoom_levels': {type: 'boolean', nullable: true, default: null},
'hide_numeric_scale_value': {type: 'boolean', default: false},
'hideGroupCheckbox': { type: 'boolean', default: false },
@@ -62,6 +64,8 @@ export class OptionsConfig extends BaseObjectConfig {
* @param {number} [cfg.wmsMaxHeight] - the image max height for WMS GetMap request
* @param {number} [cfg.wmsMaxWidth] - the image max width for WMS GetMap request
* @param {boolean} [cfg.fixed_scale_overview_map] - does the Overview map have fixed scale ?
+ * @param {number} [cfg.max_scale_points] - maximum scale when zooming on points
+ * @param {boolean} [cfg.max_scale_lines_polygons] - maximum scale when zooming on lines or polygons
* @param {boolean} [cfg.use_native_zoom_levels] - does the map use native zoom levels ?
* @param {boolean} [cfg.hide_numeric_scale_value] - does the scale line hide numeric scale value ?
* @param {boolean} [cfg.hideGroupCheckbox] - are groups checkbox hidden ?
@@ -207,6 +211,22 @@ export class OptionsConfig extends BaseObjectConfig {
return this._fixed_scale_overview_map;
}
+ /**
+ * Maximum scale when zooming on points
+ * @type {boolean}
+ */
+ get max_scale_points() {
+ return this._max_scale_points;
+ }
+
+ /**
+ * Maximum scale when zooming on lines or polygons
+ * @type {boolean}
+ */
+ get max_scale_lines_polygons() {
+ return this._max_scale_lines_polygons;
+ }
+
/**
* The map uses native zoom levels
* @type {boolean}
diff --git a/assets/src/modules/map.js b/assets/src/modules/map.js
index 707290d84d..307b24d3a7 100644
--- a/assets/src/modules/map.js
+++ b/assets/src/modules/map.js
@@ -1074,4 +1074,53 @@ export default class map extends olMap {
removeToolLayer(layer) {
this._toolsGroup.getLayers().remove(layer);
}
+
+ /**
+ * Zoom to given geometry or extent
+ * @param {geometry|extent} geometryOrExtent The geometry or extent to zoom to. CRS is 4326 by default.
+ * @param {object} [options] Options.
+ */
+ zoomToGeometryOrExtent(geometryOrExtent, options) {
+ const geometryType = geometryOrExtent.getType?.();
+ if (geometryType && (mainLizmap.initialConfig.options.max_scale_lines_polygons || mainLizmap.initialConfig.options.max_scale_lines_polygons)) {
+ let maxScale;
+ if (['Polygon', 'Linestring', 'MultiPolygon', 'MultiLinestring'].includes(geometryType)){
+ maxScale = mainLizmap.initialConfig.options.max_scale_lines_polygons;
+ } else if (geometryType === 'Point'){
+ maxScale = mainLizmap.initialConfig.options.max_scale_points;
+ }
+ const resolution = mainLizmap.utils.getResolutionFromScale(
+ maxScale,
+ mainLizmap.map.getView().getProjection().getMetersPerUnit()
+ );
+ if (!options?.minResolution) {
+ if (!options) {
+ options = { minResolution: resolution };
+ } else {
+ options.minResolution = resolution;
+ }
+ }
+ }
+ this.getView().fit(geometryOrExtent, options);
+ }
+
+ /**
+ * Zoom to given feature id
+ * @param {string} featureTypeDotId The string as `featureType.fid` to zoom to.
+ * @param {object} [options] Options.
+ */
+ zoomToFid(featureTypeDotId, options) {
+ const [featureType, fid] = featureTypeDotId.split('.');
+ if (!featureType || !fid) {
+ console.log('Wrong string for featureType.fid');
+ return;
+ }
+ lizMap.getLayerFeature(featureType, fid, feat => {
+ const olFeature = (new GeoJSON()).readFeature(feat, {
+ dataProjection: 'EPSG:4326',
+ featureProjection: mainLizmap.projection
+ });
+ this.zoomToGeometryOrExtent(olFeature.getGeometry(), options);
+ });
+ }
}