Bug with PayPal API context checkout - php

I have a problem with PayPal Express Checkout integration : https://developer.paypal.com/docs/classic/express-checkout/in-context/javascript_advanced_settings/#color
If I close the pop-up before it loads completely, the pop-up won't show up anymore until I refresh!
This does occur on all browsers. The error on Chrome console is:
ppxo_paypal_legacy_gettoken_initxo Object
print # logger.js:65
Here is my code :
window.paypalCheckoutReady = function() {
paypal.checkout.setup("{$PayPal_in_context_checkout_merchant_id}", {
environment: {if $PAYPAL_SANDBOX}"sandbox"{else}"production"{/if},
click: function(event) {
event.preventDefault();
paypal.checkout.initXO();
updateFormDatas();
var str = '';
if($('.paypal_payment_form input[name="id_product"]').length > 0)
str += '&id_product='+$('.paypal_payment_form input[name="id_product"]').val();
if($('.paypal_payment_form input[name="quantity"]').length > 0)
str += '&quantity='+$('.paypal_payment_form input[name="quantity"]').val();
if($('.paypal_payment_form input[name="id_p_attr"]').length > 0)
str += '&id_p_attr='+$('.paypal_payment_form input[name="id_p_attr"]').val();
$.support.cors = true;
$.ajax({
url: "{$base_dir_ssl}modules/paypal/express_checkout/payment.php",
type: "GET",
data: '&ajax=1&onlytoken=1&express_checkout='+$('input[name="express_checkout"]').val()+'&current_shop_url='+$('input[name="current_shop_url"]').val()+'&bn='+$('input[name="bn"]').val()+str,
async: true,
crossDomain: true,
success: function (token) {
var url = paypal.checkout.urlPrefix +token;
paypal.checkout.startFlow(url);
},
error: function (responseData, textStatus, errorThrown) {
alert("Error in ajax post"+responseData.statusText);
paypal.checkout.closeFlow();
}
});
},
buttons: [
{
container: 'paypal_process_payment',
type: 'checkout',
color: 'blue',
size: 'small',
shape: 'pill'
},
{
container: 'payment_paypal_express_checkout',
type: 'checkout',
color: 'gold',
size: 'small',
shape: 'pill'
}
]
});
};

I ran into the same issue,
After looking into the source code, it turns out that when paypal.checkout.initXO(); the paypal.checkout.startFlow function is wrapped in a once function, which means you can only call startFlow once. and paypal.checkout.initXO is overwritten to show a warning in the console.
Inside, paypal.checkout.closeFlow there is a call to paypal.checkout.reset which is important to resetting these functions.
The problem was happening when the user clicks the close button too early, where the startFlow promise wasn't being resolved (which means when the user closes the modal it will redirect to the canceled url) nor the paypal.checkout.closeFlow catch wasn't being hit either.
I was able to resolve the issue, by keeping track of how many times the user clicked the button, if it was more than once, I called paypal.checkout.closeFlow (which will reset) beforepaypal.checkout.initXO();

Related

How to clear caches automatically while refresh a page?

I am building a website using php + jquery.
In a jquery ajax page, I have to clear caches every time by ctrl +F5, otherwise, the buttons of this page can not be clicked.
My thought is refresh this page mandatorily by "window.location.reload(true);" , but I could not clear the caches at the same time!
Is there any Jquery or something can clear the caches automatically after clicking the buttons instead of ctrl +F5?
my codes are below:
...
$("[id = One_Click_Accept]").click(function(){
...
$.ajax({
url: WebsitePath + '/accreditation_check/' + CurAccreditationId,
data: {
accreditation_id: CurAccreditationId,
IsAccredited: 1,
CheckerName:$('#CheckerName').val(),
CheckTime: Math.round(new Date().getTime()/1000).toString(), //it need a 10 digit timestamp to save to the db.
TheCountry : TheCountry,
TheSchool: TheSchool,
TheDegree: TheDegree,
TheMajor: TheMajor,
YearOfGraduation: YearOfGraduation
},
type: "POST",
dataType: 'json',
cache: false,
success: function (Result) {
if (Result.Status == 1) {
alert('认证成功');
} else {
alert('认证失败');
$("#One_Click_Accept").val('再次认证');
}
},
error: function () {
alert('认证失败');
$("#One_Click_Accept").val('再次认证');
}
});
}
//window.location.reload(true);
});
Thank you guys!
I resolved it by using "setTimeout(function()" to delay the load time.
Not only that, I had to use a different selector, It looks like "$(document).on('click',"[id = One_Click_Accept]",function(e) ".

