ColdFusion in Context: Disable Text and Check Boxes
Suppose you don't want to create separate code for display and edit of a complex logical record. After all, when you label data on two different pages, it's easy to forget to change one of them later. How can you discourage the user from changing fields when the page is presented for display only? One answer is to disable user input with a combination of javascript and HTML.
You may ask why one technique or the other won't be enough by itself. Part of the answer is that not all input fields are created equal. Another part of the answer is that browsers vary; they don't all obey the same controls. The techniques presented here will work with most browsers. I'm indebted to many workers in javascript and HTML magic for pieces of the consolidated approach used here.
Overview
You want ColdFusion to block and unblock the form depending on if it is being used for edit or display. However, ColdFusion can only impact javascript by writing the javascript on the fly or by changing something (a URL, the contents of a form field, a cookie) that javascript will notice. For this demonstration, you'll add "?1" to the URL to lock the form or anything else (not ending in 1) to leave it unlocked. The default values displayed by the fields are hardcoded here but would normally be query-driven. A function that executes on load reads the URL, locks or unlocks the form elements, and sets the value of the hidden field "blocked" to 1 for locked or 0 for unlocked.
Begin the Page; Prepare to Shift Text Focus
All the code in this example is in one file; call it onoff.cfm. Because the onLoad attribute will be used at the beginning of the body, the head is formally introduced here rather than ignored. If "blocked" is not 1, the divert function does nothing but return true. If "blocked" is 1, the divert function will shift the focus to doit, the submit button of the form, when the user tries to change text that has been protected by this function.
<head>
<script>
function divert()
{
if (document.myform.blocked.value != 1) return true;
document.myform.doit.focus();
}
Prepare to Bounce Checkbox Changes
In this form, all the checkbox names consist of "c" followed by an integer. The first checkbox calls change(1) when the user checks it, the second checkbox calls change(2), and so forth. This is a simple way of telling this function which checkbox needs to be examined. If "blocked" is not 1, this function does nothing. If it is, it looks at the current value of the checkbox and sets it to its opposite, undoing whatever the user did. The eval function is used here to construct the fully-qualified name of the checkbox on the fly.
function change(unique)
{
if (document.myform.blocked.value != 1) return;
eval("document.myform.c"+unique+".checked = ! document.myform.c"+unique+".checked");
}
Prepare to Lock and Unlock the Form
If the URL ends in 1, the lock function is executed. It sets "blocked" to 1 and disables all the fields. This will cause some browsers to gray out the fields and keep the user from changing them. Others will ignore this attribute for some kinds of fields; that's why it's necessary to simulate the attribute's effects by shifting the focus of text fields and by resetting the values of checkboxes. t1 and t1 are text fields; c1 through c5 are checkboxes.
function lock()
{
document.myform.blocked.value = 1;
document.myform.t1.disabled = true;
document.myform.t2.disabled = true;
document.myform.c1.disabled = true;
document.myform.c2.disabled = true;
document.myform.c3.disabled = true;
document.myform.c4.disabled = true;
document.myform.c5.disabled = true;
}
function unlock()
{
document.myform.blocked.value = 0;
document.myform.t1.disabled = false;
document.myform.t2.disabled = false;
document.myform.c1.disabled = false;
document.myform.c2.disabled = false;
document.myform.c3.disabled = false;
document.myform.c4.disabled = false;
document.myform.c5.disabled = false;
}
Set the Form and Close the Header
The javascript substring function has odd syntax relative to other languages you may have used. This combination causes "mode" to be set to the last character of the URL. You can find javascript references that tell how to hunt for the question mark of a query string and grab what follows, but this is sufficient for this demonstration. When the page finishes loading, if the URL ends in 1, the form gets locked; otherwise, it gets unlocked.
function direct()
{
mode = document.URL.substring(document.URL.length,document.URL.length-1);
if (mode == 1) lock();
else unlock();
return true;
}
</script>
</head>
<body onLoad="direct()">
Create the Form and Finish the Page
Most of the work is already done; the form itself is fairly straightforward. Because we won't process the contents of this form, the action and method have been omitted. Every text field invokes the divert function when the user tries to focus on it. Every checkbox invokes the change function (with the appropriate parameter) when the user checks it. A hidden field, "blocked", has been defined to let functions keep track of the state of the form. The submit button, "doit", is more than a form control; it receives the diverted focus of attempts to change text.
<form name=myform>
A<input type="text" name="t1" value="apple" onFocus="divert(this)"><br>
B<input type="text" name="t2" value="banana" onFocus="divert(this)"><br>
<input type="checkbox" name="c1" value="one" onclick="change(1)">one<BR>
<input type="checkbox" name="c2" value="two" onclick="change(2)">two<BR>
<input type="checkbox" name="c3" value="three" onclick="change(3)">three<BR>
<input type="checkbox" name="c4" value="four" onclick="change(4)">four<BR>
<input type="checkbox" name="c5" value="five" onclick="change(5)">five<BR>
<input type="hidden" name="blocked" value="0">
<input type="submit" name="doit" value="done">
</form>
</body>
Try it Out
Now to see the results. Call the locked form with 1 at the end of the URL as in onoff.cfm?1. Call the unlocked form as onoff.cfm?0; notice that your changes appear in the URL when the unlocked form is submitted. Because your action page will confirm the correct mode (won't it?), don't be too concerned that users may change the URL; because, you're not going to let unauthorized changes won't reach the database.
That doesn't mean they won't reach the action page. The mix of form values that reaches the action page will vary with the browser type; because, not all browsers handle the disabled attribute the same way. Just be aware of what you should be doing (or not doing) with the data the page sees.
Now flesh out the concept. For example, use the mode to select an appropriate action page. Learn how to disable other form elements. Then, share the wealth. =Marty=
[After publication, the hidden "blocked" input was moved to be the last input so the form would remain locked after submission for this demo, and the hint to watch the URL when submitting the unlocked form was added.]