Hello Everyone,
I've added the AGO Directions Widget to an application for routing my building inspectors. The widget works very nicely but I am wondering if it can be modified, and if so, what the code modification would be to achieve the following.
Have the stops show not only the stop number but also the address of the stop as well?
Thank you.
Jeff
Solved! Go to Solution.
Jeff,
The labels are added after the second address. Adjust the label properties in the _onDirectionsStart function.
Widget.js
///////////////////////////////////////////////////////////////////////////
// Copyright © 2014 - 2016 Esri. All Rights Reserved.
//
// Licensed under the Apache License Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///////////////////////////////////////////////////////////////////////////
define([
'dojo/_base/declare',
'jimu/BaseWidget',
'esri/dijit/Directions',
'esri/tasks/locator',
'esri/tasks/RouteParameters',
'esri/request',
'esri/graphicsUtils',
'esri/layers/ArcGISDynamicMapServiceLayer',
'dojo/on',
'dojo/_base/lang',
'dojo/_base/html',
'dojo/_base/array',
'dojo/_base/config',
'dojo/Deferred',
'dojo/promise/all',
'jimu/portalUtils',
'esri/layers/GraphicsLayer',
'esri/symbols/TextSymbol',
'esri/symbols/Font',
'esri/graphic',
'esri/Color'
],
function(declare, BaseWidget, Directions, Locator, RouteParameters, esriRequest, graphicsUtils,
ArcGISDynamicMapServiceLayer, on, lang, html, array, dojoConfig, Deferred, all, portalUtils,
GraphicsLayer, TextSymbol, Font, Graphic, Color) {
return declare([BaseWidget], {
name: 'Directions',
baseClass: 'jimu-widget-directions',
_dijitDirections:null,
_routeTaskUrl: "//route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World",
_locatorUrl: "//geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer",
_active: false,//save last active state
_dijitDef: null,
_trafficLayer: null,
_isInitPresetStopsFlag: false,
_stopsLabelGL: null,
onOpen: function () {
this._toggleDartStyleByAppConfig();
this.widgetManager.activateWidget(this);
},
onClose: function(){
this._hide();
},
onNormalize: function(){
this._show();
},
onMinimize: function(){
this._hide();
},
onMaximize: function(){
this._show();
},
onDeActive: function(){
this._deactivateDirections();
this._enableWebMapPopup();
},
setStartStop: function(stop){
console.info("stop added", stop);
this.getDirectionsDijit().then(lang.hitch(this, function(directionsDijit){
directionsDijit.reset().then(lang.hitch(this, function(){
directionsDijit.addStop(stop);
}), lang.hitch(this, function(err){
console.error(err);
}));
}), lang.hitch(this, function(err){
console.error(err);
}));
},
addStop: function(stop){
console.info("stop added", stop);
this.getDirectionsDijit().then(lang.hitch(this, function(directionsDijit) {
directionsDijit.addStop(stop);
}), lang.hitch(this, function(err) {
console.error(err);
}));
},
getDirectionsDijit: function(){
if(!this._dijitDef){
this._dijitDef = new Deferred();
}
if(this._dijitDef.isFulfilled()){
this._dijitDef = new Deferred();
}
if(this._dijitDirections){
this._dijitDef.resolve(this._dijitDirections);
}
return this._dijitDef;
},
_handlePopup: function(){
if(this.map.activeDirectionsWidget && this.map.activeDirectionsWidget.mapClickActive){
this._disableWebMapPopup();
}else{
this._enableWebMapPopup();
}
},
_disableWebMapPopup:function(){
if(this.map){
this.map.setInfoWindowOnClick(false);
}
},
_enableWebMapPopup:function(){
if(this.map){
this.map.setInfoWindowOnClick(true);
}
},
destroy: function(){
if(this.map.activeDirectionsWidget === this._dijitDirections){
this.map.activeDirectionsWidget = null;
}
if(this._trafficLayer){
this.map.removeLayer(this._trafficLayer);
this._trafficLayer = null;
}
this._handlePopup();
this.inherited(arguments);
},
startup: function(){
this.inherited(arguments);
this.portal = portalUtils.getPortal(this.appConfig.portalUrl);
this._stopsLabelGL = new GraphicsLayer();
this.map.addLayer(this._stopsLabelGL);
this._preProcessConfig().then(lang.hitch(this, function(){
var routeParams = new RouteParameters();
var routeOptions = this.config.routeOptions;
if(routeOptions){
if(routeOptions.directionsLanguage){
routeParams.directionsLanguage = routeOptions.directionsLanguage;
}
else{
routeParams.directionsLanguage = dojoConfig.locale || "en_us";
}
routeParams.directionsLengthUnits = routeOptions.directionsLengthUnits;
routeParams.directionsOutputType = routeOptions.directionsOutputType;
if(routeOptions.impedanceAttribute){
routeParams.impedanceAttribute = routeOptions.impedanceAttribute;
}
}
var options = {
map: this.map,
searchOptions: this.config.searchOptions,
routeParams: routeParams,
routeTaskUrl: this.config.routeTaskUrl,
dragging: true,
showClearButton: true,
mapClickActive: true
};
//set units on root for API-3.20
if(this.config.routeOptions && this.config.routeOptions.directionsLengthUnits) {
options.directionsLengthUnits = this.config.routeOptions.directionsLengthUnits;
}
if(this.config.trafficLayerUrl){
this._trafficLayer = new ArcGISDynamicMapServiceLayer(this.config.trafficLayerUrl);
options.trafficLayer = this._trafficLayer;
options.traffic = true;
}else{
options.traffic = false;
options.showTrafficOption = false;
}
this.setDoNotFetchTravelModes(options).then(lang.hitch(this, function() {
html.empty(this.directionController);
var directionContainer = html.create('div', {}, this.directionController);
//Only init Directions dijit when we can access the route task url.
esriRequest({
url: options.routeTaskUrl,
content: {
f: 'json'
},
handleAs: 'json',
callbackParamName: 'callback'
}).then(lang.hitch(this, function() {
this._dijitDirections = new Directions(options, directionContainer);
//html.place(this._dijitDirections.domNode, this.directionController);
this._dijitDirections.startup();
this.own(on(this._dijitDirections, 'load', lang.hitch(this, this._onDirectionsActivate)));
this.own(on(this._dijitDirections, 'directions-start', lang.hitch(this, this._onDirectionsStart)));
this.own(on(this._dijitDirections, 'directions-clear', lang.hitch(this, this._onDirectionsClear)));
this.own(on(this._dijitDirections,
'directions-finish',
lang.hitch(this, this._onDirectionsFinish)));
this.own(on(this._dijitDirections,
'map-click-active',
lang.hitch(this, this._handlePopup)));
this._activateDirections();
this._storeLastActiveState();
if (this._dijitDef && !this._dijitDef.isFulfilled()) {
this._dijitDef.resolve(this._dijitDirections);
}
}), lang.hitch(this, function(err) {
console.log("Can't access " + options.routeTaskUrl, err);
}));
}), lang.hitch(this, function(err) {
console.error(err);
}));
}));
},
onAppConfigChanged: function(appConfig){
this.appConfig = appConfig;
this._toggleDartStyleByAppConfig();
},
_onDirectionsClear: function(evt){
if(this._stopsLabelGL){
this._stopsLabelGL.clear();
}
},
_onDirectionsStart: function(evt){
if(evt.target.stops && evt.target.stops.length > 0 && this._stopsLabelGL){
this._stopsLabelGL.clear();
var stops = evt.target.stops;
var font = new Font("12px", Font.STYLE_NORMAL, Font.VARIANT_NORMAL, Font.WEIGHT_BOLD);
array.map(stops, lang.hitch(this, function(stop){
if ("undefined" !== typeof stop.name && "" !== stop.name){
var textSymbol = new TextSymbol(stop.name, font, new Color([0, 0, 0]));
textSymbol.horizontalAlignment = "left";
textSymbol.setOffset(12, 10);
var labelPointGraphic = new Graphic(stop.feature.geometry, textSymbol);
this._stopsLabelGL.add(labelPointGraphic);
}
}));
}
},
_onDirectionsFinish: function(evt){
if(evt && evt.result){
var routeResults = evt.result.routeResults;
if(lang.isArrayLike(routeResults) && routeResults.length > 0){
var routes = [];
array.forEach(routeResults, function(routeResult){
if(routeResult.route){
routes.push(routeResult.route);
}
});
if(routes.length > 0){
var ext = null;
try{
ext = graphicsUtils.graphicsExtent(routes);
if(ext){
ext = ext.expand(1.3);
}
}catch(e){
console.log(e);
}
if(ext){
this.map.setExtent(ext);
}
}
}
}
},
_preProcessConfig:function(){
if(!this.config.geocoderOptions){
this.config.geocoderOptions = {};
}
if(!(this.config.geocoderOptions.geocoders &&
this.config.geocoderOptions.geocoders.length > 0)){
this.config.geocoderOptions.geocoders = [{
url: '',
placeholder: ''
}];
}
var placeholder = this.config.geocoderOptions.geocoders[0].placeholder;
if(!placeholder){
if(!this.config.routeTaskUrl){
//user doesn't open the setting page, we use the default placeholder
placeholder = this.nls.searchPlaceholder;
}
}
this.config.searchOptions = {
enableSuggestions: this.config.geocoderOptions.autoComplete,
maxSuggestions: this.config.geocoderOptions.maxLocations,
minCharacters: this.config.geocoderOptions.minCharacters,
suggestionDelay: this.config.geocoderOptions.searchDelay,
sources: [{
locator: null,
name: '',
singleLineFieldName: '',
outFields: ["*"],
placeholder: placeholder
}]
};
var def = new Deferred();
all([this._getRouteTaskUrl(), this._getLocatorUrl()]).then(
lang.hitch(this, function(results){
this.config.routeTaskUrl = results[0];
this.config.routeTaskUrl = this._replaceRouteTaskUrlWithAppProxy(this.config.routeTaskUrl);
var locatorUrl = results[1];
esriRequest({
url: locatorUrl,
hanleAs:'json',
content:{
f:'json'
},
callbackParamName:'callback'
}).then(lang.hitch(this, function(geocodeMeta){
this.config.searchOptions.sources[0].locator = new Locator(locatorUrl);
this.config.searchOptions.sources[0].name = geocodeMeta.serviceDescription || '';
this.config.searchOptions.sources[0].singleLineFieldName =
geocodeMeta.singleLineAddressField && geocodeMeta.singleLineAddressField.name || '';
def.resolve();
}), lang.hitch(this, function(err){
console.error(err);
def.reject();
}));
}), lang.hitch(this, function(err){
console.error(err);
def.reject();
}));
return def;
},
_replaceRouteTaskUrlWithAppProxy: function(routeTaskUrl){
// Use proxies to replace the routeTaskUrl
var ret = routeTaskUrl;
if(!window.isBuilder && !this.appConfig.mode &&
this.appConfig.appProxies && this.appConfig.appProxies.length > 0) {
array.some(this.appConfig.appProxies, function(proxyItem) {
if(routeTaskUrl === proxyItem.sourceUrl) {
ret = proxyItem.proxyUrl;
return true;
}
});
}
return ret;
},
_getRouteTaskUrl: function(){
var def = new Deferred();
if(this.config.routeTaskUrl){
def.resolve(this.config.routeTaskUrl);
}
else{
this.portal.loadSelfInfo().then(lang.hitch(this, function(response){
if(response && response.helperServices && response.helperServices.route){
def.resolve(response.helperServices.route.url);
}
else{
def.resolve(this._routeTaskUrl);
}
}), lang.hitch(this, function(err){
console.error(err);
def.resolve(this._routeTaskUrl);
}));
}
return def;
},
_getLocatorUrl: function(){
var def = new Deferred();
var geocodeArgs = this.config.geocoderOptions &&
this.config.geocoderOptions.geocoders &&
this.config.geocoderOptions.geocoders[0];
var url = geocodeArgs && geocodeArgs.url;
if(url){
def.resolve(url);
}
else{
this.portal.loadSelfInfo().then(lang.hitch(this, function(response){
if(response && response.helperServices &&
response.helperServices.geocode &&
response.helperServices.geocode.length > 0){
var geocode = response.helperServices.geocode[0];
def.resolve(geocode.url);
}
else{
def.resolve(this._locatorUrl);
}
}), lang.hitch(this, function(err){
console.error(err);
def.resolve(this._locatorUrl);
}));
}
return def;
},
setDoNotFetchTravelModes: function(options) {
var def = new Deferred();
if (this.config.travelModesUrl) {
options.travelModesServiceUrl = this.config.travelModesUrl;
options.doNotFetchTravelModesFromOwningSystem = false;
def.resolve();
} else {
this._getTravelModesUrlVersion().then(lang.hitch(this, function(version) {
if (version && version >= 10.4) {
options.doNotFetchTravelModesFromOwningSystem = false;
} else {
options.doNotFetchTravelModesFromOwningSystem = true;
}
def.resolve();
}), lang.hitch(this, function(err){
def.reject(err);
}));
}
return def;
},
_getTravelModesUrlVersion: function() {
var def = new Deferred();
esriRequest({
url: this.config.routeTaskUrl,
content: {
f: 'json'
},
handleAs: 'json',
callbackParamName: 'callback'
}).then(lang.hitch(this, function(results) {
def.resolve(results.currentVersion);
}), lang.hitch(this, function(err) {
console.log("Can't access " + this.config.routeTaskUrl, err);
def.reject(err);
}));
return def;
},
_hide: function(){
if(this._dijitDirections){
this._storeLastActiveState();
this._deactivateDirections();
}
},
_show: function(){
if(this._dijitDirections){
this._resetByLastActiveState();
}
},
_storeLastActiveState: function(){
if(this._dijitDirections){
this._active = this._dijitDirections.mapClickActive;
}
},
_resetByLastActiveState: function(){
if(this._dijitDirections){
if(this._active){
this._activateDirections();
}
else{
this._deactivateDirections();
}
this._storeLastActiveState();
}
},
_activateDirections: function() {
if (this._dijitDirections) {
if (typeof this._dijitDirections.activate === 'function') {
this._dijitDirections.activate();//Deprecated at v3.13
}
if (typeof this._dijitDirections.mapClickActive !== "undefined") {
this._dijitDirections.set("mapClickActive", true);
}
this._disableWebMapPopup();
}
},
_deactivateDirections: function() {
if (this._dijitDirections) {
if (typeof this._dijitDirections.deactivate === 'function') {
this._dijitDirections.deactivate();//Deprecated at v3.13
}
if (typeof this._dijitDirections.mapClickActive !== "undefined") {
this._dijitDirections.set("mapClickActive", false);
}
this._enableWebMapPopup();
}
},
_onDirectionsActivate: function () {
if (this.config.defaultLocations &&
this.config.defaultLocations.length && this.config.defaultLocations.length > 0 &&
false === this._isInitPresetStopsFlag) {
this._isInitPresetStopsFlag = true;
this._dijitDirections.addStops(this.config.defaultLocations);
}
},
isHasFrom: function () {
var hasFrom = false;
if (this._dijitDirections) {
var stops = this._dijitDirections.stops;
if (stops && stops.length >= 0) {
var from = stops[0];
if (("undefined" !== typeof from.name && "" !== from.name) ||
("undefined" !== typeof from.feature) ||
("undefined" !== typeof from.extent)) {
hasFrom = true;
}
}
}
return hasFrom;
},
// isHasTo: function () {
// var hasTo = false;
// if (this._dijitDirections) {
// var stops = this._dijitDirections.stops;
// if (stops && stops.length === 1) {
// var to = stops[1];
// if (("undefined" !== typeof to.name && "" !== to.name) ||
// ("undefined" !== typeof to.feature) ||
// ("undefined" !== typeof to.extent)) {
// hasTo = true;
// }
// } else if (stops && stops.length > 1) {
// hasTo = true;
// }
// }
// return hasTo;
// },
// actionTo: function (geometry) {
// this.getDirectionsDijit().then(lang.hitch(this, function (directionsDijit) {
// //var stops = this._dijitDirections.stops;
// if (false === this.isHasFrom()) {
// directionsDijit.addStops(["", geometry]);
// } else {
// directionsDijit.addStop(geometry);
// }
// }), lang.hitch(this, function (err) {
// console.error(err);
// }));
// },
// actionFrom: function (geometry) {
// this.setStartStop(geometry);
// }
actionTo: function (geometry) {
this.getDirectionsDijit().then(lang.hitch(this, function (directionsDijit) {
var stops = this._getReplaceStops(directionsDijit, geometry, "last");
directionsDijit.reset().then(lang.hitch(this, function () {
directionsDijit.addStops(stops);
}), lang.hitch(this, function (err) {
console.error(err);
}));
}), lang.hitch(this, function (err) {
console.error(err);
}));
},
actionFrom: function (geometry) {
this.getDirectionsDijit().then(lang.hitch(this, function (directionsDijit) {
var stops = this._getReplaceStops(directionsDijit, geometry, "first");
directionsDijit.reset().then(lang.hitch(this, function () {
directionsDijit.addStops(stops);
}), lang.hitch(this, function (err) {
console.error(err);
}));
}), lang.hitch(this, function (err) {
console.error(err);
}));
},
_getReplaceStops: function (dijitDirections, geometry, place) {
var stops = [];
if (dijitDirections && dijitDirections.stops) {
stops = lang.clone(dijitDirections.stops);//directionsDijit.reset() will clean stops now, so clone
console.info("stops added", stops);
if (place === "first") {
//replace first stop ,as "From"
stops[0] = geometry;
} else if (place === "last") {
if (false === this.isHasFrom()) {
//if without start stop, leave a blank
stops = ["", geometry];
} else {
//append a "To" stop
stops.push(geometry);
}
}
}
return stops;
},
_toggleDartStyleByAppConfig: function () {
var themeName = this.appConfig.theme.name;
if ((themeName === "DashboardTheme" &&
(this.appConfig.theme.styles[0] === 'default' || this.appConfig.theme.styles[0] === 'style3')) ||
themeName === "DartTheme") {
html.addClass(this.domNode, "dart-theme");
} else {
html.removeClass(this.domNode, "dart-theme");
}
}
});
});
Jeff,
Have the stops show not only the stop number but also the address of the stop as well
What exactly do you mean? You want a label on the map to show the address?
Hi Robert,
That's correct. By default the stops are labeled on the map 1...2...3...and so on in sequence. I was wondering if it was possible to have the address that the building inspectors type in to create the stop could be also represented as a label next to the location as well.
Thanks.
Jeff
Jeff,
The labels are added after the second address. Adjust the label properties in the _onDirectionsStart function.
Widget.js
///////////////////////////////////////////////////////////////////////////
// Copyright © 2014 - 2016 Esri. All Rights Reserved.
//
// Licensed under the Apache License Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///////////////////////////////////////////////////////////////////////////
define([
'dojo/_base/declare',
'jimu/BaseWidget',
'esri/dijit/Directions',
'esri/tasks/locator',
'esri/tasks/RouteParameters',
'esri/request',
'esri/graphicsUtils',
'esri/layers/ArcGISDynamicMapServiceLayer',
'dojo/on',
'dojo/_base/lang',
'dojo/_base/html',
'dojo/_base/array',
'dojo/_base/config',
'dojo/Deferred',
'dojo/promise/all',
'jimu/portalUtils',
'esri/layers/GraphicsLayer',
'esri/symbols/TextSymbol',
'esri/symbols/Font',
'esri/graphic',
'esri/Color'
],
function(declare, BaseWidget, Directions, Locator, RouteParameters, esriRequest, graphicsUtils,
ArcGISDynamicMapServiceLayer, on, lang, html, array, dojoConfig, Deferred, all, portalUtils,
GraphicsLayer, TextSymbol, Font, Graphic, Color) {
return declare([BaseWidget], {
name: 'Directions',
baseClass: 'jimu-widget-directions',
_dijitDirections:null,
_routeTaskUrl: "//route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World",
_locatorUrl: "//geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer",
_active: false,//save last active state
_dijitDef: null,
_trafficLayer: null,
_isInitPresetStopsFlag: false,
_stopsLabelGL: null,
onOpen: function () {
this._toggleDartStyleByAppConfig();
this.widgetManager.activateWidget(this);
},
onClose: function(){
this._hide();
},
onNormalize: function(){
this._show();
},
onMinimize: function(){
this._hide();
},
onMaximize: function(){
this._show();
},
onDeActive: function(){
this._deactivateDirections();
this._enableWebMapPopup();
},
setStartStop: function(stop){
console.info("stop added", stop);
this.getDirectionsDijit().then(lang.hitch(this, function(directionsDijit){
directionsDijit.reset().then(lang.hitch(this, function(){
directionsDijit.addStop(stop);
}), lang.hitch(this, function(err){
console.error(err);
}));
}), lang.hitch(this, function(err){
console.error(err);
}));
},
addStop: function(stop){
console.info("stop added", stop);
this.getDirectionsDijit().then(lang.hitch(this, function(directionsDijit) {
directionsDijit.addStop(stop);
}), lang.hitch(this, function(err) {
console.error(err);
}));
},
getDirectionsDijit: function(){
if(!this._dijitDef){
this._dijitDef = new Deferred();
}
if(this._dijitDef.isFulfilled()){
this._dijitDef = new Deferred();
}
if(this._dijitDirections){
this._dijitDef.resolve(this._dijitDirections);
}
return this._dijitDef;
},
_handlePopup: function(){
if(this.map.activeDirectionsWidget && this.map.activeDirectionsWidget.mapClickActive){
this._disableWebMapPopup();
}else{
this._enableWebMapPopup();
}
},
_disableWebMapPopup:function(){
if(this.map){
this.map.setInfoWindowOnClick(false);
}
},
_enableWebMapPopup:function(){
if(this.map){
this.map.setInfoWindowOnClick(true);
}
},
destroy: function(){
if(this.map.activeDirectionsWidget === this._dijitDirections){
this.map.activeDirectionsWidget = null;
}
if(this._trafficLayer){
this.map.removeLayer(this._trafficLayer);
this._trafficLayer = null;
}
this._handlePopup();
this.inherited(arguments);
},
startup: function(){
this.inherited(arguments);
this.portal = portalUtils.getPortal(this.appConfig.portalUrl);
this._stopsLabelGL = new GraphicsLayer();
this.map.addLayer(this._stopsLabelGL);
this._preProcessConfig().then(lang.hitch(this, function(){
var routeParams = new RouteParameters();
var routeOptions = this.config.routeOptions;
if(routeOptions){
if(routeOptions.directionsLanguage){
routeParams.directionsLanguage = routeOptions.directionsLanguage;
}
else{
routeParams.directionsLanguage = dojoConfig.locale || "en_us";
}
routeParams.directionsLengthUnits = routeOptions.directionsLengthUnits;
routeParams.directionsOutputType = routeOptions.directionsOutputType;
if(routeOptions.impedanceAttribute){
routeParams.impedanceAttribute = routeOptions.impedanceAttribute;
}
}
var options = {
map: this.map,
searchOptions: this.config.searchOptions,
routeParams: routeParams,
routeTaskUrl: this.config.routeTaskUrl,
dragging: true,
showClearButton: true,
mapClickActive: true
};
//set units on root for API-3.20
if(this.config.routeOptions && this.config.routeOptions.directionsLengthUnits) {
options.directionsLengthUnits = this.config.routeOptions.directionsLengthUnits;
}
if(this.config.trafficLayerUrl){
this._trafficLayer = new ArcGISDynamicMapServiceLayer(this.config.trafficLayerUrl);
options.trafficLayer = this._trafficLayer;
options.traffic = true;
}else{
options.traffic = false;
options.showTrafficOption = false;
}
this.setDoNotFetchTravelModes(options).then(lang.hitch(this, function() {
html.empty(this.directionController);
var directionContainer = html.create('div', {}, this.directionController);
//Only init Directions dijit when we can access the route task url.
esriRequest({
url: options.routeTaskUrl,
content: {
f: 'json'
},
handleAs: 'json',
callbackParamName: 'callback'
}).then(lang.hitch(this, function() {
this._dijitDirections = new Directions(options, directionContainer);
//html.place(this._dijitDirections.domNode, this.directionController);
this._dijitDirections.startup();
this.own(on(this._dijitDirections, 'load', lang.hitch(this, this._onDirectionsActivate)));
this.own(on(this._dijitDirections, 'directions-start', lang.hitch(this, this._onDirectionsStart)));
this.own(on(this._dijitDirections, 'directions-clear', lang.hitch(this, this._onDirectionsClear)));
this.own(on(this._dijitDirections,
'directions-finish',
lang.hitch(this, this._onDirectionsFinish)));
this.own(on(this._dijitDirections,
'map-click-active',
lang.hitch(this, this._handlePopup)));
this._activateDirections();
this._storeLastActiveState();
if (this._dijitDef && !this._dijitDef.isFulfilled()) {
this._dijitDef.resolve(this._dijitDirections);
}
}), lang.hitch(this, function(err) {
console.log("Can't access " + options.routeTaskUrl, err);
}));
}), lang.hitch(this, function(err) {
console.error(err);
}));
}));
},
onAppConfigChanged: function(appConfig){
this.appConfig = appConfig;
this._toggleDartStyleByAppConfig();
},
_onDirectionsClear: function(evt){
if(this._stopsLabelGL){
this._stopsLabelGL.clear();
}
},
_onDirectionsStart: function(evt){
if(evt.target.stops && evt.target.stops.length > 0 && this._stopsLabelGL){
this._stopsLabelGL.clear();
var stops = evt.target.stops;
var font = new Font("12px", Font.STYLE_NORMAL, Font.VARIANT_NORMAL, Font.WEIGHT_BOLD);
array.map(stops, lang.hitch(this, function(stop){
if ("undefined" !== typeof stop.name && "" !== stop.name){
var textSymbol = new TextSymbol(stop.name, font, new Color([0, 0, 0]));
textSymbol.horizontalAlignment = "left";
textSymbol.setOffset(12, 10);
var labelPointGraphic = new Graphic(stop.feature.geometry, textSymbol);
this._stopsLabelGL.add(labelPointGraphic);
}
}));
}
},
_onDirectionsFinish: function(evt){
if(evt && evt.result){
var routeResults = evt.result.routeResults;
if(lang.isArrayLike(routeResults) && routeResults.length > 0){
var routes = [];
array.forEach(routeResults, function(routeResult){
if(routeResult.route){
routes.push(routeResult.route);
}
});
if(routes.length > 0){
var ext = null;
try{
ext = graphicsUtils.graphicsExtent(routes);
if(ext){
ext = ext.expand(1.3);
}
}catch(e){
console.log(e);
}
if(ext){
this.map.setExtent(ext);
}
}
}
}
},
_preProcessConfig:function(){
if(!this.config.geocoderOptions){
this.config.geocoderOptions = {};
}
if(!(this.config.geocoderOptions.geocoders &&
this.config.geocoderOptions.geocoders.length > 0)){
this.config.geocoderOptions.geocoders = [{
url: '',
placeholder: ''
}];
}
var placeholder = this.config.geocoderOptions.geocoders[0].placeholder;
if(!placeholder){
if(!this.config.routeTaskUrl){
//user doesn't open the setting page, we use the default placeholder
placeholder = this.nls.searchPlaceholder;
}
}
this.config.searchOptions = {
enableSuggestions: this.config.geocoderOptions.autoComplete,
maxSuggestions: this.config.geocoderOptions.maxLocations,
minCharacters: this.config.geocoderOptions.minCharacters,
suggestionDelay: this.config.geocoderOptions.searchDelay,
sources: [{
locator: null,
name: '',
singleLineFieldName: '',
outFields: ["*"],
placeholder: placeholder
}]
};
var def = new Deferred();
all([this._getRouteTaskUrl(), this._getLocatorUrl()]).then(
lang.hitch(this, function(results){
this.config.routeTaskUrl = results[0];
this.config.routeTaskUrl = this._replaceRouteTaskUrlWithAppProxy(this.config.routeTaskUrl);
var locatorUrl = results[1];
esriRequest({
url: locatorUrl,
hanleAs:'json',
content:{
f:'json'
},
callbackParamName:'callback'
}).then(lang.hitch(this, function(geocodeMeta){
this.config.searchOptions.sources[0].locator = new Locator(locatorUrl);
this.config.searchOptions.sources[0].name = geocodeMeta.serviceDescription || '';
this.config.searchOptions.sources[0].singleLineFieldName =
geocodeMeta.singleLineAddressField && geocodeMeta.singleLineAddressField.name || '';
def.resolve();
}), lang.hitch(this, function(err){
console.error(err);
def.reject();
}));
}), lang.hitch(this, function(err){
console.error(err);
def.reject();
}));
return def;
},
_replaceRouteTaskUrlWithAppProxy: function(routeTaskUrl){
// Use proxies to replace the routeTaskUrl
var ret = routeTaskUrl;
if(!window.isBuilder && !this.appConfig.mode &&
this.appConfig.appProxies && this.appConfig.appProxies.length > 0) {
array.some(this.appConfig.appProxies, function(proxyItem) {
if(routeTaskUrl === proxyItem.sourceUrl) {
ret = proxyItem.proxyUrl;
return true;
}
});
}
return ret;
},
_getRouteTaskUrl: function(){
var def = new Deferred();
if(this.config.routeTaskUrl){
def.resolve(this.config.routeTaskUrl);
}
else{
this.portal.loadSelfInfo().then(lang.hitch(this, function(response){
if(response && response.helperServices && response.helperServices.route){
def.resolve(response.helperServices.route.url);
}
else{
def.resolve(this._routeTaskUrl);
}
}), lang.hitch(this, function(err){
console.error(err);
def.resolve(this._routeTaskUrl);
}));
}
return def;
},
_getLocatorUrl: function(){
var def = new Deferred();
var geocodeArgs = this.config.geocoderOptions &&
this.config.geocoderOptions.geocoders &&
this.config.geocoderOptions.geocoders[0];
var url = geocodeArgs && geocodeArgs.url;
if(url){
def.resolve(url);
}
else{
this.portal.loadSelfInfo().then(lang.hitch(this, function(response){
if(response && response.helperServices &&
response.helperServices.geocode &&
response.helperServices.geocode.length > 0){
var geocode = response.helperServices.geocode[0];
def.resolve(geocode.url);
}
else{
def.resolve(this._locatorUrl);
}
}), lang.hitch(this, function(err){
console.error(err);
def.resolve(this._locatorUrl);
}));
}
return def;
},
setDoNotFetchTravelModes: function(options) {
var def = new Deferred();
if (this.config.travelModesUrl) {
options.travelModesServiceUrl = this.config.travelModesUrl;
options.doNotFetchTravelModesFromOwningSystem = false;
def.resolve();
} else {
this._getTravelModesUrlVersion().then(lang.hitch(this, function(version) {
if (version && version >= 10.4) {
options.doNotFetchTravelModesFromOwningSystem = false;
} else {
options.doNotFetchTravelModesFromOwningSystem = true;
}
def.resolve();
}), lang.hitch(this, function(err){
def.reject(err);
}));
}
return def;
},
_getTravelModesUrlVersion: function() {
var def = new Deferred();
esriRequest({
url: this.config.routeTaskUrl,
content: {
f: 'json'
},
handleAs: 'json',
callbackParamName: 'callback'
}).then(lang.hitch(this, function(results) {
def.resolve(results.currentVersion);
}), lang.hitch(this, function(err) {
console.log("Can't access " + this.config.routeTaskUrl, err);
def.reject(err);
}));
return def;
},
_hide: function(){
if(this._dijitDirections){
this._storeLastActiveState();
this._deactivateDirections();
}
},
_show: function(){
if(this._dijitDirections){
this._resetByLastActiveState();
}
},
_storeLastActiveState: function(){
if(this._dijitDirections){
this._active = this._dijitDirections.mapClickActive;
}
},
_resetByLastActiveState: function(){
if(this._dijitDirections){
if(this._active){
this._activateDirections();
}
else{
this._deactivateDirections();
}
this._storeLastActiveState();
}
},
_activateDirections: function() {
if (this._dijitDirections) {
if (typeof this._dijitDirections.activate === 'function') {
this._dijitDirections.activate();//Deprecated at v3.13
}
if (typeof this._dijitDirections.mapClickActive !== "undefined") {
this._dijitDirections.set("mapClickActive", true);
}
this._disableWebMapPopup();
}
},
_deactivateDirections: function() {
if (this._dijitDirections) {
if (typeof this._dijitDirections.deactivate === 'function') {
this._dijitDirections.deactivate();//Deprecated at v3.13
}
if (typeof this._dijitDirections.mapClickActive !== "undefined") {
this._dijitDirections.set("mapClickActive", false);
}
this._enableWebMapPopup();
}
},
_onDirectionsActivate: function () {
if (this.config.defaultLocations &&
this.config.defaultLocations.length && this.config.defaultLocations.length > 0 &&
false === this._isInitPresetStopsFlag) {
this._isInitPresetStopsFlag = true;
this._dijitDirections.addStops(this.config.defaultLocations);
}
},
isHasFrom: function () {
var hasFrom = false;
if (this._dijitDirections) {
var stops = this._dijitDirections.stops;
if (stops && stops.length >= 0) {
var from = stops[0];
if (("undefined" !== typeof from.name && "" !== from.name) ||
("undefined" !== typeof from.feature) ||
("undefined" !== typeof from.extent)) {
hasFrom = true;
}
}
}
return hasFrom;
},
// isHasTo: function () {
// var hasTo = false;
// if (this._dijitDirections) {
// var stops = this._dijitDirections.stops;
// if (stops && stops.length === 1) {
// var to = stops[1];
// if (("undefined" !== typeof to.name && "" !== to.name) ||
// ("undefined" !== typeof to.feature) ||
// ("undefined" !== typeof to.extent)) {
// hasTo = true;
// }
// } else if (stops && stops.length > 1) {
// hasTo = true;
// }
// }
// return hasTo;
// },
// actionTo: function (geometry) {
// this.getDirectionsDijit().then(lang.hitch(this, function (directionsDijit) {
// //var stops = this._dijitDirections.stops;
// if (false === this.isHasFrom()) {
// directionsDijit.addStops(["", geometry]);
// } else {
// directionsDijit.addStop(geometry);
// }
// }), lang.hitch(this, function (err) {
// console.error(err);
// }));
// },
// actionFrom: function (geometry) {
// this.setStartStop(geometry);
// }
actionTo: function (geometry) {
this.getDirectionsDijit().then(lang.hitch(this, function (directionsDijit) {
var stops = this._getReplaceStops(directionsDijit, geometry, "last");
directionsDijit.reset().then(lang.hitch(this, function () {
directionsDijit.addStops(stops);
}), lang.hitch(this, function (err) {
console.error(err);
}));
}), lang.hitch(this, function (err) {
console.error(err);
}));
},
actionFrom: function (geometry) {
this.getDirectionsDijit().then(lang.hitch(this, function (directionsDijit) {
var stops = this._getReplaceStops(directionsDijit, geometry, "first");
directionsDijit.reset().then(lang.hitch(this, function () {
directionsDijit.addStops(stops);
}), lang.hitch(this, function (err) {
console.error(err);
}));
}), lang.hitch(this, function (err) {
console.error(err);
}));
},
_getReplaceStops: function (dijitDirections, geometry, place) {
var stops = [];
if (dijitDirections && dijitDirections.stops) {
stops = lang.clone(dijitDirections.stops);//directionsDijit.reset() will clean stops now, so clone
console.info("stops added", stops);
if (place === "first") {
//replace first stop ,as "From"
stops[0] = geometry;
} else if (place === "last") {
if (false === this.isHasFrom()) {
//if without start stop, leave a blank
stops = ["", geometry];
} else {
//append a "To" stop
stops.push(geometry);
}
}
}
return stops;
},
_toggleDartStyleByAppConfig: function () {
var themeName = this.appConfig.theme.name;
if ((themeName === "DashboardTheme" &&
(this.appConfig.theme.styles[0] === 'default' || this.appConfig.theme.styles[0] === 'style3')) ||
themeName === "DartTheme") {
html.addClass(this.domNode, "dart-theme");
} else {
html.removeClass(this.domNode, "dart-theme");
}
}
});
});
Thank you, Robert.
As a follow-up question...
This application was not created within WAB Developers Edition. Instead I created it within AGO.
I've modified code in server/app folders by locating the respective Widget.js file but never with one created on AGO.
Where would that Widget.js for the Direction widget be located?
Jeff
Jeff,
The WAB directory structure is pretty easy to navigate. It would be /widgets/Directions.
Thank you so much, Robert!
Perfect.
Jeff
Hi Robert, this is great to show us how to place addresses labels next to each stop in the route. Maybe I didn't copy the code correctly but I notice I can't use the print button in the Directions widget after pasting your code in Widget.js. Besides that, my real issue is that popup type html page that out of the box directions widget uses. For the life of me, I cannot access/change any of the logo's or text on that special html page from print button in Directions widget. here is my post: Directions Widget, modify Logo at top of Print Res... - Esri Community
Robert, My apologies for involving in this discussion. Since my query is also related to the same widget and similar query, I would like to ask here.
Is there a way we can add different place holders for the start and stop in the directions widget here.
I tried modifying the placeholders in this folder
Application\widgets\Directions\nls\strings.js
Rohit,
You can do one of two things.