google.script.run is broken when used in a shared library [duplicate] - google-apps-script

This question already has answers here:
Call Library function from html with google.script.run
(3 answers)
Server error, google.script.run fails when using a shared library
(3 answers)
Closed last year.
I have the following code.gs
function test() {
Logger.log("Whoo hoo! test() called");
}
function showPopup() {
var html = HtmlService.createTemplateFromFile('index').evaluate().setWidth(400).setHeight(300);
SpreadsheetApp.getUi().showModalDialog(html, 'Click the button');
}
along with this index.html
<div>
<input type='button' onclick='google.script.run.test()' value='Test'>
</div>
These work fine: after running showPopup() I click on the button and the message appears in the logs example.
The problem comes when I add this project as a library to another spreadsheet, using the "Resources->Libraries..." menu item. Let's say I give the library the name "Test", then on the new spreadsheet I run Test.showPopup(), it puts up the popup. But then when I click on the button it does not call the test() function.
Instead, the console on the spreadsheet complains that "undefined is not a function". The problem appears to be that google.script.run.test() does not work when code is shared using the Libraries manager. It wants something like google.script.run.Test.test(), but I tried that and it didn't work either: "Cannot read property 'test' of undefined".
Is there some way I can use google.script.run in a shared (library) script?
or some other way I can re-use my code on other spreadsheets without having to cut-n-paste all the files to each one?
Ah, it looks like someone else reported this as a bug. Shucks. Any workarounds?

I was wondering the same thing. So far haven't seen an real answer on this.
My answer is not the best, but I managed a workaround doing this on the script:
function test() {
Test.test();
}
I'd love to know the real solution for this.

Related

GAS TypeError: SpreadsheetApp.getUI is not a functionDetails

I'm trying to learn some basic google scripting.
I tried reading through this several times, thought about it overnight and searched all over SO and a google for answers and feel like I'm missing something stupid.
When I click the menu item I've added to my gsheet to kick of the sidepage I get this error:
TypeError: SpreadsheetApp.getUI is not a function Details(/link)
If I click that details link I get the same message in a message box:
TypeError: SpreadsheetApp.getUI is not a function
Here's my code:
//#OnlyCurrentDoc
function onOpen() {
SpreadsheetApp
.getUi()
.createMenu("Admin")
.addItem("Admin page", "showAdminSidebar")
.addToUi();
}
function showAdminSidebar(){
var widget = HtmlService.createHtmlOutput("<h1>Sidebar<h1>");
SpreadsheetApp.getUI().showSidebar(widget);
}
I know I must be missing something simple, so thanks for any advice you can give me.
As pointed by #TheMaster above, there is a typo on the method showAdminSidebar().
...SpreadsheetApp.getUI().showSidebar(widget);... where getUI() should be getUi().
See this documentation of methods the class SpreadsheetApp has.
Just tested here and it works just fine after fixing it.

How to determine why an alert dialog was displayed by Chrome?

I am trying to fix a bug in a Chrome extension. When the extension is installed an alert dialog containing the message "undefined" will be displayed seemingly at random. This does not happen when the extension is not installed.
There is not one call to alert, confirm, or prompt in the extension source code. How do I find out why the alert dialog is being displayed?
I have attempted adding the following code to one of the background scripts and to one of the content scripts.
var originalWindowAlert = window.alert;
window.alert = function() {
console.trace();
return originalWindowAlert.apply(window, arguments);
}
I have confirmed that this technique works when used in a webpage, but it is not working for the extension.
I have also built Chromium from source code and I am able to reproduce it but so far I have not been able to figure out how to determine the origin of the alert dialog. I have set a breakpoint in the RenderFrameHostImpl::RunModalAlertDialog function but I see no way to determine what caused the breakpoint to be hit.
I am getting desperate.
I asked this question on the Chromium Extensions Google Group. I got the following very useful response from Scott Fortmann-Roe.
If you do the following in a content script:
var originalWindowAlert = window.alert;
window.alert = function() {
console.trace();
return originalWindowAlert.apply(window, arguments);
}
I don't believe it will actually intercept alerts triggered by the page as you are overriding the content script's window.alert method which is different from the page's method (content script JS is isolated from page JS).
To modify the page's alert method you'll probably need to inject a script tag into the page. E.g. something along these lines in the content script:
let script = document.createElement('script');
script.textContent = `
var originalWindowAlert = window.alert;
window.alert = function() {
console.trace()
return originalWindowAlert.apply(window, arguments);
} `;
document.body.appendChild(script);

