JavaScript Exercise

22 07 2011

Pencil and Paper Time

by quacktaculous

Write code so that if user clicks a button, the value of one text input is duplicated and assigned as the value of other such inputs. Without using a computer, see what you can devise using only pencil and paper.

Yeah, right. The above instructions tempt me instead to create paper airplanes adorned with cute doodads.  I suggest that we leave “the Stone Age” behind and go about this trivial coding exercise using appropriate hardware and software, like a computer, keyboard, text editor and web browser. After all, JavaScript is virtually useless when etched on a dead tree.

The problem itself is seemingly a purely academic exercise without any real-world application. Or, is it? Suppose you needed the user for some reason to set inputs to a default value of his/her choice, you may find one of the following snippets useful.

To knock out the HTML, the example below uses HTML5 as it is rapidly becoming the new default standard for web pages.  In an actual test situation, you may prefer to write your code with XHTML instead since there are employers are who still resistant to HTML5.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset=utf-8>
<title>Test for Job</title>
<link rel="stylesheet" type="text/css" href="form_styling.css">
</head>
<body>
<form name="myform" id="myform">
<input id="a" name="a" autofocus placeholder="Enter a number between 1 - 100" pattern="[-0-9]+" maxlength="3" required>
<input id="b" name="b" pattern="[-0-9]+" maxlength="3" required>
<input id="c" name="c"pattern="[-0-9]+" maxlength="3" required>
<input id="d" name="d"pattern="[-0-9]+" maxlength="3" required>
<button id="but" name="but">Go</button>
</form>
<script src="copy.js" type="text/javascript">
</script>
</body>
</html>

Whether you use XHTML or HTML5, is immaterial. The key to solving this exercise is JavaScript. Note that the example HTML has the JavaScript tags at the end of the body element, which is useful for enhancing page load (see Yahoo’s Best Practices for Speeding Up Your Web Site). On the other hand, PPK argues for placing the script tags in the head section (see his blog Quirks Mode: Placing JavaScript in your pages — last paragraph).

I avoid embedding the page with JavaScript, choosing instead to import a file using the SRC attribute of the script tag to include copy.js, taking an approach that favors applying an MVC style to the front-end (see See PPK’s Quirksmode: Placing JavaScript in your pages and also html-css-and-javascript-model-view.html).

You may observe that I have not included code for the form_styling.css file. I leave that to you to determine how you want your form to look.

Now, let’s turn our attention to determining the contents of copy.js. If you process instructions literally, you might be tempted to write the following code:

document.getElementById('but').onclick = function()
{
var val = document.getElementById('a').value;
document.getElementById('b').value = val;
document.getElementById('c').value = val;
document.getElementById('d').value = val;
};

The above code should work, causing the two specified inputs to acquire the value of the first one. But is this good coding style, let alone excellent? Notice that document.getElementById is used probably more than is necessary, so this approach is merely adequate at best.

Let’s use a little short-hand and that way we’ll have less verbosity which should speed things up  How about the following:

var dget = document.getElementById;
dget('but').onclick = function()
{
var val = dget('a').value;
dget('b').value = val;
dget('c').value = val;
dget('d').value = val;
};

The code may seem better, but the net gain is only marginal. While document.getElementById is dereferenced only once, each dget call needs to be evaluated and in addition, I’ve just made the code more confusing to decipher at a glance; the code has to be studied to grasp what dget really is. Hmm, let’s try something different, as follows:


myform.but.onclick = function() {
var val = myform.a.value;
myform.b.value = myform.c.value = myform.d.value = val;
};

This code gets points for brevity  but it relies on DOM 0 (see http://www.quirksmode.org/js/dom0.html), an old-fashioned approach that is still feasible (see http://javascript.about.com/od/reference/a/component.htm).  If we were to add more inputs to the mix, then the third line  could end up growing with the code  becoming vulnerable to breakage. Shall we try again?


var f = document.getElementById("myform");
document.getElementById("but").onclick = function() {
var val = f.elements[0].value;
for (var i = 0; i < f.elements.length; i++) {
f.elements[i].setAttribute("value",val);
}
return false;// return false or solution fails to stick in Safari
};

This example  embodies an actual programming solution. Notice that instead of an assignment statement, I use  an element’s setAttribute method.  Each  input value is set programmatically which makes the code more robust than the previous solution.  This code is also more efficient since it uses document.getElementById about half as much as in the first example. Yet, there is  a flaw.

The code  relies on the old-fashioned form elements collection (see http://www.w3schools.com/jsref/coll_form_elements.asp) which is apparently an historic best practice rather than a current one (see http://stackoverflow.com/questions/2435525/best-practice-access-form-elements-by-html-id-or-name-attribute). Another issue involves referring to the first input with numeric indexing which can be problematic, especially if one decides to add another input and change the order so that the new one is first.

The following example is similar to the previous one. The only real difference is that I use HTML DOM to access all the inputs with document.getElementsByTagName. I also use the item property of each input in making changes.


document.getElementById("but").onclick = function()
{
var inputs = document.getElementsByTagName('input');
var val = inputs.item(0).value;
for(var i=0; i < inputs.length; i++ )
{
inputs.item(i).value = val;
}
};

After collecting all the inputs, the code loops through them and assigns the value of the first input to all of them, even itself!

The following is a variation of the above solution.   The code also makes use of the form’s firstChild property and uses array indices instead of item which may aid legibility. Lastly using an assignment statement to set a value is faster than repeatedly using the method setAttribute as done in a previous example.


var f = document.getElementById('myform');
f.but.onclick = function() {
var val = f.firstChild.value;
var inputs = document.getElementsByTagName('input');
for (i = 0; i < inputs.length; i++) {
inputs[i].value = val;
}
};

Of course, we might do even better in terms of cross browser compatible code by using a JavaScript library such as Scriptaculous or the more popular jQuery. Let’s take a look at what such code looks like with jQuery. We need to amend the HTML to include that library. You could link to the latest version of it that Google makes available. In this case, I use my local copy of jQuery and amend the HTML by adding the following code above the other pair of script tags that refer to including copy.js (see above HTML example) as follows:


<script type="text/javascript" src="jquery.js"></script>

I change the contents of copy.js so now the file contains the following code:

$(document).ready(function(){
$("input#a").focus().select();
$("button").click(function(e){
var myval = $("input#a").val();
$('input').val( myval );
e.preventDefault();
});
});

Note how the jQuery script in this example compensates for XHTML lacking an autofocus attribute by chaining the first input’s focus and select methods. The val() is quite clever. Without a parameter, it will extract a value and with a parameter, it sets an element’s value. Lastly, observe how all the input text values are set by the one-liner in line 5.

If you try out the HTML5 code above, you may find that it may work only partially depending on the browser. For example, the placeholder text works in FireFox 5 but not Safari 5.0.4 on a windows desktop running XP, service pack 3. Remember, HTML5 is still an evolving standard!

This work is licensed under a Creative Commons License


Actions

Information

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.