I'm trying to learn Google Apps Script, and I just did a bit of an experiment with creating two ".gs files" in the same project, each with an onOpen() function.
After saving, closing, and then opening the document, only one of the onOpen() functions ran (the Sidebar.gs file).
Do these need to be included in the same file? Well, I guess I know that it is a work around. I guess my question is WHY?
Project:
Code.gs:
function onOpen() {
DocumentApp.getUi().createMenu("PACKT").addItem("Greeting","greeting").addToUi();
}
function greeting() {
var ui = DocumentApp.getUi();
ui.alert("Greeting", "Hello World!", ui.ButtonSet.OK);
}
Sidebar.js:
function onOpen() {
var htmlOutput = HtmlService.createHtmlOutput('<button onclick="alert(\'Hello World!\');">Click Me</button>').setTitle("My Sidebar");
DocumentApp.getUi().showSidebar(htmlOutput);
}
Thanks!
You should never have two functions with the same name in the same namespace. It simply doesn't make sense: which of them should be executed when functionName() call happens? (In reality, the function that was last to be defined will be the surviving one; with the rest lost without trace).
In particular, you should not have two onOpen functions within the same project, be it one file or separate (the files share the namespace, meaning that the functions in one file can be called from the other as if they were in the same file).
But your one onOpen() function can simply call whatever functions need to run:
function onOpen() {
doThisThing();
doAnotherThing();
}
Related
I added a prototype function to String in google sheet project, and created a new version to be referenced in another project.
Then I referenced this new library version in another project (Resources-> Libraries in the script editor).
Now I want to use this function, but execution fails as it doesn't recognized this func.
Function definition in project1:
if (!String.prototype.newStringFunc) {
String.prototype.newStringFunc = function() {
Logger.log(this.toString());
};
}
Usage in Project2:
function test()
{
var s = "Hello";
s.newStringFunc();
}
Result:
TypeError: s.newStringFunc is not a function
If the function is defined in Project2 - all good.
Other "regular" functions within Project1, are recognized and executed properly.
Is it not possible to add a prototype function to an external library?
Prototype libraries used to work on old Rhino javascript interpreter.
So, if you turn your Project2 back to old Rhino javascript interpreter for project1, it doenst matter.
It will work again.
Just Go to Menu >> Execute >> Disable Chrome V8.
I don't really know for how long the old interpreter will be available, until then, lets use it.
I have a local copy of the hls.js library and I need to include a personal script with custom functions in it.
How do I go about adding a new script to the library and how do I use the function written in the new script?
Let's say that I want to add a script called hello.js that contains a function that logs "Hello World".
When I call that function in my main.js I need it to execute.
Any ideas on how to do this?
Currently, I'm getting an error that the function is not defined.
I placed the hello.js script in the src folder of the library but this (as expected) doesn't seem to work.
It should be possible to add functions to the exported hls.js object.
Your custom-script.js:
var hls = require('hls.js')
hls.customFunc1 = function () {
}
hls.customFunc2 = function () {
}
on main.js:
require('custom-script')
// your code follows
Any other code would be able to use the custom functions by just require'ing hls.js.
I've got a library (Hubspot Odometer) which I am using in a web application I am developing and it works fine to create and run Odometer style widgets on a page.
The trouble is that they are part of a dashboard interface which has panes that are loaded via AJAX. The initial view is not loaded via AJAX so the JavaScript executes fine and the odometers render correctly.
When I load a new pane with odometers however they are not rendered correctly nor do they act as they should. The reason for this is that the odometer library runs as one big IIFE.
What I am wondering is can I re-invoke the IIFE manually after I load content via AJAX so that the odometers are rendered and bound to correctly?
I am also using jQuery if that offers me any additional options.
Try this:
var funcName = (function funcName() {
// rest of the code
return funcName;
}());
Also see this jsbin.
The whole idea of the IIFE is that its an anonymous function that is immediately executed. So by definition, no there is no way to re-execute it.
With that said however, you can store the function expression to a global variable, and execute it. For example
window.my_iife = (function() { /* stuff */ });
window.my_iife();
Notice the slight difference in syntax compared to the traditional IIFE: ((function() {})());
By storing the function in window, you are able to access it later from either the developer console or anywhere else in your code. If you simply store it in a var, or declare it as function my_iife() { /* ... */ } somewhere you risk that var or function declaration itself being wrapped in an IIFE and thus being inaccessible. As an example, that scenario could occur if the file you declared your var/function in is part of a Sprockets manifest (such as application.js in Rails).
var funcName = null;
(funcName = function funcName() {
// rest of the code
return funcName;
}());
funcName();
This is what worked for me
I'm working on a web application that includes different JavaScript files, depending on where I am in the app. For instance, I have a display.js for each page, each of which has an "init()" function that is called as soon as the page is loaded.
This works well for the webapp, but in my QUnit tests, where all script files are included from a single index.html, functions of the same names override each other.
How are such problems best handled? One test index.html file per page creates lots of boilerplate code and makes it non-trivial to execute all test cases. That's why I decided to name each and every function distinctively, e.g. "initFrontPage()" instead of "init()". This, however, makes the application code a bit weird: Not only do I have to include the right file, I also have to call the right functions in it. Is there a better way?
The solution is to use namespaces:
In foo/display.js:
window.foo = {};
foo.init = function () { ... };
In bar/display.js:
window.bar = {};
bar.init = function () { ... };
Then, in the page that uses bar/display.js's init method:
(function (display) {
display.init();
}(bar));
It would be a good idea to wrap your display.js code in an IIFE as well.
I have problems with calling a JavaScript function (which is inside of an object, in it's own .js file) from an other HTML page. In the code exsample I'll just use a simple Hello World function.
//.js file
window.addEvent('domready',function(){
var Site = {
//Here I have like three other functions
//This function I want to detect the browser version. I use MooTools for this
detectBrowser : function(){
if(Browser.ie){
//Then what ever content goes here
}
}
}
//I execute the other three functions here because they need to be called on every page
Site.dropdownmenu();
Site.accordion();
Site.lightbox();
});
I'm working with MooTools so I have wraped everything inside of the domready function.
Now, I want this cetect function to execute only at one page. I have tried somethink like this:
//In the HTML file between two script tags:
Site.alert();
That does'nt work. Any ideas?
If I execute it in the .js file it works fine. But I don't want it to execute at every page.
If you declare a variable with var in a function, the variable is local to that function and inaccessible from outside that function. To make it explicitly global, declare it as a property of window:
window.addEvent('domready',function(){
window.Site = ...
This isn't necessary for the code to work, it just makes it explicit for programmers that might read your code that Site is a global.
External Javascript files just execute code; the code doesn't know where it's coming from.
As long as your code runs after the external JS file, it will work fine.