feature hightlight on mouseover

385
2
Jump to solution
02-02-2024 01:24 PM
GeoffreyJoseph
New Contributor III

Can someone please help me understand why my highlights on mouseover are not working here? I am (slowly) working on learning the js api by cobbling together a new version of an app I made in leaflet (many years ago from the new api samples. Very interesting. I am trying to get the mouseover highlight to work as it does in that app. I know there are other things I may not be doing optimally, feel free to chime in. Eventually I want to use the reactiveUtils I think. Thanks.

 

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
  <title>Arkansas District Finder</title>

  <script src="https://js.arcgis.com/calcite-components/1.6.1/calcite.esm.js" type="module"></script>
  <link rel="stylesheet" href="https://js.arcgis.com/calcite-components/1.6.1/calcite.css" />

  <script src="https://js.arcgis.com/4.28/"></script>
  <link rel="stylesheet" href="https://js.arcgis.com/4.28/esri/themes/light/main.css" />
</head>
<style>
  html,
  body,
  #viewDiv {
    padding: 0;
    margin: 0;
    height: 100%;
    width: 100%;
  }

  body {
    display: flex;
  }

  calcite-loader {
    align-self: center;
    justify-self: center;
  }

  #header-title {
    margin-left: 1rem;
    margin-right: 1rem;
  }

  #info-content {
    padding: 0.75rem;
  }

  calcite-rating {
    margin-top: 0.25rem;
  }

  #search-container.esri-search.esri-widget {
    width: 100% !important;
    align-items: flex-start;
    /* do not want scroll bar on panel. Clicking it makes
      search suggestions disappear */
    min-height: 300px;
    padding: 0px;
    overflow: auto;
    /* overflow: hidden; */
  }

  button:disabled {
    opacity: 0.4;
    -moz-opacity: 0.4;
    -webkit-opacity: 0.4;
    cursor: default;
  }

  #info {
    visibility: hidden;
  }

  .esri-feature {
    letter-spacing: 0em;
    line-height: 1.55rem;
    font-feature-settings: "liga"1, "calt"0;
    background: #fff;
    padding: 1em;
  }
</style>

<body>
  <calcite-loader></calcite-loader>
  <calcite-shell hidden>

    <calcite-shell-panel slot="panel-start">
      <calcite-panel>

        <calcite-block open>
          <div
            style="width: 100%; background:red; color:white; max-width: 100%; display: flex; flex-direction: row; align-items: center;justify-content: center">
            <h2>Arkansas District Finder</h2>
          </div>
        </calcite-block>

        <calcite-block heading="Select Chamber" open>
          <div style="width: 360px; max-width: 100%; display: flex; flex-direction: row">
            <calcite-button class="esri-button style-button" id="senate" type="button" disabled>
              State Senate
            </calcite-button>
            <calcite-button class="esri-button style-button" id="house" type="button">
              State House
            </calcite-button>
          </div>
        </calcite-block>
        <calcite-block id="senBlock" heading="Search Arkansas State Senators" collapsible open>
          <calcite-label>
            Senators
            <calcite-combobox id="senSelect" selection-mode="single" placeholder="Select a Senator">

            </calcite-combobox>
          </calcite-label>
        </calcite-block>
        <calcite-block id="repBlock" heading="Arkansas State Reps" collapsible open hidden>
          <calcite-label>
            Representatives
            <calcite-combobox id="repSelect" selection-mode="single" placeholder="Select a Representative">

            </calcite-combobox>
            <calcite-label>
        </calcite-block>
        <calcite-block heading="Find  My Districts" collapsible closed>
          <div id="search-container"></div>
        </calcite-block>
        <calcite-block heading="Legend" collapsible open>
          <div id="legend-container"></div>
        </calcite-block>

      </calcite-panel>
    </calcite-shell-panel>
    <div id="overviewDiv">
      <div id="extentDiv"></div>
    </div>
    
    <div id="viewDiv"></div>
    <calcite-shell-panel slot="panel-start" width-scale="s" id="info" align="center">
      <calcite-panel heading="Arkansas Senate">
        <calcite-card>
          <img slot="thumbnail" alt="Sample image alt" src="https://placebear.com/280/200">
          <span slot="title">Senator Name Here</span>
          <span slot="subtitle"></span></span>
          <div slot="footer-start" id="example-slotted-footer">
                <calcite-chip id="badge-1" value="calcite chip" icon="check-circle" scale="s"></calcite-chip>
                <calcite-chip id="badge-2" value="calcite chip" icon="globe" scale="s"></calcite-chip>
                <calcite-chip id="badge-3" value="calcite chip" icon="security" scale="s"></calcite-chip>
            </div>
            <div slot="footer-end">
                <calcite-chip id="badge-4" value="calcite chip" icon="user" scale="s"></calcite-chip>
                <calcite-action scale="s" icon="ellipsis" id="example-slotted-action"></calcite-action>
            </div>
        </calcite-card>
      </calcite-panel>
    </calcite-shell-panel>
  </calcite-shell>
  <script>
    require([
        "esri/core/promiseUtils",
        "esri/core/reactiveUtils",
        "esri/WebMap",
        "esri/views/MapView",
        "esri/widgets/Home",
        "esri/widgets/Features"
    ] , function(promiseUtils, reactiveUtils, WebMap, MapView, Home, Features){
          const webmapId = new URLSearchParams(window.location.search).get("webmap")
            ?? "c7e90511a9094e14a6b373c5d47916f6";

          // Create a Map with a basemap, to be used with in the main view
          const map = new WebMap({
            portalItem: {
              id: webmapId
            }          
          });
          map.load()
          .then(() => {
            map.layers
              .filter(layer => { return layer.type === 'feature' })
              .map(layer => {
                let featLayer = layer; 
                featLayer.outFields = ['*'];
                return featLayer; 
              });
          });
          const view = new MapView({
            container: "viewDiv",
            map: map,
            popupEnabled: false
          });

          // Provide graphic to a new instance of a Feature widget
          const featuresWidget = new Features({
            container: 'features-widget',
            view: view
          });

          const popup = "<div id='features-widget'></div>"
          view.ui.add(featuresWidget, "bottom-right");

          view.ui.move("zoom", "top-left");
          var home = new Home({
              view: view
          });
          view.ui.add(home, "top-left");
          view.ui.add("info", "bottom-left");    

          // Open the Features widget with features fetched from
          // the view click event location.
          reactiveUtils.on(
            () => view,
            "click",
            (event) => {
              featuresWidget.open({
                location: event.mapPoint,
                fetchFeatures: true
              });
            }
          );
          map.when(() => {
            // 2016 election layer
            const senateLayer = map.layers.items[0];
            senateLayer.outFields = ['*'];
            view.whenLayerView(senateLayer).then((layerView) => {
              let highlight;
              let objectId;

              const debouncedUpdate = promiseUtils.debounce(async (event) => {
                  // Perform a hitTest on the View
                  const hitTest = await view.hitTest(event);
                  
                  // Make sure graphic is for the current layer
                  const results = hitTest.results.filter((result) => {
                    return result.graphic.layer.title === "Arkansas State Senate";
                  });

                  if(results.length){
                    const result = results[0];

                    const newObjectId = result && result.graphic.attributes[result.layer.objectIdField];
                    document.getElementById("info").style.visibility = "hidden";

                    if (!newObjectId) {
                      highlight?.remove();
                      objectId = null;
                    } else if (objectId !== newObjectId) {
                      highlight?.remove();
                      objectId = newObjectId;
                      highlight = layerView.highlight(result.graphic);
                    }
                    //result.forEach((graphicHit) => {
                    const graphic = result.graphic;

                    const attributes = graphic.attributes;

                    const firstName = attributes.FirstName;
                    const lastName = attributes.LastName;
                    const email = attributes.Email;
                    const party = attributes.Party;
                    const district = attributes.district;
                    const chamber = attributes.Chamber;
                    const id = attributes.OBJECTID;

                    document.getElementById("info").style.visibility = "visible";

                    var panel = document.querySelector('#info');
                    
                    panel.children[0].heading = firstName + " " + lastName + " (" + party +")";

                    document.querySelector('[slot="title"]').innerText= "Arkansas " + chamber + " District " + district;
                    document.querySelector('[slot="subtitle"]').innerText=email;
                    document.querySelector('[slot="thumbnail"]').src=attributes.PhotoURL;
                    document.querySelector('[slot="thumbnail"]').width="320px";

                  }else{
                    highlight?.remove();
                    document.getElementById("info").style.visibility = "hidden";
                  }

              });
              // Listen for the pointer-move event on the View
              view.on("pointer-move", (event) => {
                debouncedUpdate(event).catch((err) => {
                  if (!promiseUtils.isAbortError(err)) {
                    throw err;
                  }
                });
              });          
            });
        });    
         


          document.querySelector("calcite-shell").hidden = false;
          document.querySelector("calcite-loader").hidden = true;
          
      });
  </script>
</body>
</html>  

 

0 Kudos
1 Solution

Accepted Solutions
JoelBennett
MVP Regular Contributor

With the following changes I got it to highlight on mouseover:

 

1) Line 215 should be:

const senateLayer = map.layers.items[3];

 

2) Line 242 should be:

highlight = layerView.highlight([newObjectId]);

 

3) Technically not necessary, but I also changed line 227 to:

return result.graphic.layer == layerView.layer;

 

 

View solution in original post

0 Kudos
2 Replies
JoelBennett
MVP Regular Contributor

With the following changes I got it to highlight on mouseover:

 

1) Line 215 should be:

const senateLayer = map.layers.items[3];

 

2) Line 242 should be:

highlight = layerView.highlight([newObjectId]);

 

3) Technically not necessary, but I also changed line 227 to:

return result.graphic.layer == layerView.layer;

 

 

0 Kudos
GeoffreyJoseph
New Contributor III

Thanks very much for your help.

0 Kudos