Unable to update global variable using javascript on button click - javascript

I need to update the price global variable. I believe it may have something to do with scope. I would appreciate it if you could be of assistance in this regard.
This is the script:
var price = 0;
var nextdayClass = $('.delivery1');
var $standardClass = $('.delivery2');
var $pickupClass = $('.delivery3');
nextdayClass.on('click', function() {
var nextday = $('#nextday').data('price');
price = nextday;
console.log(price);
});
standardClass.on('click', function () {
var standard = $('#standard').data('price');
price = standard;
console.log(price);
});
pickupClass.on('click', function () {
var pickup = $('#pickup').data('price');
price= pickup;
console.log(price);
});
console.log(price);
cartTotalHTML += '<div>' +
'<ul>' +
'<li>' +
'<div>Subtotal</div>' +
'<div>' + formatMoney(total) + '</div>' +
'</li>' +
'<li>' +
'<div>Shipping</div>' +
'<div>' + formatMoney(price) + '</div>' +
'</li>' +
'<li>' +
'<div>Total</div>' +
'<div>' + totalAfterShipping(total, price) + '</div' +
'</li>' +
'</ul>' +
'</div>';
$('#cartOutput').html(cartItemHTML);
Here is the html where i am getting my data from:
<div class="delivery">
<div>Shipping method</div>
<div>Select the one you want</div>
<div class="delivery_options">
<label>Next day delivery
<input id="nextday" type="radio" name="radio" data-name="nextday" data-price="9000">
<span class="checkmark delivery1"></span>
<span class="delivery_price">R90</span>
</label>
<label>Standard delivery
<input id="standard" type="radio" name="radio" data-name="standard" data-price="3000">
<span class="checkmark delivery2"></span>
<span >R30</span>
</label>
<label>Personal pickup
<input id="pickup" type="radio" checked="checked" data-name="pickup" data-price="0" name="radio">
<span class="checkmark delivery3"></span>
<span >Free</span>
</label>
</div>
</div>
Here is the html where i am taking my data to:
<div class="col-lg-6 offset-lg-2">
<div class="cart_total">
<div>Cart total</div>
<div>Final info</div>
<div id="cartTotalOutput">
</div>
<div><input type="submit" class="button checkout_button"></div>
</div>
</div>
</div>

