I wrote an Struts 2 application and want to localize it. Now I am using javascript and I would like to put the scripts out of my HTML template to an own javascript file.
When I do it, my s:text tags are not rendered (of course).
Question is how can I localize my javascript files with Struts 2 in a clean way? I would like to avoid to use another technique than the properties files i currently use.
Thanks,
Christian
If you want to stick with your resource bundles back at server, one way possible would be to save your javascript files as .jsp file and serve them with an action so this way your struts tags in your javascript files will get a chance to retrieve the data from server and return the file upon request.
Personally I prefer to keep client messages in javascript files and server messages in resource bundles. This way you can save a .jsp processing IMHO.
You can use a hidden field in your JSP and pass its id to the external JavaScript file and get its value like follows.
In your JSP,
<s:hidden id="warning" value="%{getText('propertyKey')}"/>
(hidden field poplated with the value of the property key in the resource bundle)
Call your external JS method from the same JSP,
<s:a href="%{deleteSelected}">
<img src="<s:url value='/images/delete.gif'/>" border="none"
onclick="javascript:return displayWarning('warning')"/>
</s:a>
In external JavaScript file,
function displayWarning(message) {
var ret = true;
ret = confirm(document.getElementById(message).value);
return ret;
}
<script type="text/javascript">
var mytxt='<s:text name="my.text.prop" />';
alert(mytxt);
</script>
This is also possible, but you cant have them inside a function.You should assign relevant properties to global JS variable at the time of page load. Almost same concept slimier to use hidden variables.
Related
I've partial templates that are used by the show, edit and create form.
In the show-form I don't want them editable, it can be confusing for the user.
Is there a simple solution for this otherwise I need a different template for the show-form or... why use a template then.
I've tied this and created 2 scripts, one that disables and one that enables.
Script 1.
$(document).ready(function(){
$('.elements').attr('readonly',true);
$('.elements').prop('disabled',true);
});
Script 2.
$(document).ready(function(){
$('.elements').attr('readonly',false);
$('.elements').prop('disabled',false);
});
Then I stored those scripts in assets\javascript.
It worked good in show but both edit and create went read-only too.
It seems like everything that is put in this directory is automatically used in each form, because even though I removed the call from the forms, it was working.
Here I show where I originally added the script-call:
<asset:javascript src="myScript_1.js"/>
</body>
</html>
I was going to add it as a comment but then it started to get long and complicated to follow.
why store it in assets ?
simply add a function block to the templates that need it
_template1.gsp
<script>
$(document).ready(function(){
setReadOnly('${someDefinition}')
function setReadOnly(value) {
if (value==='READONLY') {
$('.elements').attr('readonly',true).prop('disabled',true);
}
}
})
</script>
If this function needs to be shared by a bunch of pages, you could add it to an assets / javascript file but rather than declare it in application.js call the js file <asset:javascript tags specificially on each page
and maybe a variable that you pass to template to say when it should be called
or put that above template1 as a master template and call in each of the other templates that needs the js file (So many options)
Now on the main controller doing action
def MyController {
def view() {
String mode='READONLY'
render view: 'index', model:[instance:params,mode:mode]
}
}
the in index.gsp
if js is there then it will pick up mode and set readonly for that controller action or pass that from one template to another, the controller does not have to define actual mode, the main master view page or index page could define mode too
Maybe you need to play/understand then implement you can't rush these things otherwise you will end up wasting time and rewriting
Just to ensure we are on the same page.
By default the application.js file in the javascript folder has a tree line enabled - this by default then reads in all js files. If you wish to manually call js in different places you will need to remove this line and declare each and every js file that you use like the other lines provided in that file.
So that is the price to pay (no more auto loading js files) until declared in application.js
But then most importantly as you have noticed these are global js functions and really nothing new should be going in there that hasn't got a function something() { } a function call.
They will then react when the actual function is called rather than how you had it which was open for call from any old page since it happened as documents opened regardless
According to Marc Palmer
Preventing XSS attacks
In a nutshell, to protect your app from code injection XSS exploits
you must:
Set the default grails.views.default.codec in config to "HTML"
OK.
So if I have this below in my Config.groovy
grails.views.default.codec = "none"
And in my Controller, I add:
def afterInterceptor = { model ->
model.headerJs = "alert('bingo for '+[$params.unitId]);"
}
And in my GSP:
<r:script disposition="head">${headerJs}</r:script>
It works. I see the expected javascript alert when I do View Source and I get my alert when the page serves.
But, if in Config.groovy I apply the recommended change:
grails.views.default.codec = "html"
My GSP renders
<script type="text/javascript">alert('halooba for '+[1]);</script>
which I can see is very secure.
My goal with this app is to have custom JS snippets, various properties and other values stored for the customer in the Domain. These values would be entered by our Admins (not the customer). Based on who invokes the page with an HTTP request, such as www.mydomain.com/ThisApp/?customerId=13423 (but an encoded customerId) I'd make calls to Services from my Controller to fetch the associated settings for the customer from the Domain and inject them into the GSP.
I know that I can put JS and CSS into files and then use the Resources Plugin to bring them in properly, but I'm also looking at this method for specific customizations.
So, to follow this security method, I either need to be able to unencode this, or I need to determine another method for including javascript into the GSP that does not encode it.
Any suggestions?
THANKS!
You can suggest Grails not to escape by using raw() available in GSP as:
<r:script disposition="head">${raw(headerJs)}</r:script>
For Grails 2.2.x and below, you can put the recommended encoding in your Config.groovy:
grails.views.default.codec = "html"
and use a Taglib to bring in values that are SAFE and should not be HTML encoded:
<r:script><com_myapp:getJSDeferred unitId="${params.unitId}" /></r:script>
and it will be rendered raw.
FYI: Above solution will not allow for JSON output to assign to javascript variable.
My workaround, say you have model.data defined as hashmap:
var someVar= ${raw(data as JSON).toString())};
I have asp.net mvc project with knockout.js so my index page is getting really huge because of lots of javascript functionality.
I'd love to move js code into a separate file but it does not allow me to apply it to the most of the code because if I have something like
$.ajax({
url: "#Html.Raw(#Url.Action("Load"))",
Then it pops up a error if I move this part of the code into another file.
Please advise how can I resolve this issue?
Javascript files are not parsed by ASP.net, so the variables you have of #Html.Raw and #Url.Action("Load") will never be processed.
As #James Lai noted, server side code isn't parsed as such by ASP.Net. See this post for a workaround, or you can pick and choose which scripts can still stay on the page (with server-side code) instead of the "everything" - your choice as to which approach meets your requirements.
Javascript files are not parsed by ASP.NET MVC, thus #Html.Raw(#Url.Action("Load")) will not work in javascript file.
Heres workaround
Instead declare a variable in view.cshtml. In script section as
<script type="text/javascript">
var actionUrl = '#Url.Action("Load", "Controller")';
</script>
And use actionUrl in javascript file.
With a grails app and from a local database, I'm returning some text in a xml format.
I can return it well formed in a <textarea></textarea> tag with the correct indenting (tabulation, line return,...etc.)
I want to go a bit further. In the text I'm returning, there are some <img/> tags and I'd like to replace those tag by the real images themselves.
I searched around and found no solution as of now. I understood that you can't add an image to a textarea (other then in a background), and if I choose a div tag, I won't have the indenting anymore (and therefore, harder to read)
I was wondering if using a <g:textField/> or an other tag from the grails library will do the trick. And if so, How can I append them to a page using jquery.
For example, how to append a <g:textField/> in jquery. It doesn't interpret it and I get this error
SyntaxError: missing ) after argument list [Break On This Error]...+doc).append("<input type="text" id="FTMAP_"+nb_sec+"" ...
And in my javascript file, I have
$("#FTM_"+doc).append("<g:textField id='FTMAP_"+nb_sec+"' ... />
Any possible solutions ?
EDIT
I did forget to mention that my final intentions are to be able to modify the text (tags included) and to have a nice and neat indentation so that it is the easiest possible for the end user.
You are asking a few different questions:
1. Can I use a single HTML tag to include images inside pre-formatted text.
No. You will have to parse the text and translate it into styled text yourself.
2. Is there a tag in the grails standard tags to accomplish this for me?
No.
3. How can I add grails tags from my javascript code.
Grails tags are processed on the server-side, and javascript is processed on the client. This means you cannot directly add grails tags via javascript.
There are a couple methods that can accomplish the same result, however:
You can set a javascript variable to the rendered content of a grails tag. This solution is good for data that is known at the time of the initial request.
var tagOutput = "${g.textField(/* etc */)}";
You can make an ajax request for the content to be added. Then your server-side grails code can render the tags you need. This is better for realtime data, or data that will be updated more than once on a single rendered page.
I still find myself having to declare global variables in my .aspx files (the project was started before razor). For example I have to declare global javascript variables like this in my .aspx files:
var getDistributionListUrl = '<%= Url.Action("GetDistributionList", "PublicDocument") %>';
I can then reference this variable in my .js files.
Is there a better way?
Is there a better way?
There is nothing wrong with this.
Personally I use HTML5 data-* attributes on some DOM elements that I am manipulating later in my scripts. For example:
<div id="foo" data-url="<%= Url.Action("GetDistributionList", "PublicDocument") %>">
Hello
</div>
and then in my js:
$('#foo').click(function() {
var url = $(this).data('url');
...
});
But in 99.99% of the cases those urls are associated with either <form> elements or link hrefs so in my javascript I simply retrieve and use this value when I need to do some progressive enhancement on the given DOM element (like unobtrusively AJAXifying forms or anchors).