jQuery loop through strings calculate percentage discount from string values - javascript

I'm currently trying to calculate the percentage off -- or difference in percent between two prices on a web store. I also need to be able to loop through all items on the page that have the same classname applied.
Inside the class name div there is some text contained in an empty that needs to be trimmed in order to calculate the percentage. So, I have to remove the text part of the string, keep the numbers and do the math.
The HTML output I'm working with looks like this:
<div class="price-wrap">
<div class="price regular-price">
<span>Retail Price:</span>
$549.00
</div>
<div class="price sale-price">
<span>Our Price:</span>
$489.00
</div>
</div>
I'm using the following jQuery to isolate the price values (numeric) for the sale price and regular price using "parseInt" to get rid of the text:
var regPrice = parseInt($('.regular-price').text().replace(/[^0-9.]/g, ""));
var salePrice = parseInt($('.sale-price').text().replace(/[^0-9.]/g, ""));
This is producing the values that I am expecting. Where I'm running into an issue is how to create a calculation using these var's that will loop through all ".regular-price" and ".sale-price" classes on the page and produce a percentage result.
I have tried using the "each" function to accomplish my result:
$('.sale-price').each(function(index) {
console.log( ((regPrice - salePrice) / (regPrice)) * 100%) );
});
But the console is empty.
I would just like to be able to calculate the percentage diff between the two numbers while looping through all items and write to the console until I decide where to put the value.
Thanks.

