this is my first time using this site to ask a question. I'd appreciate the help, I have to turn in this bit of the project today as part of my course :(
I'm following this tutorial: https://www.youtube.com/watch?v=ncsCnC3Ynlw (chapter: stripe elements)
When I visit my checkout page, the card element isn't showing up.
I am at the stage around 3:45:00, and when looking at the checkout, the div for the card element is just a thin, empty bar.
Could anyone help me find where I made a mistake? I think it might be the connection between the script and the template or just the script itself, but I'm losing my mind trying to figure out what I've done wrong.
My views.py:
def BasketView(request):
carrinho = Carrinho(request)
total = str(carrinho.gettotal())
total = total.replace('.', '')
total = int(total)
stripe.api_key='sk_test_[...]'
intent = stripe.PaymentIntent.create(
amount=total,
currency='brl',
metadata={'integration_check': 'accept_a_payment', 'userid': request.user.id}
)
return render(request, 'pedido/pedido_novo.html', {'client_secret': intent.client_secret})
My html template:
{% load static %}
{% block title %}Livraria Aquaflora | Novo Pedido{% endblock %}
{% block adtscripts %}
<script src="https://js.stripe.com/v3/"></script>
<script src="https://unpkg.com/imask#6.0.7/dist/imask.js"></script>
<script src="{% static 'js/orderform.js' %}"></script>
<script src="{% static 'js/payment.js' %}" data-rel-js></script>
{% endblock %}
{% block conteudo %}
<div class="container-fluid">
<div class="row no-gutter">
<div class="col-md-12">
<div class="login d-flex align-items-center py-5">
<div class="container">
<div class="row">
<form id="payment-form" class="col-12 col-lg-6 mx-auto">
<div class="form-group">
<label class="small font-weight-bold">Nome</label>
<input type="text" class="form-control" id="custName" placeholder="Nome Completo" required>
</div>
<div class="form-group">
<label class="small font-weight-bold">CPF</label>
<input type="text" class="form-control" id="cpf" placeholder="CPF" required>
</div>
<div class="form-group">
<label class="small font-weight-bold">CEP</label>
<input type="text" class="form-control" id="cep" placeholder="CEP" required>
</div>
<div class="form-group">
<label class="small font-weight-bold">Endereço</label>
<input type="text" class="form-control" id="ender" placeholder="Endereço com Número e complemento" required>
</div>
<div class="form-group">
<label class="small font-weight-bold">Bairro</label>
<input type="text" class="form-control" id="bairro" placeholder="Bairro" required>
</div>
<div class="form-group">
<label class="small font-weight-bold">Cidade</label>
<input type="text" class="form-control" id="cidade" placeholder="Cidade" required>
</div>
<div class="form-group">
<label class="small font-weight-bold">Estado</label>
<input type="text" class="form-control" id="estado" placeholder="Estado" required>
</div>
<hr class="my-4">
<h4 class="mb-3">Pagamento</h4>
<hr class="my-4">
<div id="payment-element" class="form-control form-control-payment">
</div>
<button id="submit" class="btn btn-primary btn-block py-2 mb-4 mt-5 fw500 w-100" data-secret="{{ client_secret }}">Pagar</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
var CSRF_TOKEN = '{{ csrf_token }}';
</script>
{% endblock %}
and finally, my script,
var stripe = Stripe('pk_test_[...]');
var elem = document.getElementById('submit');
clientsecret = elem.getAttribute('data-secret');
var elements = stripe.elements();
var style = {
base: {
color: "#000",
lineHeight: '2.4',
fontSize: '16px'
}
};
var card = elements.create("card", { style: style });
card.mount("#card-element");
card.on('change', function(event) {
var displayError = document.getElementById('card-errors')
if (event.error) {
displayError.textContent = event.error.message;
$('#card-errors').addClass('alert alert-info');
} else {
displayError.textContent = '';
$('#card-errors').removeClass('alert alert-info');
}
});
I figured it out. Leaving it here for other dummies like me.
Do not add the .js file to the top of the page. Add it to the bottom, after the /body tag. Turns out values will be NULL if the javascript loads before the page.
The Python code looks correct, at least it looks like mine does in my working integration using Django. So here's a couple of things to try:
You don't need the clientSecret until you use stripe.confirmCardPayment() so don't fetch it yet.
Try putting the data-secret="{{client_secret}}" on the <form> element. You'll need to add an events listener to the <form>'s "submit" event anyway to prevent the default submission and trigger the confirmation so might as well retrieve the client_secret then.
I know this doesn't answer why the button was no selectable but at least it gives you some next steps.
Related
AS I am new to jQuery I am trying to learn new things so I need little help in this : As I am trying to hide form field on submitting the form and display successful message but the form keep reloading and fields are not hiding.
following is my code
$(document).ready(function() {
$("#contact_form").submit( function() {
$("#contact_form").hide();
$(".successMessage").show();
});
});
<section class="section NPScontainer">
<a name="pagecontent" id="pagecontent"></a>
<div class="container content page NPScontainer">
<div class="feature_divider NPS-divider"></div>
{% render 'page-multi-column', content: page.content %}
<div class="one-whole column">
<div class="rich-text__content center">
<div class="rich-text__text featured_text">
<h1>THANK YOU</h1>
<p><strong>Thank you for giving us a rating</strong></p>
<p>If you have further details to share with us regarding your rating, please don’t hesitate to share them.</p>
<p>Your feedback will help us improve our services for you.</p>
</div>
<p class="successMessage">"Thank you, we value your feedback. If your feedback requires a response, our customer service team will reach out to you via the email address you have provided.”</p>
<div class="nps_feedback_form">
{% form 'contact' %}
{{ form.errors | default_errors }}
<div class="feedback-type">
<label for="feedback-type">Feedback type</label>
<div class="nps-radio">
<span><input type="radio" name="contact[feedback_type]" value="Compliments" id="comments"><label for="comments">Compliments</label></span>
<span><input type="radio" name="contact[feedback_type]" value="Areas for improvement" id="suggestions"><label for="suggestions">Areas for improvement</label></span>
<span><input type="radio" name="contact[feedback_type]" value="Questions" id="questions"><label for="questions">Questions</label></span>
</div>
</div>
<div class="message">
<label for="message">Feedback</label>
<textarea name="contact[body]" id="message" required></textarea>
</div>
<div class="personal-info">
<div class="first-name">
<label for="first-name">Name</label>
<input type="text" name="contact[first_name]" id="first-name" required/>
</div>
<div class="email">
<label for="email">Email</label>
<input type="email" name="contact[email]" id="email" required />
</div>
</div>
<div class="submit">
<input id="submitnpsform" type="submit" value="Submit"/>
</div>
{% endform %}
</div>
</div>
</div>
</div>
</section>
The default flow for forms is reloading the page when submitting, so you need to prevent this using event.preventDefault(). That should stop the form from reloading the page.
$(document).ready(function() {
$("#contact_form").submit( function(event) {
event.preventDefault()
$("#contact_form").hide();
$(".successMessage").show();
});
});
I'm using Turbolinks in my laravel App, the problem I'm encountering now is when I switch view, the content is loaded before the CSS and images and it causes an awkward display of HTML before quickly switching to full view with is bad for UX. How can I fix this, probably by ensuring turbolinks only switches once it has loaded all CSS and images first?
====EDIT====
I've been able to uncover this much
We are routing from there to the login page:
#extends('./layouts/base')
#section('meta')
#section('title', 'Become a Tuper Seller')
<link rel = "stylesheet" href = " {{ asset('fonts/material-icon/css/material-design-iconic-font.min.css')}} ">
#endsection
#section('body')
<link rel = "stylesheet" href = " {{ mix('css/auth.css')}} ">
<div class = "auth-form">
<div class="main">
<!-- Sign up form -->
<section class="signup">
<div class="container">
<div class="signup-content">
<div class="signup-form">
<h2 class="form-title">Create A Consumer Account</h2>
<form method="POST" class="register-form" id="register-form">
#csrf
<div class="form-group">
<label for="username"><i class="zmdi zmdi-account material-icons-name"></i></label>
<input type="text" name="username" id="name" placeholder="Your Name" value = "{{ old('username')}}"/>
</div>
#error("username")
<div class = "alert alert-danger"> {{ $message }}</div>
#enderror
<div class="form-group">
<label for="email"><i class="zmdi zmdi-email"></i></label>
<input type="email" name="email" value = "{{ old('email')}}" id="email" placeholder="Your Email"/>
</div>
#error('email')
<div class = "alert alert-danger"> {{ $message }}</div>
#enderror
<div class="form-group">
<label for="telephone"><i class="zmdi zmdi-phone"></i></label>
<input type="number" value = "{{ old('telephone') }}"name="telephone" id="telephone" placeholder="Telephone"/>
</div>
#error("telephone")
<div class = "alert alert-danger"> {{ $message }}</div>
#enderror
<div class="form-group">
<label for="password"><i class="zmdi zmdi-lock"></i></label>
<input type="password" name="password" value = "{{ old('password') }}"id="pass" placeholder="Password"/>
</div>
#error('password')
<div class = "alert alert-danger"> {{ $message }}</div>
#enderror
<div class="form-group">
<label for="password_confirmation"><i class="zmdi zmdi-lock-outline"></i></label>
<input type="password" value = "{{ old('password_confirmation')}}" name="password_confirmation" id="re_pass" placeholder="Repeat your password"/>
</div>
<div class="form-group">
<input type="checkbox" name="agree-term" id="agree-term" class="agree-term" />
<label for="agree-term" class="label-agree-term"><span><span></span></span>I agree all statements in Terms of service</label>
</div>
<div class="form-group form-button">
<input type="submit" name="signup" id="signup" class="form-submit" value="Register"/>
</div>
</form>
</div>
<div class="signup-image">
<figure><img src=" {{ asset('img/tuper_logo.jpg')}} " alt="sing up image"></figure>
I want to be a seller
</div>
</div>
</div>
</section>
<!-- Sing in Form -->
</div>
</div>
#endsection
I've noticed that replacing the mix(auth.css) in the login page with inline style tags and pasting the mix file fixes this error but this is not a suitable way of accomplishing this.
Well ive found a pretty neat solution. Since the css lag is caused by the link tag and since it works well when i paste the required css into style tags, i can replace by link tag with
<style>
{{ file_get_contents(asset('css/auth.css'))}}
</style>
This way it dumps the css as content instead of hyper referencing it which erradicates the dumbass delay. Also the mix helper wont work here if mix.version() is set in your webpack.mix.js because of the cache hashing.
But i dont imagine it will be a problem since there will be no cache of the css.
I have been trying to make a form in HTML (Bootstrap) that sends the information to my mail id. for this I am using formsubmit.
for some reason, when submiting the form, It redirects the page to a 'success' page. I do realise that there is a way to redirect it to a different page but I would rather have the section in which the form is present to disappear and show a 'success' section. For reference, here is my form code:
<section id="get-started" class="get-started">
<div class="container">
<div class="row text-center">
<h1 class="display-3 fw-bold text-capitalize">Get started</h1>
<div class="heading-line"></div>
<!-- <p class="lh-lg">
can write something here later
</p> -->
</div>
<!-- START THE CTA CONTENT -->
<div class="row text-white">
<div class="col-12 col-lg-6 gradient shadow p-3">
<div class="cta-info w-100">
<h4 class="display-4 fw-bold">Sign up for Beta!</h4>
<p class="lh-lg">
Join the waitlist for the beta program. Limited spots available! </p>
<h3 class="display-3--brief">What will be the next step?</h3>
<ul class="cta-info__list">
<li>Enter your details.</li>
<li>Wait to be accepted into the beta program.</li>
<li>Enjoy using Clickytize.</li>
</ul>
</div>
</div>
<div class="col-12 col-lg-6 bg-white shadow p-3">
<div class="form w-100 pb-2">
<h4 class="display-3--title mb-5">Join the waitlist!</h4>
<form action="https://formsubmit.co/533cb72c9e26d2503a81229e9c8a246a" method="POST" class="row">
<input type="hidden" name="_captcha" value="false">
<div class="col-lg-6 col-md mb-3">
<input type="text" placeholder="First Name" id="inputFirstName" name="firstName" class="shadow form-control form-control-lg">
</div>
<div class="col-lg-6 col-md mb-3">
<input type="text" placeholder="Last Name" id="inputLastName" name="lastName" class="shadow form-control form-control-lg">
</div>
<div class="col-lg-12 mb-3">
<input type="email" placeholder="email address" id="inputEmail" name="emailId" class="shadow form-control form-control-lg">
</div>
<div class="col-lg-12 mb-3">
<textarea name="message" placeholder="Link your social media profile" id="message" name="message" class="shadow form-control form-control-lg"></textarea>
</div>
<div class="text-center d-grid mt-1">
<button type="submit" class="btn btn-primary rounded-pill pt-3 pb-3">
submit
<i class="fas fa-paper-plane"></i>
</button>
<script>
form.onSubmit= (event)=>{
event.preventDefault();
}
</script>
</div>
</form>
</div>
</div>
</div>
</div>
</section>
If you want to prevent redirection of page and submit the form then you need to take care of submitting the form data using javascript.
First add onsubmit event attribute in your form tag like this:
<form method="POST" class="row my-form" onsubmit="return submitForm()">
We can remove the action attribute from the form tag.
in Javascript:
function submitForm() {
const form = document.querySelector('.my-form')
const formData = new FormData(form)
const url = 'https://formsubmit.co/533cb72c9e26d2503a81229e9c8a246a'
fetch(
url,
{
method: 'POST',
body: formData
}
)
return false
}
We are using the native fetch API to send data to form-data to the endpoint. We are also using the FormData API to create an object of form inputs
Returing false prevents page from reload.
Read more about:
Fetch API FormData API
I'm trying to get the user enter a username and access that value from a separate js file. The page redirects from one html to another after the user enters the name in the server (python) code. Is it causing the issue? Because, no matter what method (name, id, form, input field) I try it doesn't work. If I run the script from within the html file then I'm able to access it. Any help is appreciated!
const userStore = window.localStorage;
document.addEventListener('DOMContentLoaded', () => {
// Connect to websocket
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);
if (!userStore.getItem('username')){
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('#username').onsubmit = function() {
const name = document.querySelector('#username').value;
alert(`Welcome back ${name}!`);
};
});
} else {
userStore.setItem('username', document.querySelector("#username"));
}
{% extends "layout.html" %}
{% block title %}
Title
{% endblock %}
{% block main %}
<section id="cover" class="min-vh-100">
<div id="cover-caption">
<div class="container">
<div class="row text-white">
<div class="col-xl-5 col-lg-6 col-md-8 col-sm-10 mx-auto text-center form p-4">
<h1 class="display-4 py-2">Enter your Username.</h1>
<div class="px-2">
<form id="form" action="/flackchat" method="POST" class="justify-content-center">
<div class="form-group">
<label class="sr-only">Name</label>
<input id="username" type="text" class="form-control" name="username" placeholder="Username">
</div>
<button type="submit" class="btn btn-primary btn-lg">Continue</button>
</form>
</div>
</div>
</div>
</div>
</div>
</section>
{% endblock %}
I am trying to do the multiplication of two HTML inputs as they are typed. This code works for one of the tables.
HTML:
{%extends "dashboard.html"%}
{%block content_A%}
{% for o in org.office %}
<div class="col-md-18">
<div class="card">
<div class="header">
<h4 class="title">Weekly Report for {{org.organization_name}} {{org.organization_ID}}</h4>
<p>Office: {{o.owner_name}} {{o.office_ID}}</p>
<p>Week ending: {{we.strftime('%m-%d-%Y')}}</p>
<p>Invoice submitted: {{today.strftime('%m-%d-%Y')}}</p>
<table>
<div class="panel-body">
<div class="row">
<div class="col-xs-6">
{% if t[1] == o.office_ID%}
<h3>Backpacks: {{t[0]}}</h3>
<h5>Per Piece Profit: {{t[2]}}</h5>
<h4>Total Backpack Profit: {{t[4]}}</h4>
{% else %}
<h3>Backpacks: 0</h3>
{% endif %}
<hr>
</div>
<div class="col-xs-6">
<h3>Hotlines:</h3>
<div class="form-group row">
<div class="col-xs-4">
<input class="form-control" type="text" name="hln" maxlength="4">
<input class="hidden" type="text" name="or" value="{{t[3]}}">
</div>
</div>
<h5>Per Piece Profit: {{t[3]}}</h5>
<h4>Total Hotline Profit:</h4>
<input type="text" name="hlnt" readonly />
</div>
</div>
</div>
</table>
</div>
</div>
</div>
{% endfor %}
{% endblock %}
Here is the Jquery that does the
$(document).on("keyup", "[name='hln']", function() {
var value = parseFloat($(this).val());
var or = $('input[name="or"]').val();
$('input[name="hlnt"]').val(value * or);
});
This works on a single table, however the html is created dynamicly in a Jinja for loop.
When there is more than one table the value is entered into all of them.
See the working example below it will work based upon the child, parent and sibling relationship or DOM Elements and will set the value according to which element the value has been changed
I have copied the code twice so that you can see changing value from one will not set values in all total fields
$(document).on("keyup", "[name='hln']", function() {
var value = parseFloat($(this).val());
// it will select the sibling element which mean the [name='or'] element1
var or = parseFloat($(this).siblings("input[name='or']").val());
// find the parent of input with class 'parent-class' and then find its child with name hlnt and set the value to it
$(this).parents(".parent-class").find('input[name="hlnt"]').val(value * or);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col-xs-6 parent-class"> <!--add class here-->
<h3>Hotlines:</h3>
<div class="form-group row">
<div class="col-xs-4">
<input class="form-control" type="text" name="hln" id="hot" maxlength="4">
<input class="hidden" type="text" id="ovr" name="or" value="3">
</div>
</div>
<h5>Per Piece Profit: 3</h5>
<h4>Total Hotline Profit:</h4>
<input type="text" name="hlnt" id="output-value" readonly />
</div>
<!--copied same content as above to see how this work as saperately withot affeting others->
<div class="col-xs-6 parent-class"> <!--add class here-->
<h3>Hotlines:</h3>
<div class="form-group row">
<div class="col-xs-4">
<input class="form-control" type="text" name="hln" id="hot" maxlength="4">
<input class="hidden" type="text" id="ovr" name="or" value="4">
</div>
</div>
<h5>Per Piece Profit: 4</h5>
<h4>Total Hotline Profit:</h4>
<input type="text" name="hlnt" id="output-value" readonly />
</div>
Don't use a general selector like $('input[name="hlnt"]') this will get all the hlnt named inputs in the page. Instead find a common parent for the hln and hlnt inputs and search from that parent:
$(document).on("keyup", "[name='hln']", function() {
$this = $(this);
//get closest parent
//https://api.jquery.com/closest/
let parent = $this.closest('.col-xs-6');
var value = parseFloat($this.val());
var or = parent.find('input[name="or"]').val();
//use find() to find the child element
parent.find('input[name="hlnt"]').val(value * or);
});