Twitter Typeahead: Suggestion list goes away when ajax fetching result for new keyword

I am using Twitter Typeahead (v0.11.1). I have configured an ajax call to get suggestion list upon typing each letter in textbox.
On entering every character an ajax call gets send and it brings results. If typed continuously in textbox then previous ajax calls are aborted and new ajax call is sent on pause of last character entered.
So, while this process if found some results after two characters and paused then it showing suggestion list. Now, if continue to type then exiting list goes away.
I would like to retain suggestion list for each ajax call till user not selected an item from it.
Below is the code used:
var typeahead_pre_written_xhr = null;
var helper_typeahead = $( "#input-box" ).typeahead({
highlight: true,
minLength: 0
},
{
name: "Search Suggestions",
display: ["title"],
templates: {
empty: function () {
return '<div class="tt-suggestion tt-selectable">No matching helper comment found</div>';
}
},
source: function (query, processSync, processAsync) {
if( typeahead_pre_written_xhr != null ) {
typeahead_pre_written_xhr.abort();
typeahead_pre_written_xhr = null;
}
action_url = "suggestion_list";
return typeahead_pre_written_xhr = $.ajax({ cache: false
, url: action_url + query
, type: 'POST'
, data: { 'search': query }
, dataType: 'json'
, success: function (data)
{
return processAsync(data.res);
}
});
}
}).bind("typeahead:selected", function(evt, item) {
// do some stuff
});

How to reset ckeditor save event

