widgets/Search.js
define([
'dojo/_base/declare',
'dijit/_WidgetBase',
'dijit/_TemplatedMixin',
'dijit/_WidgetsInTemplateMixin',
'./Search/QueryBuilder/QueryBuilderMixin',
'dojo/_base/lang',
'dojo/on',
'dojo/dom-style',
'dojo/aspect',
'dojo/topic',
'dojo/keys',
'dojo/_base/array',
'dojo/dom',
'dojo/dom-construct',
'dojo/dom-attr',
'dojo/dom-geometry',
'dijit/registry',
'dojo/io-query',
'dojo/when',
'dojo/promise/all',
'dojo/Deferred',
'dijit/form/Select',
'dijit/form/TextBox',
'dijit/form/SimpleTextarea',
'dijit/form/DateTextBox',
'dijit/form/TimeTextBox',
'dijit/form/NumberTextBox',
'dijit/form/CurrencyTextBox',
'dijit/form/NumberSpinner',
'esri/request',
'esri/toolbars/draw',
'esri/tasks/query',
'esri/tasks/GeometryService',
'esri/geometry/geometryEngine',
'esri/layers/GraphicsLayer',
'esri/graphic',
'esri/symbols/SimpleMarkerSymbol',
'esri/symbols/SimpleLineSymbol',
'esri/symbols/SimpleFillSymbol',
'./Search/GetDistinctValues',
// template
'dojo/text!./Search/templates/Search.html',
//i18n
'dojo/i18n!./Search/nls/Search',
//template widgets
'dijit/layout/LayoutContainer',
'dijit/layout/ContentPane',
'dijit/layout/TabContainer',
'dijit/form/Button',
'dijit/form/CheckBox',
'dijit/form/ToggleButton',
// css
'xstyle/css!./Search/css/Search.css',
'xstyle/css!./Search/css/Draw.css'
], function (
declare,
_WidgetBase,
_TemplatedMixin,
_WidgetsInTemplateMixin,
_QueryBuilderMixin,
lang,
on,
domStyle,
aspect,
topic,
keys,
array,
dom,
domConstruct,
domAttr,
domGeom,
registry,
ioQuery,
when,
allPromise,
Deferred,
Select,
TextBox,
SimpleTextarea,
DateTextBox,
TimeTextBox,
NumberTextBox,
CurrencyTextBox,
NumberSpinner,
esriRequest,
Draw,
Query,
GeometryService,
geometryEngine,
GraphicsLayer,
Graphic,
SimpleMarkerSymbol,
SimpleLineSymbol,
SimpleFillSymbol,
GetDistinctValues,
template,
i18n
) {
return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, _QueryBuilderMixin], {
name: 'Search',
baseClass: 'cmvSearchWidget',
widgetsInTemplate: true,
templateString: template,
mapClickMode: null,
// i18n
defaultI18n: i18n,
i18n: {},
title: 'Search Results',
topicID: 'searchResults',
attributesContainerID: 'attributesContainer',
layerJSON: {},
shapeLayer: 0,
attributeLayer: 0,
searchIndex: 0,
drawToolbar: null,
isAdvancedSearch: false,
loadingCount: 0,
// to override the default tab when the widget starts
defaultTab: 0,
defaultBufferDistance: 0,
/*
To hide specific tabs.
This is an zero-based array so [1] would hide the second tab.
It is an array to anticipate more than 2 tabs in a future release.
*/
hiddenTabs: [],
// collects the geometry from multiple shapes for use in the search
spatialGeometry: null,
// the current tab/table of search results
selectedTable: null,
/*
Search capabilities that can be enabled/disabled
individually in the configuration file.
*/
enableAdvancedSearch: false,
enableDrawMultipleShapes: true,
enableAddToExistingResults: true,
enableSpatialFilters: true,
// configure which spatial filters are available
spatialFilters: {
entireMap: true,
currentExtent: true,
identifiedFeature: true,
searchFeatures: true,
searchSelected: true,
searchSource: true,
searchBuffer: true
},
drawingOptions: {
rectangle: true,
circle: true,
point: true,
polyline: true,
freehandPolyline: true,
polygon: true,
freehandPolygon: true,
stopDrawing: true,
identifiedFeature: true,
selectedFeatures: true,
symbols: {}
},
useIdentifyPanel: true,
defaultQueryStringOptions: {
// what parameter is used to pass the layer index
layerParameter: 'layer',
// what parameter is used to pass the attribute search index
searchParameter: 'search',
// what parameter is used to pass the values to be searched
valueParameter: 'values',
// if passing multiple values, how are they delimited
valueDelimiter: '|',
// Should the widget open when the search is executed?
openWidget: true
},
// symbology for drawn shapes
defaultSymbols: {
point: {
type: 'esriSMS',
style: 'esriSMSCircle',
size: 6,
color: [0, 0, 0, 64],
angle: 0,
xoffset: 0,
yoffset: 0,
outline: {
type: 'esriSLS',
style: 'esriSLSSolid',
color: [255, 0, 0],
width: 2
}
},
polyline: {
type: 'esriSLS',
style: 'esriSLSSolid',
color: [255, 0, 0],
width: 2
},
polygon: {
type: 'esriSFS',
style: 'esriSFSSolid',
color: [0, 0, 0, 64],
outline: {
type: 'esriSLS',
style: 'esriSLSSolid',
color: [255, 0, 0],
width: 1
}
},
// symbology for buffer around shapes
buffer: {
type: 'esriSFS',
style: 'esriSFSSolid',
color: [255, 0, 0, 32],
outline: {
type: 'esriSLS',
style: 'esriSLSDash',
color: [255, 0, 0, 255],
width: 1
}
}
},
bufferUnits: [
{
value: GeometryService.UNIT_FOOT,
label: 'Feet',
selected: true
},
{
value: GeometryService.UNIT_STATUTE_MILE,
label: 'Miles'
},
{
value: GeometryService.UNIT_METER,
label: 'Meters'
},
{
value: GeometryService.UNIT_KILOMETER,
label: 'Kilometers'
},
{
value: GeometryService.UNIT_NAUTICAL_MILE,
label: 'Nautical Miles'
},
{
value: GeometryService.UNIT_US_NAUTICAL_MILE,
label: 'US Nautical Miles'
}
],
postMixInProperties: function () {
this.inherited(arguments);
this.i18n = this.mixinDeep(this.defaultI18n, this.i18n);
},
postCreate: function () {
this.inherited(arguments);
this.initAdvancedFeatures();
this.initLayerSelect();
this.initSpatialFilters();
this.inputBufferDistance.set('value', this.defaultBufferDistance || 0);
this.selectBufferUnits.set('options', this.bufferUnits);
this.drawToolbar = new Draw(this.map);
this.enableDrawingButtons();
this.addGraphicsLayer();
this.tabContainer.watch('selectedChildWidget', lang.hitch(this, function () {
this.stopDrawing();
}));
if (this.useIdentifyPanel) {
this.own(topic.subscribe('identifyPanel/show', lang.hitch(this, 'enableIdentifyButton')));
this.own(topic.subscribe('identifyPanel/hide', lang.hitch(this, 'disableIdentifyButton')));
this.own(topic.subscribe('identifyPanel/update', lang.hitch(this, function (features) {
if (features && features.length > 0) {
this.enableIdentifyButton();
} else {
this.disableIdentifyButton();
}
})));
}
if (this.map.infoWindow) {
on(this.map.infoWindow, 'show', lang.hitch(this, 'enableIdentifyButton'));
on(this.map.infoWindow, 'hide', lang.hitch(this, 'disableIdentifyButton'));
}
this.own(on(this.drawToolbar, 'draw-end', lang.hitch(this, 'endDrawing')));
if (this.map.infoWindow && this.map.infoWindow.count) {
this.enableIdentifyButton();
}
this.addTopics();
},
startup: function () {
this.inherited(arguments);
this.buildSearchControls();
if (this.getParent) {
var parent = this.getParent();
if (parent) {
this.own(on(parent, 'show', lang.hitch(this, function () {
this.tabContainer.resize();
})));
}
}
aspect.after(this, 'resize', lang.hitch(this, function () {
this.tabContainer.resize();
}));
this.tabChildren = this.tabContainer.getChildren();
if (this.defaultTab !== null) {
var defTab = this.tabChildren[this.defaultTab];
if (defTab) {
this.tabContainer.selectChild(defTab);
}
}
var k = 0, len = this.hiddenTabs.length;
for (k = 0; k < len; k++) {
var tab = this.tabChildren[this.hiddenTabs[k]];
domStyle.set(tab.domNode, 'display', 'none');
domStyle.set(tab.controlButton.domNode, 'display', 'none');
}
// Search from the applications query string
this.checkQueryString();
this.setAdvancedSearch(false);
},
addTopics: function () {
this.own(topic.subscribe('mapClickMode/currentSet', lang.hitch(this, 'setMapClickMode')));
this.own(topic.subscribe(this.topicID + '/search', lang.hitch(this, 'executeSearch')));
this.own(topic.subscribe(this.attributesContainerID + '/tableUpdated', lang.hitch(this, 'setSearchTable')));
if (this.parentWidget) {
this.own(aspect.after(this.parentWidget, 'resize', lang.hitch(this, 'resize')));
this.own(topic.subscribe(this.parentWidget.id + '/resize/resize', lang.hitch(this, 'resize')));
this.own(topic.subscribe('titlePane/event', lang.hitch(this, function (args) {
if (this.parentWidget && args.widgetID === this.parentWidget.id && (args.action === 'dock' || args.action === 'undock')) {
this.resize({
action: args.action
});
}
})));
}
},
/*******************************
* Search Functions
*******************************/
executeSearchWithReturn: function (evt) {
if (evt.keyCode === keys.ENTER) {
this.doAttributeSearch();
}
},
search: function (geometry, layerIndex, advancedQuery) {
if (!this.layers || this.layers.length === 0) {
return;
}
this.laterSearchesAdded = 0;
var isQuery = false;
var layer = this.layers[layerIndex];
var search = layer.attributeSearches[this.searchIndex] || {};
var searchOptions = this.buildSearchOptions(layer, search, advancedQuery);
if (layer.findOptions) { // It is a FindTask
searchOptions.findOptions = this.buildFindOptions(layer, search);
} else {
searchOptions.queryOptions = this.buildQueryOptions(layer, search, geometry, advancedQuery);
isQuery = true;
}
this.hideInfoWindow();
// publish to an accompanying attributed table
if (searchOptions.findOptions || searchOptions.queryOptions) {
topic.publish(this.attributesContainerID + '/addTable', searchOptions);
if (isQuery && searchOptions.queryOptions.queryParameters.additionalSubLayerIDs &&
searchOptions.queryOptions.queryParameters.additionalSubLayerIDs.length > 0) {
this.laterSearchesHandler = topic.subscribe(searchOptions.topicID + '/queryResults', lang.hitch(this, function (results) {
this.handleMultipleSearches(results, searchOptions);
}));
}
}
},
handleMultipleSearches: function (results, searchOptions) {
if (results) {
if (this.laterSearchesAdded < searchOptions.queryOptions.queryParameters.additionalSubLayerIDs.length) {
var additionalSubLayerID = searchOptions.queryOptions.queryParameters.additionalSubLayerIDs[this.laterSearchesAdded];
searchOptions.queryOptions.queryParameters.addToExisting = true;
searchOptions.queryOptions.queryParameters.sublayerID = additionalSubLayerID;
this.laterSearchesAdded += this.laterSearchesAdded + 1;
topic.publish(this.attributesContainerID + '/addTable', searchOptions);
} else {
this.laterSearchesHandler.remove();
}
}
},
buildSearchOptions: function (layer, search, advancedQuery) {
var gridOptions = lang.clone(search.gridOptions || layer.gridOptions || {});
var featureOptions = lang.clone(search.featureOptions || layer.featureOptions || {});
var symbolOptions = lang.clone(search.symbolOptions || layer.symbolOptions || {});
var toolbarOptions = lang.clone(search.toolbarOptions || layer.toolbarOptions || {});
var infoTemplates = lang.clone(search.infoTemplates || layer.infoTemplates || {});
return {
title: search.title || layer.title || this.title,
topicID: search.topicID || layer.topicID || this.topicID,
findOptions: null,
queryOptions: advancedQuery || null,
gridOptions: gridOptions,
featureOptions: featureOptions,
symbolOptions: symbolOptions,
toolbarOptions: toolbarOptions,
infoTemplates: infoTemplates
};
},
buildQueryOptions: function (layer, search, geometry, advancedQuery) {
var where = null,
distance = null,
unit = null,
showOnly = false,
addToExisting = false,
queryOptions = {
idProperty: search.idProperty || layer.idProperty || 'FID',
linkField: search.linkField || layer.linkField || null,
linkedQuery: lang.clone(search.linkedQuery || layer.linkedQuery || null)
};
if (geometry) {
distance = this.inputBufferDistance.get('value');
if (isNaN(distance)) {
topic.publish('growler/growl', {
title: 'Search',
message: 'Invalid distance',
level: 'error',
timeout: 3000
});
return null;
}
unit = this.selectBufferUnits.get('value');
showOnly = this.checkBufferOnly.get('checked');
addToExisting = this.checkSpatialAddToExisting.get('checked');
} else {
where = this.buildWhereClause(layer, search, advancedQuery);
if (where === null) {
return null;
}
geometry = this.getSpatialFilterGeometry();
addToExisting = this.checkAttributeAddToExisting.get('checked');
}
var queryParameters = lang.clone(search.queryParameters || layer.queryParameters || {});
queryOptions.queryParameters = lang.mixin(queryParameters, {
//type: search.type || layer.type || 'spatial',
geometry: this.geometryToJson(geometry),
where: where,
addToExisting: addToExisting,
outSpatialReference: search.outSpatialReference || this.map.spatialReference,
spatialRelationship: search.spatialRelationship || layer.spatialRelationship || Query.SPATIAL_REL_INTERSECTS
});
var bufferParameters = lang.clone(search.bufferParameters || layer.bufferParameters || {});
queryOptions.bufferParameters = lang.mixin(bufferParameters, {
distance: distance,
unit: unit,
showOnly: showOnly
});
return queryOptions;
},
buildFindOptions: function (layer, search) {
var searchTerm = null;
if (search.searchFields.length > 0) {
var inputId = search.inputIds[0];
var input = registry.byId(inputId);
searchTerm = this.getSearchTerm(input, search.searchFields[0]);
if (searchTerm === null) {
return null;
}
}
return lang.mixin(layer.findOptions, {
searchText: searchTerm,
contains: !this.containsSearchText.checked,
outSpatialReference: search.outSpatialReference || this.map.spatialReference
});
},
buildWhereClause: function (layer, search, advancedQuery) {
var fields = search.searchFields;
var searchTerm = null;
var where = this.getDefaultWhereClause(layer, search);
if (advancedQuery && advancedQuery.where) {
if (where !== '') {
where += ' AND ';
}
where = where + '(' + advancedQuery.where + ')';
return where;
}
var len = fields.length;
for (var k = 0; k < len; k++) {
var field = fields[k];
var inputId = search.inputIds[k];
var input = registry.byId(inputId);
if (field.where) {
if (where !== '') {
where += ' AND ';
}
where += '(' + field.where + ')';
}
searchTerm = this.getSearchTerm(input, field);
if (searchTerm === null) {
return null;
} else if (searchTerm.length > 0 && field.expression) {
var attrWhere = field.expression;
attrWhere = attrWhere.replace(/\[value\]/g, searchTerm);
if (!attrWhere) {
break;
}
if (where !== '') {
where += ' AND ';
}
where += attrWhere;
}
}
if (where.length === 0) {
where = '1=1';
}
return where;
},
getSpatialFilterGeometry: function () {
var geometry = null, type = this.selectAttributeSpatialFilter.get('value');
switch (type) {
case 'entireMap':
break;
case 'currentExtent':
geometry = this.map.extent;
break;
case 'identifiedFeatures':
geometry = this.getGeometryFromIdentifiedFeature();
break;
case 'searchSource':
if (this.selectedTable) {
geometry = this.getGeometryFromGraphicsLayer(this.selectedTable.sourceGraphics);
}
break;
case 'searchFeatures':
if (this.selectedTable) {
geometry = this.getGeometryFromGraphicsLayer(this.selectedTable.featureGraphics);
}
break;
case 'searchSelected':
if (this.selectedTable) {
geometry = this.getGeometryFromSelectedFeatures();
}
break;
case 'searchBuffer':
if (this.selectedTable) {
geometry = this.getGeometryFromGraphicsLayer(this.selectedTable.bufferGraphics);
}
break;
default:
break;
}
return geometry;
},
getGeometryFromGraphicsLayer: function (layer) {
if (!layer || !layer.graphics) {
return null;
}
var graphics = layer.graphics;
var k = 0, len = graphics.length, geoms = [];
for (k = 0; k < len; k++) {
geoms.push(graphics[k].geometry);
}
return geometryEngine.union(geoms);
},
getGeometryFromIdentifiedFeature: function () {
var popup = this.map.infoWindow,
feature = null;
if (popup && (this.useIdentifyPanel || popup.isShowing)) {
feature = popup.getSelectedFeature();
}
return feature.geometry;
},
getGeometryFromSelectedFeatures: function () {
var geom = null;
if (this.selectedTable) {
geom = this.getGeometryFromGraphicsLayer(this.selectedTable.selectedGraphics);
}
return geom;
},
getSearchTerm: function (input, field) {
var fieldName = field.label || field.field || field.name;
if (input.isValid && !input.isValid()) {
topic.publish('growler/growl', {
title: 'Search',
message: 'Invalid value for ' + fieldName + '.',
level: 'error',
timeout: 3000
});
return null;
}
var value = input.get('value'), searchTerm = '';
switch (field.type) {
case 'date':
case 'time':
case 'number':
case 'currency':
case 'numberspinner':
value = input.toString();
if (field.format) {
searchTerm = input.format(value);
} else {
searchTerm = value;
}
break;
default:
if (lang.isArray(value)) {
searchTerm = value.join('\', \'');
}
searchTerm = value;
if (searchTerm === '*' || searchTerm === null) {
searchTerm = '';
}
break;
}
if (searchTerm === '' && field.required) {
input.domNode.focus();
topic.publish('growler/growl', {
title: 'Search',
message: 'You must provide a search term for ' + fieldName + '.',
level: 'error',
timeout: 3000
});
return null;
}
if (field.minChars && field.required) {
if (searchTerm.length < field.minChars) {
input.domNode.focus();
topic.publish('growler/growl', {
title: 'Search',
message: 'Search term for ' + fieldName + ' must be at least ' + field.minChars + ' characters.',
level: 'error',
timeout: 3000
});
return null;
}
}
return searchTerm;
},
// a topic subscription to listen for published topics
// also used to search from the queryString
executeSearch: function (options) {
if (options.bufferDistance) {
this.inputBufferDistance.set('value', options.bufferDistance);
if (options.bufferUnits) {
this.selectBufferUnits.set('value', options.bufferUnits);
}
}
//attribute search
var doAttrSearch = false;
if (options.searchTerm) {
var inputId = null,
input = null,
layer = this.layers[options.layerIndex];
if (layer) {
this.attributeLayer = options.layerIndex;
this.onAttributeLayerChange(this.attributeLayer);
var search = layer.attributeSearches[options.searchIndex];
if (search) {
this.onAttributeQueryChange(options.searchIndex);
if (lang.isArray(options.searchTerm)) {
var len = options.searchTerm.length;
for (var k = 0; k < len; k++) {
inputId = search.inputIds[k];
if (inputId) {
input = registry.byId(inputId);
if (input) {
input.set('value', options.searchTerm[k]);
doAttrSearch = true;
}
}
}
} else {
inputId = search.inputIds[0];
input = registry.byId(inputId);
if (input) {
input.set('value', options.searchTerm);
doAttrSearch = true;
}
}
}
}
}
if (options.geometry || doAttrSearch) {
this.search(options.geometry, options.layerIndex);
}
},
checkQueryString: function () {
// searching by geometry from the query string is not yet supported
var options = this.mixinDeep(this.defaultQueryStringOptions, this.queryStringOptions || {});
var uri = window.location.href;
var qs = uri.substring(uri.indexOf('?') + 1, uri.length);
var qsObj = ioQuery.queryToObject(qs);
var value = qsObj[options.valueParameter];
var layerIndex = qsObj[options.layerParameter] || 0;
var searchIndex = qsObj[options.searchParameter] || 0;
var widget = null;
// only continue if there is a term to search
if (!value) {
return;
}
if (value.indexOf(options.valueDelimiter) > -1) {
value = value.split(options.valueDelimiter);
}
if (options.openWidget) {
widget = this.parentWidget;
if (widget && widget.toggleable) {
if (!widget.open) {
widget.toggle();
}
}
}
// make sure the attributesTable widget is loaded before executing
// check every 0.25 seconds
var qsTimer = window.setInterval(lang.hitch(this, function () {
widget = registry.byId(this.attributesContainerID + '_widget');
if (widget) {
// no need to continue, so clear the timer
window.clearInterval(qsTimer);
// we're ready so execute the search.
this.executeSearch({
layerIndex: layerIndex,
searchIndex: searchIndex,
searchTerm: value
});
}
}), 250);
// clear the timer after 30 seconds in case we are waiting that long
window.setTimeout(function () {
window.clearInterval(qsTimer);
}, 30000);
},
/*******************************
* Form/Field Functions
*******************************/
// Initialize the controls used for the search.
buildSearchControls: function () {
// change to
var domNode = this.divAttributeQueryFields;
if (domNode) {
for (var i = 0; i < this.layers.length; i++) {
var layer = this.layers[i];
if (layer) {
var searches = layer.attributeSearches;
if (searches) {
for (var j = 0; j < searches.length; j++) {
var search = searches[j];
if (search) {
var firstSearch = ((i === 0) && (j === 0));
// add the div for the search
var id = '_' + i.toString() + '_' + j.toString();
var divName = 'divSearch' + id;
var divNode = domConstruct.create('div', {
id: divName,
style: {
display: 'none'
}
}, domNode, 'last');
// display the first search for the first layer
if (firstSearch) {
domStyle.set(divName, 'display', 'block');
}
search.divName = divName;
search.inputIds = [];
// add the controls for the search
for (var k = 0; k < search.searchFields.length; k++) {
this.buildSearchControl(search, layer, divNode, id, k, firstSearch);
}
//this.initialized = true;
}
}
}
}
}
}
},
buildSearchControl: function (search, layer, divNode, id, k, firstSearch) {
var field = search.searchFields[k];
var inputId = 'inputSearch_' + id + '_' + k.toString();
if (field) {
var fieldNode = domConstruct.create('div', {
className: 'searchField'
}, divNode, 'last');
this.buildSearchControlLabel(field, search, layer, fieldNode);
if (field.unique || field.values) {
this.buildSearchControlSelect(field, search, layer, fieldNode, inputId, firstSearch);
} else {
this.buildSearchControlInput(field, search, layer, fieldNode, inputId);
}
// the first input field is for focus
search.inputIds.push(inputId);
}
},
buildSearchControlLabel: function (field, search, layer, fieldNode) {
var labelWidth = field.labelWidth || layer.labelWidth || null;
if (typeof labelWidth === 'number') {
labelWidth += 'px';
}
var txt = field.label + ':';
var title = field.label;
if (field.minChars) {
title = 'Enter at least ' + field.minChars + ' characters';
}
domConstruct.create('div', {
innerHTML: txt,
className: 'searchFieldLabel',
title: title,
style: {
width: labelWidth
}
}, fieldNode, 'last');
},
buildSearchControlSelect: function (field, search, layer, fieldNode, inputId, firstSearch) {
var input = null,
style = field.style || layer.style || null,
fieldWidth = field.width || layer.fieldWidth || '99%',
fieldHeight = field.height || layer.fieldHeight || 'inherit',
options = [];
if (typeof fieldWidth === 'number') {
fieldWidth += 'px';
}
if (typeof fieldHeight === 'number') {
fieldHeight += 'px';
}
if (field.values) {
array.forEach(field.values, function (item) {
if (typeof item === 'string') {
options.push({
label: item,
value: item,
selected: false
});
} else {
options.push(item);
}
});
if (options.length > 0) {
options[0].selected = true;
}
}
input = new Select({
id: inputId,
options: options,
disabled: (!field.values),
style: style || {
height: fieldHeight,
width: fieldWidth
}
});
if (input) {
input.placeAt(fieldNode, 'last');
}
// only do this for the first search for the first layer
if (field.type === 'unique' && firstSearch) {
var queryParameters = lang.clone(layer.queryParameters);
queryParameters.url = field.url || layer.queryParameters.url;
var where = this.getDefaultWhereClause(layer, search, field);
var fieldName = field.field || field.name;
this.getDistinctValues(inputId, queryParameters, fieldName, field.includeBlankValue, where);
}
},
buildSearchControlInput: function (field, search, layer, fieldNode, inputId) {
var input = null,
style = field.style || layer.style || null,
fieldWidth = field.width || layer.fieldWidth || '99%',
fieldHeight = field.height || layer.fieldHeight || 'inherit';
if (typeof fieldWidth === 'number') {
fieldWidth += 'px';
}
if (typeof fieldHeight === 'number') {
fieldHeight += 'px';
}
var options = {
id: inputId,
constraints: field.constraints || {},
value: field.defaultValue,
placeHolder: field.placeholder,
style: style || {
height: fieldHeight,
width: fieldWidth
}
};
switch (field.type) {
case 'date':
input = new DateTextBox(options);
break;
case 'time':
input = new TimeTextBox(options);
break;
case 'number':
input = new NumberTextBox(options);
break;
case 'currency':
input = new CurrencyTextBox(options);
break;
case 'numberspinner':
options.smallDelta = field.smallDelta || 1;
input = new NumberSpinner(options);
break;
case 'textarea':
input = new SimpleTextarea(options);
break;
default:
input = new TextBox(options);
break;
}
if (input) {
input.placeAt(fieldNode, 'last');
this.own(on(input, 'keyup', lang.hitch(this, 'executeSearchWithReturn')));
}
},
initLayerSelect: function () {
var attrOptions = [],
shapeOptions = [];
var len = this.layers.length,
option = null,
attributeLayerSet = false;
for (var i = 0; i < len; i++) {
option = {
value: i,
label: this.layers[i].name
};
if (this.layers[i].attributeSearches && this.layers[i].attributeSearches.length > 0) {
attrOptions.push(lang.clone(option));
if (!attributeLayerSet) {
this.attributeLayer = i;
attributeLayerSet = true;
}
}
if (this.layers[i].queryParameters && this.layers[i].queryParameters.type === 'spatial') {
option.value = (shapeOptions.length);
shapeOptions.push(option);
}
}
if (attrOptions.length > 0) {
this.selectLayerByAttribute.set('options', attrOptions);
this.onAttributeLayerChange(this.attributeLayer);
} else {
this.selectLayerByAttribute.set('disabled', true);
}
if (shapeOptions.length > 0) {
this.selectLayerByShape.set('options', shapeOptions);
this.onShapeLayerChange(this.shapeLayer);
} else {
this.selectLayerByShape.set('disabled', true);
}
},
initAdvancedFeatures: function () {
// allow or not the Advanced Attributes Search
this.checkAdvancedSearchEnabled();
// allow or not the drawing multiple shapes before searching
if (!this.enableDrawMultipleShapes) {
domStyle.set(this.btnSpatialSearch.domNode, 'display', 'none');
this.drawingOptions.stopDrawing = false;
}
// allow or the search results to be added to the previous results
if (!this.enableAddToExistingResults) {
domStyle.set(this.divAttributeAddToExisting, 'display', 'none');
domStyle.set(this.divSpatialAddToExisting, 'display', 'none');
this.drawingOptions.selectedFeatures = false;
}
// allow or not the use of spatial features
if (!this.enableSpatialFilters) {
domStyle.set(this.divAttributeSpatialFilter, 'display', 'none');
}
},
onShapeLayerChange: function (newValue) {
this.shapeLayer = newValue;
},
onAttributeLayerChange: function (newValue) {
this.attributeLayer = newValue;
this.selectAttributeQuery.set('disabled', true);
this.showLoadingSpinnerWhile(allPromise([
this.loadBasicAttributeQuerySelect()
]));
},
loadBasicAttributeQuerySelect: function () {
var layer = this.layers[this.attributeLayer];
if (!layer || !layer.attributeSearches) {
return when(null);
}
domStyle.set(this.divAttributeQuerySelect, 'display', 'none');
this.selectAttributeQuery.set('value', null);
this.selectAttributeQuery.set('options', null);
if (!layer.attributeSearches || layer.attributeSearches.length === 0) {
return when(null);
}
var options = layer.attributeSearches.map(function (search, i) {
var option = {
value: i,
label: search.name
};
if (i === 0) {
option.selected = true;
}
return option;
});
this.selectAttributeQuery.set('options', options);
this.selectAttributeQuery.set('disabled', false);
this.selectAttributeQuery.set('value', 0);
return this.onAttributeQueryChange(0).then(lang.hitch(this, function () {
if (options.length > 1) {
domStyle.set(this.divAttributeQuerySelect, 'display', 'block');
}
}));
},
showLoadingSpinnerWhile: function (fn) {
this.loadingCount += 1;
domStyle.set(this.divLoadingSpinner, 'display', 'block');
domStyle.set(this.divSearchAttributesCenter, 'display', 'none');
if (typeof fn === 'function') {
fn = fn();
}
return when(fn).then(lang.hitch(this, function () {
this.loadingCount -= 1;
if (this.loadingCount === 0) {
domStyle.set(this.divLoadingSpinner, 'display', 'none');
domStyle.set(this.divSearchAttributesCenter, 'display', 'block');
}
}));
},
onAttributeQueryChange: function (newValue) {
// 'none' all of the query divs
var domNode = this.divAttributeQueryFields;
if (domNode) {
array.forEach(this.layers, function (layer) {
if (!layer.attributeSearches) {
return;
}
array.forEach(layer.attributeSearches, function (search) {
var divNode = dom.byId(search.divName);
if (divNode) {
domStyle.set(search.divName, 'display', 'none');
}
});
});
}
// 'block' the query div and set the focus to the first widget
this.searchIndex = newValue;
var layer = this.layers[this.attributeLayer];
if (!layer || !layer.attributeSearches || !layer.attributeSearches[newValue]) {
return when(null);
}
var search = layer.attributeSearches[newValue];
if (!dom.byId(search.divName)) {
return when(null);
}
var queryBuilderPromise = this.getQueryBuilder();
// refresh the controls if any require unique values
return allPromise(
queryBuilderPromise,
search.searchFields.map(lang.hitch(this, function (field, k) {
if (field.unique) {
var queryParameters = lang.clone(search.queryParameters || layer.queryParameters || {});
var where = this.getDefaultWhereClause(layer, search, field);
if (field.url) {
queryParameters.url = field.url;
}
var fieldName = field.field || field.name;
return this.getDistinctValues(search.inputIds[k], queryParameters, fieldName, field.includeBlankValue, where);
}
return when(null);
}))
).then(lang.hitch(this, function () {
domStyle.set(search.divName, 'display', 'block');
// only show "Contains" checkbox for FindTasks
domStyle.set(this.divQueryContains, 'display', ((layer.findOptions) ? 'block' : 'none'));
this.checkAdvancedSearchEnabled(layer, search);
this.checkClearButtonEnabled(layer, search);
// put focus on the first input field
var input = registry.byId(search.inputIds[0]);
if (input && input.domNode) {
input.domNode.focus();
this.btnAttributeSearch.set('disabled', false);
}
}));
},
clearAttributeFields: function () {
var layer = this.layers[this.attributeLayer];
if (layer) {
var searches = layer.attributeSearches;
if (searches) {
for (var j = 0; j < searches.length; j++) {
var search = searches[j];
if (search) {
var divNode = dom.byId(search.divName);
if (!divNode) {
return;
}
for (var k = 0; k < search.searchFields.length; k++) {
var input = registry.byId(search.inputIds[k]);
if (input) {
input.setValue('');
}
}
}
}
}
}
},
getDefaultWhereClause: function (layer, search, field) {
var where = layer.expression || '';
if (search && search.expression) {
if (where !== '') {
where += ' AND ';
}
where += '(' + search.expression + ')';
}
if (field && field.where) {
if (where !== '') {
where += ' AND ';
}
where += '(' + field.where + ')';
}
return where;
},
/*
* Retrieve the list of distinct values from ArcGIS Server using the ArcGIS API for JavaScript.
* @param {string} inputId The Dojo id of the control to populate with unique values.
* @param {object} queryParameters Used to get the operational layer's url to be queried for unique values.
* @param {string} fieldName The field name for which to retrieve unique values.
* @param {boolean} includeBlankValue Whether to add a blank (null) value to the resulting list.
* @param {string} expression The where expression with which to filter the query.
*/
getDistinctValues: function (inputId, queryParameters, fieldName, includeBlankValue, expression) {
var url = this.getLayerURL(queryParameters);
// To support coded domains, load the feature layer before continuing
var deferred = this.getLayerJSON(url);
deferred.then(lang.hitch(this, function (layer) {
var doSort = false, codedValues = null;
if (layer) {
codedValues = this.getFieldCodedValues(layer, fieldName);
}
var q = new GetDistinctValues(url, fieldName, expression);
q.executeQuery().then(lang.hitch(this, function (results) {
var options = [];
options = options.concat(array.map(results, lang.hitch(this, function (value) {
var label = value;
if (codedValues) {
var k = null, len = codedValues.length;
for (k = 0; k < len; k++) {
var codedValue = codedValues[k];
if (value === codedValue.code) {
label = codedValue.name;
doSort = true;
}
}
}
return {
label: label,
value: value,
selected: false
};
})));
if (doSort) {
options.sort(function (a, b) {
var lA = (a.label) ? a.label.toLowerCase() : a.label;
var lB = (b.label) ? b.label.toLowerCase() : b.label;
return (lA === lB) ? 0 : (lA > lB) ? 1 : -1;
});
}
if (includeBlankValue) {
options.unshift({
label: ' ',
value: null,
selected: false
});
}
var input = registry.byId(inputId);
input.set('options', options);
input.set('disabled', false);
if (options.length > 0) {
options[0].selected = true;
input.set('value', 0);
}
}));
}));
},
getFieldCodedValues: function (layer, fieldName) {
var codedValues = null;
array.forEach(layer.fields, function (field) {
if (field.name === fieldName) {
var codedValueDomain = field.domain;
if (codedValueDomain && codedValueDomain.type === 'codedValue') {
codedValues = codedValueDomain.codedValues;
}
}
});
return codedValues;
},
getLayerJSON: function (url) {
var deferred = new Deferred();
var layerJSON = this.layerJSON;
if (layerJSON[url]) {
if (layerJSON[url].promise) {
return layerJSON[url].promise;
}
deferred.resolve(layerJSON[url]);
} else {
layerJSON[url] = deferred;
esriRequest({
url: url,
parameters: {
f: 'json'
},
content: {
f: 'json'
},
handleAs: 'json',
callbackParamName: 'callback'
}, {
disableIdentityLookup: false,
usePost: false,
useProxy: false
}).then(
lang.hitch(this, function (data) {
layerJSON[url] = data;
deferred.resolve(layerJSON[url]);
}),
lang.hitch(this, function () {
layerJSON[url] = {};
deferred.resolve(layerJSON[url]);
})
);
}
return deferred.promise;
},
getLayerURL: function (qp) {
var url = qp.url;
if (url && qp.sublayerID) {
var len = url.length;
if (url.substring(len - 1, len) === '/') {
url = url.substring(0, len - 1);
}
url += '/' + qp.sublayerID;
}
if (!url && qp.layerID) {
var layer = this.map.getLayer(qp.layerID);
if (layer) {
if (layer.declaredClass === 'esri.layers.FeatureLayer') { // Feature Layer
url = layer.url;
} else if (layer.declaredClass === 'esri.layers.ArcGISDynamicMapServiceLayer') { // Dynamic Layer
if (qp.sublayerID !== null) {
url = layer.url + '/' + qp.sublayerID;
} else if (layer.visibleLayers && layer.visibleLayers.length === 1) {
url = layer.url + '/' + layer.visibleLayers[0];
}
}
}
}
return url;
},
doAttributeSearch: function () {
if (this.enableAdvancedSearch && this.isAdvancedSearch) {
this.doAdvancedSearch();
} else {
this.search(null, this.attributeLayer);
}
},
doAdvancedSearch: function () {
var where = this.queryBuilder.toSQL();
if (!where) {
return;
}
this.search(null, this.attributeLayer, {
where: where.sql
});
},
initSpatialFilters: function () {
var type = this.selectAttributeSpatialFilter.get('value'),
geomOptions = [],
popup = this.map.infoWindow;
for (var key in this.spatialFilters) {
if (this.spatialFilters.hasOwnProperty(key)) {
if ((this.spatialFilters[key]) && (this.includeSpatialFilter(key, popup))) {
geomOptions.push({
value: key,
label: this.i18n.Labels.spatialFilters[key]
});
}
}
}
this.selectAttributeSpatialFilter.set('options', geomOptions);
this.selectGeometry = null;
if (geomOptions.length > 0) {
this.selectAttributeSpatialFilter.set('disabled', false);
this.selectAttributeSpatialFilter.set('value', type);
} else {
this.selectAttributeSpatialFilter.set('disabled', true);
}
},
includeSpatialFilter: function (key, popup) {
switch (key) {
case 'identifiedFeature':
if (popup && popup.isShowing) {
return true;
}
break;
case 'searchSource':
if (this.selectedTable && this.selectedTable.sourceGraphics.graphics.length > 0) {
return true;
}
break;
case 'searchFeatures':
if (this.selectedTable && this.selectedTable.featureGraphics.graphics.length > 0) {
return true;
}
break;
case 'searchSelected':
if (this.selectedTable && this.selectedTable.selectedGraphics.graphics.length > 0) {
return true;
}
break;
case 'searchBuffer':
if (this.selectedTable && this.selectedTable.bufferGraphics.graphics.length > 0) {
return true;
}
break;
default:
return true;
}
return false;
},
onSpatialBufferChange: function () {
this.addBufferGraphic();
},
/*******************************
* Advanced Search Functions
*******************************/
setAdvancedSearch: function (advanced) {
this.isAdvancedSearch = advanced;
domStyle.set(this.btnAdvancedSwitch.domNode, 'display', this.isAdvancedSearch ? 'none' : 'block');
domStyle.set(this.divBasicSearchBody, 'display', this.isAdvancedSearch ? 'none' : 'block');
domStyle.set(this.btnBasicSwitch.domNode, 'display', this.isAdvancedSearch ? 'block' : 'none');
domStyle.set(this.divAdvancedSearchBody, 'display', this.isAdvancedSearch ? 'block' : 'none');
},
toggleAdvancedSearch: function () {
this.setAdvancedSearch(!this.isAdvancedSearch);
},
checkAdvancedSearchEnabled: function (layer, search) {
var enabled = this.enableAdvancedSearch;
if (layer && layer.enableAdvancedSearch === false) {
enabled = false;
} else if (layer && layer.findOptions) {
enabled = false;
} else if (search && search.enableAdvancedSearch === false) {
enabled = false;
} else if (layer && search) {
var advancedSearchOptions = search.advancedSearchOptions || layer.advancedSearchOptions || {};
if (advancedSearchOptions.enabled === false) {
enabled = false;
}
}
if (enabled) {
this.showAdvancedSearch();
} else {
this.hideAdvancedSearch();
}
return enabled;
},
checkClearButtonEnabled: function (layer, search) {
var enabled = this.enableClearButton;
if (layer && layer.enableClearButton === false) {
enabled = false;
} else if (search && search.enableClearButton === false) {
enabled = false;
}
if (enabled) {
this.showClearButton();
} else {
this.hideClearButton();
}
return enabled;
},
showAdvancedSearch: function () {
if (this.enableAdvancedSearch) {
domStyle.set(this.divAdvancedSearchButtons, 'display', 'block');
}
},
hideAdvancedSearch: function () {
domStyle.set(this.divAdvancedSearchButtons, 'display', 'none');
this.setAdvancedSearch(false);
},
showClearButton: function () {
if (this.enableClearButton) {
domStyle.set(this.divExtraActions, 'display', 'inline-block');
}
},
hideClearButton: function () {
domStyle.set(this.divExtraActions, 'display', 'none');
},
doExportSQL: function () {
domAttr.set(this.sqlImportExportDialogTitle, 'textContent', this.i18n.Labels.exportDialogTitle);
this.sqlImportExportTextbox.set('disabled', true);
this.sqlImportExportTextbox.set('value', this.queryBuilder.toSQL().sql);
this.sqlImportExportDialog.show();
domStyle.set(this.searchAdvancedImportDialogBtn, 'display', 'none');
},
doShowImportSQLDialog: function () {
domAttr.set(this.sqlImportExportDialogTitle, 'textContent', this.i18n.Labels.importDialogTitle);
this.sqlImportExportTextbox.set('disabled', false);
this.sqlImportExportTextbox.set('value', '');
this.sqlImportExportDialog.show();
domStyle.set(this.searchAdvancedImportDialogBtn, 'display', 'block');
},
doImportSQL: function () {
this.queryBuilder.fromSQL(this.sqlImportExportTextbox.get('value'));
this.sqlImportExportDialog.hide();
},
/*******************************
* Drawing Functions
*******************************/
enableDrawingButtons: function () {
var opts = this.drawingOptions;
var disp = (opts.rectangle !== false) ? 'inline-block' : 'none';
domStyle.set(this.searchRectangleButtonDijit.domNode, 'display', disp);
disp = (opts.circle !== false) ? 'inline-block' : 'none';
domStyle.set(this.searchCircleButtonDijit.domNode, 'display', disp);
disp = (opts.point !== false) ? 'inline-block' : 'none';
domStyle.set(this.searchPointButtonDijit.domNode, 'display', disp);
disp = (opts.polyline !== false) ? 'inline-block' : 'none';
domStyle.set(this.searchPolylineButtonDijit.domNode, 'display', disp);
disp = (opts.freehandPolyline !== false) ? 'inline-block' : 'none';
domStyle.set(this.searchFreehandPolylineButtonDijit.domNode, 'display', disp);
disp = (opts.polygon !== false) ? 'inline-block' : 'none';
domStyle.set(this.searchPolygonButtonDijit.domNode, 'display', disp);
disp = (opts.freehandPolygon !== false) ? 'inline-block' : 'none';
domStyle.set(this.searchFreehandPolygonButtonDijit.domNode, 'display', disp);
disp = (opts.stopDrawing !== false) ? 'inline-block' : 'none';
domStyle.set(this.searchStopDrawingButtonDijit.domNode, 'display', disp);
disp = (opts.identifiedFeature !== false) ? 'inline-block' : 'none';
domStyle.set(this.searchIdentifyButtonDijit.domNode, 'display', disp);
disp = (opts.selectedFeatures !== false) ? 'inline-block' : 'none';
domStyle.set(this.searchSelectedButtonDijit.domNode, 'display', disp);
},
prepareForDrawing: function (btn) {
// is btn checked?
var chk = btn.get('checked');
this.cancelDrawing();
if (chk) {
// toggle btn to checked state
btn.set('checked', true);
}
return chk;
},
drawRectangle: function () {
var btn = this.searchRectangleButtonDijit;
if (this.prepareForDrawing(btn)) {
this.drawToolbar.activate(Draw.EXTENT);
}
},
drawCircle: function () {
var btn = this.searchCircleButtonDijit;
if (this.prepareForDrawing(btn)) {
this.drawToolbar.activate(Draw.CIRCLE);
}
},
drawPoint: function () {
var btn = this.searchPointButtonDijit;
if (this.prepareForDrawing(btn)) {
this.drawToolbar.activate(Draw.POINT);
}
},
drawPolyline: function () {
var btn = this.searchPolylineButtonDijit;
if (this.prepareForDrawing(btn)) {
this.drawToolbar.activate(Draw.POLYLINE);
}
},
drawFreehandPolyline: function () {
var btn = this.searchFreehandPolylineButtonDijit;
if (this.prepareForDrawing(btn)) {
this.drawToolbar.activate(Draw.FREEHAND_POLYLINE);
}
},
drawPolygon: function () {
var btn = this.searchPolygonButtonDijit;
if (this.prepareForDrawing(btn)) {
this.drawToolbar.activate(Draw.POLYGON);
}
},
drawFreehandPolygon: function () {
var btn = this.searchFreehandPolygonButtonDijit;
if (this.prepareForDrawing(btn)) {
this.drawToolbar.activate(Draw.FREEHAND_POLYGON);
}
},
uncheckDrawingTools: function () {
this.searchRectangleButtonDijit.set('checked', false);
this.searchCircleButtonDijit.set('checked', false);
this.searchPointButtonDijit.set('checked', false);
this.searchPolylineButtonDijit.set('checked', false);
this.searchFreehandPolylineButtonDijit.set('checked', false);
this.searchPolygonButtonDijit.set('checked', false);
this.searchFreehandPolygonButtonDijit.set('checked', false);
this.searchStopDrawingButtonDijit.set('checked', true);
this.searchStopDrawingButtonDijit.set('disabled', true);
this.btnSpatialSearch.set('disabled', true);
},
endDrawing: function (evt) {
var clickMode = this.mapClickMode,
geometry = null;
if (clickMode === 'search' && evt) {
geometry = evt.geometry;
}
if (geometry) {
if (this.spatialGeometry) {
this.spatialGeometry = geometryEngine.union(this.spatialGeometry, geometry);
} else {
this.spatialGeometry = geometry;
}
this.addDrawingGraphic(evt);
this.addBufferGraphic();
if (this.enableDrawMultipleShapes) {
this.btnSpatialSearch.set('disabled', false);
this.searchStopDrawingButtonDijit.set('disabled', false);
} else {
this.doSpatialSearch();
}
}
},
stopDrawing: function () {
this.cancelDrawing();
this.connectMapClick();
},
cancelDrawing: function () {
this.hideInfoWindow();
this.disconnectMapClick();
this.uncheckDrawingTools();
this.drawToolbar.deactivate();
this.spatialGeometry = null;
this.drawingGraphicsLayer.clear();
this.bufferGraphic = null;
},
doSpatialSearch: function () {
this.uncheckDrawingTools();
this.map.enableMapNavigation();
this.drawToolbar.deactivate();
this.drawingGraphicsLayer.clear();
this.bufferGraphic = null;
this.connectMapClick();
if (this.spatialGeometry) {
this.search(this.spatialGeometry, this.shapeLayer);
this.spatialGeometry = null;
}
},
addGraphicsLayer: function () {
this.drawingGraphicsLayer = new GraphicsLayer({
id: this.topicID + '_SourceGraphics',
title: 'Search Drawing Graphics'
});
this.map.addLayer(this.drawingGraphicsLayer);
// symbology for drawn features
var symbolOptions = this.drawingOptions.symbols || {};
var symbols = this.mixinDeep(lang.clone(this.defaultSymbols), symbolOptions);
this.drawingPointSymbol = new SimpleMarkerSymbol(symbols.point);
this.drawingPolylineSymbol = new SimpleLineSymbol(symbols.polyline);
this.drawingPolygonSymbol = new SimpleFillSymbol(symbols.polygon);
this.bufferPolygonSymbol = new SimpleFillSymbol(symbols.buffer);
},
addDrawingGraphic: function (feature) {
var symbol = null,
graphic = null;
switch (feature.geometry.type) {
case 'point':
case 'multipoint':
symbol = this.drawingPointSymbol;
break;
case 'polyline':
symbol = this.drawingPolylineSymbol;
break;
case 'extent':
case 'polygon':
symbol = this.drawingPolygonSymbol;
break;
default:
}
if (symbol) {
graphic = new Graphic(feature.geometry, symbol, feature.attributes);
this.drawingGraphicsLayer.add(graphic);
}
},
addBufferGraphic: function () {
var geometry = null,
distance = this.inputBufferDistance.get('value'),
unit = this.selectBufferUnits.get('value');
this.drawingGraphicsLayer.remove(this.bufferGraphic);
this.bufferGraphic = null;
if (isNaN(distance) || distance === 0 || !this.spatialGeometry) {
return;
}
if (this.map.spatialReference.wkid === 4326 || this.map.spatialReference.wkid === 102100) {
geometry = geometryEngine.geodesicBuffer(this.spatialGeometry, distance, unit);
if (geometry) {
this.bufferGraphic = new Graphic(geometry, this.bufferPolygonSymbol);
this.drawingGraphicsLayer.add(this.bufferGraphic);
}
}
},
/*******************************
* Using Identify Functions
*******************************/
useIdentifiedFeatures: function () {
var geometry = this.getGeometryFromIdentifiedFeature();
if (geometry) {
this.search(geometry, this.shapeLayer);
return;
}
topic.publish('growler/growl', {
title: 'Search',
message: 'You must have identified a feature',
level: 'error',
timeout: 3000
});
},
enableIdentifyButton: function () {
this.searchIdentifyButtonDijit.set('disabled', false);
this.initSpatialFilters();
},
disableIdentifyButton: function () {
this.searchIdentifyButtonDijit.set('disabled', true);
this.initSpatialFilters();
},
/*******************************
* Using Selected Functions
*******************************/
useSelectedFeatures: function () {
var geometry = this.getGeometryFromSelectedFeatures();
if (geometry) {
this.search(geometry, this.shapeLayer);
return;
}
topic.publish('growler/growl', {
title: 'Search',
message: 'You must have selected feature(s)',
level: 'error',
timeout: 3000
});
},
toggleSelectedButton: function () {
var geometry = this.getGeometryFromSelectedFeatures();
if (geometry) {
this.enableSelectedButton();
} else {
this.disableSelectedButton();
}
},
enableSelectedButton: function () {
this.searchSelectedButtonDijit.set('disabled', false);
},
disableSelectedButton: function () {
this.searchSelectedButtonDijit.set('disabled', true);
},
/*******************************
* Miscellaneous Functions
*******************************/
resize: function (options) {
if (options) {
if (options.h) {
domGeom.setContentSize(this.containerNode, {
h: (options.h - 2)
});
}
if (this.parentWidget && options.action === 'undock') {
var dim = domGeom.getContentBox(this.parentWidget.containerNode);
var minSize = this.parentWidget.resizeOptions.minSize;
if (minSize) {
if (minSize.w && minSize.w > dim.w) {
domGeom.setContentSize(this.parentWidget.domNode, {
w: (minSize.w)
});
}
}
}
}
this.tabContainer.resize();
},
geometryToJson: function (geom) {
if (geom && geom.type && geom.toJson) {
var type = geom.type;
geom = geom.toJson();
geom.type = type;
}
return geom;
},
hideInfoWindow: function () {
if (this.map && this.map.infoWindow) {
this.map.infoWindow.hide();
}
},
disconnectMapClick: function () {
topic.publish('mapClickMode/setCurrent', 'search');
},
connectMapClick: function () {
topic.publish('mapClickMode/setDefault');
},
setMapClickMode: function (mode) {
this.mapClickMode = mode;
},
onLayoutChange: function (open) {
if (!open && this.mapClickMode === 'search') {
this.connectMapClick();
this.drawToolbar.deactivate();
this.inherited(arguments);
}
},
setSearchTable: function (searchTable) {
this.selectedTable = searchTable;
this.initSpatialFilters();
this.toggleSelectedButton();
},
mixinDeep: function (dest, source) {
//Recursively mix the properties of two objects
var empty = {};
for (var name in source) {
if (!(name in dest) || (dest[name] !== source[name] && (!(name in empty) || empty[name] !== source[name]))) {
try {
if (source[name].constructor === Object) {
dest[name] = this.mixinDeep(dest[name], source[name]);
} else {
dest[name] = source[name];
}
} catch (e) {
// Property in destination object not set. Create it and set its value.
dest[name] = source[name];
}
}
}
return dest;
}
});
});