PayPal in context checkout with single page app (Angular) - javascript

I'm trying to use PayPal's in-context checkout in a single page app, but having issues whenever visiting a page with a PayPal button for the second time.
I've just lifted PayPal's sample code from here http://plnkr.co/edit/2GGEyNEFUPCZ7jIIGk9X?p=preview and put it onto a page in my app:
<div>
<div class="container">
<div class="row product">
<div class="col-md-4">
<h3>Toy Story Jessie T-Shirt</h3>
<p>
<a href="http://166.78.8.98/cgi-bin/aries.cgi?live=1&returnurl=http://166.78.8.98/cgi-bin/return.htm&cancelurl=http://166.78.8.98/cgi-bin/cancel.htm" id="t1">
</a>
</p>
</div>
</div>
<div class="row product">
<div class="col-md-4">
<h3>Toy Story Jessie T-Shirt</h3>
<p>
<form id="t2" class="ajaxasync" method="POST" action="http://166.78.8.98/cgi-bin/aries.cgi?live=1&returnurl=http://166.78.8.98/cgi-bin/return.htm&cancelurl=http://166.78.8.98/cgi-bin/cancel.htm">
</form>
</p>
</div>
</div>
</div>
<script>
window.paypalCheckoutReady = function() {
paypal.checkout.setup("6XF3MPZBZV6HU", {
environment: 'sandbox',
click: function(event) {
event.preventDefault();
paypal.checkout.initXO();
$.support.cors = true;
$.ajax({
url: "http://166.78.8.98/cgi-bin/aries.cgi?sandbox=1&direct=1&returnurl=http://166.78.8.98/cgi-bin/return.htm&cancelurl=http://166.78.8.98/cgi-bin/cancel.htm",
type: "GET",
data: '&ajax=1&onlytoken=1',
async: true,
crossDomain: true,
//Load the minibrowser with the redirection url in the success handler
success: function (token) {
var url = paypal.checkout.urlPrefix +token;
//Loading Mini browser with redirect url, true for async AJAX calls
paypal.checkout.startFlow(url);
},
error: function (responseData, textStatus, errorThrown) {
alert("Error in ajax post"+responseData.statusText);
//Gracefully Close the minibrowser in case of AJAX errors
paypal.checkout.closeFlow();
}
});
},
buttons: [
{ container: 't1' }, { container: 't2' }]
});
}
</script>
<script async src="//www.paypalobjects.com/api/checkout.js"></script>
</div>
This works great the first time I visit the page. However, on subsequent visits (without a hard reload in between), I get
Uncaught Error: Attempting to load postRobot twice on the same window
This is because it's trying to load the checkout.js script twice. So if I put a conditional to not run the checkout.js script on subsequent pageviews and instead jump straight to paypal.checkout.setup, I get
Error: You are calling paypal.checkout.setup() more than once. This function can only be called once per page load. Any further calls will be ignored.
And the button is never generated.
I need to maintain the in-context experience (the window that pops up) when the button is clicked. I've searched all through PayPal's docs and have inspected the object thoroughly in the console, but hoping I'm missing something.
How can I "reload" the button on a new page if I've already loaded checkout.js and called paypal.checkout.setup() on a prior page?

I ended up writing a directive to solve my own problem, as it does not appear that PayPal has any kind of single-page functionality.
paypal-checkout directive
The directive runs the PayPal instantiation code once, and then subsequent directive placements will simply show the already-primed button on future page/state loads.

Related

after ajax success refresh / reload page but prevent page blink

