Description Image Demo
I want to create a small demo like the picture if I click the item in the left column to choose the Country and the right column will display all the city of country in the left column that I chosen. How can I do that?
I wrote a small sample, I hope it helps you:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<style>
select {
min-width: 100px;
float: left;
margin-right: 20px;
}
</style>
</head>
<body>
<select id="countrySelect" size="10"></select>
<select id="citySelect" size="10"></select>
<script>
var countries = [{name: "USA", id:1}, {name: "Canada", id:2}];
var cities = [{name: "New York", id:1, countryId:1}, {name: "Boston", id:2, countryId:1}, {name: "Ottawa", id:3, countryId:2}, {name: "Toronto", id:4, countryId:2}];
var $countrySelect = $('#countrySelect');
var $citySelect = $('#citySelect'), countrySelectHtml = '';
for (var i=0; i<countries.length; i++) $countrySelect.append($('<option>').attr('value', countries[i].id).text(countries[i].name));
$countrySelect.change(function () {
var countryId = $countrySelect.val();
$citySelect.html('');
for (var i=0; i<cities.length; i++)
if (cities[i].countryId == countryId) $citySelect.append($('<option />').attr('value', cities[i].id).text(cities[i].name));
});
$citySelect.change(function () {
alert('Selected city: ' + $(this).find('option:selected').text() + ' (id=' + $citySelect.val() + ')');
});
</script>
</html>
Related
my array has 2 elements. I'm creating a dynamic list using the "Name" and displaying the "Location" while submitting. But I also want to display the "ID" while submitting.
JS Code create a dynamic list using Name - ITC, JOY When I chose ITC, I want to display India and 100. But this code only allow me to choose single value from the array.
<!DOCTYPE html>
<html>
<body>
<head>
<script language="JavaScript">
var Comp = [
{Name: "ITC" , Location: "India ", ID: "100" },
{Name: "JOY" , Location: "US " ,ID: "200" },
];
var AllCustomers = document.getElementById("AllCustomers");
for (var i = 0; i < Comp.length; i++) {
var My_list = document.createElement("OPTION");
My_list.innerHTML = Comp[i].Name;
My_list.value = Comp[i].Location;
AllCustomers.appendChild(My_list)
}
function ShowCX()
{
document.getElementById("display_message").innerHTML=AllCustomers.value;
document.getElementById("display_message2").innerHTML=AllCustomers.value;
}
</script>
</head>
<select id="AllCustomers">
</select>
<input type="button" onclick="ShowCX()" value="submit" />
<p> Location: <span id = "display_message"></span> </p>
<p> ID: <span id = "display_message2"></span> </p>
</body>
</html>
I think this is what you're looking for. What I did is I stored an Object with the Location and ID in the value attribute and accessed it when it was selected. There are many ways to do this though. Also I changed the for loop for better abstraction.
var Comp = [{
Name: "ITC",
Location: "India ",
ID: "100"
},
{
Name: "JOY",
Location: "US ",
ID: "200"
},
];
var AllCustomers = document.getElementById("AllCustomers");
/*for (var i = 0; i < Comp.length; i++) {
var My_list = document.createElement("OPTION");
My_list.innerHTML = Comp[i].Name;
My_list.value = Comp[i].Location;
AllCustomers.appendChild(My_list)
}*/
Comp.forEach(element=>{
var My_list = document.createElement("OPTION");
My_list.innerHTML = element.Name;
My_list.value = JSON.stringify({"loc":element.Location,"id":element.ID});//storing as a JSON in value attribute
AllCustomers.appendChild(My_list)
})
function ShowCX() {
value = JSON.parse(AllCustomers.value); //gettinng the JSON
document.getElementById("display_message").innerHTML = value.loc;
document.getElementById("display_message2").innerHTML = value.id;
}
<!DOCTYPE html>
<html>
<body>
<head>
</head>
<select id="AllCustomers">
</select>
<input type="button" onclick="ShowCX()" value="submit" />
<p> Location: <span id="display_message"></span> </p>
<p> ID: <span id="display_message2"></span> </p>
</body>
</html>
You can get the selected index of the by using its selectedIndex property that way you can dynamically display your values based on user input. I've also added in the id.
<!DOCTYPE html>
<html>
<head></head>
<body>
<select id="AllCustomers"></select>
<input type="button" onclick="ShowCX()" value="submit" />
<p> Location: <span id="display_message"></span> </p>
<p> ID: <span id="display_message2"></span> </p>
<script language="JavaScript">
var Comp = [
{ Name: "ITC", Location: "India ", ID: "100" },
{ Name: "JOY", Location: "US ", ID: "200" },
];
var AllCustomers = document.getElementById("AllCustomers");
for (var i = 0; i < Comp.length; i++) {
var My_list = document.createElement("OPTION");
My_list.innerHTML = Comp[i].Name;
My_list.value = Comp[i].Location;
My_list.id = Comp[i].ID;
AllCustomers.appendChild(My_list)
}
function ShowCX() {
var selectedIndex = document.getElementById("AllCustomers").selectedIndex
document.getElementById("display_message").innerHTML = AllCustomers[selectedIndex].value; document.getElementById("display_message2").innerHTML = AllCustomers[selectedIndex].value;
document.getElementById("display_message2").innerHTML = AllCustomers[selectedIndex].value; document.getElementById("display_message2").innerHTML = AllCustomers[selectedIndex].id;
}
</script>
</body>
</html>
document.getElementById("display_message2").innerHTML=Comp[AllCustomers.selectedIndex].ID;
How can I give the output as: Name:..., Description:..., Main Temp:... Instead of: Name:..., Name:..., Name:..., Description..., Description:..
for (var i = 0; i < 3; i++) {
$('#name').append('<b>Name:</b><ul>' + `<li>${name[i]}</li>` + '</ul>');
$('#main_temp').append('<b>Main Temp: </b><ul>' + `<li>${mainTemp[i]}</li>` + '</ul>');
$('#weather_description').append('<b>Weather Description:</b><ul>' + `<li>${description[i]}</li>` + '</ul>');
}
output:
Name:
Vancouver
Name:
Vancouver
Name:
Vancouver
Weather Description:
light rain
Weather Description:
light rain
Weather Description:
clear sky
Main Temp:
289.917
Main Temp:
286.551
Main Temp:
285.244
You might be looking for something like this:
JS
var text = '';
for (var i = 0; i < 3; i++) {
text= '';
text = '<ul>' +
`<li><b>Name: </b>${name[i]}</li>` +
`<li><b>Main Temp: </b>${mainTemp[i]}</li>` +
`<li><b>Weather Description: </b>${description[i]}</li>` +
'</ul>';
$('#container').append(text);
}
HTML
<div id="container">
</div>
The problem is that you are appending always to the same element.
You could use a template to extract the html from your logic and to better define the groupings by which your output should exist in.
var names = [ 'Vancouver', 'Vancouver', 'Vancouver' ];
var description = [ 'light rain', 'light rain', 'light rain' ];
var mainTemp = [ 289.917, 286.551, 285.244 ];
var template = document.querySelector('#outputTemplate').innerHTML;
var $output = $('#output');
for (var i = 0; i < 3; i++) {
let $template = $(template);
$template.find('.name').text(names[i]);
$template.find('.description').text(description[i]);
$template.find('.mainTemp').text(mainTemp[i]);
$output.append($template);
}
.group {
border: 1px solid rgb(0, 0, 0);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output">
</div>
<script type="text/html" id="outputTemplate">
<div class="group">
<label>
<b>Name:</b><ul><li class="name"></li></ul>
</label>
<label>
<b>Weather Description:</b><ul><li class="description"></li></ul>
</label>
<label>
<b>Main Temp:</b><ul><li class="mainTemp"></li></ul>
</label>
</div>
</script>
I created a list of arrays dynamically, which has the following syntax:
<script>
var item1001 = new Array();
item1001[0] = 1001; //id
item1001[1] = "Item name";
item1001[2] = 500; //item price
item1001[3] = "http://whatever"; //item page link
var item1002 = new Array();
item1002[0] = 1002; //id
item1002[1] = "Item name";
item1002[2] = 600; //item price
item1002[3] = "http://whatever"; //item page link
var item1003 = new Array();
item1003[0] = 1003; //id
item1003[1] = "Item name";
item1003[2] = 700; //item price
item1003[3] = "http://whatever"; //item page link
...
</script>
Now I have a form with a SELECT populated with all the items:
<select name="items" id="items">
<option value="1001">Item name</option>
<option value="1002">Item name</option>
<option value="1003">Item name</option>
...
</select>
Just wanted to retrieve the item price when the select changes, to make some calculations with JavaScript:
jQuery( "#items" ).change(function() {
var myItemPrice="item"+Number(jQuery( "#items" ).val()+"[2]");
console.log("Item price: "+myItemPrice);
var total = Number(myItemPrice - (myItemPrice*5)/100);
console.log("Total: "+total);
});
But I don't know how to access the array, i.e. "item1001[2]" dinamically, based upon "select" value...
Just for the sake of showing how to access to a variable as a window's attribute:
var item1001 =[];
item1001[0] = 1001; //id
item1001[1] = "Item name";
item1001[2] = 500; //item price
item1001[3] = "http://whatever"; //item page link
var item1002 = [];
item1002[0] = 1002; //id
item1002[1] = "Item name";
item1002[2] = 600; //item price
item1002[3] = "http://whatever"; //item page link
var item1003 = [];
item1003[0] = 1003; //id
item1003[1] = "Item name";
item1003[2] = 700; //item price
item1003[3] = "http://whatever"; //item page link
jQuery( "#items" ).change(function() {
var myItemPrice="item"+jQuery( "#items" ).val();
console.log("Item price: "+myItemPrice);
var total = window[myItemPrice][2];
console.log("Total: "+total);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select name="items" id="items">
<option value="1001">Item name</option>
<option value="1002">Item name</option>
<option value="1003">Item name</option>
...
</select>
But you could just store your items in an object or an array:
var items= {
"1001": ["Item name", 500],
"1002": [...],
...
}
And your event handler would be much easier:
jQuery( "#items" ).change(function() {
var myItem=jQuery( "#items" ).val();
console.log("Item price: "+items[myItem][1]);
});
Use single javascript object instead:
var items = {};
items["1001"] = {name: "...", price: 100};
items["1005"] = {name: "...", price: 500};
var price = items[$('#items').val()].price;
..
You can use window to access global scope.
window['item' + $(this).val()][2]
But better restructure your initial data. You can use object to store data
var items = {
1001: { id: 1001, name: '', price: 100},
1002: { id: 1002, name: '', price: 100}
}
var price = items[$(this).val()].price
<select name="items" id="items">
<option value="1001">Item name</option>
<option value="1002">Item name</option>
<option value="1003">Item name</option>
</select>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
var item = {
1001 :{id:"1001", name:"Item name", price: 500, url:"http://whatever"},
1002 :{id:"1002", name:"Item name", price: 600, url:"http://whatever"},
1003 :{id:"1003", name:"Item name", price: 700, url:"http://whatever"}
};
$( "#items").change(function(){
var myItemPrice = item[$("#items").val()].price;
console.log("Item price: "+myItemPrice);
var total = myItemPrice - (myItemPrice*5)/100;
console.log("Total: "+total);
});
</script>
I've created a JSON file to call out the name of a list of beers to display ABV and country but I am unable to display the results on the webpage. I was able to get the select tag to drop down the list, but when selecting a beer, it will only show the selected results as "undefined."
Here is the JS code I have so far...
var $select = $("#beerListing");
var beer = Array();
var country = Array();
$.getJSON("data.json", function(data) {
$select.html('');
for (var i = 0; i < data['beer'].length; i++)
$select.append('<option id="' + data["beer"][i]['id'] + '">' + data["beer"][i]["beer_name"] + '</option>');
for (x in data) {
if (beer.indexOf(data[x].beer_name) < 0) {
var y = beer.length;
beer[y] = data[x].beer_name;
country[y] = data[x].brewery_country;
}
}
showBeerList();
});
function showBeerList() {
var select = document.getElementById('beerListing');
for (var i = 0; i < beer.length; i++) {
var obj = document.createElement("option");
obj.text = beer[i];
obj.value = i;
select.appendChild(obj);
}
}
function getBeerInfo(picked) {
if (picked == "Pick Your Poison...") {
location.reload();
} else {
document.getElementById("name").innerHTML = beer[picked];
document.getElementById("country").innerHTML = country[picked];
}
}
HTML:
<html>
<head></head>
<body>
<h1>LCBO API TESTING</h1>
<select name="beerlist" id="beerListing" class="form-control" onchange="getBeerInfo(this.value)">
</select>
<br>
<label>Name:</label>
<label id="name">--</label>
<br>
<label>Country:</label>
<label id="country">--</label>
<br>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="main.js"></script>
</body>
</html>
JSON List called data.json
{
"beer": [{
"beer_name": "Organic Devon Cider",
"brewery_name": "Luscombe Organic Drinks",
"beer_type": "Cider",
"beer_abv": "4.9",
"beer_ibu": "0",
"comment": "",
"venue_name": "The Anchor & Hope",
"venue_city": "London",
"venue_state": "Greater London",
"brewery_country": "England"
}, {
"beer_name": "Beer A",
"brewery_name": "Beer A",
"beer_type": "Cider",
"beer_abv": "4.9",
"beer_ibu": "0",
"comment": "",
"venue_name": "Beer",
"venue_city": "New York",
"venue_state": "New York",
"brewery_country": "USA"
}]
}
You seemed to be adding the options to the select element twice and using for-in which iterates properties, not entries in an array.
Below snippet will not work as requires external data source.
var $select = $("#beerListing") ;
var beer = Array();
var country = Array();
$.getJSON("data.json", function(data) {
$select.html('');
for (var i = 0; i < data.beer.length; i = i + 1) {
if (beer.indexOf(data.beer[i].beer_name) < 0) {
beer.push(data.beer[i].beer_name);
country.push(data.beer[i].brewery_country);
}
}
showBeerList();
}
function showBeerList() {
var select = document.getElementById('beerListing');
for (var i = 0; i < beer.length; i++) {
var obj = document.createElement("option");
obj.text = beer[i];
obj.value = i;
select.appendChild(obj);
}
}
function getBeerInfo(picked) {
if (picked == "Pick Your Poison...") {
location.reload();
}
else {
document.getElementById("name").innerHTML = beer[picked];
document.getElementById("country").innerHTML = country[picked];
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>LCBO API TESTING</h1>
<select name="beerlist" id="beerListing" class="form-control" onchange="getBeerInfo(this.value)">
</select>
<br>
<label>Name:</label>
<label id="name">--</label>
<br>
<label>Country:</label>
<label id="country">--</label>
<br>
I got it working here: https://jsfiddle.net/bu7pkb5f/1/
What are you doing with:
if (beer.indexOf(data[x].beer_name) < 0) {
var y = beer.length;
beer[y] = data[x].beer_name;
country[y] = data[x].brewery_country;
}
I don't understand it but it's creating a third item in the list after the two real beer entries are processed. I left it commented out in the fiddle so you can check it out for yourself.
Using knockout, I have a select (a list of names) whose options are bound to another set of knockout-bound data (people). When the name of any person changes, the value of the select option that is bound to that person's name is correctly updated. However, the select's selection is not preserved if you had that person selected already.
See this jsFiddle for a live example: http://jsfiddle.net/DbBZQ/
Select "Jane" from the list.
Change the name "Jane" to something else ("Jane Doe" for example).
Notice the select defaults back to the first item.
How can I make the selection stick to the same option index even if the underlying value has changed? Is there a way to instruct knockout to preserve the selection or do I have to do this separately using JS?
Complete Code Example
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script type="text/javascript" src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
var data =
{
people: ko.observableArray(
[
{ name: ko.observable("Jim") },
{ name: ko.observable("Jane") },
{
name: ko.observable("Sam"),
subordinates: ko.observableArray(
[
{
name: ko.observable("Tambone"),
subordinates: ko.observableArray(
[
{ name: ko.observable("Edward") },
{ name: ko.observable("Kristy") },
{ name: ko.observable("Thomas") },
{ name: ko.observable("Andy") }
])
},
{ name: ko.observable("Jules") }
])
}
])
};
var allNames = ko.computed(function ()
{
var names = [];
var selector = function (name, indent)
{
var option =
{
value: name,
text: (indent || "") + name
};
return option;
};
for (var i = 0; i < data.people().length; i++)
{
names.push(selector(data.people()[i].name()));
addSubordinates(names, 1, data.people()[i].subordinates, selector);
}
return names;
});
function addSubordinates(names, depth, subordinates, selector)
{
if (subordinates != null)
{
var indentText = "";
for (var i = 0; i < depth; i++)
indentText += ". . ";
for (var i = 0; i < subordinates().length; i++)
{
names.push(selector(subordinates()[i].name(), indentText));
addSubordinates(names, depth + 1, subordinates()[i].subordinates, selector);
}
}
}
</script>
</head>
<body>
<div data-bind="foreach: data.people">
<input type="text" data-bind="value: name" /><br />
</div>
Add Person
<br /><br /><br />
<select data-bind="options: allNames, optionsValue: 'value', optionsText: 'text', optionsCaption: 'All Names...'" />
<script type="text/javascript">
ko.applyBindings();
</script>
</body>
</html>
The reason the selection is lost is because the selected value is matched directly to the name property, which changes. As a result, the selected value no longer exists in the data source (allNames).
If you want to retain the selection, you have a couple of options:
Implement a hack such as tracking the index, and resetting it after the value changes
Bind the selected value to a property that doesn't change.
Do you have an immutable property that you can use as the selected value?
For the sake of an example, I added an id property to the objects in the data source, and use that as the selected value instead of name. This works the way you expect:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script type="text/javascript" src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
var data =
{
people: ko.observableArray(
[
{ id: 1, name: ko.observable("Jim") },
{ id: 2, name: ko.observable("Jane") },
{
id: 3, name: ko.observable("Sam"),
subordinates: ko.observableArray(
[
{
id: 4, name: ko.observable("Tambone"),
subordinates: ko.observableArray(
[
{ id: 5, name: ko.observable("Edward") },
{ id: 6, name: ko.observable("Kristy") },
{ id: 7, name: ko.observable("Thomas") },
{ id: 8, name: ko.observable("Andy") }
])
},
{ id: 9, name: ko.observable("Jules") }
])
}
])
};
var allNames = ko.computed(function ()
{
var names = [];
var selector = function (id, name, indent)
{
var option =
{
value: id,
text: (indent || "") + name
};
return option;
};
for (var i = 0; i < data.people().length; i++)
{
names.push(selector(data.people()[i].id, data.people()[i].name()));
addSubordinates(names, 1, data.people()[i].subordinates, selector);
}
return names;
});
function addSubordinates(names, depth, subordinates, selector)
{
if (subordinates != null)
{
var indentText = "";
for (var i = 0; i < depth; i++)
indentText += ". . ";
for (var i = 0; i < subordinates().length; i++)
{
names.push(selector(subordinates()[i].id,subordinates()[i].name(), indentText));
addSubordinates(names, depth + 1, subordinates()[i].subordinates, selector);
}
}
}
</script>
</head>
<body>
<div data-bind="foreach: data.people">
<input type="text" data-bind="value: name" /><br />
</div>
Add Person
<br /><br /><br />
<select data-bind="options: allNames, optionsValue: 'value', optionsText: 'text', optionsCaption: 'All Names...'" />
<script type="text/javascript">
ko.applyBindings();
</script>
</body>
</html>
Edit:
As an alternative, what if you set up the value property so that it was a ko.computed that returned the index of the item? Like this:
var allNames = ko.computed(function ()
{
var names = [];
var selector = function (item, name, indent)
{
var option =
{
value: ko.computed(function(){ return data.people().indexOf(item);}),
text: (indent || "") + name
};
return option;
};
for (var i = 0; i < data.people().length; i++)
{
names.push(selector(data.people()[i], data.people()[i].name()));
addSubordinates(names, 1, data.people()[i].subordinates, selector);
}
return names;
});
function addSubordinates(names, depth, subordinates, selector)
{
if (subordinates != null)
{
var indentText = "";
for (var i = 0; i < depth; i++)
indentText += ". . ";
for (var i = 0; i < subordinates().length; i++)
{
names.push(selector(subordinates()[i],subordinates()[i].name(), indentText));
addSubordinates(names, depth + 1, subordinates()[i].subordinates, selector);
}
}
}