I have a web application where a lot of inline javascript is used. For example:
<input type="button" id="btn1" onclick="return test();">
I want to separate javascript code from the UI by placing it in a separate file or inside the script tag. Including javascript event attachment. For example instead of the above I'd have:
<input type="button" id="btn1">
and in the script section I'd us:
<script type="text/javascript>
btn1.onclick = function() {
test();
}
</script>
or
<script type="text/javascript>
if (btn1.addEventListener){
btn1.addEventListener('click', test, false);
}else if (btn1.attachEvent){
btn1.attachEvent('onclick', test );
}
</script>
Why do I want to do that? I like separating my UI from the business logic and database, that's my general approach. Also it is better from performance standpoint, as external javascript can be easier cached by browsers. Another reason - it is more secure. My question is whether this is worth the hassle of changing the application, removing all the inline javascript?
I'd appreciate if someone gave me some pointers, some links to articles - I have been searching the web and found some conflicting information. Would appreciate to hear some opinions
From the maintenance point of view is much easier to have at least two separate files: html and js. After that you can have a separation between UI, business logic and data. You can check this question for more information on design patterns.
I'm fully in favor of separating JS code from markup, mostly for maintenance reasons and clarity of intent. As you pointed out, it's also better from a caching perspective.
I would go one step further and suggest that you would also benefit from a framework (pick your poison, there are plenty of good options, but jQuery is a good place to start as it's very well documented and handles a lot of the boilerplate stuff like your example has (browser differences, etc).
All that said, one part of your question made me curious. In what way do you think having javascript in a separate file will make your pages more secure?
Related
I have a lot of inline javascript, but nothing more then calls to functions such as:
<form id="some_id" style="x" method="post" onsubmit="return someFunction(this);"></form>
or "onchange", "onkeyup". I also have some scripts (not many) written inside <script> tags in html and all of the rest is external. The inside calls just as explicit above are all called to external script functions.
I opted to do this because found it more practical considering many async calls with element insertion and needed listeners to register those changes. This is, $.on("form onsubmit", function(){ would not apply to new elements appended async without a listener.
I'm building new elements in the server side due to my template structure and append them directly on the ajax callback.
My main file.js (external) is sitting at 1832 lines and and my index file which includes file.js has about ~500, ~350 with inline javascript as shown above.
This said:
Would it be considered a huge flaw to leave inline javascript as shown above (yes I know google does that) or could it be considered acceptable even by high standards?
Considering "inline javascript is not kept in cache", what does that mean exactly? Each time the user requests the web page he fetches the whole "onsubmit" in the line above? Or am I missing the meaning of this sentence.
Sorry if the question is vague but I'm quite thinking I had most of my service barely done and don't know if I should go over this or not at all :( thank you very much.
It's really hard to define "huge flaw" so let's just stick to pro's and con's of keeping the code "as-is":
Pro's :
Your current code works : No additional work is needed.
Con's :
Harder to debug : you JS is split on many places, a bug will be harder to track using the browser debug tools.Especially for more experienced JS developers who "expect" (or at least hope) the code to be organised following the good practices, like separating HTML, JS and CSS.
Speed : Your clients have to download and parse the additional JS with each query. If you were able to factorize all these methods calls in the main JS file, this would not be needed.
Modularity : all the methods you are calling from the HTML have to sit in the global namespace. The script you have written will be harder to reuse.
So basically, I would keep the code like this if the website is meant to be developed by you only, won't be used by million people and if you do not hope to reuse any of this code on another project.
If any of these condition is not met, I would refactor the code.
Also, refactoring the code, and learning how to correctly bind handler is a very good exercice if you plan on learning some more javascript.
$('body').on('onsubmit', 'form', function(){});
This will deal with any future changes to the DOM.
I'm building a website and considering using pure dynamic pages, i.e. no html files and everything is handled by a router in javascript and the DOM elements are all created and inserted to the document by javascript.
I'm just wondering whether it's a good idea. IMHO, events can be attached to DOM elements when they are created, which may make the code more readable. And the static and dynamic parts might be better incorporated. But the page format may become unclear. And I'm not so sure whether performance will be compromised.
Is anyone aware of any websites that actually use this approach?
Thanks a lot!
The question is a bit vague, but you're probably looking for something like any number of the new-age JavaScript front-end MVC frameworks:
http://angularjs.org/
http://meteor.com/
http://backbonejs.org/
etc.
Try pure, a javascript library, which separates representation(HTML) and logic(js), making the code clear and easy to understand.
It also supports integration with major javascript libraries.
pure.js Example
HTML template
<div class="hello">
<span class="who"></span>
</div>
Rendering directive
{
"span.who":"who"
}
JSON Data
{
"who":"Hello Wrrrld"
}
The resulting HTML
<div class="hello">
<span class="who">Hello Wrrrld</span>
</div>
I run into following code in my project:
html:
<input type="button" id="addmore" value="Add more" onclick="add_table(this)"/>
js:
function add_table(elem){
var current_id = jQuery("table.t1:last").attr("id");
First I thought that this code is wrong and I must rewrite it to external code, i.e.
jQuery('#addmore)'.click(function add_table(elem){
var current_id = jQuery("table.t1:last").attr("id");
But then I looked at it again and found that this html is more readable - I see which functions binds to which elements already in html, and I don't need to search it in js.
Of course it not encapsulated inside
jQuery(document).ready(
so it will not work under some circumstances
So question: how bad this code is?
It's a question re-usability and personal taste. Inline code is more readable for very simple things like your example, but of course you are relying on add_table() being a global function - if you have hundreds of elements with different click handlers, you could end up with hundreds of functions/variables polluting the global namespace. And that's bad! :)
In terms of re-usability, I find it better to code in distinct components that abstract functionality and can be called upon whenever needed - all within a defined (non-global) namespace.
jQuery('#addmore)'.click(function add_table(elem) {
var current_id = jQuery("table.t1:last").attr("id");
}
The code above gives a good separation of concerns - meaning the semantic information (HTML) is oblivious to the behavioural information (Javascript), which again helps create cleaner, more manageable code.
Depending on the size of your site (and level of traffic) there might be a bandwidth issue. i.e. onclick="add_table(this)" adds 24 bytes of data to a download. This could be put in a cached JavaScript page which only gets downloaded once, rather than for each request. If you have lots of pages with extra code in them an you have a lot of traffic it may make a noticeable bandwidth difference.
What UI patterns do you usually use in JavaScript?
By UI patterns I mean best practices to be used to build and organize UI, generated/managed from JavaScript (apart from libraries like jQuery or YUI).
For example, if you came from .NET world you are familiar with MVC (Model-View-Controller) patterns family. In the world of WinForms and ASP.NET you will meet Model-View-Presenter. In WPF most likely you will find MVVM (Model-View-ViewModel) approach.
And what about JavaScript?
Patterns are usually language-agnostic. If a pattern has value, barring certain edge cases it will have value regardless of what language or technology you're using. Take MVC. The concept of separating the model from the view from the controller has value regardless of whether the model is implemented with an RDBMS or some other technology, whether the view is HTML or Swing or X.
Where you see certain patterns applied more in one technology than another, it usually just means that the developers of the technology had a particular approach that they supported more fully than others.
JavaScript itself doesn't impose any particular pattern on you. Some JavaScript frameworks, like YUI or Dojo or Glow will tend to lead you one direction more than another.
At the end of the day, look at the problem you're solving, the resources and experience you have, and follow the patterns that make sense.
I'd like to recommend Ross Harmes & Dustin Diaz's book, Pro JavaScript Design Patterns, definitely the best resource on this subject, and definitely worth a read.
There’s also a very interesting article on JavaScript MVC in the latest issue of A List Apart.
A good approach to building GUI application is that of browser:
using markup for UI layout
using javascript UI logic
using CSS for UI styling
Most of modern GUI frameworks (ExtJS, Dojo etc) offer APIs that greatly help building GUI in JavaScript solely. But there is another GUI framework Ample SDK that brings the before mentioned separation of concerns. It allows for using XML-based languages (XHTML, XUL, SVG) for layout, CSS for style and DOM APIs for UI logic.
To orchestrate a client-side GUI application you can use either MVC or a little bit more advanced pattern PAC, as for the former - there is a PureMVC implementation available
Take a look at the following snippet (only concerns UI logic, not app logic, to be built with MVC/PAC):
index.html
<script type="application/ample+xml">
<xul:tabbox onselect="fOnSelect(event)"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<xul:tabs>
<xul:tab label="checkbox" />
<xul:tab label="textbox" />
<xul:tab label="datepicker" />
</xul:tabs>
<xul:tabpanels>
<xul:tabpanel>
<xul:checkbox />
</xul:tabpanel>
<xul:tabpanel>
<xul:textbox />
</xul:tabpanel>
<xul:tabpanel>
<xul:datepicker />
</xul:tabpanel>
</xul:tabpanels>
</xul:tabbox>
</script>
index.css
#namespace xul url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
xul|tab:focus {
color: red;
}
index.js
function fOnSelect(oEvent) {
alert(oEvent.currentTarget.selectedItems.length)
}
As i know there are no specific patterns for Javascript yet. But I think there is a potential for something like widgets(component) approach. Since mainly we use javascript to empower our html code. It is logically that we should connect our every javascript object to html tag. So here we have something like Model(jsObject)+View(HTMLrepresentation). To get MVC we need controllers and we have Events for this. In this case we will have incapsulated easily extensibel component.
for example:
// this is a part of some FormValid.js
<script>
function FormValid(){
}
FormValid.prototype.validate=function(){...}
</script>
//this is our HTML
<form id="form1"...onsubmit="this.jsObject.validate();">
</form>
<script>
//all the following stuff could be solved in one line, but you need to create some helper. Like Components.Attach("FormValid").to("form1");
var newObj=new FormValid()
var form=document.getElementById("form1");
from.jsObject=newObj;
newObj.htmlObj=form;
</script>
Also I have an idea of using template engines like Zparser to separate view and model. I am developing js library for this, so I am in this question right now.
We have core object with view method. All our classes have it like a prototype at he end. This method gets templates property of class and using some templates parser generates HTML basing on our model. This HTML is inserted in htmlObj node so the VIEW of our object is updated. This is basically an idea and our code becomes:
// this is a part of some FormValid.js
<script>
function FormValid(){
}
Components.extendCore(FormValid);
FormValid.prototype.validate=function(){...}
</script>
FormValid.prototype.templates={
main:'<form class="form1"...onsubmit="this.jsObject.validate();">...</form>'
}
//this is our HTML
<div id="form1"></div>
<script>
Components.Attach("FormValid").to("form1");
</script>
I still think last one inline <script> should be there and it is not mixing logic with representation because this is component - solid piece. It have no meaning one without another. Actually this should be a part of application. Something like html of component(in las one example is div) should be defined and wrapped with component which will automatically add script and ids.
Now. I showed you 2 examples and i will explain why second is too specific. All stuff is in accessibility and performance(and memory leaks). If you will refresh all html of component frequently - it will blink, also you will need to set up all dynamic events back and check everything for memory leaks. But the main problem if JS will fail - your application will show nothing.
So i prefer to have choice between those two:) and use everything on their places.
Check out a site called quince. I am not sure how many patterns here are javascript ui patterns. But this is a pretty good resource for ui patterns
Patterns aren't always language agnostic. A lot of classic design patterns are pointless in JavaScript because we don't need a lot of the workaround that they solve in stricter langauge paradigms.
The reason MVC isn't such a hot fit for client-side web development, however is more situational.
First of all I think time and pain have proven that typical web applications are best treated as two separate applications. The one that happens on the browser and the one that happens on the server. The fewer dependencies you establish between the two, the more flexible, maintainable and easier web apps have been to modify in my experience.
The M is business logic (which people tend to incaccurately conflate with "database layer" IMO).
The problem with MVC in that scenario is that we don't want to expose business logic on the client-side and attempting to munge the whole app into one hideous http-divide-hiding construct has proven painful as I mentioned.
Very similar patterns where you separate data or "view model" concerns can work fairly well, however.
I'm developing a facebook app right now all by my lonesome. I'm attempting to make a javascript call on an onclick event. In this onclick event, I'm populating some arguments (from the server side in php) based on that item that is being linked. I'm inserting a little bit of JSON and some other stuff with funky characters.
Facebook expects all the attribute fields of an anchor to be strictly alphanumeric. No quotes, exclamation marks, anything other than 0-9a-Z_. So it barfs on the arguments I want to pass to my javascript function (such as JSON) when the user clicks that link.
So I thought, why don't I use my templating system to just autogenerate the javascript? For each link I want to generate, I generate a unique javascript function (DoItX where X is a unique integer for this page). Then instead of trying to pass arguments to my javascript function via onclick, I will insert my arguments as local variables for DoX. On link "X" I just say onclick="DoX()".
So I did this and viola it works! (it also helps me avoid the quote escaping hell I was in earlier). But I feel icky.
My question is, am I nuts? Is there an easier way to do this? I understand the implications that somehow somebody was able to change my templated local variable, ie:
var local = {TEMPLATED FIELD};
into something with a semicolon, inserting arbitrary javascript to the client. (and I'm trying to write code to be paranoid of this).
When is it ok (is it ever ok) to generate javascript from the server? Anything I should look out for/best practices?
Depending on your application generating JavaScript in your templating language can save a lot of time but there are pitfalls to watch out for. The most serious one being that it gets really hard to test your JavaScript when you don't have your full templating stack available.
One other major pitfall is that it becomes tempting to try and 'abstract' JavaScript logic to some higher level classes. Usually this is a sign that you will be shaving yaks in your project. Keep JavaScript login in JavaScript.
Judging from the little bit of information you have given it your solution seems sensible.
If you must generate javascript, I would suggest only generating JSON and having all functions be static.
It more cleanly separates the data, and it also makes it easier to validate to prevent XSS and the like.
JS generated from server is used in lots of areas. The following is the sample from a ASP.NET page where the JS script is generated by the framework:
<script src="/WebResource.axd?d=9h5pvXGekfRWNS1g8hPVOQ2&t=633794516691875000" type="text/javascript"></script>
Try to have reusable script functions that don't require regeneration; and 'squeeze' out the really dynamic ones for server-side generation.
If you want to feel better about it, make sure that most of your JavaScript is in separate library files that don't get generated, and then, when you generate code, generate calls to those libraries rather than generating extensive amounts of JavaScript code.
it's fine to generate JS from the server. just bear in mind not to fine too big a page from the server.
Generally speaking I avoid ever automatically generating JavaScript from a server-side language, though I do however; create JavaScript variables that are initialized from server-side variables that my JavaScript will use. This makes testing and debugging much simpler.
In your case I may create local variables like the following which is easy to test:
<script type='text/javascript' language='javascript'>
<!--
var FUNC_ARG_X = <%= keyX %>;
var FUNC_ARG_Y = <%= keyY %>;
var FUNC_ARG_Z = <%= keyZ %>;
//-->
</script>
<script type='text/javascript' language='javascript'>
<!--
function DoCleanCall(arg) {
// Whatever logic here.
}
//-->
</script>
now in your markup use:
<a href='#' onclick='DoCleanCall(FUNC_ARG_X);'>Test</a>
Now of course you could have embedded the server-side variable on the <a/> tag, however it is sometimes required that you refer to these values from other parts of your JavaScript.
Notice also how the generated content is in it's own <script> tag, this is deliberate as it prevents parsers from failing and telling you that you have invalid code for every reference you use it in (as does ASP.NET), it will still fail on that section only however.