How to pass variable to total in script - javascript

I have the following code to use but i don't know how to pass the [TOTAL] variable which holds the shopping cart total to the total in the paypal script below. Otherwise the buyer will always be able to buy whatever for $1 which obviously is incorrect.
<script>
var $total = document.getElementById("balancePrice");
paypal.Button.render({
env: 'production', // Or 'sandbox'
client: {
sandbox: 'AYdNDf4q9a-V8p8kcVe885AytuFfmXcwfAn7--tEkgV4UMK7k_QroOJsktMpp6v_Y9r2bKz9OUi6cSFi',
production: 'AfNogtQ4SAPFsVEZIA_KUbMnuN0uNR3cALoL5PsJHlpuV5tMDxwnty2-Ceu11d82KiqnRmEi_Ykap6fP'
},
commit: true, // Show a 'Pay Now' button
payment: function(data, actions) {
return actions.payment.create({
payment: {
transactions: [
{
amount: { total: $total, currency: 'GBP' }
}
]
}
});
},
onAuthorize: function(data, actions) {
return actions.payment.execute().then(function(payment) {
// The payment is complete!
// You can now show a confirmation message to the customer
});
}
}, '#paypal-button');
</script>
Here is the html of the checkout. [BALANCE] is what displays the total cost of the order after shipping etc and what i'd like to be passed to the paypal code.
<div class="divOrderTotal">
<div class="header">
<h3 class="checkout-headers">[checkout3_orderTotal]</h3>
<div class="clear"></div>
</div>
<div id="total_div" name="total_div" class="pad10 boxShadow">
<!--START: total_template_noshipping-->
<div class="totalinstructions pad10 boxShadow">[checkout3_totalinstructions]</div>
<!--END: total_template_noshipping-->
<!--START: total_template-->
<div class="total_items">[itemCount] Item(s)</div>
<div class="total_subtotal">[SUBTOTAL]</div>
<div class="clear"></div>
<!--START: DISCOUNTS-->
<div class="total_discount-detail">[shoppingcart_discount]: (details)</div>
<div class="total_discount">- [DISCOUNT]</div>
<div class="clear"></div>
<!--START: PROMOTIONS-->
<div id="divDiscountDetails" name="divDiscountDetails" style="display:none;">
<div class="total_promotion">Promotion Name</div>
<div class="clear"></div>
<!--START: DISPLAY_PROMOS-->
<div class="total_promotion-name">[promotion_name]</div>
<div class="button right"><!--START: REMOVE_PROMO-->Remove<!--END: REMOVE_PROMO--></div>
<!--END: DISPLAY_PROMOS-->
<div class="clear"></div>
</div>
<div class="clear"></div>
<!--END: PROMOTIONS-->
<!--END: DISCOUNTS-->
<!--START: BUYSAFE-->
<div class="total_buysafe-logo"><img src="assets/templates/common/images/buysafe.gif" alt="" /></div>
<div class="total_buysafe">[buysafe_totalbondcost]</div>
<div class="clear"></div>
<!--END: BUYSAFE-->
<!--START: HANDLING-->
<div class="total_handling-item">[handling_itemname]</div>
<div class="total_handling-price">[handling_price]</div>
<div class="clear"></div>
<!--END: HANDLING-->
<div class="total_cart-shipping">[shoppingcart_shipping]</div>
<div class="total_shipping">[SHIPPING]</div>
<div class="clear"></div>
<div class="total_cart-taxes">[shoppingcart_taxes]</div>
<div class="total_taxes">[TAX]</div>
<div class="clear"></div>
<div class="total_cart-total">[shoppingcart_total]</div>
<div class="total_total">[TOTAL]</div>
<div class="clear"></div>
<!--START: GIFTCERTS-->
<div class="total_cart-giftcerts">[shoppingcart_giftcertificate]: (details)</div>
<div class="total_giftcerts">-[GIFTCERTS]</div>
<div id="divGiftCertDetails" name="divGiftCertDetails" style="display:none;">
<div class="total_giftcerts-details">
<div class="giftcerts-name">Gift Code</div>
<div class="giftcerts-amount">Amount</div>
<div class="giftcerts-balance">Balance</div>
<div class="clear"></div>
</div>
<!--START: GIFTCERTS_DETAILS_ITEMS-->
<div class="total_giftcerts-details-items">
<div class="giftcerts-name">[certificate_name]</div>
<div class="giftcerts-amount">[discount_amount]</div>
<div class="giftcerts-balance">[discount_balance]</div>
<div class="button">Remove</div>
<div class="clear"></div>
</div>
<!--START: GIFTCERTS_DETAILS_ITEMS-->
</div>
<!--END: GIFTCERTS-->
<div id="divBalance">
<div class="total_cart-balance">[shoppingcart_balance]</div>
<div id="balancePrice">[BALANCE]</div>
<div class="clear"></div>
</div>
<!--START: apply_coupon-->
<div id="divApplyCoupon">
<div class="coupon-header">[viewcart_coupon-header]</div>
<div class="coupon-field">
<input id="coupon" onchange="clearContent(this);" maxlength="30" size="15" value="" name="coupon_code" class="txtBoxStyle" />
<input type="button" onclick="applyCoupon(this.form.coupon_code.value);" value="Apply" class="btn" onmouseover="this.className='btn_over'" onmouseout="this.className='btn'" />
</div>
<div class="clear"></div>
<div class="coupon-message">[viewcart_coupon-message]</div>
<div name="divInvalidCoupon" id="divInvalidCoupon" style="display:[invalidCouponDisplay]; color:#F00;">[viewcart_coupon-invalid]</div>
<div class="coupon-applied">[divCouponApplied]</div>
</div>
<div class="clear"></div>
<!--END: apply_coupon-->
<!--END: total_template-->
</div>
</div>
</div>
<div class="clear"></div>
The following errors happen
ppxo_unhandled_error {stack: "Error: TypeError: Cannot read property 'textConten…://www.paypalobjects.com/api/checkout.js:3080:13)", errtype: "[object Error]", timestamp: 1516799614450, windowID: "f18cf37d7c", pageID: "2f88e8f682", …}
And this
types.js:119 Uncaught Error: TypeError: Cannot read property 'textContent' of null
When i do the following in the google console i get
var a = document.getElementById("balancePrice");
var b = a.textContent;
console.log(b)
Results in
$5.64
undefined

