ArcGIS Online WebMap authentication timeout - esri

I have an ArcGIS Online public account and add WebMap to my website.
My ArcGIS Online WebMap looks like this ESRI's sample: LINK
And I am trying to add my WebMap to my website like this ESRI's reference page. You will see there is a map in the center of page: LINK
My WebMap is displayed on my webpage well. When I access my webpage, my WebMap asks my ID and Password. If I entered it, then it shows my map.
However, my question is, if I moved to different page and then come back to map page, it asks again. Is it possible to set a timeout so I don't have to sign in everytime I access the page?

The reason I asked this question is that to find out if there were a way to reduce my code simple and work on code in front-end.
I've researched OAuth that ESRI provided and I ended up using esri/IdentityManager. There were references to use esri/IdentityManager package; however there were no sample code to using it with personal WebMap which used arcgisUtils.createMap
So here is sample code that I worked:
require([
"dojo/parser",
"dojo/ready",
"dijit/layout/BorderContainer",
"dijit/layout/ContentPane",
"dojo/dom",
"esri/map",
"esri/urlUtils",
"esri/arcgis/utils",
"esri/dijit/Legend",
"esri/dijit/LayerList",
"esri/graphic",
"esri/symbols/PictureMarkerSymbol",
"esri/symbols/TextSymbol",
"esri/geometry/Point",
"esri/dijit/Scalebar",
"dojo/_base/unload",
"dojo/cookie",
"dojo/json",
"esri/config",
"esri/IdentityManager",
"esri/layers/FeatureLayer",
"dojo/domReady!"
], function (
parser,
ready,
BorderContainer,
ContentPane,
dom,
Map,
urlUtils,
arcgisUtils,
Legend,
LayerList,
Graphic,
PictureMarkerSymbol,
TextSymbol,
Point,
Scalebar,
baseUnload,
cookie,
JSON,
esriConfig,
esriId,
FeatureLayer
) {
var mapOptions = {
basemap: "topo",
autoResize: true, // see http://forums.arcgis.com/threads/90825-Mobile-Sample-Fail
center: [currentPosition.lng, currentPosition.lat],
zoom: 15,
logo: false
};
// cookie/local storage name
var cred = "esri_jsapi_id_manager_data";
// store credentials/serverInfos before the page unloads
baseUnload.addOnUnload(storeCredentials);
// look for credentials in local storage
loadCredentials();
parser.parse();
esriConfig.defaults.io.proxyUrl = "/proxy/";
//Create a map based on an ArcGIS Online web map id
arcgisUtils.createMap('PUT-YOUR-ESRI-KEY', "esriMapCanvas", { mapOptions: mapOptions }).then(function (response) {
var map = response.map;
// add a blue marker
var picSymbol = new PictureMarkerSymbol(
'http://static.arcgis.com/images/Symbols/Shapes/RedPin1LargeB.png', 50, 50);
var geometryPoint = new Point('SET YOUR LAT', 'SET YOUR LONG');
map.graphics.add(new Graphic(geometryPoint, picSymbol));
//add the scalebar
var scalebar = new Scalebar({
map: map,
scalebarUnit: "english"
});
//add the map layers
var mapLayers = new LayerList({
map: map,
layers: arcgisUtils.getLayerList(response)
}, "esriLayerList");
mapLayers.startup();
//add the legend. Note that we use the utility method getLegendLayers to get
//the layers to display in the legend from the createMap response.
var legendLayers = arcgisUtils.getLegendLayers(response);
var legendDijit = new Legend({
map: map,
layerInfos: legendLayers
}, "esriLegend");
legendDijit.startup();
});
function storeCredentials() {
// make sure there are some credentials to persist
if (esriId.credentials.length === 0) {
return;
}
// serialize the ID manager state to a string
var idString = JSON.stringify(esriId.toJson());
// store it client side
if (supports_local_storage()) {
// use local storage
window.localStorage.setItem(cred, idString);
// console.log("wrote to local storage");
}
else {
// use a cookie
cookie(cred, idString, { expires: 1 });
// console.log("wrote a cookie :-/");
}
}
function supports_local_storage() {
try {
return "localStorage" in window && window["localStorage"] !== null;
} catch (e) {
return false;
}
}
function loadCredentials() {
var idJson, idObject;
if (supports_local_storage()) {
// read from local storage
idJson = window.localStorage.getItem(cred);
}
else {
// read from a cookie
idJson = cookie(cred);
}
if (idJson && idJson != "null" && idJson.length > 4) {
idObject = JSON.parse(idJson);
esriId.initialize(idObject);
}
else {
// console.log("didn't find anything to load :(");
}
}
});

Related

How can i add and remove the dynamic marker on esri map javascript api?