as title you see, I meet some problem with my website,
I use ajax to read my API, and after ajax success, I need to reload page to display some data,
Unfortunately, the page sometime will blink and then reload, but sometime will not.
And I use setTimeout to achieve that, because I'm writing shopping cart page,
It allow user edit their shopping carts' goods.
My idea is: after user stop click plus or minus button or stop typing quantity about 1 second,
ajax will execute to read my API, after ajax success, reload page.
So, is there have any ways to prevent page blink?
Or maybe I can made a loading gif to display on the page?
My code will be like:
var timeout = null;
$('.num').on('keyup', function() {
var newNum = $(this).val();
var pid = $(this).attr("name");
clearTimeout(timeout);
timeout = setTimeout(function() {
if(newNum <= 0){
alert("At least 1 product!");
$(this).val("1");
$.ajax({
type: "post",
url: myAPI,
async: false,
data: {
pid: pid,
newNum: 1
},
dataType: "json",
success:function(data){
window.location.reload(true);
},
});
}else {
$.ajax({
type: "post",
url: myAPI,
async: false,
data: {
pid: pid,
newNum: newNum
},
dataType:"json",
success:function(data){
window.location.reload(true);
},
});
}
}, 1000)
});
You can add a loader gif as you want then remove when document loaded.
<div class="loader-fix" style="position:fixed;height:100vh;width:100vw;background:#ffffff;">
<img src="your.gif" />
</div>
<script>
$(window).on('load', function (e) {
$('.loader-fix').fadeOut('slow', function () {
$(this).remove();
});
});
</script>
What is the point in using ajax when you want to reload the page to show updated data...?
success:function(data){
window.location.reload(true);
}
What is the use of above piece of code..?
For your purpose a simple form submission thing was enough, but you have used ajax getting data but not using it anywhere.
If you want to reload the page, then better go with solution by Şahin Ersever.
If you want a dynamic site, where data is fetched from backend in background and updated on frontend without refreshing the page, do something like this.
<html>
<body>
<h1> Dynamic load using AJAX </h1>
<div class="dynamic_div">
<div class="some_class">
<!-- here some more elements may/may not contain dynamic data or some server side based-->
<!-- Like this -->
<h1> Name:- <?php echo $name;?> </h1>
<p> <?php echo $some_other_variable;?> </p>
<p> <?php echo $some_other_variable;?> </p>
....
</div>
</div>
<button onclick="letsload()">Load</button>
<script>
function letsload(){
$.post("someurl",{ data1: "value1", data2 : "value2"},
function(data, status){
if(status == "success"){
$('.dynamic_div').html(data);//Loading updated data
}
});
}
</script>
</body>
</html>
On data variable, you can echo out desired html/json or a success/error code, and handle the data/code in ajax function accordingly.
Edit :-
Looking at your comment But I check my website, if ajax success, I use console.log to print my data, it's not working, but if reload page, it can work.
I have a quick and easy solution for this.
Let's take above example, which I have given.
Suppose if I want updated data to be displayed in dynamic_div what I will do, is I keep the element to be shown inside that div in separate file.
eg:- updated.php
<div class="some_class">
<!-- here some more elements may/may not contain dynamic data or some server side based-->
<!-- Like this -->
<h1> Name:- <?php echo $name;?> </h1>
<p> <?php echo $some_other_variable;?> </p>
<p> <?php echo $some_other_variable;?> </p>
....
</div>
Now What I do is on success of my ajax, I will load this div in to my .dynamic_div like this.
success:function(data){
$('.dynamic_div').load("updated.php");//Load the inside elements into div
}
Now you will get updated data, as you have already updated it somewhere in backend, so load() will load a page inside a division, without refreshing the whole page.
Comment down for any queries.
AJAX Read data from a web server - after a web page has loaded
Update a web page without reloading the page
Send data to a web server in the background
What is Ajax
If you want to reload page then don't use ajax call,
but if you want to load data using ajax then update your html using JavaScript in ajax success message.

nuxt build Breaks VueJS Events

I'm running a nuxtjs application in production and it's causing some VueJS functionality to break, particular with DOM events. However, development mode works just fine as it should flawlessly, though it is slower than production mode due to the code not being minified and compiled and all that.
#click events do not fire their functionality
.prevent does not prevent anything
Here's my source of an example section that does not work.
The #click event calls that change the view do not do anything.
Upon hitting enter to fire v-on:keydown.enter="login" it does not get prevented and the form gets submitted as a GET request to the same page ( the URL shows the GET ?variables )
After looking at the HTML code in the browser to see if there's any logged warnings or errors, there's nothing and nothing on the server side logs.
Plus, the <button> tags that have the #click to fire the login or signup methods do not have any events on them, basically not doing anything; just HTML.
On my production server after running nuxt build by executing npm run build, there are no errors or warnings.
<template>
<div class='card'>
<div class='tabs 2-col'>
<span :class="{active : view != 'signup'}" #click="view = 'login'">
Login
</span>
<span :class="{active : view == 'signup'}" #click="view = 'signup'">
Sign Up
</span>
</div>
<div class='card-body'>
<form v-show="view == 'login'" v-on:keydown.enter="login" novalidate>
<!-- my other html -->
<button #click.prevent="login">Login</button>
</form>
<form v-show="view == 'signup'" v-on:keydown.enter="signup" novalidate>
<!-- my other html -->
<button #click.prevent="signup">Sign Up</button>
</form>
</div>
</div>
</template>
<script>
export default {
data : function(){
return { view : 'login'};
},
methods : {
login: function(){
// my functionality
},
signup:function(){
// my functionality
},
}
}
</script>
Thank you for any help! I've been banging my head for hours.
data proprerty should be a function that return the object. try to do this:
data: function () {
return {
view: 'login',
}
}

Log in from another php file with jquery load function

