What is a good "non-hacky" way to pass a value from JSP to javascript in a specific scenario - javascript

So, here we go guys, my team is working on a big java web application, it has a lot of legacy code. The way the previous team that worked on the application used to pass variables from JSP to javascript was compiling all the .js files as .jsp
In the beggining of the javascript file, it would include (commentated javascript code that would render as java code) a file that opens a <script> tag and does some importing, and in the end of the file it would include a jsp file that closes the tag.
Something like this in a javascript file:
/* <%# include file="init.jsp" %> */
real javascript code here
/* <%# include file="end.jsp" %> */
So we could call the script file like this in some random jsp:
<script src='whatever.js?param=<%=parameter%>'></script>
And so we could get a parameter from the url since in reality it is a jsp
var x = "<%=UtilitiesWeb.getParameterFromUrl('param')%>"
And everyone agrees that it's a really bad practise.
So, I want a better way to this, but I also have some restrictions. Look at the following scenario.
I have this jsp:
<%
final String id = (String) request.getAttribute("id");
%>
<div id="<%=id>">
<script src="whatever.js"></script>
Basically, I need the whatever.js to get the java variable id so I can do some modifications in the div (in my case, the div is going to be a grid with some data populated by the avascript). But, I can't do something like this:
<script src="whatever.js" data-customattribute="<%=id>"></script>
// Inside the javascript file
var id = $("script[data-customattribute]").attr("data-customattribute")
The reason I can't do this is because this my jsp is called in many places assynchronously, so I can't guarantee I'm getting the ID related to the js file. I don't think that getting the .last() script with the attribute would be reliable either, since the app has many javascript files called assynchronously (but it could be, so if anyone has more understanding about this please say it).
I also tried using document.currentScript but it returned null, not sure why?
I was thinking of using a <object> block to call the jsp file with javascript (or maybe the only the javascript, not sure if this works), so the javascript would only have acess to the div inside the object, and it would not be confused with any other divs inside the document, but I've heard there are some drawbacks to using things like <object> or <iframe>.
So...any ideas/tips/advices? Any input is appreciated.

The way we'd always done it is to have the scripts simply define functions, then you can embed function calls directly in your JSP like so:
<% final String id = (String) request.getAttribute("id"); %>
<script src="whatever.js"></script>
<div id="<%=id>"></div>
<script>whatever("<%=id>")</script>
It seems easier to debug that way, and you can statically serve the script files.
As an aside, and if you're able, I'd recommend you look at Apache Velocity to replace the JSP layer. It makes life nicer :)

Related

Using gsp layout declared variable in javaScript file that is being loaded in the same page

I recently started learning grails and I am trying to use a gsp variable declared in the layout of the page as:
<g:set var="abtestType" value="newSearchBar" />
in the js file that is being loaded on the same page. Things that I have tried:
alert(${abtestType});
alert(<%=abtestType%>);
alert("abtestType:"+abtestType);
but its showing error as variable is not defined. Probably I am trying to fetch it in wrong way, need help regarding this.
Even thinking about doing so neither makes sense nor applicable.
Reason for such statement is that when a gsp page is rendered to an html page, it replace grails tags with appropriate html tags or value. Similarly it replaces the ${} or <%%> with html or javascript or whatever that goes on front-end.
Hence the code that you have tried could have worked fine if you were having those javascript code lines in the gsp itself but as you have called externalised js file it actually don't know anything about gsp or jsp or any other Language's front-end support.
The one way of doing that if using global variable in javascript. e.g.
declare abtestType above like below:
<script>
var abtestType = "${abtestType}"
</script>
Now you have access to global variable abtestType in your javascript.
Use it in your javascript but remember now you need to have this variable iff the code using it is called otherwise very same error would you get i.e. variable is not defined
There is another way that I found in this post but is a manipulation actually.
Is there any analogue in Javascript to the __FILE__ variable in PHP?
Also, another good links is
Pass vars to JavaScript via the SRC attribute
Hope it helps!

Include a JavaScript file as it was written in a script tag

