I'm working on a program where I add items to a cart and I have the totals compute dynamically as things are added and removed. My problem is when I change the totals with a selected list. Right now only the first item in the shopping cart's quantity selector works.
Also when I add new items to the cart the quantity switches back to 1. Anyway to solidify my quantity values?
I would REALLY appreciate any help that can be given. I've been looking at this code for hours trying to figure out why I can't get everything to work right.
Here's my code revolving around the cart and manipulating it:
//Activates "Add" button so cart can be populated
$('#item-list').on('click', '.addme', function(){
// 1. Read the item index using data- attribute
var index = $(this).data('index');
if(!inCart(index)){
cart.push(index);
}
// 3. Update the cart list and total credits
displayCartItems();
checkCart();
// update price
calculateTotalPrice();
});
//function to check if items are in cart
function inCart(index){
for (var i=0; i<cart.length; i++){
if (cart[i] == index)
return true;
}
return false;
}
//Displays the shopping cart items
function displayCartItems(){
// create a table row for each item in cart array
var itemInfo = '';
for (var i=0; i<cart.length; i++){
var index = cart[i];
itemInfo += createTableRow(index);
}
$('#selected-list').html(itemInfo);
}
//Constructs the shopping cart table
function createTableRow(index){
var trow = '';
trow += "<tr><td>"+item_list[index].title + "</td>>";
trow += "<td id='itemsprice'>"+item_list[index].price + "</td>";
trow += "<td><select class='item-quantity' data-quantity='"+index+"'><option value='1'>1</option><option value='2'>2</option><option value='3'>3</option><option value='4'>4</option><option value='5'>5</option><option value='6'>6</option><option value='7'>7</option><option value='8'>8</option><option value='9'>9</option><option value='10'>10</option></td>";
trow += "<td id='tc-item'>"+item_list[index].price+"</td>"
trow += "<td><button type='button' class='delete-item' value='"+index+"'>Delete</button></td></tr>";
return trow;
}
//When quantity is changed change the value and compute new totals
$('#selected-list').on('change', '.item-quantity', function(){
calculateTotalPrice();
});
//If delete button is pressed in cart, the item is removed from the cart
$('#selected-list').on('click', '.delete-item', function(){
var index = $(this).val();
removeItemFromCart(index);
calculateTotalPrice();
checkCart();
});
function checkCart(){
if(cart.length == 0){
$('#empty-cart').html("Your cart is empty!");
} else {
$('#empty-cart').html("");
}
}
//function to remove items from the shopping cart
function removeItemFromCart(index){
// identify and remove the index from the cart and redisplay cart table
var pos = -1;
for (var i=0; i<cart.length; i++){
if (index == cart[i]){
pos = i;
break;
}
}
if (pos>-1){
cart.splice(pos, 1);
// reset the cart table
displayCartItems();
} else {
alert("Could not find!");
}
}
function calculateTotalPrice(){
var quantity = $('.item-quantity').val();
var subtotal = 0;
var tax = 0;
var shipping = 0;
var total = 0;
//for loop to calculate the subtotal
for(var i = 0; i < cart.length; i++){
var productPrice = item_list[cart[i]].price;
subtotal += productPrice * quantity;
}
//Percent taxed is 6%
var taxPerc = .06;
//Calculating taxes
tax = subtotal * taxPerc;
//Percent for shipping is 2%
var shippingPerc = .02;
//Calculating shipping
shipping = subtotal * shippingPerc;
//Calculating total
total = subtotal + tax + shipping;
//Displaying totals
//$('#tc-item').html(totalItemPrice.toFixed(2));
$('#subtotal').html(subtotal.toFixed(2));
$('#tax').html(tax.toFixed(2));
$('#shipping').html(shipping.toFixed(2));
$('#total').html(total.toFixed(2));
}
//Activates the Display cart and Hide cart buttons in shopping cart
$('#show-cart').on('click', function(){
$('#selected-list').show();
});
$('#hide-cart').on('click', function(){
$('#selected-list').hide();
});
I'm positive my calculateTotalPrice() function needs some tweaking, but I've been unable to figure out how to fix it thus far.
Here's the rest of my code if anyone needs it:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html>
<head>
<meta charset="utf-8">
<!-- Set the viewport so this responsive site displays correctly on mobile devices -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sam's Discount Store </title>
<!-- Include bootstrap CSS -->
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"> </script>
<style type="text/css">
.courselist { cursor: pointer;}
.t-head { color: #fff; background-color: #333366; font-size: 20px; line- height: 20px; }
#top-box, #footer { background-color: #330066; color: #fff; text-align: center;}
#content {border: 1px solid #330099;}
</style>
<script>
$(function(){
/* The following function defines a constructor for creating an array of objects with four properties.
The keyword "this" refers to the instance of the object
*/
function Item(type,title,description,price){
this.type = type;
this.title = title;
this.description = description;
this.price = price;
}
//create an array to store items
var item_list = [];
var cart = []; //store index of elements in the shopping cart
//add items
//add baseballgear items
item_list.push(new Item('baseballgear','Louisville Slugger', 'The finest craftsmanship and finest materials ensure stepping to the plate with the Louisville Slugger® M9 Maple M110 Bat will allow you to swing what the pros swing.', 79.99 ));
item_list.push(new Item('baseballgear','Marucci Bat', 'Named for one of the most lethal hitters in the game, the Marucci® CUTCH22 Pro Model Baseball Bat features the same cut and finish swung by MLB® center fielder, Andrew McCutchen. The "Cutch" features a large, powerful, balanced barrel with a sleek cherry red and grey finish to deliver maximum performance at the plate. This adult wooden bat is also handcrafted and bone-rubbed to ensure superior quality and surface hardness.', 139.99));
item_list.push(new Item('baseballgear', 'Rawlings Glove', "Unrivaled quality season after season, the Rawlings® 11.25'' Pro Preferred® Series Glove returns to provide elite craftsmanship and superior performance for elite middle infielders.",349.99));
item_list.push(new Item('baseballgear', 'Wilson Glove', "Enhance your field performance with unrivaled dependability with the Wilson® 11.5 A2000™ Series Glove. Made with Pro Stock® leather for long-lasting performance, this glove's construction is preferred by professionals for its top-notch quality. Dri-Lex® technology in the wrist lining transfers moisture away from the skin to keep you cool and dry. The advanced design has been improved upon by the Wilson&Reg; Advisory Staff.",249.99 ));
item_list.push(new Item('baseballgear', 'Easton Baseball Helmet', 'Give your favorite player maximum protection at the plate with the Easton® Junior Z5 Elite Baseball Helmet. The ABS shell withstands impact and disperses energy away from the head, with a stylish Digi-Camo design. Featuring dual density foam liner for advanced comfort, this helmet boasts BioDri™ padded inner liner to wick moisture away from the skin to keep them cool and dry. Wrapped ear pads provide enhanced coverage around the head.', 54.99));
item_list.push(new Item('baseballgear', 'Rawlings Batting Gloves', 'Get the most out of your batting gloves this season with the Rawlings® Adult Workhorse 950 Batting Gloves. These gloves feature an Oiltac® leather palm pad to provide better grip and softness. Equipped with a Dura-Plus™ pad for added protection in the palm, the Dynamic Fit System™ provides greater comfort, flex, and feel during every play. The adjustable wrist closure is reinforced to provide a more secure fit', 34.99));
//add soccergear items
item_list.push(new Item('soccergear', 'Nike Ordem Soccer Ball', 'Hit the back of the net with the The Nike® Ordem 3 PL Soccer Ball. The Ordem 3 is the official match ball of the English Premier League for the 2015-2016 season. This FIFA® approved ball features Aerowtrac grooves and a micro-textured casing for accurate flight. The carbon latex bladder and fuse-welded construction allow for an exceptional touch while the vivid visual Power Graphics allow you to track the ball so you can react quickly.', 150.00));
item_list.push(new Item('soccergear', 'Wilson Shinguard', 'Maximize your protection for practice or game day with the Wilson® NCAA® Forte ll Soccer Shinguard. This high impact shinguard is constructed of a removable inner shell for adjustable protection to diffuse impact during elite-level play. Its Lycra® sleeve contains power band enhancements for added compression and blood circulation. Focus on your game with the Wilson® NCAA® Forte ll Soccer Shinguard.', 24.99 ));
item_list.push(new Item('soccergear', 'Adidas Goalie Gloves', 'Protect the goal line with intensity when you sport the adidas® Ace Zones Pro Soccer Goalie Gloves. Evo Zone Technology delivers superior catching and control so you can dominate the game from the net. The negative cut ensures a snug feel while seamless touch features deliver breathability through the latex and foam construction. A stretch-strap wraps your hand to complete the gloves with a comfortable fit.', 114.99));
item_list.push(new Item('soccergear', 'Storelli Exoshield Goalie Jersey', 'Block kicks to the net with maximum mobility in the Storelli® Exoshield GK Adult Goalie Gladiator Jersey. This jersey withstands impact between the posts with polyurethane foam protection at the elbows. For increased comfort, the compression material wicks moisture away to keep the skin cool and dry. Dive and defend without distraction in the lightweight Storelli® Exoshield GK Adult Goalie Gladiator Jersey.', 64.99));
item_list.push(new Item('soccergear', 'Storelli BodyShield Slider Shorts', "Enjoy superior protection with the classic fit of the Storelli® sliders. Lightweight foam padding delivers high-performance protection to keep you safe from impact, swelling and cuts, while the unique design lets you freely move while the pads stay in place. Stay safe on the field with the antimicrobial technology and lightweight padding of the Storelli® Men's Slider Shorts.", 59.99));
item_list.push(new Item('soccergear', 'Adidas Estadio Teamp Backpack', 'Transport your gear to and from the field in style with the adidas® Estadio Team Backpack II. Built with soccer in mind, this backpack is constructed with multiple compartments to conveniently organize and store all of your gear. LoadSpring™ technology adds comfort to the shoulder straps so you can carry more equipment. FreshPAK™ shoe compartment keeps gear fresh throughout the season.', 55.00));
//add videogames
item_list.push(new Item('videogames', 'Star Wars Battlefront', 'Visit classic planets from the original Star Wars™ trilogy, detailed with an unprecedented amount of realism and sense of authenticity that will transport you to a galaxy far, far away', 59.99));
item_list.push(new Item('videogames', 'Just Cause 3', "The Mediterranean republic of Medici is suffering under the brutal control of General Di Ravello, a dictator with an insatiable appetite for power. Enter Rico Rodriguez, a man on a mission to destroy the general's ambitions by any means necessary. With more than 400 square miles of complete freedom from sky to seabed, and a huge arsenal of weaponry, gadgets and vehicles, prepare to unleash chaos in the most creative and explosive ways you can imagine.", 59.99));
item_list.push(new Item('videogames', 'Call of Duty Black Ops III', 'Call of Duty: black Ops III is the ultimate 3-games-in-1 experience. The Campaign you must navigate the hot spots of a new Cold War to find your missing brothers. Multiplayer features a new momentum-based chained movement system, allowing players to fluidly move through the environment with finesse. No Treyarch title would be complete without its signature Zombies offering "Shadows of Evil" has its own distinct storyline right out of the box.', 59.99));
item_list.push(new Item('videogames', 'Fallout 4', 'The epic storylines, adrenaline-pumping action and explosive thrills are back. The Fallout franchise returns with Fallout 4. Grab your controller and get ready to dive back into the enveloping storyline of this legendary series.', 59.99));
item_list.push(new Item('videogames', 'Halo 5: Guardians', 'A mysterious and unstoppable force threatens the galaxy, the Master Chief is missing and his loyalty questioned. Experience the most dramatic Halo story to date in a 4-player cooperative epic that spans three worlds. Challenge friends and rivals in new multiplayer modes: Warzone, massive 24-player battles, and Arena, pure 4-vs-4 competitive combat.*', 59.99));
item_list.push(new Item('videogames', "Assassin's Creed Syndicate", "WELCOME TO THE FAMILY — London, 1868. The Industrial Revolution fattens the purses of the privileged while the working class struggles to survive — until two Assassins rise to lead the world's first organized crime family. Conquer the streets of London. Bring the ruling class to their knees. Make history in a visceral adventure unlike any game you've played before.", 59.99));
// display item list
displayAll();
//When a new category is chosen it will correct and display items of that category type
$('#category').on('change', function(){
// read the selected category using 'value' attribute
var category = $(this).val();
if (category == '0')
displayAll(); // display all items
else
displaySelectedItems(category); // display selected items
});
//When category is chosen, items with the same type will be displayed
function displaySelectedItems(category){
var itemInfo = '';
/* display data:
use a for loop to go through each element in the item_list array
*/
for (var i=0; i<item_list.length; i++){
// display only selected items
if (item_list[i].type == category){
itemInfo += createItemData(item_list[i], i);
}
// add each item to the table
$('#item-list').html(itemInfo);
}
}
//Displays the item list
function displayAll(){
var itemInfo = '';
/* display data:
use a for loop to go through each element in the item_list array
Each element is an object.
*/
for (var i=0; i<item_list.length; i++){
// use each item to create HTML content
itemInfo += createItemData(item_list[i], i);
// add each item to the table
$('#item-list').html(itemInfo);
}
}
//Creates the item's data
function createItemData(item, index){
var trow = "<tr class='itemlist data-index='" +index+ "' >";
trow += "<td class=item-title'>"+item.title + "</td>";
trow += "<td class='item-description'>"+item.description + "</td>";
trow += "<td class='price'>$"+item.price + "</td>";
trow += "<td class='adding'><button type='button' class='addme' data- index='"+index+"'>Add</td></tr>";
return trow;
}
//Activates "Add" button so cart can be populated
$('#item-list').on('click', '.addme', function(){
// 1. Read the item index using data- attribute
var index = $(this).data('index');
if(!inCart(index)){
cart.push(index);
}
// 3. Update the cart list and total credits
displayCartItems();
checkCart();
// update price
calculateTotalPrice();
});
//function to check if items are in cart
function inCart(index){
for (var i=0; i<cart.length; i++){
if (cart[i] == index)
return true;
}
return false;
}
//Displays the shopping cart items
function displayCartItems(){
// create a table row for each item in cart array
var itemInfo = '';
for (var i=0; i<cart.length; i++){
var index = cart[i];
itemInfo += createTableRow(index);
}
$('#selected-list').html(itemInfo);
}
//Constructs the shopping cart table
function createTableRow(index){
var trow = '';
trow += "<tr><td>"+item_list[index].title + "</td>>";
trow += "<td id='itemsprice'>"+item_list[index].price + "</td>";
trow += "<td><select class='item-quantity' data-quantity='"+index+"'><option value='1'>1</option><option value='2'>2</option><option value='3'>3</option><option value='4'>4</option><option value='5'>5</option><option value='6'>6</option><option value='7'>7</option><option value='8'>8</option><option value='9'>9</option><option value='10'>10</option></td>";
trow += "<td id='tc-item'>"+item_list[index].price+"</td>"
trow += "<td><button type='button' class='delete-item' value='"+index+"'>Delete</button></td></tr>";
return trow;
}
//When quantity is changed change the value and compute new totals
$('#selected-list').on('change', '.item-quantity', function(){
calculateTotalPrice();
});
//If delete button is pressed in cart, the item is removed from the cart
$('#selected-list').on('click', '.delete-item', function(){
var index = $(this).val();
removeItemFromCart(index);
calculateTotalPrice();
checkCart();
});
function checkCart(){
if(cart.length == 0){
$('#empty-cart').html("Your cart is empty!");
} else {
$('#empty-cart').html("");
}
}
//function to remove items from the shopping cart
function removeItemFromCart(index){
// identify and remove the index from the cart and redisplay cart table
var pos = -1;
for (var i=0; i<cart.length; i++){
if (index == cart[i]){
pos = i;
break;
}
}
if (pos>-1){
cart.splice(pos, 1);
// reset the cart table
displayCartItems();
} else {
alert("Could not find!");
}
}
function calculateTotalPrice(){
var quantity = $('.item-quantity').val();
var subtotal = 0;
var tax = 0;
var shipping = 0;
var total = 0;
//for loop to calculate the subtotal
for(var i = 0; i < cart.length; i++){
var productPrice = item_list[cart[i]].price;
subtotal += productPrice * quantity;
}
//Percent taxed is 6%
var taxPerc = .06;
//Calculating taxes
tax = subtotal * taxPerc;
//Percent for shipping is 2%
var shippingPerc = .02;
//Calculating shipping
shipping = subtotal * shippingPerc;
//Calculating total
total = subtotal + tax + shipping;
//Displaying totals
//$('#tc-item').html(totalItemPrice.toFixed(2));
$('#subtotal').html(subtotal.toFixed(2));
$('#tax').html(tax.toFixed(2));
$('#shipping').html(shipping.toFixed(2));
$('#total').html(total.toFixed(2));
}
//Activates the Display cart and Hide cart buttons in shopping cart
$('#show-cart').on('click', function(){
$('#selected-list').show();
});
$('#hide-cart').on('click', function(){
$('#selected-list').hide();
});
});
</script>
</head>
<body>
<div class='container'>
<div class='row' id='top-box' >
<div class='col-sm-12'>
<h2>Sam's Discount Store</h2>
<h3>Variety of Items!</h3>
</div>
</div>
<div class='row' id='content'>
<div class='col-sm-8'>
<h3 class='title'>Discounted Items</h3>
<h4>
<select id='category'>
<option value='0' >All</option>
<option value='baseballgear' >Baseball Items</option>
<option value='soccergear' >Soccer Items</option>
<option value='videogames'>Video Games</option>
</select>
</h4>
<table class='table table-bordered clmlabels' >
<tr class='t-head'><td >Product</td>
<td >Description</td>
<td >Cost</td>
</tr>
<tbody id='item-list'>
</tbody>
</table>
</div>
<div class='col-sm-4'>
<h2>Cart Items</h2>
<p><button class='btn btn-primary' id='show-cart'>Display cart</button>
<button class='btn' id='hide-cart'>Hide cart</button></p>
<table class='table selected-list' id='selected-list'>
</table>
</div>
<table class='cart-table'>
<tr>
<td id='empty-cart'></td>
<tr>
<td>Subtotal: </td>
<td><span id='subtotal'>0</td>
</tr>
<tr>
<td>Tax: </td>
<td><span id='tax'>0</td>
</tr>
<tr>
<td>Shipping: </td>
<td><span id='shipping'>0</td>
</tr>
<tr>
<td>Total: </td>
<td><span id='total'>0</td>
</tr>
</table>
</div>
</div>
<div class='row' id='footer'
<div class='col-sm-12'> <p>Sam's Discount Store</p></div>
</div>
</div>
</body>
</html>
I have updated your code a bit. Now I think its working as expected. Please take a look at it.
Major change that I made is now instead of pushing only index into the cart array; I am now inserting quantity too like this:
cart.push({"index": index, "qty": 1});
Also whenever we change the quantity via select box; we are updating the number. And same value is getting used in total amount calculation.
I will suggest to compare below code with you local copy can see what all changes has been done. Hope it will help you.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html>
<head>
<meta charset="utf-8">
<!-- Set the viewport so this responsive site displays correctly on mobile devices -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sam's Discount Store </title>
<!-- Include bootstrap CSS -->
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"> </script>
<style type="text/css">
.courselist { cursor: pointer;}
.t-head { color: #fff; background-color: #333366; font-size: 20px; line- height: 20px; }
#top-box, #footer { background-color: #330066; color: #fff; text-align: center;}
#content {border: 1px solid #330099;}
</style>
<script>
$(function(){
/* The following function defines a constructor for creating an array of objects with four properties.
The keyword "this" refers to the instance of the object
*/
function Item(type,title,description,price){
this.type = type;
this.title = title;
this.description = description;
this.price = price;
}
//create an array to store items
var item_list = [];
var cart = []; //store index of elements in the shopping cart
//add items
//add baseballgear items
item_list.push(new Item('baseballgear','Louisville Slugger', 'The finest craftsmanship and finest materials ensure stepping to the plate with the Louisville Slugger® M9 Maple M110 Bat will allow you to swing what the pros swing.', 79.99 ));
item_list.push(new Item('baseballgear','Marucci Bat', 'Named for one of the most lethal hitters in the game, the Marucci® CUTCH22 Pro Model Baseball Bat features the same cut and finish swung by MLB® center fielder, Andrew McCutchen. The "Cutch" features a large, powerful, balanced barrel with a sleek cherry red and grey finish to deliver maximum performance at the plate. This adult wooden bat is also handcrafted and bone-rubbed to ensure superior quality and surface hardness.', 139.99));
item_list.push(new Item('baseballgear', 'Rawlings Glove', "Unrivaled quality season after season, the Rawlings® 11.25'' Pro Preferred® Series Glove returns to provide elite craftsmanship and superior performance for elite middle infielders.",349.99));
item_list.push(new Item('baseballgear', 'Wilson Glove', "Enhance your field performance with unrivaled dependability with the Wilson® 11.5 A2000™ Series Glove. Made with Pro Stock® leather for long-lasting performance, this glove's construction is preferred by professionals for its top-notch quality. Dri-Lex® technology in the wrist lining transfers moisture away from the skin to keep you cool and dry. The advanced design has been improved upon by the Wilson&Reg; Advisory Staff.",249.99 ));
item_list.push(new Item('baseballgear', 'Easton Baseball Helmet', 'Give your favorite player maximum protection at the plate with the Easton® Junior Z5 Elite Baseball Helmet. The ABS shell withstands impact and disperses energy away from the head, with a stylish Digi-Camo design. Featuring dual density foam liner for advanced comfort, this helmet boasts BioDri™ padded inner liner to wick moisture away from the skin to keep them cool and dry. Wrapped ear pads provide enhanced coverage around the head.', 54.99));
item_list.push(new Item('baseballgear', 'Rawlings Batting Gloves', 'Get the most out of your batting gloves this season with the Rawlings® Adult Workhorse 950 Batting Gloves. These gloves feature an Oiltac® leather palm pad to provide better grip and softness. Equipped with a Dura-Plus™ pad for added protection in the palm, the Dynamic Fit System™ provides greater comfort, flex, and feel during every play. The adjustable wrist closure is reinforced to provide a more secure fit', 34.99));
//add soccergear items
item_list.push(new Item('soccergear', 'Nike Ordem Soccer Ball', 'Hit the back of the net with the The Nike® Ordem 3 PL Soccer Ball. The Ordem 3 is the official match ball of the English Premier League for the 2015-2016 season. This FIFA® approved ball features Aerowtrac grooves and a micro-textured casing for accurate flight. The carbon latex bladder and fuse-welded construction allow for an exceptional touch while the vivid visual Power Graphics allow you to track the ball so you can react quickly.', 150.00));
item_list.push(new Item('soccergear', 'Wilson Shinguard', 'Maximize your protection for practice or game day with the Wilson® NCAA® Forte ll Soccer Shinguard. This high impact shinguard is constructed of a removable inner shell for adjustable protection to diffuse impact during elite-level play. Its Lycra® sleeve contains power band enhancements for added compression and blood circulation. Focus on your game with the Wilson® NCAA® Forte ll Soccer Shinguard.', 24.99 ));
item_list.push(new Item('soccergear', 'Adidas Goalie Gloves', 'Protect the goal line with intensity when you sport the adidas® Ace Zones Pro Soccer Goalie Gloves. Evo Zone Technology delivers superior catching and control so you can dominate the game from the net. The negative cut ensures a snug feel while seamless touch features deliver breathability through the latex and foam construction. A stretch-strap wraps your hand to complete the gloves with a comfortable fit.', 114.99));
item_list.push(new Item('soccergear', 'Storelli Exoshield Goalie Jersey', 'Block kicks to the net with maximum mobility in the Storelli® Exoshield GK Adult Goalie Gladiator Jersey. This jersey withstands impact between the posts with polyurethane foam protection at the elbows. For increased comfort, the compression material wicks moisture away to keep the skin cool and dry. Dive and defend without distraction in the lightweight Storelli® Exoshield GK Adult Goalie Gladiator Jersey.', 64.99));
item_list.push(new Item('soccergear', 'Storelli BodyShield Slider Shorts', "Enjoy superior protection with the classic fit of the Storelli® sliders. Lightweight foam padding delivers high-performance protection to keep you safe from impact, swelling and cuts, while the unique design lets you freely move while the pads stay in place. Stay safe on the field with the antimicrobial technology and lightweight padding of the Storelli® Men's Slider Shorts.", 59.99));
item_list.push(new Item('soccergear', 'Adidas Estadio Teamp Backpack', 'Transport your gear to and from the field in style with the adidas® Estadio Team Backpack II. Built with soccer in mind, this backpack is constructed with multiple compartments to conveniently organize and store all of your gear. LoadSpring™ technology adds comfort to the shoulder straps so you can carry more equipment. FreshPAK™ shoe compartment keeps gear fresh throughout the season.', 55.00));
//add videogames
item_list.push(new Item('videogames', 'Star Wars Battlefront', 'Visit classic planets from the original Star Wars™ trilogy, detailed with an unprecedented amount of realism and sense of authenticity that will transport you to a galaxy far, far away', 59.99));
item_list.push(new Item('videogames', 'Just Cause 3', "The Mediterranean republic of Medici is suffering under the brutal control of General Di Ravello, a dictator with an insatiable appetite for power. Enter Rico Rodriguez, a man on a mission to destroy the general's ambitions by any means necessary. With more than 400 square miles of complete freedom from sky to seabed, and a huge arsenal of weaponry, gadgets and vehicles, prepare to unleash chaos in the most creative and explosive ways you can imagine.", 59.99));
item_list.push(new Item('videogames', 'Call of Duty Black Ops III', 'Call of Duty: black Ops III is the ultimate 3-games-in-1 experience. The Campaign you must navigate the hot spots of a new Cold War to find your missing brothers. Multiplayer features a new momentum-based chained movement system, allowing players to fluidly move through the environment with finesse. No Treyarch title would be complete without its signature Zombies offering "Shadows of Evil" has its own distinct storyline right out of the box.', 59.99));
item_list.push(new Item('videogames', 'Fallout 4', 'The epic storylines, adrenaline-pumping action and explosive thrills are back. The Fallout franchise returns with Fallout 4. Grab your controller and get ready to dive back into the enveloping storyline of this legendary series.', 59.99));
item_list.push(new Item('videogames', 'Halo 5: Guardians', 'A mysterious and unstoppable force threatens the galaxy, the Master Chief is missing and his loyalty questioned. Experience the most dramatic Halo story to date in a 4-player cooperative epic that spans three worlds. Challenge friends and rivals in new multiplayer modes: Warzone, massive 24-player battles, and Arena, pure 4-vs-4 competitive combat.*', 59.99));
item_list.push(new Item('videogames', "Assassin's Creed Syndicate", "WELCOME TO THE FAMILY — London, 1868. The Industrial Revolution fattens the purses of the privileged while the working class struggles to survive — until two Assassins rise to lead the world's first organized crime family. Conquer the streets of London. Bring the ruling class to their knees. Make history in a visceral adventure unlike any game you've played before.", 59.99));
// display item list
displayAll();
//When a new category is chosen it will correct and display items of that category type
$('#category').on('change', function(){
// read the selected category using 'value' attribute
var category = $(this).val();
if (category == '0')
displayAll(); // display all items
else
displaySelectedItems(category); // display selected items
});
//When category is chosen, items with the same type will be displayed
function displaySelectedItems(category){
var itemInfo = '';
/* display data:
use a for loop to go through each element in the item_list array
*/
for (var i=0; i<item_list.length; i++){
// display only selected items
if (item_list[i].type == category){
itemInfo += createItemData(item_list[i], i);
}
// add each item to the table
$('#item-list').html(itemInfo);
}
}
//Displays the item list
function displayAll(){
var itemInfo = '';
/* display data:
use a for loop to go through each element in the item_list array
Each element is an object.
*/
for (var i=0; i<item_list.length; i++){
// use each item to create HTML content
itemInfo += createItemData(item_list[i], i);
// add each item to the table
$('#item-list').html(itemInfo);
}
}
//Creates the item's data
function createItemData(item, index){
var trow = "<tr class='itemlist data-index='" +index+ "' >";
trow += "<td class=item-title'>"+item.title + "</td>";
trow += "<td class='item-description'>"+item.description + "</td>";
trow += "<td class='price'>$"+item.price + "</td>";
trow += "<td class='adding'><button type='button' class='addme' data-index='"+index+"'>Add</td></tr>";
return trow;
}
//Activates "Add" button so cart can be populated
$('#item-list').on('click', '.addme', function(){
// 1. Read the item index using data- attribute
var index = $(this).data('index');
if(!inCart(index)){
cart.push({"index": index, "qty": 1});
}
// 3. Update the cart list and total credits
displayCartItems();
checkCart();
// update price
calculateTotalPrice();
});
//function to check if items are in cart
function inCart(index){
for (var i=0; i<cart.length; i++){
if (cart[i].index == index)
return true;
}
return false;
}
//Displays the shopping cart items
function displayCartItems(){
// create a table row for each item in cart array
var itemInfo = '';
for (var i=0; i<cart.length; i++){
var index = cart[i].index;
itemInfo += createTableRow(index);
}
$('#selected-list').html(itemInfo);
for (var i=0; i<cart.length; i++){
var index = cart[i].index;
var qty = cart[i].qty;
$("select#quantity_"+index).val(qty);
}
}
//Constructs the shopping cart table
function createTableRow(index){
var trow = '';
trow += "<tr><td>"+item_list[index].title + "</td>>";
trow += "<td id='itemsprice'>"+item_list[index].price + "</td>";
trow += "<td><select id='quantity_"+index+"' class='item-quantity' data-quantity='"+index+"'><option value='1'>1</option><option value='2'>2</option><option value='3'>3</option><option value='4'>4</option><option value='5'>5</option><option value='6'>6</option><option value='7'>7</option><option value='8'>8</option><option value='9'>9</option><option value='10'>10</option></td>";
trow += "<td id='tc-item'>"+item_list[index].price+"</td>"
trow += "<td><button type='button' class='delete-item' value='"+index+"'>Delete</button></td></tr>";
return trow;
}
//When quantity is changed change the value and compute new totals
$('#selected-list').on('change', '.item-quantity', function(){
var index = $(this).data("quantity");
for (var i=0; i<cart.length; i++){
if (index == cart[i].index){
cart[i].qty = parseInt($(this).val(),10);
}
}
calculateTotalPrice();
});
//If delete button is pressed in cart, the item is removed from the cart
$('#selected-list').on('click', '.delete-item', function(){
var index = $(this).val();
removeItemFromCart(index);
calculateTotalPrice();
checkCart();
});
function checkCart(){
if(cart.length == 0){
$('#empty-cart').html("Your cart is empty!");
} else {
$('#empty-cart').html("");
}
}
//function to remove items from the shopping cart
function removeItemFromCart(index){
// identify and remove the index from the cart and redisplay cart table
var pos = -1;
for (var i=0; i<cart.length; i++){
if (index == cart[i].index){
pos = i;
break;
}
}
if (pos>-1){
cart.splice(pos, 1);
// reset the cart table
displayCartItems();
} else {
alert("Could not find!");
}
}
function calculateTotalPrice(){
var subtotal = 0;
var tax = 0;
var shipping = 0;
var total = 0;
//for loop to calculate the subtotal
for(var i = 0; i < cart.length; i++){
var productPrice = item_list[cart[i].index].price;
var quantity = cart[i].qty;
subtotal += productPrice * quantity;
}
//Percent taxed is 6%
var taxPerc = .06;
//Calculating taxes
tax = subtotal * taxPerc;
//Percent for shipping is 2%
var shippingPerc = .02;
//Calculating shipping
shipping = subtotal * shippingPerc;
//Calculating total
total = subtotal + tax + shipping;
//Displaying totals
//$('#tc-item').html(totalItemPrice.toFixed(2));
$('#subtotal').html(subtotal.toFixed(2));
$('#tax').html(tax.toFixed(2));
$('#shipping').html(shipping.toFixed(2));
$('#total').html(total.toFixed(2));
}
//Activates the Display cart and Hide cart buttons in shopping cart
$('#show-cart').on('click', function(){
$('#selected-list').show();
});
$('#hide-cart').on('click', function(){
$('#selected-list').hide();
});
});
</script>
</head>
<body>
<div class='container'>
<div class='row' id='top-box' >
<div class='col-sm-12'>
<h2>Sam's Discount Store</h2>
<h3>Variety of Items!</h3>
</div>
</div>
<div class='row' id='content'>
<div class='col-sm-8'>
<h3 class='title'>Discounted Items</h3>
<h4>
<select id='category'>
<option value='0' >All</option>
<option value='baseballgear' >Baseball Items</option>
<option value='soccergear' >Soccer Items</option>
<option value='videogames'>Video Games</option>
</select>
</h4>
<table class='table table-bordered clmlabels' >
<tr class='t-head'><td >Product</td>
<td >Description</td>
<td >Cost</td>
</tr>
<tbody id='item-list'>
</tbody>
</table>
</div>
<div class='col-sm-4'>
<h2>Cart Items</h2>
<p><button class='btn btn-primary' id='show-cart'>Display cart</button>
<button class='btn' id='hide-cart'>Hide cart</button></p>
<table class='table selected-list' id='selected-list'>
</table>
</div>
<table class='cart-table'>
<tr>
<td id='empty-cart'></td>
<tr>
<td>Subtotal: </td>
<td><span id='subtotal'>0</td>
</tr>
<tr>
<td>Tax: </td>
<td><span id='tax'>0</td>
</tr>
<tr>
<td>Shipping: </td>
<td><span id='shipping'>0</td>
</tr>
<tr>
<td>Total: </td>
<td><span id='total'>0</td>
</tr>
</table>
</div>
</div>
<div class='row' id='footer'
<div class='col-sm-12'> <p>Sam's Discount Store</p></div>
</div>
</div>
</body>
</html>
Related
I am fairly new to coding and wanted a better (less repetative) way of creating this line of code for my fetch call. I'll add the important parts of the code.
HTML
<form id= 'selectionForm' action="#">
<p>
<label>
<input type="checkbox" class="filled-in" name="Nexflix" id="Nexflix"/>
<span>Netflix</span>
</label>
</p>
</form>
Javascript
document.getElementById('fetch').addEventListener('click', function (element) {
element.preventDefault();
let checkedElements = document.querySelectorAll('#Nexflix:checked');
var options = {
method: "GET",
headers: {
"X-RapidAPI-Key": "using my own",
"X-RapidAPI-Host": "streaming-availability.p.rapidapi.com",
},
};
let outputContainer = document.getElementById('output');
for (let e of checkedElements) {
fetch('https://streaming-availability.p.rapidapi.com/search/basic?country=us&service=netflix&service=netflix&type=movie&genre=18&page=1&output_language=en&language=en', options).then((response) => response.json()).then( (data) => {
outputContainer.appendChild(document.createTextNode('The checked element is : '+e.id));
outputContainer.appendChild(document.createElement("br"));
outputContainer.appendChild(document.createTextNode(data.results[0].title));
outputContainer.appendChild(document.createElement("br"));
outputContainer.appendChild(document.createTextNode('IMDB Rating : ' + data.results[0].imdbRating));
outputContainer.appendChild(document.createElement("br"));
outputContainer.appendChild(document.createTextNode('Year of release : ' + data.results[0].year));
outputContainer.appendChild(document.createElement("br"));
outputContainer.appendChild(document.createTextNode('Overview : ' + data.results[0].overview));
outputContainer.appendChild(document.createElement("br"));
outputContainer.appendChild(document.createTextNode(data.results[1].title));
I would also like to repeat this for other films/results from the API. They give results like
{2 items
"results":[8 items
0:{21 items
"age":10
"backdropPath":"/pYziM5SEmptPW0LdNhWvjzR2zD1.jpg"
"backdropURLs":{...}4 items
"cast":[...]4 items
"countries":[...]1 item
"genres":[...]2 items
"imdbID":"tt9850370"
"imdbRating":64
"imdbVoteCount":1069
"originalTitle":"#AnneFrank. Parallel Stories"
"overview":"One single Anne Frank moves us more than the countless others who suffered just as she did but whose faces have remained in the shadows-Primo Levi. The Oscar®-winning Helen Mirren will introduce audiences to Anne Frank's story through the words in her diary. The set will be her room in the secret refuge in Amsterdam, reconstructed in every detail by set designers from the Piccolo Theatre in Milan. Anne Frank this year would have been 90 years old. Anne's story is intertwined with that of five Holocaust survivors, teenage girls just like her, with the same ideals, the same desire to live: Arianna Szörenyi, Sarah Lichtsztejn-Montard, Helga Weiss and sisters Andra and Tatiana Bucci. Their testimonies alternate with those of their children and grandchildren."
"posterPath":"/hkC4yNDFmW1yQuQhtZydMeRuaAb.jpg"
"posterURLs":{...}7 items
"runtime":92
"significants":[...]2 items
"streamingInfo":{...}1 item
"tagline":""
"title":"#AnneFrank. Parallel Stories"
"tmdbID":"610643"
"video":"FzT7-NfkxLA"
"year":2019
}
1:{...}21 items
2:{...}21 items
3:{...}21 items
4:{...}21 items
5:{...}21 items
6:{...}21 items
7:{...}21 items
Thank you for your time reading this!
Use <p>aragraphs instead of text nodes with many linebreaks inbetween.
You can create them easily in a loop:
const lines = [
'The checked element is : '+e.id,
data.results[0].title,
'IMDB Rating : ' + data.results[0].imdbRating,
'Year of release : ' + data.results[0].year,
'Overview : ' + data.results[0].overview,
data.results[1].title
];
for (const line of lines) {
const paragraph = document.createElement('p');
paragraph.appendChild(document.createTextNode(line));
outputContainer.appendChild(paragraph);
}
I'm a Laravel newbie and I recently started working on a equipment management system whereby the admin adds quantity stock one each equipment to the system and when admin let the user borrow the equipment it deducts the quantity that the user wants from the equipment stock table. My only challenge is how to make the system to subtract quantity that the borrower wants from the equipment stock table?
Here's my controller for the button "borrow"
So when I click the borrow button it will deducts the ('quantity_item') to the equipment stock table ('e_quantity')
public function borrow($id){
$first = Reservation::where('id', $id)->first();
$kl = $first->name;
$mn = $first->Name_item;
$st = $first->quantity_item; //this is the quantity that the borrower wants
$op = $first->dt_item;
$qr = $first->room_item;
$first->delete();
$second = new BorrowedItems();
$second->bname = $kl;
$second->bdate = $mn;
$second->itemb = $op;
$second->bquantity = $st;
$second->broom = $qr;
$second->save();
return redirect()->back()->with('message','Item Borrowed Successfully!');
}
This is my Equipment Stock Table
This is my BorrowedItem Table
so when I click the borrow button the data from reservationtable will transfer here
This is my Reservation Table
I have an E-Commerce website built on HTML, JavaScript & PHP.
On product details page user can add product to cart thus I'm displaying total amount of cart value.
I want to display decimal number always (10,2) format.
Currently my code works with minimal thing. On clicking "Add to cart" if product price is 12.00 the Counter div displays 12 only.
<span>
<a href="cart.php" class="text-white">
<i class="fa fa-shopping-cart p1" data-count="10" data-currency="€" id="total"></i>
</a>
</span>
.p1[data-count]:after{
position:absolute;
right:1%;
top:1%;
content: attr(data-count);
font-size:10px;
padding:.2em;
line-height:1em;
color: white;
background:#21468b;
text-align:center;
width: 100%;
font-weight:normal;
}
<script>
var theTotal = '0';
var ProductSellingPrice = '12.00'
$('#insert').click(function(){
theTotal = Number(theTotal) + Number(ProductSellingPrice);
$('#total').attr('data-count', theTotal);
});
</script>
So on clicking insert, the existing TheTotal & current product Price gets added. If there are no products on cart then p1 doesn't display any value, thus want to display zero always if empty/zero. If product price is 12.00 then shows 12 only. If product price is 12.50 then 12.50 is displayed.
I want it to display decimal always & also currency symbol using data attribute.
Displaying decimal problem is solved by #Simone, i m not able to find answer for displaying currency before value using data attribute.
If you want 12.00 and not 12 you have to use Number.prototype.toFixed()
So you have to convert all the single product total (quantity * price is the single total ) into Float number and when you do the total sum, take the number and do this:
Number.parseFloat(total).toFixed(2); // two decimal
Example:
var quantity = 10;
var price = 11;
var tot = parseFloat(quantity * price).toFixed(2);
console.log(tot); // "110.00"
I'm building a webpage that utilizes a fairly complex table layout which will hold a decent amount of data. I don't want to hardcode all this data in, so I would like to read it in from a text file and dynamically create the webpage that way. The following is an example I have come up with to illustrate what I am trying to accomplish.
// imagine this as the basket that holds all the groceries
<table id=”basket”>
// this is the label for a new section of the basket (like fruits, or vegetables)
<thead>Fruits</thead>
// this is the section of the basket for the items described by the label above
<tbody>
<tr>
<td>
// this is the container of these items
<table class="category">
// a new section of the container for each item
<tr>
<td>
// information about this particular item
<table class="Item">
<tr><td>Strawberry</td></tr>
<tr><td>Red</td></tr>
<tr><td>Seeds</td></tr>
</table>
</td>
// verbose description about this item
<td>Strawberries are sweet and grow in the summer</td>
</tr>
So if I had data like the following:
Fruits
strawberry, red, seeds, Strawberries are sweet and grow in the summer
blueberry, blue, seeds, Willy Wonka likes these
avocado, green, pit, Still not sure how I feel about these
Vegetables
Celery, green, stalk, A top tier vegetable
Radish, Red, bulb, I still haven't warmed up to these
Potato, Brown, root, A classic!
Underneath the basket table I would have two instances of this code, one for fruits and one for vegetables
// this is the label for a new section of the basket (like fruits, or vegetables)
<thead>Fruits</thead>
// this is the section of the basket for the items described by the label above
<tbody>
<tr>
<td>
// this is the container of these items
<table class="category">
and within each of those sections I would have however many instances of this code as called for, (in this case, 3 for each because there are 3 fruits and 3 vegetables listed)
// a new section of the container for each item
<tr>
<td>
// information about this particular item
<table class="Item">
<tr><td>Strawberry</td></tr>
<tr><td>Red</td></tr>
<tr><td>Seeds</td></tr>
</table>
</td>
// verbose description about this item
<td>Strawberries are sweet and grow in the summer</td>
</tr>
So my ultimate question is,
What is the best way for me to structure a text file in order to accomplish this
and
With what kind of PHP or JavaScript could I successfully read this properly formatted text file, and then generate the HTML I want that contains the correct data
Any advice or insight would be appreciated, thank you.
Okay personally I'd recommend saving your data in json format which is a pretty standard way to represent this type of data. You could then supply it via AJAX or save it in a file and include it with a script tag. Really all depends on your requirements.
Also I don't know what your UI requirements are but I'd personally not create nested tables like this. I would use div tags and write custom css to get the layout I wanted.
// This could be supplied via AJAX or you could save it in a javascript or json file.
// It really depends on your requirements.
var jsonData = [
{
name: "Fruits",
items: [
{
name: "Strawberry",
color: "red",
type: "seeds",
description: "Strawberries are sweet and grow in the summer"
},
{
name: "Blueberry",
color: "blue",
type: "seeds",
description: "Willy Wonka likes these"
},
{
name: "Avocado",
color: "green",
type: "pit",
description: "Still not sure how I feel about these"
}
]
},
{
name: "Vegetables",
items: [
{
name: "Celery",
color: "green",
type: "stalk",
description: "A top tier vegetable"
},
{
name: "Radish",
color: "red",
type: "bulb",
description: "I still haven't warmed up to these"
},
{
name: "Potato",
color: "brown",
type: "root",
description: "A classic!"
}
]
}
]
// This is the javascript code that would read your json data and build HTML from it
document.getElementById("basket").innerHTML = getBasketHTML(jsonData)
function getBasketHTML(data) {
// loop through data
var HTML = ""
for (var i = 0, i_end = data.length; i < i_end; i++) {
var category = data[i]
// add new row and table for each category
HTML += "<tr><table>"
// add category label
HTML += "<thead>" + category.name + "</thead>"
// add category table
HTML += "<tbody><tr><td><table class='category'>"
// loop through category items and build HTML
for (var j = 0, j_end = category.items.length; j < j_end; j++) {
HTML += getItemHTML(category.items[j])
}
// close category table
HTML += "</table></td></tr></tbody></table></tr>"
}
return HTML
}
function getItemHTML(item) {
// opening row tag
var HTML = "<tr>"
// add item information
HTML += "<td><table class='Item'>"
HTML += "<tr><td>" + item.name + "</td></tr>"
HTML += "<tr><td>" + item.color + "</td></tr>"
HTML += "<tr><td>" + item.type + "</td></tr>"
HTML += "</table></td>"
// add verbose description
HTML += "<td>" + item.description + "</td>"
// closing row tag
HTML += "</tr>"
return HTML
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
<table id="basket"></table>
</body>
</html>
On our current website that is hosted offsite via another company it is all done with .NET, I simply have access to HTML, JS, and CSS files to edit. A lot of data is output on the page via tokens. On our web page we have a weight token, it grabs the items weight and outputs it between a span tag. So if you're viewing the source it'll show the following:
<span id="order_summary_weight">78.000000 lbs</span>
The token by default outputs the lbs. What I need to do is have javascript grab the 78.000000, convert it to an integer I'm assuming and if that integer, in this case 78.000000 is greater than 50.000000 I'd like it append a line after the 78.000000 lbs to say "Your weight total is over 50 lbs, we will contact you directly with a shipping charge." Understand some weight totals may be as small as 0.010000
I'm coming to you fine folks here because I am at a complete lost where to start in this endeavor.
Something like this ? :
html :
<div class="wrap">
<span class="price" id="order_summary_weight">78.000000 lbs</span>
</div>
<hr>
<div class="wrap">
<span class="price" id="order_summary">50.000000 lbs</span>
</div>
JS :
$('.wrap').each(function(){
var price = $(this).find('.price').text();
price = price.replace(' lbs', '');
price = parseInt(price);
if(price > 50){
$(this).append('<div class="alert">Your weight total is over 50 lbs, we will contact you directly with a shipping charge.</div>');
}
});
DEMO : http://jsfiddle.net/w3qg4/1/
function getWeight()
{
var x=document.getElementById("order_summary_weight");
if(x > 50){
alert("Your weight total is over 50 lbs, we will contact you directly with a shipping charge. Understand some weight totals may be as small as 0.010000");
}
}