I would like to do something whenever a user clicks on the ellipsis (i.e. three dots) on a list item to expand the different actions but I couldn't find an associated event. Is there a way I can respond to respond to this?
I think the layerlist example with associated actions shows you how to do this. This is the URL for it:
https://developers.arcgis.com/javascript/latest/sample-code/widgets-layerlist-actions/
I'm not sure if you are asking about something else but this handles customizing the 3 ellipse button on the LayerList itself.
I looked at this, I think it only shows how to handle the events where you actually click on one of the actions and not the ellipsis that expands the actions. Sorry if I got this wrong, I'm somewhat new to the JSAPI. Thanks!
The 3 ellipse button performs the 'action' of the ListItem. If you look at the code, there is a function created called 'defineActions'. This is then used in the LayerList creation by specifying the property 'listItemCreatedFunction' as this function called 'defineActions'. This process will pull in the objects created through the 'defineActions' function.
If you look at the 'defineActions' function, it first determines if this is the layer that should have these actions defined by looking at the ListItem Title property:
if (item.title === "US Demographics") {
Then it sets up what will happen when you click on the 3 ellipse button for this ListItem using the 'actionSections' property:
item.actionsSections = [
[
{
title: "Go to full extent",
className: "esri-icon-zoom-out-fixed",
id: "full-extent"
},
{
title: "Layer information",
className: "esri-icon-description",
id: "information"
}
],
[
{
title: "Increase opacity",
className: "esri-icon-up",
id: "increase-opacity"
},
{
title: "Decrease opacity",
className: "esri-icon-down",
id: "decrease-opacity"
}
]
];
}
And also, even though it goes beyond your '3 ellipse' question, the function then adds the opacity slider to each sub item by searching to see if it is a child of a ListItem and has a parent:
if(item.children.length > 1 && item.parent){
const slider = new Slider({
min: 0,
max: 1,
precision: 2,
values: [ 1 ],
visibleElements: {
labels: true,
rangeLabels: true
}
});
item.panel = {
content: slider,
className: "esri-icon-sliders-horizontal",
title: "Change layer opacity"
}
slider.on("thumb-drag", (event) => {
const { value } = event;
item.layer.opacity = value;
})
}
That is what is used to setup the functions under the 3 ellipse button, as well as what happens with the opacity slider underneath.
Later on in the code, after the view has had a chance to finish rendering (under 'view.when(() => {'), and after the LayerList (layerList) has been created, there is the definition of what to do when the "trigger-action" event is fired. This is what determines what will happen when an item from the 3 ellipse button drop down gets selected because the 'id' used in the actionsSections corresponds to the 'id' used in the trigger-action event bubble.
layerList.on("trigger-action", (event) => {
// The layer visible in the view at the time of the trigger.
const visibleLayer = USALayer.visible ? USALayer : censusLayer;
// Capture the action id.
const id = event.action.id;
if (id === "full-extent") {
// if the full-extent action is triggered then navigate
// to the full extent of the visible layer
view.goTo(visibleLayer.fullExtent)
.catch((error) => {
if (error.name != "AbortError"){
console.error(error);
}
});
} else if (id === "information") {
// if the information action is triggered, then
// open the item details page of the service layer
window.open(visibleLayer.url);
} else if (id === "increase-opacity") {
// if the increase-opacity action is triggered, then
// increase the opacity of the GroupLayer by 0.25
if (demographicGroupLayer.opacity < 1) {
demographicGroupLayer.opacity += 0.25;
}
} else if (id === "decrease-opacity") {
// if the decrease-opacity action is triggered, then
// decrease the opacity of the GroupLayer by 0.25
if (demographicGroupLayer.opacity > 0) {
demographicGroupLayer.opacity -= 0.25;
}
}
});
Hopefully this is answers your question.
Thanks for your response Jeffrey. I think I understand everything you described and am already doing that. What I really want, and maybe this is something no one else needs and is not possible, is to do something when someone clicks on the ellipses (not when (and if) they click on one of the contained actions. Is that even possible?
I guess you could attach to the 3 ellipse button itself. This is from an example that Esri was showing how to attach to the back button of the Editor widget, but it seems to work here as well.
// Use the LayerList's 3 ellipse button to do something different
layerList.when(function (results) {
console.log("isFulfilled");
let arrComp = document.getElementsByClassName('esri-layer-list__item-actions-menu-item');
if (arrComp.length > 0) {
// Add a tooltip for the 3 ellipse button
arrComp[0].setAttribute("title", "Something to happen here");
// Add a listerner to listen for when the editor's back button is clicked
arrComp[0].addEventListener('click', function (evt) {
// Prevent the default behavior for the back button and
// instead remove the editor and reopen the popup
evt.preventDefault();
alert("pressed the 3 ellipse button");
});
}
}, function (error) {
console.log("Error in layerList.when")
});