Defining Django context variable in Jquery giving me error? - javascript

I am trying to use a django context variable in my jquery script.
First of all, this WORKS:
index.html
<head>
<script type="text/javascript">
var page_size = {{page_obj.paginator.num_pages}};
</script>
<script type="text/javascript" src="{% static 'js/paginate.js' %}"></script>
</head>
js/paginate.js
$(document).ready( function() {
alert(page_size); //THIS WORKS!!!
});
However, I didn't want the users to be able to be view my variables so I simply added the global variable declaration in my "paginate.js" file:
index.html
<head>
<script type="text/javascript" src="{% static 'js/paginate.js' %}"></script>
</head>
js/paginate.js
var page_size = {{page_obj.paginator.num_pages}}; //Exactly the same as the above!!
$(document).ready( function() {
alert(page_size); //ERROR!!!
});
Strangely enough, this gives me an error:
SyntaxError: invalid property id
var page_size = {{page_obj.paginator.num_pages}};
I have no idea why the first one works while the second one gives me an error, because they are exactly the same... Maybe because I'm second one is declaration in Jquery..?? Any idea??
Thanks..

TL;DR
You can't pass a variable to a static files because they aren't parse by the Django template processor.
Explanations
Your first example works because you set the {{ page_obj.paginator.num_pages }} in your template, which will be parsed and transform into a number. When you're returning a template with Django (through any render method), only the template will be rendered. CSS and Javascript linked in your template are called static files: that means they're ressources which will not be read by the Django template processor.
Imagine that you want to insert your variable in an img in your page. Does it makes any sense? No? However, it's the same behavior.
How to do this then?
You can get the data either via an AJAX request in your Javascript file (warning: a bit overkill for your case here), or using your first method.
Related topic:
Passing Python Data to JavaScript via Django
Passing parameters to the Javascript code on a page using django templates?

In Django, if we need to pass variables from a view to a JS/html file, we'll have to ensure that the file is parsed by the django template engine. In other words the file has to be served by Django.
Whereas here, the included Javascript isn't processed by the Django template processor on the server, so that won't work.
If you need to pass template variables to be used in JS files, then you have to use the first method mentioned in the question i.e. create a small <script> block wherein some global variable is declared to contain those template variables. Then, any JS file can get the values by looking for the global js variable.

Related

Using Ruby Variables in JavaScript

I'm new to Ruby so I had a question in regards to using some variables throughout my codebase. I have a variable declared in my Ruby file as follows:
#pages = 350
Now, I know that in HAML, I can simply do:
-if #pages = 350, and in HAML with inline javascript, I can do something like:
:javascript
console.log("#{#pages}");
However, I am linking an external JavaScript file in my HAML document, and I was wondering if it would be possible to use my Ruby variables in my external JS document? I need some variables in order to build what I am trying to build. Thanks!
Update as per one of the answers:
In my HAML file, I have the following:
:javascript
printPages(3);
In my external JS file, I have:
$(function() {
window.printPages = function(pages) {
console.log(pages);
}
});
I you are loading static javascript files I really would not recommend trying to insert variables into that code.
Instead, think about how you would provide that to your javascript code.
You could send it to that code as an argument.
<script type="text/javascript" src="./my-external-script.js"></script>
:javascript
runMyExternalFunction(#{#pages})
Or you could add the variable as a data attribute on your page, and your javascript could look for that when it loads.
Haml:
%body data-pages=#pages
JS:
console.log(document.body.dataset.pages) // value of #pages
Update about your javascript:
Using jquery's on page ready event $() for declaring the function is a bad idea. That means that it waits for everything on the page to be compeletely loaded, and then declares the function your page needs.
What you should be doing is setting up all the function that will be needed right away, and then calling those functions when the page is loaded.
They way you have it, the page loads, printPages() is executed (which doesn't exist yet), and then after all that printPages is created and put into the global scope.
So remove the $() from your external script and add it to your HAML instead.
In fact, if your aren't doing anything super fancy with transpiling or bundling, then you can simply declare the function in your external JS file, and it will be available globally. This doesn't work with your code because they way you've declared the function, it would only be available to code within that $() callback.
// js file
function printPages(pages) {
console.log(pages);
}
HAML:
$(() => {
printPages({#pages})
})

How to access a variable among multiple javascript files

Currently i have 2 html pages and 2 java script pages,say
h1.html,h2.html
j1.js,j2.js
where can i declare a variable so that the variable can be accessible between both of java script and html files
i want to initialize a value to that variable in first java script file and access that value in the second java script file
if you want to access variable values across two html files even after the page loads you can use localStorage in js.
say if you want to set a value for a variable localStorage.setItem("newvariable", 'variablevalue'); and for getting value use this var getValue = localStorage.getItem("newvariable");
EDIT:
for your base question refer those js files one by one
<script src="j1.js"></script>
<script src="j2.js"></script>
you can declare the variable in any javascript file, and just include the file next to the other javascript file forexample.
// for example if you have file1.js like this.
var myvalue = 25;
You can then save this file and include it in your main or other html files for example at the bottom of your html document.
<html>
<body> </body>
<script src='file1.js'></script> // put the javascript file with your variable declaration on top of the other file you want to access the value from.
<script src='file2.js'></script>
</html>
after the above you can then just print the variable in 'file2.js' like this.
// inside file2.js
console.log(myvalue) // which was declared in the 'file1.js'
hope this helps.
You can bring your javascripts in to the <head> of your html then you can refer to the javascript as a function passing values as a parameter and returning data as well.
PS Don't forget to declare the javascript on your form.

Use TAL:defined variable in javascript

I'm creating a page template for a plone-based website. I've defined some variables using the template attribute language:
<tal:macro metal:define-macro="sample" tal:define="var python: here.getThisVar();">
Now I would like to use var in an extern javascript file, that I call by clicking a button inside my template. How can I transfer my variable, that I can work with it in my javascript file?
In your template define a javascript variable by writing it out using TAL like this:
<script type="text/javascript" tal:content="string:var MY_VAR=${view/myVar};"></script>
Now MY_VAR should be available in scope of your external js as long as you call it after the line above...
Another way: inject your variable into HTML using an HTML 5 data attribute::
<div id="myVar" tal:attributes="data-myVar python:here.getThisVar();">
Then read it using JAvaScript/jQuery::
$('#myVar').data('myVar');
There are a variety of ways to do it. All involve constructing Javascript code as if it's text, then returning the result for insertion into a page or rendering as a JS resource in the javascript registry.
If you'd like a robust example that includes provisions for message translatability and works with the JS resource registry, see the way Plone itself does it: https://github.com/plone/Products.CMFPlone/blob/4.2.7/Products/CMFPlone/browser/jsvariables.py

Is there a way to send variables to javascript files?

is it possible to do something like this
to send the value id=3 to the js file
<script src="http://site.com/js/loader.js?id=3" ....
otherwise what's the approach to do that?
No, that won't work.
Just set the variables before you load the file:
<script>var id = 3;</script>
<script src="http://site.com/js/loader.js" ....
Since all the scripts share a global namespace, you'll be able to access the id variable from inside your loader.js file.
Of course you should think about the style and implications of using global vars to achieve that. Using a global object that hold these config variables might be a cleaner approach.
If that is just a javascript file, you can just define the variable before load it.
<script>
var id = 3;
</script>
<script src="http://site.com/js/loader.js" ....
It would work, but not if your .js URL is just for a static file. If you wrote server-side code that output JavaScript, then you could output custom JavaScript based on the query string.
This is probably overkill for what you're trying to achieve.
k so this question has pretty much been answered. But there is another approach, which may or may not be suitable for you. If you want to render script conditionally or fetch a certain script for a certain id. You can declare it in a serverside script
http://site.com/js/loader.js.php?id=1
In the loader.js.php
Just use the following line in the beginning
<?
header("Content-type: text/javascript");//To declare it is a javascript file
$id=$_REQUEST['id'];
?>
//Normal js continues after this
//When you need to use the variable, just use
var id=<?=$id?>

Function Undefined: Must a javascript function be defined within the same file?

I've got a file notifications.js containing one event bound to an element, and a function updateNotification(). This function uses jQuery to update certain elements on the page when a JSON object is passed as a parameter.
The problem:
I'm attempting to call this function within the page (via <script> tags), however rather than calling it, it breaks the page. I did some digging around within the Chrome Developer Console (not sure of the name), and an error is flagged:
/pleaseshare/views/install/:50 Uncaught ReferenceError:updateNotification is not defined
However, when I pan within the console, I can clearly see the file notifications.js listed under scripts, and the function is defined there. If I define the function within the current scope (e.g. the line above the call), it works fine.
What I've tried
The function contains some javascript that requires jQuery, so I've attempted both with and without encasing it in $(document).ready( function() {});, with neither seeming to have any affect.
I'm pretty stumped.
For good measure, here's a link to show the structure of my javascript and html: http://snippi.com/s/znk6xe9
Any help in figuring out why this is happening, or explanations of why javascript functions cannot be called cross-file (although I'd hope this isn't the case), would be greatly appreciated ;)!!
A function cannot be called unless it was defined in the same file or one loaded before the attempt to call it.
A function cannot be called unless it is in the same or greater scope then the one trying to call it.
You code looks like the structure should work, but is clearly a reduced test case that has been reduced to the point where it won't.
Got it working. The issue was definitely multi-faceted, but I figured it out.
First off the use of RequireJS had an impact on updateNotification(), in that it couldn't be called cross-file, and was therefore considered undefined. I assume this because of how RequireJS loads files, and I'll look into the documentation later (and post an edit if I find anything relevant).
Secondly, updateNotification() would again be considered undefined when encased within jQuery's DOM ready loader $(document).ready(function(){}). However updateNotification() contains executions which require jQuery, so I had to encase the contents of the function in $(document).ready(function(){}).
This is an issue very unique to RequireJS/jQuery, hence why in most use cases this wouldn't occur.
Side note: The tags are edited to reflect this.
you need to import your script into your page:
<script type="text/javascript" language="javascript" src="path/to/notifications.js"></script>
This needs to be added above the <script> tag that calls updateNotification()
Functions do not need to be declared in the same file. In fact, avoiding having every declaration dumped into the global namespace is usually a concern in JavaScript.
In the sample code in the link you provided, updateNotification is declared as a global, so there should not be a scoping problem.
However, in the same sample, you don't show notifications.js being included. You need to import it using a <script></script> element and that element must come before the script element that includes the call to updateNotification. You also must include jQuery before notifications.js, since it uses jQuery. So you need something like:
<body>
// One or two elements
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="notifications.js"></script>
<script type="text/javascript">
$(document).ready( function() {
var json = {status : 'ok', message: 'Hello'};
updateNotification(json);
});
</script>
// All other elements
</body>

Categories

Resources