SearchViewModel.js 18 KB

12345
  1. /*
  2. All material copyright ESRI, All Rights Reserved, unless otherwise specified.
  3. See https://js.arcgis.com/4.25/esri/copyright.txt for details.
  4. */
  5. import{_ as e}from"../../chunks/tslib.es6.js";import{getAssetUrl as t}from"../../assets.js";import r from"../../config.js";import s from"../../Graphic.js";import o from"../../PopupTemplate.js";import"../../symbols.js";import i from"../../core/Accessor.js";import l from"../../core/Collection.js";import a from"../../core/Error.js";import n from"../../core/Evented.js";import u from"../../core/Handles.js";import c from"../../core/Logger.js";import{unwrap as h,isSome as p,isNone as g}from"../../core/maybe.js";import{eachAlways as d,after as m}from"../../core/promiseUtils.js";import{watch as y,whenOnce as f,initial as S}from"../../core/reactiveUtils.js";import{property as _}from"../../core/accessorSupport/decorators/property.js";import"../../core/arrayUtils.js";import"../../core/accessorSupport/ensureType.js";import{subclass as v}from"../../core/accessorSupport/decorators/subclass.js";import w from"../../geometry/Point.js";import b from"../../geometry/SpatialReference.js";import{onLocaleChange as x}from"../../intl/locale.js";import{fetchMessageBundle as I}from"../../intl/messages.js";import L from"../../portal/Portal.js";import{highlightsSupported as T}from"../../views/support/layerViewUtils.js";import R from"./LayerSearchSource.js";import j from"./LocatorSearchSource.js";import E from"./SearchSource.js";import{getPointFromGeometry as P,getPointWithElevation as F}from"./support/geometryUtils.js";import{isArcGISWorldGeocoder as C,meteredArcGISLocatorUrl as G,isProxiedArcGISWorldGeocoder as O,isMeteredArcGISWorldGeocoder as A}from"./support/locatorUtils.js";import{supported as N,getCurrentPosition as D,positionToPoint as M}from"../support/geolocationUtils.js";import{GoToMixin as V}from"../support/GoTo.js";import k from"../../symbols/PictureMarkerSymbol.js";import B from"../../symbols/SimpleLineSymbol.js";import J from"../../symbols/SimpleFillSymbol.js";import U from"../../symbols/TextSymbol.js";function H(e,t){return e.hasOwnProperty(t)&&null!=e[t]&&""!==e[t]}const Q=()=>I("esri/widgets/Search/t9n/Search"),Z="esri.widgets.Search.SearchViewModel",q=c.getLogger(Z),z="highlight",K=l.ofType({key:e=>e.layer?"layer":"locator",base:E,typeMap:{layer:R,locator:j}}),W=b.WGS84,X="esri/images/search/search-symbol-32.png",Y=/<(?:.|\s)*?>/g,$=-1;let ee=class extends(V(n.EventedMixin(i))){constructor(e){super(e),this._handles=new u,this._gotoController=null,this._searching=null,this._createdFeatureLayers=[],this.autoNavigate=!0,this.autoSelect=!0,this.defaultPopupTemplate=null,this.defaultSources=new K,this.defaultSymbols={point:new k({url:t(X),size:24,width:24,height:24}),polyline:new B({color:[130,130,130,1],width:2}),polygon:new J({color:[235,235,235,.4],outline:{color:[130,130,130,1],width:2}})},this.includeDefaultSources=!0,this.maxInputLength=128,this.maxResults=6,this.maxSuggestions=6,this.messages=null,this.minSuggestCharacters=3,this.popupEnabled=!0,this.popupTemplate=null,this.portal=L.getDefault(),this.resultCount=null,this.resultGraphicEnabled=!0,this.resultGraphic=null,this.results=null,this.selectedSuggestion=null,this.searchAllEnabled=!0,this.selectedResult=null,this.sources=new K,this.suggestionDelay=350,this.suggestionCount=null,this.suggestions=null,this.suggestionsEnabled=!0,this.view=null}initialize(){const e=async()=>{const e=await Q();this.messages=e,this.defaultPopupTemplate=new o({title:e.searchResult,content:"{Match_addr}"})};e(),this._handles.add([y((()=>[this.includeDefaultSources,this.view,this.portal]),(()=>this._update()),S),x(e)])}destroy(){this._destroyFeatureLayers(),this._abortGoTo(),this.clearGraphics(),this._handles.destroy(),this._handles=null}get activeSource(){return this.allSources.at(this.activeSourceIndex)??null}get activeSourceIndex(){return 1===this.allSources.length||!this.searchAllEnabled?0:$}set activeSourceIndex(e){this._overrideIfSome("activeSourceIndex",e)}get allPlaceholder(){return this.messages?.allPlaceholder}set allPlaceholder(e){this._overrideIfSome("allPlaceholder",e)}get allSources(){const{sources:e,defaultSources:t,includeDefaultSources:r}=this,s="function"==typeof r?r.call(null,{sources:e,defaultSources:t}):r?t.concat(e):e,o=this._get("allSources")||new K;return o.removeAll(),o.addMany(s.filter(Boolean)),o}get locationEnabled(){return this._get("locationEnabled")||N()}set locationEnabled(e){if(void 0===e)return void this._clearOverride("locationEnabled");const t=N();if(e&&!t){const e=new a("locationEnabled:geolocation-unsupported","Geolocation API is unsupported.",{geolocation:navigator.geolocation});q.error(e)}this._override("locationEnabled",!!e&&t)}get placeholder(){const{allSources:e,activeSourceIndex:t,allPlaceholder:r}=this;if(t===$)return r;const s=e.at(t);return s?s.placeholder:""}set searchTerm(e){this._set("searchTerm",e||""),this.clearGraphics(),this.selectedSuggestion&&this.selectedSuggestion.text!==e&&this._set("selectedSuggestion",null),""===e&&this._clear()}get searchTerm(){return this._get("searchTerm")||""}get state(){return this._searching?"searching":this.updating?"loading":0===this.allSources.length?"disabled":"ready"}get updating(){return null!=this._updatingPromise}clear(){this.searchTerm=""}clearGraphics(){this._removeHighlight(),this._closePopup(),this.view&&this.view.graphics.remove(this.resultGraphic),this._set("resultGraphic",null)}search(e,t){this.emit("search-start"),this.clearGraphics();const r=this._createSuggestionForSearch(e),s=this.when().then((()=>this._getResultsFromSources(r,t).then((e=>{if(h(t?.signal)?.aborted)return null;const s={activeSourceIndex:this.activeSourceIndex,searchTerm:r.text,numResults:0,numErrors:0,errors:[],results:[]};this._formatResponse(s,e,r);const o=this._getFirstResult(s.results),i=(r.location&&o?o.name:r.text).replace(Y,"");return this._set("searchTerm",i),(r.key&&"number"==typeof r.sourceIndex||r.location)&&this._set("selectedSuggestion",r),this._set("results",s.results),this._set("resultCount",s.results.reduce(((e,t)=>e+t.results.length),0)),this.emit("search-complete",s),this._selectFirstResult(o).then((()=>s))})))).then((e=>(this._clearSearching(),e)),(e=>{throw this._clearSearching(),e}));return this._searching=s,s}searchNearby(e){if(!this.locationEnabled){const e=new a("searchNearby:geolocation-unsupported","Geolocation API is unsupported.",{geolocation:navigator.geolocation});return q.error(e),Promise.reject(e)}const t=D().then((t=>M({position:t,view:this.view},e))).then((t=>this.search(t,e)));return this._searching=t,t.catch((()=>{})).then((()=>this._clearSearching())),t}select(e){if(this.clearGraphics(),!e){const t=new a("select:missing-parameter","Cannot select without a searchResult.",{searchResult:e});return q.error(t),Promise.reject(t)}const{view:t}=this,r=H(e,"sourceIndex")?e.sourceIndex:this._getSourceIndexOfResult(e),o=this.allSources.at(r);if(!o){const e=new a("select:missing-source","Cannot select without a source.",{source:o});return q.error(e),Promise.reject(e)}const i=o instanceof R?this._getLayerSourcePopupTemplate(o):o.popupTemplate,l=o.resultSymbol||this._getDefaultSymbol(e),n=H(o,"resultGraphicEnabled")?o.resultGraphicEnabled:this.resultGraphicEnabled,u=H(o,"autoNavigate")?o.autoNavigate:this.autoNavigate,c=H(o,"popupEnabled")?o.popupEnabled:this.popupEnabled,h=c?i||this.popupTemplate||this.defaultPopupTemplate:null,{feature:g}=e;if(!g){const e=new a("select:missing-feature","Cannot select without a feature.",{feature:g});return q.error(e),Promise.reject(e)}const{attributes:m,geometry:y,layer:f,sourceLayer:S}=g,_=P(y),v={layerViewQuery:this._getLayerView(g),elevationQuery:t&&p(_)?F(_,t).catch((()=>_)):Promise.resolve(_)};return d(v).then((i=>{const a=i.layerViewQuery.value,d=i.elevationQuery.value;l instanceof U&&(l.text=e.name);const _=t&&u?e.target||e.extent:null;return(p(_)?this._goToSearchResult(_):Promise.resolve()).then((()=>{const i=a?g:new s({geometry:y,symbol:l,attributes:m,layer:f,sourceLayer:S,popupTemplate:h}),u=c&&this.view?.popup,p=u&&i.getEffectivePopupTemplate(u.defaultPopupTemplateEnabled);return p&&t.popup.open({features:[i],location:d}),a&&T(a)&&!p&&this._highlightFeature({graphic:i,layerView:a}),!a&&n&&t&&t.graphics.push(i),this._setResultFloor(e),this._set("selectedResult",e),this._set("resultGraphic",i),this.emit("select-result",{result:e,source:o,sourceIndex:r}),e}))}))}suggest(e,t,r){const s=e||this.searchTerm;return this.emit("suggest-start",{searchTerm:s}),this._suggestTimer(t,r).then((()=>this._suggestImmediate(s,r).then((e=>(this._set("suggestions",e.results),this._set("suggestionCount",e.results.reduce(((e,t)=>e+t.results.length),0)),this.emit("suggest-complete",e),e)))))}async when(){await f((()=>!this.updating))}async _update(){const{portal:e,view:t}=this;if(this.includeDefaultSources){const r=this._updatingPromise=d([e?.load(),t?.when()]);if(this.destroyed)return;if(await r,r!==this._updatingPromise)return}await f((()=>this.messages)),this.destroyed||this._updateDefaultSources(),this._updatingPromise=null}_clearSearching(){this._searching=null}_convertHelperServices(){const e=this.portal?.helperServices?.geocode;if(!e)return[];return e.map((e=>{if(!1===e.placefinding)return;const t=r.apiKey&&C(e.url)?{url:G}:null,s=j.fromJSON({...e,...t}),o=s.url;if(C(o)||O(o)||A(o)){const e=s.outFields||["Addr_type","Match_addr","StAddr","City"],t=s.placeholder||this.messages.placeholder,r="number"==typeof s.defaultZoomScale?s.defaultZoomScale:2500;s.set({singleLineFieldName:"SingleLine",outFields:e,placeholder:t,defaultZoomScale:r})}return s.singleLineFieldName?s:void 0})).filter(Boolean)}_destroyFeatureLayers(){this._createdFeatureLayers.forEach((e=>e?.destroy())),this._createdFeatureLayers=[]}_getLayerSources(e,t){const r=this.view?.map;return e.map((e=>{const s=r.findLayerById(e.id);if(!s)return;const o=this._getLayerJSON(e),i=R.fromJSON(o);return i.placeholder=t,this._getLayer(s,o).then((e=>{i.layer=e})),i})).filter(Boolean).toArray()}_getTableSources(e,t){const r=this.view?.map;return e.map((e=>{const s=r.findTableById(e.id);if(!s)return;const o=this._getLayerJSON(e),i=R.fromJSON(o);return i.placeholder=t,this._getLayer(s,o).then((e=>{i.layer=e})),i})).filter(Boolean).toArray()}_convertApplicationProperties(){const e=this.view?.map,t=e?.applicationProperties?.viewing?.search;if(!t)return[];const{enabled:r,hintText:s,layers:o,tables:i}=t;if(!r)return[];return[...this._getLayerSources(o,s),...this._getTableSources(i,s)]}async _getSubLayer(e,t){if(await e.load(),!e.allSublayers)throw new Error;const r=e.allSublayers.find((e=>e.id===t.subLayer));if(!r)throw new Error;const s=await r.createFeatureLayer();return this._createdFeatureLayers.push(s),s}async _getBuildingSubLayer(e,t){await e.load();const r=e.allSublayers.find((e=>e.id===t.subLayer));if("building-component"!==r?.type)throw new Error;if(await r.load(),null==r.associatedLayer)throw new Error;return await r.associatedLayer.load(),r}_getLayer(e,t){return"feature"===e.type||"scene"===e.type||"csv"===e.type||"geojson"===e.type||"ogc-feature"===e.type?Promise.resolve(e):"map-image"===e.type?this._getSubLayer(e,t).catch((()=>{const t=new a("search:create-featurelayer","Could not create a FeatureLayer from the MapImageLayer",{layer:e});return q.error(t),null})):"building-scene"===e.type?this._getBuildingSubLayer(e,t):Promise.resolve(null)}_getLayerJSON(e){return"function"==typeof e.toJSON?e.toJSON():e}_updateDefaultSources(){const{defaultSources:e,includeDefaultSources:t}=this;this._destroyFeatureLayers(),e.removeAll(),t&&e.addMany([...this._convertApplicationProperties(),...this._convertHelperServices()])}_abortGoTo(){this._gotoController&&this._gotoController.abort(),this._gotoController=null}_clear(){this._abortGoTo(),this._set("resultCount",null),this._set("results",null),this._set("suggestions",null),this._set("suggestionCount",null),this._set("selectedResult",null),this._set("selectedSuggestion",null),this.emit("search-clear")}_closePopup(){const e=this.view?.popup,{resultGraphic:t}=this;if(!e||!t)return;const{selectedFeature:r}=e;r&&r===t&&e.close()}_suggestTimer(e,t){const r=null!=e?e:this.suggestionDelay;return m(r,null,t&&t.signal)}_createLocationForSearch(e){return e instanceof s?P(e.geometry):e instanceof w?e:Array.isArray(e)&&2===e.length?new w({longitude:e[0],latitude:e[1]}):null}_createSuggestionForSearch(e){if(e&&H(e,"key")&&H(e,"text")&&H(e,"sourceIndex"))return e;const t=this._createLocationForSearch(e),r="string"==typeof e?e:this.searchTerm,{selectedSuggestion:s,selectedResult:o}=this,i=!e&&s&&o,l=i&&s.key===o.key&&s.sourceIndex===o.sourceIndex,a=i&&s.location;return l||a?s:{location:h(t),text:t?"":r,sourceIndex:null,key:null}}_getFirstResult(e){let t=null;return e&&e.some((e=>{const{results:r}=e,s=r[0],o=!!s;return o&&(t=s),o})),t}_selectFirstResult(e){return this.autoSelect&&e?this.select(e):Promise.resolve(null)}_suggestImmediate(e,t){return this.when().then((()=>this._getSuggestionsFromSources(e,t))).then((r=>{if(h(t?.signal)?.aborted)return null;const s={activeSourceIndex:this.activeSourceIndex,searchTerm:e,numResults:0,numErrors:0,errors:[],results:[]};return this._formatResponse(s,r),s}))}_formatSourceResponse(e,t,r){const s=t&&t.value||[],o=t&&t.error,i=this.allSources.at(r);if(o){const t={sourceIndex:r,source:i,error:o};e.errors.push(t),q.error(o),e.numErrors++}else{const t={sourceIndex:r,source:i,results:s};e.results.push(t),e.numResults+=s.length}}_formatResponse(e,t,r){if(t)if(e.activeSourceIndex===$){const s=r&&H(r,"sourceIndex")&&-1!==r.sourceIndex?r.sourceIndex:void 0;t.forEach(((t,r)=>{const o=void 0!==s?s:r;this._formatSourceResponse(e,t,o)}))}else this._formatSourceResponse(e,t[0],e.activeSourceIndex)}_getResultsFromSources(e,t){const{allSources:r}=this,s=!e.location&&H(e,"sourceIndex")?e.sourceIndex:this.activeSourceIndex,o=[];if(!r.length){const e=new a("search:no-sources-defined","At least one source is required.",{allSources:r});return q.error(e),Promise.reject(e)}return s===$?r.forEach(((r,s)=>{o.push(this._getResultsFromSource(e,s,t))})):o.push(this._getResultsFromSource(e,s,t)),d(o)}_getSuggestionsFromSources(e,t){const{allSources:r,activeSourceIndex:s}=this,o=[];if(!r.length){const e=new a("suggest:no-sources-defined","At least one source is required.",{allSources:r});return q.error(e),Promise.reject(e)}return s===$?r.forEach(((r,s)=>{o.push(this._getSuggestionsFromSource(e,s,t))})):o.push(this._getSuggestionsFromSource(e,s,t)),d(o)}_getResultsFromSource(e,t,r){const s=this.allSources.at(t),{location:o=null}=e,i=this.view?.spatialReference||W,l=H(s,"maxResults")?s.maxResults:this.maxResults,a=!!(s instanceof R&&H(s,"exactMatch"))&&s.exactMatch,{view:n}=this;return s.getResults({view:n,sourceIndex:t,location:o,suggestResult:e,spatialReference:i,exactMatch:a,maxResults:l},r)}_getSuggestionsFromSource(e,t,r){const s=this.allSources.at(t),o=H(s,"suggestionsEnabled")?s.suggestionsEnabled:this.suggestionsEnabled,i=e.length,l=H(s,"minSuggestCharacters")?s.minSuggestCharacters:this.minSuggestCharacters;if(o&&e.trim()&&i>=l){const o=this.view?.spatialReference||W,i=H(s,"maxSuggestions")?s.maxSuggestions:this.maxSuggestions,{view:l}=this,a=!!(s instanceof R&&H(s,"exactMatch"))&&s.exactMatch;return s.getSuggestions({view:l,sourceIndex:t,suggestTerm:e,spatialReference:o,maxSuggestions:i,exactMatch:a},r)}return Promise.resolve(null)}_getLayerSourcePopupTemplate(e){const{layer:t}=e;if(t)return H(e,"popupTemplate")?e.popupTemplate:t.popupTemplate}_getSourceIndexOfResult(e){const t=this.results;let r=null;return t.some((t=>t.results.some((s=>s===e&&(r=t.sourceIndex,!0))))),r}async _goToSearchResult(e){const t=!!e;this._abortGoTo();const r=new AbortController;this._gotoController=r;const s={target:{target:e},options:{animate:t,signal:r.signal}};await this.callGoTo(s),this._gotoController=null}_getDefaultSymbol(e){const{defaultSymbols:t}=this,r=e.feature?.geometry;if(g(r))return null;switch(r.type){case"point":case"multipoint":return t.point;case"polyline":return t.polyline;case"extent":case"polygon":return t.polygon;default:return null}}_removeHighlight(){this._handles.remove(z)}async _getLayerView(e){const{view:t}=this;if(!e||!t||"building-component"===e.layer.type||"subtype-sublayer"===e.layer.type)return null;const{layer:r}=e;return await t.when(),t.whenLayerView(r)}_highlightFeature(e){const{graphic:t,layerView:r}=e,{attributes:s,layer:o}=t,{objectIdField:i}=o,l=s&&s[i],a=r.highlight(l||t);this._handles.add(a,z)}_setResultFloor(e){const{view:t}=this,r=e.feature?.attributes,s=e.feature?.sourceLayer;if(s&&"floorInfo"in s&&s?.floorInfo?.floorField&&r){const e=r[s.floorInfo.floorField];t?.emit("select-result-floor",e)}}};ee.ALL_INDEX=$,e([_()],ee.prototype,"_searching",void 0),e([_()],ee.prototype,"_updatingPromise",void 0),e([_({readOnly:!0,value:null})],ee.prototype,"activeSource",null),e([_()],ee.prototype,"activeSourceIndex",null),e([_()],ee.prototype,"allPlaceholder",null),e([_({readOnly:!0})],ee.prototype,"allSources",null),e([_()],ee.prototype,"autoNavigate",void 0),e([_()],ee.prototype,"autoSelect",void 0),e([_()],ee.prototype,"defaultPopupTemplate",void 0),e([_({readOnly:!0})],ee.prototype,"defaultSources",void 0),e([_()],ee.prototype,"defaultSymbols",void 0),e([_()],ee.prototype,"includeDefaultSources",void 0),e([_()],ee.prototype,"locationEnabled",null),e([_()],ee.prototype,"maxInputLength",void 0),e([_()],ee.prototype,"maxResults",void 0),e([_()],ee.prototype,"maxSuggestions",void 0),e([_()],ee.prototype,"messages",void 0),e([_()],ee.prototype,"minSuggestCharacters",void 0),e([_({readOnly:!0})],ee.prototype,"placeholder",null),e([_()],ee.prototype,"popupEnabled",void 0),e([_({type:o})],ee.prototype,"popupTemplate",void 0),e([_({type:L})],ee.prototype,"portal",void 0),e([_()],ee.prototype,"resultCount",void 0),e([_()],ee.prototype,"resultGraphicEnabled",void 0),e([_({readOnly:!0})],ee.prototype,"resultGraphic",void 0),e([_({readOnly:!0})],ee.prototype,"results",void 0),e([_({readOnly:!0})],ee.prototype,"selectedSuggestion",void 0),e([_()],ee.prototype,"searchAllEnabled",void 0),e([_({readOnly:!0})],ee.prototype,"selectedResult",void 0),e([_()],ee.prototype,"searchTerm",null),e([_({type:K})],ee.prototype,"sources",void 0),e([_({readOnly:!0})],ee.prototype,"state",null),e([_()],ee.prototype,"suggestionDelay",void 0),e([_()],ee.prototype,"suggestionCount",void 0),e([_({readOnly:!0})],ee.prototype,"suggestions",void 0),e([_()],ee.prototype,"suggestionsEnabled",void 0),e([_({readOnly:!0})],ee.prototype,"updating",null),e([_()],ee.prototype,"view",void 0),e([_()],ee.prototype,"clear",null),ee=e([v(Z)],ee);const te=ee;export{te as default};