As far as Grails' templates go, do they have their own DOM? Is it different from the DOM of the main GSP(parent GSP) into which a template gets loaded or does the template's DOM become part of the parent GSP's DOM? I'm having a hard time differentiating between these two DOMs and their relationship. Do they both have their own separate DOM ready moments? And so their own separate DOM ready clauses as far as javascript goes? If anyone can please clarify on these points. Much obliged.
GSP, Groovy server pages, are server based. The DOM you are concerned with is the client-side browser DOM. To answer your question, no. The entire HTML document (even if it's made up of several GSP templates) is still one DOM within the browser.
Having said this, however, it also depends on how you are loading the content of the page. I'm assuming you are loading all the content in a single HTTP request.
The separate GSP templates are built into a single HTML document before being sent to the browser.
Grails uses a framework called SiteMesh http://www.sitemesh.org behind the scenes.
Edit:
I guess the answer depends on whether you are using the <g:render template="myTemplate" /> tag from inside a gsp or doing an ajax call and using the render method from your controller like this: render(template: "myTemplate")
The ajax call will inject the html from the template into the browser's DOM.
Related
Just a quick question here. I am trying to register a js file for script validation using
if (!Page.ClientScript.IsClientScriptBlockRegistered("strIncludeJSFile")) Page.ClientScript.RegisterClientScriptBlock(strIncludeJSFile.GetType(), "strIncludeJSFile", strIncludeJSFile);
code in C# and it works well for the js files. But, some js files are used in multiple pages, so I am unsure if the above code will be a good idea. As such, I want to do the same thing in the js file itself, instead of using the code behind. Is there any possibility to do that? Or is this thing specific to C#?
of course you can register a js file (or script block) from html by using a script tag. However, the main reason RegisterClientScriptBlock exists is because developers might need to generate (or modify) a script block dynamically from code behind or conditionally register a script file dynamically.
If you need any of the above...generate a script block dynamically, then you "might" be better off registering it from code behind, I mean, it depends on the whole solution itself, it's hard to recommend an approach without having some context. Either way, some options are:
register the script blocks from code behind if you need to generate based on some conditions that can only be evaluated from server side code
use a master page for better and register the script block from the master page. This will make it easier to maintain if you keep the logic in one place
similar to the option above, you can use a base page class if using a master page is not possible
use an html script element if what you need is to reference a static js file
use place holders such as js variables and fetch dynamic data from the server using ajax
use unobtrusive javascript, custom data attributes and ajax
Whatever the suitable option(s) is depends on too many factor that you have to assess
I have a web page with some user content displayed on initial page load. There's a button that can trigger further page loads (somewhat like Twitter's infinite scrolling). The Django template that renders the original page is also used to render content for infinite scroll (partial view). The server sends formatted HTML via AJAX that can be easily inserted into my existing page like this:
$(new-Html).insertAfter($('existing-content'))
With this option, I can reuse the existing template to render my content. Is it worth the convenience and can I assume that escaping at Django's end covers me from XSS? It's this jQuery ticket that worries me. It can be dangerous stuffing all that HTML into a selector $(..)
Or, should I use JSON as response type and carefully craft all user content as text nodes with jQuery? This is a lot more work & error prone since I'll be duplicating the template rendering to a large extent. Even though this route appears a lot more safer, it's difficult to maintain two redundant rendering methods, one via template, other via JS.
update : I considered using innerHTML as suggested in one of the comments but not sure about that either : http://www.slideshare.net/x00mario/the-innerhtml-apocalypse (Mario Heiderich on mXSS)
The Django template that renders the original page is also used to render content for infinite scroll (partial view).
Therefore you are safe. If all you are doing is rendering content that you have control of and already trust for your initial page load, then there will be nothing malicious in the page source to be rendered. In this case as you are loading form a trusted source, if there was any malicious code rendered that would cause XSS then this would be an issue with the AJAX service that supplies the source, not the JQuery that renders it.
The ticket you refer to is regarding XSS WITH $(LOCATION.HASH) AND $(#<TAG>) which is different to what you are doing (and has also been marked as fixed).
Update
Use this line before passing the HTML into the jQuery it will remove any scripts (including onmouseover etc.) that are included in the HTML:
var cleansed = str.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gmi, "");
cleansed = cleansed.replace(/\bon\w+\s*=[\s\S]*?>/gmi, ">");
I still say that the jQuery/Django method is the ideal method. The above line will clean the content of scripts before you add it to the DOM.
Previous
Django should escape anything it's passing into that line of jQuery. So long as you aren't using an eval() statement anywhere in there, cross-site scripting shouldn't be a concern. I'd say it's more practical to continue the way you're going.
Currently I am creating a website which is completely JS driven. I don't use any HTML pages at all (except index page). Every query returns JSON and then I generate HTML inside JavaScript and insert into the DOM. Are there any disadvantages of doing this instead of creating HTML file with layout structure, then loading this file into the DOM and changing elements with new data from JSON?
EDIT:
All of my pages are loaded with AJAX calls. But I have a structure like this:
<nav></nav>
<div id="content"></div>
<footer></footer>
Basically, I never change nav or footer elements, they are only loaded once, when loading index.html file. Then on every page click I send an AJAX call to the server, it returns data in JSON and I generate HTML code with jQuery and insert like this $('#content').html(content);
Creating separate HTML files, and then for example using $('#someID').html(newContent) to change every element with JSON data, will use even more code and I will need 1 more request to server to load this file, so I thought I could just generate it in browser.
EDIT2:
SEO is not very important, because my website requires logging in so I will create all meta tags in index.html file.
In general, it's a nice way of doing things. I assume that you're updating the page with AJAX each time (although you didn't say that).
There are some things to look out for. If you always have the same URL, then your users can't come back to the same page. And they can't send links to their friends. To deal with this, you can use history.pushState() to update the URL without reloading the page.
Also, if you're sending more than one request per page and you don't have an HTML structure waiting for them, you may get them back in a different order each time. It's not a problem, just something to be aware of.
Returning HTML from the AJAX is a bad idea. It means that when you want to change the layout of the page, you need to edit all of your files. If you're returning JSON, it's much easier to make changes in one place.
One thing that definitly matters :
How long will it take you to develop a new system that will send data as JSON + code the JS required to inject it as HTML into the page ?
How long will it take to just return HTML ? And how long if you can re-use some of your already existing server-side code ?
and check how much is the server side interrection of your pages...
also some advantages of creating pure HTML :
1) It's simple markup, and often just as compact or actually more compact than JSON.
2) It's less error prone cause all you're getting is markup, and no code.
3) It will be faster to program in most cases cause you won't have to write code separately for the client end.
4) The HTML is the content, the JavaScript is the behavior. You're mixing both for absolutely no compelling reason.
in javascript or nay other scripting language .. if you encountered a problem in between the rest of the code will not work
and also it is easier to debug in pure html pages
my opinion ... use scriptiong code wherever necessary .. rest of the code you can do in html ...
it will save the triptime of going to server then fetch the data and then displaying it again.
Keep point No. 4 in your mind while coding.
I think that you can consider 3 methods:
Sending only JSON to the client and rendering according to a template (i.e.
handlerbar.js)
Creating the pages from the server-side, usually faster rendering also you can cache the page.
Or a mixture of this would be to generate partial views from the server and sending them to the client, for example it's like having a handlebar template on the client and applying the data from the JSON, but only having the same template on the server-side and rendering it on the server and sending it to the client in the final format, on the client you can just replace the partial views.
Also some things to think about determined by the use case of the applicaton, is that if you are targeting SEO you should consider ColBeseder advice, of if you are targeting mobile users, probably you would better go with the JSON only response, as this is a more lightweight response.
EDIT:
According to what you said you are creating a single page application, if this is correct, then probably you can go with either the JSON or a partial views like AngularJS has. But if your server-side logic is written to handle only JSON response, then probably you could better use a template engine on the client like handlerbar.js, underscore, or jquery templates, and you can define reusable portions of your HTML and apply to it the data from the JSON.
If you cared about SEO you'd want the HTML there at page load, which is closer to your second strategy than your first.
Update May 2014: Google claims to be getting better at executing Javascript: http://googlewebmastercentral.blogspot.com/2014/05/understanding-web-pages-better.html Still unclear what works and what does not.
Further updates probably belong here: Do Google or other search engines execute JavaScript?
I have some simple JQuery / Javascript to perform some simple logic for all external hyperlinks:
<script>
$("a[href^='http://']:not([href*='"+location.hostname+"']),[href^='https://']:not([href*='"+location.hostname+"'])")
.addClass("external")
.attr("target","_blank")
.attr("title","Opens new window").click(function(e) {alert('You are leaving mysite and going somewhere else, you crazy dude')});
</script>
This is fine for one page. However, I wish to have this in every web page in my application and be 100% sure that it is there.
Is there any good trick to do this?
The only one I can think of is if you are using a java architecture, to have a base JSP and ensure the base JSP calls this.
Any better ideas?
You don't need some server side framework... If you use some templating library (jade handlebars, mustache, jquery templates) or if you simply separate out your HTML files you can pull them each in with jquery and render them on the page. Check out the .load function.
Also, you should separate out your html pages even if they are static.
Wrap it in a function and call the function. Then you can just call the function and leave the implementation to the function call.
Since you didn't specify a server side technology such asp.net or php of course there would be other options (partial views or templates) using that.
function doStuff(){
$("a[href^='http://']:not([href*='"+location.hostname+"']),
[href^='https://']:not([href*='"+location.hostname+"'])")
.addClass("external")
.attr("target","_blank")
.attr("title","Opens new window").click(function(e) {alert('You are leaving mysite and going somewhere else, you crazy dude')});
}
<script>
doStuff();
</script>
This depends on how your site is structured. If you've got a server-side framework (like your JSP example), then you can have a function that makes sure that the script somehow gets included.
If you just have static HTML pages, my recommendation would be to put that code in a script file (let's say dontleaveme.js). Then on every page, just do
<script src="dontleaveme.js"></script>
A good application design will have a layout file or header and footer files which are used on every page. Then it is easy to make changes, such as adding a script, which affect every page on the site. If you are not using this technique, this is a great reason to start.
A common pattern for loading backbone templates is something like:
<script type='text/template' id='foo'>
my template
</script>
----
var whatever = $('#foo').html();
I would like to include the script in an external file like so:
<script type='text/template' id='foo' src='myTemplate.tpl'></script>
But the html() of foo is now empty.
I watched the browser pull the template file down, but I am not sure if it is in the page dom or not. Is there a simple way to reference the content of the script in javascript, or did the browser simply ignore it and throw out the result?
I think to actually execute externally loaded script you have to do an eval() of the contents. You're not adding it to the DOM really since it's script, you're adding it to the JS runtime. There might be other ways of doing it but eval() is generally considered a security hole since malicious code could be evaluated.
What I tend to do is generate template sections on the server so I know all my JS is there when the DOM is ready.
If the point is execute an action just after the script has been loaded you can put a onload attribute on the script tag. If you want to download the content in runtime, then you could use the async download strategy (like Gats pointed).
It´s important keep in mind some important points when using templates for jquery templates in external files, there is an interesting article about jquery templates with external files, you must check it.