AutoComplete EsriJS search widget
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define([ | |
'dojo/_base/declare', | |
'dojo/_base/lang', | |
'dojo/Deferred', | |
'esri/tasks/locator' | |
], function( | |
declare, lang, | |
Deferred, | |
Locator | |
) { | |
'use strict'; | |
function asAddress(params, val) { | |
var address | |
, options; | |
address = { | |
'SingleLine': val | |
}; | |
options = { | |
address: address, | |
outFields: params.outFields | |
}; | |
return options; | |
} | |
return declare(null, { | |
constructor: function(options, spatialReference) { | |
this.options = options || {}; | |
this.params = options.params; | |
this.spatialReference = spatialReference; | |
this.url = this.options.url; | |
this.task = new Locator(this.url); | |
this.task.outSpatialReference = this.spatialReference; | |
}, | |
execute: function(val) { | |
if (val.length < 5) { | |
var deferred = new Deferred(); | |
setTimeout(function() { | |
deferred.resolve([]); | |
}, 100); | |
return deferred.promise; | |
} else { | |
return this.task.addressToLocations(asAddress(this.params, val)); | |
} | |
} | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define([ | |
'dojo/_base/declare', | |
'dojo/_base/lang', | |
'dojo/_base/array', | |
'dojo/dom', | |
'dojo/dom-construct', | |
'dojo/dom-attr', | |
'dojo/dom-class', | |
'dojo/on', | |
'dojo/topic', | |
'dojo/query', | |
'dojo/Evented', | |
// Dijit stuff | |
'dijit/_WidgetBase', | |
'dijit/_TemplatedMixin', | |
'dijit/a11yclick', | |
'esri/graphicsUtils', | |
'utils/symbolutil', | |
// widget tools | |
'widgets/agssearch/services/searchservice', | |
// template | |
'text!widgets/agssearch/templates/agssearch.tpl.html' | |
], function( | |
declare, lang, arrayUtil, | |
dom, domConstruct, domAttr, domClass, | |
on, topic, query, | |
Evented, | |
_WidgetBase, _TemplatedMixin, a11yclick, | |
graphicsUtils, | |
symbolUtil, | |
SearchService, | |
template | |
) { | |
'use strict'; | |
function stopEvent(e) { | |
e.preventDefault(); | |
} | |
function val(t, name) { | |
return t[name]; | |
} | |
function domval(name) { | |
return val(dom.byId(name), 'value'); | |
} | |
function head(t) { | |
if (t && lang.isArray(t)) { | |
return t[0]; | |
} else { | |
return {}; | |
} | |
} | |
return declare([_WidgetBase, _TemplatedMixin, Evented], { | |
templateString: template, | |
// lifecycle 1 | |
constructor: function() { | |
this.searchCount = 0; | |
this.loaded = false; | |
this.findPlaceHolder = 'Find...'; | |
}, | |
// start widget | |
startup: function() { | |
this._init(); | |
}, | |
postCreate: function() { | |
this._findService = new SearchService({ | |
map: this.get('map'), | |
settings: this.get('settings') | |
}); | |
this.own( | |
on(dom.byId('searchForm'), 'submit', stopEvent), | |
on(dom.byId('searchForm'), 'keyup', lang.hitch(this, '_find')), | |
on(dom.byId('find-clear'), a11yclick, lang.hitch(this, '_clearSearch')), | |
on( | |
document.body, | |
'.find-result:click', | |
lang.hitch(this, '_itemClicked') | |
) | |
); | |
}, | |
_itemClicked: function(e) { | |
var term | |
, value | |
, cache | |
, found | |
, fieldName; | |
term = domAttr.get(e.target, 'data-term'); | |
value = domAttr.get(e.target, 'data-lookup'); | |
cache = head(this._findService.store.query({ | |
term: term | |
})); | |
fieldName = this.get('searchField'); | |
dom.byId('find-input').value = value; | |
this._clear(); | |
found = head(arrayUtil.filter(cache.results, function(item) { | |
if (item.value && item.value === value) { | |
return item.value === value; | |
} | |
if (item.feature.attributes[fieldName] === value) { | |
return item.feature.attributes[fieldName] === value; | |
} | |
return false; | |
})); | |
if (found && found.feature && found.feature.geometry) { | |
this.map.graphics.clear(); | |
if (!found.feature.symbol) { | |
if (found.feature.geometry.type === 'polygon') { | |
found.feature.setSymbol(symbolUtil.selectedPolygonSymbol()); | |
} else if (found.feature.geometry.type === 'point') { | |
found.feature.setSymbol(symbolUtil.locationMarker()); | |
} | |
} | |
this.map.graphics.add(found.feature); | |
if (found.feature.geometry.type !== 'point') { | |
this.map.setExtent(graphicsUtils.graphicsExtent([found.feature])); | |
} else { | |
this.map.centerAndZoom( | |
found.feature.geometry, | |
this.map._params.lods.length - 2 | |
); | |
} | |
} | |
}, | |
// widget methods | |
_updateList: function(response) { | |
var list | |
, elems | |
, fieldName; | |
list = dom.byId('resultsList'); | |
fieldName = this.get('searchField'); | |
this._clear(); | |
elems = arrayUtil.map(response.results, function(item) { | |
if (item.value) { | |
return [ | |
'<li value="', | |
item.value, | |
'"', | |
' data-lookup="', | |
item.value, | |
'"', | |
' data-term="', | |
response.term, | |
'"', | |
' class="find-result">', | |
item.foundFieldName ? | |
[item.foundFieldName, ' - ', item.value].join('') : item.value, | |
'</li>' | |
].join(''); | |
} else { | |
return [ | |
'<li value="', | |
item.feature.attributes[fieldName], | |
'"', | |
' data-term="', | |
response.term, | |
'"', | |
' class="find-result">', | |
item.feature.attributes[fieldName], | |
'</li>' | |
].join(''); | |
} | |
}); | |
list.innerHTML = elems.join(''); | |
domClass.remove(dom.byId('findResults'), 'hidden'); | |
if (!--this.searchCount) { | |
domClass.remove(dom.byId('find-input'), 'ags-searching'); | |
this.emit('search-complete', {}); | |
} | |
}, | |
_clear: function() { | |
domClass.add(dom.byId('findResults'), 'hidden'); | |
domClass.remove(dom.byId('find-input'), 'ags-searching'); | |
domConstruct.empty(dom.byId('resultsList')); | |
}, | |
_clearSearch: function() { | |
this._clear(); | |
dom.byId('find-input').value = ''; | |
this.map.graphics.clear(); | |
}, | |
_find: function() { | |
this.search(domval('find-input')); | |
}, | |
search: function(term) { | |
if (term.length > 2) { | |
this.searchCount++; | |
domClass.add(dom.byId('find-input'), 'ags-searching'); | |
this.emit('search-start', {}); | |
this._findService.search(term).then( | |
lang.hitch(this, '_updateList'), | |
lang.hitch(this, function() { this.searchCount--; }) | |
); | |
} else { | |
this._clear(); | |
} | |
}, | |
// private functions | |
_init: function() { | |
this.set('loaded', true); | |
} | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@searching: #FFFF00; | |
#findDiv { | |
position: absolute; | |
top: 10px; | |
right: 10px; | |
z-index: 50; | |
} | |
#searchForm { | |
float: left; | |
height: 30px; | |
margin-left: 10px; | |
margin-right: 15px; | |
width: 250px; | |
input { | |
float: right; | |
height: 30px !important; | |
} | |
} | |
#find-clear { | |
float: right; | |
margin-top: 5px; | |
cursor: pointer; | |
} | |
.ags-searching { | |
background-color: @searching; | |
} | |
#findResults { | |
padding: 2px; | |
margin-top: 32px; | |
background-color: #fff; | |
color: #000; | |
li { | |
list-style-type: none; | |
padding: 5px; | |
cursor: pointer; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="findDiv"> | |
<form id="searchForm" role="form"> | |
<input id="find-input" class="form-control" | |
placeholder="${findPlaceHolder}" | |
title="${findPlaceHolder}" | |
type="text" value=""> | |
<div id="findResults" class="hidden"> | |
<ul id="resultsList"></ul> | |
</div> | |
</form> | |
<span id="find-clear" class="glyphicon glyphicon-remove"></span> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define([], { | |
return { | |
"name": "agssearch", | |
"path": "widgets/agssearch/agssearch", | |
"node": "findDiv", | |
"nodeVisible": true, | |
"options": { | |
"searchField": "AIN", | |
"settings": { | |
"searchparams": [{ | |
"url": "<MAPSERVER URL>", | |
"type": "query", | |
"searchField": "AIN", | |
"params": { | |
"returnGeometry": true, | |
"outFields": [ "OBJECTID", "AIN" ] | |
} | |
}, { | |
"url": "<MAPSERVER URL>", | |
"type": "find", | |
"params": { | |
"layerIds": [0], | |
"returnGeometry": true, | |
"searchFields": ["ID", "LOC_ID", "LOCATION"], | |
"outFields": [ "ID", "LOC_ID", "LOCATION" ] | |
} | |
}, { | |
"url": "<LOCATOR SERVICE URL>", | |
"type": "address", | |
"params": { | |
"outFields": [ "Loc_name" ] | |
} | |
}] | |
} | |
} | |
}; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define([ | |
'dojo/_base/declare', | |
'dojo/_base/lang', | |
'esri/tasks/FindTask', | |
'esri/tasks/FindParameters' | |
], function( | |
declare, lang, | |
FindTask, FindParameters | |
) { | |
'use strict'; | |
function paramsGen(params) { | |
return lang.mixin(new FindParameters(), params); | |
} | |
function withSearch(params, val) { | |
params.searchText = val; | |
return params; | |
} | |
return declare([], { | |
constructor: function(options) { | |
this.options = options || {}; | |
this.url = this.options.url; | |
this.task = new FindTask(this.url); | |
this.params = paramsGen(options.params); | |
}, | |
execute: function(val) { | |
return this.task.execute(withSearch(this.params, val)); | |
} | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define([ | |
'dojo/_base/declare', | |
'dojo/_base/lang', | |
'esri/tasks/QueryTask', | |
'esri/tasks/query' | |
], function( | |
declare, lang, | |
QueryTask, Query | |
) { | |
'use strict'; | |
function paramsGen(params) { | |
return lang.mixin(new Query(), params); | |
} | |
return declare(null, { | |
constructor: function(options) { | |
this.options = options || {}; | |
this.url = this.options.url; | |
this.task = new QueryTask(this.url); | |
this.params = paramsGen(options.params); | |
}, | |
execute: function(val) { | |
this.params.where = [ | |
this.options.searchField, | |
" LIKE '%", | |
val, | |
"%'" | |
].join(''); | |
return this.task.execute(this.params); | |
} | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define([ | |
'dojo/_base/declare', | |
'dojo/_base/lang', | |
'dojo/_base/array', | |
'dojo/Deferred', | |
'dojo/promise/all', | |
'dojo/store/Memory', | |
'esri/graphic', | |
'./findservice', | |
'./queryservice', | |
'./addressservice' | |
], function( | |
declare, lang, arrayUtil, | |
Deferred, all, | |
Memory, | |
Graphic, | |
FindService, QueryService, AddressService | |
) { | |
'use strict'; | |
function head(t) { | |
return t[0]; | |
} | |
function concat(arr1, arr2) { | |
return [].concat(arr1, arr2); | |
} | |
function top(arr, num) { | |
return arr.slice(0, num); | |
} | |
function assign(items) { | |
return arrayUtil.map(items, function(item) { | |
return { | |
feature: item | |
}; | |
}); | |
} | |
function isAddress(item) { | |
return !!item.address; | |
} | |
function transform(item) { | |
return { | |
feature: new Graphic(item.location, null, item.attributes), | |
value: item.address | |
}; | |
} | |
function filterAddressesByScore(arr, score) { | |
return arrayUtil.filter(arr, function(address) { | |
return address.score > score; | |
}); | |
} | |
function validateArray(arr) { | |
if (head(arr) && isAddress(head(arr))) { | |
return arrayUtil.map(top(filterAddressesByScore(arr, 75), 10), transform); | |
} else { | |
return arr; | |
} | |
} | |
function cleanResults(results) { | |
var clean = []; | |
arrayUtil.forEach(results, function(res) { | |
if (lang.isArray(res)) { | |
clean = concat(clean, validateArray(res)); | |
} else { | |
clean.push(res); | |
} | |
}); | |
return clean; | |
} | |
function clean(results) { | |
var features = []; | |
arrayUtil.forEach(cleanResults(results), function(result) { | |
if (result.features) { | |
features = concat(features, assign(top(result.features, 10))); | |
} else { | |
features.push(result); | |
} | |
}); | |
return features; | |
} | |
return declare(null, { | |
options: {}, | |
constructor: function(options) { | |
var sr; | |
this.options = options || {}; | |
this.store = new Memory({ | |
data: [], | |
idProperty: 'term' | |
}); | |
this.tasks = []; | |
sr = this.options.map.spatialReference; | |
if (this.options.settings.searchparams) { | |
var sparams = this.options.settings.searchparams; | |
this.tasks = arrayUtil.map(sparams, function(param) { | |
if (param.type === 'query') { | |
return new QueryService(param); | |
} else if (param.type === 'find') { | |
return new FindService(param); | |
} else if (param.type === 'address') { | |
return new AddressService(param, sr); | |
} | |
}, this); | |
} | |
}, | |
search: function(term) { | |
var def, promises, cache; | |
def = new Deferred(); | |
cache = this.store.get(term); | |
if (cache) { | |
def.resolve({ | |
results: cache.results, | |
term: term | |
}); | |
} else { | |
promises = arrayUtil.map(this.tasks, function(task) { | |
return task.execute(term); | |
}); | |
all(promises).then(lang.hitch(this, function(results) { | |
var res = clean(results); | |
this.store.add({ | |
term: term, | |
results: res | |
}); | |
def.resolve({ | |
results: res, | |
term: term | |
}); | |
})); | |
} | |
return def.promise; | |
} | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment