Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Devise Web 2.0 applications with PHP and DHTML, Part 2: Use JavaScript to create HTML elements on the fly

Jack Herrington (jherr@pobox.com), Senior Software Engineer, Studio B
Jack D. Herrington is a senior software engineer with more than 20 years of experience. He's the author of three books: Code Generation in Action, Podcasting Hacks, and PHP Hacks. He has also written more than 30 articles.

Summary:  Part 1 of this "Devise Web 2.0 applications with PHP and DHTML" series discusses how to build PHP applications with user interface elements like tabs, spinners, and pop-ups using JavaScript, Cascading Style Sheets (CSS), and HTML. Part 2 extends the lesson to include graphing techniques that use JavaScript to create new HTML elements on the fly.

View more content in this series

Date:  09 May 2006
Level:  Intermediate
Also available in:   Russian

Activity:  6941 views
Comments:  

Part 1 shows how to move, hide, and display Web page content. But what about creating new HTML on the fly? How do you graph data and use similar fun techniques? Figure 1 shows a graph of world illiteracy rates (data from Unesco; see Resources).


Figure 1. Illiteracy rates worldwide by year
Illiteracy rates worldwide by year

This isn't the most entertaining data set, but it's encouraging. What if you want to see only the illiteracy rate in Europe? Easy: Click the drop-down and select Europe.


Figure 2. Illiteracy rates in Europe by year
Illiteracy rates in Europe by year

The graph shows that illiteracy rates are far lower in Europe than they are worldwide. The code in Listing 1 produces this dynamic graph.


Listing 1. The bar graph code

<html>
<head>
<title>Bar Graph Example</title>
<script>
var years = [ 1970, 1980, 1990, 1995, 2000, 2005, 2010, 2015 ];

var rates = [];
rates[ 'World' ] = [ 36.6, 30.3, 24.7, 22.4,
  20.3, 18.3, 16.5, 15.0 ];
rates[ 'Africa' ] = [ 72.4, 62.4, 51.2, 45.6,
  40.2, 35.2, 30.8, 26.8 ];
rates[ 'America' ] = [ 14.8, 11.6, 9.0, 7.9,
  6.9, 6.0, 5.3, 4.6 ];
rates[ 'Asia' ] = [ 48.5, 38.7, 30.2, 27.2,
  24.4, 21.8, 19.6, 17.7 ];
rates[ 'Europe' ] = [ 6.4, 4.3, 2.8, 2.2, 1.8,
  1.4, 1.1, 0.8 ];
rates[ 'Oceania' ] = [ 11.1, 8.7, 7.1, 6.6,
  6.1, 5.6, 5.3, 5.0 ];

function plot( region )
{
  var html = "";
  html += "<table width='100%' cellspacing='0' cellpadding='1'>";
  for( var year in years )
  {
    var val = Math.round( rates[region][year] );
    html += "<tr>";
    html += "<td width='8%'>"+years[year]+"</td>";
    html += "<td width='1%' class='bar-start'></td>";
    html += "<td width='92%'>";
    html += "<table width='100%' cellspacing='0' ";
	html += "cellpadding='0'><tr>";
    html += "<td width='"+val+"%' class='bar-on'>";
	html += "&nbsp;</td>";
    html += "<td width='"+(100-val);
	html += "%' class='bar-off'>&nbsp;</td>";
    html += "</tr></table></td>";
    html += "<td width='1%' class='bar-start'></td>";
    html += "</tr>";
  }
  html += "</table>";
  document.getElementById( "graph" ).innerHTML = html;
}
</script>
<style>
body { font-family: arial, verdana, sans serif; }
.bar-on { background: blue; }
.bar-off { background: white; }
.bar-start { width:1px; background: black; }
#graph { width: 600px; }
</style>
</head>
<body onload="plot('World')">
Region:
<select onchange="plot(this.options[this.selectedIndex].value)">
<option value="World">World</option>
<option value="Africa">Africa</option>
<option value="America">America</option>
<option value="Asia">Asia</option>
<option value="Europe">Europe</option>
<option value="Oceania">Oceania</option>
</select><br/><br/>
Rates of illiteracy (larger is worse):<br/><br/>
<div id="graph">
</div>
</body>
</html>

