pure js shopping cart - javascript

I'm trying to make a shopping cart with pure JS. I'm trying to dynamically create some divs with my products and buttons to increase/decrease/delete them, but I am stuck. Below is my function which is creating these divs:
function displayCart() {
let output = '';
for (let i in cart) {
output += '<div class="card card-body cartc">' + '<p>' +
'<span id="' + cart[i].name + '">' + cart[i].name + '</span>' +
'<button class="minus">-</button>' +
' ' + cart[i].count + ' шт.' +
'<button class="plus">+</button>' +
'<button class="delete">x</button>' +
'</p>' + '</div>';
};
document.querySelector('.cart').innerHTML = output;
document.querySelector('.total').innerHTML = totalCost();}
So the next step is to put events on buttons.
document.addEventListener("click", function (event) {
if (document.querySelector('.minus')) {
let name = this.querySelector('.cartc span').getAttribute("id");
removeItemFromCart(name);
displayCart();
}});
As you can see, it finds the first .cart span id and returns it to removeItemFromCart(), but this function should work in every div that I create, not just the first one. How can it be solved?
You can take a look at the whole project at https://enoltc.github.io/hw-2/ or https://github.com/ENoLTC/hw-2/
Creating a Shopping Cart using only HTML/JavaScript
The difference is that I want to write my script in pure JavaScript, without using simpleCart or jQuery.

So I did it this way
let buttons = document.getElementById("show-cart");
buttons.addEventListener("click", function (event) {
let name = event.target.getAttribute("data-name");
if (event.target.className === "delete") {
removeItemFromCartAll(name);
displayCart();
} else if (event.target.className === "minus") {
removeItemFromCart(name);
displayCart();
} else if (event.target.className === "plus") {
addItemToCart(name, 0, 1);
displayCart();
}
});

Related

prev and next returning undefined instead page numbers in pagination

I am trying to create pagination with the below code and I am facing the problem to access page number ($clickedPageLink.dataset.page) when I click Prev and Next links. However, I am able to successfully get the page number when I click page number 1 to 5. Please find the plunker for reference Pagination. When click Prev and Next, console.log($clickedPageLink.dataset.page) is giving undefined. Can any one help to get the values for Prev and Next also as given in html?
let prevVal = 2;
let nextVal = 3;
let str = ['<nav class="pagination">'];
str.push('<ul class="pagination__pages">');
str.push('<li class="pagination__page pagination--previous">');
str.push('<a class="pagination__link" data-page="' + (prevVal - 1) + '" href="#">');
str.push('<span><i class="fas fa-angle-left"></i> Prev</span>');
str.push('</a></li>');
for (let plengthMn = 1; plengthMn <= 5; plengthMn++) {
str.push('<li class="pagination__page">');
str.push('<a class="pagination__link" data-page="' + plengthMn + '" href="#">' + plengthMn + '</a>');
str.push('</li>');
}
str.push('<li class="pagination__page pagination--next">');
str.push('<a class="pagination__link" data-page="' + (nextVal + 1) + '" href="#">');
str.push('<span>Next <i class="fas fa-angle-right"></i></span>');
str.push('</a></li>');
const $paginationList = document.getElementById('products-item_pagination');
$paginationList.innerHTML = str.join('');
const $paginationLinkMn = document.querySelectorAll('.pagination__link');
function attachEventToElementList(elmList, event, eventHandler) {
if(!elmList) {
return;
}
elmList.forEach(function(elm) {
elm.addEventListener(event, eventHandler);
});
}
attachEventToElementList($paginationLinkMn, 'click', goToPageMn);
function goToPageMn(event) {
const $clickedPageLink = event.target;
console.log($clickedPageLink.dataset.page)
}
And in my html, I have,
<div id="products-item_pagination" class="product-pagination"></div>
The problem with the above code is, the event is never firing up for anchor tag which is the parent of prev icon. Below css hack has solved the problem.
a > * {
pointer-events: none;
}

Creating a list of students and assigning a function to each button

I am trying to allow clients to create a list of students then view more info by simply clicking on the button with the students name. I've got it to create the button and display the students name in the button but it only calls the function when I click submit to add the student to the list, the actual student button doesn't seem to function.
function updateStudentList() {
var html = "";
for (var i = 0; i < students.length; i++) {
html += "<li><button type='button' class='studentButton'" + "id=" + students[i].name +">" + students[i].name + "</button></li>";
}
$('#studentList').html(html);
for (var i = 0; i < students.length; i++) {
document.getElementById(students[i].name).addEventListener('click', openStudentInfo(students[i].name));
}
}
function openStudentInfo(studentName) {
console.log("Opening " + studentName + " info.");
var studentInfo = requestStudentByName(studentName);
if (studentInfo != null) {
var studentInfoForm = $("#studentInfoForm");
var html = "";
html += "<h3>Student Name: " + studentInfo.name + "</h3>";
html += "<h3>Student ID: " + studentInfo.studentID + "</h3>";
studentInfoForm.html(html);
$("#studentInfoModal").show();
}
}
HTML:
<ul data-role="listview" id="studentList"> </ul>
Note: I can't use the onclick tag in HTML, it causes security issues. Cordova also blocks this.
The way you binding the event is not ok. Try binding this way:
$(document).ready(function() {
$("#studentList").on("click", ".studentButton", function() {
var studentId = $(this).data("studentid");
openStudentInfo(studentId);
});
});
And in your HTML generation:
html += "<li><button type='button' class='studentButton' data-studentid='" + students[i].studentID +"'>" + students[i].name + "</button></li>";
This kind of event delagation works not metter how you create the elements inside the root element(studentList in this case), because the event was bound in it, and not on the dynamic elements.
no jquery version of DontVoteMeDown's answer
document.getElementById('studentList').addEventListener('click', function(event) {
var clickedEl = event.target;
if(clickedEl.className === 'studentButton') {
var studentId = clickedEl.dataset.studentId;
openStudentInfo(studentId);
}
});

