I am moving all my javascript out of my views, and into separate .js files. But I am facing one issue.
Some javascript references a model parameter:
var data = #Html.Raw(Model.RunningTotalData)
#Html, and probably Model... isn't available in the js files.
One solution might be, in the <div> that the code is working with, create a data- type field? And populate it on the view, and then the js code somehow reads that data?
At the moment, the js is rendering a graph on a div, defined as:
<div id="allbalancediv" style="width: 100%;"></div>
Could I add a data-xxx there, and then refer to that data field in my js code? I'm not sure if that's the right way to go, or if there's a better option.
You obviously can't render server side content into static javascript files. But you can still render a script tag that sets up data for your JS files.
// View
<script>var data = #Html.Raw(Model.RunningTotalData)</script>
<script src="/frontend.js"></script>
Or a data attribute that gives your JS code an id to fetch via AJAX from a JSON api would work too.
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.
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?
I am trying to implement D3 graphs and charts in a FileMaker solution. I am stuck on loading a JSON file properly to be used in D3 code displayed in the webviewer.
I am loading all JS libraries into global variables ($$LIB.D3.JS, $$LIB.JQUERY.JS, etc.). Then I am placing the HTML code on the layout (giving an object name, i.e. html). The web viewer grabs the HTML code (from a text box on the layout) and JS code (from global variables) to render the page. This all works fine. (I am using this method detailed here: https://www.youtube.com/watch?v=lMo7fILZTQs)
However, the D3 code I have uses the getJSON() function to get a JSON, parse the data and create the visualization. I can't figure out a way to get the JSON file as a file from within FileMaker. I could put the content of the JSON file into a FileMaker variable and feed that into the HTML, but I then would not be able to use getJSON(). I would have to redo the D3 code to get the data from a JS variable and parse the data from the variable.
Is there a way for me to load a JSON file so FileMaker could use it to render the visualization properly in the WebViewer.
You have two options.
1. Calc the JSON into the HTML as you mentioned. Your right you will have to change how you load the JSON with d3. But its not tough. When you load the JSON from disk, using something like d3.json('/data.json', callback) you are just loading the json and then giving it to the callback function. If the JSON is in the HTML page in a something like var embeddedJSON You can just call the callback directly with the embeddedJSON like
callback (embeddedJSON)
Your code may look more like this.
d3.json('/data.json', function(data){
// bunch of d3 code
})
The callback in this case is an anonymous function. You can change it like this.
var render = function(data){
// bunch of d3 code
})
// then call render with your json variable that you embedded into the html
render ( embeddedJSON )
That will work just fine.
2. Export the html page to the temp directory, and export the json file with the data into right next to it. Then display the html using a file://url. In this case you can use d3.json(/data.json, callback ) and that will work just fine too.
Each of these methods have their pros and cons, but they both work.
In most cases, the best practice for integrating javascript or other assets in a Webviewer is to push assets to the temp directory (get this using GetTemporaryPath() in FileMaker), you can then export assets directly to named files. Once this is done, you can reference these files in your code using the file:// protocol.
This has numerous advantages over older methods, such as loading everything into global variables. One of the biggest of these is that provided you load your JSON into a discrete file and don't "pollute" any other files with FileMaker data, you can work entirely in the code environment of your choice, then simply move web JavaScript libraries, html, CSS, and other assets directly into your FileMaker solution.
I want to Send data via AJax call to serlvet, the serlvet will return some result based to which I will redirect to a page.
So where do I add this global .js file i.e the file that contains the AJAX call. PLEASE NOTE I'M USING PREDEFINED FORM COMPONENT AND A PREDEFINED TEMPLATE(Form Template) SO I CAN'T DO STUFF LIKE <cq:include clientLibs> to add .js file, as I don't have source code of component(form template).
I found a link where we add a global JS but I don't have this option in my CQ5 instance. So Weird.
http://www.sfu.ca/itservices/cms/howto/advanced/style-a-page/customjavascript.html
Am not sure of this custom style-sheet and JavaScript section. Might be they would've customized the page properties as i too don't find them in CQ 5.4 / 5.5.
Though you may not be able to include your custom CSS and JS in JSP using <cq:includeClientLibs>, you can make them as part of the clientlibs that is getting included in the form or the page component.
i.e. You can create a cq:clientLibrary folder that has the categories property set to the same value which is being included in the page.
But, it is recommended to be cautious while trying this way, as your JS would be available in all the pages where this client library is included, and hence try to write the script as specific as possible so that it doesn't affect the rest of the functionality.