Importing JavaScript in JSP tags - javascript

I have a .tag file that requires a JavaScript library (as in a .js file).
Currently I am just remembering to import the .js file in every JSP that uses the tag but this is a bit cumbersome and prone to error.
Is there a way to do the importing of the .js inside the JSP tag?
(for caching reasons I would want the .js to be a script import)

There is no reason you cannot have a script tag in the body, even though it is preferable for it to be in the head. Just emit the script tag before you emit your tag's markup. The only thing to consider is that you do not want to include the script more than once if you use the jsp tag on the page more than once. The way to solve that is to remember that you have already included the script, by addng an attribute to the request object.

Short of just including the js in every page automatically, I do not think so. It really would not be something that tags are designed to to.
Without knowing what your tag is actually doing (presumably its its outputting something in the body section) then there is no way that it will be able to get at the head to put the declaration there.
One solution that might (in my head) work would be to have an include that copies verbatim what you have in the head after the place in the head to import tags right up to where you want to use the tag. This is really not something that you would want to do. You would have to have multiple 'header' files to import depending on the content and where you want to use the tag. Maintenance nightmare. Just a bad idea all round. Any solution I can think of would require more work than manually just adding in the declaration.
I think you are out of luck and stuck with manually putting it in.
edit: Just import it in every page. It will be cached and then this problem goes away.

Related

How to load error trackers from script tag?

I'm working on small .js which is going to be embedded on multiple websites, it will be loaded in a classic way - via script tag: <script src="myscript.js"></script> in sites body tag. I cannot add any more scripts to those sites.
I would like to track errors with error tracker such as Sentry, Rollup or HoneyBadger. However, all of them require being loaded with another script tag, most preferred before everything else.
Note: Those services need to load before everything else to catch errors property.
As I cannot add another script tag in the site's code, I need to execute their code inside my script, but before my actual script code.
I tried taking the content of HoneyBadger javascript library and putting it directly inside my file - it worked, however, I feel like it's terrible practice, as their code is written with modern browsers in mind, and mine supports older ones.
Is there any good way in my situation to load their .js externally?
I don't think that would work because of the way honeybadger.js v0.5 parses the script tag to get those attributes--it looks for the script tag in the dom when it's loaded.
Also, we've moved away from using the data- attributes in honeybadger.js v1.0, which was just released. In that version, you must use Honeybadger.configure to set your API key. Take a look at the new docs here:
https://docs.honeybadger.io/lib/javascript/integration/browser.html
I'd recommend going with v1.0, and using Honeybadger.configure for the configuration.

Managing page specific Javascript: 1 big file with conditionals or multiple files

In my project I have a load of functions that are used on every page, so I have put these in a single javascript file common.js and have included it in my footer template. My questions is, what is the best way to handle page-specific javscript?
For example, on one of my pages I have a google map. If my map js code is run on a page where I don't have an element with id map_canvas, I get an error.
Method 1: I could write some PHP which echos an additional script tag requesting map.js if and only if I'm on a map page.
Method 2: I could give the <body> of my map page an id of "map_page", then I could write a conditional clause in common.js along the lines of:
if (#map_page exists){
put contents of map.js here
}
The problem with method 1 is that it increases the number of requests to the server.
The problem with method 2 is that it bloats my common javascript file.
Please can somebody explain, which, if any would be the preferred method to do this, or if neither are suitable, what I should do instead?
I have approximately 10 page-specific javascript files to deal with.
Thanks
I would say that simpler is better. On every page, just add a script tag calling map.js. Or, in your common.js, you don't need to paste all of map.js's code. You can just create a new script tag with the js and call map.js like that. I would not recommend the php method. The easiest and simplest, therefore the least likely to be buggy method, is just to add another script tag to the pages that need it. Or if that is not an option, common.js could include this:
if(need map.js){
var mapjs=document.createElement("script");
mapjs.type="text/javascript";
mapjs.src="map.js";
document.body.appendChild(mapjs);
}

Data attributes and script tags

I have a project I'm working on called Natalie.
What it does, (twitter.com is a good example if you don't understand my explanation) is it uses the hash tag, to load a page via XHR, and then inserts it into the page, so you can have a generic look that doesn't change between pages, that doesn't need PHP or the like.
It has several configuration properties, the main ones being:
A selector to use to find the place you would like to insert the loaded page.
A folder path to use at the document root. (Think Apache configuration)
The page to load if there isn't a hash tag.
I currently have them in an object called Natalie.config but I would like to do something like <script src="Natalie.js" data-natalie-docroot="/Folder"></script>
Is there any way to tell which tag the script is running from, or do you have to search all script tags for these attributes?
I would much rather prevent something like this from happening if possible:
<script src="Natalie.js"></script>
<script data-natalie-docroot="/Folder"></script>
I'd simply put data-natalie-docroot="/Folder" on the <body> tag. The reason being that it is not directly associated to the script itself. Your approach also wouldn't work if someone wanted to load your script using a dynamic script loader.

Calling a JavaScript object class that's in a separate .js file

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".

Executing groovy statements in JavaScript sources in Grails

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.

Categories