Change data property using checkbox from false to true using jQuery

I have created list of items in a table. I want to calculate the price of checked items, but can't figure out how to update the data property when a checkbox is checked/unchecked. I have included the code for generating the list and updating the price calculation.
$.each(shopList, function (i, elem) {
var item = elem.item;
var link = elem.link;
var user = elem.user;
var price = elem.price;
var priority = elem.priority;
$(".listItems").append(
'<tr class="items" data-priority="' + priority + '">' +
'<td><input type="checkbox" class="priority"' + ((priority) ? 'checked' : '') + ' /></td>' +
'<td>' + '' + item + '' + '</td>' +
'<td>' + user + '</td>' +
'<td class="price">' + price + '</td>' +
'<td><button class="btn btn-default deleteItem">Del </button></td>' +
'</tr>'
);
});
And the code to update the price:
function updatePriority(){
sumPriority = 0;
$('tr.items[data-priority=true] .price').each(function () {
var total = $(this).text();
if (!isNaN(total) || total.length != 0) {
sumPriority += parseFloat(total);
};
});
$('.totalPriority').html(sumPriority.toFixed(2));
};
When the page renders it has checked and unchecked items and everything works that way at first, but not when a change is made.
How can I update the data-property true/false in the DOM?
Do not use data-property but just use the Checkbox :checked status
Instead of looping over the [data-priority=true] checkboxes you can loop over the checked checkboxes instead, and use parent().find('.price') to find the correct price labels.
function updatePriority(){
sumPriority = 0;
$('.priority:checked').each(function () {
var priceElement = $(this).parent().parent().find('.price');
var total = priceElement.text();
if (!isNaN(total) || total.length != 0) {
sumPriority += parseFloat(total);
};
});
$('.totalPriority').html(sumPriority.toFixed(2));
};
How can I update the data-property true/false in the DOM?
If you really want to keep your code as it is and only update the data-priority attribute when you change a checkbox you can implement change listeners on the checkboxes and change the parents attribute:
$('tr.items .price').change(function() {
if ($(this).is(":checked")) {
$(this).parent().parent().attr("data-priority",true);
}else{
$(this).parent().parent().attr("data-priority",false);
}
});
You can try this :
function updatePriority(){
sumPriority = 0;
$('.listItems tr td .priority').each(function () {
if ($(this).is(":checked"))
{
var price=$(this).parent().find('.price').text();
var total = price;
if (!isNaN(total) || total.length != 0) {
sumPriority += parseFloat(total);
};
}
});
$('.totalPriority').html(sumPriority.toFixed(2));
};

jQuery - why do 2 elements get appended when I click an icon

I've created a JSfiddle here:
basically I have a form that will allow users to input additional sections... but when I have added more than 2 units and then proceed to click on the 'plus' (+) icon I get more than 1 element created in that section... its probably something elementary, but any info will help.
Move your Click functions out of the click function
//add unit input box and increment click counter by one.
addUnit.click(function () {
unitCounter += 1;
unitElementCount = jQuery(".unit-element").length;
if (unitCounter <= 4) {
error.hide();
container.append('<table id="unit-' + unitCounter + '-div" class="create-course-table-element unit-element"><tr><td><label class="unit-label">Unit ' + unitCounter + '</label></td><td><input class="create-course-input-element unit-input" id="unit-id-' + unitCounter + '" name="unit-' + unitCounter + '" /><div id="delete-unit-' + unitCounter + '" class="ui-icon ui-icon-circle-close del-unit" title="Delete unit"></div></td></tr><tr><td align="center">Sections</td><td><div id="add-section-icon-' + unitCounter + '" class="ui-icon ui-icon-plus add-section-icon"></div></td></tr></table><div id="section-id-' + unitCounter + '-div" class="this-section"></div>');
} else if (unitElementCount == 4) {
unitCounter = 5;
error.html("");
error.fadeIn(1500);
error.append("<p class='error-message'>Note: You are only able to add 4 units to a given course. Each unit allows you to add 10 separate sections of content; therefore you may add a total of 40 different sections to a given course. If the material requires more units, you should consider dividing the course into 2 parts.</p>");
}
});
//This part has been slightly modified and moved out of the addUnit.click() function
var counterSecTwo = 0;
var counterSecThree = 0;
var counterSecFour = 0;
jQuery(document).on("click", "#add-section-icon-2",function () {
counterSecTwo += 1;
var container = jQuery("#section-id-2-div");
container.append("<p>test "+counterSecTwo+"</p>");
});
jQuery(document).on("click", "#add-section-icon-3",function () {
counterSecThree += 1;
var container = jQuery("#section-id-3-div");
container.append("<p>test "+counterSecThree+"</p>");
});
jQuery(document).on("click", "#add-section-icon-4",function () {
counterSecFour += 1;
var container = jQuery("#section-id-4-div");
container.append("<p>test "+counterSecFour+"</p>");
});
});
Here I am binding the click handlers to Document as the elements do not exist yet: you could also add the event listener when you create the actual element.
Modified fiddle: http://jsfiddle.net/vewP7/

