I'm writing a Django app and while somewhat familiar with Django I'm pretty unfamiliar with JavaScript. I'm adding a few lines of JavaScript into one of my pages in order to include a map.
The script simply encompasses initializing the map and then adding markers according to information saved in my database.
Given that there is so little code, would it still be considered bad practice to leave the script in the HTML template and pass information from my database using {{info}}?
If so, what method would you consider to be better?
I assume what you're suggesting is putting both the JS script and its required data into the template (the data being injected into the JS script through string interpolation)
You can see how this can get quickly out of hand. Below I provide levels of code organization, in approximate ascending order (the further you go to better, in general)
1. Include your JS using a script tag, not embedded into the HTML
First: putting the JS into its own .js file and including it via <script> tag is easy. So let's do that. Moreover, modern browsers can load files in parallel, so it's a plus to load the HTML and JS files simultaneously.
2. Avoid feeding the data into the JS using a Django template
Now the other problem I've seen people do is pass the data into the JS using a <script>data = {"info": "something"}</script> before including their JS code.
Which isn't ideal either for many reasons, stemming from the fact that the data is being string-interpolated in the Django template:
3. Make JS pull the data through a Django (REST) API
However since you said you are familiar with Django, I'd like to suggest you create a view that returns the data that your client side JS needs in JSON format. E.g. something that returns {"info": "something"} on /api/info.
There's lots of ways to achieve this, here's a start (albeit might be outdated)
Then I'd have the script.js file read the data with a simple HTTP GET call. Lots of JS libraries can do this for you easily.
Some advantages of this approach
Your code (the JS part) is independent from the data part (the JSON data)
You can easily view/test what's being fed into your JSON, since it's just a HTTP GET request away
Your HTML/JS part is completely static and hence cachable which improves the performance of loading the page.
The Python data conversion to JSON is pretty straightforward (no interpolation kung-fu)
Yep that's bad practice.
Consider defining static folder for your app as described on official django documentation page: Managing static files and upload your js via static template tag.
You could get data which in {{ info }} variable by creating separate django view which would return JsonResponse and then perform AJAX Request to fetch desired data from newly createdd js file.
In my Django projects, if I am using a "base" template that every other template extends, I just put a block called "extrahead" inside of the <head></head> in the HTML.
<html>
<head>
........ other header stuff
........ include other scripts
{% block extrahead %}
{% endblock %}
</head>
.............
</html>
... and then use that block just in the template you want the map on. That is assuming that it is just static js code?
Related
I was tasked to create a javascript library.
The role of this library is to create a complex form with multiple choices/steps on any website. (It means that we don't have access to the website where the form is deployed.)
The code to use the library is the following :
<body>
<div id="container"><!-- Here should be inserted my HTML form --></div>
</body>
<script src="http://wwww.example.com/path/to/myLibrary.js"></script>
<script>
(function() {
var dom = document.getElementById('container');
var mb = new MLibrary(dom);
mb.initialize();
})();
</script>
Once filled, this form is finally sent to our API endpoint where it is treated.
Because of the complexity of the form, I need to create a huge amount of element using javascript. The HTML source code of the form is ~600 lines of HTML
Having this much HTML inside a .js file has proved to be ridiculously hard to maintain and horrible to read.
Because of performance purpose, I was required to avoid AJAX request as much as possible which means that I should avoid to store the HTML on the server and get it through AJAX.
If you can't use AJAX to get HTML, how can you handle a large amount of HTML inside a javascript library in order for it to be maintainable ?
I've created a very basic version of this library using JSFiddle :
https://jsfiddle.net/xd4ojka2/
I faced the same problem awhile back. Basically, I had to bundle my html with my js with Webpack. In development, all code lives in it's own file: html inside .html, js in .js, less or sass in their respective files. Then Webpack will build the app by combining all these files, giving me a build.js file (the name is configurable).
That file might be bigger than your average JS file, but it has all the stuff your app needs, meaning no AJAX to fetch HTML, or other parts of the app. Since this file will be kept in browser's cache, you need to implement a cache busting (outside of the scope of this question).
You could programmatically create HTML tags using JSON input on the fly. The JSON input for generating the markup can be retrieved using AJAX calls or stored in LocalStorage on app initialization or be lazy loaded.
I'm trying to figure out how to organize my javascript/django code.
So far I used to put my javascript page specific code in the same file. i.e I embed javascript in a <script> tag inside the template.
This creates a lot of mess when my JS code become large:
- django template variables {{var}} inside my JS code does not look well,
- I get an error when I try to minify it with tools like this one: http://jscompress.com/ ,
- And I just try to separate them as much as possible.
Today, in my embeded <script> tag my JS code looks like:
var app = {
func: function() {
// can I use the {% url %} tag here ?
$.post('/url/', {csrfmiddlewaretoken:'{{csrf_token}}', something:'value'} )
},
jsonFromServer: '{{pythonDict|safe}}', // I need this data structure,
};
As you can see, there are some values I need to pass form django to javascript, the most common is the csrftoken, for ajax requests. But sometimes I also pass a json dictionary that is needed for the app itself. Sometimes I want to pass the server time as well.
I'm thinking of moving the JS code to a separate file, I read that it is better way to organize like that. But I can't see how it is possible in a normal django app, without django have to render the .js files. And I believe it is better the JS file won't be served by django?
So how could I organize my JS without too much django code in it ?
I Don't know if it's "beautiful" but usually, I organize my code like that when it's about make web dev in MVC:
I put my <script> tag in the template of my page.
I write my js in an external file, traditionally in the /static/JS/my_template_name.js
As my gobal layout can have some JS code too, I make a great use of the JS modules: https://medium.freecodecamp.com/javascript-modules-a-beginner-s-guide-783f7d7a5fcc#.bjf4xwuq4
Usually, I don't have to do that.
When I need var from server in my js code, I make some Ajax calls.
But if you really want to process like that, I can suggest you to do something like this in your template:
<script>
var from_server = {{vars_from_server}};
</script>
Normally, if you pass a variable named vars_from_server to your template it will replace the placeholder between the script tags. Just think to format "vars_from_server" in a correct JS way.
After that, you will be able to access your vars in your scripts by accessing from_server variable from anywhere.
Currently I am creating a website which is completely JS driven. I don't use any HTML pages at all (except index page). Every query returns JSON and then I generate HTML inside JavaScript and insert into the DOM. Are there any disadvantages of doing this instead of creating HTML file with layout structure, then loading this file into the DOM and changing elements with new data from JSON?
EDIT:
All of my pages are loaded with AJAX calls. But I have a structure like this:
<nav></nav>
<div id="content"></div>
<footer></footer>
Basically, I never change nav or footer elements, they are only loaded once, when loading index.html file. Then on every page click I send an AJAX call to the server, it returns data in JSON and I generate HTML code with jQuery and insert like this $('#content').html(content);
Creating separate HTML files, and then for example using $('#someID').html(newContent) to change every element with JSON data, will use even more code and I will need 1 more request to server to load this file, so I thought I could just generate it in browser.
EDIT2:
SEO is not very important, because my website requires logging in so I will create all meta tags in index.html file.
In general, it's a nice way of doing things. I assume that you're updating the page with AJAX each time (although you didn't say that).
There are some things to look out for. If you always have the same URL, then your users can't come back to the same page. And they can't send links to their friends. To deal with this, you can use history.pushState() to update the URL without reloading the page.
Also, if you're sending more than one request per page and you don't have an HTML structure waiting for them, you may get them back in a different order each time. It's not a problem, just something to be aware of.
Returning HTML from the AJAX is a bad idea. It means that when you want to change the layout of the page, you need to edit all of your files. If you're returning JSON, it's much easier to make changes in one place.
One thing that definitly matters :
How long will it take you to develop a new system that will send data as JSON + code the JS required to inject it as HTML into the page ?
How long will it take to just return HTML ? And how long if you can re-use some of your already existing server-side code ?
and check how much is the server side interrection of your pages...
also some advantages of creating pure HTML :
1) It's simple markup, and often just as compact or actually more compact than JSON.
2) It's less error prone cause all you're getting is markup, and no code.
3) It will be faster to program in most cases cause you won't have to write code separately for the client end.
4) The HTML is the content, the JavaScript is the behavior. You're mixing both for absolutely no compelling reason.
in javascript or nay other scripting language .. if you encountered a problem in between the rest of the code will not work
and also it is easier to debug in pure html pages
my opinion ... use scriptiong code wherever necessary .. rest of the code you can do in html ...
it will save the triptime of going to server then fetch the data and then displaying it again.
Keep point No. 4 in your mind while coding.
I think that you can consider 3 methods:
Sending only JSON to the client and rendering according to a template (i.e.
handlerbar.js)
Creating the pages from the server-side, usually faster rendering also you can cache the page.
Or a mixture of this would be to generate partial views from the server and sending them to the client, for example it's like having a handlebar template on the client and applying the data from the JSON, but only having the same template on the server-side and rendering it on the server and sending it to the client in the final format, on the client you can just replace the partial views.
Also some things to think about determined by the use case of the applicaton, is that if you are targeting SEO you should consider ColBeseder advice, of if you are targeting mobile users, probably you would better go with the JSON only response, as this is a more lightweight response.
EDIT:
According to what you said you are creating a single page application, if this is correct, then probably you can go with either the JSON or a partial views like AngularJS has. But if your server-side logic is written to handle only JSON response, then probably you could better use a template engine on the client like handlerbar.js, underscore, or jquery templates, and you can define reusable portions of your HTML and apply to it the data from the JSON.
If you cared about SEO you'd want the HTML there at page load, which is closer to your second strategy than your first.
Update May 2014: Google claims to be getting better at executing Javascript: http://googlewebmastercentral.blogspot.com/2014/05/understanding-web-pages-better.html Still unclear what works and what does not.
Further updates probably belong here: Do Google or other search engines execute JavaScript?
I am currently working on cleaning up a little web app I've written in Mojolicious. As part of that cleanup I am separating out my javascript into the public directory from my html.ep files.
The problem I have though is I don't seem to be able to reference tag helpers any more, like 'url_for' or even referencing values in the stash such as '<% $stashvalue %>'.
Any idea's on how or if I can do this is very much appreciated.
cheers.
The stuff in the public directory is served statically, optimally by your webserver, not by Mojolicious or Plack, so that file does not get processed by Mojolicious, thus <% $stashvalue %> not meaning anything.
A solution would be to embed those parts of javascript that need to access server side variables in the mojo templates - rather ugly, but less code to be written.
Another one would be to make an ajax call from your javascript files, when they are loaded, and get the values sent by the server - more elegant, but more code to be written.
Another one that I can think of, would be to move those javascript files under a folder that gets processed by Mojolicious and include them parameterized - in your html.ep file that needs that js file, do :
<script type="text/javascript" src="http://example.com/url/served/by/mojo/?param1=<% $stashvalue %>¶m2=<% $stashvalue2 %>"></script>
And, in the controller that responds to /url/served/by/mojo/, render that js file, with the params replaced by the ones from the query. As an alternative, you could store/receive those params also on the session
As usually in Perl, there is more than one way to do it.
What I typically do is encapsulate most of my javascript in function calls or objects in pure javascript files. Then in my templates I include those pure javascript files and use the api that I built in those files from the template, interpolating the server-side variables into the arguments of the functions. You can peruse the code for Galileo to see several examples.
For example, see how this template passes stash values to this pure javascript file's functionality.
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.