One form, many uses - server side jQuery with Jaxer
I'm sure many of you have had to do 'corporate reviews' at work. You know, you get given a form and are asked to grade yourself on various aspects of your job. You fill in your parts of the form and then give it to your employer who fills in the rest. After doing so, he probably photocopies it, gives back to you for reflection, and then proceeds to make some private notes on his copy.
These days, especially for larger organisations, it might make more sense to do this kind of thing on the company intranet rather than wasting thousands of sheets of paper. However, in order to do this, you'll either need two separate forms (one for you and one for your boss), or the ability to view one form in different ways, depending on who is looking at it.
That is exactly what I want to try and do - create one 'master' form, and use server side DOM manipulation with Jaxer to disable, or completely remove certain form elements before they reach the client's browser. (If anybody read last weeks article 'Running server side processes via JavaScript with Jaxer' you may remember that I said I was going to look at the Jaxer.Request.data API this week. Well, I changed my mind!)
Anyway, I've set up an example which hopefully shows what I mean.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
<title>One form, many uses</title>
<script src="jquery.js" runat="both"></script>
<link href="style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<form method='POST' accept-charset='utf-8'>
<span>
<label>Name:</label>
<input type="text" name="name" disabled="disabled">
</span>
<span class="employee">
<label>How good are you at your job?</label>
<input name="rating" type="text"><br/>
</span>
<span class="employer">
<label>Areas to improve</label>
<input name="improve" type="text"><br/>
</span>
<span class="employer private">
<label>Notes: (not disclosed)</label>
<input name="notes" type="text"><br/>
</span>
</form>
<script type="text/javascript" runat="server-nocache">
// server side DOM manipulation here... (see below)
</script>
</body>
</html>
Breaking it down
The elements of this form have been 'tagged' with one or more of the following css classes which define if and how each element should be presented to the user.
- employer: only users with role 'employer' can edit
- employee: only users with role 'employee' can edit
- private: only users with correct role can view (must be combined with one of the above)
We can then use jQuery on the server side to select these elements and disable them, or even completely remove them from the DOM before they reach the clients browser:
// some kind of authentication to get current users role
role = getRole()
// remove private form elements
$((role == 'employer') ? '.employee.private' : '.employer.private')
.remove();
// disable irrelevant form elements
$((role == 'employer') ? '.employee input' : '.employer input')
.attr('disabled', 'disabled');
// no need to inject Jaxer client framework (saves about 20k)
Jaxer.response.setClientFramework();
By enclosing this script in <script runat="server-nocache">, we are telling Jaxer two things - the code should only run on the server, and that the code or should not be cached and will therefore not be available during callbacks. The DOM that the client receives will contain modifications made by this script on the server, but not the script itself nor any way of accessing it.
Once a role has been determined for the session (by some kind of user authentication method - but that's out of scope for this article), we use jQuery to locate certain form elements and disable, or completely remove them from the DOM. Remember though, that all this is happening on the web server, before the client receives anything.
In this example we're doing all of the work on the server. As a result, the client will not be making any ajax calls to server functions, and so has no need for the Jaxer Client Framework. So, we simply tell Jaxer not to inject the client framework in the DOM that's passed to the client's browser. Doing this makes a saving of about 20k in javascript downloads, so it's always worth asking yourself weather or not the client actually needs access to the Jaxer Framework.
Summing up
What we have done is created one 'master' form, and applied access restrictions to certain elements by 'tagging' them with css classes. We then used server side jQuery to manipulate the DOM and disable or completely remove unwanted elements. The DOM that the client receives, contains only the information that's relevant to them.
I think this need to view one form in several different ways is a common one. Other examples I can think of include include doctor/patient, job seeker/job agency, bank application forms, or any kind of application form for that matter. However, the technique is not limited to forms, and could be used to apply access restrictions to any DOM elements.
Can you think of any other uses for this technique? Any pitfalls, ways to do it differently or extend it?
LATEST ARTICLES
TODAY'S MOST POPULAR
-
8th Aug 08
-
4th Sep 08
-
14th Nov 09
MOST POPULAR ARTICLES
RECENT COMMENTS
-
1 day 23 hours ago
-
4 days 12 hours ago
-
4 days 18 hours ago
-
5 days 14 min ago
-
5 days 16 hours ago


Comments
25th Aug 2008, 6:26pm
Another nice use of server-side DOM manipulation. One note, regarding the runat attribute of your server-side JavaScript: since you're not defining any functions, any of the server-type values for runat would do just as well. They only differ in what they do with functions: "server" caches them in case they're needed during callbacks; "server-nocache" avoids caching them; "server-proxy" caches them but also makes them available as callbacks from the client. In your case I would have recommended "server" since it's the shortest one ;-) and also prevents you form accidentally proxying functions should you change your code and add some functions in the future.
26th Aug 2008, 12:46am
You're absolutely right. In fact, you'll notice that in the actual code I did user "server", it was only in the write up that I mentioned "server-proxy" - no idea why I did that, but I've updated to article so it's correct now. Thanks for pointing that out.
25th Aug 2008, 8:39pm
Excellent article.
some parallels with http://www.aptana.com/node/336 in scope. It has some additional code that uses the session object that is worth looking at.
8th Sep 2008, 12:45pm
20th Oct 2008, 9:01am
Lovely - I find articles like these the bedrock of what is great about the internet. Cheers ;-) Good Reference - Web Design Yorkshire
29th Oct 2008, 8:40am
Good work. but can u provide the source code download?
29th Apr 2009, 9:26am
One note, regarding the runat attribute of your server-side JavaScript: since you're not defining any functions, any of the server-type values for runat would do just as well. They only differ in what they do with functions: "server" caches them in case they're needed during callbacks
Please share your thoughts, comments and suggestions...