I have an info template that is just a single picture from a traffic camera that's inserted using the media type. Nothing fancy here. I want it to update the image every second but I cant seem to get the node for the image. I've used every kind of getElementsBy and querySelector and combination of the two that I can think of but the image eludes me. The best I have gotten is using what I have below which yields me an html collection with one object, the esri-popup-renderer__media-item, that has the image as a child but when I try to search it for the img tag I get nothing. I tried jQuery selection with $(".esri-popup-renderer__media-item img:first") but it returned the entire html document.
If there is an easier way to make this image update I'm willing to completely abandon this strategy.
view.popup.watch("visible", function (visible) {
if (visible === true) {
var media_item = document.getElementsByClassName("esri-popup-renderer__media-item");
console.log(media_item);
var image = media_item.getElementsByTagName("img");
console.log(image.src);
function updateImage() {
image.src = image.src.split("?")[0] + "?t=" + new Date().getTime();
}
var image_refresh_interval = setInterval(updateImage, 1000);
}else{
clearInterval(image_refresh_interval);
}
});
Solved! Go to Solution.
Chris,
Here is a full sample demonstrating that:
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"
/>
<title>Multiple popup elements - 4.4</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.4/esri/css/main.css">
<link rel="stylesheet" href="https://js.arcgis.com/4.4/dijit/themes/claro/claro.css">
<script src="https://js.arcgis.com/4.4/"></script>
<style>
html,
body,
#mapDiv {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"dojo/query",
"esri/core/watchUtils",
"dojo/domReady!"
], function(Map, MapView, FeatureLayer, query, watchUtils) {
// setup the map
var map = new Map({
basemap: "hybrid"
});
var view = new MapView({
container: "mapDiv",
map: map,
center: [-118.399400711028, 34.08713590709093],
zoom: 17,
// Since there are many elements, it is best to dock the popup so
// the elements display better rather than have to scroll through them all.
popup: {
dockEnabled: true,
dockOptions: {
buttonEnabled: false,
breakpoint: false
}
}
});
var featureLayer = new FeatureLayer({
url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/ArcGIS/rest/services/Beverly%20Hills%20Trees%20By%20Blo...",
popupTemplate: {
title: "<font color='#008000'>Beverly Hills trees by block",
// Set content elements in the order to display.
// The first element displayed here is the fieldInfos.
content: [{
// It is also possible to set the fieldInfos outside of the content
// directly in the popupTemplate. If no fieldInfos is specifically set
// in the content, it defaults to whatever may be set within the popupTemplate.
type: "fields",
fieldInfos: [{
fieldName: "Point_Count",
visible: false,
label: "Count of Points",
format: {
places: 0,
digitSeparator: true
}
}, {
fieldName: "relationships/0/Point_Count_COMMON",
visible: true,
label: "Sum of species tree count",
format: {
places: 0,
digitSeparator: true
},
statisticType: "sum"
}, {
fieldName: "relationships/0/COMMON",
visible: false,
label: "Common Name"
}, {
fieldName: "BLOCKCE10",
visible: true,
label: "Block"
}]
}, {
// You can also set a descriptive text element. This element
// uses an attribute from the featurelayer which displays a
// sentence giving the total amount of trees value within a
// specified census block. Text elements can only be set within the content.
type: "text",
text: "There are {Point_Count} trees within census block {BLOCKCE10}"
}, {
// You can set a media element within the popup as well. This
// can be either an image or a chart. You specify this within
// the mediaInfos. The following creates a pie chart in addition
// to two separate images. The chart is also set up to work with
// related tables. Similar to text elements, media can only be set within the content.
type: "media",
mediaInfos: [{
title: "<b>Welcome to Beverly Hills</b>",
type: "image",
value: {
sourceURL: "https://www.beverlyhills.org/cbhfiles/storage/files/13203374121770673849/122707_039r_final.jpg"
}
}, {
title: "<b>Palm tree lined street</b>",
type: "image",
value: {
sourceURL: "https://cdn.loc.gov/service/pnp/highsm/21600/21679r.jpg"
}
}]
}, {
// You can set a attachment element(s) within the popup as well.
// Similar to text and media elements, attachments can only be set
// within the content. Any attachmentInfos associated with the feature
// will be listed in the popup.
type: "attachments"
}]
},
outFields: ["*"]
});
map.add(featureLayer);
view.popup.watch("visible", function (visible) {
if (visible === true) {
watchUtils.whenNot(view.popup.viewModel, "pendingPromisesCount", function(cnt){
setTimeout(function(){
var media_item = query(".esri-popup-renderer__media-item > img");
if(media_item[0]){
var image = media_item[0];
console.log(image.src);
function updateImage() {
image.src = image.src.split("?")[0] + "?t=" + new Date().getTime();
}
var image_refresh_interval = setInterval(updateImage, 1000);
}
}, 200);
});
}else{
clearInterval(image_refresh_interval);
}
});
});
</script>
</head>
<body>
<div id="mapDiv"></div>
</body>
</html>
Chris,
Here is a full sample demonstrating that:
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"
/>
<title>Multiple popup elements - 4.4</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.4/esri/css/main.css">
<link rel="stylesheet" href="https://js.arcgis.com/4.4/dijit/themes/claro/claro.css">
<script src="https://js.arcgis.com/4.4/"></script>
<style>
html,
body,
#mapDiv {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"dojo/query",
"esri/core/watchUtils",
"dojo/domReady!"
], function(Map, MapView, FeatureLayer, query, watchUtils) {
// setup the map
var map = new Map({
basemap: "hybrid"
});
var view = new MapView({
container: "mapDiv",
map: map,
center: [-118.399400711028, 34.08713590709093],
zoom: 17,
// Since there are many elements, it is best to dock the popup so
// the elements display better rather than have to scroll through them all.
popup: {
dockEnabled: true,
dockOptions: {
buttonEnabled: false,
breakpoint: false
}
}
});
var featureLayer = new FeatureLayer({
url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/ArcGIS/rest/services/Beverly%20Hills%20Trees%20By%20Blo...",
popupTemplate: {
title: "<font color='#008000'>Beverly Hills trees by block",
// Set content elements in the order to display.
// The first element displayed here is the fieldInfos.
content: [{
// It is also possible to set the fieldInfos outside of the content
// directly in the popupTemplate. If no fieldInfos is specifically set
// in the content, it defaults to whatever may be set within the popupTemplate.
type: "fields",
fieldInfos: [{
fieldName: "Point_Count",
visible: false,
label: "Count of Points",
format: {
places: 0,
digitSeparator: true
}
}, {
fieldName: "relationships/0/Point_Count_COMMON",
visible: true,
label: "Sum of species tree count",
format: {
places: 0,
digitSeparator: true
},
statisticType: "sum"
}, {
fieldName: "relationships/0/COMMON",
visible: false,
label: "Common Name"
}, {
fieldName: "BLOCKCE10",
visible: true,
label: "Block"
}]
}, {
// You can also set a descriptive text element. This element
// uses an attribute from the featurelayer which displays a
// sentence giving the total amount of trees value within a
// specified census block. Text elements can only be set within the content.
type: "text",
text: "There are {Point_Count} trees within census block {BLOCKCE10}"
}, {
// You can set a media element within the popup as well. This
// can be either an image or a chart. You specify this within
// the mediaInfos. The following creates a pie chart in addition
// to two separate images. The chart is also set up to work with
// related tables. Similar to text elements, media can only be set within the content.
type: "media",
mediaInfos: [{
title: "<b>Welcome to Beverly Hills</b>",
type: "image",
value: {
sourceURL: "https://www.beverlyhills.org/cbhfiles/storage/files/13203374121770673849/122707_039r_final.jpg"
}
}, {
title: "<b>Palm tree lined street</b>",
type: "image",
value: {
sourceURL: "https://cdn.loc.gov/service/pnp/highsm/21600/21679r.jpg"
}
}]
}, {
// You can set a attachment element(s) within the popup as well.
// Similar to text and media elements, attachments can only be set
// within the content. Any attachmentInfos associated with the feature
// will be listed in the popup.
type: "attachments"
}]
},
outFields: ["*"]
});
map.add(featureLayer);
view.popup.watch("visible", function (visible) {
if (visible === true) {
watchUtils.whenNot(view.popup.viewModel, "pendingPromisesCount", function(cnt){
setTimeout(function(){
var media_item = query(".esri-popup-renderer__media-item > img");
if(media_item[0]){
var image = media_item[0];
console.log(image.src);
function updateImage() {
image.src = image.src.split("?")[0] + "?t=" + new Date().getTime();
}
var image_refresh_interval = setInterval(updateImage, 1000);
}
}, 200);
});
}else{
clearInterval(image_refresh_interval);
}
});
});
</script>
</head>
<body>
<div id="mapDiv"></div>
</body>
</html>
Worked like a charm. Thanks Robert. The current cameras map is a Google Maps mashup in a 3rd party interface. Our Traffic Eng department wanted me to make them a simple esri based map to replace it that they can embed.
Spoke too soon. I cant stop the updates now even if I close the popup. The close button wouldn't work initially because the scope of image_refresh_interval was limited. I hitched the function in setTimeout and it fixed that but the app keeps polling the image URL for every feature you click even after closing the popup. I attached the whole page below. It might still be a scope problem.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="https://js.arcgis.com/4.4/esri/css/main.css">
<link rel="stylesheet" href="https://js.arcgis.com/4.4/dijit/themes/claro/claro.css">
<script src="https://js.arcgis.com/4.4/"></script>
<style>
html,
body,
#mapDiv {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/WebMap",
"esri/layers/FeatureLayer",
"dojo/query",
"esri/core/watchUtils",
"dojo/_base/lang",
"dojo/domReady!"
], function (
Map,
MapView,
WebMap,
FeatureLayer,
query,
watchUtils,
lang
) {
var cameras = new FeatureLayer({
url: "http://gis.baycountyfl.gov/arcgis/rest/services/TrafficCameras/MapServer/0",
outFields: ["*"],
popupTemplate: {
title: "{Location} {Camera}",
content: [{
type: "media",
mediaInfos: [{
title: "",
type: "image",
value: {
sourceURL: "http://tmc.baycountyfl.gov/CameraImages/Camera{Camera}.jpg?t=" + new Date().getTime()
}
}]
}]
}
}),
mapobj = new Map({
basemap: "streets",
layers: [cameras]
}),
view = new MapView({
map: mapobj,
container: "mapDiv",
center: [-85.726147, 30.183486],
zoom: 14
});
view.popup.viewModel.actions = [];
view.popup.watch("visible", function (visible) {
if (visible === true) {
watchUtils.whenNot(view.popup.viewModel, "pendingPromisesCount", function (cnt) {
setTimeout(lang.hitch(this, function () {
var media_item = query(".esri-popup-renderer__media-item > img");
if (media_item[0]) {
var image = media_item[0];
console.log(image.src);
function updateImage() {
image.src = image.src.split("?")[0] + "?t=" + new Date().getTime();
}
this.image_refresh_interval = setInterval(updateImage, 1000);
}
}, 200));
});
} else {
clearInterval(this.image_refresh_interval);
}
});
});
</script>
</head>
<body>
<div id="mapDiv"></div>
</body>
</html>
Chris,
Well here is that issue fixed:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="https://js.arcgis.com/4.4/esri/css/main.css">
<link rel="stylesheet" href="https://js.arcgis.com/4.4/dijit/themes/claro/claro.css">
<script src="https://js.arcgis.com/4.4/"></script>
<style>
html,
body,
#mapDiv {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
<script>
var image_refresh_interval;
require([
"esri/Map",
"esri/views/MapView",
"esri/WebMap",
"esri/layers/FeatureLayer",
"dojo/query",
"esri/core/watchUtils",
"dojo/_base/lang",
"dojo/domReady!"
], function(
Map,
MapView,
WebMap,
FeatureLayer,
query,
watchUtils,
lang
) {
var cameras = new FeatureLayer({
url: "http://gis.baycountyfl.gov/arcgis/rest/services/TrafficCameras/MapServer/0",
outFields: ["*"],
popupTemplate: {
title: "{Location} {Camera}",
content: [{
type: "media",
mediaInfos: [{
title: "",
type: "image",
value: {
sourceURL: "http://tmc.baycountyfl.gov/CameraImages/Camera{Camera}.jpg?t=" + new Date().getTime()
}
}]
}]
}
}),
mapobj = new Map({
basemap: "streets",
layers: [cameras]
}),
view = new MapView({
map: mapobj,
container: "mapDiv",
center: [-85.726147, 30.183486],
zoom: 14
});
view.popup.viewModel.actions = [];
view.popup.watch("visible", function(visible) {
if (visible === true) {
watchUtils.whenNot(view.popup.viewModel, "pendingPromisesCount", function(cnt) {
setTimeout(lang.hitch(this, function() {
var media_item = query(".esri-popup-renderer__media-item > img");
if (media_item[0]) {
var image = media_item[0];
function updateImage() {
image.src = image.src.split("?")[0] + "?t=" + new Date().getTime();
console.log(image.src);
}
if(!image_refresh_interval){
image_refresh_interval = setInterval(updateImage, 1000);
}
}
}, 200));
});
} else {
clearInterval(image_refresh_interval);
image_refresh_interval = null;
}
});
});
</script>
</head>
<body>
<div id="mapDiv"></div>
</body>
</html>