Begin with an empty <div> with the ID "graph". The onload attribute of the <body> tag tells the browser to call the plot function when the page is loaded. The plot function is where the fun happens.

The function begins by creating an empty string. Next, it builds up the graph by adding <table>, <tr>, and <td> tags into the string. The function then sets the innerHTML attribute of the graph <div> tag to be the newly generated HTML.

The graph itself is a table with four columns: the year, a little spacer, the bar, and another spacer. Within each row of the bar column is another table. These nested tables have two cells: The first is colored blue, and the second is white. The width of the blue cell is the percentage of illiteracy, and the width of the white cell is 100 minus the original percentage. The result is a simple HTML bar graph with no images.

The Region drop-down has an onchange handler that's called whenever a new item is selected. When that happens, the plot method is called with the currently selected value, and the graph is updated.

This code is very compatible. The use of innerHTML, which is being replaced by DOM methods like createElement and appendChild, is compatible with every modern browser.

Bar graphs in PHP

In implementing the PHP for bar graphs, this article looks at how to take data from the PHP code in the server and put it into dynamic HTML (DHTML) JavaScript. The PHP code for the bar graph is shown in Listing 2.


Listing 2. The bar graph code in PHP

<?php
$years = array( 1970, 1980, 1990, 1995, 2000, 2005, 2010, 2015 );
$countries = array();
$countries[ "World" ] = array( 36.6, 30.3, 24.7, 22.4,
  20.3, 18.3, 16.5, 15.0 );
$countries[ "Africa" ] = array( 72.4, 62.4, 51.2, 45.6,
  40.2, 35.2, 30.8, 26.8 );
$countries[ "America" ] = array( 14.8, 11.6, 9.0, 7.9,
  6.9, 6.0, 5.3, 4.6 );
$countries[ "Asia" ] = array( 48.5, 38.7, 30.2, 27.2,
  24.4, 21.8, 19.6, 17.7 );
$countries[ "Europe" ] = array( 6.4, 4.3, 2.8, 2.2,
  1.8, 1.4, 1.1, 0.8 );
$countries[ "Oceania" ] = array( 11.1, 8.7, 7.1, 6.6,
  6.1, 5.6, 5.3, 5.0 );
?>
<html>
<head>
<title>Bar Graph Example</title>
<script>
var years = [ <?php echo( join( ",", $years ) ); ?> ];

var rates = [];
<?php
foreach( $countries as $name => $values ) {
?>
rates[ '<?php echo($name) ?>' ] = [
  <?php echo( join( ",", $values ) ); ?> ];
<?php } ?>

function plot( region )
{
  var html = "";
  html += "<table width='100%' cellspacing='0' cellpadding='1'>";
  for( var year in years )
  {
    var val = Math.round( rates[region][year] );
    html += "<tr>";
    html += "<td width='8%'>"+years[year]+"</td>";
    html += "<td width='1%' class='bar-start'></td>";
    html += "<td width='92%'>";
    html += "<table width='100%' cellspacing='0' cellpadding='0'><tr>";
    html += "<td width='"+val+"%' class='bar-on'>&nbsp;</td>";
    html += "<td width='"+(100-val)+"%' class='bar-off'>&nbsp;</td>";
    html += "</tr></table></td>";
    html += "<td width='1%' class='bar-start'></td>";
    html += "</tr>";
  }
  html += "</table>";
  document.getElementById( "graph" ).innerHTML = html;
}
</script>
<style>
body { font-family: arial, verdana, sans serif; }
.bar-on { background: blue; }
.bar-off { background: white; }
.bar-start { width:1px; background: black; }
#graph { width: 600px; }
</style>
</head>
<body onload="plot('World')">
Region: <select onchange="plot(this.options[this.selectedIndex].value)">
<?php
foreach( $countries as $name => $values ) {
?>
<option value="<?php echo($name) ?>"><?php echo($name) ?></option>
<?php } ?>
</select><br/><br/>
Rates of illiteracy (larger is worse):<br/><br/>
<div id="graph">
</div>
</body>
</html>

