My Application class looks like this:
public class Application extends Controller {
public static Result index() {
return ok(index.render("<p>This is a paragraph</p>"));
}
and my index.scala.html file looks like:
#(htmlcode: String)
#main("Example") {
#htmlcode
}
and my main.scala.html file is fairly simple, with the standard !DOCTYPE declaration, html, head, body tags, etc.
...
<body>#content</body>
...
But when I run my application, the index page displays the source code <p>This is a paragraph</p> instead of just This is a paragraph. The source file looks like
...
<body>
<p>This is a paragraph</p>
</body>
...
How would I have the page render the code instead of just displaying it?
It is simply converting/protecting the values you are giving it. All the HTML markup should be done in the template (scala.html) file and not in the controller.
BTW this question comes pretty closes to this other question : How to pass raw html to Play framework view?
Simply use the Html() function
#main("Example") {
#Html(htmlcode)
}
Related
I have Freemarker templates for generating pdf documents, that can have multiple pages based on variables content. I need generate unique code on each page, the generating logic takes page number as parameter. I have working utils class, callable from template used for dates formatting etc.
Ideally I would like to be able call my utils class like that, with something that would provide current page number on each page (simplified example):
<h1>Utils result: ${utils.generateUniqueNumber(pageNumber)}</h1>
I will probably need to place this code into header/footer, to achieve have it on each page.
Currently I have working page counter in footer defined using css:
<head>
<title>RESEA - Selection Notice OWCMS</title>
<style type="text/css">
.page-counter:before {
content: "Page "counter(page)" of "counter(pages)
}
</style>
</head>
Then used in footer , works as expected.
I'm not sure if actual paging is driven by Freemarker or CSS, so maybe I need to make CSS call my utils function.
Any advise, or relevant study source is welcome!
I am using sitemesh for a spring based site. The problem is that I have some javascript that I want it to run on the onload event of only one specific page using jquery $(function() { ... }) and not on every page.
I have included the jquery.js in the bottom of my decorator, after the body. So, if I try to include a <script> tag in the body of my decorated page the script won't be executed because jquery will be loaded after that! I know that I could include the jquery.js in the header of my decorator so it will be before the custom script in the decorated page however I don't really like that solution since it will contain javascritp in the head of my page.
So I would like to have something like a placeholder in my sitemesh decorator in where the custom from my decorated page will be placed (as you can understand I come from the django world :p). Is this possible ? Do you propose anything else or should I just put my jquery.js in the header and be done with it ?
To answer my question, after some search I found the following solution:
I Added the following to the end of my decorator page (after including jquery.js)
<decorator:getProperty property="page.local_script"></decorator:getProperty>
I also added the following
<content tag="local_script">
<script>
$(function() {
alert("Starting");
});
</script>
</content>
The decorated result page contained the contents of the local_script tag exactly where I wanted them and everything worked fine :)
I don't know why this feature of sitemesh is not properly documented - using this you can have a great templating behaviour (like django).
I have custom tag which contains form with text input and submit. I want to validate this text input using JS, so my custom tag output should look like:
<script type="text/javascript">
function validate(form) {
var text = form.textInput;
// validation code
}
</script>
<form onsubmit='return validate(this);'>
<input type='text' name='textInput'/>
<input type='submit'/>
</form>
(Note, this code simplified!)
My problem appears when I want to use this tag twice or more times at page - I want to print form at page again, but not JS validation code! Validation code must be unique at the page. How can I archive that? My custom tag extends javax.servlet.jsp.tagext.TagSupport
I found the most suitable solution for me.
Class javax.servlet.jsp.tagext.TagSupport contains protected field pageContext which presents... page context! I can easily access context attributes of javax.servlet.jsp.PageContext. So, I put next code in my custom tag:
public int doStartTag() throws JspException {
if (pageContext.getAttribute("validated") == null) {
// validation code writing
pageContext.setAttribute("validated", true);
}
...
}
If condition would be reachable only once per page rendering.
Hope it would be useful for someone.
I suggest you to try to embed that JavaScript function in some .js file an import that file. If you don't want to do that, for some reason you should try to define that function dynamically, if it is not defined:
if (typeof window.validateMyForm === 'undefined') {
window.validateMyForm = function(form) {
var text = form.textInput;
// validation code
}
}
As you guess this should define function only if it is not already defined.
First answer is correct, but that means that programer must know where in code are already inserted custom tags and according to that this whether to set that parameter to true or false. And what about code changes, you will have to always go thought whole page and revise all used tags on a page.
Make the custom tag to accept a parameter that toggles the validation on or off, and of course have it generate different code depending on the value of the parameter.
I have a custom tag that has no body at all. I'm trying to programmatically replace the empty body with, for simplicity's sake,
[<c:out value="SUCCESS!"/>]
The goal is to see "[SUCCESS!]" displayed by the JSP which uses the tag, but all I see is "[]" and if I look at the generated source code, I can see that the c:out statement is written on the page between the brackets, but not interpreted.
Is there a common way to achieve this ? The final goal will be to use other custom tags instead of the "c:out" tag. The tags/content will come from a database.
I tried different techniques with SimpleTagSupport and BodyTagSupport but none of those were successfull. In fact I'm not sure if it is technically possible to do it, since, the tag has already been interpreted at that time.. But then how should this be done ?
Server tags (like your custom tag or JSTL tags) get transformed to Java code when the JSP is translated into a servlet. For example, the following JSP code:
<c:out value="FooBar" />
gets translated to something like this inside the servlet:
....
OutTag outTag = (OutTag) tagHandlerPool.get(OutTag.class);
outTag.setPageContext(pageContext);
outTag.setParent(null);
outTag.setValue(new String("FooBar"));
int evalOut = outTag.doStartTag();
....
In your custom tags you can call other Java classes/methods and can write HTML code (not JSP code) to the response.
The [<c:out value="SUCCESS!"/>] is not interpreted because at this level it's just a string that gets written directly to the response.
I have custom JSP tags that generate some HTML content, along with some javascript functions that get called by this HTML code. In the current implementation, the SCRIPT tags are created just above the HTML code.
To avoid modifying the existing code base, I want to pull up these scripts inside the HEAD section of the page using SiteMesh or some other decorator tool.
I know SiteMesh can extract content from <content tag="..."> elements, but I was wondering if it was possible also with other tags, such as SCRIPT.
Is this possible with SiteMesh, or know of any tools that could allow me to do that?
Thank you!
SiteMesh's HTMLPageParser is extensible, so you can add your own custom rule to extract <script> elements by extending HTMLPageParser and configuring SiteMesh to use your class instead of HTMLPageParser, something like this:
import com.opensymphony.module.sitemesh.parser.HTMLPageParser;
public CustomPageParser extends HTMLPageParser {
protected void addUserDefinedRules(State html, PageBuilder page) {
super.addUserDefinedRules(html, page);
html.addRule(new ScriptExtractingRule(page));
}
}
I imagine your ScriptExtractingRule would be modeled after the standard SiteMesh ContentBlockExtractingRule, storing the content in the page context so your decorator can access the blocks as if they were <content> blocks.