Free Trial

Safari Books Online is a digital library providing on-demand subscription access to thousands of learning resources.

  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint

3.3. New Elements

In addition to the new input types and the new attributes mentioned earlier, the specification also includes new elements for forms. We will discuss these in the next section. The elements meter and progress create graphical objects that previously could only be achieved with more or less complicated tricks. Suggestions for text input are offered by datalist, and output provides a placeholder for the results of calculations. The keygen element has been circulating through the World Wide Web for a long time but has only reached standardization with HTML5.

3.3.1. Displaying Measurements with “meter”

The meter element is used to graphically represent a scalar measurement within a known range. Think, for example, of the fuel gauge in your car: The needle shows the current level of fuel in your tank as somewhere between 0 and 100 percent. Previously, such graphic representations were usually coded in HTML with nested div elements, a rather inelegant solution for which the div element was probably not intended. A status display can also be displayed graphically, as a picture, through free web services, such as the Google Chart API. You can see all of these options in the example that follows.

Using the meter element is very simple: You set the desired value via the value attribute; all other attributes are optional. If you do not set a min and max value, the browser will use 0 and 1 for these attributes. So, the following meter element shows a half-full element:

<meter value=0.5></meter>

Apart from value, min, and max are also the attributes low, high, and optimum—values that the browser can incorporate into the display. Google Chrome (at the time of this writing, the only browser apart from Opera that is able to represent the meter element), for example, displays the normally green bar in yellow if the optimum value is exceeded.

In the following example you can see a graphic representation, showing the percentage of the current year that has already passed. The website presents a visualization of the output in four different ways: as text with a value in percent, using the new meter element, via nested div elements, and as graphics produced by the online service of Google’s Chart API. You can see the result in Figure 3.6.

Figure 3.6. The “meter” element and similar options for representing a state


The HTML code for this example contains the still empty elements, which are filled via JavaScript:

<h2>Text</h2>
<p><output id=op></output>
  % of the year has passed.</p>
<h2>The new <span class=tt>meter</span> element</h2>
<meter value=0 id=m></meter>
<h2>Nested <span class=tt>div</span> elements</h2>
<div id=outer style="background:lightgray;width:150px;" >
<div id=innerDIV>&nbsp;</div></div>
<h2>Google Chart API</h2>
<img id=google src="">
<p id=googleSrc class=tt></p>

For the text output, we use the output element introduced in section 3.3.5, Calculations with “output”. But first the current date is generated in JavaScript, and the meter element is initialized:

  var today = new Date();
  var m = document.getElementById("m");
  m.min = new Date(today.getFullYear(), 0, 1);
  m.max = new Date(today.getFullYear(), 11, 31);
  // m.optimum = m.min-m.max/2;
  m.value = today;

The variable today contains the number of milliseconds since the start of the UNIX epoch (on 1.1.1970). To make sure our meter element gets a sensible scale, we set the min value to January 1 of the current year and the max value accordingly to December 31. The value of the meter element is set in the last line of the listing; now the graphical representation is complete. If you activate the optimum value (in this case the middle of the year), which we left out, you will see the display change depending on whether you call the script in the first or second half of the year. The new element is wonderfully simple to use.

Let’s now move on to the other elements on our HTML web page. We want to assign the percentage of days passed to the output element tagged with the ID op. With Math.round(), we round up the percentage to the nearest number before the comma, which is plenty accurate enough for our example:

  var op = document.getElementById("op");
  op.value =
    Math.round(100/(m.max-m.min)*(m.value-m.min));

  var innerDIV = document.getElementById("innerDIV");
  innerDIV.style.width=op.value+"%";
  innerDIV.style.background = "green";

The rest of our example has nothing to do with new HTML5 techniques, but we still want to explain it for the sake of completeness. The nested div elements should also be filled with the percentage value. The idea behind this is simple: A first div area is defined in HTML with a fixed width (here, 150px). Nested into this element, another div element is displayed as filled with a green background color along the width of the calculated percentage value—a simple yet very effective trick. To round things off, we also want to include the Google Chart API. To use the online service, you have to specify the chart size (chs, in our case 200×125 pixels), the chart type (cht, here, gom, Google-O-Meter), and the chart data (chd, here, the percentage value op.value):

  var google = document.getElementById("google");
  google.src =
"http://chart.apis.google.com/chart?chs=200x125&cht=gom&chd=t:"+op.
value;
  var gSrc = document.getElementById("googleSrc");
  gSrc.innerHTML = google.src;

3.3.2. Displaying the Progress of a Task with “progress”