At the top of the file, preload the years and countries arrays with the years, and the list of countries and their literacy values. Then, PHP needs to generate three areas of the DHTML code. The first populates the years array in the JavaScript, the second populates the rates, and the third sets the contents of the <select> tag with the names of the countries.


Scatter plots

Creating new HTML on the fly is at the heart of DHTML. One option is to build a string and set the inner HTML of elements on the page. This example shows a second method, using a scatter plot as an example. Figure 3 shows a plot of a simple equation.


Figure 3. A graph of a multiperiod sine wave
A graph of a multiperiod sine wave

You can change the equation and click the Try It! button to update the graph, as shown in Figure 4.


Figure 4. A graph of a slightly different equation
A graph of a slightly different equation

All that without going back to the PHP server. This example doesn't even use a server -- you can just create a new HTML file and begin writing the HTML code. The code for the graph is shown in Listing 3.


Listing 3. The scatter plot code

<html>
<head>
<title>Dynamic Graphing Example</title>
<style type="text/css">
body { font-family: arial, verdana, sans serif; }
#graphdiv {
  height:500px; width:500px;
  border:1px solid black;
  position:relative;
}
</style>
<script>
function drawgraph()
{
  var g = document.getElementById( "graphdiv" );
  var eq = document.getElementById( "eq" ).value;

  var dx = [];
  var dy = [];

  var sx = 10000;
  var ex = -10000;
  var sy = 10000;
  var ey = -10000;

  for( var i = 0; i < 100; i++ )
  {
    var x = i / 100;
    var y = eval( eq );
    if ( y > ey ) ey = y;
    if ( y < sy ) sy = y;
    if ( x > ex ) ex = x;
    if ( x < sx ) sx = x;
    dx.push( x );
    dy.push( y );
  }

  var gwidth = 500;
  var gheight = 500;
  var imgwidth = 100;
  var imgheight = 100;

  var fx = (gwidth-(imgwidth/2))/(ex-sx);
  var fy = ((gheight-(imgheight/2))/2)/(ey-sy);

  g.innerHTML = "";
  for( i = 0; i < dx.length; i++ )
  {
    var x = ( dx[i] * fx );
    var y = ((gheight-(imgheight/2))/2)+(dy[i]*fy);
    var img = document.createElement( "img" );
    img.src = "ball.gif";
    img.style.position = "absolute";
    img.style.top = y+"px";
    img.style.left = x+"px";
    g.appendChild( img );
  }
}
</script>
</head>
<body onload="drawgraph()">
Equation:
<input type="text" id="eq" value="Math.sin(x*32)" />
<button onclick="drawgraph()">Try It!</button>
<br/><br/>
<div id="graphdiv">
</div>
</body>
</html>

Most of the code in this example is in the drawgraph JavaScript function. That function creates two arrays of numbers -- one for the x value and another for the y value. The numbers on the x axis run from 0 to 1; the numbers in the y axis are generated by evaluating the equation for each x value.

As the data are generated from the equation, the code keeps the minimum and maximum for each axis, then autoscales the data to fit.

Putting the images into the graph employs a new technique: You use the document.createElement to build an <img> tag, then you use appendChild to add the newly created img object to the graph object. This technique is preferable to setting innerHTML using a string because the code is easier to read and maintain -- and you don't have to worry about string-encoding issues.

The technique of using createElement is compliant with the World Wide Web Consortium (W3C) Document Object Model (DOM) specification and is the preferred way of creating HTML elements dynamically.


Scatter plots in PHP

The scatter plot example is self-contained. The PHP code wraps the scatter plot as a component. The code for the component is shown in Listing 4.


Listing 4. The scatter plot code in PHP