I have some html, that had a bunch of JS code inside a script tag. So I moved it to a separate .js file.
JS code also loaded some variables from CGI, using strings in a form of <%ejGet(var)%>. But after separating the code from HTML file, the strings don't get replaced with data from the server.
Is there a way to include a JS file as if it was written inside a script tag or is there another way to do this?
<script language="javascript">
<!-- hide
var syncNvram = '<%ejGetWl(wlSyncNvram)%>';
...about 1000 lines more...
</script>
So after moving this code to a separate file, the variables don't load.
The problem is that your <% ejGetWl(wlSyncNvram) %> is being executed on the server by some templating or processing engine before it gets sent to the browser, so the browser is actually seeing the output, e.g.
var syncNvram = 'abcdefg'; // or whatever the output is
The question you are really asking is, can my server side templating/processing engine process a javascript file as opposed to an html file.
The answer is, it depends on the template/processing engine, but in general, this is a bad idea. JS files should remain static assets for lots of good reasons (breaking code, distributing via CDNs, etc.)
The better thing to do is separate them out:
<script>var syncNvram = '<%ejGetWl(wlSyncNvram)%>';</script>
<script src="myfile.js"></script>
Declare it separately.
Even better might be using ajax to get it, but that is a whole different architecture which may not suit here.
To do that you need to generate the script from the CGI program.
<script src="/cgi-bin/example.js.cgi"></script>
Of course, that will be a different CGI program so getting the variables in the right state may be problematic.
Usually you would solve the problem using a different approach: include the data in the document (either in the script element or in an element such as a <meta> element, a hidden input or a data-* attribute on something relevant and then have a static script read the data from the DOM.

Why does this code use an .aspx file for JavaScript?

I found some old code which I'm not sure I understand completely. The folowing is an .aspx page containing only JavaScript:
<%# Page Language="C#" EnableSessionState="True" CodePage="65001" uiculture="auto" %>
<%
Response.ContentType = "text/plain";
%>
var csBackgroundColor;
function testfx() {
csBackgroundColor.setAttribute('disabled', 'disabled');
}
and it was referenced like this:
<script type="text/javascript" src="filename.js.aspx"></script>
I'm wondering why it wasn't just marked as completely a JavaScript file? Was it done this way so you could include code blocks? With the file this way, I don't even get IntelliSense.
First time I see something like that but you're right, the reason behind this is to make the file to be processed by the asp.net engine and run it as any other aspx page, giving him the chance to use server side code to build the js file.
If that's all the code in the file, it seems the only objetive was to set the character encoding (CodePage="65001" and the content type (Response.ContentType="text/plain"). It wouldn't make a lot of sense as you can imagine.
<hack>To get intellisense you could wrap the code in <script> ... </script> blocks and remove them before saving.</hack>
This was probably created by a developer that didn't want to, couldn't, or didn't have the time to write object oriented JavaScript. Encapsulating the logic and configuring through a configuration object would allow you to de-couple the code from external variable dependencies, (e.g. var foo = <%= SomeServerSideVariable %>).

Ruby on Rails with Unobtrusive JavaScript - Managing URLs

I'm using a modular system of JavaScript files when working in Rails - basically each view will have its own module in a .js file. My issue comes when I need a dynamic, Rails generated string within my JavaScript, for example translation strings and URLs.
Translations are nicely solved using babilu but I'm still stuck on the generation of URLs. I could write something that looked at the routes in the application and generate JavaScript methods which I could pass stuff like IDs of objects.
An alternative would be to pass in the already-generated URL to any functions I was calling, which sounds messy but could be the most flexible alternative.
I don't know that there's any truly pleasing way to do this, but one possibility is to have your server-side code write a small <script> block into the page to declare some variables that your packaged Javascript can discover and use.
<script>
var pageGlobals = {
interestingURL: <% ... url %>,
...
};
</script>
I've done this to keep track of things like image subdirectories that are determined by customer "syndicate" affiliation. The Javascript code just knows that whenever it needs that for a URL, it can just go look in a global object and pick out a standardized variable.
In my experience there tend to be only a small number of such things to communicate to the canned Javascript, so the <script> block tends not to get out of hand. I've buried mine in a page template so I don't even have to think about it with new pages.
Oldish question, but here's another way. The HTML 5 spec allows for custom data- attributes.
In your view:
<button id="myButton" data-url="<%= my_resource_path %>">Click me</button>
Then in your packaged js:
var myurl = $("#myButton").data("url");
See here also.
I don't like this either. The ideal solution to me would be javascript templates. Imagine in the .js file you could do:
var users_path = '<%= users_path %>';
But that would mean the .js files would have to be regenerated in every request (well, one could use caching just like with rails html).
Anyway, what you can also do is put the dynamic stuff in data- attributes. So you can do for example
<%= select_tag :select_something, select_options, 'data-url' => users_url %>
And then read that attribute out in the javascript file. I prefer this over the solution suggested by Pointy.
Edit: Well actually someone implemented the dynamic .js file idea. Seems straight forward enough, just create a javascripts controller and link to its actions via javascript_include_tag: dynamic javascript files

Injecting a string into a javascript on an asp.net mvc view

I have a view that contains a javascript function that i need to init/call when the page loads. The method is static but it needs to be called with some parameteres (a list of Id's) - this list is dynamic and varies by some querystring parameters (i can not generate the list clientside from the querystring).
So i need to generate this list server-side.
My options are, as far as i see it:
1) Make an ajax call on the client, requesting the ids from the server.
2) Inject/inserting the ids directly on the view (it is a property on the viewmodel).
No matter how i turn it, option 2 seems the most sane. I already got the data ready on the viewmodel and thus it's ready when the view is populated - i see no reason to make an extra request to the server, just to get the data.
I know many would think it's a bad idea to inject something dynamic into an otherwise static javascript. For that i could simply just inject a new javascript, holding only the Ids and a call to the static javascript method, which is what i really want to do.
My problem is this though: When i write my asp.net <%= %> includes, VS IDE stops highligting, making me think i might be on the wrong track? Surely i'm not the only one needing to output something in a javascript block in asp.net mvc?
Route 2 (The ViewModel) is definately the way to go and
<script type="text/javascript>
<%= Model.JavascriptToInsert %>
</script>
should work (despite lack of VS highlighting)
It will NOT work in a seperate JS file though. It must be in your view itself.
Kindness,
Dan

Categories

Resources