There's two issues here. Firstly add() is to add an element to a collection, not to attach an event handler. To do what you want use click() or on().
Secondly, price is only updated after the click event happens, yet your logic is attempting to read it immediately. To address this you need to put the console.log() line in that event handler. Try this:
var price = 0;
var $nextdayClass = $('.delivery1');
$nextdayClass.on('click', function() {
var nextday = $('#nextday').data('price');
price = nextday;
console.log(price);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="delivery1">Click me</button>
<div id="nextday" data-price="1.99">Next day: 1.99</div>
It's also worth noting that you should avoid the use of global variables where possible. A better pattern to use would be just retrieve the data attribute which holds the price where it's actually needed and remove the price variable completely.

It has nothing to do with scope.
Look at your code:
You get an element
You say that when you click the element price should be updated (well, you try to, you made a typo and called add instead of on)
You look at price
Presumably, at some point later, you click the element.
At this point price is updated.
You don't look at it again.
JavaScript does not time travel into the past and change price before you looked at it the first time.
The record of what the value was when you looked at it that is displayed in the console will not change.
If you want to log the value after you click on the element, you have to put the code that does the logging in the function that is called when you click on the element.
var price = 0;
var nextdayClass = $('.delivery1');
nextdayClass.on('click', function() {
var nextday = $('#nextday').data('price');
price = nextday; // The window object stuff is a waste of time
console.log("Clicked value", price);
});
console.log("Initial value", price);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="delivery1">5</button>
<span id=nextday data-price=5></span>

Try JQuery on() like this, also as I assume your element may be generated dynamically, try to bind the event handler to the body element/
var price = 0;
var nextdayClass = $('.delivery1');
$('body').on('click', nextdayClass, function() {
var nextday = $('#nextday').data('price');
window['price'] = nextday;
});
console.log(price); //Prints out 0

Related

Checkbox class incremented in html and jQuery

I have dynamically generated checkbox based on JSON data and that is generated by jQuery. I need to dynamically generate checkbox class name. Here is my code that is generated a checkbox
<td>
<label class="switch">
<input
id="chkEnabled"
checked
type="checkbox"
onchange="checkedorUncheked(' + result.data.resultSet[i].id + ',' + count + ')" class="chkEnabled"' + count +' >
<span class="slider round"></span>
</label >
</td>
Here class="chkEnabled"' + count +' I'm incrementing class value but when I call the method checkedorUncheked I get count value but not getting the class value. Here I console it
` this.checkedorUncheked = function (item, item2) {
//console.log('.chkEnabled' + item2);
$('.chkEnabled' + item2).change(function () {
console.log(item2);`
I'm not able to console inside change event because of class name.
when HTML elements are dynamically generated, you need to rebind the events of the generated element
Try
this.checkedorUncheked = function (item, item2) {
//console.log('.chkEnabled' + item2);
$('.chkEnabled' + item2).on('change',function () {
console.log(item2);
Use on() method instead of directly using .change(), but in comments as suggested don't generate class, generate Id instead and use the same.
then code becomes
$('#chkEnabled' + item2).on('change',function () {
console.log(item2);
UPDATE
<input
id=' + result.data.resultSet[i].id + '
checked
type="checkbox"
onchange="checkedorUncheked(this);" count=' + count +' >
<span class="slider round"></span>
function checkedorUncheked (e){
var itme1 = $(e).attr('id'); /// for id
var item2 = $(e).attr('count'); // count
if($(e).prop('checked') == true){
//do something
}
else{
/// do another
}
}

Summing prices based on quantity

I have appended by data to my panel in the code below which displays all the necessary data.
I am trying to extract the price which is being displayed and multiply by the quantity(the value that will be entered).
The problem is when i alert the price like in the code i get NaN although it is a number.
$(".container").append(
'<p id="name">Drug: '+ drug.name + '</p> <p id="price">Drug Price : '+drug.price+'</p>
<input type="text" onKeyUp="multiply()" id="qty" name="qty" />
<p id="total">Total Price $:'+0+' </p>');
function multiply()
{
a = Number(document.getElementById('qty').value);
b = Number(document.getElementById('price').value);
c = a * b;
document.getElementById('total').value = c;
alert('this' + b);
}
The element <p id="price">Drug Price : '+drug.price+'</p> doesn't contain a value attribute since it's a paragraph element.
I've swapped over lots of the code to JQuery since you're already using it, and used data- attributes to handle the values which lets you store them without having to extract from the elements content.
var drug = {"name":"test", "price":"100"};
// In the appended content, I've added a "data-price" attribute to the price element
// and a span to the total to make the final print out simpler
$(".container").append(
'<p id="name">Drug: ' + drug.name + '</p>'+
'<p id="price" data-price="'+drug.price+'">Drug Price : ' + drug.price + '</p>'+
'<input type="text" onKeyUp="multiply()" id="qty" name="qty" />'+
'<p id="total">Total Price $:<span></span></p>');
function multiply() {
a = Number($('#qty').val());
// Here we access the data attribute
b = Number($('#price').data("price"));
c = a * b;
// Printing out the final value into the span we added earlier
$("#total span").text(c);
alert("Total = " + c);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container"></div>
Since you already using jQuery here is the code:
Use onkeyup="multiply(drug.price, this.value)"
function multiply(a,b){
var c = a * b;
document.getElementById('total').value = c;
}
Please note that id has to be uniqe within the document (You can use class if you have multiple, same elements ) and declare the javaScript variables properly.
Hope that helps.

Remove one of the added lines on click

I want to only remove the line of the specific .delete that I press. How can I specify that in jQuery. Now it's removing all the p since I've chosen that as the value but I can't figure out how to make it specific for each line of append.
HTML
<div id="menu">
<h3>Shopping list</h3>
<div class="line">
<p class="title">Amount</p>
<p class="title">Product</p>
<p class="title">Price</p>
<div>
<input class='amountInput' type='number' name='quantity' min='0' max='1000' step='1'>
<input class='productInput' type="text" name="message" value="">
<input class='priceInput' type='number' name='quantity' min='0' max='1000000' step='0.01'>
<button class="food">Add</button>
</div>
<div class="messages">
</div>
</div>
</div>
<div class="totalPrice">
</div>
jQuery
$(document).ready(function() {
var totalPrice = 0;
$('.food').click(function() {
var $frm = $(this).parent();
var toAdd = $frm.children(".productInput").val();
var addPrice = $frm.children(".priceInput").val();
var addAmount = $frm.children(".amountInput").val();
var div = $("<div>");
div.append("<p>" + addAmount + "</p>", "<p id='product'> " + toAdd + " </p>", "<p>" + addPrice + "</p>", "<p class='delete'>" + "X" + "</p>");
$frm.parent().children(".messages").append(div);
totalPrice += addAmount * addPrice;
$(".totalPrice").text("Total Price: $" + totalPrice);
});
});
$(document).on('click', '.delete', function() {
$('p').remove()
});
If you want to remove the elements that are being added, you'll just need to use $(this) within your function to refer to the element that triggered the call :
// When an element with the delete class is clicked
$(document).on('click', '.delete', function() {
// Remove the closest <div> above the element that was clicked
$(this).closest('div').remove();
});
If you want to update pricing...
When you remove your elements, you may want up consider updating your pricing as well, which you can do by reading your last element and subtracting it :
$(document).on('click', '.delete', function() {
// Get the previous element which contains your price
var priceToSubtract = parseInt($(this).prev().text());
// Subtract the price
totalPrice -= priceToSubtract;
// Update your price
$(".totalPrice").text("Total Price: $" + totalPrice);
$(this).closest('div').remove();
});
This will require you to scope your totalPrice variable outside of your $(document).ready() block as seen below :
<script>
var totalPrice = 0;
$(document).ready(function() {
// Your code here
});
</script>
You should remove the parent div of the all the p, like:
// This is delegated event as the HTML element is added dynamically
$(document).on('click', '.delete', function() {
$(this).closest("div").remove(); // .closest will traverse upwards to find the matched element that is div
});
Note: You need to use event delegation as the HTML elements are added dynamically. Learn more about it here.

jquery each loop write data for each div

I hope this makes sense. I have an onclick and I am trying to write this data for each div with this.
jQuery('.circle_counter_div').each(function() {
var tagtext = '[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]';
})
I am cloning items but I can only write the data for one of them. How do I write data for each cloned item?
So with the above example I want tagtext to equal
[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]
[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]
[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]
Full Code
HTML
<div class="sc_options circle_counter_div" id="clone_this" style="display: block;">
<input type="text" class="circle_size"/>
</div>
<div class="sc_options circle_counter_div" id="clone_this" style="display: block;">
<input type="text" class="circle_size"/>
</div>
<div class="sc_options circle_counter_div" id="clone_this" style="display: block;">
<input type="text" class="circle_size"/>
</div>
<input type="submit" class="sc_options circle_counter_div" id="insert" name="insert" value="<?php _e("Insert", 'themedelta'); ?>" onClick="insertcirclecountershortcode();" style="display:none"/>
Script
// Insert the column shortcode
function insertcirclecountershortcode() {
var tagtext;
var start;
var last;
var start = '[circlecounters]';
var last = '[/circlecounters]';
jQuery('.circle_counter_div').each(function() {
var tagtext = '[circlecounter rel="' + jQuery('.circle_size').val() + '"][/circlecounter]';
})
var finish = start + tagtext + last;
if (window.tinyMCE) {
window.tinyMCE.execInstanceCommand(window.tinyMCE.activeEditor.id, 'mceInsertContent', false, finish);
//Peforms a clean up of the current editor HTML.t
//tinyMCEPopup.editor.execCommand('mceCleanup');
//Repaints the editor. Sometimes the browser has graphic glitches.
tinyMCEPopup.editor.execCommand('mceRepaint');
tinyMCEPopup.close();
}
return;
}
Extended Answer: After some more information was provided perhaps you're just missing the index and value properties on the loop. Its hard to tell, since little sample code is provided.
$('.test').each(function(i,v) {
var tagtext = $(v).html();
console.log(tagtext);
})
http://jsfiddle.net/4xKvh/
Original Answer:
Use use classes instead of an Id. Id's are only suposed to be used once on a page.
Since there should only be one occurance jQuery is filtering the result down to 1, even though the markup may have multiple elements with that Id on the page. This is to make use of the built-in browser function getElementById().
For proof checkout this jsFiddle
Using the class attribute is more appropriate for what you're trying to do.
jQuery('.clone_this').each(function() {
var tagtext = '[something][/something]';
})
And the markup:
<div class="clone_this"></div>
This will allow jQuery to return an array of elements like you're looking for
This is what I needed... Finally got it working.
tagtext = ' ';
jQuery('#circle_counter_div .circlecounter').each(function() {
tagtext += '[circlecounter rel="' + jQuery('.circle_size').val() + '" datathickness="' + jQuery('.circle_thickness').val() + '" datafgcolor="' + jQuery('.circle_color').val() + '" text="' + jQuery('.circle_text').val() + '" fontawesome="' + jQuery('.font_awesome_icon').val() + '" fontsize="' + jQuery('.circle_font_size').val() + '"][/circlecounter]';
});
var start = '[circlecounters]';
var last = '[/circlecounters]';
var finish = start + tagtext + last;

Javascript append/remove elements

I have one question. Is possible delete <span> element added with javascript append?
When i try remove added span then nothing happens.
Like this:
<script type="text/javascript">
$(document).ready(function(){
$('#SelectBoxData span').click(function(){
var StatusID = this.id;
var StatusIDSplit = StatusID.split("_");
var StatusText = $('#SelectBoxData #' + StatusID).text();
$("#SelectBox").append('<span id=' + StatusID + '>' + StatusText + '</span>');
$("#SelectBoxData #" + StatusID).remove();
InputValue = $("#StatusID").val();
if(InputValue == ""){
$("#StatusID").val(StatusIDSplit[1]);
}
else{
$("#StatusID").val($("#StatusID").val() + ',' + StatusIDSplit[1]);
}
});
$('#SelectBox span').click(function(){
var StatusID = this.id;
$("#SelectBox #" + StatusID).remove();
});
});
</script>
<div id="SelectBoxBG">
<div id="SelectBox"><div class="SelectBoxBtn"></div></div>
<div id="SelectBoxData">
<span id="StatusData_1">Admin</span>
<span id="StatusData_2">Editor</span>
<span id="StatusData_4">Test 1</span>
<span id="StatusData_6">Test 2</span>
</div>
<input type="hidden" id="StatusID" />
</div>
Please help me.
Thanks.
Yes, you can delete them. However, you can't add click event handlers to them before they exist. This code:
$('#SelectBox span').click(function(){
var StatusID = this.id;
$("#SelectBox #" + StatusID).remove();
});
will only add a click event handler to <span> elements inside of #SelectBox at the time the code is run (so, based on your provided HTML, zero elements). If you want the event handler to react to dynamically added elements then you need to use a technique called event delegation, using the .on() function:
$('#SelectBox').on('click', 'span', function() {
$(this).remove(); // equivalent to the code you had before
});

Categories

Resources