Javascript scope issue with opensocial payment API - javascript

I have a strange issue and I have been stuck for hours now. I am working on porting somebody's game to a social platform called Mixi. Now, there is a button inside the game which triggers a Javascript function with four parameters. (the game passes the values for these while calling.)
Now, I have written definition for this function calling the Mixi API for payment and if I call this function from anywhere within my file, the window/widget shows up. But, when it gets called from within the game, something messes up and it just crashes.
I have checked Console and it seems that something is wrong with the context or scope. If I put an alert in the same function, it gets called perfectly fine from within the game. But, since it is an API call and depends on objects from other JS files, included before this file in the Mixi application, I think opensocial.requestPayment malfunctions since context changes when function is called from within the game.
Same thing is observed for functionality like Inviting friends. A call from within the .js or another .js in the same application works fine but from within the game API call does not work, and the Network monitor in Firebug shows "rpc.json" something as the last thing. The same thing also comes when the function is called manually, but is immediately followed by something win_create.pl from the server of Mixi and shows up the dialog.
Code for the functions seems to be fine, since it works perfectly when called from this container web application. But from within the game, only the alerts come (means function is called) but API is not called correctly.
I have tried doing this:
var that = this; // outside the function
function sendPaymentRequest(itemName, amount etc.){
that.opensocial.sendPaymentRequest... // works only if called from within this application
}
But this makes no difference, either.
I am sorry if this sounds confusing, as I didn't know how to explain this in a nutshell. If you need any further information, please let me know.
Update: Code Snippets:
The following function is used for calling opensocial's payment request:
function sendPaymentRequest(id, price, count, name, imageUrl) {
var itemId = id;
var amount = price * count;
var itemName = name;
$.post(
"http://url.com/payment.php",
{"item_id":itemId, "item_price":amount, "item_name":itemName },
function(data){
var responseJSON = JSON.parse(data);
//alert("Signature Fetched: "+ responseJSON.signature); -- this works
var params = {};
params[opensocial.Payment.Field.AMOUNT] = amount;
params[mixi.Payment.Field.ITEM_NAME] = "diamond";
params[mixi.Payment.Field.SIGNATURE] = responseJSON.signature;
params[mixi.Payment.Field.ITEM_ID] = id;
params[mixi.Payment.Field.IS_TEST] = 'true';
params[mixi.Payment.Field.INVENTORY_CODE] = 123;
params[opensocial.Payment.Field.PAYMENT_TYPE] = opensocial.Payment.PaymentType.PAYMENT;
var payment = opensocial.newPayment(params);
//alert("Just before opensocial request payment" + opensocial.requestPayment); -- works even when called from game
console.log(payment);
opensocial.requestPayment(
payment,
"http://url.com/payment-callback.php",
function(response){
var data;
var code;
var msg;
if (response.hadError()){
code = response.getErrorCode();
msg = response.getErrorMessage();
alert('code=' + code + ' msg=' + msg);
}else{
data = response.getData();
// alert('ok. itemNmae=' + data.fields_.itemName);
}
}
);
});
}
This specific function is being called from within the game. But, the window for payment which this method is supposed to open doesn't show. However, if the same call to opensocial.requestPayment is made from anywhere within the javascript file from a global scope, it shows instantly.

Related

Returning empty string on a input that has a value

I have a date input in my page, which I'm using Daterangepicker framework to populate it.
Here is the code of how I start my page!
$(function(){
startSelectors();
var variaveis = returnInputVars();
var rede = variaveis[0];
var codLoja = variaveis[1];
var period = variaveis[2];
console.log('1.'+rede+' 2.'+codLoja+' 3.'+period);
});
function returnInputVars(){
var rede = $("#dropdown-parceria").val();
var codLoja = $("#dropdown-loja").val();
var periodo = $("#datepicker-range").val();
return [rede, codLoja, periodo];
};
The function startSelectors() is set to start my datepicker and other fields, which is working perfectly. After it, I create a var called "variaveis" to fill
with the values of each field because I will use then later (this functions also works perfectly at other scripts of my page).
Running the page, my console returns this:
The funny thing is, if I type at the console this, the value is shown, just while starting the script is does not work!
Anybody experienced something like this?
***UPDATE
Adding this script to my start function:
console.log($("#datepicker-range"));
The value is shown, but the second console.log don't:
EDIT 1. FIDDLE (Suggested by #halleron)
To ensure things are loaded in the correct order, it is useful to apply a page sniffer code snippet that will scan the page continuously until a condition is met, or until a preset counter limit is reached (to prevent strain on browser memory). Below is an example of what I typically use that would fit your scenario.
I think because you are dealing with asynchronous loading, you can't have a global variable that holds the values in a global scope without an interval to detect when it can be used. Otherwise, it will attempt to read the variable when it is not yet ready.
You can invoke functions anywhere you like. But I would keep all of your variables contained within the page_sniffer_2017() because that is a controlled environment where you know that everything successfully loaded and you know that the variables are ready to be accessed without error.
That way, regardless of connection speed, your functions will only fire when ready and your code will flow, sequentially, in the right order.
Within the ajax success options, always add a class to the body of the document that you can search on to determine if it has finished loading.
$(document).ready(function() {
page_sniffer_2017();
});
function page_sniffer_2017() {
var counter = 0;
var imgScanner = setInterval(function() {
if ($("#datepicker-range").length > 0 && $("#datepicker-range").val().length && jQuery('body').hasClass('date-picker-successfully-generated')) {
var periodoDatepicker = $("#datepicker-range").val(); // ok
console.log(periodoDatepicker); // ok
var variaveis = returnInputVars(replaceDate(periodoDatepicker)); // ok
console.log(variaveis[0], variaveis[1], variaveis[2]);
//startNewSelectors(variaveis);
// start ajax call
generateData(variaveis[0], variaveis[1], variaveis[2]);
clearInterval(imgScanner);
} else {
//var doNothing = "";
counter++;
if (counter === 100) {
console.log(counter);
clearInterval(imgScanner);
}
}
}, 50);
}

How to use the Firebase real time database for web application

In my website I'm Showing my database after user has given the database name, Is there any way I can constantly update the web shown databasebase without refreshing the page . I've tried using setInterval but it's not working for some reason .
function c(){
setInterval(beta, 1000);
}
function beta(){
var d = document.getElementById("opopo").value;
var firebaseRefff= firebase.database().ref('LOCATION/'+d);
firebaseRefff.on('child_added', snap=> {
var slot=snap.getKey();
var alloted=snap.child("ALLOTED").val();
var date=snap.child("DATE").val();
var limit=snap.child("LIMIT").val();
var time=snap.child("TIME").val();
$("table tbody").append(""+slot+""+alloted+""+date+""+limit+""+time+"Null");
});
}
You do not need, and should not use, setInterval to trigger the queries. What you have in your beta() function looks pretty good.
firebaseRefff.on('child_added', snap => {}) means "whenever a child is added under this location, trigger the callback function (empty in my example) with the parameter 'snap'". It will also be called once, initially, for each child that is already at that database reference location.
You need to make sure you've called beta() once to setup this trigger.
If you're still having problems, you might want to insert logging to make sure beta() is being called, what the full reference path is, if the callback is ever triggered, and if your jquery string is correct.

I am stuck getting a JSON return from the Linkedin API

I am using the RESTFUL API request. Here is my code:
$(document).ready(function(){
var LinkedinAuth = "https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=75rsv9vpa1ixv3&redirect_uri=https%3A%2F%2Fmattobra.github.io/page.html&state=987654321&scope=r_basicprofile"
$(button).click(function(){
LinkedinAuth
})
var start = function(){$.getJSON("https://api.linkedin.com/v1/people/~:(id,first-name,skills,educations,languages,twitter-accounts)?format=json", function(data){console.log(data)})
}
I have the user log in. And then it brings them to the next page. however, the json never gets returned.
I don't see you calling the start() function anywhere in your code. You only declare it. I think you should put it inside the button click function.

How to run a long script and send constant feedback to an html dialog

In a Google Spreadsheet, I have a long script that permorms many actions in steps, like:
function MyLongScript()
{
var Results1 = Action1();
//send feedback 1
var Results2 = Action2(Results1);
//send feedback 2
var Results3 = Action3(Results2);
//send feedback 3
//end code
}
And I want to show the users a dialog box that tells them that script is running and updates each step of the scritp, like "Action1 complete", ..., "Action2 complete" and so on.
So, I have the HTML interface which contains some table rows with these steps. The question is: how do I make the dialog see that the code performed a certain step?
Right now I'm trying to start the code from the dialog after it loads:
$(function() {
google.script.run
.withSuccessHandler(MainCodeSuccess)
.withFailureHandler(MainCodeFailure)
.MyLongScript();
}
And the dialog is called with the UI and HtmlService:
function CallDialog()
{
var ui = HtmlService.createTemplateFromFile('FeedbackWindow')
.evaluate()
.setWidth(300)
.setHeight(500);
SpreadsheetApp.getUi().showModalDialog(ui, "Dialog Title");
}
What I need is either a getStatus() in the dialog scritp or a sendStatus() in the server script.
What is the best way of achieving this?
You can run multiple google.script.run calls to the server simultaneously. You can't have one server call send multiple success calls back. You could have your MyLongScript() run, save progress status somewhere, and just keep that running, then have a second google.script.run executing on a loop every certain time period. You can use a JavaScript setInterval(): window.setInterval("javascript function", milliseconds); I don't think that there is a jQuery equivalent.
So it might (roughly) look like this:
$(function() {
google.script.run
.withSuccessHandler(MainCodeSuccess)
.withFailureHandler(MainCodeFailure)
.MyLongScript();
window.setInterval("statusChecker()", milliseconds);
}
window.statusChecker = function() {
google.script.run
.withSuccessHandler(statusCheckSuccess)
.withFailureHandler(onFailure)
.StatuChecker();
};
window.statusCheckSuccess = function(returnStatus) {
if (returnStatus !== false) {
//To Do - show msg to user
document.getElementById('idMsgToUser').textContent = returnStatus;
};
};
Your MyLongScript() might need to be saving the state of the current status to a file. I'm not sure if the subsequent, and simultaneous google.script.run calls wipes out the data in a global variable. If a global variable would hold the data even with all the simultaneous server scripts running, you could save the current status to a global variable. You'd need to experiment with that, or maybe someone knows the answer to that question.

copying data from one page to another using phantomJS

I am trying to copy some data from one processed web page into a new one that I want to export. The background is that I need to scrape parts of a page and need to build a new page with parts of the original page.
The problem seems that phantomJs includeJs() and evaluate() methods are sandboxed and I can't see a proper way to import DOM from one page to another.
I have some test code that looks like this, with page being the original and out the new page:
....
var title = page.evaluate(function() {
return title = document.getElementById('fooo').innerHTML;
});
console.log('page title:' + title);
//fs.write('c:/Temp/title.js', "var title = '" + title + "';", 'w');
var out = new WebPage;
out.viewportSize = page.viewportSize;
out.content = '<html><head></head><body><div id="wrapper"></div><p>done</p></body></html>';
out.includeJs('c:/Temp/title.js', function() {
var p = document.createElement('p');
p.appendChild(document.createTextNode(title));
document.getElementById('wrapper').appendChild(p);
});
...
The function in your last includeJs call here won't work - as you note, it's sandboxed, and that means that closures won't work, so title won't be defined. A method of passing variables to page.evaluate is noted as a feature request, but isn't available as of PhantomJS v.1.4.1.
The general way I get around this is by using the Function constructor, which allows you to create a function using a string:
var myVar = {some:"values", I:"want to pass into my page"},
test = new Function("window.myVar = " + JSON.stringify(myVar));
page.evaluate(test);
Now you can evaluate a function like the one you have, referencing myVar in the sandbox, and your data will be available in the client scope.

Categories