I am creating an application using JP 4.12 and I would like for the application to point to an URL within the attribute table of a feature layer when a user clicks on a point feature. I came across the following post and I tried the following code but it does not seem to work.
In the SpecificAttribute, I have placed the name of the field that contains the URLs.
Any help would be greatly appreciated!
Solved! Go to Solution.
It is your lucky day - I needed a break from what I was doing, and I learned some things along the way.
If you use this version (combination of the esri sample and your code), you'll notice there's a console.log output of the passport office name on map click. Line 205. You can handle the rest I think.
A couple problems with your original. I disabled popups on fLayer. Consolidated the event handling because you have 3 views. Complicated! Also created a click handler!
There is a syntax highlighter in "More... "
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport"
content="initial-scale=1, maximum-scale=1,user-scalable=no" />
<title>{PROTOTYPE} Passport Agency Map - JavaScript 4.12</title>
<!--reference the JavaScript 4.12-->
<link rel="stylesheet"
href="https://js.arcgis.com/4.12/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.12/"></script>
<style>
html,
body,
#mainviewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#hiViewDiv {
padding: 0;
margin: 0;
height: 135px;
width: 200px;
background-color: rgba(255, 255, 255, 0.9);
border-style: solid;
}
#prViewDiv {
padding: 0;
margin: 0;
height: 135px;
width: 200px;
background-color: rgba(255, 255, 255, 0.9);
border-style: solid;
}
/*Style for feature hover */
.esri-feature {
letter-spacing: 0em;
line-height: 1.55rem;
font-feature-settings: "liga"1, "calt"0;
background: #fff;
padding: 1em;
}
</style>
<script>
require([
"esri/Map",
"esri/widgets/Home",
"esri/widgets/BasemapToggle",
"esri/layers/FeatureLayer",
"esri/views/MapView",
"esri/widgets/Feature",
"esri/widgets/Track",
"esri/Graphic"
], function (Map, Home, BasemapToggle, FeatureLayer, MapView, Feature, Track, Graphic) {
var fLayer = new FeatureLayer({
portalItem: {
id: "5710089ef1374c6d939ebee954c8b15c" //Portal ID number
},
popupEnabled: false,
outFields: ["*"]
});
var map = new Map({
basemap: "streets-navigation-vector",
layers: [fLayer]
});
//Contiguous USA Main Map
var mainView = new MapView({
container: "mainviewDiv",
map: map,
extent: {
spatialReference: {
latestWkid: 3857,
wkid: 102100
},
xmin: -14513000, //bounding box for the inital load of the application
ymin: 2887000,
xmax: -7390000,
ymax: 6326000
},
constraints: {
minScale: 39911104 //user cannot zoom out past this scale
}
});
// Hawaii inset map
var hiView = new MapView({
container: "hiViewDiv",
map: map,
extent: {
xmin: -17834000,
ymin: 2111000,
xmax: -17173000,
ymax: 2573000,
spatialReference: {
wkid: 102100
}
},
spatialReference: {
wkid: 102100
},
ui: {
components: []
}
});
mainView.ui.add("hiViewDiv", "bottom-left");
// Puerto Rico inset map
var prView = new MapView({
container: "prViewDiv",
map: map,
extent: {
xmin: -7887000,
ymin: 1924000,
xmax: -6957000,
ymax: 2257000,
spatialReference: {
wkid: 102100
}
},
spatialReference: {
wkid: 102100
},
ui: {
components: []
}
});
mainView.ui.add("prViewDiv", "bottom-right");
//adding a home button
var homeBtn = new Home({
view: mainView
}); // end of Home Button
mainView.ui.add(homeBtn, "top-left"); //adding a home button to the top left under the zoom in/out
var toggle = new BasemapToggle({
view: mainView,
nextBasemap: "satellite"
}); //end of BasemapToggle
mainView.ui.add(toggle, "top-left"); //adding basemap toggle to the top right
var graphic = {
popupTemplate: {
content: "Mouse over passport icons to show details..."
}
};
// Provide graphic to a new instance of a Feature widget
var feature = new Feature({
graphic: graphic,
map: mainView.map,
spatialReference: mainView.spatialReference
});
mainView.ui.add(feature, "top-right"); //adding feature hover widget to top right
mainView.when().then(function () {
// Create a default graphic for when the application starts
return fLayer.when();
}).then(function (layer) {
return mainView.whenLayerView(layer);
}).then(setupLayerEvent);
prView
.when()
.then(function () {
return fLayer.when();
})
.then(function (layer) {
return prView.whenLayerView(layer);
})
.then(setupLayerEvent);
hiView
.when()
.then(function () {
return fLayer.when();
})
.then(function (layer) {
return hiView.whenLayerView(layer);
})
.then(setupLayerEvent);
function setupLayerEvent(layerView) {
layerView.view.on("pointer-move", eventHandler);
layerView.view.on("pointer-down", eventHandler);
layerView.view.on("click", clickHandler);
function eventHandler(event) {
layerView.view.hitTest(event).then(getGraphics);
}
function clickHandler(event) {
layerView.view.hitTest(event).then(function (response) {
if (response.results.length) {
const graphic = response.results.filter(function (result) {
return result.graphic.layer === fLayer;
})[0].graphic;
const attributes = graphic.attributes;
console.log(attributes.Name); //continue here.
} else {
}
});
}
let highlight, currentId;
function getGraphics(response) {
if (response.results.length) {
const graphic = response.results.filter(function (result) {
return result.graphic.layer === fLayer;
})[0].graphic;
const attributes = graphic.attributes;
const URL = attributes.Link;
const id = attributes.FID;
if (
highlight && currentId !== id
) {
highlight.remove();
highlight = null;
return;
}
// highlight all features belonging to the same hurricane as the feature
// returned from the hitTest
const query = layerView.layer.createQuery();
query.where = "FID = " + id;
layerView.queryObjectIds(query).then(function (ids) {
highlight = layerView.highlight(ids);
feature.graphic = graphic;
currentId = id;
});
} else {
// remove the highlight if no features are
// returned from the hitTest
highlight.remove();
highlight = null;
}
}
}
}); // end of Main function
</script>
</head>
<body>
<div id="mainviewDiv" class="esri-widget"></div>
<div id="hiViewDiv" class="esri-widget"></div>
<div id="prViewDiv" class="esri-widget"></div>
</body>
</html>
Does the event fire? (add console.log entry) or is it the popup itself not working?
The pop-up works and I can access the external website if I click on the icon and then click on the link within the pop-up. I would like to skip the pop-up altogether and when I click on the icon, it goes straight to the external website. I have a feature hover for accessing the info in the pop-up. Hope that helps.
There's a couple things going on. Popups need to be disabled on view/layer, or manually handled. Also FeatureLayer doesn't have a click event.
This sample might help: https://developers.arcgis.com/javascript/latest/sample-code/view-hittest/index.html
In this sample, the view events are handled manually. It has a lot more going on, but hopefully the event flow can help.
In codepen, after line 139 - I added window.open("http://google.ca");
and on feature click (not mouse over) it opens a window to google.
Here is the code below in full. I am not sure how to copy/paste with the line numbers on the side like in other posts, so sorry if it looks confusing. Would the click event go in the mainView.WhenLayerView function?
It is your lucky day - I needed a break from what I was doing, and I learned some things along the way.
If you use this version (combination of the esri sample and your code), you'll notice there's a console.log output of the passport office name on map click. Line 205. You can handle the rest I think.
A couple problems with your original. I disabled popups on fLayer. Consolidated the event handling because you have 3 views. Complicated! Also created a click handler!
There is a syntax highlighter in "More... "
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport"
content="initial-scale=1, maximum-scale=1,user-scalable=no" />
<title>{PROTOTYPE} Passport Agency Map - JavaScript 4.12</title>
<!--reference the JavaScript 4.12-->
<link rel="stylesheet"
href="https://js.arcgis.com/4.12/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.12/"></script>
<style>
html,
body,
#mainviewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#hiViewDiv {
padding: 0;
margin: 0;
height: 135px;
width: 200px;
background-color: rgba(255, 255, 255, 0.9);
border-style: solid;
}
#prViewDiv {
padding: 0;
margin: 0;
height: 135px;
width: 200px;
background-color: rgba(255, 255, 255, 0.9);
border-style: solid;
}
/*Style for feature hover */
.esri-feature {
letter-spacing: 0em;
line-height: 1.55rem;
font-feature-settings: "liga"1, "calt"0;
background: #fff;
padding: 1em;
}
</style>
<script>
require([
"esri/Map",
"esri/widgets/Home",
"esri/widgets/BasemapToggle",
"esri/layers/FeatureLayer",
"esri/views/MapView",
"esri/widgets/Feature",
"esri/widgets/Track",
"esri/Graphic"
], function (Map, Home, BasemapToggle, FeatureLayer, MapView, Feature, Track, Graphic) {
var fLayer = new FeatureLayer({
portalItem: {
id: "5710089ef1374c6d939ebee954c8b15c" //Portal ID number
},
popupEnabled: false,
outFields: ["*"]
});
var map = new Map({
basemap: "streets-navigation-vector",
layers: [fLayer]
});
//Contiguous USA Main Map
var mainView = new MapView({
container: "mainviewDiv",
map: map,
extent: {
spatialReference: {
latestWkid: 3857,
wkid: 102100
},
xmin: -14513000, //bounding box for the inital load of the application
ymin: 2887000,
xmax: -7390000,
ymax: 6326000
},
constraints: {
minScale: 39911104 //user cannot zoom out past this scale
}
});
// Hawaii inset map
var hiView = new MapView({
container: "hiViewDiv",
map: map,
extent: {
xmin: -17834000,
ymin: 2111000,
xmax: -17173000,
ymax: 2573000,
spatialReference: {
wkid: 102100
}
},
spatialReference: {
wkid: 102100
},
ui: {
components: []
}
});
mainView.ui.add("hiViewDiv", "bottom-left");
// Puerto Rico inset map
var prView = new MapView({
container: "prViewDiv",
map: map,
extent: {
xmin: -7887000,
ymin: 1924000,
xmax: -6957000,
ymax: 2257000,
spatialReference: {
wkid: 102100
}
},
spatialReference: {
wkid: 102100
},
ui: {
components: []
}
});
mainView.ui.add("prViewDiv", "bottom-right");
//adding a home button
var homeBtn = new Home({
view: mainView
}); // end of Home Button
mainView.ui.add(homeBtn, "top-left"); //adding a home button to the top left under the zoom in/out
var toggle = new BasemapToggle({
view: mainView,
nextBasemap: "satellite"
}); //end of BasemapToggle
mainView.ui.add(toggle, "top-left"); //adding basemap toggle to the top right
var graphic = {
popupTemplate: {
content: "Mouse over passport icons to show details..."
}
};
// Provide graphic to a new instance of a Feature widget
var feature = new Feature({
graphic: graphic,
map: mainView.map,
spatialReference: mainView.spatialReference
});
mainView.ui.add(feature, "top-right"); //adding feature hover widget to top right
mainView.when().then(function () {
// Create a default graphic for when the application starts
return fLayer.when();
}).then(function (layer) {
return mainView.whenLayerView(layer);
}).then(setupLayerEvent);
prView
.when()
.then(function () {
return fLayer.when();
})
.then(function (layer) {
return prView.whenLayerView(layer);
})
.then(setupLayerEvent);
hiView
.when()
.then(function () {
return fLayer.when();
})
.then(function (layer) {
return hiView.whenLayerView(layer);
})
.then(setupLayerEvent);
function setupLayerEvent(layerView) {
layerView.view.on("pointer-move", eventHandler);
layerView.view.on("pointer-down", eventHandler);
layerView.view.on("click", clickHandler);
function eventHandler(event) {
layerView.view.hitTest(event).then(getGraphics);
}
function clickHandler(event) {
layerView.view.hitTest(event).then(function (response) {
if (response.results.length) {
const graphic = response.results.filter(function (result) {
return result.graphic.layer === fLayer;
})[0].graphic;
const attributes = graphic.attributes;
console.log(attributes.Name); //continue here.
} else {
}
});
}
let highlight, currentId;
function getGraphics(response) {
if (response.results.length) {
const graphic = response.results.filter(function (result) {
return result.graphic.layer === fLayer;
})[0].graphic;
const attributes = graphic.attributes;
const URL = attributes.Link;
const id = attributes.FID;
if (
highlight && currentId !== id
) {
highlight.remove();
highlight = null;
return;
}
// highlight all features belonging to the same hurricane as the feature
// returned from the hitTest
const query = layerView.layer.createQuery();
query.where = "FID = " + id;
layerView.queryObjectIds(query).then(function (ids) {
highlight = layerView.highlight(ids);
feature.graphic = graphic;
currentId = id;
});
} else {
// remove the highlight if no features are
// returned from the hitTest
highlight.remove();
highlight = null;
}
}
}
}); // end of Main function
</script>
</head>
<body>
<div id="mainviewDiv" class="esri-widget"></div>
<div id="hiViewDiv" class="esri-widget"></div>
<div id="prViewDiv" class="esri-widget"></div>
</body>
</html>
Thank you for helping! I am still trying to figure out the rest. However, now the feature pop-up on the top right does not disappear and is covering up some of the points to the northeast.
Glad I could help!
It will always be hard to keep things on top of the map without covering something. It's also depends on the browser size, or container if this will be in an iframe.
Have fun!