I have defined the following module in MyModule.js:
MyModule.js:
MyModule = {
controller: {
paintCar: function(color){
//PAINTING PROCESS
}
},
tester: {
...
},
};
Then, I have another javascript file, other.js:
other.js:
MyModule.controller.paintCar('red');
My index.html
<body>
<script scr="MyModule.js"></script>
<script src="other.js"></script>
</body>
All these files are put under WebContent directory of Eclipse Dynamic Web Project.
In other.js when I try to run the above code, I got error "MyModule is not defined". Why?
You misspelt src here: <script scr="MyModule.js">. This would have been picked up by basic automated QA testing.
(Original answer before the theory was confirmed) Presumably, because you aren't loading the script files properly. Since you haven't shown us the code that does that (or even told us what environment you are using) it is hard to say exactly how you went wrong.
Assuming you are using client side JS in a webpage, your code should look something like:
<script src="MyModule.js"></script>
<script src="other.js"></script>
Order is significant. End tags are mandatory. Self-closing tag syntax is unacceptable (unless the document is served as application/xhtml+xml)
(This uses HTML 5 syntax. For HTML 4 / XHTML 1, add a type attribute. For HTML 3.2, add a language attribute)
You haven't mentioned your environment, but generally you have to ensure that the JavaScript in MyModule.js is executed before the JavaScript in other.js, because you need MyModule.js to set up the MyModule variable.
How you do it will vary by environment. In a web browser, you'd do that by putting in two script tags, first one for MyModule.js then the one for other.js (although frequently, for use on websites, you want to have a build process that combines your scripts into a single file to minimize HTTP requests). In NodeJS, there's the whole require mechanism.
Update based on your edit:
Looks like a typo:
<body>
<script scr="MyModule.js"></script>
^^-- here, they're transposed
<script src="other.js"></script>
</body>
If that typo isn't really in your file, then look to see that the files are where the web server expects, that the web server isn't being thrown by capitalisation, that sort of thing. Fundamentally, that's correct.
Related
I have 3 files, an index.html, a Learner.js, and a bot.js. Right now, the bot.js is a regular js file that I load in the html file with <script> tags, and the Learner.js is a NodeJS file. The only reason I have this file is because I want to use a Neural Net library but it only works with NodeJS, not regular javascript, so how exactly would I reference any functions, varibles, etc. in my bot.js that exist in Learner.js, should I load the file using <script> tags, or what's the best way to go about this?
The answer is that its (potentially) complicated.
There are things that node.js can do that browser JavaScript cannot do (like have filesystem access), and things that the browser doesn't do (e.g. Buffer API, module system). Obviously the later can be brought to the browser by libraries, but on the former you're out of luck.
So the question is, what node-specific stuff does that library use? If its just require use webpack/browserify or a babel/rollup plugin. But you're going to have to comb through that library to see what its actually using and whether or not that would be present in the browser.
You can add it simply:
<script type="text/javascript" src="Learner.js"></script>
<script type="text/javascript" src="bot.js"></script>
But, if your Learner.js javascript file use some native node.js engine functions or simply require() calls, it wont work.
In this case, consider to try to use Browserify or similar tools, to allow run nodejs specific stuff into the browser.
All these tools have limitations, not all code can be executed browser side.
When it is not possible you have to implement a web service server in nodejs (for example using a REST api, JSON over RPC pattern, ...) to allow execute the code and get the result in the browser.
As long as both are JavaScript and have variables that have global scope, a variable from Learner.js can be used in bot.js is Learner.js is loaded before bot.js
<script type="text/javascript" src="Learner.js"></script>
<script type="text/javascript" src="bot.js"></script>
You could also use a property of window or (in the global scope) this to get the same effect.
But
When you are using node you'll have to make sure you are also running the node server and best way to get outputs are by sending json object by use of some API, and get that json response in bot.js
I am new to typescript, knockout and requirejs. I have created some demo using this files. Now, I want to implement some minor logic using typescript and knockoutjs.
I have created 4-5 typescript files, which are imported internally. When I run the html file. I am getting the error stating. as Titled
Can somebody help me on this error. What I am missing in this code.
have search on google and spend quite a good time but didn't find the proper solutions. It must be related to requireJS to define all modules. But, as new in requireJS not able to catch up with that. I have also search stackoverflow for the similar error, but it doesn't help me out.
Waiting for the solution
Here your TypeScript has compiled happily, to code that will work in a requireJS environment (technically, an AMD environment). That means it generates output that assumes that define/require etc all already exist.
The overall answer is that you need to include RequireJS before you depend on your compiled code.
Notably the error suggests you've made a separate mistake though: you're depending directly on the RequireJS module scripts (i.e. you have a <script src="my-compiled-code.js"></script> tag in your HTML). That's not how require modules work. Instead, once you've made RequireJS available, you should have a single top-level startup script (either inline in your HTML or as a separate file) that configures RequireJS and then require()'s the top-level files of your application to start everything off. You can load this file either by hand, or with RequireJS's "data-main" attribute.
For example, a minimal HTML looks something like:
<!DOCTYPE html>
<html>
<head>
<script data-main="scripts/main" src="scripts/require.js"></script>
</head>
<body>
</body>
</html>
This loads RequireJS from 'scripts/require.js' and then tells it to load the script at 'scripts/main.js' to start off the loading process (you'll probably want to update both paths - note that data-main doesn't need a .js extension).
The main script should then be something very simple like:
// Set up any config you need (you might not need this)
requirejs.config({
basePath: "/scripts"
});
// Tell RequireJS to load your main module (and its dependencies)
require("mainmodule");
Generally, it's not TypeScript problems you're fighting here, it's RequireJS. I'd try spending a bit more time playing with just Require (maybe in pure JavaScript, so it's clearer) and looking at working examples for that, so you can get that bit working first, then add in the rest.
I have recently got a chance to explore one famous JavaScript library; In that library, I have found one strange way of referring JavaScript library from HTML page.
The application folder structure looks like this,
index.html contains the reference of subroot.js;
index.html
<head>
<title>Index</title>
<script src="js/subroot.js"></script>
</head>
subroot.js only contains the following code (i.e.,the relative path of root.js)
subroot.js
../../js/root.js
When I try to run the index.html, i get syntax error in the first line of subroot.js
Questions:
Is it right way to refer another javascript library by its relative path?
If yes, Why I get error message on the web page?
JavaScript by itself doesn't support loading files or referring paths. You need a module loader of some kind to achieve what you want. With the new version of the standard (ECMAScript 6) there is something called "imports" which you might find useful. I have experience using JSPM and the SystemJS module loader, which makes it pretty easy to connect the dots.
However, without using any additional tools you should just inject another script tag in your HTML.
Just reference root.js in the HTMl file not in the Subroot.js file, you can't reference another .js file from a .js file as far as I know.
<script src="../js/root.js"></script>
See Link
write this in subroot.js file
var x = document.createElement('script');
x.src = '../../js/root.js';
document.getElementsByTagName("head")[0].appendChild(x);
I've seen quite a few questions regarding loading a .js file into an HTML file, and I know how to do that. However, say I have the file "classlist.js." How can I go about using the classes defined in that javascript file in another javascript file? I keep seeing answers that suggest using the
<script type="text/javascript" src="filepath"></script>
syntax. When used in a .js file, though, it throws a syntax error on the "<" so I assume this code is invalid.
So, how would one utilize a function in a .js file that was defined in a separate .js file... that works, and is efficient (If there is one)?
EDIT:
I'm going to clarify some thing for the future, since I'm still fairly new to Javascript, and it looks like there were a number of other factors I didn't even know came into play.
I had two .js files, one of which declared classes that were extensions of classes in the other file. I wanted to use the extended classes in a webpage, and I thought I had to load the originial classes into the second .js file, THEN load that .js file into the HTML file. I wasn't programming completely outside of HTML.
Sorry for any misunderstanding, hopefully this thread is helpful to somebody else in the future.
Assuming you are talking about javascript in a web browser, all js files are loading in an html file, typically index.html. You need to use the script tag to load the javascript in the proper order in that html file, not in the javascript file. So if file B requires the things in file A, you need to load file A first, meaning put the script tag that loads file A before the script tag that loads file B.
Two answers:
Non Browser
If you're using JavaScript in a non-browser environment (NodeJS, RingoJS, SilkJS, Rhino, or any of a bunch of others), the answer depends on the environment — but many of these use the CommonJS require mechanism. E.g.:
// Get access to public symbols in foo.js
var foo = require("foo.js");
// Use the `bar` function exported by foo.js
foo.bar();
Browser
If you're using JavaScript in a browser, you put script tags like the one you quoted in the HTML, in the order in which they should be processed (so, scripts relying on things defined in other scripts should be included after the scripts they rely on).
If you want to maximize efficiency in terms of page load time, combine the scripts together on the server (probably also minifying/compressing/packing them) and use just the one script tag.
The answers posted above should do the trick however since you mentioned doing it efficiently you can consider taking a look at javascript module based loaders like require js( http://requirejs.org/ ) based on AMD
You have to put the reference to classlist.js in your HTML file (not your Javascript file), before any other SCRIPT element which requires it. For example, within the 'head' element:
<html>
<head>
<script src="testclass.js"></script>
<script src="file_using_testclass.js"></script>
<script>
var tc = new TestClass();
</script>
</head>
We are trying to switch the packaging for our project from dojo to google closure, but we haven't had any luck so far. Here is a simple example that illustrates what we are trying to accomplish:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src="runtime/src/core/lib/goog-rev26/base.js"></script>
<script>
goog.require("foo.bar");
function main() {foo.bar.echo("hello world")}
</script>
</head>
<body onload="main()">
</body>
</html>
Then in /foo/bar.js I have:
goog.provide("foo.bar");
foo.bar.echo = function(s) {console.debug(s);}
The errors I receive in firebug are as follows:
goog.require could not find: foo.bar
foo is not defined
When I look in the Net tab, there isn't an http request out to fetch a file - I was expecting the closure library to generate a script tag to fetch bar.js.
help! ;)
I figured it out and it's not very hard, but there are a few gotchas.
Basically, you can use the dependency generating script calcdeps.py (you should read calcdeps.py docs) in one of several modes:
Generating deps.js file
Concatenating everything into a single file, optionally compiling it using the closure compiler.
For development you should use (1), since it allows you to not run the calcdeps.py after editing the JS sources, unless you make changes to the dependency tree. The rest of the answer is about this way, I haven't tried the other one yet.
Here's what I did to generate it:
#!/bin/bash
cd closure-library/closure/goog
python ../bin/calcdeps.py -p ../../../js -o deps > ../../../my-deps.js
...assuming the following directory structure:
project/
closure-library/ (as checked out from SVN)
js/ (my JS code)
app.html
(the -p parameter traverses all js files in the specified directory and the docs say you can specify multiple directories to search if you have to.)
The above call creates a my-deps.js file next to the main app.html, which I use to run the application. The created file contains information about my JS files in js/ and looks like this:
goog.addDependency('../../../js/controllers.js', ['proj.controllers'], []);
goog.addDependency('../../../js/ui.js', ['proj.ui'], ['proj.controllers']);
- where the first string it the path to my JS file relative to closure-library/closure/goog/base.js (this is important!), the second array is the list of goog.provide-d strings, and the last array is the list of goog.require-d strings.
Now in app.html I have:
<script src="closure-library/closure/goog/base.js"></script>
<script src="my-deps.js"></script>
<script>
goog.require("proj.ui");
</script>
<script>
// here we can use the required objects
</script>
Note:
In addition to including closure's base.js, I include my generated deps.js
As mentioned in the tutorial the goog.require call has to be in a separate script tag, because it appends a script tag to load the required scripts and they are loaded after the current script tag finished processing.
Gotchas:
The described above issue with paths being relative to base.js. goog.require creates the script URL to load by concatenating the base.js base URL (i.e. without base.js leafname) and the first parameter to goog.addDependency in deps.js.
calcdeps.py doesn't work well on Windows, in particular using the backslashes in the deps.js string literals
If something doesn't work well, you may want to look through all issues mentioning calcdeps and make sure you have an up to date checkout.
Update!!!
New version of calcdeps.py changes the game a little bit. To create your deps.js you now need to use the -d flag. eg:
python path-to-closure-library/closure/bin/calcdeps.py -i path-to-your-src/requirements.js -o deps -d path-to-closure-library/closure/ -p path-to-your-src/ --output_file=path-to-your-src/deps.js
To compile:
python path-to-closure-library/closure/bin/calcdeps.py -i path-to-your-src/requirements.js -d path-to-closure-library/closure/ -p ./ --output_file=path-to-your-release/scripts.min.js -c path-to-compiler/compiler.jar -f "--compilation_level=ADVANCED_OPTIMIZATIONS" -f "--debug=true" -f "--process_closure_primitives=true" -f "--manage_closure_dependencies=true" -o compiled
So the process is actually now a lot easier, but you have to use your powers of ESP to find out about it as its totally undocumented. The calcdeps.py now also does not work with Python 3.1 on windows so that is also heaps of fun. A few hacks got it working for me (which I will not put here as I'm not a python programmer and there must be better ways to do it).
Generally the last day has been super fun, hope this post helps someone avoid the same enjoyment.
Guido
I was able to get it to work by adding the following to deps.js:
goog.addDependency('../../../foo/bar.js', ['foo.bar'], []);
Firefox now makes an http request to /foo/bar.js when it encounters the goog.requires statement.
However, the file contains this comment:
// This file has been auto-generated by GenJsDeps, please do not edit.
According to this, GenJsDeps is the same as calcdeps.py. If you look at the documentation, it looks like there is an -o deps switch which will re-generate deps.js so it isn't edited manually.
Yes you should use calcdepds.py. I created a big blog post after much trial and error to figure out the best way to do this, I also go over the differences between dojo.require and goog.require:
http://apphacker.wordpress.com/2009/12/28/howto-how-to-use-goog-require-and-goog-provide-for-your-own-code/
Here's a little project that I've been working on that might be helpful to you: http://github.com/fintler/lanyard
Take a look at the build.xml, the file named lanyard.js, and all of the files located in src/geom/*.
The build.xml has an example of how to call calcdeps.py through ant for all of the js located in src. It may not be the best way to do things, but it's been working for me so far.
Either way to get custom modules working, at least for development version, is to include manually js files in head section of html page, after google's base.js file inclusion.
<script type="text/javascript" src="js/closure/goog/base.js"></script>
<script type="text/javascript" src="js/closure/custom/custom.js"></script>
<script type="text/javascript" src="js/closure/custom/sub/sub.js"></script>
...
But, you should care about sequence of inclusion by yourself. For not very large custom files sets it works good. For production version you still had better use js source compiling to get all benefits of closure library.
solution:
download closure to your project externals (or assets, whatever).
don't bother with setting onload, delay, playing with async, etc..
they won't work (they are also very poor design pattern and extremely lame..)
- this is your main.js where you dynamically injecting your code into the DOM (for example creating a bookmarklet or something):
/**
* loads the base.js of google closure.
* http://code.google.com/p/closure-library/
*/
(function() {
var s = document.createElement('script');
s.type = "text/javascript";
s.src = "./assets/closure/goog/base.js";
s.async = true;
document.getElementsByTagName("body")[0].appendChild(s);
}());
/**
* activated from the base.js as JSONProtocol.
*/
window['starter'] = function() {
console.log("hi...");
};
now:
edit your base.js
add the the end of the file
......
.......
........
/**
* run the method when done load. just like JSONProtocol.
*/
window.setTimeout(function() {
window['starter']();
}, 5);
your "callback" simply activates starter when the file has done rendering,
it works perfectly and it keeps loading every resource asynchronously.
p.s.
the window['....'] syntax is so you could safely use closure-compiler to the max and always use the same name (although there are another ways to do so, but this is the simple "always working" way..).
2. on base.js you could also avoid the timeout and just use
......
.......
........
/**
* run the method when done load. just like JSONProtocol.
*/
window['starter']();
but as a rule of thumb modern browsers acts better when you wrap those "don't care, just do this stuff at the end, like JSONProtocol callback" stuff-
timeouts (mostly used with values from 0-5) are not interrupted as timeouts but as a way to breaks the synchronicity of the code-block allowing truly "context-switch"-like behavior.
although there is an extra overhead there.