How can I add and remove the dynamic marker on esri map using the javascript api? When I add the marker in the graphics layer, it's added but how can I remove it and add the new marker by another latitude longitude?
This is my code so far;
require(
["esri/map",
"esri/graphic",
"esri/symbols/PictureMarkerSymbol",
"esri/symbols/TextSymbol",
"esri/geometry/Point",
"esri/SpatialReference",
"esri/tasks/ProjectParameters",
"esri/tasks/GeometryService",
"dojo/dom",
"dojo/on",
"esri/dijit/HomeButton",
"dojo/domReady!"
],
function setupmap(Map, Graphic, PictureMarkerSymbol, TextSymbol, Point, SpatialReference, ProjectParameters, GeometryService, dom, on, HomeButton) {
var map = new Map("map-container", {
center: [83.0179802, 25.32327],
zoom: 13,
basemap: "streets"
});
map.graphics.clear();
map.on("load", function (evt) {
var home = new HomeButton({map: map}, "HomeButton");
home.startup();
picSymbol = new PictureMarkerSymbol(iconType, 20, 20);
$.each(detailsJSON, function (location, lstNodes) {
var locArr = location.split("--");
var latitude=locArr[0];
var longitude=locArr[1];
var geometryPoint = new Point(longitude, latitude,new SpatialReference(4326));
map.graphics.add(new Graphic(geometryPoint, picSymbol));
});
});
}
);
You can store a reference to the Graphic object you're adding and later remove it using the remove(graphic) method.
let graphic = new Graphic(geometryPoint, picSymbol);
map.graphics.add(graphic);
...
map.graphics.remove(graphic);
You can also remove all graphics from the layer using method removeAll().
See the arcgis-js-api reference for further info.
To make your component more stateless you can use the attributes collection of the Graphic to store a tag (or an Id or similar) and remove the item based on this value.
When adding;
let graphic = new Graphic(geometryPoint, picSymbol);
graphic.attributes = { "tag": "toBeRemovedLater" };
map.graphics.add(graphic);
When removing;
angular.forEach(map.graphics.graphics, (graphic: any) => {
if (graphic.attributes && graphic.attributes.tag == "toBeRemovedLater")
map.graphics.remove(graphic);
});
You can use Sketch Widget that simplifies the process of adding and updating graphics.
const sketch = new Sketch({
availableCreateTools: ['point'],
layer: graphicsLayer,
view,
});
view.ui.add(sketch, 'top-right');

Not able to view ArcGIS non shared Scene Layer with BuildingSceneLayer even though I have signed in and the file is from my Portal

I am viewing BuildingSceneLayer using ArcGIS Javascript API.
I want to display a SceneLayer which is not shared as public in the ArcGIS portal.
When I try viewing it I get
Sceenshot
When I view in Codepen
https://codepen.io/arnofiva/pen/c410babb5384945a12b1d8206ebe27ce?editors=1010
require([
"esri/Map",
"esri/views/SceneView",
"esri/layers/BuildingSceneLayer"
], function(Map, SceneView, BuildingSceneLayer) {
// Create Map
var map = new Map({
basemap: "terrain",
ground: "world-elevation"
});
// Create the SceneView
var view = new SceneView({
container: "viewDiv",
map: map,
camera: {
position: [-74.0338, 40.6913, 707],
tilt: 81,
heading: 50
}
});
// Create SceneLayer and add to the map
var sceneLayer = new BuildingSceneLayer({
portalItem: {
id: "e7bf9f676ed64937bff9f44c84fdae2b"
},
popupEnabled: false
});
map.add(sceneLayer);
sceneLayer.when().then(function() {
view.goTo(sceneLayer.fullExtent);
});
});
I get a popup for logging in. How do I enable that in my code?

How can I show automatically registered users geolocation in a global map with google maps api as they register?

I'm trying to show all users geolocation from a web site in a map. Through google maps API documentation I've got a way to show my location as user. But, how I make it for show all geolocation from the registered people on the website?
<div id="map"></div>
<script>
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 6
});
var infoWindow = new google.maps.InfoWindow({map: map});
// Try HTML5 geolocation.
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
infoWindow.setPosition(pos);
infoWindow.setContent('Location found.');
map.setCenter(pos);
}, function() {
handleLocationError(true, infoWindow, map.getCenter());
});
} else {
// Browser doesn't support Geolocation
handleLocationError(false, infoWindow, map.getCenter());
}
}
function handleLocationError(browserHasGeolocation, infoWindow, pos) {
infoWindow.setPosition(pos);
infoWindow.setContent(browserHasGeolocation ?
'Error: The Geolocation service failed.' :
'Error: Your browser doesn\'t support geolocation.');
}
</script>
Create objects of the google.maps.Marker() type, set a position using the setPosition function of it and add it to your map using the setMap function.
Example (Lat/Lng is the center of Germany - insert your users coordinates there):
var marker=new google.maps.Marker();
// use your registered user coordinates here
marker.setPosition(new google.maps.LatLng(48.14544, 8.19208));
marker.setMap(map);
Additionally you can use boundaries to make your map autozoom to get every marker visible:
var bounds=new google.maps.LatLngBounds();
...
bounds.extend(marker.getPosition());
...
map.fitBounds(bounds);

