From c0b9c777d9afce86b60fbc0b90030632eb822d7d Mon Sep 17 00:00:00 2001 From: hpinkos Date: Mon, 13 Aug 2018 17:07:54 -0400 Subject: [PATCH 1/4] Add optional custom geocoder command --- Source/Widgets/Geocoder/Geocoder.js | 8 +++ Source/Widgets/Geocoder/GeocoderViewModel.js | 26 ++++--- Specs/Widgets/Geocoder/GeocoderSpec.js | 54 ++------------- .../Widgets/Geocoder/GeocoderViewModelSpec.js | 68 +++++++++++++++---- 4 files changed, 87 insertions(+), 69 deletions(-) diff --git a/Source/Widgets/Geocoder/Geocoder.js b/Source/Widgets/Geocoder/Geocoder.js index 7926cf53b48..389316dfe03 100644 --- a/Source/Widgets/Geocoder/Geocoder.js +++ b/Source/Widgets/Geocoder/Geocoder.js @@ -34,6 +34,7 @@ define([ * @param {GeocoderService[]} [options.geocoderServices] The geocoder services to be used * @param {Boolean} [options.autoComplete = true] True if the geocoder should query as the user types to autocomplete * @param {Number} [options.flightDuration=1.5] The duration of the camera flight to an entered location, in seconds. + * @param {Geocoder~DestinationFoundFunction} [options.destinationFound] A callback function that is called after a successful geocode. If not supplied, the default behavior is to fly the camera to the result destination. */ function Geocoder(options) { //>>includeStart('debug', pragmas.debug); @@ -210,5 +211,12 @@ css: { active: $data === $parent._selectedSuggestion }'); return destroyObject(this); }; + /** + * A function that handles the result of a successful geocode. + * @callback Geocoder~DestinationFoundFunction + * @param {GeocoderViewModel} viewModel The view model. + * @param {Cartesian3|Rectangle} destination The destination result of the geocode. + */ + return Geocoder; }); diff --git a/Source/Widgets/Geocoder/GeocoderViewModel.js b/Source/Widgets/Geocoder/GeocoderViewModel.js index 344d83e9ded..27ffc4e6726 100644 --- a/Source/Widgets/Geocoder/GeocoderViewModel.js +++ b/Source/Widgets/Geocoder/GeocoderViewModel.js @@ -50,6 +50,7 @@ define([ * If more than one are supplied, suggestions will be gathered for the geocoders that support it, * and if no suggestion is selected the result from the first geocoder service wil be used. * @param {Number} [options.flightDuration] The duration of the camera flight to an entered location, in seconds. + * @param {Geocoder~DestinationFoundFunction} [options.destinationFound] A callback function that is called after a successful geocode. If not supplied, the default behavior is to fly the camera to the result destination. */ function GeocoderViewModel(options) { //>>includeStart('debug', pragmas.debug); @@ -77,9 +78,7 @@ define([ this._suggestions = []; this._selectedSuggestion = undefined; this._showSuggestions = true; - this._updateCamera = updateCamera; - this._adjustSuggestionsScroll = adjustSuggestionsScroll; - this._updateSearchSuggestions = updateSearchSuggestions; + this._handleArrowDown = handleArrowDown; this._handleArrowUp = handleArrowUp; @@ -140,7 +139,7 @@ define([ that._searchText = data.displayName; var destination = data.destination; clearSuggestions(that); - updateCamera(that, destination); + that.destinationFoundCommand(that, destination); }; this.hideSuggestions = function () { @@ -173,6 +172,12 @@ define([ */ this.autoComplete = defaultValue(options.autocomplete, true); + /** + * Gets and sets the command called when a geocode destination is found + * @type {Command} + */ + this.destinationFoundCommand = createCommand(defaultValue(options.destinationFound, GeocoderViewModel._updateCamera)); + this._focusTextbox = false; knockout.track(this, ['_searchText', '_isSearchInProgress', 'keepExpanded', '_suggestions', '_selectedSuggestion', '_showSuggestions', '_focusTextbox']); @@ -180,7 +185,7 @@ define([ var searchTextObservable = knockout.getObservable(this, '_searchText'); searchTextObservable.extend({ rateLimit: { timeout: 500 } }); this._suggestionSubscription = searchTextObservable.subscribe(function() { - updateSearchSuggestions(that); + GeocoderViewModel._updateSearchSuggestions(that); }); /** * Gets a value indicating whether a search is currently in progress. This property is observable. @@ -326,7 +331,7 @@ define([ } next = currentIndex - 1; viewModel._selectedSuggestion = viewModel._suggestions[next]; - adjustSuggestionsScroll(viewModel, next); + GeocoderViewModel._adjustSuggestionsScroll(viewModel, next); } function handleArrowDown(viewModel) { @@ -338,7 +343,7 @@ define([ var next = (currentIndex + 1) % numberOfSuggestions; viewModel._selectedSuggestion = viewModel._suggestions[next]; - adjustSuggestionsScroll(viewModel, next); + GeocoderViewModel._adjustSuggestionsScroll(viewModel, next); } function computeFlyToLocationForCartographic(cartographic, terrainProvider) { @@ -445,7 +450,7 @@ define([ var geocoderResults = result.value; if (result.state === 'fulfilled' && defined(geocoderResults) && geocoderResults.length > 0) { viewModel._searchText = geocoderResults[0].displayName; - updateCamera(viewModel, geocoderResults[0].destination); + viewModel.destinationFoundCommand(viewModel, geocoderResults[0].destination); return; } viewModel._searchText = query + ' (not found)'; @@ -521,5 +526,10 @@ define([ }); } + //exposed for testing + GeocoderViewModel._updateCamera = updateCamera; + GeocoderViewModel._updateSearchSuggestions = updateSearchSuggestions; + GeocoderViewModel._adjustSuggestionsScroll = adjustSuggestionsScroll; + return GeocoderViewModel; }); diff --git a/Specs/Widgets/Geocoder/GeocoderSpec.js b/Specs/Widgets/Geocoder/GeocoderSpec.js index ba723f2c2fa..7bb84695f7c 100644 --- a/Specs/Widgets/Geocoder/GeocoderSpec.js +++ b/Specs/Widgets/Geocoder/GeocoderSpec.js @@ -12,24 +12,6 @@ defineSuite([ var scene; - var mockDestination = new Cartesian3(1.0, 2.0, 3.0); - var geocoderResults = [{ - displayName: 'a', - destination: mockDestination - }, { - displayName: 'b', - destination: mockDestination - }, { - displayName: 'c', - destination: mockDestination - }]; - - var customGeocoderOptions = { - autoComplete : true, - geocode : function (input) { - return when.resolve(geocoderResults); - } - }; beforeEach(function() { scene = createScene(); }); @@ -40,16 +22,20 @@ defineSuite([ it('constructor sets expected properties', function() { var flightDuration = 1234; + var destinationFound = jasmine.createSpy(); var geocoder = new Geocoder({ container : document.body, scene : scene, - flightDuration : flightDuration + flightDuration : flightDuration, + destinationFound : destinationFound }); var viewModel = geocoder.viewModel; expect(viewModel.scene).toBe(scene); expect(viewModel.flightDuration).toBe(flightDuration); + viewModel.destinationFoundCommand(); + expect(destinationFound).toHaveBeenCalled(); geocoder.destroy(); }); @@ -96,34 +82,4 @@ defineSuite([ }); }).toThrowDeveloperError(); }); - - it('automatic suggestions can be navigated by arrow up/down keys', function() { - var container = document.createElement('div'); - container.id = 'testContainer'; - document.body.appendChild(container); - var geocoder = new Geocoder({ - container : 'testContainer', - scene : scene, - geocoderServices : [customGeocoderOptions] - }); - var viewModel = geocoder._viewModel; - viewModel._searchText = 'some_text'; - viewModel._updateSearchSuggestions(viewModel); - - expect(viewModel._selectedSuggestion).toEqual(undefined); - viewModel._handleArrowDown(viewModel); - expect(viewModel._selectedSuggestion.displayName).toEqual('a'); - viewModel._handleArrowDown(viewModel); - viewModel._handleArrowDown(viewModel); - expect(viewModel._selectedSuggestion.displayName).toEqual('c'); - viewModel._handleArrowDown(viewModel); - expect(viewModel._selectedSuggestion.displayName).toEqual('a'); - viewModel._handleArrowDown(viewModel); - viewModel._handleArrowUp(viewModel); - expect(viewModel._selectedSuggestion.displayName).toEqual('a'); - viewModel._handleArrowUp(viewModel); - expect(viewModel._selectedSuggestion).toBeUndefined(); - document.body.removeChild(container); - }); - }, 'WebGL'); diff --git a/Specs/Widgets/Geocoder/GeocoderViewModelSpec.js b/Specs/Widgets/Geocoder/GeocoderViewModelSpec.js index b49ec845cd9..7e84a505112 100644 --- a/Specs/Widgets/Geocoder/GeocoderViewModelSpec.js +++ b/Specs/Widgets/Geocoder/GeocoderViewModelSpec.js @@ -23,6 +23,9 @@ defineSuite([ }, { displayName: 'b', destination: mockDestination + }, { + displayName: 'c', + destination: mockDestination }]; var customGeocoderOptions = { autoComplete: true, @@ -158,8 +161,8 @@ defineSuite([ geocoderServices : [customGeocoderOptions] }); geocoder._searchText = 'some_text'; - geocoder._updateSearchSuggestions(geocoder); - expect(geocoder._suggestions.length).toEqual(2); + GeocoderViewModel._updateSearchSuggestions(geocoder); + expect(geocoder._suggestions.length).toEqual(3); }); it('update search suggestions results in empty list if the query is empty', function() { @@ -168,35 +171,38 @@ defineSuite([ geocoderServices : [customGeocoderOptions] }); geocoder._searchText = ''; - spyOn(geocoder, '_adjustSuggestionsScroll'); - geocoder._updateSearchSuggestions(geocoder); + + GeocoderViewModel._updateSearchSuggestions(geocoder); expect(geocoder._suggestions.length).toEqual(0); }); it('can activate selected search suggestion', function () { + spyOn(GeocoderViewModel, '_updateCamera'); + var destination = new Rectangle(0.0, -0.1, 0.1, 0.1); var geocoder = new GeocoderViewModel({ scene : scene, geocoderServices : [customGeocoderOptions] }); - spyOn(geocoder, '_updateCamera'); - spyOn(geocoder, '_adjustSuggestionsScroll'); - var suggestion = { displayName: 'a', destination: new Rectangle(0.0, -0.1, 0.1, 0.1) }; + var suggestion = { displayName: 'a', destination: destination }; geocoder._selectedSuggestion = suggestion; geocoder.activateSuggestion(suggestion); expect(geocoder._searchText).toEqual('a'); + expect(GeocoderViewModel._updateCamera).toHaveBeenCalledWith(geocoder, destination); }); it('if more than one geocoder service is provided, use first result from first geocode in array order', function () { + spyOn(GeocoderViewModel, '_updateCamera'); + var geocoder = new GeocoderViewModel({ scene : scene, geocoderServices : [noResultsGeocoder, customGeocoderOptions2] }); geocoder._searchText = 'sthsnth'; // an empty query will prevent geocoding - spyOn(geocoder, '_updateCamera'); - spyOn(geocoder, '_adjustSuggestionsScroll'); + geocoder.search(); expect(geocoder._searchText).toEqual(geocoderResults2[0].displayName); + expect(GeocoderViewModel._updateCamera).toHaveBeenCalledWith(geocoder, mockDestination); }); it('can update autoComplete suggestions list using multiple geocoders', function () { @@ -205,10 +211,48 @@ defineSuite([ geocoderServices : [customGeocoderOptions, customGeocoderOptions2] }); geocoder._searchText = 'sthsnth'; // an empty query will prevent geocoding - spyOn(geocoder, '_updateCamera'); - spyOn(geocoder, '_adjustSuggestionsScroll'); - geocoder._updateSearchSuggestions(geocoder); + GeocoderViewModel._updateSearchSuggestions(geocoder); expect(geocoder._suggestions.length).toEqual(geocoderResults1.length + geocoderResults2.length); }); + it('uses custom destination found callback', function () { + spyOn(GeocoderViewModel, '_updateCamera'); + + var destinationFound = jasmine.createSpy(); + var geocoder = new GeocoderViewModel({ + scene : scene, + geocoderServices : [noResultsGeocoder, customGeocoderOptions2], + destinationFound: destinationFound + }); + geocoder._searchText = 'sthsnth'; // an empty query will prevent geocoding + geocoder.search(); + + expect(geocoder._searchText).toEqual(geocoderResults2[0].displayName); + expect(GeocoderViewModel._updateCamera).not.toHaveBeenCalled(); + expect(destinationFound).toHaveBeenCalledWith(geocoder, mockDestination); + }); + + it('automatic suggestions can be navigated by arrow up/down keys', function() { + spyOn(GeocoderViewModel, '_adjustSuggestionsScroll'); + var viewModel = new GeocoderViewModel({ + scene : scene, + geocoderServices : [customGeocoderOptions] + }); + viewModel._searchText = 'some_text'; + GeocoderViewModel._updateSearchSuggestions(viewModel); + + expect(viewModel._selectedSuggestion).toEqual(undefined); + viewModel._handleArrowDown(viewModel); + expect(viewModel._selectedSuggestion.displayName).toEqual('a'); + viewModel._handleArrowDown(viewModel); + viewModel._handleArrowDown(viewModel); + expect(viewModel._selectedSuggestion.displayName).toEqual('c'); + viewModel._handleArrowDown(viewModel); + expect(viewModel._selectedSuggestion.displayName).toEqual('a'); + viewModel._handleArrowDown(viewModel); + viewModel._handleArrowUp(viewModel); + expect(viewModel._selectedSuggestion.displayName).toEqual('a'); + viewModel._handleArrowUp(viewModel); + expect(viewModel._selectedSuggestion).toBeUndefined(); + }); }, 'WebGL'); From 386023433ddb1879cef4ef1eb89e0a7759d4be4b Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 14 Aug 2018 13:36:03 -0400 Subject: [PATCH 2/4] CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 4982d701e39..5df0a5b7d9e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ Change Log ##### Additions :tada: * Added `ClippingPlaneCollection.planeAdded` and `ClippingPlaneCollection.planeRemoved` events. `planeAdded` is raised when a new plane is added to the collection and `planeRemoved` is raised when a plane is removed. [#6875](https://github.com/AnalyticalGraphicsInc/cesium/pull/6875) * Added `Matrix4.setScale` for setting the scale on an affine transformation matrix [#6888](https://github.com/AnalyticalGraphicsInc/cesium/pull/6888) +* Added `GeocoderViewModel.destinationFoundCommand` for specifying a `Command` that is called upon a successful geocode. The default behavior is to fly to the destination found by the geocoder. [#6915](https://github.com/AnalyticalGraphicsInc/cesium/pull/6915) ##### Fixes :wrench: * The Geocoder widget now takes terrain altitude into account when calculating its final destination. From 1feacbda0916e327fd9faef14385ca4eae3f6c9c Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 14 Aug 2018 14:56:43 -0400 Subject: [PATCH 3/4] geocoder command -> function --- CHANGES.md | 2 +- Source/Widgets/Geocoder/Geocoder.js | 2 +- Source/Widgets/Geocoder/GeocoderViewModel.js | 17 +++++++++++------ Specs/Widgets/Geocoder/GeocoderSpec.js | 3 +-- Specs/Widgets/Geocoder/GeocoderViewModelSpec.js | 12 ++++++------ 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5df0a5b7d9e..d7220293c77 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,7 +11,7 @@ Change Log ##### Additions :tada: * Added `ClippingPlaneCollection.planeAdded` and `ClippingPlaneCollection.planeRemoved` events. `planeAdded` is raised when a new plane is added to the collection and `planeRemoved` is raised when a plane is removed. [#6875](https://github.com/AnalyticalGraphicsInc/cesium/pull/6875) * Added `Matrix4.setScale` for setting the scale on an affine transformation matrix [#6888](https://github.com/AnalyticalGraphicsInc/cesium/pull/6888) -* Added `GeocoderViewModel.destinationFoundCommand` for specifying a `Command` that is called upon a successful geocode. The default behavior is to fly to the destination found by the geocoder. [#6915](https://github.com/AnalyticalGraphicsInc/cesium/pull/6915) +* Added `GeocoderViewModel.destinationFound` for specifying a function that is called upon a successful geocode. The default behavior is to fly to the destination found by the geocoder. [#6915](https://github.com/AnalyticalGraphicsInc/cesium/pull/6915) ##### Fixes :wrench: * The Geocoder widget now takes terrain altitude into account when calculating its final destination. diff --git a/Source/Widgets/Geocoder/Geocoder.js b/Source/Widgets/Geocoder/Geocoder.js index 389316dfe03..09385f39f27 100644 --- a/Source/Widgets/Geocoder/Geocoder.js +++ b/Source/Widgets/Geocoder/Geocoder.js @@ -34,7 +34,7 @@ define([ * @param {GeocoderService[]} [options.geocoderServices] The geocoder services to be used * @param {Boolean} [options.autoComplete = true] True if the geocoder should query as the user types to autocomplete * @param {Number} [options.flightDuration=1.5] The duration of the camera flight to an entered location, in seconds. - * @param {Geocoder~DestinationFoundFunction} [options.destinationFound] A callback function that is called after a successful geocode. If not supplied, the default behavior is to fly the camera to the result destination. + * @param {Geocoder~DestinationFoundFunction} [options.destinationFound=GeocoderViewModel.flyToDestination] A callback function that is called after a successful geocode. If not supplied, the default behavior is to fly the camera to the result destination. */ function Geocoder(options) { //>>includeStart('debug', pragmas.debug); diff --git a/Source/Widgets/Geocoder/GeocoderViewModel.js b/Source/Widgets/Geocoder/GeocoderViewModel.js index 27ffc4e6726..757ed8824e8 100644 --- a/Source/Widgets/Geocoder/GeocoderViewModel.js +++ b/Source/Widgets/Geocoder/GeocoderViewModel.js @@ -139,7 +139,7 @@ define([ that._searchText = data.displayName; var destination = data.destination; clearSuggestions(that); - that.destinationFoundCommand(that, destination); + that.destinationFound(that, destination); }; this.hideSuggestions = function () { @@ -174,9 +174,9 @@ define([ /** * Gets and sets the command called when a geocode destination is found - * @type {Command} + * @type {Geocoder~DestinationFoundFunction} */ - this.destinationFoundCommand = createCommand(defaultValue(options.destinationFound, GeocoderViewModel._updateCamera)); + this.destinationFound = defaultValue(options.destinationFound, GeocoderViewModel.flyToDestination); this._focusTextbox = false; @@ -362,7 +362,7 @@ define([ }); } - function updateCamera(viewModel, destination) { + function flyToDestination(viewModel, destination) { var scene = viewModel._scene; var mapProjection = scene.mapProjection; var ellipsoid = mapProjection.ellipsoid; @@ -450,7 +450,7 @@ define([ var geocoderResults = result.value; if (result.state === 'fulfilled' && defined(geocoderResults) && geocoderResults.length > 0) { viewModel._searchText = geocoderResults[0].displayName; - viewModel.destinationFoundCommand(viewModel, geocoderResults[0].destination); + viewModel.destinationFound(viewModel, geocoderResults[0].destination); return; } viewModel._searchText = query + ' (not found)'; @@ -526,8 +526,13 @@ define([ }); } + /** + * A function to fly to the destination found by a successful geocode. + * @type {Geocoder~DestinationFoundFunction} + */ + GeocoderViewModel.flyToDestination = flyToDestination; + //exposed for testing - GeocoderViewModel._updateCamera = updateCamera; GeocoderViewModel._updateSearchSuggestions = updateSearchSuggestions; GeocoderViewModel._adjustSuggestionsScroll = adjustSuggestionsScroll; diff --git a/Specs/Widgets/Geocoder/GeocoderSpec.js b/Specs/Widgets/Geocoder/GeocoderSpec.js index 7bb84695f7c..d5eb07e6828 100644 --- a/Specs/Widgets/Geocoder/GeocoderSpec.js +++ b/Specs/Widgets/Geocoder/GeocoderSpec.js @@ -34,8 +34,7 @@ defineSuite([ var viewModel = geocoder.viewModel; expect(viewModel.scene).toBe(scene); expect(viewModel.flightDuration).toBe(flightDuration); - viewModel.destinationFoundCommand(); - expect(destinationFound).toHaveBeenCalled(); + expect(viewModel.destinationFound).toBe(destinationFound); geocoder.destroy(); }); diff --git a/Specs/Widgets/Geocoder/GeocoderViewModelSpec.js b/Specs/Widgets/Geocoder/GeocoderViewModelSpec.js index 7e84a505112..17a35fc6ce1 100644 --- a/Specs/Widgets/Geocoder/GeocoderViewModelSpec.js +++ b/Specs/Widgets/Geocoder/GeocoderViewModelSpec.js @@ -177,7 +177,7 @@ defineSuite([ }); it('can activate selected search suggestion', function () { - spyOn(GeocoderViewModel, '_updateCamera'); + spyOn(GeocoderViewModel, 'flyToDestination'); var destination = new Rectangle(0.0, -0.1, 0.1, 0.1); var geocoder = new GeocoderViewModel({ scene : scene, @@ -188,11 +188,11 @@ defineSuite([ geocoder._selectedSuggestion = suggestion; geocoder.activateSuggestion(suggestion); expect(geocoder._searchText).toEqual('a'); - expect(GeocoderViewModel._updateCamera).toHaveBeenCalledWith(geocoder, destination); + expect(GeocoderViewModel.flyToDestination).toHaveBeenCalledWith(geocoder, destination); }); it('if more than one geocoder service is provided, use first result from first geocode in array order', function () { - spyOn(GeocoderViewModel, '_updateCamera'); + spyOn(GeocoderViewModel, 'flyToDestination'); var geocoder = new GeocoderViewModel({ scene : scene, @@ -202,7 +202,7 @@ defineSuite([ geocoder.search(); expect(geocoder._searchText).toEqual(geocoderResults2[0].displayName); - expect(GeocoderViewModel._updateCamera).toHaveBeenCalledWith(geocoder, mockDestination); + expect(GeocoderViewModel.flyToDestination).toHaveBeenCalledWith(geocoder, mockDestination); }); it('can update autoComplete suggestions list using multiple geocoders', function () { @@ -216,7 +216,7 @@ defineSuite([ }); it('uses custom destination found callback', function () { - spyOn(GeocoderViewModel, '_updateCamera'); + spyOn(GeocoderViewModel, 'flyToDestination'); var destinationFound = jasmine.createSpy(); var geocoder = new GeocoderViewModel({ @@ -228,7 +228,7 @@ defineSuite([ geocoder.search(); expect(geocoder._searchText).toEqual(geocoderResults2[0].displayName); - expect(GeocoderViewModel._updateCamera).not.toHaveBeenCalled(); + expect(GeocoderViewModel.flyToDestination).not.toHaveBeenCalled(); expect(destinationFound).toHaveBeenCalledWith(geocoder, mockDestination); }); From 32bd0c470ec71bd7707df42c4929d7ae61b57bd6 Mon Sep 17 00:00:00 2001 From: Hannah Date: Tue, 14 Aug 2018 14:58:03 -0400 Subject: [PATCH 4/4] doc --- Source/Widgets/Geocoder/GeocoderViewModel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Widgets/Geocoder/GeocoderViewModel.js b/Source/Widgets/Geocoder/GeocoderViewModel.js index 757ed8824e8..b1ab192bb84 100644 --- a/Source/Widgets/Geocoder/GeocoderViewModel.js +++ b/Source/Widgets/Geocoder/GeocoderViewModel.js @@ -50,7 +50,7 @@ define([ * If more than one are supplied, suggestions will be gathered for the geocoders that support it, * and if no suggestion is selected the result from the first geocoder service wil be used. * @param {Number} [options.flightDuration] The duration of the camera flight to an entered location, in seconds. - * @param {Geocoder~DestinationFoundFunction} [options.destinationFound] A callback function that is called after a successful geocode. If not supplied, the default behavior is to fly the camera to the result destination. + * @param {Geocoder~DestinationFoundFunction} [options.destinationFound=GeocoderViewModel.flyToDestination] A callback function that is called after a successful geocode. If not supplied, the default behavior is to fly the camera to the result destination. */ function GeocoderViewModel(options) { //>>includeStart('debug', pragmas.debug);