Dynamic Sizing

Elements on a page can be resized in response to user events. The script to resize an element needs to change the element's width and/or height style settings, either as replacments or calculated values. Pertinent style properties are shown in the following table.

CSS and DOM Reference Effects
width:value
object.style.width="n"
Sets the width of the element; n is a string measurement, either in pixels or percentages.

height:n
object.style.height="n"
Sets the height of the element; n is a string measurement, either in pixels or percentages.

object.style.pixelWidth=n Sets the width of the element; n is numeric for use in calculations.

object.style.pixelHeight=n  Sets the height of the element; n is numeric for use in calculations.

Figure 13-16. Element width and height properties.

As in the case of top and left positioning properties, width and height settings are string values that can be used as replacements. Calculated widths and heights must be done through pixelWidth and pixelHeight numeric values.

The following image is resized by resetting its width property when the image is clicked (the height property is not specified in order to maintain proportionality). In this case, the width of the image is changed by reassigning a different string value as the width property.




Figure 13-17. Changing an element's size.
<img src="GREECE.jpg" style="width:100px; cursor:move"
  onclick="this.style.width='200px'"/>
Listing 13-13. Code to change an element's size.

In contrast, the following image is resized incrementally. Each time the mouse is clicked on the image, it's width is increased by 30 (pixels); when the mouse is clicked with the Ctrl key depressed, the image width is decreased by 30 (pixels). Since the width is a calculated value, the pixelWidth property is used in the script.



Figure 13-18. Resizing an element through calculations.
<script type="text/javascript">

function Resize(Picture) 
{
  if (event.ctrlKey) {
    if (Picture.style.pixelWidth > 50) {
      Picture.style.pixelWidth -= 30;
    }
  } else {
    if (Picture.style.pixelWidth < 300) {
      Picture.style.pixelWidth += 30;
    }
  }
}

</script>

<img src="GREECE.jpg" style="width:100px; cursor:move" 
  onclick="Resize(this)"/>
Listing 13-14. Code to resize an element through calculations.

The script takes two different actions depending on whether the Ctrl key is depressed. If the Ctrl key is depressed (event.ctrlKey is discussed below), then 30 (pixels) is subtracted from the current pixelWidth property; otherwise, 30 (pixels) is added to the property. In either case, a check is made on the current width of the image to make sure it does not contract or expand beyond certain width values.

The Event Object

For the preceding image it is necessary to know whether the user is holding down the Ctrl key while clicking the mouse. A script can trap for these types of keystroke events through the event object. This DOM object contains information about user and system events taking place in the browser. There will be occasion later to trap for other events; for present purposes the need is to detect whether the Ctrl key is depressed. This event, along with the Alt key event, are detected with the following syntax.

DOM Reference Effects
event.ctrlKey Returns true if the Ctrl key is depressed.

event.altKey Returns true if the Alt key is depressed.

Figure 13-19. Trapping Crtl and Alt key events.

Check for the Ctrl or Alt key event in an if statement:

if (event.ctrlKey) {
  process CtrlKey event...
}

if (event.altKey) {
  process AltKey event...
}

Dynamic Charting

An interesting use of element resizing is to display a bar chart representing values as graphic bars of varying length. In the following example, a click on the "Chart" button produces a bar chart that plots the values in the accompanying textboxes. Changing any of these values produces a different chart.


Figure 13-20. Producing a bar chart.

It is a relatively simple matter to arrange the textboxes and <span> tags (for the bars) in a table to keep them aligned.

<table border="0" cellpadding="0" cellspacing="0">
<tr>
  <td style="padding-right:5px">
    <input id="Qty1" type="text" style="width:50px" value="30"/></td>
  <td style="border-left:solid 2 #000000">
    <span id="Bar1" style="height:20; background-color:red"></span></td>
</tr>
<tr>
  <td style="padding-right:5px">
    <input id="Qty2" type="text" style="width:50px" value="55"/></td>
  <td style="border-left:solid 2 #000000">
    <span id="Bar2" style="height:20; background-color:blue"></span></td>
</tr>
<tr>
  <td style="padding-right:5px">
    <input id="Qty3" type="text" style="width:50px" value="110"/></td>
  <td style="border-left:solid 2 #000000">
    <span id="Bar3" style="height:20; background-color:green"></span></td>
</tr>
<tr>
  <td style="padding-right:5px">
    <input id="Qty4" type="text" style="width:50px" value="75"/></td>
  <td style="border-left:solid 2 #000000">
    <span id="Bar4" style="height:20; background-color:yellow"></span></td>
</tr>
<tr>
  <td style="padding-right:5px">
    <input id="Qty5" type="text" style="width:50px" value="35"/></td>
  <td style="border-left:solid 2 #000000; border-bottom:solid 2 #000000">
    <span id="Bar5" style="height:20; background-color:brown"></span></td>
</tr>
</table>

<input type="button" value="Chart" onclick="BarChart()"/>
Listing 13-15. XHTML code for a bar chart.

