I'm trying to build a cart page for an e-commerce website. I'm having trouble figuring out the JS for calculating.. below I'm getting a file through AJAX call called products.json which has products information like id, name, imp, prices etc and an array called productsArray which has product ids saved of products I've clicked on their respective cart icons. Now the logic is if the products.json file contains the id of products present in the array I want it to display on the cart page. So when I click the products add to cart button, for whichever product I click it gets added to local storage and from there I get it and compare it with each of the products present in the JSON file. Now this is printing my product with all furnished information. Now I want to change the price when the quantity of product is changed. I've also added a code fo that below and that too works. When I click on 2 then the price gets multiplied by 2 and showcases it in HTML. similarly for other values. The problem is this works only for the first product. I'm unable to get the functionality working for all products even though the IDs are all same.. How do I tackle this issue? Also I need to be able to access all the product prices as you can see in the second image below, sum them up then update the total on the top and the right containers under various descriptions.. How do I do these as well? Pls help! Have been trying to crack this for past 3-4 days..
let products = new Set();
let counter = 0;
// adding click events to cart icon
document.body.addEventListener('click', e => {
if (e.target.closest('.shopping')) {
products.add(e.target.closest('.prod-card').id);
// adding number of products in cart icon
counter = Number(document.querySelector('#cart-badge').innerHTML) + 1;
document.querySelector('#cart-badge').innerHTML = String(counter);
};
// storing product ids in local storage
localStorage.setItem('Products_IDs', JSON.stringify(Array.from(products)))
});
// parsing JSON List for cart page
let RetrievedData = localStorage.getItem("Products_IDs");
let productsArray = JSON.parse(RetrievedData);
// for (i = 0; i < productsArray.length; i++){
// console.log(productsArray);
// }
let xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
let myProducts = JSON.parse(this.responseText);
for (i = 0; i < productsArray.length; i++) {
for (j = 0; j < myProducts.products.length; j++) {
if (productsArray[i] == myProducts.products[j].id) {
let ReturnedHTML2 = " ";
ReturnedHTML2 = `<div class="cart-items-holder" id='pdt-box'>
<div class='pdt-container' id='pdt-single'>
<img class='img-sweater' src="Images/${myProducts.products[j].imageName}.png" alt="Sweater Image">
<div class="pdt-text w-100">
<div class="text1">
<h6>${myProducts.products[j].name}</h6>
<p class="mb-0 text-secondary">Color : Multicolor</p>
<p class="mb-0 text-secondary">Seller : Indus Valley & Co</p>
<div class="forms mt-xl-3 mt-lg-3 mt-md-2 mt-sm-2 d-flex justify-content-start align-items-start">
<div class="form-group">
<label class='mr-2' for="exampleFormControlSelectSize"></label>
<select class="form-control" id="exampleFormControlSelectSize">
<option>Size : Onesize</option>
<option>S</option>
<option>M</option>
<option>L</option>
<option>XL</option>
<option>XXL</option>
</select>
</div>
<div class="form-group2 ml-3">
<label class='mr-2' for="exampleFormControlSelectQuantity"></label>
<select class="form-control" id="exampleFormControlSelectQuantity">
<option>QTY : 1</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
</div>
</div>
</div>
<div class="text2">
<p class='pricing mb-0'>Rs.<strong id='final-price'>${myProducts.products[j].priceAfterDiscount}</strong> <del id='initial-price'>Rs.${myProducts.products[j].price}</del><span
class="offer font-weight-bold ml-1">(60%Off)</span></p>
<small class="text-secondary">Delivery in 4 - 6 days</small>
</div>
</div>
</div>
<div class="options">
<a class="ml-3 mr-3 text-dark font-weight-bold" id='remove-btn' href="">REMOVE</a> | <a class="ml-3 mr-3 text-dark font-weight-bold" id='wishlist-btn' href="">ADD TO WISHLIST</a>
</div>
</div>
<br>`
document.querySelector('#cart-items-area').innerHTML += ReturnedHTML2;
sessionStorage.setItem("discounted_price", Number(document.getElementById('final-price').innerHTML))
document.getElementById('exampleFormControlSelectQuantity').onchange = function() {
if (document.getElementById('exampleFormControlSelectQuantity').selectedIndex == 1) {
price_1 = sessionStorage.getItem("discounted_price");
document.getElementById('final-price').innerHTML = price_1 * 1;
} else if (document.getElementById('exampleFormControlSelectQuantity').selectedIndex == 2) {
price_2 = sessionStorage.getItem("discounted_price");
document.getElementById('final-price').innerHTML = price_2 * 2;
} else if (document.getElementById('exampleFormControlSelectQuantity').selectedIndex == 3) {
price_3 = sessionStorage.getItem("discounted_price");
document.getElementById('final-price').innerHTML = price_3 * 3;
} else if (document.getElementById('exampleFormControlSelectQuantity').selectedIndex == 4) {
price_4 = sessionStorage.getItem("discounted_price");
document.getElementById('final-price').innerHTML = price_4 * 4;
} else {
price_default = sessionStorage.getItem("discounted_price");
document.getElementById('final-price').innerHTML = price_default;
}
}
}
}
}
}
};
xmlhttp.open("GET", "products.json", true);
xmlhttp.send();
[
Seeing that you've spent a few days on this already. I would consider it worth spending some time to refactor the existing code to be a bit more organized! :)
I see a lot of nested ifs and fors => extract them to separate functions
I see a big template containing an HTML document string => separate function taking 2 arguments & returns the fully rendered html document.
If you end up looking at this code for yet another day, at least it would help if you extracted every part into its own simpler function. you can also then run each function individually to test that it does what you expect this way! :) It helps a tonne to split things up!
Right now it's all one "big monster function" in the XMLHTTPRequest handler.
Also, there is a fair bit of repeated code in the bottom, Whenever you see this it should help guide you to where to reduce and simplify your code a bit!:
if (document.getElementById('exampleFormControlSelectQuantity').selectedIndex == 1) {
price_1 = sessionStorage.getItem("discounted_price");
document.getElementById('final-price').innerHTML = price_1 * 1;
} else if (/*repeated code*/) {
/* repeated code, with a single number changing 2, 3, 4... */
}
the conditional code is (almost) exactly the same, so you don't have to make the same document query for the same element in every case.
const selected_number = document.getElementById('exampleFormControlSelectQuantity').selectedIndex;
and you can re-use this like this:
if (selected_number == 1) {
price_1 = sessionStorage.getItem("discounted_price");
document.getElementById('final-price').innerHTML = price_1 * 1;
} else if (selected_number == 2) {
/* repeated code, with a single number changing 2, 3, 4... */
}
but now you can also just assume the number is... the number you need inside the conditional... so you can shorten the individual number checks to a single snippet of code like this:
price = sessionStorage.getItem("discounted_price");
document.getElementById('final-price').innerHTML = price * selected_number;
Related
I have a dating project. We are using laravel 6 and jquery 3.4.1
The problem is that I need to draw a div when receiving AJAX.
So, javascript and blade template :
static countNewMessages() {
$.get('/some/link/here', results => {
let total = 0;
if (results.length === 0) {
$('.chat__list-block').each(function (index) {
$(this).removeClass('chat__list-block_new');
});
$('.chat__list-non-read-counter').addClass('chat__list-non-read-counter_hidden').each(function (index) {
$(this).text('');
});
$('#number-of-new-messages').addClass('d-none').removeClass('d-flex').html('');
$('#inbox-messages-count-title').html('0');
return false;
}
results.forEach(v => {
if (Chat.containers?.threads) {
let threadElement = $('.chat__list-block[data-pid=' + v.from_userid + ']');
threadElement.addClass('chat__list-block_new');
threadElement.find('.chat__list-non-read-counter')
.addClass('chat__list-non-read-counter_hidden')
.text(v.count);
if (0 < threadElement.length && !threadElement.hasClass('chat__list-block_active') && 0 < v.count) {
threadElement.find('.chat__list-non-read-counter')
.removeClass('chat__list-non-read-counter_hidden');
}
}
total += v.count;
$('#number-of-new-messages').addClass('d-flex').removeClass('d-none').html(total);
$('#inbox-messages-count-title').html(total);
});
});
}
#if(count($threads))
<div>Chat requests</div>
#else
<div>No chat requests</div>
#endif
The standard if-else behavior in the template suits me fine. If a user visits the page but has no messages the second block is displayed, and if he has messages the first block is displayed. But if a user who is on the block "no chat requests" and receives new messages then the block "chat requests" is rendered only after a full refresh of the page.
If you need more information, please let me know
Try this :
#if(count($threads))
<div data-threads-count="{{ count($threads) }}">Chat requests</div>
#else
<div data-threads-count="{{ count($threads) }}">No chat requests</div>
#endif
Now you can access threads count by using data function in jquery ex :
$(selector).data('threads-count');
or
$(selector).attr('data-threads-count');
Both will return threads count
i hope it was useful 😊
I am making a Memory cards game(where cards are flipped on their back and you must open and find the pairs)
I have 12 divs with 12 images and there 6 pairs of images. How can I write JS or jQuery code to check if the images are the same ?
I added data index to divs with setAttribute but on console.log they print undefined.
<div class="frontCard">
<img src="frontCard1.jpg" alt="">
</div>
<div class="frontCard">
<img src="frontCard2.jpg" alt="">
</div>
<div class="frontCard">
<img src="frontCard1.jpg" alt="">
</div>
and js code
const item = document.querySelectorAll(".card");
item.forEach((item, index) => {
item.setAttribute("data-index", index);
})
var openCards = 0;
var points=0;
$(".card").click(function() {
if (openCards >= 2) {
$(".card").removeClass('cardOpen');
$(this).addClass('cardOpen');
openCards = 1;
} else {
$(this).addClass('cardOpen');
openCards++;
if (openCards == 2) {
if (true)//this is where i need the condition
{
const openCard = document.querySelectorAll(".cardOpen");
console.log("index:" + openCard.index);
points++;
console.log(points);
}
}
}
});
basically there are multiple things wrong in your js.
First of - shouldn't .card be .frontCard?
I got a code which is working as expected, even though it might not be the most beuatiful.
Check out the snippet
const item = document.querySelectorAll(".frontCard");
item.forEach((item, index) => {
item.setAttribute("data-index", index);
})
var openCards = 0;
var points=0;
$(".frontCard").click(function() {
if (openCards >= 2) {
$(".frontCard").removeClass('cardOpen');
openCards = 1;
$(this).addClass('cardOpen');
} else {
$(this).addClass('cardOpen');
openCards++;
if (openCards == 2) {
if ($($(".cardOpen")[0]).find("img")[0].src == $($(".cardOpen")[1]).find("img")[0].src){
const openCard = document.querySelectorAll(".cardOpen");
console.log("index:" + openCard.index);
points++;
console.log(points);
$(".frontCard").removeClass('cardOpen');
}else{
console.log("NoPoints")
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="frontCard">
<img src="https://seomofo-da30.kxcdn.com/wp-content/uploads/2010/05/google_logo_new.png" alt="test">
</div>
<div class="frontCard">
<img src="https://i.dlpng.com/static/png/9013_preview.png" alt="test2">
</div>
<div class="frontCard">
<img src="https://seomofo-da30.kxcdn.com/wp-content/uploads/2010/05/google_logo_new.png" alt="test3">
</div>
Assuming that your cards are using the same image, you could check against that. This would require adding ID fields to each card in order to compare the individual cards.
A better way to do this would be to write some JavaScript to contain the cards in an array and fill the array with some ints such as [0,0,1,1,2,2...]. You could then use that to shuffle the cards, or display them and check their values. Just leave yourself a comment as to which number corresponds to which card:)
This would also allow you to display them dynamically if you always start with the back image and then replace the element by ID with the appropriate new image (or lay it over top of it to hide it)
I am creating a Vue app, where a list of jobs will be displayed and this data is coming from a JSON object. In this app I also am adding filtering functionality as well as pagination. So what I have so far is:
<div id="app" v-cloak>
<h2>Location</h2>
<select v-model="selectedLocation" v-on:change="setPages">
<option value="">Any</option>
<option v-for="location in locations" v-bind:value="location" >{{ location }}</option>
</select>
<div v-for="job in jobs">
<a v-bind:href="'/job-details-page/?entity=' + job.id"><h2>{{ job.title }}</h2></a>
<div v-if="job.customText12"><strong>Location:</strong> {{ job.customText12 }}</div>
</div>
<div class="paginationBtns">
<button type="button" v-if="page != 1" v-on:click="page--">Prev</button>
<button type="button" v-for="pageNumber in pages.slice(page-1, page+5)" v-on:click="page = pageNumber"> {{pageNumber}} </button>
<button type="button" v-if="page < pages.length" v-on:click="page++">Next</button>
</div>
<script>
var json = <?php echo getBhQuery('search','JobOrder','isOpen:true','id,title,categories,dateAdded,externalCategoryID,employmentType,customText12', null, 200, '-dateAdded');?>;
json = JSON.parse(json);
var jsonData = json.data;
var app = new Vue({
el: '#app',
data() {
return {
//assigning the jobs JSON data to this variable
jobs: jsonData,
locations: ['Chicago', 'Philly', 'Baltimore'],
//Used to filter based on selected filter options
selectedLocation: '',
page: 1,
perPage: 10,
pages: [],
}
},
methods: {
setPages () {
this.pages = [];
let numberOfPages = Math.ceil(this.jobs.length / this.perPage);
for (let i = 1; i <= numberOfPages; i++) {
this.pages.push(i);
}
},
paginate (jobs) {
let page = this.page;
let perPage = this.perPage;
let from = (page * perPage) - perPage;
let to = (page * perPage);
return jobs.slice(from, to);
},
}
watch: {
jobs () {
this.setPages();
}
},
})
computed: {
filteredJobs: function(){
var filteredList = this.jobs.filter(el=> {
return el.customText12.toUpperCase().match(this.selectedLocation.toUpperCase())
});
return this.paginate(filteredList);
}
}
</script>
So the issue I am running into is that I want the amount of pages to change when the user filters the list using the select input. The list itself changes, but the amount of pages does not, and there ends up being a ton of empty pages once you get past a certain point.
I believe the reason why this is happening is the amount of pages is being set based on the length of the jobs data object. Since that never changes the amount of pages stays the same as well. What I need to happen is once the setPages method is ran it needs to empty the pages data array, then look at the filteredJobs object and find the length of that instead of the base jobs object.
The filteredJobs filtering is a computed property and I am not sure how to grab the length of the object once it has been filtered.
EDIT: Okay so I added this into the setPages method:
let numberOfPages = Math.ceil(this.filteredJobs.length / this.perPage);
instead of
let numberOfPages = Math.ceil(this.jobs.length / this.perPage);
and I found out it is actually grabbing the length of filteredJobs, but since I am running the paginate method on that computed property, it is saying there is only 10 items in the filteredJobs array currently and will only add one pagination page. So grabbing the length of filteredJobs may not be the best route for this. Possibly setting a data variable to equal the filtered jobs object may be better and grab the length of that.
This question already has answers here:
How to put all elements' content in array using jQuery ?
(2 answers)
Closed 6 years ago.
I have the problem that I'm trying to get the content of all span's with the same class.
Thats the relevant html:
#foreach($products as $product
<div class="media-body">
<h4 class="media-heading">{{ $product->title }}</h4>
<p>{{ $product->short_description }}</p>
<div class="pull-right">
<span class="priceCell">{{$product->sales_price}}</span>€
<span>Quantities: </span><span class="quantitie">{{ $product->quantity }} </span>
<br>
</div>
</div>
#endforeach
The $products variable have 6 different products. So 6 different quantities.
I need the different quantities as a array that looks like this:
var quantities = [25,20,15,10,5,1];
current js:
var quantities = document.getElementsByClassName("quantities");
alert(quantities) -- gives : html collection
I need the quantities array like this : [10,5,3,1]
Cause I want to use it with this code:
for (var q = 0; q < quantitys.length; q++) {
endPrice += (parseInt(quantities[q]) * parseFloat(prices[q]));
}
prices variable also looks like this: [15.00, 20.00, ...]
and other things.. but nothing have worked for me. Can someone help me there? Thanks!
Try use simple things
var spans = document.getElementsByClassName("quantities");
for(i=0;i<spans.length;i++)
{
alert(spans[i].innerHTML);
}
<span class="quantities">A</span>
<span class="quantities">B</span>
<span class="quantities">C</span>
<span class="quantities">D</span>
<span class="quantities">E</span>
Simple example with array
function getSpanDataByClass(className){
var spans = document.getElementsByClassName(className),
result = [];
if(!spans){
//no data
}
for(var i = 0; i < spans.length; i++){
result.push(spans[i].innerHTML);
}
return result;
};
function runDebug(){
var spanInnerData = getSpanDataByClass("quantities");
alert(spanInnerData);
};
runDebug();
<span class="quantities">A</span>
<span class="other">B</span>
<span class="quantities">C</span>
<span class="other">X</span>
<span class="quantities">Y</span>
<span class="quantities">Z</span>
I do not have a good grasp of the js namespace and am WAGing* re the title, but that's one of my guesses about what's happening.
WAG = Wild Guess
My app is crashing (dramatically); trying to figure out why. In fact, after 3 Q/A pairs, it blows up the entire Chrome tab..! I'm beginning to suspect I've done something wrong in my code...
Warning: Save your browsing session before running these jsFiddles. (In Chrome, the jsFiddle only blows up its own tab but I can't comment on other browsers)
jsFiddle One
jsFiddle Two - dupe in case jsFiddle One blown away
Please help me to understand exactly which spectacular moronism I've committed today.
HTML:
<div id="result">
<div class="truth tr0"><h2>---</h2></div>
<div class="truth tr1"><h2>answer to one</h2></div>
<div class="truth tr2"><h2>answer to two</h2></div>
<div class="truth tr3"><h2>answer to three</h2></div>
<div class="truth tr4"><h2>answer to four</h2></div>
</div>
<div id="replaceLink">
<div class="youcould yc1">
<h2>QUESTION ONE</h2>
</div>
<div class="youcould yc2">
<h2>QUESTION TWO</h2>
</div>
<div class="youcould yc3">
<h2>QUESTION THREE</h2>
</div>
<div class="youcould yc4">
<h2>QUESTION FOUR</h2>
</div>
<div class="youcould yc5">
<h2>THANK YOU</h2>
</div>
</div>
<div id="response"></div>
<input type="button" id="mybutt" value="Start Test" />
Javascript/jQuery:
var cnt = 0;
var window = {};
window.arrDone = [];
function nextQues() {
if (window.arrDone.length == 4) return 5;
success = 0;
while (success == 0) {
nn = Math.floor(Math.random() * 3) + 1;
if (window.arrDone.indexOf(nn) == -1 && nn != 5) {
success++;
window.arrDone.push(nn);
}
}
return nn;
}
$('.youcould, .truth').hide();
$('.tr0').show();
$('.youcould').click(function() {
$(this).hide();
thisA = window.arrDone[window.arrDone.length -1];
$('.tr'+thisA).show();
});
$('.truth').click(function() {
$(this).hide();
nextQ = nextQues();
$('.yc'+nextQ).show();
});
$('#mybutt').click(function () {
$(this).hide();
$('.tr0').hide();
nextQ = nextQues();
$('.yc'+nextQ).show();
});
My guess would be
var window = {};
window is special, so creating a global variable named window is begging for trouble.
Your while loop runs infinitely on the third pass because it doesn't meet the condition.
At some point, arrDone will contain the numbers 1, 2, and 3, as produced by your random generator (which will never produce 5, btw). In that case, nextQues() does not abort and return five (as arrDone.lenght == 3), and will enter the loop. Your random generator produces nothing but the numbers 1, 2, and 3, which always are already in the array, so the if-condition (that would end the loop) is never fulfilled. You have an infinite loop generating random numbers.
I guess you want
function nextQues() {
var l = 4;
if (window.arrDone.length >= l)
return l+1;
while (true) {
var nn = Math.floor(Math.random() * l) + 1; // generate 1, 2, 3 or 4
if (window.arrDone.indexOf(nn) == -1) {
window.arrDone.push(nn);
return nn;
}
}
}