How to call a function that is inside another function javascript - javascript

I have two files as below:
trycapture.js (which has) trycapture() (which has) drawaggregate() definition
main.js from which I want to call drawaggregate();
trycapture.js
trycapture(){
... some code
function drawaggregate(){
... definition
}
}
main.js
.. some variables
var try_obj = new trycapture();
try_obj.drawAggregate(emit_x1,emit_y1,emit_x2,emit_y2);
HTML
<head>
<script src="trycapture.js"></script>
<script src="js/main.js"></script>
</head>
How can I call that function. I tried creating an object right before calling drawaggregation() such as above:
I still get the error:
TypeError:try_obj.drawaggregate is not a function
Also, in index.html I made sure that I include trycapture.js before main.js How can I call that function?

Add
this.drawaggregate = drawaggregate;
after your function definition to make it a public method of the trycapture object.
Overall, you will change your trycapture.js to the following:
function trycapture(){
... some code
// Locally accessible only
function drawaggregate(){
... definition
}
this.drawaggregate = drawaggregate; // Makes it publicly accessible also
}
the drawaggregate() method can then be called like so:
var try_obj = new trycapture();
try_obj.drawaggregate();

Related

Call Library function from html with google.script.run

I implement library with Google App Script and I have some difficulties to call a function from library using google.script.run.
Here is the code of my Library :
Code.gs
function ShowSideBar() {
var html = HtmlService.createTemplateFromFile('Index_librairie').evaluate()
.setTitle('Console de gestion')
.setWidth(300);
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.showSidebar(html);
}
function execution_appeler_par_html(){
Logger.log("execution_appeler_par_html");
}
Index_librairie.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
google.script.run.withSuccessHandler(work_off).execution_appeler_par_html();
function work_off(e){
alert(e);
}
</script>
</head>
<body>
test de ouf
</body>
</html>
Here is my Spreadsheet that use the Library :
Code.gs
function onopen() {
lbrairietestedouard.ShowSideBar();
}
Google.script.run does not reconize execution_appeler_par_html() function.
I should use libraryname.execution_appeler_par_html() but this syntaxe doesn't work in configuration of google.script.run
It seems that google.script.run can't look inside Objects or self-executing anonymous functions. In my case, putting any code inside an object or IIFE resulted in "is not a function" type of error being thrown in the console.
You can work around this by declaring a single function that will call nested methods inside libraries and objects.
.GS file
function callLibraryFunction(func, args){
var arr = func.split(".");
var libName = arr[0];
var libFunc = arr[1];
args = args || [];
return this[libName][libFunc].apply(this, args);
}
In JavaScript, every object behaves like an associative array of key-value pairs, including the global object that 'this' would be pointing to in this scenario. Although both 'libName' and 'libFunc' are of String type, we can still reference them inside the global object by using the above syntax. apply() simply calls the function on 'this', making the result available in global scope.
Here's how you call the library function from the client:
google.script.run.callLibraryFunction("Library.libraryFunction", [5, 3]);
I don't claim this solution as my own - this is something I saw at Bruce McPherson's website a while back. You could come up with other ad-hoc solutions that may be more appropriate for your case, but I think this one is the most universal.
Noticed the same problem trying to invoque library from google.script.run within HTML code.
Here is the workaround I use :
LIBRARY SIDE : aLibrary
function aFunction(){
//code...;
}
ADDON SIDE (requires library "aLibrary")
function aFunction(){
aLibrary.aFunction();
}
HTML
<input type="button" value="run aFunction" onclick="google.script.run.aFunction()" />
I like the workaround because I keep a clear view and organisation of my functions names, and do not need to alter HTML code if I bring my functions directly inside the addOn project, once development is satsifying.
Only thing I did not try yet : handling arguments and return values....
I hope this contribution is not to foolish, please forgive me I am very amateur...
After quite long time working on this, I found out that any function that you call from the library using google.script.run must exist in both the main script and the library script. The function must at least be declared in the main script while the implementation as well as the parameters are not important. The implementation will be in your library. If the main script does not include the name of the function, the error <your function> is not a function will appear.
Now that there is no meaning of having a library if every single function needs to exist in the main function, the solution provided by #Anton Dementiev would be used as a workaround. Suppose you have a function named testFunc in your library, you can call it using the following method:
google.script.run.callLibraryFunction("testFunc", [5, 3]);
where the library has this function:
function callLibraryFunction(func, args) {
args = args || [];
return this[func].apply(this, args);
}
and the main script has this declaration:
function callLibraryFunction() {
}
Google must fix this stupid behaviour

How to call a static JS function defined in other javascript file

I am using Meteor JS.
I have a JavaScript function defined in file A which I want to reuse by calling from file B. Example:
File A:
function Storeclass(){}
Storeclass.validate=function(){...}
From A JavaScript I try to call StoreClass.validateBasic() it works but the same call doesn't work from B. Also I tried in B doing var storeClassObj=new StoreClass(); and storeClassObj.validate(). I get error ReferenceError: StoreClass is not defined.
Read this doc about namespacing in Meteor.
The relevant portion is this:
// File Scope. This variable will be visible only inside this
// one file. Other files in this app or package won't see it.
var alicePerson = {name: "alice"};
// Package Scope. This variable is visible to every file inside
// of this package or app. The difference is that 'var' is
// omitted.
bobPerson = {name: "bob"};
However, later on in the same doc, it says this:
When declaring functions, keep in mind that function x () {} is just shorthand for var x = function x () {} in JavaScript.
This suggests that the function you have written is private to the file A and cannot be accessed from file B, even if load order is correct!
Because your function in file B might invoke before File A is ready so you have to make sure that all required js files are loaded successfully.
If you are using jQuery then in file B call your function in document ready function:
$( document ).ready(function() {
//File A code
});
or in plain JavaScript:
(function() {
// your page initialization code here
// file A code
})();

How to split jquery source code into multiple files when using the module pattern?

I've got some problems splitting up my jquery source code into more than one file. My real source code is a bit more complicated but the following simple example shows my problem very good. At first I would like to show you a working example with only one javascript file. Afterwards, I will describe what I tried in order to split the javascript into two files.
My html code looks like this ("./jquery" is a symbolic link to my local jquery download):
<html>
<head>
<script src="./jquery"></script>
<script src="./file1.js"></script>
</head>
<body>
<div id="content"></div>
</body>
</html>
The jquery source code in file1.js looks like this:
$(document).ready(function() {
var Test = (function() {
var content = $('#content');
var init = function() {
content.html('<p>test</p>');
};
return {
init: init
}
})();
Test.init();
});
After opening the page, "test" is displayed so that this example works as expected.
But now I want to put the whole Test part into another file file2.js. My html is basically the same but gets an additional line:
<script src="./file2.js"></script>
file1.js now contains only the call of the init function:
$(document).ready(function() {
Test.init();
});
and file2.js contains the definition of Test:
var Test = (function() {
var content = $('#content');
var init = function() {
content.html('<p>test</p>');
};
return {
init: init
}
})();
When I open the page, "test" is not displayed any more. In order to make sure that the init function is called at all, I added a console.log("test"); to the init function which is working fine. Therefore, I suppose that the function might be called before the DOM is ready, but actually I am pretty clueless. Maybe someone can give me a hint how to make that run.
Best regards and thanks in advance!
You can do several things according to your preferences...
1. Move your scripts to the end of the HTML file intead than in header...
<html>
<head>
</head>
<body>
<div id="content"></div>
</body>
<script src="./jquery"></script>
<script src="./file2.js"></script>
<script src="./file1.js"></script>
</html>
Think this problem secuencially... if you don't want to declare a var in each module referring an element in your DOM you need that the element exists first, then you can declare the "global" var to the module content. This way your original file2.js works.
Another way is to declare the content "global" to your module but init this in your init function...
var Test = (function() {
var content;
var init = function() {
content = $('#content');
content.html('<p>test</p>');
};
return {
init: init
}
})();
Now you can use the content variable in all of your module's functions.
Hope this helps, let me know.
file1 depends on file2. Make sure file1 comes ordinally after file2 in your html.
AngularJS offers dependency injection, modules, services, factories and all sorts of other goodness. Takes a bit to get used to, but well worth it IMO: much cleaner abstraction of javascript from DOM, data from presentation etc.
I appreciate your question is JQuery specific, but especially if you're starting a new site, I suggest you give Angular a try.
Modify your file2.js as follows:
var Test = {
content : $('#content'),
init : function() {
Test.content.html('<p>test</p>');
}
//, include other functions here
};
Modify your file1.js as follows:
$(document).ready(function(){
Test.init();
})
Now declare file2.js before your declare file1.js because file1.js is referencing a function from file2.js .

Global javascript object not defined error?

I don't know if this is too localized or not but I don't have much code. The problem I am having is an object being declared in a global js file named System.js called budgetModel which holds data for the entire web app is showing as undefined.
I created a class like object called BudgetModel in js within the System.js file and when a user logs in the website directs them to a page called index.php which onload executes two methods called setupSystem() and then setup().
Near the bottom of the html before the closing 'body' tag I placed two scripts, the System.js and a setup function to load the data that was passed from php to javascript using json as the variable budgetcost and another called budgetexp:
<script src="util/js/System.js" type="text/javascript"></script>
<script type="text/javascript">
function setup(){
budgetModel.setCost(budgetcost, budgetexp);
}
</script>
Also in the System.js file I have this global function and variable:
var budgetModel;
function setupSystem(){
budgetModel = new BudgetModel();
}
The setupSystem function is called before the setup function is called within the index.php file. The error I get is that it complains the budgetModel variable is not defined. How can this be fixed or is it even possible and if it is possible should my System.js script line be somewhere else?
EDIT:
I fixed the problem. There was a very very small syntax error in the System.js file.
I also noticed that window. syntax doesn't matter either way if the variable is declared global or not. Sorry for the bother everyone x_x
EDIT2:
Here is as much code as I can provide:
index.php:
<!DOCTYPE html>
<html>
<head>
<title>Test Page</title>
<link rel="stylesheet" href="util/css/globalStyles.css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body onload="setup();">
...
<script src="util/js/System.js" type="text/javascript"></script>
<script type="text/javascript">
function setup(){
if (typeof(budgetcost) !== 'undefined'){
setupSystem();
budgetModel.setModel(budgetcost, budgetexp);
teamAssumpModel.setModel(teamagents);
}
}
</script>
</body>
System.js:
var budgetModel;
var teamAssumpModel;
function setupSystem(){
window.budgetModel = new BudgetModel();
window.teamAssumpModel = new TeamAssumpModel();
}
function TeamAssumpModel() {
this.teamagents = [[]];
this.setModel = function(teamagents){
this.teamagents = teamagents;
};
this.getAgents = function(){
return this.teamagents;
};
}
function BudgetModel(){
this.budgetcost = [[]];
this.budgetexp = [[]];
this.setModel = function(budgetcost, budgetexp){
this.budgetcost = budgetcost;
this.budgetexp = budgetexp;
};
this.getExp = function(){
return this.budgetexp;
};
this.getCost = function(){
return this.budgetcost;
};
}
So this is pretty much what what I have. budgetModel works in the index.php but when I include this same file into another php file it reads as undefined. What else is required to make it visible to other php files?

Calling a javascript function from other file

I have a javascript file that I'm am calling in the head of an HTML file, it's called custom.js, it defines this function:
var example = function(element){
console.log(element);
};
Then in the actual HTML document, just before the body tag closes, I try to initialize it by calling the same function like this
example('.header-background');
I get the error example is not a function, what exactly am I doing wrong? Thank you so much for your help.
here is a bit more context
<!DOCTYPE html>
<html>
<head></head>
<body>
// the main body of html
<script src="custom/custom.js"></script> // here is the file with the example function
example ('.header-background'); // here im calling the function
</body>
</html>
Change var example to window.example. If you declare a variable with var inside of a function or closure it isn't globally accessible.
e.g.,
function foo()
{
var test = 'hi';
}
console.log(test); // error, test isn't accessible
function foo()
{
window.test = 'hi';
}
console.log(test); // works
Global variables should generally be avoided there. There's most likely a better way to do what you want to do.
Make sure to the file where your function in the html page you are calling the function:
<script type="text/JavaScript" src="youtpathtothefile/custom.js"></script>
Hope it helps
Please make sure two things:
your javascript file is loaded after jQuery library.
your javascript is loaded after the every dom in the html file has finish loading.
Maybe that could help you.

Categories