Using external .properties in Thymeleaf template - spring

In summary, I need to find a way to use value from .properties files in a Thymeleaf template.
In details now, I want to have Google Analytics on my page. There are development and production application build profiles. Each of these profiles has its directory with properties. The account details are in these properties files.
For now I assign the appropriate values to variables in the model and use them.
<script type="text/javascript" th:inline="javascript">
var _gaq = _gaq || [];
var _gaId = /*[[${googleAnalyticsId}]]*/'';//these are the variables I'm talking about
var _gaDomainName = /*[[${googleAnalyticsDomainName}]]*/'';
_gaq.push(['_setAccount', _gaId]);
_gaq.push(['_setDomainName', _gaDomainName]);
_gaq.push(['_trackPageview']);
</script>
But it seems quite dirty, let alone the manoeuvring that needs to be done in order to change any of these values.
What I'd like to do in the page template is to just point to the property name like we do in Spring with #Value. E.g.
<script type="text/javascript" th:inline="javascript">
var _gaq = _gaq || [];
var _gaId = /*[[${google.analytics.id}]]*/'';//I want to assign values directly from the properties file
var _gaDomainName = /*[[${google.analytics.domain.name}]]*/'';
_gaq.push(['_setAccount', _gaId]);
_gaq.push(['_setDomainName', _gaDomainName]);
_gaq.push(['_trackPageview']);
</script>
Thanks in advance.

Why you can't use the standard message-source way with #{googleAnalyticsDomainName}?

Related

How to pass attribute value to a standard JS function in thymeleaf

In my template file using thymeleaf I have below code
<script type="text/javascript" >
var ue=UE.geteditor();
ue.ready(function()
{
ue.setcontent("${user.email}");
});
</script>
I want to set the content of ue to attribute user's email ,but got "${user.email}" as a string instead.
What's the correct way to use thymeleaf attribute value in plain JS function?Any help?Thx.
You need to use script inlining.
<script th:inline="javascript">
let user = {
email: [[${user.email}]]
};
let ue = UE.geteditor();
ue.ready(function() {
ue.setcontent(user.email);
});
</script>

Javascript code end of webpage with Spring and Dojo

I have a pretty specific issue to deal with : I am looking for a solution about IE6 crashing when there is too much javascript in a webpage. The project I am working on is using Dojo, SpringJS, Apache Tiles and Spring Webflow. For each field used (defined in .tagx files), the decoration is added as following :
<script type="text/javascript">
Spring.addDecoration(
new Spring.ElementDecoration({
elementId : '_${field}_id',
widgetType : 'dijit.form.ValidationTextBox',
widgetAttrs : {
<!-- Widget attrs -->
}
})
);
</script>
So, in the generated webpage, a lot of javascript is added everywhere. The problem is IE6 seems to crash when there is too much javascript. The solution "experts" found was to write all the javascript code at the end of the HTML page.
In intent to do that, I tried to create a new tag called putScriptInCache.tagx :
<jsp:useBean id="mapScripts" class="java.util.HashMap" scope="request"/>
<jsp:doBody var="theBody" />
<c:set target="${mapScripts}" property="${id}" value="${theBody}"/>
Which replaces previous javascript tag :
<lbputil:putScriptInCache id="${field}">
Spring.addDecoration(
new Spring.ElementDecoration({
elementId : '_${field}_id',
widgetType : 'dijit.form.ValidationTextBox',
widgetAttrs : {
<!-- Widget attrs -->
}
})
);
</lbputil:putScriptInCache>
Finally, I have written a piece of code which loops on the map created and write javascript at the end of the html body :
<script type="text/javascript">
dojo.addOnLoad(function(){
<c:forEach items="${mapScripts}" var="script">
<c:out value="${script.value}" escapeXml="false" />
</c:forEach>
});
</script>
It seems to work pretty well but an issue remains : when an ajax request is fired, an Apache Tiles fragment of the jsp is reloaded using Spring Webflow. After that, I noticed that the map in request scope was empty and I can't figure out why. It should have been filled with the reloaded fragment fields javascript code.
EDIT : If someone has a totally different way to solve my initial issue, do not hesitate to propose it !
After lookep at the spring-dojo.js, I found that this script already evaluates scripts at the end of the fragment rendering.
handleResponse: function(response, ioArgs, callbackResponse) {
//...
//Extract and store all <script> elements from the response
var scriptPattern = '(?:<script(.|[\n|\r])*?>)((\n|\r|.)*?)(?:<\/script>)';
var extractedScriptNodes = [];
var matchAll = new RegExp(scriptPattern, 'img');
var matchOne = new RegExp(scriptPattern, 'im');
var scriptNodes = response.match(matchAll);
if (scriptNodes != null)
{
for (var i=0; i<scriptNodes.length; i++)
{
var script = (scriptNodes[i].match(matchOne) || ['','',''])[2];
script = script.replace(/<!--/mg,'').replace(/\/\/-->/mg,'').replace(/<!\[CDATA\[(\/\/>)*/mg,'').replace(/(<!)*\]\]>/mg,'');
extractedScriptNodes.push(script);
}
}
//...
//Evaluate any script code
dojo.forEach(extractedScriptNodes, function(script){
dojo.eval(script);
});
// APPEL du callBackResponse
if (callbackResponse != null){
callbackResponse();
}
return response;
},
First, it stores script tags into extractedScriptNodes, then it replaces the script tags with // Original script removed to avoid re-execution . Finally, it evaluates each extractedScriptNodes after having rendered the view.
So, it should already work...