how can I modify my jQuery function to update the number counter

I am showing number counter in one of my section. When I add new betslips to the container the numbers are displaying correctly. However, when I delete any of the row the counter is not getting updated. For example if there are 3 rows numbered 1, 2 and 3 and if I delete row number 2 the updated values are 1 and 3. Infact the counter should reset to 1 and 2.
Here is my JS code
Adding the betslip rows
function createSingleBetDiv(betInfo) {
var id = betInfo['betType'] + '_' + betInfo['productId'] + '_' + betInfo['mpid'],
div = createDiv(id + '_div', 'singleBet', 'bet gray2'),
a = createA(null, null, null, null, 'right orange'),
leftDiv = createDiv(null, null, 'left'),
closeDiv = createDiv(null, null, 'icon_shut_bet'),
singleBetNumber = ++document.getElementsByName('singleBet').length;
// Info abt the bet
$(leftDiv).append('<p class="title"><b>' + singleBetNumber + '. ' + betInfo['horseName'] + '</b></p>');
var raceInfo = "";
$("#raceInfo").contents().filter(function () {
if (this.nodeType === 3) raceInfo = $(this).text() + ', ' + betInfo['betTypeName'] + ' (' + betInfo['value'] + ')';
});
$(leftDiv).append('<p class="title">' + raceInfo + '</p>');
// Closing btn
(function(id) {
a.onclick=function() {
removeSingleBet(id + '_div');
};
})(id);
$(a).append(closeDiv);
// Creating input field
$(leftDiv).append('<p class="supermid"><input id="' + id + '_input\" type="text"></p>');
// Creating WIN / PLACE checkbox selection
$(leftDiv).append('<p><input id="' + id + '_checkbox\" type="checkbox"><b>' + winPlace + '</b></p>');
// Append left part
$(div).append(leftDiv);
// Append right part
$(div).append(a);
// Appending div with data
$.data(div, 'mapForBet', betInfo);
return div;
}
Function to remove betslip
function removeSingleBet(id) {
// Remove the div
removeElement(id);
// Decrease the betslip counter
decreaseBetSlipCount();
// Decrease bet singles counter
updateBetSinglesCounter();
}
function decreaseBetSlipCount() {
var length = $("#racingBetSlipCount").text().length,
count = $("#racingBetSlipCount").text().substring(1, length-1),
text;
count = parseInt(count);
if (!isNaN(count)) count--;
if (count == 0) text = noSelections;
else text = count;
$("#racingBetSlipCount").text('(' + text + ')');
}
This could be done using only CSS, e.g:
DEMO jsFiddle
HTML:
<div id="bets">
<div class="bet"> some content</div>
<div class="bet"> some content</div>
<div class="bet"> some content</div>
</div>
CSS:
#bets {
counter-reset: rowNumber;
}
#bets .bet {
counter-increment: rowNumber;
}
#bets .bet::before {
content: counter(rowNumber);
min-width: 1em;
margin-right: 0.5em;
}
All row number will be updated automatically when adding/removing any row.
You can manage to do that with following steps;
Enclose bet no with span,
$(leftDiv).append('<p class="title"><b><span class="bet_no">' + singleBetNumber + '<span>. ' + betInfo['horseName'] + '</b></p>');
and I assume you have aouter div called "your_div"
Call below function after every increase and decrease event
function updateBetNo() {
var counter = 1;
$("#your_div .bet_no").each(function(i, val) {
$(this).text(counter);
counter++;
});
}
Make the betNumber findable:
$(leftDiv).append('<p class="title"><b><span class="singleBetNumber">' + singleBetNumber + '</span>. ' + betInfo['horseName'] + '</b></p>');
After an insert or delete renumber:
$('.singleBedNumber').each(function(idx, el) {
$(el).html('' + (idx + 1));
});
The first problem I see is that $("#racingBetSlipCount") is likely not selecting what you think it is. Since #racingBetSlipCount is an id selector it will only select one item.
To me you need to wrap the betnumber in something accessible so you can update it without having to parse through the title.
So first you would update the creation of the betTitle:
$(leftDiv).append('<p class="title"><b><span class=\'betNum\'>' + singleBetNumber + '</span>. ' + betInfo['horseName'] + '</b></p>');
Then you can loop through each and update the number appropriately.
var count = 1;
$.each($(".betNum"), function(){
$(this).html(count++);
});

Categories