Button doesn't work on google spreadsheet

I am working to link an image in my Google Sheet document to a specific cell in another tab. I'm doing this by building a simple function that will do this. However, when I assign the function and then click on the image, I then get the error :
Script function "test" could not be found
When I run the function in the script manager interface, it works fine. It's when I try to actually use it in the sheet with the image.
Function Script :
function test()
{
Browser.msgBox("You clicked it!");
}
It turned out that the document owner had left their job and ownership rights had been moved to someone else. Can it matter ?
The error is : Here
Thank you very much,
Make sure the assigned function name does not include the () brackets. 😎
Did a little snippet just to demonstrate on how you might approach this:
I used the sample from HTML Service: Create and Serve HTML on creating a button (in your case it's image) which responds to a click event. I'm using a bound script.
//in bounds script, this integral function triggers as soon as you open the spreadsheet
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Dialog')
.addItem('Click Me', 'test')
.addToUi();
}
//Then I attached your test function
function test()
{
Browser.msgBox("You clicked it!");
}
And sure enough upon clicking the button, the test function triggered:

create a link that opens a page and runs a function contained in the link

I am still learning PHP so my question may seem a little obvious but...
My question relates to opencart but is probably quite a common practice on many websites. I am creating a opencart module and in that module i have several buttons that complete different tasks. Now I have assigned the button the correct 'href' with the path and appropriate action. eg
$this->data['dosomething'] = $this->url->link('module/modulename/dosomething', 'token=' . $this->session->data['token'], 'SSL');
Note: I have called the module and action a general name for the purposes of my question.
In the controller I then have a private function called 'index', followed by a private function called 'dosomething' like below
public function index() {
* insert code *
}
public function dosomething() {
*insert code*
$this->redirect($this->url->link('module/modulename', 'token=' . $this->session->data['token'], 'SSL'));
}
Now, I would like to know how do I get the button to direct to the module controller and then run the 'dosomething' function. I could put something information in the link, ie action=dosomething and do it this way but most of opencart simply uses the text of the last / as the action. If I use the href stated above I get a error as it is trying to find the controller and template located in 'module/modulename/dosomething' rather than the controller and template located in 'module/modulename' USING the function 'dosomething'.
I hope this makes sense. I see that many other scripts in opencart successfully use this method but I just cant figure out how? I am sure I missing something obvious.
What you are doing is correct. OpenCart's framework will use the third piece of the route if specified as the method. If you try
public function dosomething() {
die('OK');
}
Then go to the url you've got, it should just show a blank white page with OK written on it. My guess is the error doesn't actually relate to the controller being an issue, and more to do with something else you've done. Either that, or the method and the third part of the route aren't a match, or the dosomething method isn't public

Global Variables in Chrome Extensions

Is there a simple way where I can access a global javascript variable through content-scripts in chrome extensions?
Accessing global object from content script in chrome extension
I followed the steps mentioned in the above link, but it did not work out for me. Any help would be much appreciated.
Thanks,
Shankar
I managed to complete it. Thanks for the help. I used simple message passing to retrieve the value from the extension script to the content script. The place where I had missed was, the listener at the extension script needs to be at the background page (I think so). Once I changed that, it worked.
For those from the future looking for an answer to this question, here's how I do it:
function getVariable(v) {
var c = document.createElement("div");
c.id = 'var-data';
c.style.display = 'none';
document.body.appendChild(c);
var s = document.createElement('script');
s.innerHTML = 'document.getElementById("var-data").innerText=JSON.stringify('+v+');';
document.head.appendChild(s);
var data = JSON.parse(c.innerText);
c.remove();
s.remove();
return data;
}
And basic usage:
getVariable('globalVarIWantToAccess');
All this script goes in the content-script, not the code for the main webpage, which means that no co-operation is needed from the webpage itself. Basically, the getVariable function creates a script element which is injected into the main page. This script tag retrieves the requested global variable and puts the data into a new div. The function then gets this data from the new div, deletes the new div, deletes the new script element and returns the data.