Tech Stack:
My stack is Flask. Python with HTML, CSS, JS.
Background:
I have a variable myList. It's a list and it is passed from python to the frontend. This list is empty at the page load. This is the code for my GET request in my view function.
myListBackend.clear()
return render_template(
'page.html',
myList=myListBackend,
myListLength = len(myListBackend)
)
I am successfully able to access and use these variables in my template using:
<b> {{ myList[myListLength-1] }} </b>
Note that I only try to use this myList in the template when it is NOT empty. and it does get filled eventually. getting to it in a bit.
I have an a tag which acts as a button and calls a function named myFunc on click. The code for that is:
›
This a tag is only shown to the user based on the condition that the list is not empty. The code for that condition is:
{% if myListLength != 0 %}
The variable myList is only filled in views function in POST, don't worry about it, it does get filled (I have other use of that list and the content does show when i use/print it in html).
The myFunc function which is called on click is defined in JS as below:
function myFunc(){
console.log("I am here"); // This line is important
if ( '{{myListLength}}' != 0 ){
console.log( '{{ myList[myListLength-1] | tojson }}' );
}
}
This function tries to access an index of myList variable which is passed from the python originally.
Problem:
When I load the page (GET request), It is giving me error in the console.log inside the if condition of the function myFunc. The error is:
TypeError: Object of type Undefined is not JSON serializable
The problem is that I am not calling myFunc anywhere else. And it is not printing the console.log of "I am here" (1st line of myFunc).
So, why is the program directly accessing the line of code which is using the index? I understand if the code is somehow going to that function then it will throw the error. But, I am not letting it go there if the list is empty. I also wrote that if condition to stop the flow if it is reaching there somehow, but that isnt seems to be doing anything.
I think this might be related to the behaviour of Jinja because it is ignoring console.log, so, it might be checking only the binding variable (the variable which is passed to template from backend) statements.
Since you are dealing with server side and client side languages, you have to separate clearly the processing of those two sides.
One idea would be to assign the list from Flask to a JavaScript variable and then process the variable in pure JavaScript.
So, your JavaScript part would become:
var list = JSON.parse('{{ myList | tojson }}');
function myFunc(){
if(list.length > 0){
console.log(list[list.length - 1]);
}
}
I am able to get the value of '${currentNode.identifier}' in JSP javascript functions.
When I put the same js function and try to access the '${currentNode.identifier}' inside clientlibs javascript file , it simply outputting the string. not the actual identifier.
**
How to access the current node identfier inside a client libe js file
or inside a listener js function ?
**
I appreciate all the help.
Thanks,
Sri
As rakhi already mentioned in the comment: JavaScripts are delivered "as is" and are not executable servlets like JSPs. So there will be no replacement of scriptlets and ${} attributes. So the easiest way is to have a data attribute on a DIV or any other HTML element which is rendered by a JSP:
<div data-nodeid="${currentNode.identifier}"></div>
Then you could use a jQuery selector to get the value on load:
jQuery(function() {
jQuery('div[data-nodeid]').each(function() {
var nodeId = jQuery(this).data('nodeid');
//do something with the id
});
}
Let's say the variable is called 'myvar'. I can access its value in twig using {{ myvar }}.
I can also use it inside javascript code, if inside the same twig page, by doing
<script>
//some javascript code
myJSVar = {{ myvar }};
//other javascript code
</script>
The question is: if I import a js (e.g. I have a main.js where I put all the common js stuff) is there a way do the same?
I've read about a solution for CSS (Symfony2: Use Twig variable in stylesheet) which is a bit convoluted, and another point of reference might be here (Using Twig as an Assetic filter for JavaScript in Symfony2). Any other options?
In practice what I need is passing a global variable, something that you'd find in config.yml. It's a path basically, which is different in production and in development.
Thank you!
Perhaps you could do something like:
<div id="somediv" data-var="{{ myvar }}"></div>.
And then on you main.js:
var myJSVar = $('#somediv').data('var');
I have a EE template in which I use a EE global variable {global_var}.
In the same template I have a js script.
//opening js script tag
{global_var}
//closing js script tag
Inside this script I can read and use {global_var}.
But if I move the script code to a JS template and reference to it like this
<script type="text/javascript" src='{path="js/contact_form"}'></script>
the {global_var} is no more available, why?
More info: {global_var} is a user defined variable that I added to index.php
$assign_to_config['global_vars'] = array(
"base_url" => "http://www.example.com/",
"global_var" => "hello"
);
Is there a way to read EE global variables in the referenced js file?
Try to add quotation mark to the global variable when you're outputting it to the Js.
"{global_var}"
Another reason why it may not work can be either:
The variable doesn't exist in the the DB So you might need to use syncSnippert to synchronize between the two.
The template for the variable doesn't exist so you might need to create it.
We are building large ASP.NET applications for the intranet use in multiple languages/cultures. We utilize the Globalization with RESX files and use GetResourceText on the server side to get the localized texts.
Lately we are doing more and more client side logic with JQuery.
How do I get the RESX texts to be used in Javascript?
e.g. texts used for validation, dynamic messages etc.
All our Javascripts are in .JS files, we do not want to mix HTML in the ASPX page and Javascript blocks.
Thanks for your help.
Unfortunately, in an external JS file the server side code is not being processed by the server. However I have seen a workaround where you can set your translated values in hidden fields on the page - this way your javascript will be able to read the values in.
For example:
<%-- This goes into your page --%>
<input type="hidden" id="translatedField" name="translatedField" value="<%=Resources.Resources.translatedText %>" />
and use this inside your javascript file:
// This is the js file
$(document).ready(function() {
alert($("#translatedField").attr("value"));
});
You will be able to separate the values and still see it in your external JS file.
There is also another workaround that creates a .aspx file that only outputs Javascript instead of HTML. Check out the link below:
Using server side method in an external JavaScript file
Always separate functionality from human readable strings.
If you're creating jQuery-plugins you should be able to pass an array of localized strings as parameter when you call your different jQuery functions. The array could be defined as inline javascript directly on the page calling the different jQuery plugins or you could load the from external resource in the format /scripts/localization/strings.js?ci=en-US and register a Generic ASP.Net Handler in web.config that would respond to scripts/localization/strings.js
The DatePicker control is a fine example of how to localize text for the jQuery datepick control - this js file is dynamically created from resource files (resx) and when included on a page it will make sure the calendar control will have danish text.
Create a HttpHandler (.ashx file), and return JSON with your text resource strings.
You may also "publish" it to global namespace, i.e.
Response.Write("window.Resources=");
Response.Write((new JavaScriptSerializer()).Serialize(strings));
set up HTML like:
<script src="Resx.ashx?lang=en-US" />
<button class="LogoutButtonResourceId OtherButtonClasses">(generic logout text)</button>
<a href="#"><span class="SomeLinkTextResourceId OtherClasses">
(generic link text)
</span></a>
and apply texts like this:
$(document).ready(function() {
for(var resId in Resources){
$("."+resId).html(Resources[resId]);
}
});
If you don't want to use ASP.NET to generate your main JavaScript, here are two other options:
Use ASP.NET to generate a script file that contains variable-to-string assignments, such as var mystring = 'my value';. Your main script would then reference the localized text with variables names rather than as embedded values. If that's still too "dirty" for you, you could encode the strings as JSON rather than as variable assignments, using an HttpHandler rather than straight .aspx.
Have your JavaScript code issue an Ajax call to retrieve an array or list of localized strings from the server. The server-side part of the call would retrieve the text from your resx files.
Have you considered using $.ajax in combination with ASP.NET WebMethods? It's hard to suggest a more concrete solution to this problem without understanding how your JavaScript/jQuery would consume/process the resources. I assume that they're organized into logical groups (or could be) where you could return several resource strings that belong on a single page.
Assuming that, you could write a very simple C# class -- or use a Dictionary<string, string> -- to return data from your ASP.NET WebMethod. The results would look something like:
[WebMethod]
public Dictionary<string, string> GetPageResources(string currentPage)
{
// ... Organizational stuff goes here.
}
I always separate out my AJAX calls into separate .js files/objects; that would look like:
function GetPageResources (page, callback)
$.ajax({ // Setup the AJAX call to your WebMethod
data: "{ 'currentPage':'" + page + "' }",
url: /Ajax/Resources.asmx/GetPageResources, // Or similar.
success: function (result) { // To be replaced with .done in jQuery 1.8
callback(result.d);
}
});
Then, in the .js executed on the page, you should be able to consume that data like:
// Whatever first executes when you load a page and its JS files
// -- I assume that you aren't using something like $(document).ready(function () {});
GetPageResources(document.location, SetPageResources);
function SetPageResources(resources) {
for (currentResource in resources) {
$("#" + currentResource.Key).html(currentResource.Value);
}
}
I know it's to late but want share my experience in this task)
I use AjaxMin. It can insert resx key values into js file on build event.
It's not common way but it keeps html without unneeded script blocks and can be done during minification process if you have it.
It works like this:
ajaxmin.exe test.js -RES:Strings resource.resx -o test.min.js
Also you need to do the same for ech locale if you have many.
Syntax to write resource keys in js (and also css) is written here:
Js localization
Css localization
How about injecting it as part of a javascript control initialization? what i do is as follows:
I have a self-contained javascript control - call it CRMControl, which has an init method called setupCRMControl, to which i pass a settings object. When i initialize it, i pass an object containing all the resources i need inside javascript as follows:
CRMControl.setupCRMControl({
numOfCRMs: 3,
maxNumOfItems: 10,
// then i pass a resources object with the strings i need inside
Resources: {
Cancel: '#Resources.Cancel',
Done: '#Resources.Done',
Title: '#Resources.Title'
}
});
Then, inside this javascript control:
var crmSettings = {};
this.setupCRMControl(settings) {
crmSettings = settings;
};
and whenever i want to show a resource, i say (for example, show an alert saying 'Done'):
alert(crmSettings.Resources.Done);
You can call it "R" to make it shorter or something, but this is my approach. Maybe this may not work if you have a whole bunch of strings, but for manageable cases, this may work.