Reputation: 255
I need to write a function that takes in 2 arguments, the first argument is a list of <li>
elements and the second argument is an object. The object is list of products and their prices. All the <li>
elements will have text containing a name of a product.The function should check the price of each product mentioned, calculate and return the total price.
Example:
<ul>
<li>oreos<li/>
<li>milk<li/>
<ul/>
let products = {
oreos: 20,
milk: 17,
bread: 12,
doritos: 10
}
I have tried using a for in/of loop to go through the products object and match it to the <li>
using .innerText
but am unsure of how to go about doing it.
Please help out
Upvotes: 4
Views: 915
Reputation: 68933
You can try with querySelectorAll()
and Array.prototype.reduce()
.
Please Note: You are closing the elements in the wrong way (<li/>, <ul/>
) which will create unexpected markup, should be </li>, </ul>
.
let products = {
oreos: 20,
milk: 17,
bread: 12,
doritos: 10
};
function getTotal(li, prod){
return Array.from(li).reduce((a,c) => a + prod[c.textContent], 0);
}
console.log(getTotal(document.querySelectorAll('li'), products));
<ul>
<li>oreos</li>
<li>milk</li>
</ul>
Upvotes: 1
Reputation: 48600
You fist need to fix your end-tags; the slash comes before the final tag name.
Second, you can reduce all your list values by grabbing their text value and looking them up in the product list. You can use Array.from
to translate a NodeList
into an array so that you can call Array.prototype.reduce
.
const products = {
oreos: 20,
milk: 17,
bread: 12,
doritos: 10
}
let total = calculateTotal(document.querySelector('ul.items'), products)
console.log(`Total = ${total}`)
function calculateTotal(ul, products) {
return Array.from(ul.querySelectorAll('li'))
.reduce((sum, li) => sum + products[li.textContent] || 0, 0)
}
<ul class="items">
<li>oreos</li>
<li>milk</li>
</ul>
Upvotes: 1
Reputation: 1228
function getPrice()
{
let products = {
oreos: 20,
milk: 17,
bread: 12,
doritos: 10
}
var items = document.getElementsByTagName("li");
var price = 0;
for (i = 0; i < items.length; i++) {
var item = items[i];
var val = parseFloat(products[item.innerHTML]);
price += val;
}
alert("Total price is: " + String(price));
}
You can then hook the function getPrice
to the onclick property of a button to see the result. You may want to give your lists a class, or give the ul
an id, so that getPrice
doesn't return all the lists on your HTML page.
Upvotes: 0
Reputation: 410
What you can do is that, you can use the following function:
let totalPrice = (priceList, products) => {
return products.reduce((total, elem) => {
total += priceList[elem.innerText];
return total;
}, 0)
}
This function iterates on list of products using Array.reduce and adds the list of product prices and returns the total.
You should checkout Array.reduce() for more clarity.
Upvotes: 5
Reputation: 10879
Here's what your function could look like:
I used Array.from()
and Array.prototype.reduce()
to achieve this all in one go. Of course you'd need a distinct class or even better an ID on the list instead of simply selecting all list items on the page.
let products = {
oreos: 20,
milk: 17,
bread: 12,
doritos: 10
}
function getTotal(listElements, productPrices) {
var total = Array.from(listElements).reduce(function(total, listItem) {
total += productPrices[listItem.textContent] || 0;
return total;
}, 0);
return total;
}
console.log(getTotal(document.querySelectorAll('li'), products));
<ul>
<li>oreos</li>
<li>milk</li>
</ul>
Upvotes: 2
Reputation: 382
To put you in the right direction (untested):
From: https://www.sitepoint.com/community/t/looping-through-li-elements-in-ul/6049/2 and Check if a key exists inside a json object
<ul id="foo">
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
var ul = document.getElementById("foo");
var items = ul.getElementsByTagName("li");
for (var i = 0; i < items.length; ++i) {
// do something with items[i], which is a <li> element
if((items[i] in products)) alert("yeah");
}
Read this also: Looping through list items with jquery
Trust this helps.
Upvotes: 0
Reputation: 2303
You can add an id, let's say "list" to your <ul>
, then do something like this:
let list = document.getElementById("list");
let totals = {};
for(let key of products) {
totals[key] = 0;
}
for(let i = 0; i < list.children.length; i++) {
let child = list.children[i];
let text = child.textContent;
if(totals.hasOwnProperty(text)) {
totals[text]++;
}
}
let fullPrice = 0;
for(let key of products) {
fullPrice += products[key] * totals[key];
}
console.log(fullPrice);
The code does the following:
totals
object, which will count the occurrences of each existing product in your products
object.<ul>
element, and loops through its <li>
children elements, taking the text of each <li>
and looking it up in the totals
object.PS: This code assumes there will be only <li>
elements inside your list, and that each <li>
holds only text.
Upvotes: 1
Reputation: 5556
Loop through the li elements, use their innerText as the key to lookup the price, sum them, and you're good:
let total = 0;
document.querySelectorAll('li').forEach(item => {
total += products[item.innerText];
});
There are other forms of this, and little additions you could include (such as checking that the item actually exists in the products array first), but that's the basic idea.
Upvotes: 2