Updated with html code. The total output is coming from the variable [BALANCE] which is said to be undefined when i use it
I guess that means calling
//[...]
amount: { total: '[BALANCE]', currency: 'USD' }
//[...]
doesn't do the trick.
Try the following:
var $total = document.querySelector("#balancePrice");
var total = $total.textContent.replace(/[^\d.-]/g, "");
paypal.Button.render({
env: 'production', // Or 'sandbox'
client: {
sandbox: 'test',
production: 'test'
},
commit: true, // Show a 'Pay Now' button
payment: function(data, actions) {
return actions.payment.create({
payment: {
transactions: [
{
amount: { total: total, currency: 'USD' }
}
]
}
});
},
onAuthorize: function(data, actions) {
return actions.payment.execute().then(function(payment) {
// The payment is complete!
// You can now show a confirmation message to the customer
});
}
}, '#paypal-button');
I did grabbing for the total-value in the variables above so i don't have to write a long line of code inside the payment() function.

Related

How do I add PayPal's Smart Buttons to an existing javascript cart?

I am trying to integrate PayPal's Smart Payment Buttons into my cart on my website. My cart is integrated using VanillaCart JS and here is my main.js file:
'use strict';
let cart = (JSON.parse(localStorage.getItem('cart')) || []);
const cartDOM = document.querySelector('.cart');
const addToCartButtonsDOM = document.querySelectorAll('[data-action="ADD_TO_CART"]');
if (cart.length > 0) {
cart.forEach(cartItem => {
const product = cartItem;
insertItemToDOM(product);
countCartTotal();
addToCartButtonsDOM.forEach(addToCartButtonDOM => {
const productDOM = addToCartButtonDOM.parentNode;
if (productDOM.querySelector('.product__name').innerText === product.name) {
handleActionButtons(addToCartButtonDOM, product);
}
});
});
}
addToCartButtonsDOM.forEach(addToCartButtonDOM => {
addToCartButtonDOM.addEventListener('click', () => {
const productDOM = addToCartButtonDOM.parentNode;
const product = {
image: productDOM.querySelector('.product__image').getAttribute('src'),
name: productDOM.querySelector('.product__name').innerText,
price: productDOM.querySelector('.product__price').innerText,
quantity: 1,
};
const isInCart = (cart.filter(cartItem => (cartItem.name === product.name)).length > 0);
if (!isInCart) {
insertItemToDOM(product);
cart.push(product);
saveCart();
handleActionButtons(addToCartButtonDOM, product);
}
});
});
function insertItemToDOM(product) {
cartDOM.insertAdjacentHTML('beforeend', `
<div class="cart__item">
<img class="cart__item__image" src="${product.image}" alt="${product.name}">
<h3 class="cart__item__name">${product.name}</h3>
<h3 class="cart__item__price">${product.price}</h3>
<button class="btn btn--primary btn--small${(product.quantity === 1 ? ' btn--danger' : '')}" data-action="DECREASE_ITEM">−</button>
<h3 class="cart__item__quantity">${product.quantity}</h3>
<button class="btn btn--primary btn--small" data-action="INCREASE_ITEM">&plus;</button>
<button class="btn btn--danger btn--small" data-action="REMOVE_ITEM">×</button>
</div>
`);
addCartFooter();
}
function handleActionButtons(addToCartButtonDOM, product) {
addToCartButtonDOM.innerText = 'In Cart';
addToCartButtonDOM.disabled = true;
const cartItemsDOM = cartDOM.querySelectorAll('.cart__item');
cartItemsDOM.forEach(cartItemDOM => {
if (cartItemDOM.querySelector('.cart__item__name').innerText === product.name) {
cartItemDOM.querySelector('[data-action="INCREASE_ITEM"]').addEventListener('click', () => increaseItem(product, cartItemDOM));
cartItemDOM.querySelector('[data-action="DECREASE_ITEM"]').addEventListener('click', () => decreaseItem(product, cartItemDOM, addToCartButtonDOM));
cartItemDOM.querySelector('[data-action="REMOVE_ITEM"]').addEventListener('click', () => removeItem(product, cartItemDOM, addToCartButtonDOM));
}
});
}
function increaseItem(product, cartItemDOM) {
cart.forEach(cartItem => {
if (cartItem.name === product.name) {
cartItemDOM.querySelector('.cart__item__quantity').innerText = ++cartItem.quantity;
cartItemDOM.querySelector('[data-action="DECREASE_ITEM"]').classList.remove('btn--danger');
saveCart();
}
});
}
function decreaseItem(product, cartItemDOM, addToCartButtonDOM) {
cart.forEach(cartItem => {
if (cartItem.name === product.name) {
if (cartItem.quantity > 1) {
cartItemDOM.querySelector('.cart__item__quantity').innerText = --cartItem.quantity;
saveCart();
} else {
removeItem(product, cartItemDOM, addToCartButtonDOM);
}
if (cartItem.quantity === 1) {
cartItemDOM.querySelector('[data-action="DECREASE_ITEM"]').classList.add('btn--danger');
}
}
});
}
function removeItem(product, cartItemDOM, addToCartButtonDOM) {
cartItemDOM.classList.add('cart__item--removed');
setTimeout(() => cartItemDOM.remove(), 250);
cart = cart.filter(cartItem => cartItem.name !== product.name);
saveCart();
addToCartButtonDOM.innerText = 'Add To Cart';
addToCartButtonDOM.disabled = false;
if (cart.length < 1) {
document.querySelector('.cart-footer').remove();
}
}
function addCartFooter() {
if (document.querySelector('.cart-footer') === null) {
cartDOM.insertAdjacentHTML('afterend', `
<div class="cart-footer">
<button class="btn btn--danger" data-action="CLEAR_CART">Clear Cart</button>
<button class="btn btn--primary" data-action="CHECKOUT">Pay</button>
</div>
`);
document.querySelector('[data-action="CLEAR_CART"]').addEventListener('click', () => clearCart());
document.querySelector('[data-action="CHECKOUT"]').addEventListener('click', () => checkout());
}
}
function clearCart() {
cartDOM.querySelectorAll('.cart__item').forEach(cartItemDOM => {
cartItemDOM.classList.add('cart__item--removed');
setTimeout(() => cartItemDOM.remove(), 250);
});
cart = [];
localStorage.removeItem('cart');
document.querySelector('.cart-footer').remove();
addToCartButtonsDOM.forEach(addToCartButtonDOM => {
addToCartButtonDOM.innerText = 'Add To Cart';
addToCartButtonDOM.disabled = false;
});
}
function checkout() {
}
function countCartTotal() {
let cartTotal = 0;
cart.forEach(cartItem => cartTotal += cartItem.quantity * cartItem.price);
document.querySelector('[data-action="CHECKOUT"]').innerText = `Pay $${cartTotal}`;
}
function saveCart() {
localStorage.setItem('cart', JSON.stringify(cart));
countCartTotal();
}
To break it down, this function allows me to add products to the cart section, add and take away quantities, clear the whole cart and display the pay button with how much the user must pay and this part works. The tutorial I was using is an old one and the PayPal payment method was an old one and didn't really work. So went to https://developer.paypal.com/docs/checkout/ and tried to follow this tutorial.
It gives various steps that render the buttons and you end up with a script like this:
<script
src="https://www.paypal.com/sdk/js?client-id=SB_CLIENT_ID"> // Required. Replace SB_CLIENT_ID with your sandbox client ID.
</script>
<div id="paypal-button-container"></div>
<script>
paypal.Buttons().render('#paypal-button-container');
// This function displays Smart Payment Buttons on your web page.
</script>
<script>
paypal.Buttons({
createOrder: function(data, actions) {
// This function sets up the details of the transaction, including the amount and line item details.
return actions.order.create({
purchase_units: [{
amount: {
value: '0.01'
}
}]
});
},
onApprove: function(data, actions) {
// This function captures the funds from the transaction.
return actions.order.capture().then(function(details) {
// This function shows a transaction success message to your buyer.
alert('Transaction completed by ' + details.payer.name.given_name);
});
}
}).render('#paypal-button-container');
//This function displays Smart Payment Buttons on your web page.
</script>
This works when done, however, it charges the customer whatever data is in the "value: '0.01'". But I need the PayPal button to charge the total of the cart. The issue is the script is run the index.html and the cart code is in the main.js file.
The variable that holds the value of the cart is called 'cartTotal', but when I move the Paypal code to the main.js is stops working and when I change the 'value:0.01' to 'value:cartTotal' this doesn't work either
The cart looks like this, with items added:
The JavaScript line for the pay button is:
<button class="btn btn--primary" data-action="CHECKOUT">Pay</button>
The part after answers:
My file html form looks like this:
<!DOCTYPE html>
<html>
<!-- Title -->
<title>Mobile Masters | Shop</title>
<!-- Meta Tags -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="Ross Currie">
<meta name="description" content="Mobile Gaming Accessories">
<meta name="keywords" content="Ferg, iFerg, Gaming, Mobile, Accessories, Youtube">
<!-- Links to css -->
<link rel="stylesheet" href="mmCSS.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Karma">
<body>
<script src="https://www.paypal.com/sdk/js?client-id=Ab_w_ypGev9_rr3eUjNMbF0fbqnelXD6C6fakevQDAOdLs0YAnxyvwAuQCKl-Ijie-m-hcS9C99sUw6E"> </script>
<!-- Sidebar (hidden by default) -->
<nav class="mm-sidebar mm-bar-block mm-card mm-top mm-xlarge mm-animate-left" style="display: none; z-index: 2; width: 40%; max-width: 415px;" id="mySidebar">
<a id="#products" onclick="mm_close()" class="mm-bar-item mm-button">STORE</a>
<a id="#cart" onclick="mm_close()" class="mm-bar-item mm-button">CART</a>
<a id="#socials" onclick="mm_close()" class="mm-bar-item mm-button">SOCIALS</a>
LOGIN / SIGNUP
<img src="images/back-icon.png" width="30px">
</nav>
<!-- Top menu -->
<div class="mm-top">
<div class="mm-white mm-xlarge" style="max-width:1400px; margin:auto">
<div class="mm-button mm-padding-16 mm-left" onclick="mm_open()">☰</div>
<div class="mm-center mm-padding-16"><img src="images/logo/Logo.png" width="400px"></div>
</div>
</div>
<!-- !PAGE CONTENT! -->
<div class="mm-main mm-content mm-padding" style="max-width: 1400px; margin-top: 70px;">
<h1 class="mm-heading-title">Shop</h1>
<!-- First Photo Grid-->
<div class="mm-row-padding mm-padding-16 mm-center" id="products">
<div class="mm-quarter">
<img class="product__image" src="images/products/Mobile-Fire-Button-Controller.jpg" alt="Product" style="width:100%">
<h2 class="product__name">Mobile Trigger Attachments</h2>
<p>Improve you accuracy, and defeat your opponent very time. This simple attachment ensures you will come out on top in any one vs one. Get yours today</p>
<h3 class="product__price">10.00</h3>
<button class="btn btn--primary" data-action="ADD_TO_CART">Add To Cart</button>
<br>
</div>
<div class="mm-quarter">
<img class="product__image" src="images/product-sample.png" alt="Product" style="width:100%">
<h2 class="product__name">Product 2</h2>
<h3 class="product__price">15.00</h3>
<button class="btn btn--primary" data-action="ADD_TO_CART">Add To Cart</button>
</div>
<div class="mm-quarter">
<img class="product__image" src="images/product-sample.png" alt="Product" style="width:100%">
<h2 class="product__name">Product 3</h2>
<h3 class="product__price">9.99</h3>
<button class="btn btn--primary" data-action="ADD_TO_CART">Add To Cart</button>
</div>
<div class="mm-quarter">
<img class="product__image" src="images/product-sample.png" alt="Product" style="width:100%">
<h2 class="product__name">Product 4</h2>
<h3 class="product__price">0.01</h3>
<button class="btn btn--primary" data-action="ADD_TO_CART">Add To Cart</button>
</div>
</div>
<!-- Second Photo Grid-->
<div class="mm-row-padding mm-padding-16 mm-center">
<div class="mm-quarter">
<img class="product__image" src="images/product-sample.png" alt="Product" style="width:100%">
<h2 class="product__name">Product 5</h2>
<h3 class="product__price">Price</h3>
<button class="btn btn--primary" data-action="ADD_TO_CART">Add To Cart</button>
</div>
<div class="mm-quarter">
<img class="product__image" src="images/product-sample.png" alt="Product" style="width:100%">
<h2 class="product__name">Product 6</h2>
<h3 class="product__price">Price</h3>
<button class="btn btn--primary" data-action="ADD_TO_CART">Add To Cart</button>
</div>
<div class="mm-quarter">
<img class="product__image" src="images/product-sample.png" alt="Product" style="width:100%">
<h2 class="product__name">Product 7</h2>
<h3 class="product__price">Price</h3>
<button class="btn btn--primary" data-action="ADD_TO_CART">Add To Cart</button>
</div>
<div class="mm-quarter">
<img class="product__image" src="images/product-sample.png" alt="Product" style="width:100%">
<h2 class="product__name">Product 8</h2>
<h3 class="product__price">Price</h3>
<button class="btn btn--primary" data-action="ADD_TO_CART">Add To Cart</button>
</div>
</div>
<!-- Third Photo Grid-->
<div class="mm-row-padding mm-padding-16 mm-center">
<div class="mm-quarter">
<img class="product__image" src="images/product-sample.png" alt="Product" style="width:100%">
<h2 class="product__name">Product 9</h2>
<h3 class="product__price">Price</h3>
<button class="btn btn--primary" data-action="ADD_TO_CART">Add To Cart</button>
</div>
<div class="mm-quarter">
<img class="product__image" src="images/product-sample.png" alt="Product" style="width:100%">
<h2 class="product__name">Product 10</h2>
<h3 class="product__price">Price</h3>
<button class="btn btn--primary" data-action="ADD_TO_CART">Add To Cart</button>
</div>
<div class="mm-quarter">
<img class="product__image" src="images/product-sample.png" alt="Product" style="width:100%">
<h2 class="product__name">Product 11</h2>
<h3 class="product__price">Price</h3>
<button class="btn btn--primary" data-action="ADD_TO_CART">Add To Cart</button>
</div>
<div class="mm-quarter">
<img class="product__image" src="images/product-sample.png" alt="Product" style="width:100%">
<h2 class="product__name">Product 12</h2>
<h3 class="product__price">Price</h3>
<button class="btn btn--primary" data-action="ADD_TO_CART">Add To Cart</button>
</div>
</div>
<!-- Pagination -->
<div class="mm-center mm-padding-32">
<div class="mm-bar">
1
2
3
4
»
</div>
</div>
<hr>
<div class="mm-twothird">
<section class="section">
<h1 class="mm-heading-title">Cart</h1>
<div class="cart"></div>
</section>
<div class="mm-right">
<div id="paypal-button-container" style="width: 25%;"></div>
</div>
</div>
<div>
<img src="images/Ferg%20Cart%20image%20copy.png">
</div>
<!-- Footer -->
<footer class="mm-row-padding mm-padding-32">
<hr>
<h1 class="mm-heading-title">Socials</h1>
<div class="mm-half">
<p>Follow Ferg on...</p>
<ul class="mm-ul mm-hoverable">
<a href="https://www.facebook.com/IFerg-2022941574421321" class="social-links">
<li class="mm-padding-16">
<img src="images/Facebook-Icon.png" width="55px" class="mm-left mm-margin-right">
<span class="mm-large">Facebook</span><br>
<span>iFerg | Home</span>
</li>
</a>
<hr>
<a href="https://www.instagram.com/ifergyt/" class="social-links">
<li class="mm-padding-16">
<img src="images/Insta-Icon.png" width="55px" class="mm-left mm-margin-right">
<span class="mm-large">Ferg🔥</span><br>
<span>(#ifergyt)</span>
</li>
</a>
<hr>
<a href="https://twitter.com/Ferg" class="social-links">
<li class="mm-padding-16">
<img src="images/Twitter-Icon.png" width="55px" class="mm-left mm-margin-right">
<span class="mm-large">Ferg</span><br>
<span>(#Ferg)</span>
</li>
</a>
</ul>
</div>
<div class="mm-half">
<p>Check out the links below...</p>
<ul class="mm-ul mm-hoverable">
<a href="https://www.youtube.com/channel/UCVYe9OwcrGrlRmlX8cSWgvg" class="social-links">
<li class="mm-padding-16">
<img src="images/iFerg-MainChannel-New.png" width="55px" class="mm-left mm-margin-right">
<span class="mm-large">iFerg</span><br>
<span>(Channel description)</span>
</li>
</a>
<hr>
<a href="https://www.youtube.com/channel/UCVYe9OwcrGrlRmlX8cSWgvg" class="social-links">
<li class="mm-padding-16">
<img src="images/iFerg-SecondChannel.png" width="55px" class="mm-left mm-margin-right">
<span class="mm-large">iFerg - COD Mobile</span><br>
<span>(Channel description)</span>
</li>
</a>
<hr>
<a href="https://www.youtube.com/channel/UCVYe9OwcrGrlRmlX8cSWgvg" class="social-links">
<li class="mm-padding-16">
<img src="images/iFerg-ThirdChannel.png" width="55px" class="mm-left mm-margin-right">
<span class="mm-large">iFerg - Highlights</span><br>
<span>(Channel description)</span>
</li>
</a>
</ul>
</div>
</footer>
<!-- End page content -->
</div>
<script>
// Script to open and close sidebar
function mm_open() {
document.getElementById("mySidebar").style.display = "block";
}
function mm_close() {
document.getElementById("mySidebar").style.display = "none";
}
</script>
<script src="main.js"></script>
<script>
paypal.Buttons({
createOrder: function(data, actions) {
// This function sets up the details of the transaction, including the amount and line item details.
return actions.order.create({
purchase_units: [{
amount: {
value: checkout()
}
}]
});
}
}).render('#paypal-button-container');
</script>
</body>
</html>
The cart section is:
<div class="mm-twothird">
<section class="section">
<h1 class="mm-heading-title">Cart</h1>
<div class="cart"></div>
</section>
<div class="mm-right">
<div id="paypal-button-container" style="width: 25%;"></div>
</div
</div>
And the section of main.js file that holds the cartTotal is:
function countCartTotal() {
let cartTotal = 0;
cart.forEach(cartItem => cartTotal += cartItem.quantity * cartItem.price);
document.querySelector('[data-action="CHECKOUT"]').innerText = `Pay £ ${cartTotal}`;
}
The PayPal window pops up and then disappears and I have tried the following code:
<script>
paypal.Buttons({
createOrder: function(data, actions) {
// This function sets up the details of the transaction, including the amount and line item details.
return actions.order.create({
purchase_units: [{
amount: {
value: countCartTotal()
}
}]
});
}
}).render('#paypal-button-container');
</script>
And
<script>
paypal.Buttons({
createOrder: function(data, actions) {
// This function sets up the details of the transaction, including the amount and line item details.
return actions.order.create({
purchase_units: [{
amount: {
value: document.getElementById('cartTotal').value
}
}]
});
}
}).render('#paypal-button-container');
</script>
But when I replace "value: document.getElementById('cartTotal').value" or "value: countCartTotal()" with say "value: '0.01'", the window loads fine?
This function of yours does not actually return a value:
function countCartTotal() {
let cartTotal = 0;
cart.forEach(cartItem => cartTotal += cartItem.quantity * cartItem.price);
document.querySelector('[data-action="CHECKOUT"]').innerText = `Pay £ ${cartTotal}`;
}
It appears you would need to extend it with a final line:
...
return cartTotal;
}
Then, you would be able to make use of it as desired:
amount: {
value: countCartTotal()
}
Additionally, you might need &currency=GBP as a parameter when you include the PayPal sdk/js script.

comment reply system with catching specific id value

hi guys I have a blog post page and comment and reply system. Everything works fine except one thing:
When I try to add a reply to a comment, I am always replying to the first comment. I think my fault is I can't reach the specific comment id when I click. Here is my html and ajax code:
HTML CODE
<div class="card" style=" margin-bottom:30px;">
<div class="card-header">
<a class="h3">#Model.Header</a>
<br />
<br />
<div class="row">
<div class="col-md-12 col-xs-12 col-xl-12">
<p style="font-size:small">
<b>Kategori: </b> #Model.Category.CategoryName ,<b>Makale Sayısı :</b> #Model.Category.Articles.Count()
<b>Yorum Sayısı :</b> #Model.Comments.Count() <br />
<b>Yayımlanma Tarihi: </b> #String.Format("{0: d MMMM yyyy}", Model.Date) ,<b>Etiketler:</b><i class="fa fa-tags"></i> #Model.Tags.Count()
</p>
<p style="font-size:small;">
<img class="rounded-circle img-fluid" style="width:100px;height:100px;" src="#Model.User.Photo" alt="#Model.User.FullName" />
Posted by:
#Model.User.UserName
</p>
</div>
</div>
<div class="row">
<div class="col-md-12 col-xs-12 col-xl-12">
<img id="articlephoto" style="width:100%; height:350px" class="rounded float-left" src="#Model.Photo" alt="Card image cap">
</div>
</div>
<div class="row" style="margin-top:20px">
<div class="col-md-12 col-xs-12 col-xl-12">
<p>#Html.Raw(Model.Paragraph)</p>
<p style="font-size:small">
<b>Etiketler:</b>
#foreach (var item in Model.Tags)
{
<span class="tag">#item.TagName,</span>
}
</p>
</div>
</div>
</div>
</div>
<h4>Comments</h4>
<hr />
#foreach (var item in Model.Comments.ToList())
{
<!-- Single Comment -->
<div class="media mb-4">
<img style="height:40px; width:40px;" class="d-flex mr-3 rounded-circle" src="#item.User.Photo" alt="#item.User.FullName">
<div class="media-body" style="width:400px;">
<h5 class="mt-0">#item.User.UserName</h5>
<p style="word-break:break-all">
#item.Paragraph
#if (Convert.ToInt32(Session["UserId"]) == item.UserId)
{
<a class="btn btn-danger" href="/Home/DeleteComment/#item.CommentId">
Delete
</a>
<a class="btn btn-warning replybutton" href="#replyform">
Reply
</a>
}
</p>
<p style="font-size:small"><b>Yorum Tarihi:</b>#String.Format("{0: d MMMM yyyy}", item.Date)</p>
<span id="astar" class=""> #item.CommentId</span>
#foreach (var reply in Model.ReplyComments.Where(x => x.CommentId == item.CommentId).ToList())
{
<div class="media mt-4">
<img style="height:40px; width:40px;" class="d-flex mr-3 rounded-circle" src="#item.User.Photo" alt="#item.User.FullName">
<div class="media-body">
<h5 class="mt-0">#reply.User.UserName</h5>
<p>#reply.Paragraph</p>
#if (Convert.ToInt32(Session["UserId"]) == item.UserId)
{
<a class="btn btn-danger" href="/Home/DeleteReply/#reply.ReplyCommentId">
Sil
</a>
}
</div>
</div>
}
</div>
</div>
<hr />
}
#if (Session["UserId"] != null)
{
<!-- Comments Form -->
<div id="commentform" class="card my-4">
<h5 class="card-header">Yorum Yap:</h5>
<div class="card-body">
<form>
<div class="form-group">
<textarea id="comment" typeof="text" class="form-control" rows="3"></textarea>
</div>
<button type="submit" id="send" class="btn btn-primary">Yorum Yap</button>
</form>
</div>
</div>
<div id="replyform" class="card my-4 d-none">
<h5 class="card-header">Cevap Yaz:</h5>
<div class="card-body">
<div class="form-group">
<textarea id="replytext" name="replytext" typeof="text" class="form-control" rows="3"></textarea>
</div>
<button type="submit" id="reply" name="reply" class="btn btn-primary">Cevap Yaz</button>
</div>
</div>
}
else
{
<div class="row" style="margin-bottom:30px;">
<div class="col-md-6">
<h3 class="alert- alert-heading">Yorum Yapabilmek İçin Üye Girişi Yapmalısınız.</h3>
</div>
</div>
}
AND my javascript ajax code
<script type="text/javascript">
$(document).ready(function () {
$("#reply").click(function (e) {
var r_comment = $("#replytext").val();
var r_commentid = parseInt($("#astar").html());
$.ajax({
url: '/Home/ReplyComment/',
data: { replycomment: r_comment, articleid:#Model.ArticleId, commentid: r_commentid },
type: 'POST',
dataType: 'json',
success: function (data) {
alert("Cevap gönderildi");
window.location.reload();
}
});
});
})
</script>
My problem is that I can't catch the specific comment id when I click the reply button. I am getting the comment id from <span id="astar" class=""> #item.CommentId</span>
"When I try to add a reply to a comment, I am always replying to the first comment. " - it's because all your comments have the same ID and jQuery selects the first matching element.
All comments need to have a unique ID. I don't know what language that loop is in but you need to increment the ID. So astar-1, astar-2, astar-3 etc...
Example;
$(document).ready(function(){
var valueBox = document.getElementById('value-box');
$('.reply').on('click', function(){
var comment = $(this).prev().attr('id');
valueBox.innerHTML += '<br />Reply to comment: ' + comment;
console.log(comment);
});
});
.comment::after {
display: table;
content: ' ';
clear: both;
}
span {
display: block;
float: left;
width: 45%;
}
.reply {
display: block;
float: right;
width: 45%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="comment">
<span id="comment-1">Yorum 1</span>
<div class="reply">Cevapla</div>
</div>
<div class="comment">
<span id="comment-2">Yorum 2</span>
<div class="reply">Cevapla</div>
</div>
<div class="comment">
<span id="comment-3">Yorum 3</span>
<div class="reply">Cevapla</div>
</div>
<div id="value-box">
</div>

Issue when using Vuejs with computed filter

I am writing a filter application by using Vuejs with checkboxes. It works well when I use single checkbox. However, it removes the results when I check more than than 2 checkboxes.
For example, when I check Green and Red, it should show the Title 1 and Title 2.
Or when I check Green, Red, Active, Completed, it should show the Title 1 and Title 2.
You can check my code at: https://jsfiddle.net/dalenguyen/xLcvdy0n/1/
HTML code:
<div class="content">
<div class="row">
<div class="col-md-3 col-sm-4">
<div class="box box-info">
<div class="box-header with-border">
<h3 class="box-title">Filter by</h3>
</div>
<!-- /.box-header -->
<!-- form start -->
<div class="box-body">
<div class="box box-success box-solid">
<div class="box-header with-border">
<h3 class="box-title">Health</h3>
<!-- /.box-tools -->
</div>
<!-- /.box-header -->
<div class="box-body" style="display: block;">
<div class="form-group col-md-12">
<input type="checkbox" id="green" value="Green" v-model="checkedHealths" name="Healths">
<label for="green">Green</label>
</div>
<div class="form-group col-md-12">
<input type="checkbox" id="red" value="Red" v-model="checkedHealths" name="Healths">
<label for="red">Red</label>
</div>
<div class="form-group col-md-12">
<input type="checkbox" id="yellow" value="Yellow" v-model="checkedHealths" name="Healths">
<label for="yellow">Yellow</label>
</div>
</div>
<!-- /.box-body -->
</div>
<div class="box box-success box-solid">
<div class="box-header with-border">
<h3 class="box-title">Status</h3>
<!-- /.box-tools -->
</div>
<!-- /.box-header -->
<div class="box-body" style="display: block;">
<div class="form-group col-md-12">
<input type="checkbox" id="active" value="Active" v-model="checkedStatuses" name="Statuses">
<label for="active">Active</label>
</div>
<div class="form-group col-md-12">
<input type="checkbox" id="completed" value="Completed" v-model="checkedStatuses" name="Statuses">
<label for="completed">Completed</label>
</div>
<div class="form-group col-md-12">
<input type="checkbox" id="cancelled" value="Cancelled" v-model="checkedStatuses" name="Statuses">
<label for="cancelled">Cancelled</label>
</div>
</div>
<!-- /.box-body -->
</div>
<button type="button" class="btn btn-block btn-info" v-on:click="resetFilter">Reset</button>
</div>
<!-- /.box-body -->
</div>
</div>
<div class="col-md-9 col-sm-8">
<div class="col-md-4" v-for="project in filteredProjects">
<div class="box collapsed-box">
<div class="box-header with-border">
<h4 class="box-title">{{project['title']}}</h4>
<!-- /.box-tools -->
</div>
<!-- /.box-header -->
<div class="box-body">
<table class="table table-striped">
<tr>
<td>Status</td>
<td>{{project['Status']}}</td>
</tr>
<tr>
<td>Health</td>
<td>{{project['Health']}}</td>
</tr>
</table>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
</div>
</div>
</div>
Vuejs code:
var app = new Vue({
el: '.content',
data: {
projects: [
{
"title": "Title 1",
"Status": "Active",
"Health": "Green",
},
{
"title": "Title 2",
"Status": "Completed",
"Health": "Red",
},
{
"title": "Title 3",
"Status": "Cancelled",
"Health": "Yellow",
},
]
,
checkedHealths: [],
checkedStatuses: []
},
computed: {
filteredProjects: function(){
let filterProjects = this.projects;
$.each(this.checkedHealths, function(value, key){
filterProjects = filterProjects.filter(function(project){
return project.Health == key;
})
});
$.each(this.checkedStatuses, function(value, key){
filterProjects = filterProjects.filter(function(project){
return project.Status.includes(key);
})
});
return filterProjects;
}
},
mounted: function(){
jQuery('input').iCheck({
checkboxClass: 'icheckbox_square-green',
radioClass: 'iradio_square-green',
increaseArea: '20%' // optional
});
jQuery('input').on('ifChecked', function(e){
if($(this).attr('name') === "Healths")
app.$data.checkedHealths.push($(this).val());
if($(this).attr('name') === "Statuses")
app.$data.checkedStatuses.push($(this).val());
});
jQuery('input').on('ifUnchecked', function(e){
if($(this).attr('name') === "Healths"){
let data = app.$data.checkedHealths;
app.$data.checkedHealths.splice(data.indexOf($(this).val()),1);
}
if($(this).attr('name') === "Statuses"){
let data = app.$data.checkedStatuses;
app.$data.checkedStatuses.splice(data.indexOf($(this).val()),1);
}
});
},
methods: {
resetFilter: function(){
$('input').iCheck('uncheck');
}
}
})
Your filterProjects method should look something like this.
filteredProjects: function(){
let filterProjects = this.projects;
if (this.checkedHealths.length > 0){
filterProjects = filterProjects.filter(project => {
return this.checkedHealths.includes(project.Health);
})
}
if (this.checkedStatuses.length > 0){
filterProjects = filterProjects.filter(project => {
return this.checkedStatuses.includes(project.Status)
})
}
return filterProjects;
}
Updated fiddle.
Essentially, your old filter code was checking each filter individually, where you needed to handle them all at once. The above code loops through the projects and checks if the project's value is in the selected filter values.
You're also using a lot of jQuery where you could just be using native methods and Vue.

Text content randomising on load

I have a site whereby I have different boxes with certain content that when the user refreshes the content will need to randomise in different boxes every time. Basically when you refresh, the content randomises.
So far I have managed to randomise images on load with similar code(Random Images on page load), but for some reason when attempting this for html it doesn't inject the data where I am saying for it to go, as when you refresh the page different areas populate with different text. When pasting into console to text it just lists out the object array. If you could point out where I have gone wrong that would be great. HTML and Script is below.
var text_boxes = [{
number: "2",
sub_title: "Marketers",
}, {
number: "75%",
sub_title: "Average sales increase",
}, {
number: "4",
sub_title: "Developers",
}, {
number: "6",
sub_title: "Full Time",
}, {
number: "45",
sub_title: "Sites Launched",
}, {
number: "2",
sub_title: "Marketers",
}];
var arr3 = [];
$.each(text_boxes,
function(i, el) {
setTimeout(function() {
arr3.push(el);
if (arr3.length === text_boxes.length) {
$(".item").hasClass(".text", function(i) {
$(this).next('.has-text').find('.number span').text(arr3[i].number);
$(this).next('.has-text').find('.sub-title span').text(arr3[i].sub_title);
});
}
}, 1 + Math.floor(Math.random() * 5));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="item small has-text small-offset-large">
<div class="inner">
<a href="" class="">
<div class="text">
<div class="title number">
<span>2</span>
</div>
<div class="sub-title">
<span>Marketers</span>
</div>
</div>
</a>
</div>
</div>
<div class="item small small secondary has-text test">
<div class="inner">
<a href="" class="">
<div class="text">
<div class="title">
<span>Test</span>
</div>
<div class="sub-title">
<span>Test</span>
</div>
</div>
</a>
</div>
</div>
I hope this help you. For me is not clear what is your goal.
var text_boxes = [{
number: "2",
sub_title: "Marketers",
}, {
number: "75%",
sub_title: "Average sales increase",
}, {
number: "4",
sub_title: "Developers",
}, {
number: "6",
sub_title: "Full Time",
}, {
number: "45",
sub_title: "Sites Launched",
}, {
number: "2",
sub_title: "Marketers",
}];
$.each($(".item"), function() {
var $item = $(this);
$.each(text_boxes, function(i, el) {
setTimeout(function() {
if($item.find('div.text').length) {
$item.find('.number span').text(text_boxes[i].number);
$item.find('.sub-title span').text(text_boxes[i].sub_title);
}
}, i * 1000);
});
});
div.item {
margin: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item small has-text small-offset-large">
<div class="inner">
<a href="" class="">
<div class="text">
<div class="title number">
<span>2</span>
</div>
<div class="sub-title">
<span>Marketers</span>
</div>
</div>
</a>
</div>
</div>
<div class="item small has-text small-offset-large">
<div class="inner">
<a href="" class="">
<div class="text">
<div class="title number">
<span>2</span>
</div>
<div class="sub-title">
<span>Marketers</span>
</div>
</div>
</a>
</div>
</div>
<div class="item small has-text small-offset-large">
<div class="inner">
<a href="" class="">
<div class="text">
<div class="title number">
<span>2</span>
</div>
<div class="sub-title">
<span>Marketers</span>
</div>
</div>
</a>
</div>
</div>

Ember Data isn't seeing my local store

Full Disclosure: I am new to Ember.
I have an app that I have started where when the user clicks on the next button, they create an instance of the customer model and that model is saved to local storage. On the next page, I want both the first and last name to pre-populate the text inputs. I have tried to follow the intro video but I have run into a problem. It appears that I am creating the object and then storing it successfully in local storage, but when the user transitions to the next page, the model can't be found. Here is my code:
HTML:
<script type="text/x-handlebars">
<div class="navbar navbar-inverse navbar-fixed-top">
<div id="nobox" class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
</div>
</div>
</div>
<div class="container">
{{outlet}}
<footer>
</footer>
</div>
</body>
</script>
<script type="text/x-handlebars" data-template-name="index">
<div class="container main-container" id="main">
<div class="navbar">
<div class="navbar-inner">
<!--<div class="progress-bar-label-div">
Progress:
</div>
<div class="progress-bar-div">
<div class="progress progress-striped">
<div class="bar" style="width:60%;"></div>
</div>
</div>-->
<div class="btn-group pull-right">
<a class="btn btn-primary" id="captcha" {{action 'create'}}>
Next
</a>
</div>
</div>
</div>
<div id="messages">
</div>
<div class="row top">
<div class="pull-left" >
<h3 class="purple">To start the process, please fill out the captcha below</h3>
</div>
<div class="pull-right">
</div>
</div>
<div class="well">
<div class="row">
<div class="pull-left questions">
</div>
</div>
</div>
</div>
<hr>
</script>
<script type="text/x-handlebars" data-template-name="customer">
<div class="container main-container" id="main">
<div class="navbar">
<div class="navbar-inner">
<div class="btn-group pull-right">
{{#linkTo 'wsnum' action="create" classNames="btn btn-primary"}}Next{{/linkTo}}
</div>
</div>
</div>
<div id="messages">
</div>
<div class="row top">
<div class="pull-left">
<h3>Customer Information</h3>
</div>
<div class="pull-right">
</div>
</div>
<div class="row top">
<div class="pull-left">
<span class="red">*</span> = Denotes required field
</div>
<div class="pull-right form-inputs input-text">
</div>
</div>
<br>
<div class="row-b">
<div class="control-group">
<label class="control-label" for="inputfname">First Name<span class="red">*</span>:</label>
<div class="controls">
{{view Ember.TextField valueBinding='model.first'}}
</div>
</div>
</div>
<div class="row-a">
<div class="control-group">
<label class="control-label" for="inputlname">Last Name<span class="red">*</span>:</label>
<div class="controls">
{{view Ember.TextField valueBinding='model.last'}}
</div>
</div>
</div>
</div>
<input type="hidden" name="prev" value="">
<hr>
</script>
<script type="text/x-handlebars" data-template-name="wsnum">
<div class="container main-container" id="main">
<div class="navbar">
<div class="navbar-inner">
<!--<div class="progress-bar-label-div">
Progress:
</div>
<div class="progress-bar-div">
<div class="progress progress-striped">
<div class="bar" style="width:60%;"></div>
</div>
</div>-->
<div class="btn-group pull-right">
<!--<a class="btn" href="">
Prev
</a>
<a class="btn btn-primary" id="captcha">
Next
</a>-->
{{#linkTo 'customer' classNames="btn btn-primary"}}Prev{{/linkTo}}
</div>
</div>
</div>
<div id="messages">
</div>
<div class="row top">
<div class="pull-left" >
<h3>Choose the Number of Workstations or Point of Sale Accessories only</h3>
</div>
<div class="pull-right">
</div>
</div>
<div class="well">
<div class="row">
<div class="pull-left additional-questions">
How many workstations will you need?
</div>
<div class="pull-right input-text-well">
</div>
</div>
</div>
<div class="well">
<div class="row">
<div class="pull-left additional-questions">
Request Point of Sale Accessories only
</div>
<div class="pull-right radio-wsnum">
<label class="checkbox inline radio-new-pos">
<input type="checkbox" id="posonly1" name="posonly1" value="pos"> POS only
</label>
</div>
</div>
</div>
</div>
<hr>
</script>
<script type="text/x-handlebars" data-template-name="overview">
</script>
<script type="text/x-handlebars" data-template-name="new">
</script>
<script type="text/x-handlebars" data-template-name="existing">
</script>
And my app.js:
App = Ember.Application.create();
App.store = DS.Store.create({
revision: 12,
adapter: DS.LSAdapter.extend()
});
App.Router.map(function() {
// put your routes here
this.route("customer", { path: "/customer" });
this.route("wsnum", {path: "/wsnum"});
});
App.IndexRoute = Ember.Route.extend({
});
App.IndexController = Ember.Controller.extend({
create: function(){
var customer = App.Customer.createRecord({
first:"ron",
last:"testing"
});
console.log('Before the save');
customer.save();
console.log(customer.get('first'));
this.transitionToRoute('customer');
}
});
App.CustomerRoute = Ember.Route.extend({
model: function() {
var customer = App.Customer.find();
console.log(customer.get('first'));
return customer;
}
});
App.WsnumRoute = Ember.Route.extend({
});
var attr = DS.attr;
App.Customer = DS.Model.extend({
first: attr('string'),
last: attr('string')
});
Here is a working example. Any ideas?
In App.CustomerRoute.model(), this line:
var customer = App.Customer.find();
sets the customer variable is being set to result of find(). find() returns an array of all customer records. So when you call get('first') on the array it is undefined, since the array of customers does not have a property first.
Also, the route
this.route("customer", { path: "/customer" });
should probably be:
this.route("customer", { path: "/customer/:customer_id" });
since it seems to be for displaying one customer not a list of them.
With that change, CustomerRoute is not really needed at all. So app looks like:
App = Ember.Application.create();
App.store = DS.Store.create({
revision: 12,
adapter: DS.LSAdapter.extend()
});
App.Router.map(function() {
this.route("customer", { path: "/customer/:customer_id" });
this.route("wsnum", {path: "/wsnum"});
});
App.IndexController = Ember.Controller.extend({
create: function(){
var controller = this;
var customer = App.Customer.createRecord({
first:"ron",
last:"harmon"
});
customer.save().then(function() {
controller.transitionTo('customer', customer);
});
}
});
var attr = DS.attr;
App.Customer = DS.Model.extend({
first: attr('string'),
last: attr('string')
});
Working example here: http://jsbin.com/itogeh/1/edit

Categories