JSONP callback issue - html

I'm trying to get JSONP working with a server running on an Arduino.
This is my JS code:
window.onload = init;
function init()
{
//alert("Test");
SendRequest();
}
function SendRequest()
{
alert("Sending request");
var url = "http://192.168.1.177";
var request = new XMLHttpRequest();
request.open("GET", url);
request.error = function(e) {
alert("ERROR");
};
request.send(null);
}
function ArduinoJSONP()
{
alert("Callback received!!!");
}
The callback function is never reached.
But if I just direct my browser directly to the Arduino IP I see the following displayed in the browser:
ArduinoJSONP({"data": 12345})
So it seems the server is sending the response with correct JSONP format but somehow the function is not invoked. Is there anything else I need to for JS to call the function? I even tried moving the function to the HTML body but it didn't help either.
Thank you.

You are not handling server response at all. If you doing it without any libraries you need to eval result that was returned by the server.
And actually JSONP implementation is not XHR, you have to inject it as a script tag into html with correct src attribute.
Just use a library that already have all this logic abstracted for you.
Simply inject script tag into HTML tree:
function SendRequest()
{
var element = document.createElement('script');
var s = document.getElementsByTagName('script')[0];
element.type = 'text/javascript';
element.async = true;
element.src = 'http://192.168.1.177';
s.parentNode.insertBefore(element, s);
}
You can mark it with unique id. Hookup to onload event and once executed remove that script.

Related

Is this possible to send and get back the value from google app script to html page without rendering html output?

After much discussion and R&D, image cropping is not possible with Google APP scripts. So I decided to try one using the Canvas API.
I am trying to pass the value from server script(.gs) to the HTML file and get back the value in the server side script without opening HTML output as in sidebar or model/modelLess dialog box. You can say silently call HTML, complete the process and return the value to server script method.
I tried but getFromFileArg() is not running when i am running the callToHtml().
Is this possible with below script? what you will suggest?
Server side (.gs)
function callToHtml() {
var ui = SlidesApp.getUi();
var htmlTemp = HtmlService.createTemplateFromFile('crop_img');
htmlTemp["data"] = pageElements.asImage().getBlob();
var htmlOutput = htmlTemp.evaluate();
}
function getFromFileArg(data) {
Logger.log(data);
}
crop_img.html template :
<script>
var data = <?= data ?>;
//call the server script method
google.script.run
.withSuccessHandler(
function(result, element) {
element.disabled = false;
})
.withFailureHandler(
function(msg, element) {
console.log(msg);
element.disabled = false;
})
.withUserObject(this)
.getFromFileArg(data);
</script>
You cannot "silently" call the HTML this way, no.
The HTML needs to go to the user and the user is not inside of your web app, but Google's web app (Slides), so you have to play by their rules.
You need to use one of the available UI methods such as showSidebar. You could have the displayed HTML be a spinner or message like "processing..." while the JavaScript runs.
function callToHtml() {
var ui = SlidesApp.getUi();
var htmlTemp = HtmlService.createTemplateFromFile('crop_img');
htmlTemp["data"] = pageElements.asImage().getBlob();
ui.showSidebar(htmlTemp.evaluate());
}

Node.js return html as a variable

I'm setting up a web scraper using Node.js and want to grab some html from a url and save it as a variable. A stripped down version follows.
var request = require('request');
var get_html = function(){
var url = "http://www.google.com";
var html = '';
request.get(url,function(error, response, body){
html += body;
});
return html;
};
console.log(get_html());
It seems that the function returns before request can concatenate the html to the variable html. As far as I can see, request only allows me to manipulate the html within the callback function or pipe it to a file. Is there anyway to just return it as a variable?
request.get is asynchronous and it will return result in the callback function.
You need to adapt your code a little bit like this
var request = require('request');
// get_html receive callback to process result
var get_html = function(callback) {
var url = "http://www.google.com";
var html = '';
request.get(url,function(error, response, body){
return callback(body); // call callback and parse result to it
});
};
// call get_html function
// and log html result here
get_html(function (body) { console.log(body); });
Code with a lot of function callbacks looks not beautiful.
I prefer promise than callback.
If you wish to use promise, try 'request-promise' lib.
It appears that request.get is async, so you have to put return html; in the callback. Otherwise it's returning instantly, before request.get can finish running.

Send a message from client to server

I have a server I wrote in NodeJs which listens to port 1234.
From my client (html) I want to send request to my server and wait for an answer.
I tried to use XMLHttpRequest:
var http = new XMLHttpRequest();
var url = "127.0.0.1:1234";
var params = "token=22";
http.open("post", url, true);//"https://www.google.com/search?q=asd"
http.setRequestHeader("Content-type", "text/html");
http.setRequestHeader("Content-length", 0);
http.setRequestHeader("Connection", "keep-alive");
http.onreadystatechange = function() {//Call a function when the state changes.
alert(http.responseText);
}
http.ontimeout = function()
{
alert("timeout");
}
http.timeout=10;
try
{
http.send(null);
}
catch(ex)
{
alert(ex);
}
But I always got exception. The reason was I can't use my own port.
Is There any other way to send request and get respond?
There is nothing wrong with using JQuery.ajax to make your life easier and it does get a lot easier with jquery especially when it comes to XMLHttpRequest.

Sending message from popup.js in Chrome extension to background.js

What is the proper way to send a message (and get a response) to background.js from popup.js in a Chrome extension? Every method I try ends up with an error that:
"Port: Could not establish connection. Receiving end does not exist."
I would prefer to use chrome.extension.sendMessage() over chrome.extension.connect() with port.postMessage(), but neither method seems to have worked.
What I am trying to do is wire a button in the popup.html to call into some javascript in popup.js which calls back to background.js in an effort to get info about the currentTab() that was topMost (ie:to get the current URL string to show in the popup.html)
Right now in popup.js (wired to the action of the button) I have:
function getURL()
{
chrome.extension.sendMessage({greeting: "GetURL"},
function(response) { tabURL = response.navURL });
$("#tabURL").text(tabURL);
}
In background.js I have:
chrome.extension.onMessage.addListener( function(request,sender,sendResponse)
{
if( request.greeting == "GetURL" )
{
var tabURL = "Not set yet";
chrome.tabs.getCurrent(function(tab){
tabURL = tab.url;
});
sendResponse( {navURL:tabURL} );
}
}
Any ideas?
Just to clarify, we talking about communication between popup page from browserAction and background script?
Anyway you have quite a few errors in your code.
First your totally ignore the fact that all callbacks in chrome api are asynchronous.
In background page
var tabURL = "Not set yet";
chrome.tabs.getCurrent(function(tab){
tabURL = tab.url;
}); //this will be invoked somewhere in the future
sendResponse( {navURL:tabURL} );
//navUrl will be always Not set yet because callback of getCurrent hasn't been called yet
Same in popup.js
chrome.runtime.sendMessage({greeting: "GetURL"},
function(response) { tabURL = response.navURL });//callback will be invoked somewhere in the future
$("#tabURL").text(tabURL)//tabURL will display something totally different from what you have been expected
Second error is that chrome.tabs.getCurrent doesn't give you the current tab selected by user in main window. The docs says:
Gets the tab that this script call is being made from. May be
undefined if called from a non-tab context (for example: a background
page or popup view).
So you will get undefined for all of your requests, because you call it in background page. What you need to do is to use method chrome.tabs.query to obtain currently active tabs.
So after fixing all problems new code should look something like this:
background.js
chrome.runtime.onMessage.addListener( function(request,sender,sendResponse)
{
if( request.greeting === "GetURL" )
{
var tabURL = "Not set yet";
chrome.tabs.query({active:true},function(tabs){
if(tabs.length === 0) {
sendResponse({});
return;
}
tabURL = tabs[0].url;
sendResponse( {navURL:tabURL} );
});
}
}
popup.js
function getURL() {
chrome.runtime.sendMessage({greeting: "GetURL"},
function (response) {
tabURL = response.navURL;
$("#tabURL").text(tabURL);
});
}

Google Maps API Async Loading

I am loading the Google Maps API script Asynchronously in IE9 using the following code:
function initialize() {
...
}
function loadScript() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&sensor=TRUE_OR_FALSE&callback=initialize";
document.body.appendChild(script);
}
window.onload = loadScript;
Now the thing is that when the script is fully loaded the initialize() function is called automatically. But when sometimes the user quota has been exceeded the initialize() function is not called and instead of map we see the plain white screen.
I want to detect this and fire my custom function which displays some alert like: "Error!".
Can anyone tell me to how to do this?
Thanks in advance...
As Andrew mentioned, there isn't a direct way to handle this. However, you can at least account for the possibility.
Set a timeout for a reasonable time frame (5 secondes?). In the timeout callback function, test for the existence of google and/or google.maps. If it doesn't exist, assume the script load failed.
setTimeout(function() {
if(!window.google || !window.google.maps) {
//handle script not loaded
}
}), 5000);
// Maps api asynchronous load code here.
I finally found the solution for this problem. Chad gave a nice solution but the only thing is that you can't put that piece of code in the callback() function because if the script fails to load the callback() function is never called!
So based on what Chad has mentioned I finally came up with the following solution:
function initialize() {
...
}
function loadScript() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&sensor=TRUE_OR_FALSE&callback=initialize";
setTimeout(function () {
try{
if (!google || !google.maps) {
//This will Throw the error if 'google' is not defined
}
}
catch (e) {
//You can write the code for error handling here
//Something like alert('Ah...Error Occurred!');
}
}, 5000);
document.body.appendChild(script);
}
window.onload = loadScript;
This seems to work fine for me! :)