progress works in a similar way as the meter element discussed previously except that it represents the completion progress of a task. Such tasks could, for example, be file uploads by the user or downloads of external libraries required by an application.

To give you a quick example, we do not really want to upload any files or download a lot of data; it is sufficient to set ourselves a task and fulfill it 100 percent. Our following example defines ten input elements of the type checkbox, and as soon as they are all activated, we want the progress bar to show 100 %:

<h1>Please activate all the checkboxes</h1>
<form method=get>
  <input type=checkbox onchange=updateProgress()>
  <input type=checkbox onchange=updateProgress()>
<!-- and 8 more -->
  <p>
  Progress: <progress value=0 max=10 id=pb></progress>
</form>

The progress element is initialized with a value of 0 and a maximum value of 10. As soon as an input element is activated, it calls the function updateProgress(), which looks like this:

function updateProgress() {
  var pb = document.getElementById("pb");
  var ip = document.getElementsByTagName("input");
  var cnt = 0;
  for(var i=0; i<ip.length; i++) {
    if (ip[i].checked == true) {
      cnt++;
    }
  }
  pb.value = cnt;
}

The variable ip contains a NodeList with all input elements. Each of these elements is tested in the for loop for its condition. If it is activated (checked == true), the counter variable cnt increases by 1. To finish, the value of the progress element is set to the value of the counter variable.

3.3.3. Lists of Options with “datalist”

One long-awaited new function for forms is a drop-down menu to which you can add your own entries. Because the well-known select element is limited to the values specified as option elements, web developers used to come up with various JavaScript tricks to add expandable selection lists to text fields.

The HTML5 specification now has a very elegant solution to this problem. The new datalist element was defined to function as a container for the already familiar option element. Now we can assign to each input element a datalist element that displays the selection options when needed. Browsers that do not support the datalist element will only display the empty text field.

Listing 3.1 shows the use of the new element. The input element is defined by the type text, and the attribute list refers to the id of the datalist element (in this case, homepages). When the page is loaded, the autofocus attribute positions the cursor automatically inside the text field (see section 3.2.1, Focusing with “autofocus”) and ensures, at least with the Opera browser, that the selection list appears (see Figure 3.7).

Figure 3.7. Opera, representing a “datalist” element


For the option elements within the datalist, you just need to fill the value attribute. Further attributes and a text node are possible but not required for this use. If the user clicks the Submit button, the content of the text field is prefixed with the character string http:// and the browser is redirected to the resulting URL (window.location):

Listing 3.1. The “datalist” element filled with Internet addresses

<form>
  <p>
  <label for=url>Goto</label>
  http://<input type=text id=url name=homepage
                 list=hompages autofocus>
  <datalist id=hompages>
    <option value=www.google.com>
    <option value=html5.komplett.cc/welcome>
    <option value=slashdot.org>
    <option value=wired.com>
  </datalist>
  <input type=submit
    onclick="window.location =
    'http://'+document.getElementById('url').value;
    return false;" >
</form>

If you want to equip older browsers with a selection list without duplicating the HTML code, you can fall back on the following trick. Because browsers supporting the datalist element ignore an enclosed select element, they display the new HTML5 select element. Older browsers, however, display a selection list for the text field with predefined links, which will be inserted into the text field when the selection is changed.

As you can see in Listing 3.2, we need to add a text node to the option elements because the “old” select element does not show the content of the value attribute but instead shows the text:

Listing 3.2. A “datalist” with the fallback for older browsers

<datalist id=hompages>
<select name=homepage
  onchange="document.getElementById('url').value =
    document.forms[0].homepage[1].value" >
  <option value=www.google.com>www.google.com
  <option
  value=html5.komplett.cc/welcome>html5.komplett.cc/welcome
  <option value=slashdot.org>slashdot.org
  <option value=wired.com>wired.com
</select>
</datalist>

The onchange event within the select element inserts the current text of the selection menu into the text box (see Figure 3.8).

Figure 3.8. A combination of “input” and “select” elements as fallback for older browsers (here, Internet Explorer 8)


3.3.4. Cryptographic Keys with “keygen”

The keygen element has a long history in the Mozilla Firefox browser (included since version 1.0), but Microsoft still expressed great concern regarding the implementation in HTML5. keygen is used to generate cryptographic keys, which sounds complicated, and unfortunately, it is just as complicated as it sounds.

