From 60eb50f809f29a74a1354ce44de3ae60866919b6 Mon Sep 17 00:00:00 2001
From: ldwr011 <59892926+ldwr011@users.noreply.github.com>
Date: Mon, 27 Apr 2020 10:30:21 -0400
Subject: [PATCH] Upgrade to LRS Locator 1.2.0
-Fixed bug when locating without mile point
-'Highlight Route' links are now a toggle
-Improved warnings for edge cases
---
Widget.html | 21 ++--
Widget.js | 303 +++++++++++++++++++++++++---------------------
css/style.css | 6 +
libs/LRSTask.js | 4 +-
libs/List.js | 28 ++++-
libs/Shapefile.js | 2 +-
6 files changed, 210 insertions(+), 154 deletions(-)
diff --git a/Widget.html b/Widget.html
index 4198a6b..d22e03f 100644
--- a/Widget.html
+++ b/Widget.html
@@ -25,7 +25,7 @@
- |
+ |
-
-
+
@@ -68,9 +76,6 @@
|
-
- |
-
diff --git a/Widget.js b/Widget.js
index 0f6ebce..38fb742 100644
--- a/Widget.js
+++ b/Widget.js
@@ -17,12 +17,15 @@ define([
'dijit/form/ComboBox',
'dijit/form/Select',
'dijit/form/CheckBox',
+ 'dijit/form/Button',
'dijit/registry',
'dojo/_base/html',
'dijit/ProgressBar',
'esri/request',
'esri/tasks/query',
'esri/tasks/QueryTask',
+ 'esri/tasks/FeatureSet',
+ 'esri/tasks/ProjectParameters',
'jimu/BaseWidget',
'jimu/MapManager',
'jimu/LayerStructure',
@@ -71,8 +74,8 @@ define([
'dojo/i18n!esri/nls/jsapi'
],
function (array, declare, lang, Deferred, DeferredList, dom, domConstruct, domStyle, keys, number, on, all, query, topic,
- WidgetsInTemplateMixin, ComboBox, Select, CheckBox, registry, html, ProgressBar,
- esriRequest, Query, QueryTask,
+ WidgetsInTemplateMixin, ComboBox, Select, CheckBox, Button, registry, html, ProgressBar,
+ esriRequest, Query, QueryTask, FeatureSet, ProjectParameters,
BaseWidget, MapManager, LayerStructure, Message, TabContainer, utils, exportUtils, GeojsonConverters, Popup, zoomToUtils,
Dialog, Memory, Observable, OnDemandGrid, DijitRegistry, ColumnResizer, Selection, Selector, NumberTextBox,
Color, Point, Polyline, ScreenPoint, geodesicUtils, Graphic, GraphicsLayer, FeatureLayer, PopupTemplate, SimpleMarkerSymbol, SimpleLineSymbol, TextSymbol, LabelClass, SpatialReference,
@@ -145,6 +148,7 @@ define([
this.own(
on(this._resultList, 'highlight-route', lang.hitch(this, '_onHighlightClicked')),
+ on(this._resultList, 'remove-highlight', lang.hitch(this, '_onRemoveHighlightClicked')),
on(this._resultList, 'click', lang.hitch(this, '_onResultClicked')),
on(this._resultList, 'dblclick', lang.hitch(this, '_onResultDoubleClicked')),
on(this._resultList, 'remove', lang.hitch(this, '_onRemoveClicked')),
@@ -426,6 +430,7 @@ define([
this._resultList.parentWidget = this;
//make sure text-align left
dojo.addClass(this.fromMeasureTextBox, 'text-align', 'left');
+ //this.locateBtn.set('disabled', true);
this._startupFinished = true;
},
@@ -485,7 +490,7 @@ define([
_onFromMeasureChange: function (e) {
// Make sure input is a number, or minus sign in the first position (text box has no value)
- if (this._validChar.indexOf(e.charCode) < 0 || (e.charCode == this._minusChar && this.fromMeasureTextBox.value)) {
+ if (this._validChar.indexOf(e.charCode) < 0 && e.ctrlKey == false || (e.charCode == this._minusChar && this.fromMeasureTextBox.value && e.ctrlKey == false)) {
e.preventDefault();
}
},
@@ -660,14 +665,8 @@ define([
else {
var location = { "x": e.mapPoint.x, "y": e.mapPoint.y, "wkid": e.mapPoint.spatialReference.wkid };
}
- if (this._directionalLineLayer) {
- this._directionalLineLayer.clear();
- if (dojo.query(".dls-symbol").length > 0) {
- console.log("Additional directional symbols found after clearing main layer");
- }
- //dojo.query("g#marker-feature-action-layer_layer").children(".dls-symbol").forEach(dojo.destroy);
- }
+ this._removeHighlight();
this._standBy(true);
@@ -717,11 +716,8 @@ define([
if (results.features.length == 1) {
// Set the route id.
- if (!this._addToResults) {
- this._resultList.clear();
- this._resultLayer.clear();
- this._resultLayer.redraw();
- }
+ this.clearList();
+
this._routeId = results.features[0].attributes[this._routeIdFieldName];
// Show it in the dropdown
@@ -729,12 +725,9 @@ define([
this.routeId.set("store", new Memory({data: data}));
this.routeId.set("value", String(this._routeId));
// Highlight the geometry
- if (this._directionalLineLayer) {
- this._directionalLineLayer.clear();
- }
- this._routeGraphic = new Graphic(geometryEngine.generalize(results.features[0].geometry, 3, true, 'yards'), this._directionalLine);
- this._directionalLineLayer.add(this._routeGraphic);
- this.map.addLayer(this._directionalLineLayer, 1);
+ this._removeHighlight();
+
+ this._highlightRoute(results.features[0].geometry);
this._standBy(false);
@@ -810,22 +803,15 @@ define([
var row = grid.row(event);
this._routeId = row.data.RouteId;
// geometry is in the data store, just highlight it
- if (this._directionalLineLayer) {
- this._directionalLineLayer.clear();
- }
- this._routeGraphic = new Graphic(geometryEngine.generalize(row.data.geometry, 3, true, 'yards'), this._directionalLine);
- this._directionalLineLayer.add(this._routeGraphic)
+ this._highlightRoute(row.data.geometry);
+
dom.byId('SelectRoute').disabled = false;
}));
// Select clicked
on(dom.byId('SelectRoute'), "click", lang.hitch(this, function (e) {
e.preventDefault();
- if (!this._addToResults) {
- this._resultList.clear();
- this._resultLayer.clear();
- this._resultLayer.redraw();
- }
+ this.clearList();
this.selectRouteDialog.hide();
// Show it in the dropdown
var data = [{name: this._routeId + ""}];
@@ -976,9 +962,7 @@ define([
console.log(msg);
this._showWarning({ "message": msg });
// Clear any highlight
- if (this._directionalLineLayer) {
- this._directionalLineLayer.clear();
- }
+ this._removeHighlight();
}
}),
draggable: true
@@ -1020,9 +1004,8 @@ define([
},
_onLocateClicked: function () {
- // Clear the results and any graphics.
- this._clearResults();
- this.map.graphics.clear();
+ // Clear the results.
+ this.clearList();
// Standby...
this._standBy(true);
var routeId = dojo.byId("routeId").value;
@@ -1030,37 +1013,16 @@ define([
this._createRequest(routeId, null, fromMeasure, null);
},
- _clearResults: function () {
- // Clear any results
- if (!this._addToResults) {
- this._resultList.clear();
- this._resultLayer.clear();
- this._resultLayer.redraw();
- }
- },
-
_createRequest: function (routeId, routeName, fromMeasure, toMeasure) {
-
// Validate inputs
- if (!routeId && !routeName) {
- var msg;
- if (this._routeNameFieldName) {
- msg = "Please enter or select a route id or route name.";
- } else {
- msg = "Please enter or select a route id.";
- }
+ if (!routeId) {
+ var msg = "Please enter or select a route id.";
var err = { "message": msg };
this._showError(err);
return;
}
if (!fromMeasure) {
- // var err = { "message": "Please enter a from measure." };
- // this._showError(err);
- // return;
-
// Zoom to route and show its attributes
- // *****DEBUG*****HERE*****
- // Create the routeTask
var params = {
lrsSupport: this._lrsSupport,
map: this.map,
@@ -1069,44 +1031,9 @@ define([
var routeTask = new RouteTask(params);
routeTask.getRouteById(routeId, true).then(lang.hitch(this, "_showEntireRoute")).otherwise(lang.hitch(this, "_showError"));
- } else {
-
- // If routeName is supplied lookup routeId then _runRequest
- // else _runRequest.
- if (routeName) {
- this.routeName = routeName;
- // Query routes for name
- var qt = new QueryTask(this._networkLayerUrl);
- var query = new Query();
- query.outFields = [this._routeIdFieldName];
- if (this._routeNameFieldName) {
- query.outFields.push(this._routeNameFieldName)
- }
- query.returnGeometry = false;
- query.where = this._routeNameFieldName + " = '" + routeName + "'";
- qt.execute(query).then(lang.hitch(this, function (results) {
-
- if (results.features.length == 1) {
- var rid = results.features[0].attributes["Route_ID"];
- this._runRequest(rid, fromMeasure, toMeasure);
- } else {
- // Display error message.
- var msg = "Unable to locate route name: " + this.routeName;
- console.log("MeasureToRoute - ", msg);
- var err = { "message": msg };
- this._showError(err);
- }
-
- })).otherwise(lang.hitch(this, function (err) {
- console.log("MeasureToGeometry _createRequest - error:", err);
- // Display error message
- this._showError(err);
- }));
-
- } else {
- this._runRequest(routeId, fromMeasure, toMeasure);
- }
-
+ }
+ else {
+ this._runRequest(routeId, fromMeasure, toMeasure);
}
},
@@ -1149,21 +1076,25 @@ define([
m2gRequest.then(lang.hitch(this, "_showResponseAllResults")).otherwise(lang.hitch(this, "_showError"));
},
+ _showEntireRoute: function (response) {
+ this._highlightRoute(response.geometry);
+ this._showWarning({message: "To see full results, enter a mile point."})
+ this._standBy(false);
+ },
+
_showWarning: function (warn) {
this._standBy(false);
- this.map.graphics.clear();
var rdiv = dojo.byId("resultmessage");
- rdiv.innerHTML += 'Warning: ' + warn.message + '';
- this._tabContainer.selectTab(this.nls.resultsLabel);
+ rdiv.innerHTML = 'Warning: ' + warn.message + '';
+ this._tabContainer.selectTab(this.nls.identifyLabel);
},
_showError: function (error) {
this._standBy(false);
- this.map.graphics.clear();
console.log(error);
var rdiv = dojo.byId("resultmessage");
- rdiv.innerHTML = 'Error: ' + error.message + '';
- this._tabContainer.selectTab(this.nls.resultsLabel);
+ rdiv.innerHTML = 'Error: ' + error.message + '';
+ this._tabContainer.selectTab(this.nls.identifyLabel);
},
_onClearClicked: function () {
@@ -1180,7 +1111,6 @@ define([
_clearAll: function (caller) {
if (caller) {
this._foundNetworkLayerId = null;
- this.map.graphics.clear();
this.clearSelection();
this._resetDropdown();
dojo.byId("fromMeasure").value = "";
@@ -1246,14 +1176,20 @@ define([
line: filename
}
}
- let jsonObj = {
- type: 'FeatureCollection',
- features: []
- };
- array.forEach(featureSet.features, function (feature) {
- jsonObj.features.push(GeojsonConverters.arcgisToGeoJSON(feature))
- });
- Shapefile.download(jsonObj, options);
+ // The geometry is projected to WGS84 due to GeoJSON standard.
+ this._featureSetToWGS84(featureSet)
+ .then(
+ function (outputFeatures) {
+ let jsonObj = {
+ type: 'FeatureCollection',
+ features: []
+ };
+ array.forEach(outputFeatures.features, function (feature) {
+ jsonObj.features.push(GeojsonConverters.arcgisToGeoJSON(feature))
+ });
+ Shapefile.download(jsonObj, options);
+ }
+ )
},
_exportToGeoJSON: function (filename) {
@@ -1278,21 +1214,84 @@ define([
Csv.download();
},
- clearSelection: function () {
- if (this._directionalLineLayer) {
- this._directionalLineLayer.clear();
- if (dojo.query(".dls-symbol").length > 0){
- console.log("Additional directional symbols found after clearing main layer");
+ _featureSetToWGS84: function(featureSet) {
+ var ret = new Deferred();
+ var getSR = function (featureset) {
+ if (featureset.spatialReference) {
+ return featureset.spatialReference;
+ }
+ // Get spatial refrence from graphics
+ var sf;
+ array.some(featureset.features, function(feature) {
+ if (feature.geometry && feature.geometry.spatialReference){
+ sf = feature.geometry.spatialReference;
+ return true;
+ }
+ });
+ return sf;
+ }
+ var sf = getSR(featureSet);
+ if (!sf) {
+ ret.resolve([]);
+ } else {
+ var wkid = parseInt(sf.wkid, 10);
+
+ if (wkid === 4326) {
+ ret.resolve(featureSet);
+ } else if (sf.isWebMercator()) {
+ var outFeatureset = new FeatureSet();
+ var features = [];
+ array.forEach(featureSet.features, function(feature) {
+ var g = new Graphic(feature.toJson());
+ g.geometry = webMercatorUtils.webMercatorToGeographic(feature.geometry);
+ features.push(g);
+ });
+ outFeatureset.features = features;
+ outFeatureset.geometryType = featureSet.geometryType;
+ outFeatureset.fieldAliases = featureSet.fieldAliases;
+ outFeatureset.fields = featureSet.fields;
+ ret.resolve(outFeatureset);
+ } else {
+ var params = new ProjectParameters();
+ params.geometries = array.map(featureSet.features, function(feature) {
+ return feature.geometry;
+ });
+ params.outSR = new SpatialReference(4326);
+
+ var gs = esriConfig && esriConfig.defaults && esriConfig.defaults.geometryService;
+ var existGS = gs && gs.declaredClass === "esri.tasks.GeometryService";
+ if (!existGS) {
+ gs = utils.getArcGISDefaultGeometryService();
+ }
+
+ gs.project(params).then(function(geometries) {
+ var outFeatureset = new FeatureSet();
+ var features = [];
+ array.forEach(featureSet.features, function(feature, i) {
+ var g = new Graphic(feature.toJson());
+ g.geometry = geometries[i];
+ features.push(g);
+ });
+ outFeatureset.features = features;
+ outFeatureset.geometryType = featureSet.geometryType;
+ outFeatureset.fieldAliases = featureSet.fieldAliases;
+ outFeatureset.fields = featureSet.fields;
+ ret.resolve(outFeatureset);
+ }, function(err) {
+ console.error(err);
+ ret.resolve([]);
+ });
}
}
+ return ret;
+ },
+
+ clearSelection: function () {
+ this._removeHighlight();
// Clear infoWindow and any results
this.map.infoWindow.hide();
if (this._startupFinished == true) {
- if (!this._addToResults) {
- this._resultList.clear();
- this._resultLayer.clear();
- this._resultLayer.redraw();
- }
+ this.clearList();
}
// Unsubscribe to result click events
if (this._resultClickEvents) {
@@ -1300,10 +1299,18 @@ define([
this._resultClickEvents[idx].remove();
}
}
- let rcounter = dojo.byId("resultCounter");
- rcounter.innerHTML = this.nls.resultCounter + this._resultList.items.length;
- let rdiv = dojo.byId("resultmessage");
- rdiv.innerHTML = "";
+ },
+
+ clearList: function () {
+ if (!this._addToResults) {
+ this._resultList.clear();
+ this._resultLayer.clear();
+ this._resultLayer.redraw();
+ let rcounter = dojo.byId("resultCounter");
+ rcounter.innerHTML = this.nls.resultCounter + this._resultList.items.length;
+ let rdiv = dojo.byId("resultmessage");
+ rdiv.innerHTML = "";
+ }
},
_onRouteIdKeydown: function (e) {
@@ -1365,22 +1372,23 @@ define([
},
_onHighlightClicked: function(e) {
- if (this._directionalLineLayer) {
- this._directionalLineLayer.clear();
- this.map.removeLayer(this._directionalLineLayer);
- if (dojo.query(".dls-symbol").length > 0){
- console.warn("Additional directional symbols found after clearing main layer");
- }
- }
+ this._directionalLineLayer.clear();
+ this.map.removeLayer(this._directionalLineLayer);
+ this._resultList._setHighlightLink(e.id);
var geom = e.geometry;
// Highlight it on the map...
- var geometry = new esri.geometry.Polyline(JSON.parse(geom));
+ var geometry = new Polyline(JSON.parse(geom));
geometry.setSpatialReference(this.map.spatialReference);
this._routeGraphic = new Graphic(geometry, this._directionalLine);
this._directionalLineLayer.add(this._routeGraphic);
this.map.addLayer(this._directionalLineLayer, 1);
},
+ _onRemoveHighlightClicked: function (e) {
+ this._directionalLineLayer.clear();
+ this.map.removeLayer(this._directionalLineLayer);
+ },
+
_onResultClicked: function(e) {
this.map.centerAt(e.geometry);
},
@@ -1462,7 +1470,9 @@ define([
var links = [{
geometry: this._resultContent[idx].attributes.RouteGeometry,
popuptype: "geometry",
- alias: "Highlight Route"
+ alias: "Highlight Route",
+ highlighted: "false",
+ id: "id_" + idx + this._resultList.items.length
}];
let labelSymbol = new TextSymbol().setColor(new Color("#000000"));
labelSymbol.font.setSize("7pt");
@@ -1613,12 +1623,25 @@ define([
return dfd.promise;
},
- _highlightRoute: function (evt) {
- this._directionalLineLayer.clear();
- let geometry = new esri.geometry.Polyline(evt.geometry);
+ _highlightRoute: function (routeGeometry) {
+ this._removeHighlight();
+ let geometry = new Polyline(routeGeometry);
geometry.setSpatialReference(this.map.spatialReference);
- let routeGraphic = new Graphic(evt.geometry, this._directionalLine);
+ this.map.setExtent(geometry.getExtent().expand(1.5), true);
+ let routeGraphic = new Graphic(geometry, this._directionalLine);
this._directionalLineLayer.add(routeGraphic);
+ this.map.addLayer(this._directionalLineLayer, 1);
+ },
+
+ _removeHighlight: function () {
+ if (dojo.query(".labellink > a").length > 0) {
+ dojo.query(".labellink > a").forEach(function (element) {
+ element.innerHTML = "Highlight Route";
+ element.title = "Highlight Route";
+ element.dataset.highlighted = "false";
+ })
+ }
+ this._directionalLineLayer.clear();
},
_populateAllResults: function (resultLocations, routeLayers, geoPoint, mapPoint) {
diff --git a/css/style.css b/css/style.css
index 36f4744..c3ad72f 100644
--- a/css/style.css
+++ b/css/style.css
@@ -132,6 +132,12 @@
padding-bottom: 3px;
cursor: pointer;
outline: none;
+ -webkit-touch-callout: none; /* iOS Safari */
+ -webkit-user-select: none; /* Safari */
+ -khtml-user-select: none; /* Konqueror HTML */
+ -moz-user-select: none; /* Old versions of Firefox */
+ -ms-user-select: none; /* Internet Explorer/Edge */
+ user-select: none;
}
.search-list-item .iconDiv,
diff --git a/libs/LRSTask.js b/libs/LRSTask.js
index 1e1139a..aa2c59f 100644
--- a/libs/LRSTask.js
+++ b/libs/LRSTask.js
@@ -155,7 +155,7 @@ return declare(null, {
geometryToMeasure: function(/*int*/ networkLayerId, params, callback, errback) {
params = this._mixinGDBVersion(params);
- return this._requestWithFilter("/networkLayers/"+networkLayerId+"/geometryToMeasure", params, null, callback, errback,
+ return this._requestWithFilter("/networkLayers/"+networkLayerId+"/geometryToMeasure", params, { usePost: true }, callback, errback,
lang.hitch(this, function(response) {
// Apply the response-level spatial reference to each nested geometry
array.forEach(response.locations, function(loc) {
@@ -172,7 +172,7 @@ return declare(null, {
measureToGeometry: function(/*int*/ networkLayerId, params, callback, errback) {
params = this._mixinGDBVersion(params);
- return this._requestWithFilter("/networkLayers/"+networkLayerId+"/measureToGeometry", params, null, callback, errback,
+ return this._requestWithFilter("/networkLayers/"+networkLayerId+"/measureToGeometry", params, { usePost: true }, callback, errback,
lang.hitch(this, function(response) {
// Apply the response-level spatial reference to each nested geometry
array.forEach(response.locations, function(loc) {
diff --git a/libs/List.js b/libs/List.js
index dc46f16..bda6fd7 100644
--- a/libs/List.js
+++ b/libs/List.js
@@ -193,7 +193,7 @@ define(['dojo/_base/declare',
// console.info(item.links);
array.forEach(item.links, function(link){
if(link.popuptype === "geometry"){
- var linkText = domConstruct.toDom("" + link.alias + "
");
+ var linkText = domConstruct.toDom("" + link.alias + "
");
this.own(on(linkText, 'click', lang.hitch(this, "_onHighlightRouteClick")));
domConstruct.place(linkText, linksDiv, 'before');
domClass.add(linkText, 'labellink');
@@ -326,10 +326,32 @@ define(['dojo/_base/declare',
},
_onHighlightRouteClick: function(evt) {
- if (evt.target.dataset.hasOwnProperty("geometry")) {
+ if (evt.target.dataset.highlighted == "false" && evt.target.dataset.hasOwnProperty("geometry")) {
+ evt.target.innerHTML = "Remove Highlight";
+ evt.target.title = "Remove Highlight";
+ evt.target.dataset.highlighted = "true";
let eventGeometry = evt.target.dataset.geometry;
- this.emit('highlight-route', {geometry: eventGeometry});
+ let eventId = evt.target.dataset.id;
+ this.emit('highlight-route', {geometry: eventGeometry, id: eventId});
}
+ else if (evt.target.dataset.highlighted == "true" && evt.target.dataset.hasOwnProperty("geometry")) {
+ evt.target.innerHTML = "Highlight Route";
+ evt.target.title = "Highlight Route";
+ evt.target.dataset.highlighted = "false";
+ let eventGeometry = evt.target.dataset.geometry;
+ let eventId = evt.target.dataset.id;
+ this.emit('remove-highlight', {geometry: eventGeometry, id: eventId});
+ }
+ },
+
+ _setHighlightLink: function (id) {
+ dojo.query(".labellink > a").forEach(function (element) {
+ if (element.dataset.id !== id) {
+ element.innerHTML = "Highlight Route";
+ element.title = "Highlight Route";
+ element.dataset.highlighted = "false";
+ }
+ })
},
_getItemById: function(id) {
diff --git a/libs/Shapefile.js b/libs/Shapefile.js
index 236709e..d841b5f 100644
--- a/libs/Shapefile.js
+++ b/libs/Shapefile.js
@@ -17279,7 +17279,7 @@ function justCoords(coords, l) {
}
},{"./extent":107,"./types":112}],111:[function(require,module,exports){
-module.exports = 'PROJCS["WGS_1984_Web_Mercator_Auxiliary_Sphere",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Mercator_Auxiliary_Sphere"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",0.0],PARAMETER["Standard_Parallel_1",0.0],PARAMETER["Auxiliary_Sphere_Type",0.0],UNIT["Meter",1.0]]';
+module.exports = 'GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]';
},{}],112:[function(require,module,exports){
module.exports.geometries = {