Skip to content

Commit bbef2ed

Browse files
committed
Merge branch 'feature/layer-toggle' into develop
2 parents d3ace74 + 8014ff5 commit bbef2ed

15 files changed

Lines changed: 496 additions & 121 deletions

File tree

plugins/gh-datainmap/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
- Nieuwe versies van ondersteunende software bibliotheken in gebruik genomen (o.a. Redux 4.1.0).
2+
- Mogelijkheid toegevoegd om lagen in/uit te schakelen door gebruik van shortcode instellingen `enable_toggler`, `toggle_layers`, `toggle_types`, `untoggled_layers` en `untoggled_types`. Met `filter_description="Uw eigen tekst"` is het mogelijk om per kaart de begeleidende tekst te wijzigen of onderdrukken. **Let op!** Bij gebruik eigen stylesheet moet de toggler van opmaak voorzien worden. Standaard staat de toggler uit. Meer informatie is te vinden in de shortcode documentatie.
23

34
**1.9.3 (2021-05-27)**
45

plugins/gh-datainmap/SHORTCODE.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,16 @@ De functionaliteiten van de kaart kunnen ook met de shortcode in- of uitgeschake
3434

3535
`[datainmap layers=1 types=1 enable_search=0 enable_feature_dialog=0 enable_tooltip=1]`
3636

37+
De layer toggler (voor het in- en uitschakelen van kaartlagen en locatielagen) is in te schakelen met `enable_toggler`. Standaard kunnen alle kaart- en locatielagen in/uitgeschakeld worden. Met `toggle_layers` en `toggle_types` is het mogelijk om dit te beperken.
38+
39+
`[datainmap layers=1,2 types=1,2 enable_toggler=1 toggle_layers=2 toggle_types=ALL]`
40+
41+
Om schakelen tussen lagen mogelijk te maken zonder dat alle lagen standaard staan ingeschakeld kan er gebruik gemaakt worden van `untoggled_layers` en `untoggled_types`. Kaart- en locatielagen die hierin zijn opgenomen worden bij het inladen van de kaart uitgeschakeld waardoor ze niet zichtbaar zijn, totdat de gebruiker ze inschakeld.
42+
43+
`[datainmap layers=1,2 types=1,2,3,4 enable_toggler=1 toggle_layers=2 toggle_types=ALL untoggled_layers=2 untoggled_types=1,4]`
44+
45+
Met `toggler_description` is het mogelijk om de standaard tekst (DataInMap -> Instellingen) te wijzigen, of door deze leeg te maken `toggler_description=""` wordt deze niet meer getoond.
46+
47+
`[datainmap layers=1,2 types=1,2,3,4 enable_toggler=1 toggler_description="U kunt hier kaartlagen in- of uitschakelen."]`
48+
3749
Om de container waar DataInMap wordt geplaatst te voorzien van een of meerdere CSS classes kan gebruik gemaakt worden van `css_class`, bijv. `[datainmap css_class="kaart-groot"]`. Deze CSS classes dienen in de stylesheet van het gebruikte thema te staan.

plugins/gh-datainmap/includes/settings.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ function gh_dim_sanitize_settings($input) {
4343
'maxZoom',
4444
'projection',
4545
'search_coord_system',
46-
'filter_description'
46+
'filter_description',
47+
'toggler_description',
4748
];
4849
foreach($text_fields as $k) {
4950
$input[$k] = sanitize_text_field( $input[$k] );

plugins/gh-datainmap/includes/shortcode.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ function gh_dim_shortcode($atts, $content = null) {
3333
'enable_tooltip' => 0,
3434
'enable_filter' => 0,
3535
'enable_features_listbox' => 1,
36+
'enable_toggler' => 0,
37+
'toggle_layers' => null,
38+
'untoggled_layers' => null,
39+
'toggle_types' => 'ALL',
40+
'untoggled_types' => null,
41+
'toggler_description' => $settings['toggler_description'],
3642
'dynamic_loading' => 0,
3743
'css_class' => null,
3844
'filter_properties' => null,
@@ -51,8 +57,18 @@ function gh_dim_shortcode($atts, $content = null) {
5157
$settings['enable_tooltip'] = $args['enable_tooltip'] == 1 ? true : false;
5258
$settings['enable_filter'] = $args['enable_filter'] == 1 ? true : false;
5359
$settings['enable_features_listbox'] = $args['enable_features_listbox'] == 1 ? true : false;
60+
$settings['enable_toggler'] = $args['enable_toggler'] == 1 ? true : false;
61+
$settings['toggler_description'] = $args['toggler_description'];
5462
$settings['dynamic_loading'] = $args['dynamic_loading'] == 1 ? true : false;
5563
$settings['filter_description'] = $args['filter_description'];
64+
foreach(['toggle_layers', 'toggle_types', 'untoggled_layers', 'untoggled_types'] as $k) {
65+
$settings[$k] = array_filter(
66+
array_map('trim', explode(',', $args[$k])),
67+
function($a) {
68+
return strlen($a) > 0;
69+
}
70+
);
71+
}
5672

5773
// Compose map layers
5874
$layers = get_posts([
@@ -62,6 +78,7 @@ function gh_dim_shortcode($atts, $content = null) {
6278
]);
6379
$map_layers = array_map(function($post) {
6480
return [
81+
'id' => $post->ID,
6582
'title' => get_the_title( $post->ID ),
6683
'type' => get_post_meta($post->ID, '_gh_dim_layer_type', true),
6784
'url' => get_post_meta($post->ID, '_gh_dim_layer_url', true),

plugins/gh-datainmap/views/settings.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,15 @@
198198
<p class="description"><?php _e('Optinally provide a default description to be shown when a user opens the filter menu.', 'gh-datainmap'); ?></p>
199199
</td>
200200
</tr>
201+
<tr>
202+
<th scope="row" valign="top">
203+
<label for="gh-datainmap-settings[toggler_description]"><?php _e('Toggler description', 'gh-datainmap') ?></label>
204+
</th>
205+
<td>
206+
<input type="text" name="gh-datainmap-settings[toggler_description]" id="gh-datainmap-settings[toggler_description]" value="<?php echo esc_attr( $settings['toggler_description'] ) ?>" class="regular-text" />
207+
<p class="description"><?php _e('Optinally provide a default description to be shown when a user opens the toggler menu.', 'gh-datainmap'); ?></p>
208+
</td>
209+
</tr>
201210
<tr>
202211
<th scope="row" valign="top">
203212
<label for="gh-datainmap-settings[projections]"><?php _e('Additional projections (proj4)', 'gh-datainmap') ?></label>

src/actions.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,3 +260,19 @@ export const STORE_FEATURES = 'STORE_FEATURES';
260260
export function storeFeatures(features, sourceId) {
261261
return { type: STORE_FEATURES, features: features, sourceId: sourceId};
262262
}
263+
264+
export const SET_TOGGLER_DESCRIPTION = 'SET_TOGGLER_DESCRIPTION';
265+
export function setTogglerDescription(description) {
266+
return { type: SET_TOGGLER_DESCRIPTION, description: description };
267+
}
268+
269+
export const SET_TOGGLER = 'SET_TOGGLER';
270+
export function setToggler(togglers) {
271+
return { type: SET_TOGGLER, togglers };
272+
}
273+
274+
export const TOGGLE_LAYER = 'TOGGLE_LAYER';
275+
export function toggleLayer(layerType, layerId, checked) {
276+
layerId = parseInt(layerId, 10);
277+
return { type: TOGGLE_LAYER, layer: { layerType, layerId, checked } };
278+
}

src/components/map.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export class MapComponent extends Component {
134134
let features = [];
135135
this.olMap.getLayers().forEach((layer) => {
136136
const source = layer.getSource();
137-
if(source.forEachFeatureInExtent) {
137+
if(source.forEachFeatureInExtent && layer.getVisible()) {
138138
source.forEachFeatureInExtent(extent, (feature) => {
139139
features.push(feature);
140140
});
@@ -245,6 +245,21 @@ export class MapComponent extends Component {
245245
}
246246
});
247247
}
248+
249+
// Set visbility of layers based on layer toggler
250+
if(this.props.toggleLayers) {
251+
const layers = this.olMap.getLayers().getArray();
252+
this.props.toggledLayersState.forEach((toggler) => {
253+
const found = layers.find(layer => {
254+
return layer.get('dimLayerType') === toggler.layerType && layer.get('dimLayerID') === toggler.layerId;
255+
});
256+
if(found === undefined) {
257+
return;
258+
}
259+
found.setVisible( toggler.checked );
260+
});
261+
}
262+
248263
const mapElement = this.refMap.current;
249264
mapElement.getElementsByTagName('canvas').forEach((el) => {
250265
el.setAttribute('aria-label', 'Kaart');
@@ -277,8 +292,10 @@ MapComponent.defaultProps = {
277292
enableTooltip: false,
278293
enableFeaturesListbox: true,
279294
rerenderLayers: 0,
295+
toggleLayers: 0,
280296
storedFeatures: [],
281-
selectedFilters: []
297+
selectedFilters: [],
298+
layerTogglers: []
282299
};
283300

284301
export default MapComponent;

src/components/toggler.js

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Copyright 2020-2021 Gemeente Heerenveen
3+
*
4+
* Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "Licence");
5+
* You may not use this work except in compliance with the Licence.
6+
* You may obtain a copy of the Licence at:
7+
*
8+
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
9+
*
10+
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the Licence for the specific language governing permissions and limitations under the Licence.
13+
*/
14+
import React, {Component} from 'react';
15+
import _ from 'lodash';
16+
17+
// Filter view uses :focus and :focus-within CSS states, so we need to blur from
18+
// every element that could have focus
19+
function blur(e) {
20+
if(e.key == 'Escape') {
21+
e.currentTarget.blur()
22+
}
23+
};
24+
25+
class TogglerItemComponent extends Component {
26+
isChecked(layerType, layerId) {
27+
const found = this.props.toggledLayersState.find( o => {
28+
return o.layerId === layerId && o.layerType === layerType;
29+
});
30+
return found !== undefined ? found.checked : true;
31+
}
32+
33+
render() {
34+
const layerId = this.props.layer.get('dimLayerID');
35+
const layerType = this.props.layer.get('dimLayerType');
36+
const layerName = this.props.layer.get('dimLayerName');
37+
const id = _.uniqueId('gh-dim-toggler-');
38+
const checked = this.isChecked(layerType, layerId);
39+
return (
40+
<div className="gh-dim-toggler-toggle">
41+
<input id={id} type="checkbox" defaultChecked={checked} onKeyDown={blur} onClick={(e) => this.props.handleChange(layerType, layerId, e.currentTarget.checked)} /> <label htmlFor={id}>{layerName}</label>
42+
</div>
43+
);
44+
}
45+
}
46+
47+
export class TogglerComponent extends Component {
48+
constructor(props) {
49+
super(props);
50+
}
51+
52+
doToggleLayer(layerType, layerId, checked) {
53+
this.props.doToggleLayer(layerType, layerId, checked);
54+
}
55+
56+
shouldShowLayerToggler(layerType, layerId) {
57+
return this.props.togglers.some(toggle => {
58+
if(toggle.id === undefined) {
59+
return false;
60+
}
61+
return toggle.type === layerType && (
62+
toggle.id == 'all' || toggle.id == layerId
63+
);
64+
});
65+
}
66+
67+
render() {
68+
if(this.props.layers.length == 0) {
69+
return null;
70+
}
71+
const id = _.uniqueId('toggler-title-');
72+
return (
73+
<div className="gh-dim-toggler" tabIndex="0" onKeyDown={blur}>
74+
<section aria-labelledby={id}>
75+
<header>
76+
<h1 id={id}>Lagen</h1>
77+
</header>
78+
<div className="gh-dim-togglers">
79+
{this.props.description &&
80+
<p className="gh-dim-togglers-description">{this.props.description}</p>
81+
}
82+
<form>
83+
<div role="group" aria-label="Togglers">
84+
{this.props.layers.map((layer) => {
85+
const id = layer.get('dimLayerID');
86+
const type = layer.get('dimLayerType');
87+
if(!this.shouldShowLayerToggler(type, id)) {
88+
return null;
89+
}
90+
return <TogglerItemComponent key={type + '-' + id} toggledLayersState={this.props.toggledLayersState} layer={layer} handleChange={(type, id, checked) => this.doToggleLayer(type, id, checked)} />;
91+
})}
92+
</div>
93+
</form>
94+
</div>
95+
</section>
96+
</div>
97+
)
98+
}
99+
}
100+
101+
TogglerComponent.defaultProps = {
102+
doToggleLayer: _.noop,
103+
layers: [],
104+
toggledLayersState: [],
105+
togglers: []
106+
};
107+
108+
export default TogglerComponent;

src/constants.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
export const CONTENT_TYPE_POST = 0;
22
export const CONTENT_TYPE_REDIRECT = 1;
33

4-
// The different type of features the map can return after clicking
4+
// The different types of features the map can return after clicking
55
// - BuiltIn are WordPress locations or from KML
66
// - FeatureInfoUrl are from WMS
77
export const FEATURE_TYPE_BUILTIN = 'BuiltIn';
88
export const FEATURE_TYPE_FEATUREINFOURL = 'FeatureInfoUrl';
99

10-
// The different type of features. The type will decide which modal to use
10+
// The different types of features. The type will decide which modal to use
1111
export const FEATURE_TYPE_DIMFEATURE = 'DIMFeature';
1212
export const FEATURE_TYPE_KMLFEATURE = 'KMLFeature';
1313
export const FEATURE_TYPE_WMSFEATURE = 'WMSFeature';
14-
export const FEATURE_TYPE_UNKNOWN = 'UnknownFeature';
14+
export const FEATURE_TYPE_UNKNOWN = 'UnknownFeature';
15+
16+
// The different types of layers
17+
export const LAYER_TYPE_MAP = 'MapLayer';
18+
export const LAYER_TYPE_LOCATION = 'LocationLayer';

src/containers/maplink.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ const mapStateToProps = (state) => {
2525
centerLocation: state.map.centerLocation,
2626
rerenderLayers: state.map.rerenderLayers,
2727
storedFeatures: state.map.storedFeatures,
28-
selectedFilters: state.filter.selected
28+
selectedFilters: state.filter.selected,
29+
toggledLayersState: state.toggler.toggledLayersState,
30+
toggleLayers: state.map.toggleLayers,
2931
}
3032
};
3133

0 commit comments

Comments
 (0)