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>
Solved! Go to Solution.
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();
}
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();
}
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.
Why would you want them to be able to select it?... Just remove this line then:
dOpt.disabled = true;
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.
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
}
Thanks again Robert. I'll plug that in. In the meantime, you already answered the thread. I'll mark it correct.