• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

compassinformatics / cpsi-mapview / 15022980938

14 May 2025 02:11PM UTC coverage: 26.333% (+0.04%) from 26.29%
15022980938

push

github

geographika
Move describe to test globals

492 of 2344 branches covered (20.99%)

Branch coverage included in aggregate %.

1464 of 5084 relevant lines covered (28.8%)

1.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

8.18
/app/controller/button/FeatureSelectionButtonController.js
1
/**
2
 * This class is the controller for the button 'FeatureSelectionButton'
3
 */
4
Ext.define('CpsiMapview.controller.button.FeatureSelectionButtonController', {
1✔
5
    extend: 'Ext.app.ViewController',
6

7
    alias: 'controller.cmv_feature_selection_btn',
8

9
    requires: ['Ext.window.Toast', 'BasiGX.util.Layer'],
10

11
    /**
12
     * The OpenLayers map. If not given, will be auto-detected.
13
     * @cfg
14
     */
15
    map: null,
16

17
    /**
18
     * The selector UI for the #filterMode. Created in #onBtnToggle.
19
     * @property {String}
20
     * @readonly
21
     */
22
    modeSelector: null,
23

24
    /**
25
     * The filter mode (set by the user via #modeSelector UI).
26
     * @property {String}
27
     * @readonly
28
     */
29
    filterMode: 'ADD_TO_SELECTION', // ADD_TO_SELECTION or NEW_SELECTION
30

31
    /**
32
     * The feature IDs (FIDs) used for filtering.
33
     * @property {Array}
34
     * @readonly
35
     */
36
    fidsToFilter: [],
37

38
    constructor: function () {
39
        const me = this;
5✔
40
        me.onMapClick = me.onMapClick.bind(me);
5✔
41
        me.callParent(arguments);
5✔
42
    },
43

44
    init: function () {
45
        const me = this;
5✔
46
        const ownerGrid = this.getView().up('grid');
5✔
47
        if (ownerGrid) {
5!
48
            // reset FIDs if grid clears its filters
49
            ownerGrid.on('cmv-clear-filters', function () {
5✔
50
                me.fidsToFilter = [];
×
51
            });
52
        }
53
    },
54

55
    /**
56
     * Activates this tool.
57
     * Adds a click handler to the map and tries to detect the IDs of the
58
     * clicked features. Builds a filter object for the ("where ID IN(1,2,3))
59
     * and forwards it to the grid so it gets applied to the underlying WFS.
60
     *
61
     * @param {Ext.button.Button} btn The toggled button.
62
     * @param {Boolean} pressed The toggle state.
63
     */
64
    onBtnToggle: function (btn, pressed) {
65
        const me = this;
×
66
        const view = me.getView();
×
67

68
        if (view.map && view.map instanceof ol.Map) {
×
69
            me.map = view.map;
×
70
        } else {
71
            // guess map as fallback
72
            me.map = BasiGX.util.Map.getMapComponent().map;
×
73
        }
74

75
        if (!view.queryLayer) {
×
76
            me.findWfsLayer();
×
77
        }
78

79
        if (pressed) {
×
80
            // create and show selector UI
81
            me.addModeSelectorUi();
×
82
            view.queryLayer.setVisible(true);
×
83
            me.map.on('click', me.onMapClick);
×
84
        } else {
85
            me.modeSelector.hide();
×
86
            view.queryLayer.setVisible(false);
×
87
            me.map.un('click', me.onMapClick);
×
88
        }
89
    },
90

91
    /**
92
     * Adds the mode selector UI to the toolbar (if not existing) and shows it.
93
     */
94
    addModeSelectorUi: function () {
95
        const me = this;
×
96

97
        if (!me.modeSelector) {
×
98
            me.modeSelector = Ext.create('Ext.button.Split', {
×
99
                viewModel: me.getViewModel(),
100
                bind: {
101
                    text: '{addToSelectionLabel}'
102
                },
103
                hidden: false,
104
                menu: new Ext.menu.Menu({
105
                    items: [
106
                        {
107
                            bind: {
108
                                text: '{addToSelectionLabel}'
109
                            },
110
                            handler: function (menu) {
111
                                me.filterMode = 'ADD_TO_SELECTION';
×
112
                                me.modeSelector.setText(menu.text);
×
113
                            }
114
                        },
115
                        {
116
                            bind: {
117
                                text: '{newSelectionLabel}'
118
                            },
119
                            handler: function (menu) {
120
                                me.filterMode = 'NEW_SELECTION';
×
121
                                me.modeSelector.setText(menu.text);
×
122
                            }
123
                        }
124
                    ]
125
                })
126
            });
127

128
            const tb = me.getView().up('toolbar');
×
129
            const btnGroup = me.getView().up('buttongroup');
×
130
            if (tb && btnGroup) {
×
131
                btnGroup.add(me.modeSelector);
×
132
            }
133
        }
134

135
        me.modeSelector.show();
×
136
    },
137

138
    /**
139
     * Function to determine the WFS layer to connect the click handler if not
140
     * yet defined.
141
     */
142
    findWfsLayer: function () {
143
        const me = this;
×
144
        const view = me.getView();
×
145
        if (!view.queryLayer && view.vectorLayerKey) {
×
146
            view.queryLayer = BasiGX.util.Layer.getLayerBy(
×
147
                'layerKey',
148
                view.vectorLayerKey
149
            );
150
        }
151

152
        if (!view.queryLayer) {
×
153
            Ext.Logger.warn(
×
154
                'No queryLayer found in the map for the FeaureSelectionButton with the name: ' +
155
                    view.queryLayerName
156
            );
157
        } else {
158
            // save the ID property name for future use
159
            me.idProperty = view.queryLayer.get('idProperty');
×
160
        }
161
    },
162

163
    /**
164
     * Handles map click for selection of features.
165
     *
166
     * @param {ol.MapBrowserEvent} evt The OL event
167
     */
168
    onMapClick: function (evt) {
169
        const me = this;
×
170
        const view = me.getView();
×
171

172
        // clear FIDs to filter when we have a new selection
173
        if (me.filterMode === 'NEW_SELECTION') {
×
174
            me.fidsToFilter = [];
×
175
        }
176

177
        // collect all IDs of clicked features
178
        const clickedFeatureIds = [];
×
179
        me.map.forEachFeatureAtPixel(evt.pixel, function (feature, layer) {
×
180
            // add check for correct layer
181
            if (layer && view.queryLayer && layer.id === view.queryLayer.id) {
×
182
                const source = view.queryLayer.getSource();
×
183
                if (source instanceof ol.source.Cluster) {
×
184
                    const origFeats = feature.get('features');
×
185
                    if (Ext.isArray(origFeats)) {
×
186
                        // add all sub-feature due to clustering
187
                        Ext.each(origFeats, function (origFeat) {
×
188
                            me.fidsToFilter.push(origFeat.get(me.idProperty));
×
189
                            clickedFeatureIds.push(origFeat.get(me.idProperty));
×
190
                        });
191
                    }
192
                } else {
193
                    // "normal" layers without clustering
194
                    me.fidsToFilter.push(feature.get(me.idProperty));
×
195
                    clickedFeatureIds.push(feature.get(me.idProperty));
×
196
                }
197
            }
198
        });
199

200
        // inform that no feature was hit on the map
201
        if (clickedFeatureIds.length === 0) {
×
202
            if (view.showNoSelectionMessage) {
×
203
                Ext.toast('No feature(s) at clicked position.', null, 'br');
×
204
            }
205

206
            view.fireEvent('cmv-no-feature-selected', view);
×
207
            return;
×
208
        }
209

210
        // create ExtJS "IN" filter with unique values
211
        const uniqueFids = Ext.Array.unique(me.fidsToFilter);
×
212
        const extInFilter = new Ext.util.Filter({
×
213
            type: 'fid',
214
            property: me.idProperty,
215
            value: uniqueFids,
216
            operator: 'in'
217
        });
218

219
        if (me.filterMode === 'NEW_SELECTION') {
×
220
            // removes all filters from grid without reloading WFS store
221
            view.fireEvent('cmv-reset-grid-filters');
×
222
        }
223
        // sets the ID filter in the grid
224
        view.fireEvent('cmv-id-filter-set', extInFilter);
×
225
    },
226

227
    onBeforeDestroy: function () {
228
        const me = this;
×
229
        const btn = me.getView();
×
230

231
        // detoggle button
232
        me.onBtnToggle(btn, false);
×
233
    }
234
});
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc