Skip to content

Commit d3a609c

Browse files
committed
Enhancements to Attribute Tables widget to accommodate new functionality
in Search widget 1. Add search results to previous results 2. Added ability to select multiple features on map with ctrl or shift-click. Previously selected features can be unselected in the same manner. 3. Use geometry engine in the ESRI API instead of a server-based Geoprocessing Task to buffer when the map's spatial reference wkid is 4326 or 102100 (web mercator) 4. Moved logic to work with cmv panes from Table widget to main Attributes Table container widget 5. Add `openPane` topic to open the containing pane 6. Add `'closePane` topic to close the containing pane 7. Added `selectTab` topic to select a specific tab 8. Added `tableUpdated` topic to publish when a table has changed in some way (i.e. when a feature is selected or the features are removed from the map). Fix: 1. Remove graphic layers from map when table widget is removed (tab closed)
1 parent 40d2ee9 commit d3a609c

8 files changed

+197
-73
lines changed

widgets/AttributesTable.js

+62-9
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ define([
3737
return declare([_WidgetBase, _Container], {
3838
baseClass: 'cmvAttributesContainerWidget',
3939
topicID: 'attributesContainer',
40+
sidebarID: null,
41+
sidebarPane: null,
4042

4143
// i18n
4244
i18n: i18n,
@@ -61,6 +63,7 @@ define([
6163
if (newVal && newVal.selectTab) {
6264
newVal.selectTab(name);
6365
}
66+
topic.publish(this.topicID + '/tableUpdated', newVal);
6467
});
6568

6669
this.tabContainer.on('click', lang.hitch(this.tabContainer, function () {
@@ -69,6 +72,7 @@ define([
6972
if (tab && tab.selectTab) {
7073
tab.selectTab();
7174
}
75+
topic.publish(this.topicID + '/tableUpdated', tab);
7276
}
7377
}));
7478

@@ -100,6 +104,15 @@ define([
100104

101105
// remove a tab from the tab strip
102106
this.own(topic.subscribe(this.topicID + '/removeTab', lang.hitch(this, 'removeTab')));
107+
108+
// select a tab in the tab strip
109+
this.own(topic.subscribe(this.topicID + '/selectTab', lang.hitch(this, 'selectTab')));
110+
111+
// open the sidebar pane
112+
this.own(topic.subscribe(this.topicID + '/openPane', lang.hitch(this, 'openPane')));
113+
114+
// close the sidebar pane
115+
this.own(topic.subscribe(this.topicID + '/closePane', lang.hitch(this, 'closePane')));
103116
},
104117

105118
// add multiple tables
@@ -141,6 +154,7 @@ define([
141154
}
142155
options.map = this.map;
143156
options.sidebarID = this.sidebarID;
157+
options.attributesContainerID = this.topicID;
144158

145159
if (this.useTabs) {
146160
if (!tabs) {
@@ -156,12 +170,13 @@ define([
156170
tab = new Table(options);
157171
tab.startup();
158172
tabs.addChild(tab);
173+
var self = this;
159174
tab.onClose = lang.hitch(tab, function () {
160175
var close = this.confirmClose ? confirm('Do you really want to close this tab?') : true;
161-
if (close && this.clearAll) {
162-
this.clearAll();
176+
if (close) {
177+
self.removeTab(tab.id);
163178
}
164-
return close;
179+
return false;
165180
});
166181
}
167182
if (tab && select !== false) {
@@ -175,6 +190,7 @@ define([
175190
this.addChild(tab);
176191
}
177192
}
193+
topic.publish(this.topicID + '/tableUpdated', tab);
178194
return tab;
179195
},
180196

@@ -186,30 +202,67 @@ define([
186202
}
187203
var tab = registry.byId(id);
188204
if (tab) {
189-
if (tab.clearAll) {
190-
tab.clearAll();
191-
}
192205
tabs.removeChild(tab);
206+
tab.destroy();
193207
}
194208
if (tabs.hasChildren()) {
195-
tabs.selectChild(0);
209+
tab = tabs.selectChild(0);
210+
topic.publish(this.topicID + '/tableUpdated', tab);
211+
} else {
212+
this.closePane();
213+
topic.publish(this.topicID + '/tableUpdated', null);
214+
}
215+
},
216+
217+
// select an existing tab by ID
218+
selectTab: function (id) {
219+
var tabs = this.tabContainer;
220+
var tab = registry.byId(id);
221+
if (tab) {
222+
tabs.selectChild(tab);
196223
}
224+
topic.publish(this.topicID + '/tableUpdated', tab);
197225
},
198226

199227
getTab: function (options) {
200228
var tab = registry.byId(options.id);
201229
if (tab) {
202230
if (options.queryOptions) {
203-
tab.clearAll();
204231
tab.executeQueryTask(options);
205232
} else if (options.findOptions) {
206-
tab.clearAll();
207233
tab.executeFindTask(options);
208234
}
209235
}
210236
return tab;
211237
},
212238

239+
// get the sidebar pane containing the widget (if any)
240+
getSidebarPane: function () {
241+
if (!this.sidebarPane) {
242+
this.sidebarPane = registry.byId(this.sidebarID);
243+
}
244+
},
245+
246+
// open the sidebar pane containing this widget (if any)
247+
openPane: function () {
248+
this.togglePane('block');
249+
},
250+
251+
// open the sidebar pane containing this widget (if any)
252+
closePane: function () {
253+
this.togglePane('none');
254+
},
255+
256+
togglePane: function (show) {
257+
this.getSidebarPane();
258+
if (this.sidebarPane) {
259+
var paneID = this.sidebarPane.id.toLowerCase().replace('sidebar', '');
260+
topic.publish('viewer/togglePane', {
261+
pane: paneID,
262+
show: show
263+
});
264+
}
265+
},
213266
// this will resize all the children when the container is
214267
// is resized. This works when container is in the bottom pane.
215268
// Would it work with other panes? Is there a better way?

widgets/AttributesTable/Table.js

+11-17
Original file line numberDiff line numberDiff line change
@@ -301,13 +301,6 @@ define([
301301
}
302302
},
303303

304-
// get the sidebar pane containing the widget (if any)
305-
getSidebarPane: function () {
306-
if (!this.sidebarPane) {
307-
this.sidebarPane = registry.byId(this.sidebarID);
308-
}
309-
},
310-
311304
selectTab: function () {
312305
this.showAllGraphics();
313306
this.checkSizing();
@@ -317,6 +310,13 @@ define([
317310
this.hideAllGraphics();
318311
},
319312

313+
// get the sidebar pane containing the widget (if any)
314+
getSidebarPane: function () {
315+
if (!this.sidebarPane) {
316+
this.sidebarPane = registry.byId(this.sidebarID);
317+
}
318+
},
319+
320320
/*
321321
do some rather uncomfortable gymnastics to
322322
position the toolbar and grid components properly
@@ -348,16 +348,10 @@ define([
348348
domStyle.set(bodyNode, 'margin-bottom', (ftrBox.h + 1) + 'px');
349349
},
350350

351-
// open the sidebar pane containing this widget (if any)
352-
openPane: function () {
353-
this.getSidebarPane();
354-
if (this.sidebarPane) {
355-
var paneID = this.sidebarPane.id.toLowerCase().replace('sidebar', '');
356-
topic.publish('viewer/togglePane', {
357-
pane: paneID,
358-
show: 'block'
359-
});
360-
}
351+
destroy: function () {
352+
this.clearAll();
353+
this.removeGraphicLayers();
354+
this.inherited(arguments);
361355
},
362356

363357
mixinDeep: function (dest, source) {

widgets/AttributesTable/_FeaturesMixin.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ define([
5151

5252
getFeaturesFromResults: function () {
5353
var results = this.results;
54-
var features = [];
54+
var features = this.features || [];
5555

5656
if (results.features) {
57-
features = results.features;
57+
features = features.concat(results.features);
5858
} else if (this.queryParameters && this.queryParameters.type === 'relationship') {
5959
for (var key in results) {
6060
if (results.hasOwnProperty(key)) {
@@ -109,6 +109,7 @@ define([
109109
this.clearFeatureGraphics();
110110
this.clearSelectedFeatures();
111111
this.features = [];
112+
topic.publish(this.attributesContainerID + '/tableUpdated', this);
112113
},
113114

114115
clearSelectedFeatures: function () {
@@ -117,6 +118,7 @@ define([
117118
}
118119
this.clearSelectedGraphics();
119120
this.selectedFeatures = [];
121+
topic.publish(this.attributesContainerID + '/tableUpdated', this);
120122
},
121123

122124
doneSelectingFeatures: function (zoom) {
@@ -137,6 +139,7 @@ define([
137139
}
138140

139141
this.setToolbarButtons();
142+
topic.publish(this.attributesContainerID + '/tableUpdated', this);
140143

141144
// publish the results of our selection
142145
var sv = (zoom && this.selectedFeatures.length === 1) ? this.featureOptions.streetView : false;

widgets/AttributesTable/_FindTaskMixin.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,9 @@ define([
4242
if (this.executingQuery === true) {
4343
return;
4444
}
45-
this.getConfiguration(options);
45+
this.clearAll();
4646

47-
this.clearFeatures();
48-
this.clearSelectedFeatures();
49-
this.clearGrid();
47+
this.getConfiguration(options);
5048

5149
var url = this.getFindTaskURL();
5250
if (!url) {

widgets/AttributesTable/_GraphicsMixin.js

+56-22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
define([
22
'dojo/_base/declare',
33
'dojo/_base/lang',
4+
'dojo/topic',
5+
'dojo/_base/array',
46
'dojo/sniff',
57

68
'esri/layers/GraphicsLayer',
@@ -13,6 +15,8 @@ define([
1315
], function (
1416
declare,
1517
lang,
18+
topic,
19+
array,
1620
has,
1721

1822
GraphicsLayer,
@@ -271,6 +275,8 @@ define([
271275
id: this.topicID + '_SelectedGraphics',
272276
title: 'Attribute Selected Graphics'
273277
});
278+
this.selectedGraphics.on('click', lang.hitch(this, 'selectFeatureFromMap'));
279+
274280
this.map.addLayer(this.selectedGraphics);
275281

276282
},
@@ -376,32 +382,41 @@ define([
376382
if (key) {
377383
row = this.grid.row(key);
378384
if (row) {
379-
if (!evt.ctrlKey) {
380-
this.clearSelectedFeatures();
381-
}
382-
if (row.element) { // it is in the current grid
383-
if (this.grid.select) {
384-
// prevents the map from moving around
385-
// by zooming to selected features
386-
var mnu = this.toolbarOptions.zoom;
387-
var zm = mnu.selected;
388-
mnu.selected = false;
389-
this.grid.select(row);
390-
this.grid.focus(row.element);
391-
row.element.focus();
392-
mnu.selected = zm;
393-
this.setToolbarButtons();
394-
}
395-
} else {
396-
feature = this.getFeatureFromStore(key);
397-
if (feature && feature.geometry) {
398-
this.addSelectedGraphic(feature);
399-
this.doneSelectingFeatures(false);
385+
// prevents the map from moving around
386+
// by zooming to selected features
387+
var mnu = this.toolbarOptions.zoom;
388+
var zm = mnu.selected;
389+
mnu.selected = false;
390+
391+
var selection = lang.clone(this.grid.get('selection'));
392+
selection[key] = (selection[key] !== true);
393+
394+
this.selectedFeatures = [];
395+
this.selectedGraphics.clear();
396+
//this.grid.clearSelection();
397+
398+
for (var sKey in selection) {
399+
if (selection.hasOwnProperty(sKey)) {
400+
if (this.grid.select) {
401+
row = this.grid.row(sKey);
402+
this.grid.select(row, null, selection[sKey]);
403+
}
404+
if (selection[sKey]) {
405+
feature = this.getFeatureFromStore(sKey);
406+
if (feature && feature.geometry) {
407+
this.addSelectedGraphic(feature);
408+
}
409+
}
400410
}
401411
}
412+
this.doneSelectingFeatures(false);
413+
414+
// reset the original zooming
415+
mnu.selected = zm;
416+
this.setToolbarButtons();
402417
}
403418
}
404-
if (!evt.ctrlKey && this.selectedFeatures.length === 1) {
419+
if (!evt.ctrlKey && !evt.shiftKey && this.selectedFeatures.length === 1) {
405420
if (graphic.infoTemplate && this.map.infoWindow) {
406421
var center,
407422
extent = this.getGraphicsExtent(this.selectedGraphics);
@@ -639,7 +654,26 @@ define([
639654
layer.clear();
640655
}
641656
this.setToolbarButtons();
657+
topic.publish(this.attributesContainerID + '/tableUpdated', this);
658+
659+
},
660+
661+
/*******************************
662+
* Remove Graphic Layers
663+
*******************************/
664+
665+
removeGraphicLayers: function () {
666+
this.map.removeLayer(this.featureGraphics);
667+
this.featureGraphics = null;
668+
669+
this.map.removeLayer(this.selectedGraphics);
670+
this.selectedGraphics = null;
671+
672+
this.map.removeLayer(this.sourceGraphics);
673+
this.sourceGraphics = null;
642674

675+
this.map.removeLayer(this.bufferGraphics);
676+
this.bufferGraphics = null;
643677
}
644678
});
645679
});

0 commit comments

Comments
 (0)