I created a function that use regular expression to extract the price from the element. Then I made a small algorithm that calculate the percentage of discount. Moreover, I added the possibility that the price is higher than the competition in order to return a discount of 0% instead a negative value.
function getPrice(elem){
return elem.match(/\d+.\d{2}/);
}
function getDiscount(regPrice, salePrice){
let disc = (regPrice - salePrice) * 100 / regPrice;
return disc < 0 ? 0 : disc;
}
let $regPrice = $('.regular-price');
let $salePrice = $('.sale-price');
$regPrice.each(function(k, v){
let regPrice = getPrice($regPrice[k].innerHTML);
let salePrice = getPrice($salePrice[k].innerHTML);
let discount = getDiscount(regPrice, salePrice);
console.log(discount.toFixed(2) + '% of discount!');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="price-wrap">
<div class="price regular-price">
<span>Retail Price:</span> $549.00
</div>
<div class="price sale-price">
<span>Our Price:</span> $489.00
</div>
</div>
<div class="price-wrap">
<div class="price regular-price">
<span>Retail Price:</span> $569.00
</div>
<div class="price sale-price">
<span>Our Price:</span> $459.00
</div>
</div>
<div class="price-wrap">
<div class="price regular-price">
<span>Retail Price:</span> $369.00
</div>
<div class="price sale-price">
<span>Our Price:</span> $459.00
</div>
</div>

There is a possibility that there are multiple elements with the same class on the page.
You will have to find the closest parent that encompasses both the pricing information and use this to target the element within the container.
$('#button').on('click', () => {
$('.price-wrap').each(function($elem) {
debugger;
let $regPrice = $('.regular-price', this);
let $salePrice = $('.sale-price', this);
let regPrice = getParsedPrice($regPrice);
let salePrice = getParsedPrice($salePrice);
let discount = ((regPrice - salePrice) / (regPrice)) * 100;
discount = discount > 0 ? discount : 0;
$('.discount', this).text(`$${discount.toFixed(2)}%`)
});
});
function getParsedPrice($elem) {
return parseInt($elem.text().replace(/[^0-9.]/g, ""), 10);
}
.price-wrap {
margin-bottom: 1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="price-wrap">
<div class="price regular-price">
<span>Retail Price:</span> $549.00
</div>
<div class="price sale-price">
<span>Our Price:</span> $489.00
</div>
<div class="price">
<span>Discount:</span><span class="discount"></span>
</div>
</div>
<div class="price-wrap">
<div class="price regular-price">
<span>Retail Price:</span> $753.00
</div>
<div class="price sale-price">
<span>Our Price:</span> $620.00
</div>
<div class="price">
<span>Discount:</span><span class="discount"></span>
</div>
</div>
<button id="button">Calculate Discount</button>

You need to move your variable declarations into the loop so that when there are many retail and sale prices, the variables get reset to the current values. You also need to use the index to get the associated regular price.
You can then wrap this in a JQuery object when you want the current sale price that the loop is iterating.
Then, remove the % after 100 and add another ( in the console.log statement.
I would also strongly suggest that you put the prices into their own elements, like a div which would make extracting the numbers much simpler.
$('.sale-price').each(function(index) {
var regPrice = parseInt($($('.regular-price')[index]).text().replace(/[^0-9.]/g, ""));
var salePrice = parseInt($(this).text().replace(/[^0-9.]/g, ""));
console.log(( ((regPrice - salePrice) / (regPrice)) * 100) );
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="price-wrap">
<div class="price regular-price">
<span>Retail Price:</span>
$549.00
</div>
<div class="price sale-price">
<span>Our Price:</span>
$489.00
</div>
</div>

Related

How to get closest value of span on click by class

When a user clicks on a link. I am trying to find the closest span value by class and then get that classes text. Currently it is just returning empty text:
Here is the HTML:
<div class="plan recommended">
<div class="recommended-badge"><span>DOUBLE DATA</span></div>
<div data-equalizer-listener="plan-heading" class="plan-header">
<div class="prices">
<div class="col total">
<div class="price"><sup>$</sup> <span class="amount">85</span> <span class="caption">per month</span></div>
</div>
<p class="min-payment">Min. Total Cost is $2,040 over 24 months.</p>
</div>
</div>
<div class="features">
<div class="feature included_data PO_Included_Data standard first" data-equalizer-selector="PO_Included_Data" style="height: 247px;">
<div class="description"><span class="highlight-text">28GB TOTAL DATA</span><br>
<span class="legal">Includes 14GB + 14GB bonus data for 24 mths<br>
New and recontracting services only<br>
Offer ends 15/04/18<br>
$10 per extra 1GB</span></div>
<div class="more-data-info hide" data-information="included-data"><strong>Data Pool -</strong> Combine any of our latest My Plan Plus (including SIM Only) and My Mobile Broadband Plus plans on the one bill to pool and share the data.</div>
<div>more</div>
</div>
</div>
</div>
and my javascript
So when someone clicks on the a href with the class="more-data-link" I want to find the span with the class="amount" and get its text
$(".more-data-link").on("click", function(event) {
event.preventDefault();
var x = $(this).closest('plan-header').find('.price').find('.amount').text();
console.log(x);
});
Please use this fiddle
$(".more-data-link").on("click", function(event) {
event.preventDefault();
var x = $(this).closest('.plan.recommended').find('.plan-header .price .amount').text();
console.log(x);
});
<div class="plan recommended">
<div class="recommended-badge"><span>DOUBLE DATA</span></div>
<div data-equalizer-listener="plan-heading" class="plan-header">
<div class="prices">
<div class="col total">
<div class="price"><sup>$</sup>
<span class="amount">85</span>
<span class="caption">per month</span></div>
</div>
<p class="min-payment">Min. Total Cost is $2,040 over 24 months.</p>
</div>
</div>
<div class="features">
<div class="feature included_data PO_Included_Data standard first" data-equalizer-selector="PO_Included_Data" style="height: 247px;">
<div class="description"><span class="highlight-text">28GB TOTAL DATA</span><br>
<span class="legal">Includes 14GB + 14GB bonus data for 24 mths<br>New and recontracting services only<br>Offer ends 15/04/18<br>$10 per extra 1GB</span>
</div>
<div class="more-data-info hide" data-information="included-data">
<strong>Data Pool -</strong> Combine any of our latest My Plan Plus (including SIM Only) and My Mobile Broadband Plus plans on the one bill to pool and share the data.
</div>
<div>
more
</div>
</div>
</div>
</div>
You need to select parent (plan recommended) class and then find its child...
For those seeking a solution without jquery (the logic inside the click event is the same as described by Sarvan Kumar):
window.onload = function(){
for(var tL=document.querySelectorAll('.more-data-link'), i=0, j=tL.length; i<j; i++){
tL[i].onclick = function(){
var tE = function fA(e){return !e || (e.className && e.className.indexOf('plan') !== -1 && e.className.indexOf('recommended') !== -1) ? e && e.querySelector('.amount') : fA(e.parentNode)}(this);
console.log(tE ? tE.textContent : '404')
}
}
}
I check your script and find some error in it, use innerHtml in place of text() and closest('plan-header') should be closest('.plan-header'). but may be you not get the proper result because it will search in parents div not subling check link https://www.w3schools.com/jquery/traversing_closest.asp
you can use the simplest and best way to do same by creating the attribute of the more-data-link and save value of amount in it and use the following code.
$(".more-data-link").on("click", function(event) {
event.preventDefault();
var x = $(this).attr('amount');
console.log(x);
});
$(".more-data-link").on("click", function(event) {
event.preventDefault();
var x = $(this).closest('.plan-header').find('.amount').text();
console.log(x);
});
Fixed it. You don't need to use the second find and you missed a dot

How to manipulate numeric values of some html tags and return new value instantly?

im new to js and im trying to manipulate values of some h4 and some other tags then do some little math on each and return the new value back to the tag.
thanks to #drydenlong & #oliverong i was able to achieve this so far:
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="input-group input-group-lg">
<span class="input-group-addon">Discount</span>
<input class="discount" type="text" placeholder="eg 30.22">
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="product">
<h2>Product 1</h2>
<h4 class="maththis">100</h4>
</div>
</div>
<div class="col-md-4">
<div class="product">
<h2>Product 2</h2>
<h4 class="maththis">200</h4>
</div>
</div>
<div class="col-md-4">
<div class="product">
<h2>Product 3</h2>
<h4 class="maththis" id="total">300</h4>
</div>
</div>
</div>
and this basic js
$('.discount').on('input',function(){
var base = parseInt($('.maththis').html());
var dis = $('.discount').val();
var newsum = dis - base;
$('.maththis').text(newsum);
});
i ran into some troubles and got stucked now :(
1) the calculation happens on keydown and that changes the values instantly, so there is also no going back. no new calculation possible unless relaoding page.
2) since im trying to change more values at once i also need to handle global variables i guess because in this example the value of text(). adds just the strings of the variable maththis toghether instead of each. so it makes 100 + 200 + 300= 100200300. this miscalculation gives also a NaN back.
how can i fix it so that the calculation happens on each class="maththis" seperatly and not together and how can i fix the value problem of class="maththis", so that i keep the original value somewhere incase i need to make changes on the discount value?
PEN: https://codepen.io/vup/pen/RxKjrw
PEN click function: https://codepen.io/vup/pen/Qadaqz
thanks alot <3
.text() will get you what is inside of the h1 element, so something like this will return 100:
var h1Val = $(".maththis").text();
Then you can use val() on whatever input field you have to do the math. In your case, it would be something like this:
var discount = $(".discount").val();
var h1Val = $(".maththis").text();
var total = h1Val - discount;
//Do whatever you need with the result
Here is a working example:
$('.discount').on('input',function(){
var base = $('.maththis').text();
var dis = $('.discount').val();
var total = base - dis;
$('#total').text('Total: '+total);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input class="discount" type="text" />
<h1 class="maththis">100</h1>
<span id="total"></span>
In javascript:
let num = +document.getElementsByTagName('h1')[0].innerText
In jquery:
let num = +$('h1').text();

How to get input value from ng-repeat in Angular

I am trying to do a simple shopping cart in angular. Basically I have list of items and would like user to enter Quantity and then get the list of items that have Qty more than 0.
If the Qty is greater than 0 then I will add them into an array otherwise remove it.
I must be doing something wrong that is preventing me to get the Qty correct.
It works only first time but the second time it does not update.
My controller:
var extras1 = {Id:1,PackageName:"Balloons",Description:'Pack of 6',Cost:'$50.00',Qty:0}
var extras2 = {Id:2,PackageName:"Hot Chips",Description:'Fresh fried hot chips fully of yummy fat and cholesterol.',Cost:'$10.00',Qty:0}
var extras3 = {Id:3,PackageName:"Sausages",Description:'Hot sausages from premium offcuts',Cost:'$10.00',Qty:0}
$scope.extras =[extras1,extras2,extras3];
$scope.extraSelected = function(){
$scope.selectedExtra =[];
angular.forEach($scope.extras, function(extra)
{
if(extra.Qty > 0 )
{
console.log('Extra added');
$scope.selectedExtra.push(extra);
}
})
console.log($scope.selectedExtra);
}
Markup :
<div ng-repeat="extra in extras" class="text-left">
<div class="row-centered">
<div class="row form-group">
<label class="col-md-1 col-sm-offset-1 step1-question" >{{$index + 1}}</label>
<div class="col-md-8">
<span class="h4 step1-answer"> {{ extra.PackageName}} </span>
<br/>
<span class="h5"> {{ extra.Description}} </span>
<br/>
<span class="h5"> {{ extra.Cost}} </span>
</div>
<div class="col-md-1">
<input type='text' class="form-control step1-answer text-center "
ng-model="extra.Qty"
placeholder="0" style="background-color:#ffffff;padding: 5px;height: 45px;"
ng-change="extraSelected(extra)"
/>
</div>
</div>
<hr/>
</div>
</div>
Maybe something, like this?
<input type="number" ng-model="extra.Qty" ng-change="extraSelected()">
$scope.extraSelected = function () {
$scope.selectedExtra = [];
angular.forEach($scope.extras, function(extra) {
if(extra.Qty > 0) {
console.log('Extra added');
$scope.selectedExtra.push(extra);
}
})
console.log($scope.selectedExtra);
}
$scope.extraSelected = function(extra){
$scope.selectedExtra =[];
angular.forEach($scope.extras, function(extra)
You have extra defined as the parameter being passed in and also as the parameter to the forEach function - the forEach is looping over the array with Qty is 0, so it will always be zero.
Change one of the function parameters so it doesnt clobber the other.
Lesson in functional scoping here...

Make this regex work with all numbers even though there is no decimals

Im trying to write a script that get the negative percentage number between two numbers. since one number is dynamic and have different currencies, decimals etc I need a regex for that. It almost works, but the first two numbers only work if i add two decimals (.00) to the number. Why is this?
The output on all numbers should be 33.
Fiddle: JSFIDDLE
HTML:
<div class="left">
<em class="price product-card-price">
€1.000
<span class="vatstatus">Exclusief BTW</span>
</em>
<em class="price product-card-price before">
1500
</em>
<a class="pricebubble"></a>
</div>
<div class="left">
<em class="price product-card-price">
1 000:-
<span class="vatstatus">Exclusief BTW</span>
</em>
<em class="price product-card-price before">
1500
</em>
<a class="pricebubble"></a>
</div>
<div class="left">
<em class="price product-card-price">
10,000.00SEK
<span class="vatstatus">Exclusief BTW</span>
</em>
<em class="price product-card-price before">
15000
</em>
<a class="pricebubble"></a>
</div>
<div class="left">
<em class="price product-card-price">
SEK10,000.00
<span class="vatstatus">Exclusief BTW</span>
</em>
<em class="price product-card-price before">
15000
</em>
<a class="pricebubble"></a>
</div>
Script:
$('.left').each(function() {
var frstCol = parseInt($(this).find('em.price.product-card-price').text().replace(/ /g, '').replace(/[^0-9.]|\.(?=\d{3,})/g, "").replace(/(\.\d+)+/,''), 10);
var seCol = parseInt($(this).find('em.price.product-card-price.before').text().replace(/[^0-9.]/g, ""), 10);
var result = 100 - (frstCol / seCol) * 100;
console.log("frstCol: ", frstCol, ", seCol: ", seCol);
$(this).find('a.pricebubble').text(parseInt(result)|| 0);
});
The issue is because both of the em within .left have the same class, so you're picking up the text of both in frstCol. You should use :first to restrict the selector:
var frstCol = parseInt($(this).find('em.price.product-card-price:first').text().replace(/ /g, '').replace(/[^0-9.]|\.(?=\d{3,})/g, "").replace(/(\.\d+)+/,''), 10);
Updated fiddle
Also note that you can simplify your code slightly:
$('.left').each(function() {
var frstCol = parseInt($(this).find('em.price.product-card-price:first').text().trim().replace(/[^0-9.]|\.(?=\d{3,})/g, ""), 10);
var seCol = parseInt($(this).find('em.price.product-card-price.before').text().trim().replace(/[^0-9.]/g, ""), 10);
var result = parseInt(100 - (frstCol / seCol) * 100, 10);
$(this).find('a.pricebubble').text(result || 0);
});

I have 2 price values and I want to calculate the difference

I have 2 price range. Regular Price and Offer Price displayed on screen with the below HTML rendered.
I am trying to calculate the price difference using Javascript/jquery and insert a div with the discount price.
<div class="price-box">
<p class="old-price">
<span class="price-label">Regular Price:</span>
<span class="price" id="old-price-221">Rs17.00 </span>
</p>
<p class="special-price">
<span class="price-label">Special Price</span>
<span class="price" id="product-price-221">Rs14.45 </span>
</p>
<div>
<span>Discount Price:</span>
<span>XXXXXX</span>
</div>
</div>
I have this currency symbol also displayed along with the price. So, I am wondering how to calculate the difference between "Regular Price" and "Special Price".
Can some one please help me?
P.S. I searched the site and did not find the relevant answers.
There it is : http://jsfiddle.net/s7w98ngt/2/
jQuery part :
$('.price-box').each(function(){
var element = $(this),
oldPriceRaw = element.find('.old-price .price').text(),
specialPriceRaw = element.find('.special-price .price').text(),
oldPrice = parseFloat(oldPriceRaw.replace('Rs','')),
specialPrice = parseFloat(specialPriceRaw.replace('Rs','')),
diff = 'Rs'+(oldPrice - specialPrice).toFixed(2), // 2 numbers after the comma
diffElement = element.find('.diff-price');
diffElement.text(diff);
});
HTML a bit modified :
<div class="price-box">
<p class="old-price">
<span class="price-label">Regular Price:</span>
<span class="price" id="old-price-221">Rs17.00 </span>
</p>
<p class="special-price">
<span class="price-label">Special Price</span>
<span class="price" id="product-price-221">Rs14.45 </span>
</p>
<div>
<span>Discount Price:</span>
<span class="diff-price"></span>
</div>
</div>
The tricky thing was to get the current prices value as float numbers. Then, we just calcul the difference.

Resources