I would like to do a web site using Aptana IDE and xampp, and it has a few pages. Index page is where all users which does not log in the system and home is where all users which does log in the system must visit. I am very new to develop web site. Because of that I am changing a lot of and vital things during the development. An here my problem is began.
I have created log and sign pages separately using HTML5, CSS, Javascript, JQuery and Php. To achieve more quality service, decided to use also Ajax. These pages works correctly, log page can control validation with jquery
$('#login-form').validate({
//validation rules, messages and submitHandler(ajax code) goes here});
and with using ajax, it can communicate with php file and mysql database so can check whether the user is exist or not.
$.ajax({
type: 'POST',
url: 'log.php',
data: strAjax, //username and password
success: function(data) { //data is echoing from php file either as true or false
if(data) {
window.location.href = "home.php";
}
else {
//some error messages
}
}
});
Sign systems works like it and correctly. But I do not like the design of these pages because of emptiness. So in index file when user click log in button, the log file is showing inside a div with jquery load function.
$(".jumbotron").load("login.html").hide().fadeIn(1500).delay(5000);
Same thing for sign system as well. For good looking, I am satisfied but...
The whole system messed up. (I want to cry) I have to think before start to coding web site, very bad I know but this is my first complete web site. How can achieve a system working properly in this way? I have searched some pages on the internet and they said that the ajax can not work across the pages or something like that. I am also new to stack overflow too, so some important thing will be forgotten. I can edit if you want more information.
Thank You and Regards...
EDIT 1:
<div class="jumbotron">
<div class="container">
<h1>//sometext</h1>
<p>//some text</p>
</div>
</div>
Firstly this is showing on the screen. And when the user press login button, jquery load function running which is above. And loads login.html which works properly by itself.
<form id="login-form" class="text-left">
<div class="form-group">
<label for="lg_username" class="sr-only">Username</label>
<input type="text" class="form-control" id="lg_username" name="username" placeholder="username"
data-container="body" data-toggle="popover" data-placement="left" data-content=""
value="">
</div>
<div class="form-group">
<label for="lg_password" class="sr-only">Password</label>
<input type="password" class="form-control" id="lg_password" name="password" placeholder="password"
data-container="body" data-toggle="popover" data-placement="left" data-content="">
</div>
<div class="form-group login-group-checkbox">
<input type="checkbox" id="lg_remember" name="lg_remember">
<label for="lg_remember">remember</label>
</div>
<button type="submit" class="login-button">Submit</button>
</form>
The jquery validation works right. My rules are valid. If the inputs are ok upon my rules, it send me to home.php. I think ajax code can not work.
submitHandler: function() {
var username = $('#lg_username').val();
var password = $('#lg_password').val();
var checkbox = $('#lg_remember').is(":checked");
var strAjax = "username=" + username + "&password=" + password + "&checkbox=" + checkbox;
$.ajax({
type: 'POST',
url: 'logDeneme.php',
data: strAjax,
cache: false,
success: function(data) {
if(data) {
window.location.href = "home.php";
}
else {
//error message. but when this code run, always send to home page.
}
}
});
return false;
}
This parts all works. It does not works inside index.php. My question is why and how to handle this!
Problem 1
Your form is submitting via a GET request because the JS is not getting called (see #2 below) and the HTML is likely declared like this:
<form action='log.php'>
[...]
</form>
You must specify method='post' to submit POST data.
Problem 2
Unless you're using a jQuery plugin there is no .validate event for forms. You want to use .submit.
Finally, make sure all your javascript is in $(document).ready(function() { ... }); or it won't execute at the right time. Look in the Firefox/Chrome developer console, it's a lifesaver for debugging.

How do I change the UI after a login with Google Chrome Extensions?

Ok, so I am building an extension in Google Chrome and I have it so that when my extension's icon is clicked a login form pops up (default_popup). When they fill this form out it sends an ajax request to my server, authenticates, and sends back my token.
So far so good.
Now, how do I change the popup to show something else now that it is authenticated?
I suspect that it is a really simple problem to solve, but I've been looking around for hours for a solution and I can't find one.
EDIT:
Here's what I'm doing so far:
$(document).on('submit','#login',function(e){
e.preventDefault();
var email = $('#email'),
password = $('#password');
$.ajax({
url: 'https://myurl.com/api/request?email='+email+'&password='+password,
crossDomain: true,
cache: false,
async: false,
dataType: 'json',
success: function(output) {
if (output.status == true) {
api_key = output.results.api_key;
api_secret = output.results.api_secret;
localStorage.setItem('api_key',output.results.api_key);
localStorage.setItem('api_secret',output.results.api_secret);
}
}); });
I want to rerender the output to some other content when the login is done. Is there a clean way of doing this? Usually I would use handlebarsjs, but apparently extensions don't support it without sandboxing.
It's as simple as hiding and showing elements with JavaScript. Have the #logged-in div hidden by default. Once authentication is complete, hide #login-form and show #logged-in. Assuming that you'll be storing some sort of token once they're logged in, you could store this in localStorage and check for it every time your popup.html loads. If it's there, show #logged-in, if it's not, show #login-form.
<html>
<body>
<div id="login-form">
<!-- All your login form content -->
</div>
<div id="logged-in">
<!-- All your content once authenticated-->
</div>
</body>
</html>

PHP included JavaScript is not working properly in Jquery Mobile

In my jquery mobile web app I include a Login-Form on every page the user is navigating to. I do that so that the user could login at every time he wants to, not just on the start page.
Since I do the Form submitting procedure with my very own Ajax logic, I disabled the Jquery Mobile Ajax logic with data-ajax="false" on the Form. The Ajax logic is implemented with JavsScript. On the start page everything works fine, but if I navigate to another page (through a link on the start page), my JavaScript is not firing anymore, but the form is submitted via the Jquery mobile own Ajax logic (and therefore it don't works).
The code (which I include at every page) looks like this:
<div data-role="fieldcontain">
<form id="loginForm" data-ajax="false" onsubmit="login();return false;">
<div data-role="fieldcontain">
<h2>Login</h2>
<label for="textinput1">
Email
</label>
<input name="emaillogin" id="textinput1" placeholder="Email" value=""
type="text">
<label for="textinput2">
Password
</label>
<input name="passwordlogin" id="textinput2" placeholder="Password" value=""
type="password">
</div>
<input type="submit" data-icon="ok" data-iconpos="left" value="OK">
<input type="hidden" name="inputCase" value="login">
</form>
</div>
The JavaScript (which is just at the end of the Code stated above) looks like that:
<script>
function login()
{
var request = $.ajax({
url: "../case.php",
type: "POST",
data: $('#loginForm').serialize(),
dataType: "json"
});
request.done(function(msg) {
if(parseInt(msg.status)==1)
{
//top_notification("Willkommen zurück!","success");
window.location="index.php";
}
else if(parseInt(msg.status)==0)
{
alert(msg.text);
}
else {
alert("Gibts nicht");
}
});
request.fail(function(jqXHR, textStatus) {
alert("Fehler");
});
}
</script>
Maybe I got the Jquery Mobile "we replace just the page-div with the other page-div from the new URL" thing wrong, but I understand it in that way that my whole JS logic will also be pulled from the new ressource.
EDIT Thanks. I have updated my JS code, which looks now like that:
<script>
$(document).on('pageinit', '[data-role="page"]', function(){
$(document).on('click','#submit-btn',function() {
login();
});
});
function login()
{
var request = $.ajax({
url: "../case.php",
type: "POST",
data: $('#loginForm').serialize(),
dataType: "json"
});
request.done(function(msg) {
if(parseInt(msg.status)==1)
{
//top_notification("Willkommen zurück!","success");
window.location="index.php";
}
else if(parseInt(msg.status)==0)
{
alert(msg.text);
}
else {
alert("Gibts nicht");
}
});
request.fail(function(jqXHR, textStatus) {
alert("Fehler");
});
}
</script>
BUT. Now when I navigate to 3 pages, and then submit the login Form, I will get 3 alerts (even when I navigate to just 1 site) of the request.fail function... after that the login goes correctly!
Ajax is still your problem. You have disabled ajax form submition but ajax is still used to load additional pages. This is just my assumption because you didn't mentioned that ajax is turned off all together.
If ajax is still used to load pages all your other pages are loaded into the DOM. Because of this you will have multiple forms with a same ID. When your first page is loaded there's only 1 form in a DOM and that form is used. But when another pages is loaded then additional form (with a same id) is added to the DOM. And whey you click a submit button jQuery will find first form with that ID from the DOM. And because there are 2 of them it will submit first for, same form loaded with an initial page.
That is why you NEVER use inline javascript with jQuery Mobile.
Instead of
onclick="..."
Your submit button should have an id and make it type="button".
<input type="button" data-icon="ok" data-iconpos="left" value="OK" id="submit-btn">
Put a click event on every button and use a $.mobile.activePage selector to find a form on an currently active page.
$(document).on('click','#submit-btn',function() {
$.mobile.activePage.find('#loginForm').submit();
});
Also everything should be wrapped inside a correct jQuery Mobile page event:
$(document).on('pageinit', '[data-role="page"]', function(){
$(document).on('click','#submit-btn',function() {
$.mobile.activePage.find('#loginForm').submit();
});
});

Categories

Resources