Add Text to Top of Query Dropdown

963
6
Jump to solution
07-09-2020 01:48 PM
JaredPilbeam2
MVP Regular Contributor

How do I add "Select One" to the top of the drop-down such as this?

Right now the first choice is the first value in the table when sorted ascending (i.e. Appliance Recycling). Also, something's wrong because even though it shows "Appliance Recycling" ALL the features are in fact on the map. There are actually only 16 "Appliance Recycling" categories. I'm not sure if this is related to the table or something in the code.

Current Code

<!DOCTYPE html>
<html>

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

    <link rel="stylesheet" href="https://js.arcgis.com/4.15/esri/themes/light/main.css" />
    <script src="https://js.arcgis.com/4.15/"></script>

    <style>
        html,
        body,
        #viewDiv {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }

        #viewDiv {
            position: absolute;
            height: calc(100% - 67px);
            top: 67px;
        }

        #filterDiv {
            position: relative;
            background-color: white;
            color: black;
            padding: 6px;
            top: 0;
            background: #d4e1c0;
            border-bottom: 1px dotted #91dca1;
        }

        #category,
        #keyword {
            margin-top: 8px;
            margin-bottom: 8px;
            display: inline-block;
        }

        .drop-downs {
            width: 100%;
        }

        .oneline {
            display: inline-block;
            margin-right: 6px;
        }

        #filterBtn {
            position: fixed;
            right: 6px;
            top: 6px;
            width: 50px;
            font: bold 12px Trebuchet MS;
            color: #fff;
            background-color: #098941;
            border: 1px solid #1c9c52;
            text-decoration: none;
            cursor: pointer;
            padding: 2px 4px;
        }

            #filterBtn:hover {
                background-color: #098dd1;
                border: 1px solid #0ab0ed;
            }

        .docking-control {
            position: absolute;
            z-index: 10;
            top: 50%;
            left: 50%;
            width: 250px;
            height: 80px;
            padding: 10px;
            box-sizing: border-box;
            margin: -40px 0 0 -125px;
            background-color: #fff;
            color: #323232;
            text-align: center;
            -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
        }

            .docking-control label {
                display: inline-block;
                font-weight: bold;
                margin: 0 0 10px 0;
                padding: 0;
                font-size: 16px;
            }

        #titleDiv {
            padding: 10px;
        }

        #titleText {
            color: #098941;
            font-size: 20pt;
            font-weight: 500;
            padding-bottom: 10px;
        }
    </style>

    <script>
        require([
            "esri/Map",
            "esri/views/MapView",
            "esri/layers/FeatureLayer",
            "esri/layers/GraphicsLayer",
            "esri/geometry/geometryEngine",
            "esri/Graphic"

        ], function (
            Map,
            MapView,
            FeatureLayer,
            GraphicsLayer,
            geometryEngine,
            Graphic,
        ) {


            var catTypeSelect = document.getElementById("category");
            var keyTypeSelect = document.getElementById("keyword");
            var filterButton = document.getElementById("filterBtn");
            var resRb = document.getElementById("ResidentialRB");

            //***popups***
            //popup template
            var template = { //autocasts the new template
                title: "<b>{USER_Name}</b>",
                content: [
                    { //set content elements in the order to display
                    type: "fields",
                    fieldInfos: [{
                        fieldName: "USER_Addre",
                        label: "Address",
                        visible: true,
                    }, {
                        fieldName: "USER_City",
                        label: "City",
                        visible: true,
                    },
                    {
                        fieldName: "USER_Phone",
                        label: " Phone",
                        visible: true,
                    },
                    {
                        fieldName: "USER_Email",
                        label: "Email",
                        visible: true,
                    },
                    {
                        fieldName: "USER_Notes",
                        label: "Notes",
                        visible: true,
                    },]
                    },
                    { 
                    // You can also set a descriptive text element
                        type: "text", // TextContentElement
                        text: "<font color= '#098941'><b>{Description}</b>"
                    }],
            };

            // Recycle
            var recycleLayer = new FeatureLayer({
                portalItem: {
                    // autocasts as new PortalItem()
                    id: "227061be60a14cc89946a978b440d227"
                },
                popupTemplate: template,
                outFields: ["*"],
                visible: false
            });

            // GraphicsLayer for displaying results
            var resultsLayer = new GraphicsLayer();

            var map = new Map({
                basemap: "dark-gray",
                layers: [recycleLayer, resultsLayer]
            });

            var view = new MapView({
                container: "viewDiv",
                map: map,
                center: [-87.95, 41.47],
                zoom: 10,
                //popup
                popup: {
                }
            });
            popup = view.popup;

            // query all features from the recycle layer
            view
                .when(function () {
                    return recycleLayer.when(function () {
                        var query = recycleLayer.createQuery();
                        return recycleLayer.queryFeatures(query);
                    });
                })
                .then(getValues)
                .then(getUniqueValues)
                .then(addToSelect)

            // return an array of all the values in the
            // Category and USER_Keywo fields of the Recycle layer
            function getValues(response) {
                var features = response.features;
                var values = features.map(function (feature) {
                    return {
                        Category: feature.attributes.Category,
                        USER_Keywo: feature.attributes.USER_Keywo
                    }
                });
                return values;
            }

            // return an array of unique values in
            // the USER_Keywo and Category fields of the Recycle layer
            function getUniqueValues(values) {
                var uniqueKeyValues = [];
                var uniqueCatValues = [];

                values.forEach(function (item, i) {
                    var keyVal = item.USER_Keywo.split(";");
                    var catVal = item.Category.split(";");
                    catVal.map(function (val1) {
                        if (
                            (uniqueCatValues.length < 1 || uniqueCatValues.indexOf(val1) === -1) &&
                            val1 !== ""
                        ) {
                            uniqueCatValues.push(val1);
                        }
                    });
                    keyVal.map(function (val2) {
                        if (
                            (uniqueKeyValues.length < 1 || uniqueKeyValues.indexOf(val2) === -1) &&
                            val2 !== ""
                        ) {
                            uniqueKeyValues.push(val2);
                        }
                    });
                });
                return {
                    uKeyVals: uniqueKeyValues,
                    uCatVals: uniqueCatValues
                };
            }

            // Add the unique values to the recycle type
            // select element. This will allow the user
            // to filter categories by type.
            function addToSelect(values) {
                values.uCatVals.sort();
                values.uCatVals.forEach(function (value) {
                    var option = document.createElement("option");
                    option.text = value;
                    catTypeSelect.add(option);
                });

                values.uKeyVals.sort();
                values.uKeyVals.forEach(function (value) {
                    var option = document.createElement("option");
                    option.text = value;
                    keyTypeSelect.add(option);
                });

                return setDefinitionExpression();
            }

            // set the definition expression on the recycle
            // layer to reflect the selection of the user
            function setDefinitionExpression() {
                var sqlExp = "";
                if (catTypeSelect.selectedIndex > 0) {
                    sqlExp += "Category LIKE '%" + catTypeSelect.options[catTypeSelect.selectedIndex].value + "%'";
                }
                if (keyTypeSelect.selectedIndex > 0) {
                    if (sqlExp === "") {
                        sqlExp += "USER_Keywo LIKE '%" + keyTypeSelect.options[keyTypeSelect.selectedIndex].value + "%'";
                    } else {
                        sqlExp += " AND USER_Keywo LIKE '%" + keyTypeSelect.options[keyTypeSelect.selectedIndex].value + "%'";
                    }
                }
                if (resRb.checked) {
                    if (sqlExp !== "") {
                        sqlExp += " AND USER_IsRes = 'TRUE'";
                    }

                } else {
                    if (sqlExp !== "") {
                        sqlExp += " AND USER_IsBus = 'TRUE'";
                    }
                }
                console.info(sqlExp);
                recycleLayer.definitionExpression = sqlExp;

                if (!recycleLayer.visible) {
                    recycleLayer.visible = true;
                }

                return queryForGeometries();
            }

            // Get all the geometries of the recycle layer
            // the createQuery() method creates a query
            // object that respects the definitionExpression
            // of the layer
            function queryForGeometries() {
                var rQuery = recycleLayer.createQuery();

                return recycleLayer.queryFeatures(rQuery).then(function (response) {
                    rGeometries = response.features.map(function (feature) {
                        return feature.geometry;
                    });

                    return rGeometries;
                });
            }

            filterButton.addEventListener("click", function () {
                setDefinitionExpression();
            });
            view.ui.add("titleDiv", "bottom-right");
        });
    </script>