Dojo _TemplatedMixin: changing templateString

How do I change the template of a widget, using mixins dijit/_TemplatedMixin and dijit/_WidgetsInTemplateMixin, at a later time (not in the constructor)?
My scenario is that the widget must make a call to the server to get data, and the callback function will then merge the data with a template file and then the resulting template should be used for the templateString. The widget should update its contents at this point.
Setting the templateString and calling buildRendering() has no effect.
Here is a simplified version of my code:
define([
"dojo/_base/declare",
"dojo/_base/lang",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
],
function(declare, lang, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin) {
return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
constructor: function(id) {
this.id = id;
this.templateString = "<div>Loading...</div>";
//use xhr to call REST service to get data.
//dataLoadedCallback is executed with response data
...
},
dataLoadedCallback : function(data) {
this.destroyRendering();
//render a templateString using the data response from the rest call
this.templateString = "<div>Data is loaded. Name:" + data.name + "</div>"
this.buildRendering();
},
});
});
You cannot do such thing. The template is parsed only once before postCreate method.
However there is few things you can do:
Create a non-ui widget which will do the XHR call. When this non-ui widget get the XHR response it creates the UI widget with the correct templateString
Or use dojo/dom-construct. It contains a toDom method which you can use for converting your string into nodes. Then you can append that to the widget.
Note: this will not parse any data-dojo attributes
You could also directly inject the received templateString into the widget domNode:
dataLoadedCallback : function(data) {
this.domNode.innerHTML = "<div>Data is loaded. Name:" + data.name + "</div>";
//you might be able to parse the content (if you have subwidgets) using dojo/parse
},
Last but not least, here is a util I wrote for my self. It allow to parse any templateString at any time (like dojo does on widget creation)
define([
'dojo/dom-construct',
'dojo/string',
'dijit/_AttachMixin',
'dijit/_TemplatedMixin'
], function(domConstruct, string,
_AttachMixin, _TemplatedMixin) {
// summary:
// provide an utility to parse a template a runtime (and create attach point, atach events, etc...)
// Copyright: Benjamin Santalucia
var GET_ATTRIBUTE_FUNCTION = function(n, p) { return n.getAttribute(p); },
_TemplateParserMixin = function() {};
_TemplateParserMixin.prototype = {
parseTemplate: function(template, data, container, position, transformer) {
// summary:
// parse the template exactly as dojo will nativly do with a templateString
if(this._attachPoints === undefined) {
this._attachPoints = [];
}
if(this._attachEvents === undefined) {
this._attachEvents = [];
}
var nodes,
x,
len,
newTemplate = string.substitute(template, data, transformer),
node = domConstruct.toDom(_TemplatedMixin.prototype._stringRepl.call(this, newTemplate));
if(node.nodeName === '#document-fragment') {
node = node.firstChild;
}
//parse all nodes and create attach points and attach events
nodes = node.getElementsByTagName('*');
len = nodes.length;
for(x = -1; x < len; x++) {
_AttachMixin.prototype._processTemplateNode.call(this, x < 0 ? node : nodes[x], GET_ATTRIBUTE_FUNCTION, _AttachMixin.prototype._attach);
}
if(container) {
domConstruct.place(node, container, position);
}
return node;
}
};
return _TemplateParserMixin;
});
Usage is:
returnedNode = w.parseTemplate(newTemplateString, {
templatePlaceHolderName: 'foo' //for teplate with placeholders like ${templatePlaceHolderName}
}, domNodeToInsertIn, 'only'); //last parameter is same as dojo/dom-construct::place() >> last, first, before, after, only

Reverse Geocoding With Dynamic Form