cshtml/vbhtml and the new # to include server side data, but without encoding?

I started to learn MVC and in conjunction want to use the KnockOut.js
I am having trouble understanding why the new # include tag encodes everything to HTML(edit: ok i know now to prevent XSS).. but even worse how to stop it from doing that..
I have this code.
#{
ViewBag.Title = "Home Page";
var myData = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model);
}
<script type="text/javascript">
var initialData = #myData ;
Which produces this source
<script type="text/javascript">
var initialData = [{"Title":"Tall Hat","Price":49.95},{"Title":"Long Cloak","Price":78.25}] ;
Ok. so tried using HttpUtility.HtmlDecode.. and nothing happens on the included bit in the javascript because the razor engine is reencoding it? but if it use the encode then reecnodes the encodes html.. briallinat.
I cannot work out how to stop the encoding.
The msdn says use #: but that does not work in the javascript block, i even tried
#{ #:new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model);}
That just something wierd and causes other errors.
How should this be done in the MVC model?
In aspx using
var initialData = <%= new JavaScriptSerializer().Serialize(Model) %>;
works fine..
Html.Raw(string) will write out your string in its raw, unencoded form. Provided your string is not encoded to begin with.
code example as requested (?!?!)
#{
ViewBag.Title = "Home Page";
var myData = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model);
}
<script type="text/javascript">
var initialData = #Html.Raw(myData) ;
MVC (or the Razor view engine in this case) encodes all your strings as a HTML string using the MvcHtmlString by default. To get around it, use:
<script type="text/javascript">
var initialData = "#MvcHtmlString.Create(myData)";
</script>
This then assumes your string has already been encoded.

Google Places API types functionality..

<html>
<head>
<title></title>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?libraries=places&sensor=true"></script>
<script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
var input = document.getElementById('location');
var options = {
types: ["locality"]
};
autocomplete = new google.maps.places.Autocomplete(input, options);
});
</script>
</head>
<body>
<div>Location: <input type="text" id="location" style="width:400px;" /></div>
</body>
</html>
There is my code to generate my autocomplete location text input. Google's list of supported types (http://code.google.com/apis/maps/documentation/places/supported_types.html) shows "locality" as being the type to use when I do not wish for everything to come back in the result(businesses, etc). I am getting no results.
Basically, what I would like to achieve is to search for a city (IE: Toronto) And only see results like: "Toronto, ON, Canada". Perhaps I am confused on how I implement this API.
Thank you very much for your replies!
I think the option you are looking for according to the docs is "geocode" ( http://code.google.com/apis/maps/documentation/javascript/reference.html#AutocompleteOptions ):
var options = {
types: ["geocode"]
};
you can also use the country restriction
example:
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?libraries=places&sensor=false"></script>
<script type="text/javascript">
function initialize()
{
var input = document.getElementById('searchTextField');
var options = {
types: ['(cities)'],
componentRestrictions: {country: "ca"}
};
autocomplete = new google.maps.places.Autocomplete(input, options);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<input id="searchTextField" type="text" size="50" placeholder="Anything you want!">
now you can easily add a dropdown with a selection of cities and re-filter the cities, when onchange of the dropdown occurs :)
Try, check out the jsfiddle:
var options = {
types: ['geocode']
};
types, which can be either establishment or geocode, representing
businesses or addresses, respectively. If types is not specified, both
types are returned.
If the user types Tor in the input field and the output you want is Toronto, ON, Canada then you should use types=(regions), with the brackets.
I don't know if the option was present when the question was asked, but it is available now.
Sample Request:
https://maps.googleapis.com/maps/api/place/autocomplete/json?input=Tor&key=<YOUR_API_KEY_HERE>&types=(regions)
You can use like this
types: ['geocode' || 'establishment' || 'address']

How to enable data binding in KnockoutJS using the ASP.NET MVC 3 "Razor" View Engine?

I'm trying to implement this Knockout example using ASP MVC 3's "Razor" view engine.
The first topic covers simple data binding of a C# array using the standard ASP view engine. I am trying the sample example using "Razor", and this line:
<script type="text/javascript">
var initialData = <%= new JavaScriptSerializer().Serialize(Model) %>;
</script>
results in an empty variable for initialData.
I also tried this:
#{
string data = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model);
}
And then specified the initialData like this:
var initialData = #Html.Raw(data);
This populates initialData with the dataset, but binding does not work.
I'm just trying to databind this set in order to display a count of the ideas, as in the example:
<p>You have asked for <span data-bind="text: gifts().length"> </span> gift(s)</p>
Why isn't data binding working in this instance?
The easiest way in MVC3 is to do:
var initialData = #Html.Raw(Json.Encode(Model));
I ran into this same problem, and discovered that it was my own stupidity that caused the issue (which it so often is). I forgot to wait until the DOM loaded to call ko.applyBindings(viewModel) - so simply using:
$(document).ready(function () { ko.applyBindings(viewModel); });
So the whole script as
<script type="text/javascript">
var initialData = #Html.Raw( new JavaScriptSerializer().Serialize(Model));
var viewModel = {
gifts: ko.observableArray(initialData)
};
$(document).ready(function () { ko.applyBindings(viewModel); });
</script>
This worked with knockout-1.2.1.js and jquery-1.5.1.js

Resources