I am trying to do as follow:
Get a list of paired values - each value includes a name and a number
present the user with a list of buttons , each button shows the name from the name-value pair, so if I get 10 pairs, I will present 10 buttons
when the user clicks the chosen name, the button invokes a JS with the name-value matched.
I am very new to HTML , so this part is the problematic for me.
The page is not required to look nice at this stage, just function correctly.
<html>
<head> </head>
<body>
<script>
var pairs = [
{
"name_1": 123
},
{
"name_2": 983
},
{
"name_3": 567
}
];
function present_buttons(pairs) {
for (var i in pairs) {
console.log(`index = ${i}`);
console.log(`name = ${pair[i].name}`);
console.log(`value = ${pair[i].value}`);
// send info the the HTML section, so present proper names on buttons
// make sure to hook matching value for each button so it will be sent correctly to the use_value function later on
}
}
function use_value(value) {
// do something with the value triggered by the matching name button
}
</script>
<!--
get names to present on buttons from the present_buttons()
when a button is clicked , send the matching value to the use_value() function
-->
</body>
</html>
Try this:
<html>
<head></head>
<body>
<script>
var pairs = [
{ "name_1" : 123 } ,
{ "name_2" : 983 } ,
{ "name_3" : 567 }
];
for (var i = 0; i < pairs.length; i++) {
var button = document.createElement('button');
var pair = pairs[i];
button.innerHTML = Object.keys(pair)[0];
button.addEventListener('click', function (pair) {
use_value(pair);
}.bind(this, pair));
document.getElementsByTagName('body')[0].appendChild(button);
}
function use_value(value) {
// do something with the value triggered by the matching name button
}
</script>
</body>
</html>
Related
I have successfully been able to filter, for instance shakemaps, by attribute id - I have successfully achieved this multiple ways - but all ending with the same problem.
1.) with the where filter 2.) definition expression 3.) iterating through all attribute ids and bringing them back.
The problem: All exists for only allowing/displaying one per attribute id at a time.. my goal is to feed the attribute ids into a checkbox list (which I have done), but allowing for items via attribute id to be added to the map as they are checked, collectively, one at a time - currently I can not seem to get this to work with the aspect of having multiple or more then one appear at a time on the map.
1.) i.e. the below filter (attempted logic 1) & CodePen:
.....
function filterByID(event) {
const selectedID = event.target.getAttribute("data-id");
eqLayerView.filter = {
where: "id = '" + selectedID + "'"
};
}
view.whenLayerView(fl)
.then(function(layerView) {
eqLayerView = layerView;
eqLayerView.filter = {
where: "id = ''"
};
.............
2.) i.e. another attempted logic (adding multiple at a time here, line by line, or via array):
layer.definitionExpression = "id = 'us70008jr5'",
layer.definitionExpression = "id = 'cgi988jr52'",
3.) i.e. 3rd attempt with a suggestion here on GIS exchange: https://gis.stackexchange.com/questions/364578/loop-through-attribute-ids-of-featurelayer
layer
.load()
.then(() => {
// create a query from the layer
const query = layer.createQuery();
query.returnDistinctValues = true;
query.where = "grid_value > 2"; // or 1=1 if you need them all
// the field you want distinct values for
query.outFields = ["id"];
return layer.queryFeatures(query);
})
.then(({ features }) => {
// extract the ids to a list
const ids = features.map(({ attributes }) => attributes.id);
return ids;
})
.then((ids) => {
// You can store them how you want, in this case,
// I put them in a dropdown select menu
const fragment = document.createDocumentFragment();
ids.forEach((id) => {
const option = document.createElement('option');
option.value = id;
option.innerText = id;
fragment.appendChild(option);
});
list.appendChild(fragment);
map.add(layer);
});
All attempted logic above result in the toggling of a shakemap by attribute id to be displayed only one at a time — by toggling a new on, the previous turns off, I need the ability to have multiple being able to exist on the map at once.
ArcGIS - javascript - 4.15
I am pretty sure I answer this question a couple of weeks ago, but I can't find my answer so maybe I just thought I did, in that case sorry about that.
Anyway, with a couple of fixes your code should work. The main issue here I think is that your query is not correct if you are going to use checkboxs. You need to use a set query like IN. I would be fine if you use radio buttons.
Here you have your example with the fixes I mention,
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<title>Filter features by attribute - 4.15</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 {
padding: 0;
margin: 0;
height: 500px;
width: 100%;
}
</style>
<script>
require([
'esri/views/MapView',
'esri/Map',
'esri/layers/FeatureLayer',
'esri/widgets/Expand'
], function (MapView, Map, FeatureLayer, Expand) {
const layer = new FeatureLayer({
url: 'https://services9.arcgis.com/RHVPKKiFTONKtxq3/arcgis/rest/services/USGS_Seismic_Data_v1/FeatureServer/1/',
outFields: ['*']
, definitionExpression: 'eventTime >= CURRENT_TIMESTAMP - 30 AND grid_value > 2'
});
const map = new Map({
basemap: 'gray-vector'
, layers: [layer]
});
const view = new MapView({
map: map,
container: 'viewDiv',
center: [-98, 40],
zoom: 4
});
let eqLayerView;
let selectedIDs = {};
function updatedFilter() {
const ids = [];
for(const [key, value] of Object.entries(selectedIDs)) {
if (value) {
ids.push(`'${key}'`);
}
}
eqLayerView.filter = {
where: `id IN (${ids.join(',')})`
};
console.log(`[updateFilter] ${eqLayerView.filter.where}`);
}
const idElement = document.getElementById('id-filter');
idElement.addEventListener('click', filterByID);
function filterByID(event) {
const chk = event.target;
console.log(`[filterByID] ${chk.getAttribute('data-id')} ${chk.checked}`);
selectedIDs[chk.getAttribute('data-id')] = chk.checked;
updatedFilter();
}
view.whenLayerView(layer).then(function (layerView) {
eqLayerView = layerView;
updatedFilter();
var query = layer.createQuery();
query.outFields = ['id'];
query.returnDistinctValues = true;
query.returnGeometry = false;
layer.queryFeatures(query).then(function (results) {
results.features.map(function (feat) {
let id = feat.attributes['id'];
let opt = document.createElement('input');
opt.type = 'checkbox';
let label = document.createElement('label')
label.innerHTML = id;
opt.className = 'id-item visible-id';
opt.setAttribute('data-id', id);
idElement.appendChild(opt);
idElement.appendChild(label);
selectedIDs[id] = false;
});
});
});
});
</script>
</head>
<body>
<div id='id-filter' class='esri-widget'>
</div>
<div id='viewDiv'></div>
</body>
</html>
BTW, I added some logs for you to see what I consider import info of the events.
Last thing, I use an auxiliary dictionary to keep track of the visible features to filter. Another way to do it would simply to query all the checkbox and add the id to the filter if it is checked.
I am trying to use the label to display values in a list.
For example: apple, 500kg, $3000 using these label I will display in a list.
to retrieve labels in javascript I used:
<script type="text/javascript">
function listEE(json) {
var ListTagEE= "";
for (var k = 0; k < json.feed.category.length; k++)
{
ListTagEE += ""+json.feed.category[k].term+""; }
var listing = ""
+ListTagEE+
"" ;
document.write(listing);
}
</script>
<!-- ######### Invoking the Callback Function ############# -->
<script type="text/javascript" src='https://someadresss.blogspot.com/feeds/posts/default?alt=json-in-script&callback=listEE'>
</script>
And this is code I used to replace labels with my specific values.
<script>
function lebel23_logo(etiqueta23) {
ratstok = new Array();
ratstok[1] = "Apple Peter"
ratstok[2] = "Mango"
ratstok[3] = "Pine Apple"
if (etiqueta23 == "Apple") {document.write(ratstok[1]);}
if (etiqueta23 == "Mango") {document.write(ratstok[2]);}
if (etiqueta23 == "Pineapp") {document.write(ratstok[3]);}
}</script>
earlier I was using blogger < b: loop> label tag to retrieve label. and used following code.. to display the output
lebel23_logo("<data:label.name/>");
Now I am retrieving labels in javascript through above code which is working. but not able to change label and display it with above function lebel23_logo.
Uncaught TypeError: lebel23_logo is not a function on line 9
https://js.do/helloaaa/asasqqq
sorry, my English and javascript is not that good. i hope I made this post understandable.
Replace ""+json.feed.category[k].term+"" with +lebel23_logo(json.feed.category[k].term)+
https://js.do/MustaphaBouh/asasqqq
Suppose, I have following array of objects successfully sent to handlebars file from my express server:
[
{
"name": "Jon",
"isPositive": true
},
{
"name": "Cercei",
"isPositive": false
}
]
Each time when my button gets clicked, I want to show next element of the array on my view. Is it possible with handlebars? Or do I need something more complex like Vue.js to solve this problem? Here is simple pseudocode I would like to achieve:
<head>
<script>
$(document).ready(() => {
var index = 0;
var currentCharacter = getCurrentCharacter();
start();
});
</script>
</head>
<body>
<h3 id="name"></h3>
<p id="someInfo"> </p>
<button onclick="next()">Next</button>
<script>
function getCurrentCharacter() {
/// somehow access array of objects sent from server
var myCharacters = {{characters}}; // {} used because of handlebars
var character = myCharacters[index];
index += 1;
return character;
}
function start() {
document.getElementById("name").textContent = currentCharacter.name;
/// as you see here, I change my UI based on current object fields/attributes
if (currentCharacter.isPositive) {
document.getElementById("someInfo").style.display = "block";
document.getElementById("someInfo").textContent = "Some text here";
} else {
document.getElementById("someInfo").style.visibility = "hidden";
}
}
function next() {
currentCharacter = getCurrentCharacter();
start();
}
</script>
</body>
Is it possible to have such a logic with handlebars or other templating languages? If they are not build for these purposes, please recommend me another way to solve this problem.
I have JSON data and I have two array with cities and countries.When I clicked my input cities are opening automatically but I want to do this too:
if I cliked my input cities must open (this is okey I did it)
but at the same time if I wrote something for example denmark (this is the list of countries) than denmark must seen if is matching.. how can I do that ?
click to see if you see on codepen
var myJSON = '{ "cities":[ "copenhagen", "london", "hamburg" ], "countries":[ "denmark", "norway", "sweden" ] }';
var myObj = JSON.parse(myJSON);
var testInput = document.getElementById("test");
testInput.setAttribute("data-list", myObj.countries)
function showlist() {
}
var comboplete = new Awesomplete('input.dropdown-input', {
minChars: 0,
});
Awesomplete.$('#test').addEventListener("click", function() {
if (comboplete.ul.childNodes.length === 0) {
comboplete.minChars = 0;
comboplete.evaluate();
}
else if (comboplete.ul.hasAttribute('hidden')) {
comboplete.open();
}
else {
comboplete.close();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/awesomplete/1.1.1/awesomplete.min.js"></script>
<input id="test" class="dropdown-input" />
What I get from your question is that you want entries from both arrays to show when you type anything. To achieve that use (myObj.cities.concat(myObj.countries)) array instead of myObj.cities or myObj.countries array alone.
I have this idea of mine that I want to implement by using function parameters and objects, but the its not working as expected.
First HTML code:
<!DOCTYPE html>
<html>
<head>
<title>Main</title>
<script type="text/javascript" src="scripting.js"></script>
</head>
<body>
<div >
<form id='radio'>
<input type="radio" name="choice" onClick="text(this.value)" value="list">
<input type="radio" name="choice" onClick="text(this.value)" value="box"></form>
<h1 id="title">" "</h1>
<p id="description"></p>
</div>
</body>
</html>
This is quite straight forward, I will use the value of the radio button as a parameter for my javascript text() function.
Here is my JavaScript code:
var choices = document.getElementsByName('choice');
var list = { a : 1 , b : 'Hi' };
var box = { a : 2, b : 'Hello'};
function text(choice) {
var i;
for (i = 0; i < choices.length; i += 1)
{
if(choices[i].checked)
{
document.getElementById('title').innerHTML = choice["a"];
document.getElementById('description').innerHTML = choice["b"];
}
}
}
I have created two objects with same name as the radio button from the HTML code. Next, in my function made a for loop to check which radio button is clicked. Based on the formula, the Head and Paragraph tags should display object contents in their respective tags. When I just input the parameter as a plain value, it prints out the value of the radio button. However, I am using the parameter as a reference to object variable. Example:
function parameter choice = "list";
document.getElementById('title').innerHTML = choice["a"];
Instead of getting the value displayed. I get "undefined" as a result.
Can someone help with this?
Two ways to approach this. If you keep the current variables and now that they will be global (in the window object), then use this:
var list = { a : 1 , b : 'Hi' };
var box = { a : 2, b : 'Hello'};
var choice = 'list';
console.log(window[choice]);
Notice we put choice in bracket because list and box are properties of window.
Because choice equals 'list', therefore, window[choice], window['list'], and window.list all refer to the same object named list.
Another approach is to place list and box in an object:
var types = {
list: { a : 1 , b : 'Hi' },
box: { a : 2, b : 'Hello' }
};
var choice = 'list';
console.log(types[choice]);
I prefer this method over putting everything in the global/window object.