I've been trying to find a way to use the 'Reverse Geocoding' service with the Latitude and Longitude co-ordinates coming from two text boxes on my HTML form, and I must admit I'm not really sure what I need to do.
I have managed to do this with the 'Geocode' service (see code below), but I just wondered whether someone may be able to point me in the right direction of how I could adapt the 'Geocode' javascript I have to the 'Reverse Geocoging' service.
(function Geocode() {
// This is defining the global variables
var map, geocoder, myMarker;
window.onload = function() {
//This is creating the map with the desired options
var myOptions = {
zoom: 5,
center: new google.maps.LatLng(55.378051,-3.435973),
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position: google.maps.ControlPosition.BOTTOM
},
navigationControl: true,
navigationControlOptions: {
style: google.maps.NavigationControlStyle.ZOOM_PAN,
position: google.maps.ControlPosition.TOP_RIGHT
},
scaleControl: true,
scaleControlOptions: {
position: google.maps.ControlPosition.BOTTOM_LEFT
}
};
map = new google.maps.Map(document.getElementById('map'), myOptions);
// This is making the link with the 'Search For Location' HTML form
var form = document.getElementById('SearchForLocationForm');
// This is catching the forms submit event
form.onsubmit = function() {
// This is getting the Address from the HTML forms 'Address' text box
var address = document.getElementById('GeocodeAddress').value;
// This is making the Geocoder call
getCoordinates(address);
// This is preventing the form from doing a page submit
return false;
}
}
// This creates the function that will return the coordinates for the address
function getCoordinates(address) {
// This checks to see if there is already a geocoded object. If not, it creates one
if(!geocoder) {
geocoder = new google.maps.Geocoder();
}
// This is creating a GeocoderRequest object
var geocoderRequest = {
address: address
}
// This is making the Geocode request
geocoder.geocode(geocoderRequest, function(results, status) {
// This checks to see if the Status is 'OK 'before proceeding
if (status == google.maps.GeocoderStatus.OK) {
// This centres the map on the returned location
map.setCenter(results[0].geometry.location);
// This creates a new marker and adds it to the map
var myMarker = new google.maps.Marker({
map: map,
zoom: 12,
position: results[0].geometry.location,
draggable:true
});
//This fills out the 'Latitude' and 'Longitude' text boxes on the HTML form
document.getElementById('Latitude').value= results[0].geometry.location.lat();
document.getElementById('Longitude').value= results[0].geometry.location.lng();
//This allows the marker to be draggable and tells the 'Latitude' and 'Longitude' text boxes on the HTML form to update with the new co-ordinates as the marker is dragged
google.maps.event.addListener(
myMarker,
'dragend',
function() {
document.getElementById('Latitude').value = myMarker.position.lat();
document.getElementById('Longitude').value = myMarker.position.lng();
var point = myMarker.getPosition();
map.panTo(point);
}
);
}
}
)
}
})();
UPDATE
Firstly, many thanks for the code you kindly posted and the suggestion to go and have a look at the Google documentation.
From what you suggested, and from what I took from the additional documentation I came up with the following. However, when I click my submit button nothing happens, almost as if there is no command attached to it. I don't receive any error messages and I've checked to make sure that I've linked the code to the correct fieldnames and all seems ok. I just wondered whether it would be at all possible if you, or indeed anyone else, could take a look at it please to tell me where I've gone wrong.
Many thanks and kind regards
(function ReverseGeocode() {
var form, geocoderRequest, latlng, myMarker, point;
window.onload = function() {
//This is creating the map with the desired options
var myOptions = {
zoom: 5,
center: new google.maps.LatLng(55.378051,-3.435973),
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position: google.maps.ControlPosition.BOTTOM
},
navigationControl: true,
navigationControlOptions: {
style: google.maps.NavigationControlStyle.ZOOM_PAN,
position: google.maps.ControlPosition.TOP_RIGHT
},
scaleControl: true,
scaleControlOptions: {
position: google.maps.ControlPosition.BOTTOM_LEFT
}
};
map = new google.maps.Map(document.getElementById('map'), myOptions);
var latlng = new google.maps.LatLng('Latitude', 'Longitude');
// This is making the Geocode request
geocoder.geocode({'LatLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
map.setZoom(11);
var myMarker = new google.maps.Marker({
position: results[0].geometry.location,
map: map
});
//This fills out the 'Address' text boxe on the HTML form
document.getElementById('Address').value= results[0].geometry.location.latlng();
var point = myMarker.getPosition();
map.panTo(point);
}
}
}
)}})
Once you have the latitude and longitude from your form, you do something like this (using your above code as a starting point, for the sake of clarity):
var latlng = new google.maps.LatLng(latitudeFromForm,longitudeFromForm);
// This is creating a GeocoderRequest object
var geocoderRequest = {
'latlng':latlng
}
// This is making the Geocode request
geocoder.geocode(geocoderRequest, function(results, status) {
// This checks to see if the Status is 'OK 'before proceeding
if (status == google.maps.GeocoderStatus.OK) {
// Do stuff with the result here
}
If you haven't read it yet, you may want to read the Reverse Geocoding section of http://code.google.com/apis/maps/documentation/javascript/services.html#ReverseGeocoding.