<?php
function graph_header()
{
?>
<style type="text/css">
body { font-family: arial, verdana, sans serif; }
#graphdiv {
  height:500px; width:500px;
  border:1px solid black;
  position:relative;
}
</style>
<script>
function drawgraph()
{
  var g = document.getElementById( "graphdiv" );
  var eq = document.getElementById( "eq" ).value;

  var dx = [];
  var dy = [];

  var sx = 10000;
  var ex = -10000;
  var sy = 10000;
  var ey = -10000;

  for( var i = 0; i < 100; i++ )
  {
    var x = i / 100;
    var y = eval( eq );
    if ( y > ey ) ey = y;
    if ( y < sy ) sy = y;
    if ( x > ex ) ex = x;
    if ( x < sx ) sx = x;
    dx.push( x );
    dy.push( y );
  }

  var gwidth = 500;
  var gheight = 500;
  var imgwidth = 100;
  var imgheight = 100;

  var fx = (gwidth-(imgwidth/2))/(ex-sx);
  var fy = ((gheight- (imgheight/2))/2)/(ey-sy);

  g.innerHTML = "";
  for( i = 0; i < dx.length; i++ )
  {
    var x = ( dx[i] * fx );
    var y = ((gheight-(imgheight/2))/2)+(dy[i]*fy);
    var img = document.createElement( "img" );
    img.src = "ball.gif";
    img.style.position = "absolute";
    img.style.top = y+"px";
    img.style.left = x+"px";
    g.appendChild( img );
  }
}
</script>
<?php
}

function graph_place()
{
?>
</head>
<div id="graphdiv">
</div>
<?php
}
?>

This code defines two functions: graph_header and graph_place. The graph_header function should be called in the head section of the document, and the graph_place should be called wherever you want the graph to go. Listing 5 shows the code for the updated graph page.


Listing 5. The updated scatter plot code in PHP

<?php
require_once( "graph_component.php" );
?>
<html>
<head>
<title>Dynamic Graphing Example</title>
<?php graph_header(); ?>
</head>
<body onload="drawgraph()">
Equation:
<input type="text" id="eq" value="Math.sin(x*32)" />
<button onclick="drawgraph()">Try It!</button>
<br/><br/>
<?php graph_place(); ?>
</body>
</html>

It's much simpler than the original page. You include the code for the component. Then you call the graph_header to add the JavaScript and CSS. Finally, you call the graph_place function where you want to place the graph on the page.


How far can DHTML go?

It's easy to get drawn into the power and simplicity of JavaScript code. The question quickly becomes not how little to put in but how far to push the envelope. Google Maps (see Resources) is an excellent example of a DHTML application that not only is useful on a site but also can be integrated into any Web page with only a little JavaScript. But Google didn't stop there: It also created Gmail (see Resources), which makes extensive use of DHTML to create an easy-to-use mail client right in the browser. (You may not take your JavaScript that far, but it's nice to see what you could do if you took the time.)

One technology every DHTML programmer should look into is Asynchronous JavaScript and XML (Ajax). Ajax adds the ability for the browser to make Web requests in the background. That means your DHTML application can call back to your PHP application without requiring a page refresh. The page can then use that data to refresh the information presented -- all without the user leaving the comfort of the page he's on. (See Resources for Ajax articles and tutorials.)


Conclusion

The previous article this "Devise Web 2.0 applications with PHP and DHTML" series began by talking about the new buzzword de jour, Web 2.0. Another big industry buzzword is rich client applications. They both mean cool Web applications, so you can think of them the same way. Lots of technologies are available for creating rich Internet applications. Laszlo and MXML make building Flash a lot easier, and Microsoft® has some new ideas coming in Vista. But DHTML is tempting for building rich Internet applications because you can do it with the technologies you already have, like PHP.

This article has demonstrated several methods for enriching the customer experience with simple CSS and JavaScript. You can do the same in the Web applications you're working in now -- just open a <script> tag and have some fun.


Resources

Learn

Get products and technologies

  • Innovate your next open source development project with IBM trial software, available for download or on DVD.

Discuss

About the author

Jack D. Herrington is a senior software engineer with more than 20 years of experience. He's the author of three books: Code Generation in Action, Podcasting Hacks, and PHP Hacks. He has also written more than 30 articles.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Open source, Web development
ArticleID=110655
ArticleTitle=Devise Web 2.0 applications with PHP and DHTML, Part 2: Use JavaScript to create HTML elements on the fly
publish-date=05092006
author1-email=jherr@pobox.com
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers