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>
Related
I am building a front-end UI framework for developers in my firm to use to build internal web apps. It consists of customized Bootstrap, jQuery, other open-source libraries, internal modules and stylesheets. The user environment is entirely IE9 and my server is .NET 3.5. I am hosting the shared files. Dev teams in the firm will place the links in their project pages and apply the framework to their pages.
I want to offer them the simplest method of implementing this which would be one line of code to paste that builds the library for them. Cutting and pasting 30 lines of code is stale the moment Ctrl + V is pressed, it leaves me no control and is simply inelegant.
Failed Experiments
I tried using Head.js and LazyLoad both of which use best practices for inserting scripts. But each of them has caused either content to display before styled or conditions where methods are called before scripts load. I am giving up on this approach.
It's too volatile.
A simple document.write() solution
Over the weekend, I thought: Why don't I just make a js file named "framework,js", add the script and link files in order with a stack of document.write() lines. Tell developers to put it in the head and that's it. Heck I could add the necessary metatags for IE9 and mobile too for that matter. It's so nasty and simple... but it just might work!
The user base is on an internal network and of limited size. Bandwidth is not a problem. I'll test performance before I choose this. I can direct the developer teams on where to place the link.
Knowing this and providing it actually works, is there any reason why I shouldn't do this?
My only other option to explore is bundling on the server. I am hoping not to have to resort to this since I don't own the server myself and I am not a .NET developer.
Your proposed approach is an excellent one for your situation. It has several advantages over the more sophisticated solutions, including utter simplicity, completely predictable order of execution, and full compatibility with scripts that may not lend themselves to asynchronous loading. I have used it many times in production applications, as have many other developers.
Of course the other solutions have their advantages too, but for what you're doing there is nothing wrong with good old document.write().
It sounds like you have a number of scripts and stylesheets and are probably loading them from a common directory (or a common root directory). To reduce repetition in your framework.js file, you might want to define two functions, one to write a <link> tag for CSS and another to write a <script> tag for JavaScript. So a skeleton framework.js file might look something like this:
(function() {
var scriptBase = 'js/';
var styleBase = 'css/';
function writeStyle( name ) {
document.write(
'<link rel="stylesheet" href="', styleBase, name, '">',
'</link>'
);
}
function writeScript( name ) {
document.write(
'<script src="', scriptBase, name, '">',
'</script>'
);
}
writeStyle( 'one.css' );
writeStyle( 'two.css' );
writeScript( 'one.js' );
writeScript( 'two.js' );
})();
Note that you don't have to do any special escaping of the </script> text as you may see in code that uses document.write(). That's only necessary when you're putting this code directly inside a <script> tag within the HTML file. The purpose of that escaping is to prevent the enclosing <script> tag from being closed by the </script> text inside the document.write() call. Since your code is in an external .js file this is not an issue: the presence of the </script> text inside this file won't terminate the .js file.
Another point to keep in mind is that all of the document.write() calls you make inside a .js file are inserted into the document after the .js file that writes them. So don't expect to be able to do a document.write() inside framework.js and then have other code inside framework.js that depends on the .js file you just wrote. All of those .js files (and .css) are loaded after framework.js, not interleaved with it.
One more consideration, of course, is load time. Your page could load faster if you combine and minify your CSS and JS files. But if these are internal web apps, page load time may be the least of your worries: reliability and maintainability may be more important. And in any case you can always use the document.write() solution to get up and running right now, and later optimize this only in the unlikely event that you need to.
I have created a string builder JavaScript object and I'm using it with many different .js files in my project.
Can I create this class in a separate .js file and call it from all the other scripts that instansiate it, just like a C# class file?
Is this possible, or do I continue copying and pasting it into the bottom of every .js file that uses it?
Yes, this should not be a problem. Just include the .js files in the correct order in your html pages.
If you include the file in your main HTML page with your other js, you can then use the "class" as you wish:
<script src="js1.js" type="text/javascript"></script>
<script src="js2.js" type="text/javascript"></script>
In the above example, you can now instantiate a new instance of an object from js1.js with the code in js2.js. To do this with pure javascript, you would have to add the script tag to the DOM, or use AJAX to fetch the script file and eval() it.
// Create a <script> element
var scriptEl = document.createElement("script");
scriptEl.src = "js2.js";
scriptEl.type = "text/javascript";
// Append it to the <head>
document.getElementsByTagName("head")[0].appendChild(scriptEl);
To be perfectly correct, it's not the order of inclusion that matter, but rather the order of executing code. In most cases, Andy's and Segfault's instructions are just fine, but sometimes including the class file before its consumers isn't sufficient. For example, if you use ExtJS and you happen to define your class inside an onReady handler like this:
Ext.onReady(function() {
myClass = ...
}.bind(this));
then it won't get executed by the time your second src file is included into the page and executed.
I know, the example is a bit far-fetched :) but just make sure that your code is executed in the right order, not just included in the right order.
I came across this question and I wanted to add something (which probably wasn't there a few years ago).
Even thought you can add every single script to your "index.html" it's not a very beautiful practice (imho). Especially if you consider that you may want to write a extension (~ framework). You don't want to annoy the user with a bunch of script tags he has to add to his code. What you want is a single line like this:
<script src="yourFramework" (...) />
However, with the use of RequireJS you are able to achieve this. You've the freedom to separate your code and "your user" still don't have to add a novel to his "script section".
I'd like to split my views in Grails into 2 files a .gsp file and a .js file so that I get a cleaner Javascript separation from my views. So here's an example:
views/index.gsp
views/index.js
views/home/index.jsp
views/home/index.js
But when I simply add the index.js script reference like this:
<script src="index.js" type="text/javascript"></script>
all I get is a 404.
Does anyone knows how to deal with this?
A great benefit would be to have the ability to use view data inside the index.js file to produce the desired content.
Matthias.
Actually, it should be perfectly possible to serve a JS file (or any other file type) as a GSP from your grails-app/views/ directory. The only thing you have to do, is define a suitable URL mapping for those GSPs, e.g.:
"/javascript/home/index"(view:'/home/index.js')
With this URL mapping, you can put your JS code into grails-app/views/home/index.js.gsp (note the trailing .gsp) and you can use any grails tags in your JS source. To ensure that your JS is delivered with the correct content type, you may want to place
<%# page contentType="text/javascript"%>
at the beginning of your GSP.
Unfortunately, the createLink tag doesn't support link rewriting to views, but it should be easy to write your own tag to create those links.
Anyways, keep in mind that this won't have a very positive impact on your app's performance. It's usually better to have static JS files (and also serve them as static resources) while passing dynamic stuff as parameters to JS functions for example. This will also keep you from some headaches wrt. caching etc.
The idea is good, but Grails has this directory structure for a reason. The view folder is intended for a certain artifact type (views)..
You could clone your view folder structure under web-inf, but that gives you more work as I guess the idea behind this is to keep related files close together for convenience reasons.
Even though I'm not to excited about storing Javascript together with the view I loved Robert's idea of hooking into the build process by using build events to copy javascript sources into the right directory! If you decide to go down that road you might as well compress the sources while you're at it. ShrinkSafe is popular library.
I don't think you are allowed to access js inside views/
if you need to do that ... here is the trick
create your js and rename it with myjs.gsp (use "")
iniside _myjs.gsp type you js
... write down you js in here ...
inside you gsp (for example: index.gsp, view.gsp, etc)
type this tag to upload you js
Update 2:
Grails offer the possibility of hooking into the build lifecycle using custom events.
An event handler can be written which synchronises all JavaScript files under grails-app/views with the target folder of web-app/js.
Place the custom code in $PROJECT/scripts/Events.groovy. The PackagingEnd is a good target for the invocation, since it happens right after web.xml is generated.
eventPackagingEnd = { ->
// for each js file under grails-app/views move to web-app/js
}
Update
If you'd like the JavaScript files simply 'meshed' together, you can do that using symlinks, e.g.:
grails-app/views/view1/index.js -> webapp/js/view1/index.js
As far as I know, there is no way of forcing grails to directly serve content which is outside of web-app.
Alternatively, you can inline your JavaScript, but that can have performance implications.
JavaScript files belong under web-app/js.
Then you can reference them using <g:javascript src="index.js" />.
First, a caveat. The main script is not run in a webpage. I will be running the .js file in Windows using Windows Script Host.
The problem:
I would like to create a javascript "library" containing a number of objects, each with a number of functions. I expect this library will get rather large with time and would like to keep it in a separate javascript file (let's call it Library.js). I would like to access the objects from Library.js from another script (let's call this one User.js).
In essence, I am looking for something similar to the C/C++ "include" paradigm.
Is there anyway to implement this in javascript? (Remember, this is not web-based)
This page right here is the closest I could find. It talks about .wsf files which let you combine multiple scripts (that may be written in different languages) in one file.
For your question it should be something like:
user.wsf
<job id="IncludeExample">
<script language="JScript" src="library.js"/>
<script language="JScript">
<![CDATA[
// use your library functions here
]]>
</script>
</job>
There may be better ways, but I'm not a WSH expert.
I know this is an old question and it has been answered and accepted.
I know about .WSF files and how they work; they serve the purpose.
However, I've also found it handy to do the "inclusion" from within a pure .js file that runs in WSH. Here's my solution for that.
function includeFile (filename) {
var fso = new ActiveXObject ("Scripting.FileSystemObject");
var fileStream = fso.openTextFile (filename);
var fileData = fileStream.readAll();
fileStream.Close();
eval(fileData);
}
With that utility function defined, I can do this from within a javascript module:
includeFile("externalFile1.js");
includeFile("externalFile2.js");
includeFile("etc.js");
...and then I can invoke any of the functions or tickle any of the variables defined in those modules.
A similar technique works with .vbs files:
How do I include a common file in VBScript (similar to C #include)?
You can achieve your goal by using the Windows Scripting Host instead of a specific .js or .vbs file. More information can be found at the MSDN site.
From the link:
Windows script (*.wsf) file is a text
document containing Extensible Markup
Language (XML) code. It incorporates
several features that offer you
increased scripting flexibility.
Because Windows script files are not
engine-specific, they can contain
script from any Windows Script
compatible scripting engine. They act
as a container.
You would cal lthe file using the same syntax as a .js and .vbs file:
wscript.exe myScriptFile.wsf
UPDATED: Correction noted...
There are essentially 2 places to define JavaScript functions in Grails, directly in a element on the GSP, and within a separate javascript source file under /web-app/js (for example, application.js). We have defined a commonly reused javascript function within application.js, but we also need to be able to generate parts of the function dynamically using groovy code. Unfortunately, ${some groovy code} does not appear to be processed within separate javascript source files.
Is the only way to do this by defining the javascript function within a script tag on a GSP page, or is there a more general solution? Obviously we could define the javascript function in a script tag within a template GSP file which would be reused, but there is a lot of push to keep our javascript functions defined all together in one place (i.e. the external javascript source file). This has performance benefits as well (the javascript source files are usually just downloaded once by each client's browser, instead of reloading the same javascript functions within the source of every html page they visit). I have toyed around with the idea of breaking the function up into static and dynamic pieces, putting the static ones in the external source and putting the dynamic ones in the template GSP, then gluing them together, but this seems like an unnecessary hack.
Any ideas?
(edit: It may sound like the idea of dynamically generating parts of a JavaScript function, which is then downloaded once and used over and over again by the client, would be a bad idea. However, the piece which is "dynamic" only changes perhaps once a week or month, and then only very slightly. Mostly we just want this piece generated off the database, even if only once, instead of hard coded.)
An easy solution to keep your JavaScript unobtrusive is to create a JavaScriptController and map its actions "/js/*" by adding this to your UrlMappings.groovy file:
"/js/$action"{
controller = "javascript"
}
then just create an action for each dynamic JS file you want, include in in your layout <HEAD>, and presto, you've got a JS file that you can insert Grails snippets into! :)
Note: I've found that there's currently a bug in Grails that doesn't map file extensions to content-types properly, so you'll need to include <%# page contentType="text/javascript; UTF-8" %> at the top of your view files.
This is a great solution. I would like to offer a suggestion to use somthing other then a mapping of "/js/$action" because this is no longer going to allow you to access you javascript files in /web-app/js/. All your javascript files would have to be moved to a the directory your controller would point to.
I would use something like
"/dynjs/$action"
This way you still can point to files in the /web-app/js/ files with out conflict and enjoy the benifits of gsp tags in javascript files
Please correct me if I'm wrong.
Or this... have a tag/service/dynamic method that lets tags write out their JS+CSS+whatever else, to a "cache" which is used to build the JS+CSS resources by a different controller.
Full concept here: [http://www.anyware.co.uk/2005/2009/01/19/an-idea-to-give-grails-tags-esp/][1]
If you want to use models created by the controller (that rendered HTML page which reference the Javascript in which you intend to use groovy code) in the Javascript code, then you can use this technique:
This technique does not need to change URL mappings and does not require you to create extra controller.
In your view GSP add javascript as follows:
<script type="text/javascript">
<g:render template="/javascript/yourJavascriptFile"/>
</script>
In views folder create a "javascript" folder. And create a file named:
_yourJavascriptFile.gsp
You can not only use all the GSP code in your _yourJavascriptFile.gsp file, but you can also use all the models created in your controller (that is rendering the view).
NOTE: There is nothing special about javascript folder. You can name it anything you want OR use an existing view folder. This is just a matter of organizing and identifying your HTML spitting GSP from Javascript spitting GSPs. Alternatively, you can use some naming conventions like: _something.js.gsp etc.
Name your scripts like this
/wherever/the/js/files/are/thescript.js.gsp
The gsp code inside will be rendered correctly by grails. This works, but I have no idea if it's considered a Good Idea or not.
There is another way - pass in the generated code into a function that expects closures. Those closures is generated by the program of course. The generated code is of course inlined/script-tagged in the gsp page.
it may or may not work depending on the nature of the code being generated. But i suspect it will work, and if it doesnt, minor tweaking to the coding style of your javascript will definitely make it work. Though, if these 'generated' code doesnt change much, this quite overkill imo.