Note: I know there may be ways to do this in other languages but I have only learned javascript.
I have an array of objects (food items in this case, each item has a name property). I have this code in a for loop that makes buttons for each item in the array (if the first item in the array has a name of cake then cake's button is called cake, if the item is called fries then the buttons name is fries). I want the user to be able to click the button for each item only once, and when that button is clicked, I want to display a list of each item clicked. The reason why I have var click = item[i].name is because I want each button to have the name of the item. This code makes a button for item in the array but it does not list the items clicked on. Here is my code:
HTML
<html>
<head>
</head>
<body>
<p id="likes">Likes: </p>
</body>
</html>
JAVASCRIPT
var items=[
{
name:"cake",
price:12
},
{
name:"fries",
price:10
},
{
name:"apple",
price:11
}
];
window.onload = function() {
for (var i = 0; i < items.length; i++) {
var btnItems = document.createElement("button");
btnItems.id = "btnItems";
btnItems.innerHTML = "Items";
var clicks = items[i].name;
btnItems.onclick = function () {
el.disabled = true;
clicks += items[i].name + i;
document.getElementById("clicks").innerHTML = "Items Clicked" + clicks;
}
}
Style your view as you wish but this should answer your problem
var items = [{
name: "cake",
price: 12
},
{
name: "fries",
price: 10
},
{
name: "apple",
price: 11
}
];
for (let i = 0; i < items.length; i++) {
const btn = document.createElement("button");
btn.id = "btnItems";
btn.textContent = items[i].name;
btn.onclick = function(el) {
// disable your button immediately upon click
el.target.disabled = true;
// create list element and assign value
const li = document.createElement('li');
li.textContent = items[i].name
// append list element to your <ul> list
document.getElementById('list-section').appendChild(li);
}
// append button to the DOM
document.body.appendChild(btn)
}
<ul id="list-section">
</ul>
HTML code:
I created a div to append the buttons in it.
<html>
<head>
</head>
<body>
<p id="likes">Likes: </p>
<p id="clicks"></p>
<div id="btn-container">
</div>
</body>
</html
>
Js code:
var items=[
{
name:"cake",
price:12
},
{
name:"fries",
price:10
},
{
name:"apple",
price:11
}
];
for (var i = 0; i < items.length; i++) {
var btnItems = document.createElement("button");
btnItems.id = "btnItems"+i;
var clicks = items[i].name;
btnItems.innerHTML = clicks;
document.getElementById("btn-container").appendChild(btnItems);
console.log(btnItems);
btnItems.addEventListener('click',function (el) {
alert('here');
el.disabled = true;
clicks += items[i].name + i;
document.getElementById("clicks").innerHTML = "Items Clicked" + clicks;
});
}
As you have not provided a reproducible example I cannot test this, however, you should be able to use something like this. Please take note of the comments and amend where necessary.
window.onload = function() {
for (var i = 0; i < items.length; i++) {
var btnItem = document.createElement("button");
const name = item[i].name;
// Set the button id
btnItem.id = `btnItem-${name}`;
// Set the button text to the item name
btnItem.innerHTML = name
btnItem.addEventListener('click', function (event) {
event.target.disabled = true;
// Do whatever you want here, e.g. add "name" to a list
}
}
}
Related
I have two buttons SHOW and HIDE. When show is clicked numbers will appear (which are json files, each json file contain only one number 1, 2, 3..) when HIDE is clicked first number(json) in a row dissapear. For example we clicked SHOW button 3 times and got this: 1 2 3 and then clicked HIDE once then we got: 2 3 shown. My problem is when HIDE is clicked I want to save that deleted number by showing it in my div where id="nome". After another clicking on button HIDE another hidden number is shown and old is deleted from div.
var pageCounter = 1;
var pageCounterr = 1;
var animalContainer = document.getElementById("animal-info");
var animalContainerr = document.getElementById("nome");
var btn = document.getElementById("btn");
var btnn = document.getElementById("btnn");
btn.addEventListener("click", function() {
var ourRequest = new XMLHttpRequest();
ourRequest.open('GET', 'http://10.0.9.243/animals-' + pageCounter + '.json');
ourRequest.onload = function() {
var ourData = JSON.parse(ourRequest.responseText);
renderHTML(ourData);
};
ourRequest.send();
pageCounter++;
});
function renderHTML(data) {
var htmlString = document.createElement("div");
for (i = 0; i < data.length; i++) {
let pText = document.createTextNode(data[i].name);
let pElement = document.createElement("p");
pElement.append(pText);
htmlString.append(pElement);
htmlString.classList.add('containers') // new Line added
}
animalContainer.append(htmlString);
}
btnn.addEventListener("click", function() {
let containers = document.getElementsByClassName('containers');
if (containers.length > 0) {
containers[0].remove();
}
});
<button id="btn">SHOW</button>
<button id="btnn">HIDE</button>
<h2>Numbers:</h2>
<div id="animal-info"></div>
<h2>Hidden number is:</h2>
<div id="nome"></div>
I have a problem with the function below. It's taking the data from JSON and it's creating a menu item. The problem is when there are more than 2 menu items, and I try to increase the quantity of the first item then the value of the second item is increasing.
function ShowTheMenu(theCategoryId) {
var parentEl = document.getElementById("itemlist");
ClearMenu();
for (let i = 0; i < data.length; i++) {
if (data[i].KategorijaBroj == theCategoryId) {
// MAIN PARENT
var itemBox = document.createElement("div");
itemBox.classList.add("itembox");
var itemImage = document.createElement("img");
itemImage.classList.add("itemimage");
itemImage.src = "/menuitemsimages/" + data[i].Image;
var itemContent = document.createElement("div");
itemContent.classList.add("itemcontent");
var itemTitle = document.createElement("h3");
itemTitle.classList.add("itemtitle");
itemTitle.innerHTML = data[i].Title;
var itemPrice = document.createElement("p");
itemPrice.classList.add("itemprice");
itemPrice.innerHTML = "$" + data[i].Price;
var itemQnt = document.createElement("p");
itemQnt.classList.add("quantity");
itemQnt.innerHTML = "Quantity";
var buttonsBox = document.createElement("div");
buttonsBox.classList.add("divcontrolbtns");
var itemQuantity = 0;
var quantityValue = document.createElement("div");
quantityValue.innerHTML = itemQuantity;
var increaseBtn = document.createElement("div");
increaseBtn.classList.add("controlbtns");
increaseBtn.innerHTML = "+";
increaseBtn.addEventListener("click", function () {
if(itemQuantity < 10) {
itemQuantity++;
}
quantityValue.innerHTML = itemQuantity;
})
var decreaseBtn = document.createElement("div");
decreaseBtn.classList.add("controlbtns");
decreaseBtn.innerHTML = "-";
decreaseBtn.addEventListener("click", function () {
if(itemQuantity > 0) {
itemQuantity--;
}
quantityValue.innerHTML = itemQuantity;
})
var itemAddToCart = document.createElement("button");
itemAddToCart.classList.add("btn-add-to-cart");
itemAddToCart.textContent = "Add to cart";
var itemDesc = document.createElement("p");
itemDesc.classList.add("itemdesc");
itemDesc.innerHTML = data[i].Description;
itemBox.appendChild(itemImage);
itemContent.appendChild(itemTitle);
itemContent.appendChild(itemDesc);
itemContent.appendChild(itemPrice);
itemContent.appendChild(itemAddToCart);
itemContent.appendChild(itemQnt);
buttonsBox.appendChild(increaseBtn);
buttonsBox.appendChild(quantityValue);
buttonsBox.appendChild(decreaseBtn);
itemContent.appendChild(buttonsBox);
itemBox.appendChild(itemContent);
parentEl.appendChild(itemBox);
}
}
}
IMAGE
What should I do in order for the chosen menu item value to be changed?
Try to do something like this bellow. I try to use same HTML structure that you use but to be honest, I suggest that you change a little bit ;)
<!DOCTYPE html>
<html>
<head>
<script>
// Qt
var quantity = new Array();
function ShowTheMenu(theCategoryId) {
// Clear menu
// ClearMenu();
// bt+
increaseBtn = (i) => {
// Item target
let item = document.getElementById('item_' + i);
// Qt target
let qtSpan = item.getElementsByClassName('qt');
// Qt
let qt = parseInt(qtSpan[0].innerHTML);
// Fix some errors
if (qt === undefined || !qt) qt = 0;
// Increase
if (qt < 10) qt++;
// Update
qtSpan[0].innerHTML = qt;
};
// bt-
decreaseBtn = (i) => {
// Item target
let item = document.getElementById('item_' + i);
// Qt target
let qtSpan = item.getElementsByClassName('qt');
// Qt
let qt = parseInt(qtSpan[0].innerHTML);
// Fix some errors
if (qt === undefined || !qt) qt = 0;
// Decrease
if (qt > 0) qt--;
// Update
qtSpan[0].innerHTML = qt;
};
//
var data = new Array();
data[0] = {
Image:
'https://s2.glbimg.com/WcYUQNaattnUf7d8U8MUBfk7loU=/620x430/e.glbimg.com/og/ed/f/original/2015/10/30/pizza.jpg',
KategorijaBroj: 1,
Title: 'Delicious Pizza',
Price: 10,
Description: 'Description test',
};
for (let i = 0; i < data.length; i++) {
if (data[i].KategorijaBroj == theCategoryId) {
// Img
let img = data[i].Image; // '/menuitemsimages/' + data[i].Image;
// Title
let title = data[i].Title;
// Price
let price = '$' + data[i].Price;
// Description
let desc = data[i].Description;
// Qtd
let qt = 2;
// Matriz
let newItem = `<div id="item_${i}" class="itembox">
<div class="itemcontent">
<img src="${img}" border=0 width=100/>
<h3 class="itemtitle">${title}</h3>
<p class="itemprice">${price}</p>
<div class="quantity">
<span>Quantity : </span>
<span class="qt">${qt}</span>
</div>
<div class="controlbtns">
<button class="addbtn" onClick="increaseBtn(${i})">+</button>
<button class="removebtn" onClick="decreaseBtn(${i})">-</button>
</div>
<button class="btn-add-to-cart">Add to cart</button>
<p class="description">${desc}</p>
</div>
</div>`;
// Get the menulist itens
let parentEl = document.getElementById('itemlist');
// Add item
parentEl.insertAdjacentHTML('beforeend', newItem);
}
}
}
</script>
</head>
<body>
<div id="itemlist"></div>
<script>
ShowTheMenu(1);
</script>
</body>
</html>
It's because both items are sharing the same variable, in this case, itemQuantity.
Option 1
If they all should have their own counter I would recommend using an object for tracking this.
const itemQuantity = {
'item1': 2,
'item2': 5
}
if you add some unique class or id to the element you can use this in your onclick event to use as a key. (Where I used 'item1' and 'item2')
Option 2
If you create a function that does everything that's inside your for loop and then just call that function it should also work. This works because every function then creates its own scoped variable of itemQuanity.
Go with whatever options feel best for now. How to manage data in your frontend has a lot of different ways and opinions. You'll quickly discover what works best in what scenario.
What Olavo Mello is mentioning in his answer could still make your code better. using string literals for small HTML snippets is often more readable than using document.createElement(). I would recommend fixing your counter issue first and then look if you could improve your code with Olavo Mello's answer in mind. Good luck :)
Hi guys I am trying to loop through 2 arrays , one array handles button Ids , the other handles the text. However it does not seem to be able to iterate through the text array. When I try to window.alert the value , it returns undefined.
var buttonIdArray = ['#one', '#two']
var textArray = ['this is button one', 'this is button two']
function buttonDetails() {
for (var i = 0; i < buttonIdArray.length; i++) {
$(buttonIdArray[i]).click(function() {
window.alert(textArray[i])
})
}
}
<button id ='one'>one</button>
<button id ='two'>two</button>
Because of the different scope in the .click() context you need to get your text from textArray before, like this:
var buttonIdArray = ['#one', '#two']
var textArray = ['this is button one', 'this is button two']
function buttonDetails() {
for (var i = 0; i < buttonIdArray.length; i++) {
const text = textArray[i]
$(buttonIdArray[i]).click(function() {
window.alert(text)
})
}
}
buttonDetails()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id='one'>one</button>
<button id='two'>two</button>
You can use index() of jQuery.(like below)
var buttonIdArray = ['#one','#two'];
var textArray=['this is button one','this is button two'];
for (var i =0; i<buttonIdArray.length;i++)
{
$(buttonIdArray[i]).click(function(){
console.log(textArray[$(this).index()-1]);
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id ='one'>1</button>
<button id ='two'>2</button>
This is how I would do it.
var textArray=["this is button 1","this is button 2"];
$('.myButtons').click(function(){
var index = $(this).index();
alert(textArray[index]);
});
<button class='myButtons' id="one">
Button 1
</button>
<button class='myButtons' id="two">
Button2
</button>
JS fiddle here
Or like this...
$('.myButtons').click(function(){
alert($(this).data('text'));
});
<button class='myButtons' id="one" data-text="this is my text">
Button 1
</button>
<button class='myButtons' id="two" data-text="this is my text 2">
Button2
</button>
Or like this...
var buttonArray =[
{id:'#one',text:"this is button1"},
{id:'#two',text:"this is button2"}
];
for (var i = 0; i < buttonArray.length; i++) {
var index = i;
$(buttonArray[index].id).click(function() {
alert(buttonArray[index].text);
});
}
Js Fiddle 2
Or Like this...
var buttonIdArray = ['#one', '#two']
var textArray = ['this is button one', 'this is button two']
function buttonDetails() {
for (var i = 0; i < buttonIdArray.length; i++) {
var text = textArray[i]
$(buttonIdArray[i]).click(function() {
window.alert(text)
})
}
}
buttonDetails()
There is probably a better way to do it than this, but this is how I solved your issue.
var buttonIdArray = ['#one', '#two']
var textArray = ['this is button one', 'this is button two']
function buttonDetails() {
for (var i = 0; i < buttonIdArray.length; i++) {
$(buttonIdArray[i]).attr('textArrayIndex', i)
}
}
$('button').click( function() {
window.alert(textArray[$(this).attr('textArrayIndex')]);
})
buttonDetails();
Basically, you can't have an event listener within a loop. It doesn't work.
JSFiddle
The first part of the code is working correctly, but now that each button appears, how do i add functionality to each of them? currently the only button which does something when pressed is always the last one, the rest do nothing.
Change it to
{
var output = "";
var data = JSON.parse(e.target.responseText);
for(var i=0; i<data.length; i++)
{
output = data[i].title + ' ';
var p = document.createElement("p");
var div = document.getElementById("response");
var textNode = document.createTextNode(output);
p.appendChild(textNode);
var button = document.createElement("button");
button.innerHTML = "Download";
p.appendChild(button);
div.appendChild(p);
button.addEventListener ("click", () =>
{
alert("Test");
});
}
}
You are adding the below code out side the for loop
button.addEventListener ("click", () =>
{
alert("Test");
} );
Keep the above code inside the for loop. So that for each button the event listener will be added.
Another way to approach this would be to add the callback function to the onclick variable of the elements prototype:
function doStuff() {
var output = "";
var data = JSON.parse(e.target.responseText);
for (var i = 0; i < data.length; i++) {
output = data[i].title + ' ';
var p = document.createElement("p");
var div = document.getElementById("response");
var textNode = document.createTextNode(output);
p.appendChild(textNode);
var button = document.createElement("button");
button.innerHTML = "Download";
// Adds the callback function here
button.onclick = () => {
// fill in your arrow function here...
alert("Test");
};
p.appendChild(button);
div.appendChild(p);
};
}
doStuff();
Here is a jsFiddle
You should use event delegation for dynamically added elements
// sample data
var data = [{
title: 'one'
}, {
title: 'two'
},{
title: 'three'
}];
var output = "";
for (var i = 0; i < data.length; i++) {
var output = data[i].title + " ";
var p = document.createElement("p");
var div = document.getElementById("response");
var textNode = document.createTextNode(output);
p.appendChild(textNode);
var button = document.createElement("button");
// added output to button text for identification
button.innerHTML = output + " Download";
p.appendChild(button);
div.appendChild(p);
}
// Get the parent element, add a click listener
document.getElementById("response").addEventListener("click", function(e) {
// e.target is the clicked element!
// If it was a button
if (e.target && e.target.nodeName == "BUTTON") {
// Button found! Output the identifying data!
// do other work on click
document.getElementById("display").innerHTML = e.target.innerHTML + " Clicked";
}
});
<div id="response"></div>
<div id="display">Display</div>
I have an un-ordered list with items that are generated programatically in web2py...
I'm displaying them in HTML as displayed below... I want to have a textbox that allows a user to type in a string. this string should "toggle" the visibility of the <li> values if they match or not.
<input type="text" id="userTextSearch" onkeyup="listSearch(this.value)"></input>
<ul id="fileResultsID">
{{for item in mylist:}}
<li>
<input type="checkbox" name="FileListItem" id="value"> {{=item}}</label>
</li>
{{pass}}
</ul>
function listSearch(textValue)
{
var fileGroup = document.getElementById('fileResultsID');
var items = fileGroup.getElementsByTagName('li');
var chkBx;
for(var i = 0, n = items.length; i < n; i++)
{
chkBx = items[i].getElementsByTagName('input');
alert(chkBx.InnerHtml);
//if(!items[i].value.startswith(textValue))
//{
// items[i].toggle();
//}
}
}
So far when I type, nothing visible occurs...
Q: How can get certain <li> row items to disappear as the user types?
I will need them all to comeback if the text box is empty too btw
This is what worked for me... I also have a quick loop to renable all of the list items if the textbox is cleared out.
function listSearch(textValue){
var fileGroup = document.getElementById('fileResultsID');
var items = fileGroup.getElementsByTagName('li');
var chkBx;
//check to see if user deleted everything first
if(!textValue)
{
for(var i = 0, n = items.length; i < n; i++)
{
items[i].style.display = "block";
}
}
for(var i = 0, n = items.length; i < n; i++)
{
chkBx = items[i].getElementsByTagName('input');
var str = chkBx[0].id
if(!str.toLowerCase().startsWith(textValue.toLowerCase()))
{
items[i].style.display = "none";
}
}}