On a previous ajax call I get all articles for a selected Page.
Then I display them and bind this function - on click - to each of them. This is working only one time.
When I want to change a second or third article the article id inside the ajax call keeps holding its first value.
CKEDITOR.replace( 'editor1' );
function editArticle(article){
// id changes for each article as it is supposed to
var id = article.attr('data-id');
var text = article.html();
$('#ckModal').modal();
$('.modal-title').text('Editing Article: '+id+' on Page: '+pageTitle);
CKEDITOR.instances.editor1.setData(text);
CKEDITOR.instances.editor1.resize('100%', '350', true);
CKEDITOR.instances.editor1.on('save', function(e){
e.cancel();
var html = CKEDITOR.instances.editor1.getData();
if(html){
$.ajax({
type: 'POST',
url: '/admin/nodes/edit',
cache: false,
data: {'html' : html,
'articleId' : id }
}).done(function(msg){
// next two lines did not work
//CKEDITOR.instances.editor1.fire('save');
//CKEDITOR.instances.editor1.stop('save');
// id stays the same
console.log(id);
// I echo an 'ok' string when update worked from php
if(msg === 'ok'){
article.html(html);
$('#ckModal').modal('hide');
}else{
//alert(msg);
}
}).fail(function(xhr, status, error){
console.log(JSON.stringify(xhr));
console.log("AJAX error: " + status + ' : ' + error);
});
}
});
}
I had to cancel the save event to get and set Data and perform the ajax call.
But how do I restart or reset the 'save' event - if this is what is causing the problem. I am not so shure anymore ....
Got it working by destroying editor instance in ajax done function and creating a new one after it.
function editArticle(article){
var id = article.attr('data-id');
var text = article.html();
//CKEDITOR.replace( 'editor1' );
$('#ckModal').modal();
$('.modal-title').text('Editing Article: '+id+' on Page: '+pageTitle);
CKEDITOR.instances.editor1.setData(text);
CKEDITOR.instances.editor1.resize('100%', '350', true);
CKEDITOR.instances.editor1.on('save', function(e){
e.cancel();
var html = CKEDITOR.instances.editor1.getData();
if(html){
var title = $('.modal-title').html()
$('.modal-title').prepend(spinner);
$.ajax({
type: 'POST',
url: '/admin/nodes/edit',
cache: false,
data: {'html' : html,
'articleId' : id }
}).done(function(msg){
//console.log(id);
$('.modal-title').html(title);
if(msg === 'ok'){
article.html(html);
$('#ckModal').modal('hide');
CKEDITOR.instances.editor1.destroy();
CKEDITOR.replace( 'editor1' );
}else{
//alert(msg);
}
}).fail(function(xhr, status, error){
console.log(JSON.stringify(xhr));
console.log("AJAX error: " + status + ' : ' + error);
});
}
});
}
You are assigning multiple event listeners on your editor instance 'editor1', one for each article. What happens is when you click save, the first listener (the first article assigned) called cancels all others with e.cancel().
I see you achieved what you wanted by destroying your editor. Doing this removes event listeners, and solves your problem. You could achieve the same with calling e.removeListener() in the handler, this way removing itself after the first run and avoiding the need to recreate the editor. Also note that destroying editors and recreating them is leaking memory (some versions worse than others #13123, #12307), so one should probably avoid doing that if possible.
Both solutions make the save button unusable after a save; of course it will work after another article is chosen for editing. So my suggestion is to remove all previous listeners from your save command before assigning a new one, like this:
// ... in function editArticle ...
CKEDITOR.instances.editor1.resize('100%', '350', true);
CKEDITOR.instances.editor1.getCommand('save').removeAllListeners();
CKEDITOR.instances.editor1.on('save', function(e){
// ...

Called PHP script using EXTJS alert message box

I am currently trying to call the PHP script upon clicking OK button on EXTJS message alert box.
For some reason it doesn't even display the Alert box when I use handler. However when I used Listener it displays the Alert box but doesn't call the php script upon clicking OK button. I read on different blogs and come to know Handler is the best way to go forward
I will appreciate if somebody can help me or point me to the right direction. I am using the latest release of EXTJS4
Below is the EXTJS tree panel code I've written using handler;
var treePanel = Ext.create('Ext.tree.Panel', {
id: 'tree-panel',
title: 'Available Database',
region: 'north',
split: true,
height: 360,
minSize: 150,
rootVisible: false,
autoScroll: true,
store: store,
handler: function() {
if (treePanel.getSelectionModel().hasSelection()) {
var selValue = treePanel.getSelectionModel().getSelection();
Ext.MessageBox.alert('Press OK to confirm your subscription <br>' + selValue[0].data.text,
function(btn, text) {
if (btn == 'ok') {
Ext.Ajax.request({
url: 'addSubscription.php',
params: {
nodetext: text,
parentid: selectedNode[0].data.id
},
success: function(response) {
var id = response.responseText;
grid.getView().refresh();
}
})
} else {
Ext.MessageBox.alert('Record already subscribed');
}
});
}
}
});
Ext.tree.Panel have not 'handler' property in config.
Handler is a function that is executed when you click on some of the components - such as buttons.
You can add button on your treePanel toolbar, and use button handler:
...
tbar: [{
xtype: 'button',
text: 'Subscribe',
handler: function(button) {
...
}
}],
...
See on jsfiddle: http://jsfiddle.net/FFvLa/
but doesn't call the php script upon clicking OK button.
The function must be passed as the third argument in Ext.Msg.alert:
http://jsfiddle.net/FFvLa/2/

jQuery how to make the ajax request "synchronous" when async is true

var tds = ["0", "1", "2", "3", "4", "5", "6"];
for (var i = 0; i < tds.length; i++) {
jQuery("#notification-bar").html('I am doing ' + tds[i]);
jQuery.ajax({
url: "/ajax_json_echo/",
type: "POST",
timeout: 10000,
data: tds[i],
success: function(response) {
},
error: function(x, t, m) {
}
});
} //end for
jQuery("#notification-bar").html("Done!");​
/ajax_json_echo/ might take 10 seconds or even more to deal with tds.
The expected result of notification bar is
I am doing 0
I am doing 1
I am doing 2
...
Done!
The actual result I get is:
Done!
I guess it is caused by the async variable of jquery ajax is being set to true.
If it is set to false, the browser will be frozen. When it recovers, I get "Done!" only.
The browser runs JavaScript and does page rendering all on the same thread, so while JS is running no repaints will occur. This means that your entire for loop will complete and the status message will be set to "Done!" before the page gets updated.
In the case of async being true all of the Ajax requests are queued up initially and the message set to "Done!" and then the responses are processed later asynchronously. In the case of async set to false the Ajax requests are done one at a time with no further action until the response comes in. Either way the browser never gets a chance to display the "I am doing..." messages.
Rather than using a loop you can trigger each subsequent call from within the Ajax complete (or success) callback:
var tds = ["0", "1", "2", "3", "4", "5", "6"];
function doNextAjax(i) {
if (i < tds.length) {
jQuery("#notification-bar").html('I am doing ' + tds[i]);
jQuery.ajax({
url: "/ajax_json_echo/",
type: "POST",
timeout: 10000,
data: tds[i],
success: function(response) {
},
error: function(x, t, m) {
},
complete: function() {
doNextAjax(i + 1);
}
});
} else {
jQuery("#notification-bar").html("Done!");​
}
}
doNextAjax(0);
Each time doNextAjax() is called it updates the status message and makes a single Ajax request and that's all. When the function exits the browser then has a chance to re-render and actually show that message. Then when the complete callback is fired it calls the function again for the next item. When there are no items left it sets the "Done!" message.
Note that using the complete callback to trigger the next Ajax call means that it will keep going even if a particular request fails. If you wanted to stop on error you could get rid of the complete handler and move the doNextAjax(i+1) into the success callback.
Generally this is what you use the success callback parameter to ajax() for - to run a function when the AJAX request completes.
http://api.jquery.com/jQuery.ajax/
If you can use HTML5 elements, use the <progress> element, this is why he's there.
Increase the progress-bar value in the success callback of each ajax request.
var progress = document.getElementById('progress');
progress.max = tds.length;
...
success: function(){
progress.value++;
}
LIVE DEMO
Here's the solution, you should take a look at jQuery deffered object
$.when($.ajax("/page1.php"), $.ajax("/page2.php")).done(function(a1, a2){
/* a1 and a2 are arguments resolved for the
page1 and page2 ajax requests, respectively */
var jqXHR = a1[2]; /* arguments are [ "success", statusText, jqXHR ] */
if ( /Whip It/.test(jqXHR.responseText) ) {
alert("First page has 'Whip It' somewhere.");
}
});
http://api.jquery.com/jQuery.when/
The response you wrote will happen. Change
jQuery("#notification-bar").html('I am doing ' + tds[i]);
jQuery("#notification-bar").html("Done!");​
to
jQuery("#notification-bar").append('I am doing ' + tds[i]);
jQuery("#notification-bar").append("Done!");​
and you will see result. But, behavior is not what you expect. For loop will fire up all AJAX calls, one after another. If you want to fire up next AJAX call only when the last one is finished you should use jQuery Deferred objects to manage this.
I have wrapped up an example here http://jsfiddle.net/DXYZw/2/
var tds = ["0", "1", "2", "3", "4", "5", "6"];
var sendRequest = function(ary, data) {
if (!ary.length) {
// no more calls to be made
jQuery("#notification-bar").append("Done!");
return;
}
jQuery("#notification-bar").append('I am doing ' + tds.length);
dfAJAX(ary)
.done(sendRequest)
.fail(function() {
alert("error");
});
}
var dfAJAX = function(ary) {
var dfd = new jQuery.Deferred();
var dataToSend = ary.pop();
jQuery.ajax({
url: "/ajax_json_echo/",
type: "POST",
timeout: 10000,
data: dataToSend
})
.done(function(data) {
dfd.resolve(ary, data);
})
.fail(function() {
dfd.reject();
})
return dfd.promise();
}
sendRequest(tds);

Categories