Simply put, the idea behind this element is this: The browser creates a pair of keys, one a public key and the other a private key. The public key is sent off with the other form data and is then available to the server application, whereas the private key remains saved in the browser. After this exchange of keys, the server and browser can communicate in encryption without SSL certificates. This sounds like a practical solution for those pesky self-signed certificates, which browsers keep complaining about, but sadly it is not, because the identity of the server can only be verified through a certificate that has been signed by a trustworthy authority, the Certificate Authority (CA).

So if keygen cannot replace SSL, what should the new element be used for? As explained in the Mozilla documentation, the keygen element helps create a certificate that the server can sign (signed certificate). To make this step totally secure, it is usually necessary for the applicant to appear personally before the authority. Because the issuing of signed certificates is a task for experts, we will briefly describe this element and its attributes.

The following short HTML document creates a keygen button:

<!DOCTYPE html>
  <meta charset="utf-8">
  <title>keygen Demo</title>
  <form method=post action=submit.html>
    <keygen id=kg challenge=hereismychallenge name=kg>
    <input type=submit>
  </form>

In addition to the familiar attributes, such as autofocus, disabled, name, and form, the keygen element has two special attributes: keytype and challenge. keytype in particular is interesting because the browser uses this entry to decide if it supports this element’s function. Currently, there is only one valid keytype, which is rsa, a cryptographic system developed in 1977 at the Massachusetts Institute of Technology (MIT). If no keytype is specified (as in the preceding example), rsa is used as the default value. The specification also states that a browser does not have to support any keytype at all, which is probably because of Microsoft’s veto against this element. The optional challenge attribute increases security during the key exchange. For further information, please refer to the links in the note at the end of this section.

If the browser supports the RSA key generation, it can offer a selection list to allow the user to select the length, and consequently the security, of the key (see Figure 3.9).

Figure 3.9. Selecting the key length in Google Chrome


Figure 3.10 shows the result after the form has been sent: The POST variable kg contains the public key required for encryption (here, rendered in the extremely useful Firefox add-on Firebug).

Figure 3.10. The public key of the “keygen” element, represented in Firebug


Note

If you have not had much previous experience with cryptography but would like to find out more, Wikipedia is always a good starting point. Check out http://en.wikipedia.org/wiki/Public_key_infrastructure and http://en.wikipedia.org/wiki/Challenge-response_authentication.


3.3.5. Calculations with “output”

“The output element represents the result of a calculation.” That is the very short explanation in the HTML5 specification, and you will find exactly the same text on most websites describing the new element. It all sounds very sensible, but what kind of calculations are we dealing with? Why do we need a special element for them?

As a general rule, these are calculations resulting from input fields on a website. An example familiar to most people would be an electronic shopping cart where the quantity for each product can be entered in an input field. Via the optional for attribute, you can determine which fields to include in the calculation. One or more id attributes of other fields in the document are referenced in the process.

To test the output element, we will program one of these little shopping carts for three different products. The quantity of each of these products can be changed via an input field. At the same time, the total number of items and the total price are displayed under the shopping cart. Figure 3.11 shows a shopping basket with five items.

Figure 3.11. Two “output” elements show the number of products and the price in total


The code for our example can be explained quickly and simply: To update the output elements for each change in quantity, we use the form’s oninput event:

<form oninput="updateSum();">
  <table>
    <tr><th>Product<th>Price (US$)<th>Item number
    <tr><td>Keyboard<td class=num id=i1Price>39.50<td>
    <input name=i1 id=i1 type=number min=0 value=0 max=99>
    <tr><td>Mouse<td class=num id=i2Price>26.30<td>

The output elements are defined after the table with the products and refer to the IDs of the input fields via the for attribute:

<p>Your shopping cart contains <output name=sumProd for="i1 i2 i3"
  id=sumProd></output> items. Total price:
  <output name=sum for="i1 i2 i3" id=sum></output> US$.

In the JavaScript code, a loop runs over all input elements, adding the quantities and calculating the total price:

function updateSum() {
  var ips = document.getElementsByTagName("input");
  var sum = 0;
  var prods = 0;
  for (var i=0; i<ips.length; i++) {
    var cnt=Number(ips[i].value);
    if (cnt > 0) {
      sum += cnt * Number(document.getElementById(
        ips[i].name+"Price").innerHTML);
      prods += cnt;
    }
  }
  document.getElementById("sumProd").value = prods;
  document.getElementById("sum").value = sum;
}

We get the product price directly from the table by using the innerHTML value of the relevant table column and converting it to a number with the JavaScript function Number(). The same applies to the value in the input field (ips[i].value), because without this conversion, JavaScript would add up the character strings, which would not produce the desired results. The calculated values are then inserted into the value attributes of the output elements.

  • Safari Books Online
  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint