Here is my HTML code, from where I call the function loadClient when load button is clicked,
//LOAD CLIENT BUTTON`
document.getElementById("load_button").addEventListener('click',function(){
google.script.run.loadClient();
});
here is the respective function in the code.gs file
//function02-loadClient
function loadClient() {
eval(UrlFetchApp.fetch('https://apis.google.com/js/api.js').getContentText());
return gapi.client.load("https://content.googleapis.com/discovery/v1/apis/webmasters/v3/rest")
.then(function() { Logger.log("GAPI client loaded for API"); },
function() { Logger.log("Error loading GAPI client for API" ); });
}
When you call google.script.run in the client-side environment, you're requesting execution of a server side Apps Script function.
Your implementation of loadClient() doesn't make sense in the context of server-side Apps Script execution.
Here's a full, simple example of successfully triggering a Logger.log() call on the server-side by way of a client side button click:
client.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<script>
function registerListener() {
document.getElementById('callServerFunction').addEventListener('click', function() {
google.script.run
.withSuccessHandler(function() {
alert("Successfully called server function.");
})
.withFailureHandler(function() {
alert("Failed to call server function.");
})
.serverFunction();
});
}
</script>
<body onload="registerListener()">
<button id="callServerFunction">Call Server Side Function</button>
</body>
</html>
Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('client');
}
function serverFunction() {
Logger.log("Server function called.");
}
Server side logging results after the button is clicked
[18-06-10 13:48:20:359 PDT] Server function called.
Regarding the Javascript Google API Client Libraries (i.e. https://apis.google.com/js/api.js), that's not meant to be used in the Apps Script server side context. The whole point of Apps Script is that there is a laundry list of services ready to use immediately without any setup. In addition to not being compatible, trying to load the client-side JS libraries in the server side Apps Script context is simply redundant.
Similarly, trying to use the client-side JS libraries in client-side Apps Script code doesn't make too much sense either, as you have the full set of server-side functionality available via google.script.run.
"trying to load the client-side JS libraries in the server side Apps Script context is simply redundant."
...is not redundant when G. fails to provide/implement/disclose a client-side method unimplemented on the server side; e.g.:
Drive.files.emptyTrash()
https://developers.google.com/drive/api/v2/reference/files/delete?hl=en#javascript
empty trash is simply nowhere to be found among GA Apps Script server-side js calls references urls
https://developers.google.com/apps-script/reference/drive
https://developers.google.com/apps-script/reference/drive#methods
https://developers.google.com/apps-script/advanced/drive
The sought-after capability is NOT THE SAME as file.setTrashed(true) read the necessity as: empty the trash, not 'put a file in the trash', 'mark a file as trashed'; nor is any 'interactive' option viable for e.g. for deleting thousands of files directly or via the trash.
it's impossible with Drive's GAS to permanently delete a file directly
semantics of 'delete' Google admits existence of in Google's Drive client side APIs:
https://developers.google.com/drive/api/v2/reference/files/delete?hl=en
which can't be called from, and for which there is no equivalent, on the server side !
no english phrase I can conceive of adequately captures the implications, otherwise, and economic, of this glaring omission
But perhaps someone can provide the (?undocumented) GAS Apps Script call counterexample
Related
I created a google App engine project locally. Added a simple "Place" API and started the engine. I noticed that the server is waiting on http://localhost:8888/_ah/api base URL.
Now, I want to use the google javascript client API to call my API (I am assuming that is possible). So I created a simple local website and created a simple HTML/javascript page. Then I loaded the google javascript client library and executed.
Here is my page
<html>
<head>
<script>
function load() {
console.log("API client loaded");
var ROOT = 'http://localhost:8888/_ah/api';
gapi.client.load('getPlace', 'v1', function() {
console.log("API called");
}, ROOT);
}
</script>
<script src="https://apis.google.com/js/client.js?onload=load"></script>
</head>
<body>
<div> Hello </div>
</body>
</html>
Now, when I run it, I get a 404 error. Then I checked the URL that the browser places. It looks like this:
http://<local>:8888/_ah/api/discovery/v1/apis/getPlace/v1/rpc?fields=methods%2F*%2Fid&pp=0
A few questions:
What I am doing should work correct ? (local app engine + javascript
library)
What is the expected URL for app engine generated API ? (what is the "discovery" in the URL?)
What is the "rpc" at the end ? I am hoping to create REST API
Here is a link to their API documentation
I would like to practice web programming by creating a bitcoin price ticker from scratch. My plan is to serve a script that makes api calls to exchanges to display the data. This will mean I only have to serve the script, not handle the data server-side.
I know that part of programming is learning from documentation, but the docs from bitfinex are very sparse and I couldn't find a tutorial.
I created an index.html to test my javascript. It returns a console error:
XMLHttpRequest cannot load https://api.bitfinex.com/v1/pubticker/:last_price.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'null' is therefore not allowed access.
Here is the full index.html:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js">
</script>
</head>
<body>
<script>
$.getJSON("https://api.bitfinex.com/v1/pubticker/:last_price",
function(data, status){
alert("price: "+data +" status: " + status);
}
)
</script>
Thank you stack exchange
</body>
You can't — at least, not with Javascript. That API is not configured to allow calls from Javascript running on other web sites. You will need to call this API from a script running on your web server.
(Also, for what it's worth, the :symbol token in the URL is supposed to be replaced with the symbol of the ticker you're trying to look up, e.g. /v1/pubticker/BTCUSD for BTC/USD exchange prices.)
If you run a webserver with SSL on it (as Duskwuff said, "You will need to call this API from a script running on your web server.") then you can deploy the following file to it:
<?php
$func = $_GET['fn'];
if(in_array($func,array('getBfx')))
{
$func();
}
function getBfx()
{
$a = $_GET['api'];
echo "objData = ".file_get_contents($a);
}
?>
Then you can include the script from the URL to which you deployed it, with ?func=getBfx&api=https://api.bitfinex.com/v1{Whatever} tacked onto the end of it. I didn't have to escape that URL, but you might.
i am trying to write my first firefox add-on. the main problem seem s to be that i am also new to javascript. at the moment i have:
require('sdk/page-mod').PageMod({
include: ["*"],
contentScript: 'window.addEventListener("click", function(e) { alert("blub"); }, false);',
attachTo: ["existing", "top"]
});
(thx to the answer here.)
now i want to use a declared function instead of an anonymous one, but i cant get it to work:
require('sdk/page-mod').PageMod({
include: ["*"],
contentScript: 'window.addEventListener("click", function(e) { alert("blub"); }, false);',
attachTo: ["existing", "top"]
});
getImgData function (e) {
alert("blubber3");
}
the first problem is i get syntax error by just adding the function "missing ; before statement". But cfx doesn't tell me the wrong line. (Is there any useful tool for js editing with good syntax check/ content assist?)
So how to declare a function and use ist somewhere else in the script. At the end the function needs to get the target of click and parse it.
(i read the tutorials but thy all use anonymous functions :-P)
thx in advance
It's important to realize the separation between chrome scripts and content scripts. Chrome scripts are those that run with the same security privileges as Firefox - they have full access to Firefox and your computer. Content scripts are those that run with the same privileges as web pages. They can mess around with that web page, but are severely restricted otherwise. To maintain security, the way these two types of scripts can communicate is limited. You wouldn't want a web page to be able to call any function it wants in your extension's internal code!
Your main JS file (the one that includes require('sdk/page-mod')) is a chrome script. What you're injecting (contentScript) is (obviously) a content script. They can't communicate through a direct function call as you're doing.
If your getImgData function is something that can be done with normal web page privileges, you can move your definition of it to within the content script. If it requires additional privileges, you must have your content script communicate with your chrome script via the emit and on functions as described in the link above.
If you are going to make your content script any longer, I would recommend you separate it into its own file to make your life easier.
I am trying to access a page method from centralized module.
I tried putting it in a master page it didn't work
I tried putting it in a web service and did the following
added its path to the script manager that its existed in the master page
added a web service reference to the project
configured the web.config for the page methods
Also didn't work (kept telling me that "PageMethods is not defined" <- JavaScript error)
tried to access the page methods through http request from Javascript, got server error response (500)
What am I missing?
I followed example #2 at this link and it worked fine (the samples appear to be broken however): http://www.asp.net/Ajax/Documentation/Live/tutorials/ExposingWebServicesToAJAXTutorial.aspx
Here are the steps I took:
1) create a basic .asmx web service with 'HelloWorld' method
2) add the attribute [ScriptService] to the 'HelloWorld' method (and any methods in the web service that you want to call from your page script)
3) add a ScriptManager to the page, referencing the web service, and including InlineScript="true"
4) call the page from Javascript like this:
ServiceNamespace.ServiceClass.Method(parameters, callback);
function callback(result)
{
alert(result);
}
The fact that you're getting a 500 error tells me that there's an error in your web service. I would start here: can you open your web service URL in a browser successfully, and invoke its methods?
I have been reading up on HTML 5 worker threads but all the samples i have seen seem to require the javascript be in its own file.
so im basicly wondering if its posible to start a worker work directly towards a function.
The end goal here being something along the lines of:
function AllJavascriptIsLoaded()
{
if(gWorkersSupported)
{
var Worker = new Worker(MyFunc)
Worker.Start();
}
else
{
// Horrible user experience incomming.
MyFunc();
}
}
function MyFunc()
{
// Complex and time consuming tasks
}
To my knowledge, this is not allowed for security reasons. I'd assume that a child object, or any JS script in the same file, would potentially have access to the parent DOM window, which Web Workers are not allowed to access.
So, we're stuck with posting messages to other files unless someone finds a nicer way to do it ;)
You can use something called inline-worker.
Basically you create a script resource via dataURI or BlobURL for the worker script. Given that the content of the script can be generated, you can use Function.toString() to build the content of the worker.
Example use BlobURL: http://www.html5rocks.com/en/tutorials/workers/basics/
Example use both technique: https://github.com/jussi-kalliokoski/sink.js/blob/master/src/core/inline-worker.js
Jeffrey is right about the security restriction of WebWorker. The code running in the worker cannot access the DOM, so it should only be used for calculation heavy tasks. If you try to access the DOM inside worker's code it would raise an error.
vkThread plugin helps you to implement exactly what you requested.
take a look at http://www.eslinstructor.net/vkthread/
there are examples for different kind of functions: regular function, function with context, with dependencies, anonymous, lambda.