How to call a Python function from an external JS file? - javascript

I was using some Javascript stuff for an uploader on a webpage, to test it I wrote it inline with the HTML (I know). I'm using Flask with Jinja2 templates so to connect my uploader(it just acts like a form) to the upload function in my Python, I just had
url: "{{url_for('upload_file')}}",
in the inline Javascript, because this could be referenced within the scope of the template. Now I've moved my JS to an external file and just included it in the HTML like so:
<script type="text/javascript" src="{{ url_for('static', filename='uploader.js') }}">
</script>
How can I call my Python function from the external js file? Is there some way of initializing it in the template and passing it in, or am I missing something really elementary here?
Edit: I ended up doing it a little different:
<script>
var link = "{{ url_for('upload_file') }}"
</script>
<script type="text/javascript" src="{{ url_for('static', filename='uploader.js') }}">
</script>

As you say, you need to do this in the main file. Inside a script tag, you can define an object in the global scope, and set attributes to the results of your template calls. You can then refer to the object in your script file.
Edit
There's no special syntax: this is just standard Javascript.
<script type="text/javascript">
template_vars = {
url: "{{url_for('upload_file')}}",
// etc
}
</script>
and now your other script can access template_vars.url etc.

Related

JavaScript only runs when both the code is inside the HTML and is called externally with <script src=...>

My JavaScript code only runs when the code is both inside the HTML file and called externally via
<script type="text/javascript" src="{{ url_for('static', filename='index.js') }}"></script>
<script>
var scroller = document.querySelector("#scroller");
...
</script>
I am using Flask and Jinja, with a file structure of:
/app
/static
index.js
/templates
base.html
myfile.html
routes.py
__init__.py
...
The code inside index.js is the exact same code between the <script> tags inside the HTML.
In terms of jinja and using block tags, base.html:
<body>
{% block content %}
<!-- typical HTML stuff here -->
{% endblock %}
<!-- some Bootstrap tags -->
<script ... ></script>
{% block script %}{% endblock %}
</body>
myfile.html:
<body>
...
{% block script %}
<script type="text/javascript" src="{{ url_for('static', filename='index.js') }}"></script>
{% endblock %}
<script>
...
</script>
The code itself works, and it worked not too long ago without this issue; I don't know what I changed to cause this, nor can I even imagine what could cause this. If there is more code that is required, I can easily share it.
Is there something I not understanding?
To note: I have had a similar issue trying to including external JavaScript code inside my HTML; at one point it wouldn't work, then it did, now it behaves the way I have described.
To further note: I have another .html file with its own external .js file that works fine.
Mr.#JakeJackson, Script in externl file never requires the same content to be available inside your inline code.
May be you are trying to process some elements and your script got executed before those elements are mounted to the document object.
A lazy solution to that problem is moving the external file linking tag to the bottom your HTML.Body.
OR
You can use defer attribute to your script element https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script
OR
If you have some libraries like jQuery included in your page, You can use the document.ready implementations in that
OR
you can implement your own document.ready like below
function myReady() {
return new Promise(function(resolve) {
function checkState() {
if (document.readyState !== 'loading') {
resolve();
}
}
document.addEventListener('readystatechange', checkState);
checkState();
});
};
myReady().then(function() {
// Put your app custom code here
});

Why can't I use Jinja in Javascript for a django site?

So for those of us who use Python and Django framework to develop a website, there is this awesome tool known as jinja which can be used as a template engine. For example:
Instead of hard-coding an import like this:
<script src="assets/js/onebutton.js"></script>
We can do this:
<script src="{% static 'assets/js/onebutton.js' %}"></script>
In this case, it automatically searches for a folder named static and goes inside to look for the needed code.
But why isn't it possible to use jinja template in Javascript.
For example:
homepage.html
<script src='whatever.js'></script>
<p>Another example</p>
<button id="clickme"> click me </button>
whatever.js
$(function()
{
$('#clickme').click(function(){
$.ajax({
headers : {'X-CSRFToken': getCookie('csrftoken')},
type: "POST",
url: '{% url "func" %}', //<--Problem arise here
datatype:"json",
data: {},
success: function(data){
var new_template = '<h1> %firstmsg% </h1>';
var new_frontend = new_template.replace('%firstmsg%',data.message);
console.log(new_frontend);
document.getElementById('wor').innerHTML+=new_frontend;
}
});
}
}
Django would recognize the url in the AJAX request as /'{% url "func" %}' instead of /func
The only way to solve this is to move the entire code from whatever.js into the homepage.html in a <script></script> block.
Perhaps we need to import something for Jinja templating to work?
<script src="{% static 'assets/js/onebutton.js' %}"></script>
In this case, it automatically searches for a folder named static and goes inside to look for the needed code.
This is inaccurate. All it does is it converts the given path to the static path provided in your settings file like this - /static/asssets/js/onebutton.js. That is it. Django or Jinja2 doesn't go through the folder and look for the file. It doesn't even care if file exists or not.
Later, the browser automatically fetches this file from the server when it receives the html document.
Coming back to your original questions about why you can't use Jinja2 or Django template syntax in your JS files. Well, you can. But you'll have to render your JS files from your views.
Now, I'm sure you're using the render function to return a template from your views. But what does it do?
The render function converts the django specific template tags into proper html content.
So, if you're using django's or jinja's template syntax in your js files, you'll have to render your js files too. But that seems like a bad idea. Instead, you can create some global variables in your html files, and use them in your js files.
<!-- define required variables in template -->
<script>
var URL = '{% url ... %}';
var OTHER_VARIABLE = '{{ other_variable }}';
</script>
<!-- include your js files -->
<script src="/path/to/file.js"></script>
I have a workaround for this kind of necessities. Put your js code inside <script></script> tag and save it as html file inside templates folder.
Now you can include your html file to your page.
{% include 'myapp/js_code_with_jinja.html' %}
All jinja code will work as expected.

Laravel does not evaluate the curly brackets when including .js file

I have a js file with the following script
alert("{{ route('contacts.show',':contactid:') }}");
I used the .js file and include it in my blade view
<script type="text/javascript" src={{ asset('admin/js/contact/test.js') }}></script>
But if I write the script in the blade view. It does evaluate the codes inside the curly brackets.
The JS file is not processed by PHP, so the Laravel blade templates would not be in effect in the JS file. What you should do, is define the route in a variable in JS ON THE PHP PAGE by injecting the route value into a JS variable. Then you can access that variable in your JS file.
<!DOCTYPE html>
<html>
<head>
<title>Page</title>
</head>
<body>
<script>
// Inject the PHP route value into a JS variable.
window.route = '<?php echo route("contacts.show",":contactid:"); ?>';
// You can also use 'let route = ...' to declare the variable.
</script>
<script src="./main.js"></script>
</body>
</html>
main.js:
alert(route);
Curly brackets are executed only when inside a blade file. If you need to keep the JS external and not merge the code into a blade template, you could define a JS variable in blade, in the global JS scope, load the external JS after it and then use that variable in your js.
in blade
<script>
var contactsRoute = ""{{ route('contacts.show',':contactid:') }}"";
</script>
<script type="text/javascript" src={{ asset('admin/js/contact/test.js') }}></script>
In the external js
alert(contactsRoute);

Laravel 5 : including javascript files

First off, I have to precise that I'm quite new to Laravel and that I have a lot to learn.
In one of my controller I need to call a Javascript function. To do so, I simply
echo "<script>triggerPixel();</script>";
I'm just unsure about where to store my Javascript file containing that function.
From what I got for the moment is that I should use elixir to add a file with something like this in the gulpfile.js :
mix.scripts('myscript.js');
Is this the right way to do it or should I simply add a file in resources/assets/javascripts ?
I'm a bit lost and some explanation would be welcome.
Thanks !
Put your actual .js file inside public/js folder
and then, put all your js reference in one file, for example footer.blade.php inside the resources/views folder.
Inside footer.blade.php :
<script src="{{ URL::asset('js/jquery-3.2.1.min.js') }}"></script>
<script type="text/javascript" src="{{ URL::asset('js/custom.js') }}"></script>
<script type="text/javascript" src="{{ URL::asset('js/app.js') }}"></script>
and then just call the footer inside one of your blade view using: #include ('footer')

Why I can't type any letter if I separate the .js file?

Actually I was trying to get the concept of the module pattern. Here I have simple code which I used to type directly on the page. It was fine until I tried to separate the actual code from the HTML file and kept only a single line of code on the main HTML file:
<body>
<script type='text/javascript' src='module.js'>
// module.JS file was here ....
document.body.addEventListener('keypress',function(e){module.show(e.keyCode)});
</script>
</body>
File module.JS
var module = (function() {
return {
show:function(keyCode){
document.body.innerHTML+=(String.fromCharCode(keyCode));
}
};
})();
You'll need to have two <script> elements for this.
Use one to "import" your external module and another for the script you want to embed directly on the page:
<script type='text/javascript' src='module.js'></script>
<script type='text/javascript'>
document.body.addEventListener('keypress',function(e){module.show(e.keyCode)});
</script>
For more information, you can check out this MDN documentation page. Here is an excerpt talking about the src attribute (emphasis added):
This attribute specifies the URI of an external script; this can be used as an alternative to embedding a script directly within a document. Script elements with an src attribute specified should not have a script embedded within its tags.
A script block referring to an external JavaScript source should be separate and any script inside of it does not get executed. So you need two separate script blocks one for the external JavaScript file and the other for your script.
<script src='module.js'></script>
<script>
document.body.addEventListener('keypress',function(e){module.show(e.keyCode)});
</script>

Categories

Resources