Styles are applied to the table cells to create the left and bottom borders of the chart and to offset it from the textboxes. The <span> tags are given background colors and heights, but no initial widths. Their widths are script-assigned from the values in the textboxes to produce the bars.

The "Chart" button calls the BarChart() function to plot the textbox values by assigning them as the width properties of the <span> tags.

<script type="text/javascript">

function BarChart()
{
  document.getElementById("Bar1").style.width = document.getElementById("Qty1").value;
  document.getElementById("Bar2").style.width = document.getElementById("Qty2").value;
  document.getElementById("Bar3").style.width = document.getElementById("Qty3").value;
  document.getElementById("Bar4").style.width = document.getElementById("Qty4").value;
  document.getElementById("Bar5").style.width = document.getElementById("Qty5").value;
}

</script>
Listing 13-16. Script to plot textbox values as span widths.

If you want longer or shorter bars than those given by using the entered values as pixel widths, you can multiply the values by a positive or negative integer.

Of course, additional computations may be needed to keep the bars within the right margin of the page when values become very large. In the previous example, the textbox values equate to pixels, so a textbox value of, say 1200, would push the bar beyond the page width. To remedy this problem, the largest value is typically set to 100%, with other values being percentages of this value. Bar widths, then, are based on these percentages rather than on the original numeric values, with the longest bar length being 100% of the display area.

In the following example, textbox values are converted to percentages to keep bar widths within a narrow range, regardless of the magnitudes of the numbers.


Figure 13-21. Producing a bar chart based on percentages.

The same table layout is used as in the previous example. All that differs is the script.

<script type="text/javascript">

function BarChart()
{
  // Load textbox values into array
  var Values = new Array();
  Values[0] = parseInt(document.getElementById("Qty1").value);
  Values[1] = parseInt(document.getElementById("Qty2").value);
  Values[2] = parseInt(document.getElementById("Qty3").value);
  Values[3] = parseInt(document.getElementById("Qty4").value);
  Values[4] = parseInt(document.getElementById("Qty5").value);

  // Find value of largest number
  var LargestNumber = 0;
  for (i=0; i<5; i++) {
    if (Values[i] > LargestNumber) {
      LargestNumber = Values[i];
    }
  }
  
  // Create percent array using largest number as 100%
  var Percents = new Array()
  for (i=0; i<5; i++) {
    Percents[i] = parseInt((Values[i] / LargestNumber) * 100);
  }
  
  // Make bar chart
  for (i=0; i<5; i++) {
    document.getElementById("Bar" + (i+1)).style.width = Percents[i];
  }
}

</script>
Listing 13-17. Script to produce a bar chart based on percentages.

To make the calculations more conveneint, the values from the textboxes are loaded into array Values. The textbox strings are converted to integer values with the parseInt() method.

// Load textbox values into array
var Values = new Array();
Values[0] = parseInt(document.getElementById("Qty1").value);
Values[1] = parseInt(document.getElementById("Qty2").value);
Values[2] = parseInt(document.getElementById("Qty3").value);
Values[3] = parseInt(document.getElementById("Qty4").value);
Values[4] = parseInt(document.getElementById("Qty5").value);

Next, the largest value in the array is determined. This is the value that will be considered as 100% for purposes of determining the relative percentages of the other values and the lengths of the bars.

// Find value of largest number
var LargestNumber = 0;
for (i=0; i<5; i++) {
  if (Values[i] > LargestNumber) {
    LargestNumber = Values[i];
  }
}

Now, an array of percentages, Percents, is created that stores the percentage of each value in the Values array of the largest number.

// Create percent array using largest number as 100%
var Percents = new Array()
for (i=0; i<5; i++) {
  Percents[i] = parseInt((Values[i] / LargestNumber) * 100);
}

Since percentages are decimal numbers, they are multiplied by 100 and converted to integers to result in whole numbers. For example, a calculated percentage of .3333333 would be multiplied by 100 to get 33.33333 (%) and converted to the integer number 33. The values and calculated percents for the five textbox values in this example are:

Values  Percents
 3000      25
 5500      45
12000     100
 7500      62
 3500      29

Finally, the Percents array is iterated to produce the bars, with the percentage values being used as the pixel widths of the bars.

// Make bar chart
for (i=0; i<5; i++) {
  document.getElementById("Bar" + (i+1)).style.width = Percents[i];
}

Note that the bar <span> tags have ids of "Bar1", "Bar2", "Bar3", etc. while array index i iterates from 0 through 4. Therefore, a bar id is given by adding 1 to the index:

document.getElementById("Bar" + (i+1)).style.width = Percents[i]

In this example, the percentages are used as pixel widths. You may wish to lengthen all bars by multiplying the Percents values. For instance, the calculation,

document.getElementById("Bar" + (i+1)).style.width = Percents[i] * 3

would increase the longest bar width to 300 pixels rather than the 100 pixels in the current example.