This is my first question of three where I am trying to convert a responsive web created Tom Wayson. His original app is here: tomwayson/responsive-citizens · GitHub
From my original app, I want to add the following:
// set custom extent var initialExtent = new Extent({ "xmin": 777229.03, "ymin": 1133467.92, "xmax": 848340.14, "ymax": 1185634.58, "spatialReference": { "wkid": 3435 } }); // create map and set slider style to small map = new Map("mapDiv", { showAttribution: false, sliderStyle: "small", extent: initialExtent, logo: false }); // Starts initEditing after the feature layer(s) have been added map.on("layers-add-result", initEditing); // add imagery var tiled = new ArgGISTiledMapServiceLayer("http://maps.decaturil.gov/arcgis/rest/services/Aerial_2014_Tiled/MapServer"); map.addLayer(tiled); // add operational layer var operationalLayer = new ArcGISDynamicMapServiceLayer("http://maps.decaturil.gov/arcgis/rest/services/Public/InternetVector/MapServer", { "opacity": 0.5 }); map.addLayer(operationalLayer);
In the app that I am trying to add this information into, I believe I want to modify the following, but I am not sure how (the complete app is at: csergent45/streetSigns · GitHub
excerpt 1:
var config = {
mapOptions: { basemap:'topo', center:[-117.1825, 34.0547], zoom:14, sliderPosition: 'bottom-right' }, citizenRequestLayerUrl: 'http://maps.decaturil.gov/arcgis/rest/services/test/StreetSignTest/FeatureServer/0', infoTemplate: { title: '<b>Request ${objectid}</b>', content: '<span class="infoTemplateContentRowLabel">Date: </span>' + '<span class="infoTemplateContentRowItem">${requestdate:DateFormat}</span><br><span class="infoTemplateContentRowLabel">Phone: </span>' + '<span class="infoTemplateContentRowItem">${phone:formatPhoneNumber}</span><br><span class="infoTemplateContentRowLabel">Name: </span>' + '<span class="infoTemplateContentRowItem">${name}</span><br><span class="infoTemplateContentRowLabel">Severity: </span>' + '<span class="infoTemplateContentRowItem">${severity:severityDomainLookup}</span><br><span class="infoTemplateContentRowLabel">Type: </span>' + '<span class="infoTemplateContentRowItem">${requesttype:requestTypeDomainLookup}</span><br><span class="infoTemplateContentRowLabel">Comments: </span>' + '<span class="infoTemplateContentRowItem">${comment}</span>' } };
excerpt 2:
// initialize the map and add the feature layer // and initialize map widgets var initMap = function() { app.map = BootstrapMap.create('map', config.mapOptions); app.citizenRequestLayer = new FeatureLayer(config.citizenRequestLayerUrl, { mode: FeatureLayer.MODE_ONEDEMAND, infoTemplate: new InfoTemplate(config.infoTemplate), outFields: ['*'] }); app.map.addLayer(app.citizenRequestLayer);
Solved! Go to Solution.
Chris,
The changes go in the main.js
define([ 'dojo/query', 'dojo/dom', 'dojo/dom-class', 'dojo/dom-style', 'dojo/dom-attr', 'esri/config', 'esri/layers/FeatureLayer', 'esri/InfoTemplate', 'esri/graphic', 'esri/dijit/Geocoder', 'esri/dijit/LocateButton', 'esri/dijit/Legend', 'esri/tasks/GeometryService', 'esri/geometry/Extent', 'esri/layers/ArcGISDynamicMapServiceLayer', 'esri/layers/ArcGISTiledMapServiceLayer', 'bootstrap-map-js/js/bootstrapmap', 'dojo-bootstrap/Collapse', 'dojo-bootstrap/Dropdown', 'dojo-bootstrap/Modal', 'dojo-bootstrap/Alert', 'dojo/domReady!' ], function( query, dom, domClass, domStyle, domAttr, esriConfig, FeatureLayer, InfoTemplate, Graphic, Geocoder, LocateButton, Legend, GeometryService, Extent, ArcGISDynamicMapServiceLayer, ArcGISTiledMapServiceLayer, BootstrapMap ) { 'use strict'; /* The proxy comes before all references to web services */ /* Files required for security are proxy.config, web.config and proxy.ashx - set security in Manager to Private, available to selected users and select Allow access to all users who are logged in (Roles are not required) /* The proxy section is defined on the ESRI sample. I have included it as part of the documentation that reads that the measuring will not work. I thought that might be important. */ // Proxy Definition Begin //identify proxy page to use if the toJson payload to the geometry service is greater than 2000 characters. //If this null or not available the project and lengths operation will not work. // Otherwise it will do a http post to the proxy. esriConfig.defaults.io.proxyUrl = "proxy.ashx"; esriConfig.defaults.io.alwaysUseProxy = false; // Proxy Definition End // declare geometry service esriConfig.defaults.geometryService = new GeometryService("http://maps.decaturil.gov/arcgis/rest/services/Utilities/Geometry/GeometryServer"); //Chris's options var initialExtent = new Extent({ "xmin": 777229.03, "ymin": 1133467.92, "xmax": 848340.14, "ymax": 1185634.58, "spatialReference": { "wkid": 3435 } }); // app configuration var config = { mapOptions: { showAttribution: false, sliderStyle: "small", extent: initialExtent, logo: false, sliderPosition: 'bottom-right' }, citizenRequestLayerUrl: 'http://maps.decaturil.gov/arcgis/rest/services/test/StreetSignTest/FeatureServer/0', infoTemplate: { title: '<b>Request ${objectid}</b>', content: '<span class="infoTemplateContentRowLabel">Date: </span>' + '<span class="infoTemplateContentRowItem">${requestdate:DateFormat}</span><br><span class="infoTemplateContentRowLabel">Phone: </span>' + '<span class="infoTemplateContentRowItem">${phone:formatPhoneNumber}</span><br><span class="infoTemplateContentRowLabel">Name: </span>' + '<span class="infoTemplateContentRowItem">${name}</span><br><span class="infoTemplateContentRowLabel">Severity: </span>' + '<span class="infoTemplateContentRowItem">${severity:severityDomainLookup}</span><br><span class="infoTemplateContentRowLabel">Type: </span>' + '<span class="infoTemplateContentRowItem">${requesttype:requestTypeDomainLookup}</span><br><span class="infoTemplateContentRowLabel">Comments: </span>' + '<span class="infoTemplateContentRowItem">${comment}</span>' } }; // app globals var app = {}; app.collapseMenuToggleButton = dom.byId('collapseToggleButton'); app.startEditAlert = dom.byId('startEditAlert'); app.sidebar = dom.byId('sidebar'); app.attributesModal = query('#attributesModal'); app.requestTypeSelect = query('#attributesModal [name="requesttype"]')[0]; // TODO: get these from the feature layer on load app.severityFieldDomainCodedValuesDict = { '0': 'General Nuisance', '1': 'Important To Resolve Soon', '2': 'Critical Issue' }; app.requestTypeFieldDomainCodedValuesDict = { '0': 'Abandoned Vehicle', '1': 'Animal Services', '2': 'Driveway Infraction', '3': 'Flooding', '4': 'Graffiti Removal', '5': 'Homeless Nuisance', '6': 'Illegal Dumping', '7': 'Parking Violation', '8': 'Plant/Tree Complaint', '9': 'Pothole Obstruction', '10': 'Roadway Danger', '11': 'Sidewalk Danger', '12': 'Streetlight Broken', '13': 'Street Sign Missing/Damaged', '14': 'Trash Removal', '15': 'Water Leak', '16': 'Yard Waste Removal' }; // NOTE: popup formatting functions must be globals window.severityDomainLookup = function (value, key, data){ return app.severityFieldDomainCodedValuesDict[value]; }; window.requestTypeDomainLookup = function (value, key, data){ return app.requestTypeFieldDomainCodedValuesDict[value]; }; window.formatPhoneNumber = function (value, key, data){ return value ? '<a href=\'tel:' + value + '\'>' + value + '</a>' : ''; }; // initialize the request type drop down var initAttributeForm = function() { var options = []; for (var key in app.requestTypeFieldDomainCodedValuesDict) { if (app.requestTypeFieldDomainCodedValuesDict.hasOwnProperty(key)) { options.push('<option value="' + key + '">' + app.requestTypeFieldDomainCodedValuesDict[key] + '</option>'); } } app.requestTypeSelect.innerHTML = options.join(''); }; // initialize the map and add the feature layer // and initialize map widgets var initMap = function() { app.map = BootstrapMap.create('map', config.mapOptions); var tiled = new ArcGISTiledMapServiceLayer("http://maps.decaturil.gov/arcgis/rest/services/Aerial_2014_Tiled/MapServer"); app.map.addLayer(tiled); // add operational layer var operationalLayer = new ArcGISDynamicMapServiceLayer("http://maps.decaturil.gov/arcgis/rest/services/Public/InternetVector/MapServer", { "opacity": 0.5 }); app.map.addLayer(operationalLayer); app.citizenRequestLayer = new FeatureLayer(config.citizenRequestLayerUrl, { mode: FeatureLayer.MODE_ONEDEMAND, infoTemplate: new InfoTemplate(config.infoTemplate), outFields: ['*'] }); app.map.addLayer(app.citizenRequestLayer); app.geocoder = new Geocoder({ map: app.map, autoComplete: true, arcgisGeocoder: { placeholder: 'Address or Location' }, 'class': 'geocoder' }, 'geocoder'); app.geocoder.startup(); // Begin geolocate button // add geolocate button to find the location of the current user app.map.on("load", function () { app.locateButton = new LocateButton({ map: app.map, highlightLocation: true, useTracking: true, enableHighAccuracy: true }, 'locateButton'); app.locateButton.clearOnTrackingStop = true; app.locateButton.startup(); app.locateButton.locate(); }); // End geolocate button app.legend = new Legend({ map: app.map, layerInfos: [{ title: 'Street Signs and Supports', layer: app.citizenRequestLayer }] }, 'legend'); app.legend.startup(); // TODO: other widgets, etc }; // hide nav dropdown on mobile var hideDropdownNav = function(e) { if (query('.navbar-collapse.in').length > 0) { e.stopPropagation(); app.collapseMenuToggleButton.click(); } }; // temporarily show alert when starting edits // and then start listening for a map click var startCaptureRequest = function(severity) { var listener; // NOTE: once user has clicked 'x' to dismiss // this alert, it will no longer show up domStyle.set(app.startEditAlert, 'display', ''); setTimeout(function() { domStyle.set(app.startEditAlert, 'display', 'none'); }, 3000); // save map point in app global and app.currentSeverity = severity; listener = app.map.on('click', function(e) { listener.remove(); // save map point in app global and // show form to collect incident report app.currentGeometry = e.mapPoint; app.attributesModal.modal('show'); }); }; var stopCaptureRequest = function() { app.currentSeverity = null; app.currentGeometry = null; }; // get attributes from form and submit var submitIncidentReport = function() { var attributes = { // TODO: not sure if this is needed requestreceived: null }; var currentDate = new Date(); var graphic; if (!app.currentSeverity || !app.currentGeometry) { return; } graphic = new Graphic(app.currentGeometry); attributes.severity = parseInt(app.currentSeverity, 10); query('#attributesModal input, #attributesModal select, #attributesModal textarea').forEach(function (formInput) { attributes[formInput.name] = formInput.value; }); attributes.requesttype = parseInt(attributes.requesttype, 10); attributes.requestdate = Date.UTC(currentDate.getUTCFullYear(), currentDate.getUTCMonth(), currentDate.getUTCDate(), currentDate.getUTCHours(), currentDate.getUTCMinutes(), currentDate.getUTCSeconds(), 0); graphic.setAttributes(attributes); stopCaptureRequest(); // console.log(attributes); app.citizenRequestLayer.applyEdits([graphic], null, null).then(function(response) { console.log(response); }); }; // wire up the DOM events var initEvents = function() { // listen for map clicks once severity is chosen query('.report-btn-group .dropdown-menu a').on('click', function(e) { e.preventDefault(); startCaptureRequest(domAttr.get(e.target, 'data-value')); }); // TODO show the feedback modal query('a[href="#feedback"]').on('click', function(e) { e.preventDefault(); query('#feedbackModal').modal('show'); }); // hide drop down nav after clicking on a link query('.navbar-collapse a').on('click', function(e) { hideDropdownNav(e); }); // change the basemap query('#basemapDropdown a').on('click', function(e) { var basemapName = domAttr.get(e.target, 'data-name'); if (basemapName && app.map) { app.map.setBasemap(basemapName); } }); // toggle the sidebar query('#sidebarToggleButton').on('click', function(e) { // make sure sidebar is same height as the map if (app.map.height) { domStyle.set(app.sidebar, 'height', app.map.height + 'px'); } domClass.toggle(window.document.body, 'sidebar-open'); hideDropdownNav(e); }); // submit or cancel request and hide modal query('#attributesModal .btn').on('click', function(e) { var target = e.target; if (target.innerText === 'Submit') { submitIncidentReport(); } app.attributesModal.modal('hide'); }); // submit or cancel request and hide modal query('#feedbackModal .btn').on('click', function(e) { // NOTE: this is not implemented in sample app query('#feedbackModal').modal('hide'); }); // clear current edit session globals app.attributesModal.on('hidden.bs.modal', stopCaptureRequest); }; // finally, start up the app! initAttributeForm(); initMap(); initEvents(); return app; });
Chris,
The changes go in the main.js
define([ 'dojo/query', 'dojo/dom', 'dojo/dom-class', 'dojo/dom-style', 'dojo/dom-attr', 'esri/config', 'esri/layers/FeatureLayer', 'esri/InfoTemplate', 'esri/graphic', 'esri/dijit/Geocoder', 'esri/dijit/LocateButton', 'esri/dijit/Legend', 'esri/tasks/GeometryService', 'esri/geometry/Extent', 'esri/layers/ArcGISDynamicMapServiceLayer', 'esri/layers/ArcGISTiledMapServiceLayer', 'bootstrap-map-js/js/bootstrapmap', 'dojo-bootstrap/Collapse', 'dojo-bootstrap/Dropdown', 'dojo-bootstrap/Modal', 'dojo-bootstrap/Alert', 'dojo/domReady!' ], function( query, dom, domClass, domStyle, domAttr, esriConfig, FeatureLayer, InfoTemplate, Graphic, Geocoder, LocateButton, Legend, GeometryService, Extent, ArcGISDynamicMapServiceLayer, ArcGISTiledMapServiceLayer, BootstrapMap ) { 'use strict'; /* The proxy comes before all references to web services */ /* Files required for security are proxy.config, web.config and proxy.ashx - set security in Manager to Private, available to selected users and select Allow access to all users who are logged in (Roles are not required) /* The proxy section is defined on the ESRI sample. I have included it as part of the documentation that reads that the measuring will not work. I thought that might be important. */ // Proxy Definition Begin //identify proxy page to use if the toJson payload to the geometry service is greater than 2000 characters. //If this null or not available the project and lengths operation will not work. // Otherwise it will do a http post to the proxy. esriConfig.defaults.io.proxyUrl = "proxy.ashx"; esriConfig.defaults.io.alwaysUseProxy = false; // Proxy Definition End // declare geometry service esriConfig.defaults.geometryService = new GeometryService("http://maps.decaturil.gov/arcgis/rest/services/Utilities/Geometry/GeometryServer"); //Chris's options var initialExtent = new Extent({ "xmin": 777229.03, "ymin": 1133467.92, "xmax": 848340.14, "ymax": 1185634.58, "spatialReference": { "wkid": 3435 } }); // app configuration var config = { mapOptions: { showAttribution: false, sliderStyle: "small", extent: initialExtent, logo: false, sliderPosition: 'bottom-right' }, citizenRequestLayerUrl: 'http://maps.decaturil.gov/arcgis/rest/services/test/StreetSignTest/FeatureServer/0', infoTemplate: { title: '<b>Request ${objectid}</b>', content: '<span class="infoTemplateContentRowLabel">Date: </span>' + '<span class="infoTemplateContentRowItem">${requestdate:DateFormat}</span><br><span class="infoTemplateContentRowLabel">Phone: </span>' + '<span class="infoTemplateContentRowItem">${phone:formatPhoneNumber}</span><br><span class="infoTemplateContentRowLabel">Name: </span>' + '<span class="infoTemplateContentRowItem">${name}</span><br><span class="infoTemplateContentRowLabel">Severity: </span>' + '<span class="infoTemplateContentRowItem">${severity:severityDomainLookup}</span><br><span class="infoTemplateContentRowLabel">Type: </span>' + '<span class="infoTemplateContentRowItem">${requesttype:requestTypeDomainLookup}</span><br><span class="infoTemplateContentRowLabel">Comments: </span>' + '<span class="infoTemplateContentRowItem">${comment}</span>' } }; // app globals var app = {}; app.collapseMenuToggleButton = dom.byId('collapseToggleButton'); app.startEditAlert = dom.byId('startEditAlert'); app.sidebar = dom.byId('sidebar'); app.attributesModal = query('#attributesModal'); app.requestTypeSelect = query('#attributesModal [name="requesttype"]')[0]; // TODO: get these from the feature layer on load app.severityFieldDomainCodedValuesDict = { '0': 'General Nuisance', '1': 'Important To Resolve Soon', '2': 'Critical Issue' }; app.requestTypeFieldDomainCodedValuesDict = { '0': 'Abandoned Vehicle', '1': 'Animal Services', '2': 'Driveway Infraction', '3': 'Flooding', '4': 'Graffiti Removal', '5': 'Homeless Nuisance', '6': 'Illegal Dumping', '7': 'Parking Violation', '8': 'Plant/Tree Complaint', '9': 'Pothole Obstruction', '10': 'Roadway Danger', '11': 'Sidewalk Danger', '12': 'Streetlight Broken', '13': 'Street Sign Missing/Damaged', '14': 'Trash Removal', '15': 'Water Leak', '16': 'Yard Waste Removal' }; // NOTE: popup formatting functions must be globals window.severityDomainLookup = function (value, key, data){ return app.severityFieldDomainCodedValuesDict[value]; }; window.requestTypeDomainLookup = function (value, key, data){ return app.requestTypeFieldDomainCodedValuesDict[value]; }; window.formatPhoneNumber = function (value, key, data){ return value ? '<a href=\'tel:' + value + '\'>' + value + '</a>' : ''; }; // initialize the request type drop down var initAttributeForm = function() { var options = []; for (var key in app.requestTypeFieldDomainCodedValuesDict) { if (app.requestTypeFieldDomainCodedValuesDict.hasOwnProperty(key)) { options.push('<option value="' + key + '">' + app.requestTypeFieldDomainCodedValuesDict[key] + '</option>'); } } app.requestTypeSelect.innerHTML = options.join(''); }; // initialize the map and add the feature layer // and initialize map widgets var initMap = function() { app.map = BootstrapMap.create('map', config.mapOptions); var tiled = new ArcGISTiledMapServiceLayer("http://maps.decaturil.gov/arcgis/rest/services/Aerial_2014_Tiled/MapServer"); app.map.addLayer(tiled); // add operational layer var operationalLayer = new ArcGISDynamicMapServiceLayer("http://maps.decaturil.gov/arcgis/rest/services/Public/InternetVector/MapServer", { "opacity": 0.5 }); app.map.addLayer(operationalLayer); app.citizenRequestLayer = new FeatureLayer(config.citizenRequestLayerUrl, { mode: FeatureLayer.MODE_ONEDEMAND, infoTemplate: new InfoTemplate(config.infoTemplate), outFields: ['*'] }); app.map.addLayer(app.citizenRequestLayer); app.geocoder = new Geocoder({ map: app.map, autoComplete: true, arcgisGeocoder: { placeholder: 'Address or Location' }, 'class': 'geocoder' }, 'geocoder'); app.geocoder.startup(); // Begin geolocate button // add geolocate button to find the location of the current user app.map.on("load", function () { app.locateButton = new LocateButton({ map: app.map, highlightLocation: true, useTracking: true, enableHighAccuracy: true }, 'locateButton'); app.locateButton.clearOnTrackingStop = true; app.locateButton.startup(); app.locateButton.locate(); }); // End geolocate button app.legend = new Legend({ map: app.map, layerInfos: [{ title: 'Street Signs and Supports', layer: app.citizenRequestLayer }] }, 'legend'); app.legend.startup(); // TODO: other widgets, etc }; // hide nav dropdown on mobile var hideDropdownNav = function(e) { if (query('.navbar-collapse.in').length > 0) { e.stopPropagation(); app.collapseMenuToggleButton.click(); } }; // temporarily show alert when starting edits // and then start listening for a map click var startCaptureRequest = function(severity) { var listener; // NOTE: once user has clicked 'x' to dismiss // this alert, it will no longer show up domStyle.set(app.startEditAlert, 'display', ''); setTimeout(function() { domStyle.set(app.startEditAlert, 'display', 'none'); }, 3000); // save map point in app global and app.currentSeverity = severity; listener = app.map.on('click', function(e) { listener.remove(); // save map point in app global and // show form to collect incident report app.currentGeometry = e.mapPoint; app.attributesModal.modal('show'); }); }; var stopCaptureRequest = function() { app.currentSeverity = null; app.currentGeometry = null; }; // get attributes from form and submit var submitIncidentReport = function() { var attributes = { // TODO: not sure if this is needed requestreceived: null }; var currentDate = new Date(); var graphic; if (!app.currentSeverity || !app.currentGeometry) { return; } graphic = new Graphic(app.currentGeometry); attributes.severity = parseInt(app.currentSeverity, 10); query('#attributesModal input, #attributesModal select, #attributesModal textarea').forEach(function (formInput) { attributes[formInput.name] = formInput.value; }); attributes.requesttype = parseInt(attributes.requesttype, 10); attributes.requestdate = Date.UTC(currentDate.getUTCFullYear(), currentDate.getUTCMonth(), currentDate.getUTCDate(), currentDate.getUTCHours(), currentDate.getUTCMinutes(), currentDate.getUTCSeconds(), 0); graphic.setAttributes(attributes); stopCaptureRequest(); // console.log(attributes); app.citizenRequestLayer.applyEdits([graphic], null, null).then(function(response) { console.log(response); }); }; // wire up the DOM events var initEvents = function() { // listen for map clicks once severity is chosen query('.report-btn-group .dropdown-menu a').on('click', function(e) { e.preventDefault(); startCaptureRequest(domAttr.get(e.target, 'data-value')); }); // TODO show the feedback modal query('a[href="#feedback"]').on('click', function(e) { e.preventDefault(); query('#feedbackModal').modal('show'); }); // hide drop down nav after clicking on a link query('.navbar-collapse a').on('click', function(e) { hideDropdownNav(e); }); // change the basemap query('#basemapDropdown a').on('click', function(e) { var basemapName = domAttr.get(e.target, 'data-name'); if (basemapName && app.map) { app.map.setBasemap(basemapName); } }); // toggle the sidebar query('#sidebarToggleButton').on('click', function(e) { // make sure sidebar is same height as the map if (app.map.height) { domStyle.set(app.sidebar, 'height', app.map.height + 'px'); } domClass.toggle(window.document.body, 'sidebar-open'); hideDropdownNav(e); }); // submit or cancel request and hide modal query('#attributesModal .btn').on('click', function(e) { var target = e.target; if (target.innerText === 'Submit') { submitIncidentReport(); } app.attributesModal.modal('hide'); }); // submit or cancel request and hide modal query('#feedbackModal .btn').on('click', function(e) { // NOTE: this is not implemented in sample app query('#feedbackModal').modal('hide'); }); // clear current edit session globals app.attributesModal.on('hidden.bs.modal', stopCaptureRequest); }; // finally, start up the app! initAttributeForm(); initMap(); initEvents(); return app; });
Perfect! Thank you!