Ruby on Rails with Unobtrusive JavaScript - Managing URLs - javascript

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

Related

Best way to use C#-Ressources (ResX Files) in Typescript?

our current project is in ASP.Net MVC with Razor.
We use ResX Files for a few thousend translations.
In C# and Asp.net Razor this is pretty easy with HTML:
<div>#Ressources.Local.Test</div>
Now when I wrote JavaScript I normaly did this within the cshtml files with razor like this:
<script>alert('#Ressources.Local.Test');</script>
Which works but seems a bit ugly...
A few weeks ago we starded with Typescript, and, of course excluding (nearly) all javascript code to ts-files.
The only solution we found here, to get the ressources from C# to Typescript is through a "hack":
We made a ressources.cshtml file in which we just include javascript variables:
var ressourceTest = "#Ressource.Local.Test";
We load this ressource.cshtml at first in our _layout.cshtml.
Additional, we have a self need a selfmade declarion for this variable to jump from javascript to typescript in our projectDeclarions.d.ts:
var ressourceTest:string;
And now we can use the ressource in our typescript file test.ts:
alert(ressourceTest);
As you can see it is a working "hack" or "workaround" but it seems to likly kill us for a few thousend ressources... It's handmade, the maintain duration and work is high...
Any better ideas?
I have seen a few good ideas around this.
You could supply an JSON endpoint in your MVC application to give you chunks of translations. You would decide how granular you want to make it, but you would essentially JSON serialize a translation, or set of translations and send it back. This would avoid stuffing a big view with hundreds of the things.
Another alternative is to place translations in the view to make them available, but contextually. So if you had a button that you are using to trigger some AJAX call to the server and you need to say "Update Worked" or "Update Failed" you could put the attributes inline...
<button ... data-msg-success="Saved OK" data-msg-failed="A problem occurred" />
And you could populate these attributes with your resources.

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

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 :)

Best practice of writing JS scripts with AJAX in Rails app? How to include URLs in script?

I'd like to use a little bit of simple AJAX in my Rails application. The main problem I have is that inside a script I need to specify the URL where the request will go, which in most cases is a path to some Rails controller action. Anywhere else I'm advised not to write paths explicitly by hand (i.e. not do ugly stuff like '/my_resources/' + resource_id) but use helpers like my_resource_path instead.
But this approach doesn't work well with javascript, since these helpers don't work inside assets/javascripts. I can think of some ugly ways I can bypass the problem, currently I've implemented an extremely ugly workaround which is basically putting something like this inside my view:
<%= javascript_tag "onSubmitQuotePage('#{j escape_javascript(autocomplete_authors_url(''))}');"%>
But I can't imagine Rails developers didn't think of some prettier solution, some right way of doing AJAX.
I can't say I like the way I do this so very happy to hear better ways of doing this.
But I either include the path in a data attribute on a relevant DOM element, or for some static routes I include a <script> block in the layout file that contains relevant paths.
<script>
(function() {
"use strict";
window.myapp || {};
window.myapp.new_order_path = '<%= new_order_path %>';
window.myapp.orders_path = '<%= orders_path %>';
...
}());
</script>
It's by no means a pretty solution, but the cases where I need a route in my JS are rather rare and that way I can then use myapp.new_order_path in my JS when I need it.
Just to add my two cents here: you can use Rails URI helpers to generate some sort of URI templates. E.g., if you have this route defined:
edit_user GET /users/:id/edit(.:format) users#edit
And you call it like edit_user_path(':user_id:'), it will return /users/:user_id:/edit. This way you can generate URI templates to be compiled by javascript. As #Tigraine said, you can include this in a data attribute of some top element, and use it from the client side.
It comes really in situations where you need to generate URIs for AJAX fetched resources: you just serve the resource id and let the javascript compile the URI from the template with a simple string.replace(':user_id:', user_id).

Passing data from my razor view to my js file

I'm searching for the best way to pass data from my razor view to my js file. For example, lets say we have a jquery dialog configured in the js file. For buttons text on this dialog, I would like to localize it (through resource files FR/NL/UK). The translations are available with #UserResource.ButtonDelete + #UserResource.ButtonCancel
Below are the different solutions I see:
Using the nice RazorJS nuget package to allows razor code inside my javascript file. It works pretty well. But the question is: is it a bad practice to compile js files in order to use razor syntax inside the scripts?
Declaring global variables in the js script file and assign value from the view like this:
In the view:
<script>
var labelButtonDelete = #UserResource.ButtonDelete;
</script>
In the js file:
alert('The text for my button is ' + labelButtonDelete);
What is the best way to pass data from razor to js file? Do you have another alternative?
Thanks anyway.
I've been using something like your second approach for some time without any issues. The only difference is that I'm using a singleton in my JS file to avoid polluting the global javascript namespace.
But if you will be doing more serious client side stuff, your Javascript code will follow a more object oriented structure, and from there you almost automatically get a single initialization/constructor path where you can pass your localized values.
That RazorJS looks nice, but I'm not sure if I'm comfortable mixing Javascript with Razor. Might do it for a small project, but I can see it becoming really messy if you have lots of Javascript files.
After all, I still consider the resources/localization code to be related to the view. The Javascript should only implement functionality in my opinion.

What is the best way to organize JS code in webapps where the main "meat" is still server side?

When building webapps with MVC web framworks like Django, Kohana, Rails and the like, I put together the application without JS-driven components initially, and then add them afterwards as "improvements" to the UI.
This approach leads to non-intrusive JS, but I don't have a good "standard" way of how to go about organizing the JS work. Most of the JS I write in apps like these are 10-30 line JQuery snippets that hook into some very specific part of the UI.
So far I often end up inlining these things together with the part of the UI they manage. This makes me feel dirty, I'd like to keep the JS code as organized as the python / php / ruby code, I'd like for it to be testable and I'd like for it to be reusable.
What is the best way to go about organizing JS code in a setup like this, where we're not building a full-blown JS client app, and the main meat is still server side?
I am also very interested in what other people have to say about this. The approach I've taken is to use object literal notation to store the bulk of the function, and store these in one file included on all pages (the library)
uiHelper = {
inputDefault:function(defaulttext){
// function to swap default text into input elements
},
loadSubSection:function(url){
// loads new page using ajax instead of refreshing page
},
makeSortable:function(){
// apply jQuery UI sortable properties to list and remove non javascript controls
}
}
Then I include a .js file on any page that needs to use the library that ties the elements on that page to the function in the library. I've tried to make each function as reuseable as possible and sometimes the event binding function on the page calls several of my library functions.
$(document).ready(function(){
$('#mybutton').live('click',uiHelper.loadSubSection);
//more complicated helper
$('#myotherbutton').live('click',function(){
uiHelper.doThisThing;
uiHelper.andThisThing;
});
});
edit: using jsDoc http://jsdoc.sourceforge.net/ notation for commenting for these functions can produce documentation for the 'library' and helps keep your code easy to read (functions split by comments).
The following question is along similar lines to your own - you should check it out...
Commonly accepted best practices around code organization in JavaScript
When dealing with JS code, you should first analyze whether it will be used right away when the page loads. If it's not used right away (meaning the user must do something to invoke it) you should package this into a JS file and include it later so the load time is perceived faster for the user. This means that anything that the user will sees should go first and JS related to the functionality should be imported near the end of the file.
Download this tool to analyze your website: http://getfirebug.com/
If the JS code is small enough, it should just be inline with the HTML.
Hope that helps a bit.
For quick little user interface things like that I put everything into a single javascript file that I include on every page. Then in the javascript file I check what exists on the page and run code accordingly. I might have this in UIMagic.js for example. I have jQuery, so excuse those jQuery-isms if they aren't familiar to you.
function setupMenuHover() {
if ($("li.menu").length) { // The page has a menu
$("li.menu").hover(function() { ... }, function() { ... });
}
}
$(setupMenuHover);
function setupFacebookWizbang() {
if (typeof FB != "undefined") { // The page has Facebook's Javascript API
...
}
}
$(setupFacebookWizbang);
I've found this to be a sane enough approach.
My preferred method is to store inline javascript in it's own file (so that I can edit it easily with syntax highlighting etc.), and then include it on the page by loading the contents directly:
'<script type="text/javascript">'+open('~/js/page-inline.js').read()+'</script>'
This may not perform well though, unless your templating library can cache this sort of thing.
With Django you might be able to just include the js file:
<script type="text/javascript">
{% include "js/page-inline.js" %}
</script>
Not sure if that caches the output.
If you are still worried about being 'dirty', then you could check out the following projects, which try to bridge the server/client side language mismatch:
http://pyjs.org/ (Python generating JavaScript)
http://code.google.com/webtoolkit/ (Java generating JavaScript)
http://nodejs.org/ (JavaScript all the way!)

Categories

Resources