I have a javascript engine(using jquery) that needs to render a html which comes as a output from a third party server (REST API). The response contains plain text and occasional html elements like <b>, <p> <br> etc which I want to render as html output. (and not literally as <b>, <p> etc)
Is there a way ?
Here is what I am doing - in pseudo code. Note : I am using blueimp javascript template to generate code.
jQuery.get({
url: 'someRESTfulURL/id',
method: 'get',
success: function(resp) {
//resp contains html elements like <b> etc
var data = {title: resp.title, content: resp.content};
$("#maindiv").html(tmpl("text-tmpl", data));
}
});
<script type="text/x-tmpl" id="text-tmpl">
<h3>{%=o.title%}</h3>
<p>{%=o.content%}</p>
</script>
<html><body><div id='maindiv'></div></body></html>
The javascript template is encoding the html characters and hence the problem. Is there a way I can use this template and still render the html chars.
There are two ways you can do this with jQuery:
The first is when you have the response data already, then you can put it into an element like this:
$("#myElement").html(myData);
The second is that you could load the data directly into the element:
$("#myElement").load("http://myurlgoeshere.com/webservice");
You have to prevent the escaping of HTML special characters. Try this:
<script type="text/x-tmpl" id="text-tmpl">
<h3>{%#o.title%}</h3>
<p>{%#o.content%}</p>
</script>
The difference is just the '#' instead of the '='.
Related
My code:
window.open("http://www.facebook.com/sharer.php?u="+urlToShare+"&"+"t="+"test","_blank", "width=700, height=400");
On the resulting URL '&' should be replaced with '&', right? But, it isn't being replaced.
No.
An & which you want to express as data in an HTML document should (with a few exceptions such as being inside a <script> or when followed by a space) be expressed as &. It will then be interpreted by the browser as & after the HTML is parsed.
In this case, you have JavaScript (which is not HTML) and a URL (which is also not HTML) so there is no HTML to parse so the HTML parsing rules that would read & as & do not apply.
Not in HTML. Character references are not allowed everywhere:
In certain cases described in other sections, text may be mixed with
character references.
When the HTML parser finds a <script> tag, it switches the tokenizer to the script data state.
Unlike the data state, the script data state doesn't have character references.
So just use & instead of &.
<!-- This is HTML -->
<script>
alert('&');
</script>
However, you would need & in XHTML, because in XML the parser doesn't have different behaviors depending on the element.
<!-- This is XHTML -->
<script>
alert('&');
</script>
But using & in JS code is undesirable, so you can wrap the code in a CDATA section
<!-- This is XHTML -->
<script><![CDATA[
alert('&');
]]></script>
I just started using Mustache and I like it so far, but this has me perplexed.
I am using the GitHub gist API to pull down my gists, and part of what I want to do is include the embedding functionality into my page. The problem is Mustache seems to not want to have anything to do with my dynamic script tag.
For example, this works fine:
<div class="gist-detail">
{{id}} <!-- This produces a valid Gist ID -->
</div>
Additionally, this works perfect:
<div class="gist-detail">
<script src='http://gist.github.com/1.js'></script> <!-- Produces the correct embed markup with Gist ID #1 -->
</div>
If I try to pull these together, something goes terribly wrong:
<div class="gist-detail">
<script src='http://gist.github.com/{{id}}.js'></script> <!-- Blows up! -->
</div>
Chrome Inspector shows this:
GET https://gist.github.com/%7B%7Bid%7D%7D.js 404 (Not Found)
... which looks like to me something is weird with escapes or whatnot, so I switch over to the raw syntax:
<div class="gist-detail">
<script src='http://gist.github.com/{{{id}}}.js'></script> <!-- Blows again! -->
</div>
And I get the same result in Inspector:
GET https://gist.github.com/%7B%7B%7Bid%7D%7D%7D.js 404 (Not Found)
How do I get the correct values to embed in the script tag?
EDIT
I am injecting the template as follows (in document.ready:
function LoadGists() {
var gistApi = "https://api.github.com/users/<myuser>/gists";
$.getJSON(gistApi, function (data) {
var html, template;
template = $('#mustache_gist').html();
html = Mustache.to_html(template, {gists: data}).replace(/^\s*/mg, '');
$('.gist').html(html);
});
}
The actually template is inside of a ruby partial, but it is wrapped in a div (not a script tag, is that a problem?) (that's hidden):
<div id="mustache_gist" style="display: none;">
{{#gists}}
<!-- see above -->
{{/gists}}
</div>
I assume a div is ok rather than a script because in either case, I'm pulling the .html(). Is this a bad assumption?
To avoid automatic escaping in Mustache use {{{token}}} instead of {{token}}.
It seems like your template is in HTML and trying to retrieve the template using html() results in a pre-URL-escaped template to be returned. Try placing your template inside a <script type="text/html"> tag instead.
When you embed your template inside an HTML element that excepts more HTML elements as children, it may get processed by the browser as HTML. Escaping may occur. By using a <script> tag with a non-script content type, you're basically telling the browser not to touch your template.
It looks like your script is getting requested before Mustache has a chance to update the src property. What you want to do is define the template in a way that it's not parsed as part of the DOM. A common approach is to define your template inside of a <textarea> tag. This will preserve formatting and prevent character escaping.
<textarea id="gist-detail-template" style="display:none">
<script src='http://gist.github.com/{{id}}.js'></script>
</textarea>
Now, to instantiate the template:
var template = $('#gist-detail-template').val();
var html = Mustache.to_html(template, yourTemplateData);
Here's an official example: http://mustache.github.com/#demo
With jQuery templates, I'm trying to use the {{wrap}} template tag to wrap the results of another template. This second template renders plain text, not HTML. I currently get an empty string where I expect to get the plain text rendered by the wrapped template.
If I surround the plain text with some HTML elements, like a <div> tag, then everything works fine, but I get the <div> rendered into the results. I would be fine creating a dummy tag around my contents in order to get the {{html}} tag to work, but I wouldn't want it in the rendered results.
I will also want to use this same wrapper, if possible to wrap templates that actually do produce HTML as well, so it would be good if the same wrapper template can work for both cases.
Here is my code:
$("#x").html($("#myTmpl").tmpl());
<div id="x" />
<script id="myTmpl" type="text/x-jquery-tmpl">
The following wraps some non-HTML content: {{wrap "#wrapper"}} help {{/wrap}}
</script>
<script id="wrapper" type="text/x-jquery-tmpl">
<table>
<tbody>
<tr>
<td>
Wrapped content: {{html $item.html}}
</td>
</tr>
</tbody>
</table>
</script>
This code can be found at this jsFiddle: http://jsfiddle.net/bernardchen1/BYdeg/
I eventually found a solution. I created use a dummy tag to wrap the plain text (or even the html that is produced by other templates), and then I created a function that I pass into the template invocation that can strip out the dummy tag. I invoke it like this: {{html $data.clean($item)}}. The "clean" function needs access to the content being returned by the inner template, which I found to be $item.wrapped[0]. Once I had that content, I could get its inner html to return from the clean function.
I'm concerned about whether I'm supposed to be accessing $item.wrapped though.
Ultimately, I may just try refactoring my code to not require this dummy tag and the cleaning function.
This solution can be found here: http://jsfiddle.net/bernardchen1/nmzWt/
Edit: there is another solution to call appendTo to attach the template html to another DOM element, and then grab the data back out.
I have some html code rendered on the server side. This is passed to a jsp which renders a javascript-call with this html:
<script type="text/javascript">
window.parent.${param.popup_return}("${helpId}", "${content}");
</script>
content is like
"
This is a <p class="xyz">test</p>
"
My problem is that - according to the quotes in 'content' - the javascript-call is wrong as it is rendered to
<script type="text/javascript">
window.parent.${param.popup_return}("ybc", "This is a <p class="xyz">test</p>");
</script>
Does anyone know how I can solve this (besides manually replacing all quotes)?
Use a JSON encoder to create the encoded strings.
But you'll also have to ensure that the output doesn't contain the sequence </ in string literals, which is invalid in a <script> block (</script is the version that will also break browsers).
Many JSON encoders either by default or optionally will encode to <\/ or \u003C/ to avoid this problem.
I use this:
<div id="result" style="display:none">
${content}
</div>
<script type="text/javascript">
window.parent.${param.popup_return}("${helpId}", dojo.byId("result").innerHTML);
</script>
This seems to work perfectly
You aren't using JSTL here (you originally tagged the question with only JSTL). You are using EL in template text. It get printed plain as-is. You'd like to use JSTL core <c:out> to escape predefined XML entities (which also works for HTML in this particular case, quotes is among the escaped XML entities).
window.parent.${param.popup_return}("<c:out value="${helpId}" />", "<c:out value="${content}" />");
An alternative (if you hate that the JSP syntax highlighter or validator bugs/jerks about nested tags/quotes) is the JSTL function fn:escapeXml():
window.parent.${param.popup_return}("${fn:escapeXml(helpId)}", "${fn:escapeXml(content)}");
Have you tried using single quotes instead of double quotes? i.e. changing "${content}" to '${content}'
Here's my code:
<a href="#">
<img src="myimage.jpg"
onmouseover="showDescription(
'Text', 'Text with HTML tags in them<br />More text');"
onmouseout="revertDescription();"
alt="Image description">
The W3C Markup Validator doesn't like this. It doesn't want HTML tags inside my JavaScript code. Here's the error message it produces if I attempt this:
character "<" is the first character of a delimiter but occurred as data
How can I fix this while making sure that my page doesn't mess up if I pass the HTML tag-containing string to document.getElementById('myElement').innerHTML?
You could wrap your functions inside separate <script>...</script> tags somewhere else in the document, and there use ...
<script>
//<![CDATA[
...code...
//]]>
</script>
From http://javascript.about.com/library/blxhtml.htm:
To fix this problem wer can do one of two things. The simplest way, particularly if the Javascript contains more than just one or two lines, is to make the Javascript external to the page resulting in their being nothing between the script tags to stop the page validating.
If it is just one or two lines then it is probably not worth making an external script so you will want to leave the content between the script tags and tell the validator that this is to be ignored. We do this by placing the Javascript code within a CDATA tag like this ...
There are many ways to get there.
Use < or < instead of <
Use > or > instead of >
Get a id to the image, such as "image1", then
document.getElementById("image1").onmouseover = showDescription(
'Text', 'Text with HTML tags in them<br />More text');
Hope this works.
onmouseover="showDescription('Text', 'Text with HTML tags in them<br />More text');"
Like with all attribute values, you must HTML-encode &, <, and the attribute delimiter (" here). The fact that it's JavaScript inside the attribute value makes no difference; the HTML attribute value is decoded before JavaScript gets a look at it.
onmouseover="showDescription('Text', 'Text with HTML tags in them<br />More text');"
This is in contrast to a <script> element, whose contents are CDATA and thus not &-escaped in HTML4. In XHTML there are no CDATA elements; you can add a <![CDATA[ section to make XHTML behave the same, but it's usually simpler for both script elements and event handler attributes to just avoid the problem by never using a & or < character. In a string literal another escape is available which you can use to get around this:
onmouseover="showDescription('Text', 'Text with HTML tags in them\x3Cbr />More text');"
Replace < by %3C and > by %3E and use unescape when outputting the contents.
This won't validate:
function(){
return ('<b> bold </b>');
}
This gives the same results and validates:
function(){
return unescape('%3Cb%3E bold %3C/b%3E');
}
How about putting this within a <script ...> block:
var myText = 'Text with HTML tags in them<br />More text';
And later in your HTML:
<a href="#">
<img src="myimage.jpg"
onmouseover="showDescription(
'Text', myText);"
onmouseout="revertDescription();"
alt="Image description">