</head>

<body>
    <div id="viewDiv"></div>
    <div id="filterDiv">
        <div class="drop-downs">
            <div class="oneline">Select Category:</div>
            <select id="category" class="oneline"></select>
            <div class="oneline">Select Keyword:</div>
            <select id="keyword" class="oneline"></select>
            <div>
                <input id="ResidentialRB" name="resorbus" type="radio" value="Residential" checked="checked"><label for="ResidentialRB">Residential</label>
                <input id="BusinessRB" name="resorbus" type="radio" value="Business"><label for="BusinessRB">Business</label>
            </div>
            <button id="filterBtn">Search</button>
        </div>
        <div id="titleDiv" class="esri-widget">
            <div id="titleText">Green Guide</div>
            <div>Easy Ways To Be More Green</div>
        </div>
    </div>
</body>

</html>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Jared,

      function addToSelect(values) {
        var dOpt = document.createElement("option");
        dOpt.value = "";
        dOpt.diabled = true;
        dOpt.selected = true;
        dOpt.text = "Select one";
        catTypeSelect.add(dOpt);
        values.uCatVals.sort();
        values.uCatVals.forEach(function (value) {
          var option = document.createElement("option");
          option.text = value;
          catTypeSelect.add(option);
        });

        var dOpt2 = document.createElement("option");
        dOpt2.value = "";
        dOpt2.diabled = true;
        dOpt2.selected = true;
        dOpt2.text = "Select one";
        keyTypeSelect.add(dOpt2);
        values.uKeyVals.sort();
        values.uKeyVals.forEach(function (value) {
          var option = document.createElement("option");
          option.text = value;
          keyTypeSelect.add(option);
        });

        return setDefinitionExpression();
      }

View solution in original post

6 Replies
RobertScheitlin__GISP
MVP Emeritus

Jared,

      function addToSelect(values) {
        var dOpt = document.createElement("option");
        dOpt.value = "";
        dOpt.diabled = true;
        dOpt.selected = true;
        dOpt.text = "Select one";
        catTypeSelect.add(dOpt);
        values.uCatVals.sort();
        values.uCatVals.forEach(function (value) {
          var option = document.createElement("option");
          option.text = value;
          catTypeSelect.add(option);
        });

        var dOpt2 = document.createElement("option");
        dOpt2.value = "";
        dOpt2.diabled = true;
        dOpt2.selected = true;
        dOpt2.text = "Select one";
        keyTypeSelect.add(dOpt2);
        values.uKeyVals.sort();
        values.uKeyVals.forEach(function (value) {
          var option = document.createElement("option");
          option.text = value;
          keyTypeSelect.add(option);
        });

        return setDefinitionExpression();
      }
JaredPilbeam2
MVP Regular Contributor

Hi Robert,

Thanks for that. I implemented those changes and it does what I asked! But, is there a way to make the "Select one" selectable? Right now, the end-user can see it but can't click it.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Why would you want them to be able to select it?... Just remove this line then:

dOpt.disabled = true;
JaredPilbeam2
MVP Regular Contributor

Thanks Robert!

I need them to be able to select it because when a Category is selected it is supposed to filter the corresponding keyword(s). If "Select one" is not selectable I don't see how the user can sort of reset their search. Honestly, the app is not functioning correctly at the moment, so when it is I probably won't have to remove that line.

I've requested ESRI's help in the matter, but here's how it is supposed to (i.e. how I'd like it to) work: User selects Category --> Keyword(s) automatically get filtered leaving only those features in the map. All Categories have their corresponding keywords, for example Asbestos Info / Removal Service:

I'm basically lacking a function that filters a Categories' corresponding Keyword(s), I guess.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Jared,

   If that is the case then you have to re-query the layer based on the selected category and re-populate the keyword select.

      catTypeSelect.addEventListener("change", function(){
        var sqlExp = "";
        if (catTypeSelect.selectedIndex > 0) {
          sqlExp += "USER_Categ LIKE '%" + catTypeSelect.options[catTypeSelect.selectedIndex].value + "%'";
        }
        var query = recycleLayer.createQuery();
        query.where = sqlExp;
        recycleLayer.queryFeatures(query)
        .then(getValues2)
        .then(getUniqueValues2)
        .then(addToSelect2)
      });

      function getValues2(response) {
        var features = response.features;
        var values = features.map(function (feature) {
          return feature.attributes.USER_Keywo
        });
        return values;
      }

      function getUniqueValues2(values) {
        var uniqueKeyValues = [];

        values.forEach(function (item, i) {
          var keyVal = item.split(";");
          keyVal.map(function (val2) {
            if (
              (uniqueKeyValues.length < 1 || uniqueKeyValues.indexOf(val2) === -1) &&
              val2 !== ""
            ) {
              uniqueKeyValues.push(val2);
            }
          });
        });
        return uniqueKeyValues;
      }

      function addToSelect2(values) {
        while (keyTypeSelect.options.length > 0) {                
          keyTypeSelect.remove(0);
        }
        var dOpt2 = document.createElement("option");
        dOpt2.value = "";
        dOpt2.disabled = true;
        dOpt2.selected = true;
        dOpt2.text = "Select one";
        keyTypeSelect.add(dOpt2);
        values.sort();
        values.forEach(function (value) {
          var option = document.createElement("option");
          option.text = value;
          keyTypeSelect.add(option);
        });
        return true
      }
JaredPilbeam2
MVP Regular Contributor

Thanks again Robert. I'll plug that in. In the meantime, you already answered the thread. I'll mark it correct.

0 Kudos