BUY THIS BOOK
Add to Cart

Print Book $29.95


Add to Cart

PDF $23.99

Safari Books Online

What is this?

Add to UK Cart

Print Book £20.99

What is this?

Looking to Reprint or License this content?


PHP Hacks
PHP Hacks Tips & Tools For Creating Dynamic Websites

By Jack Herrington
Book Price: $29.95 USD
£20.99 GBP
PDF Price: $23.99

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Installation and Basics
Before you start hacking PHP, you have to either install PHP or get an account on a machine that has PHP already installed. This chapter covers the basics of installing PHP, as well as installing the critical second component, the MySQL database engine, that is so commonly used to provide data that drives PHP applications. The chapter also covers installing PEAR open source modules, which you can use for free in your own PHP applications.
Install the PHP language on Windows, Mac OS X, and Linux, and for both Apache and Internet Information Server.
Installing PHP is the first step in using this book, and on most operating systems, it's a very easy thing to do. PHP installation starts with going to the PHP web site (http://www.php.net/) and downloading either the source code or the binaries, along with documentation.
On Windows, you need to start your PHP installation by downloading the PHP binaries for PHP Version 5. Use the .msi installer to make it easy on yourself, and specify the installation directory as c:\php5. With your PHP installation in place, you can run the PHP interpreter from a Windows DOS prompt:
	C:\> php -v
	PHP 5.0.4 (cli) (built: Mar 31 2005 02:45:00)
	Copyright © 1997-2004 The PHP Group
	Zend Engine v2.0.4-dev, Copyright (c) 1998-2004 Zend Technologies
If the php executable is not found, you need to add c:\php5\bin to your path. Use the Advanced tab of the system control panel, and click on the Environment Variables button. From there, edit the Path variable, adding c:\php5\bin to whatever path you already have in place.
You will need to close any open command prompt windows and then open a new command prompt window to ensure that these changes take effect.
Command-line access to PHP is great, but you really want to have PHP installed in and integrated with your web server. On Windows, you have two options for this integration. The first is to install the Apache Web Server and configure it for PHP; the second is to install the Internet Information Services (IIS) web server and to install PHP into that environment.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Hacks 1–2: Introduction
Before you start hacking PHP, you have to either install PHP or get an account on a machine that has PHP already installed. This chapter covers the basics of installing PHP, as well as installing the critical second component, the MySQL database engine, that is so commonly used to provide data that drives PHP applications. The chapter also covers installing PEAR open source modules, which you can use for free in your own PHP applications.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Install PHP
Install the PHP language on Windows, Mac OS X, and Linux, and for both Apache and Internet Information Server.
Installing PHP is the first step in using this book, and on most operating systems, it's a very easy thing to do. PHP installation starts with going to the PHP web site (http://www.php.net/) and downloading either the source code or the binaries, along with documentation.
On Windows, you need to start your PHP installation by downloading the PHP binaries for PHP Version 5. Use the .msi installer to make it easy on yourself, and specify the installation directory as c:\php5. With your PHP installation in place, you can run the PHP interpreter from a Windows DOS prompt:
	C:\> php -v
	PHP 5.0.4 (cli) (built: Mar 31 2005 02:45:00)
	Copyright © 1997-2004 The PHP Group
	Zend Engine v2.0.4-dev, Copyright (c) 1998-2004 Zend Technologies
If the php executable is not found, you need to add c:\php5\bin to your path. Use the Advanced tab of the system control panel, and click on the Environment Variables button. From there, edit the Path variable, adding c:\php5\bin to whatever path you already have in place.
You will need to close any open command prompt windows and then open a new command prompt window to ensure that these changes take effect.
Command-line access to PHP is great, but you really want to have PHP installed in and integrated with your web server. On Windows, you have two options for this integration. The first is to install the Apache Web Server and configure it for PHP; the second is to install the Internet Information Services (IIS) web server and to install PHP into that environment.
In either case, you need to copy the php.ini file to your Windows directory, c:\windows. Edit the c:\windows\php.ini file and change the extension_dir line to read as follows:
	extension_dir = "c:\php5\ext"
Further, uncomment lines such as this one:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Install PEAR Modules
Access the vast PEAR source code repository to find cool functionality to add to your PHP applications.
The PEAR library is a set of user-contributed PHP modules that are structured in a common way so that they can be downloaded, installed, and versioned consistently. PEAR is so fundamental to PHP that it now comes as a standard part of the PHP installation.
To find out what is available in the PEAR library, surf on over to the PEAR site (http://pear.php.net/). There you can find the list of modules or search by module name. When you find a module you want to install, simply run the pear program on your command line.
On Windows, the invocation looks like this:
	C:\> pear install DB
	downloading DB-1.7.6.tgz …
	Starting to download DB-1.7.6.tgz (124,807 bytes)
	............................done: 124,807 bytes
	install ok: DB 1.7.6
In this case, I am installing the PEAR module named DB [Hack #35] , an object-oriented database wrapper that is used extensively in this book.
On Windows, you might need to make sure that the pear.bat batch file, located in the bin directory of your PHP installation directory, is on the path. In addition, the directory where the PEAR modules are installed is often not created by default. In that case, you need to use Windows Explorer or the command line to create the PEAR directory. If you installed PHP in c:\php5, the PEAR directory is c:\php5\pear. You might also need to add this directory to the modules path in the c:\windows\php.ini file.
On Unix systems, including Mac OS X, running the pear program is just as easy:
	% sudo pear install HTTP_Client
	downloading HTTP_Client-1.0.0.tgz …
	Starting to download HTTP_Client-1.0.0.tgz (6,396 bytes)
	.....done: 6,396 bytes
	install ok: HTTP_Client 1.0.0
	%
Here I am installing the HTTP_Client PEAR module [Hack #84] . You'll have to use the sudo command because the PEAR module will be installed system-wide.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Web Design
This chapter provides user interface hacks that you can perform with HTML using PHP. The hacks cover building tabs and boxes to clean up your web interface, building interface elements like breadcrumb trails, and building lightweight HTML graphs. The chapter even includes a hack that shows you how to send HTML email to your customers.
Use CSS to allow your user to select how your web application should look.
Have you ever run across a user who just has to have every blog he reads appear in his own personal color scheme? Are you that kind of user? Thankfully, supporting these users is far easier with CSS support in modern browsers.
CSS defines the fonts, colors, sizes, and even positions of elements of a page independent of the HTML code for that page. You can change the look of a single HTML page drastically simply by redefining its CSS stylesheet. This hack shows how to provide user-selectable CSS and offers some advice on creating customizable interfaces.
Start out by saving the code in Example 2-1 as index.php.
Example 2-1. Simple index page that sets the stage for customizable CSS
	<html>
	<head>
	<?php
	$style = "default";
	if ( $_GET["style"] )
			$style = $_GET["style"];
	$files = array();
	$dh = opendir( "styles" );
	while( $file = @readdir( $dh ) )
	{
			if( preg_match( "/[.]css$/", $file ) )
			{
				$file = preg_replace( "/[.]css$/", "", $file );
				$files []= $file;
			}
	}
	?>
	<style type="text/css" media="all">@import url(styles/<?php echo($style); ?>.
	css);</style>
	</head>
	<body>
	<table width="800">
	<tr>
	<td width="200" class="menu" valign="top">
	<div class="menu-active"><a href="home.php">Home</a></div>
	<div class="menu-inactive"><a href="faq.php">FAQ</a></div>
	<div class="menu-inactive"><a href="contact.php">Contact</a></div>
	</td>
	<td width="600" valign="top">

			<table class="box">
			<tr>
			<td class="box-title">
				   Important information
			</td>
			</tr>
			<tr>
			<td class="box-content">
				Lots of information about important events and
				stuff.
			</td>
			</tr>
			</table>

	</td>
	</tr>
	</table>
	<form>
	Style: <select name="style">
	<?php foreach( $files as $file ) { ?>
	<option value="<?php echo($file); ?>"
	<?php echo( $file == $style ? "selected" : "" ); ?>
	><?php echo($file); ?></option>
	<?php } ?>
	</select>
	<input type="submit" value="Select" />
	</form>
	</body>
	</html>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Hacks 3–10: Introduction
This chapter provides user interface hacks that you can perform with HTML using PHP. The hacks cover building tabs and boxes to clean up your web interface, building interface elements like breadcrumb trails, and building lightweight HTML graphs. The chapter even includes a hack that shows you how to send HTML email to your customers.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Create a Skinnable Interface
Use CSS to allow your user to select how your web application should look.
Have you ever run across a user who just has to have every blog he reads appear in his own personal color scheme? Are you that kind of user? Thankfully, supporting these users is far easier with CSS support in modern browsers.
CSS defines the fonts, colors, sizes, and even positions of elements of a page independent of the HTML code for that page. You can change the look of a single HTML page drastically simply by redefining its CSS stylesheet. This hack shows how to provide user-selectable CSS and offers some advice on creating customizable interfaces.
Start out by saving the code in Example 2-1 as index.php.
Example 2-1. Simple index page that sets the stage for customizable CSS
	<html>
	<head>
	<?php
	$style = "default";
	if ( $_GET["style"] )
			$style = $_GET["style"];
	$files = array();
	$dh = opendir( "styles" );
	while( $file = @readdir( $dh ) )
	{
			if( preg_match( "/[.]css$/", $file ) )
			{
				$file = preg_replace( "/[.]css$/", "", $file );
				$files []= $file;
			}
	}
	?>
	<style type="text/css" media="all">@import url(styles/<?php echo($style); ?>.
	css);</style>
	</head>
	<body>
	<table width="800">
	<tr>
	<td width="200" class="menu" valign="top">
	<div class="menu-active"><a href="home.php">Home</a></div>
	<div class="menu-inactive"><a href="faq.php">FAQ</a></div>
	<div class="menu-inactive"><a href="contact.php">Contact</a></div>
	</td>
	<td width="600" valign="top">

			<table class="box">
			<tr>
			<td class="box-title">
				   Important information
			</td>
			</tr>
			<tr>
			<td class="box-content">
				Lots of information about important events and
				stuff.
			</td>
			</tr>
			</table>

	</td>
	</tr>
	</table>
	<form>
	Style: <select name="style">
	<?php foreach( $files as $file ) { ?>
	<option value="<?php echo($file); ?>"
	<?php echo( $file == $style ? "selected" : "" ); ?>
	><?php echo($file); ?></option>
	<?php } ?>
	</select>
	<input type="submit" value="Select" />
	</form>
	</body>
	</html>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Build a Breadcrumb Trail
Use a breadcrumb trail to tell your users where they are on your site.
A breadcrumb trail is a list of links at the top of a page that indicates where a person is in the site's organizational hierarchy.
A breadcrumb trail is not, as the term might suggest, the set of pages that a person navigated through to get to his destination. The user already has the Back button for retracing his steps.
A breadcrumb trail allows a user to navigate back up the hierarchy a little to where he would find more relevant information. For example, the trail might be: Home | Platforms | Portables | PSP. The user could easily navigate back to the Portables page, which lists all of the portable game consoles, the Platforms page, which lists the different gaming platforms, or the home page, all with a single click.
Figure 2-3 shows the breadcrumb trail that Yahoo! uses in its directory to show where you are. In this case, I'm in the Buddy section of the Comedy category, within the Titles area of Movies and Films. As a user, I can go back to any level of organization that suits my interests.
Figure 2-3: The Yahoo! directory breadcrumb trail
By convention, the last item on the list is the current page and is not given a link. The first item on the list is the home page of the site.
To add breadcrumbs to your own site, save the code shown in Example 2-4 as showpage.php.
Example 2-4. Creating a breadcrumb trail
	<?php
	$id = $_GET['id'];
	if ( strlen( $id ) < 1 )
		$id = "home";

	$pages = array(
		home => array( id=>"home", parent=>"", title=>"Home",
				url=>"showpage.php?id=home" ),
		users => array( id=>"users", parent=>"home", title=>"Users",
				url=>"showpage.php?id=users" ),
		jack => array( id=>"jack", parent=>"users", title=>"Jack",
				url=>"showpage.php?id=jack" )
		);

		function breadcrumbs( $id, $pages )
		{
		  $bcl = array();
		  $pageid = $id;
		  while( strlen( $pageid ) > 0 )
		  {
			$bcl[] = $pageid;
			$pageid = $pages[ $pageid ]['parent'];
		  }
		  for( $i = count( $bcl ) - 1; $i >= 0; $i-- )
		  {
			$page = $pages[$bcl[$i]];
			if ( $i > 0 )
			{
				echo( "<a href=\"" );
				echo( $page['url'] );
				echo( "\">" );
			}
			echo( $page['title'] );
			if ( $i > 0 )
			{
			echo( "</a> | " );
			}
		  }
	   }
	   ?>
	   <html>
	   <head>
	   <title>Page - <?php echo( $id ); ?></title>
	   </head>
	   <body>
	   Breadcrumbs: <?php breadcrumbs( $id, $pages ); ?><br/>
	   Page name: <?php echo( $id ); ?>
	   </body>
	   </html>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Create HTML Boxes
Use HTML and simple graphics to create attractive boxes for your web pages.
Sometimes it's useful to put your page content into boxes to make it easier for users to navigate your site. You can draw attention to a particular piece of content, create newspaper-like interfaces, or just go with a little cubism to impress your artsy friends. The scripts in this hack make it easy to draw boxes around any content you like.
Save the code in Example 2-5 as box1test.php.
Example 2-5. A test page for boxing up content
	<html>
	<head>
	<? include( "box1.php" );
	add_box_styles();
	?>
	</head>
	<body>
	<div style="width:200px;">
	<? start_box( "News" ); ?>
	Today's news is that there is no news. Which is probably a good thing since
	the news can be fairly distressing at times.<br/><br/>
	<a href="morenews.html">more…</a>
	<? end_box(); ?>
	</div>
	</body>
	</html>
For the PHP portion of the mini-application, save the code in Example 2-6 as box1.php.
Example 2-6. Adding a little PHP and CSS
	<?
	function add_box_styles() { ?>
	<style type="text/css">
	.box {
		font-family: arial, verdana, sans-serif;
		font-size: x-small;
		background: #ccc;
	}
	.box-title { 
		font-size: small; 
		font-weight: bold; 
		color: white; 
		background: #777; 
		padding: 5px; 
		text-align: center;
	}
	.box-content { 
		background: white; 
		padding: 5px;
	}
	</style>
	<? }

	function start_box( $name ) { ?>
	<table class="box" cellspacing="2" cellpadding="0">
	<tr><td class="box-title"><? print( $name ) ?></td></tr>
	<tr><td class="box-content">
	<? }
	
	function end_box() { ?>
	</td></tr></table>
	<? } ?>
More important than this particular set of CSS tags is the fact that you can easily customize the box to your liking, highlighting any portion of the box's content that you want. You can even combine this with user-selectable CSS [Hack #3] , and let the user decide on his own box styles!
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Add Tabs to Your Web Interface
Use HTML and CSS to create a tabbed interface for your web application.
Sometimes there is just too much data to put onto one web page. An easy way to break up a site (or even a content-heavy page) is to display it using tabs, where the data is broken up into subelements, each correlating to a named tab. Lucky for us, tabs are a piece of cake with PHP.
Save the code in Example 2-9 as index.php.
Example 2-9. Using the tabs library to show a tabbed interface
	<?php
	require_once("tabs.php");
	?>
	<html>
	<head>
	<?php tabs_header(); ?>
	</head>
	<body>
	<div style="width:600px;">
	<?php tabs_start(); ?>
	<?php tab( "Tab one" ); ?>
	This is the first tab.
	<?php tab( "Tab two" ); ?>
	This is the second tab.
	<?php tabs_end(); ?>
	</div>
	</body>
	</html>
Next, code up a nice PHP and CSS library. Save the code in Example 2-10 as tabs.php.
Example 2-10. Using PHP and some CSS to create user-friendly tabs
	<?php
	$tabs = array();

	function tabs_header()
	{
	?>
	<style type="text/css">
	.tab {
		border-bottom: 1px solid black;
		text-align: center;
		font-family: arial, verdana;
	  }
	.tab-active { 
		border-left: 1px solid black; 
		border-top: 1px solid black; 
		border-right: 1px solid black; 
		text-align: center; 
		font-family: arial, verdana; 
		font-weight: bold;
	  }
	.tab-content { 
		padding: 5px; 
		border-left: 1px solid black; 
		border-right: 1px solid black; 
		border-bottom: 1px solid black;
	  } 
	</style> 
	<?php
	}

	function tabs_start()
	{  
      ob_start(); 
	}

	function endtab() 
	{ 
	  global $tabs;

	  $text = ob_get_clean();
      $tabs[ count( $tabs ) - 1 ][ 'text' ] = $text;

	  ob_start();
	}

	function tab( $title ) 
	{
	  global $tabs;

	  if ( count( $tabs ) > 0 )
		endtab();
		$tabs []= array(
		  title => $title,
		  text => ""
		);
	  }

	  function tabs_end()
	  {
		global $tabs;

		endtab();
		ob_end_clean();

		$index = 0;
		if ( $_GET['tabindex'] )
			$index = $_GET['tabindex'];

	  ?>
	  <table width="100%" cellspacing="0" cellpadding="0">
	  <tr>
	  <?php
		$baseuri = $_SERVER['REQUEST_URI'];
		$baseuri = preg_replace( "/\?.*$/", "", $baseuri );
		$curindex = 0;
		foreach( $tabs as $tab )
		{
		   $class = "tab";
		   if ( $index == $curindex )
		   $class ="tab-active";
		?>
		<td class="<?php echo($class); ?>">
		<a href="<?php echo( $baseuri."?tabindex=".$curindex ); ?>">
		<?php echo( $tab['title'] ); ?>
		</a>
		</td>
		<?php
			$curindex += 1;
		 }
		?>
		</tr>
		<tr><td class="tab-content" colspan="<?php echo( count( $tabs ) + 1 ); ?>">
		<?php echo( $tabs[$index ]['text'] ); ?>
		</td></tr>
		</table>
		<?php
		}
		?>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Give Your Customers Formatting Control with XSL
Use PHP's XSL support to enable your customers to design their own pages.
Amazon provides an interesting service to its corporate customers. The customer can skin an Amazon page by providing an XSL stylesheet that formats the XML data about the products, prices, and related data. This means that if you're a corporate customer, you can add your own links and graphics, and even customize the look and feel of Amazon.com to give purchasing pages an integrated look.
This hack does the same with PHP's XSL engine (and no corporate membership is required!). Figure 2-10 shows the flow of XSL processing in this hack (and with XSL in general). The processor takes two inputs. In this case, the input.xml file contains the data for the page, and the format.xsl file contains the formatting for the page, along with specifications for where the data is to be placed. The XSL processor then takes these two inputs and emits XML, HTML, or text.
Figure 2-10: The XSL processing flow
Save the code in Example 2-11 as conv.php.
Example 2-11. Generating output from XML and XSL
	<?php
	$xml = new DOMDocument();
	$xml->Load( "input.xml" );

	$xsl = new DOMDocument();
	$xsl->Load( "format.xsl" );

	$xslproc = new XSLTProcessor();
	$xslproc->importStylesheet( $xsl );
	print( $xslproc->transformToXML( $xml ) );
	?>
As a sample XML file, save Example 2-12 as input.xml.
Example 2-12. A sample XML file
	<books>
		<book name="Code Generation in Action" />
		<book name="MDA Explained" />
		<book name="PHP in a Nutshell" />
	</books>
Save Example 2-13 and name it format.xsl.
Example 2-13. Some sample XSL to handle formatting
	<?xml version="1.0" encoding="UTF-8"?>
	<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
	   <xsl:output method="html" />
	   <xsl:template match="/">
	    <html>
		 <body>
		  <xsl:for-each select="/books/book">
		   <xsl:value-of select="@name" /><br/>
		  </xsl:for-each>
		 </body>
		</html>
	  </xsl:template>
	 </xsl:stylesheet>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Build Lightweight HTML Graphs
Use HTML to create simple graphs for your data.
It seems as though every site you go to these days requires QuickTime or Flash so that you can see fancy images and graphs. For simple bar graphs, though, you don't need fancy image rendering or Flash movies. You can use this hack to create bar graphs with just a few HTML tables and some PHP. The result looks just as cool as those other Flash-heavy sites but doesn't require any extra plug-ins or downloads.
Save the code in Example 2-14 as htmlgraph.php.
Example 2-14. Drawing some simple bar graphs
	<html>
	<?
	$data = array(
			array( "movies", 20 ),
			array( "food", 30 ),
			array( "workout", 10 ),
			array( "work", 40 )
	);
	$max = 0;
	foreach ( $data as $d ) { $max += $d[1]; }
	?>
	<body>
	<table width="400" cellspacing="0" cellpadding="2">
	<? foreach( $data as $d ) {
	$percent = ( $d[1] / $max ) * 100;
	?>
	<tr>
	<td width="20%"><? echo( $d[0] ) ?></td>
	<td width="10%"><? echo( $d[1] ) ?>%</td>
	<td>
	<table width="<? echo($percent) ?>%" bgcolor="#aaa">
			<tr><td> </td></tr>
	</table>
	</td>
	</tr>
	<? } ?>
	</table>
	</body>
	</html>
You can use several techniques to create HTML graphs. I chose to use two tables; the first contains the textual data, and the second contains a set of nested tables, each with a width value based on the graph value in that row.
I calculate the width by first finding the maximum value of the combined data, and storing that in $max. I then derive the percentage by dividing $max by the current value, and multiplying the result by 100 (to set the scale between 0 and 100). That number is stored in $percent, which is then used in the width attribute of the table.
Use your browser to surf to the htmlgraph.php page. You should see something similar to Figure 2-12.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Properly Size Image Tags
Use PHP image support to set the height and width attributes of your images properly.
All of the modern browsers start showing web pages as quickly as possible so that web surfers feel they are getting fast(er) response times. This means browsers will start showing a page well before any images or other accompanying resources are downloaded. Because the browser hasn't downloaded the image before rendering the page, it doesn't know how big the image should be, unless you specify height and width attributes on the img tag.
If you don't specify the width and height of images, though, the page will jerk around as it's being downloaded. The browser will guess at the size of the image (usually picking 10 pixels by 10 pixels), but then find out after the image is downloaded that the actual size is much larger. Thus, the browser will need to lay out the page again to adjust for the new size.
This hack builds img tags with the proper width and height attributes by using the getimagesize function to retrieve the actual width and height of the image.
Save the code in Example 2-16 as imagesize.php.
Example 2-16. A little image magic
	<html>
	<?php
	function placegraphic( $file )
	{

	list( $width, $height ) = getimagesize("rss.png");
	echo( "<img src=\"$file\" width=\"$width\" height=\"$height\" />" );
	}
	?> 
	<body> 
	<?php placegraphic( "rss.png" ); ?> 
	</body>
	</html>
Create an image file named rss.png in the same directory as this PHP file, and then browse to the imagesize.php page. You should see the image displayed properly, without any stretching. Use the View Source command in the browser to view the HTML source code to make sure that the width and height attributes were set properly.
You can use the placegraphic function anywhere you would have put an img tag previously. But I don't recommend using this function in static headers or footers where the size of the images will never change. A performance overhead is associated with figuring out the size of an image. So you should use this function only when you don't know the size of the image until the graphic is requested.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Send HTML Email
Use multipart email messages to send email content in both plain text and HTML format.
Email is another interface to your web application. Ideally, you want that interface (and any other, be it a phone or a handheld device) to be as full-featured as the one you provide through a web server. While this isn't always possible, it's a good goal to keep in mind, and it will help push you to create better user interfaces.
This hack describes how to send email using a multipart construction, where one part contains a plain-text version of the email and the other part is HTML. If your customers have HTML email turned off, they will still get a nice email, even if they don't get all of the HTML markup.
Figure 2-13 shows some different forms of mail messages. On the lefthand side is the simplest form of mail, the text message. At the top of the email is the header, which defines the subject, whom the mail is from, whom the mail is going to, and so on. These are followed by a carriage return, and finally, the message text.
Figure 2-13: Different mail forms
The emails in the middle and on the right in Figure 2-13 are multipart messages. The header remains much the same as with the text message, with the exception that some information about the multiple parts is included. The text is then placed within a part, and the HTML is placed in another part.
This way, mailers can decide which part of the message they want to display. Email with HTML that contains graphics can include the referenced graphics as additional parts of the message, as shown in the righthand image.
Save the code in Example 2-17 as htmlemail.php.
Example 2-17. Sending multipart emails in HTML and text formats
	<?php
	$to = "to@email.com";
	$to_full = "Sally Cool";
	$from = "from@email.com";
	$from_full = "Joe Schmoe";
	$subject = "HTML Mail Test";

	$random_hash = "zzz582x";

	ob_start();
	?>
	To: <?php echo($to_full); ?> <<?php echo($to); ?>>
	From: <?php echo($from_full); ?> <<?php echo($from); ?>>
	MIME-Version: 1.0
	Content-Type: multipart/alternative;
				boundary="==Multipart_Boundary_<?php echo($random_hash); ?>" 
	<?php 
	$headers = ob_get_clean(); 
	ob_start(); ?>

	This is a multi-part message in MIME format.

	--==Multipart_Boundary_<?php echo( $random_hash ); ?>
	Content-Type: text/plain; charset="iso-8859-1"
	Content-Transfer-Encoding: 7bit

	This is the text of the message in a simple text format.

	--==Multipart_Boundary_<?php echo( $random_hash ); ?>
	Content-Type: text/html; charset="iso-8859-1"
	Content-Transfer-Encoding: 7bit

	<html>
	<body>
	<p>Here is something with <b>HTML</b> formatting. That can include all of the
	usual:</p>
	<ul>
	<li>Bulleted lists</li>
	<li>Tables</li>
	<li>Images (if you include them as attachments or external links)</li>
	<li>Character formatting</li>
	<li>…and more!</li>
	</ul>
	</body>
	</html>
	
	--==Multipart_Boundary_<?php echo( $random_hash ); ?>--
	
	<?php
	$message = ob_get_clean();
	
	$ok = @mail( $to, $subject, $message, $headers );
	
	echo( $ok ? "Mail sent\n" : "Mail failed\n" );
	?>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: DHTML
This chapter covers using Dynamic HTML (DHTML) in your web applications. DHTML is a term used to define the powerful combination of HTML, CSS, and JavaScript. The hacks in this chapter use DHTML to create all types of interactive interfaces for your web applications, from spreadsheets to dynamic graphs, pop ups, slideshows, vector graphics, and more.
Use the ActiveWidgets spreadsheet library to put an interactive JavaScript data control on your page.
Let's face it: some data—particularly financial and statistical data—just looks better when it's presented as a spreadsheet. Unfortunately, HTML does a poor job of giving you an interactive spreadsheet-style feel, especially when it comes to scrolling around, sorting, or any of the truly interactive user experience elements of a spreadsheet.
This hack uses the ActiveWidgets (http://activewidgets.com/) grid control to create a spreadsheet-style interface on a web page.
Save the code in Example 3-1 as index.php.
Example 3-1. A script that provides state-specific data in a spreadsheet format
<?php $states = array(
	array( "Alabama",4447100,1963711,52419.02,1675.01,50744,87.6,38.7 ),
	array( "Alaska",626932,260978,663267.26,91316,571951.26,1.1,0.5 ),
	array( "Arizona",5130632,2189189,113998.3,363.73,113634.57,45.2,19.3 ),
	array( "Arkansas",2673400,1173043,53178.62,1110.45,52068.17,51.3,22.5 ),
	array( "California",33871648,12214549,163695.57,7736.23,155959.34,217.2,78.3 ),

	array( "Colorado",4301261,1808037,104093.57,376.04,103717.53,41.5,17.4 ),
	array( "South Dakota",754844,323208,77116.49,1231.85,75884.64,9.9,4.3 ),
	…
	array( "Tennessee",5689283,2439443,42143.27,926.15,41217.12,138,59.2 ),
	array( "Texas",20851820,8157575,268580.82,6783.7,261797.12,79.6,31.2 ),
	array( "Utah",2233169,768594,84898.83,2755.18,82143.65,27.2,9.4 ),
	array( "Vermont",608827,294382,9614.26,364.7,9249.56,65.8,31.8 ),
	array( "Virginia",7078515,2904192,42774.2,3180.13,39594.07,178.8,73.3 ),
	array( "Washington",5894121,2451075,71299.64,4755.58,66544.06,88.6,36.8 ),
	array( "West Virginia",1808344,844623,24229.76,152.03,24077.73,75.1,35.1 ),
	array( "Wisconsin",5363675,2321144,65497.82,11187.72,54310.1,98.8,42.7 ),
	array( "Wyoming",493782,223854,97813.56,713.16,97100.4,5.1,2.3 ),
	array( "Puerto Rico",3808610,1418476,5324.5,1899.94,3424.56,1112.1,414.2 )
);
?>
<html>
<head>
<link href="runtime/styles/xp/grid.css" rel="stylesheet" type="text/css" ></link>
<script src="runtime/lib/grid.js"></script>
</head>
<body>
<div style="width:500px;height:300px;">
<script>
var data = [
<?php $first = true; foreach( $states as $state ) { if ( !$first ) echo( "," );
?>
[ "<?php echo($state[0]); ?>", <?php echo($state[1]); ?>,
	<?php echo($state[2]); ?>, <?php echo($state[3]); ?>,
	<?php echo($state[4]); ?>, <?php echo($state[5]); ?>,
	<?php echo($state[6]); ?>, <?php echo($state[7]); ?> ]
<?php $first = false; } ?>
];

var columns = [ "State", "Population", "Housing Units", "Total Area",
 "Total Water", "Total Land", "Population Density", "Housing Density" ];

function dataLookup( row, col )
{
	return data[row][col];
}

function headerLookup( col )
{
	return columns[ col ];
}

var grid = new Active.Controls.Grid;
grid.setRowCount( data.length );
grid.setColumnCount( columns.length );
grid.setDataText( dataLookup );

grid.setColumnText( headerLookup );
document.write( grid );
</script>
</div>
</body>
</html>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Hacks 11–26: Introduction
This chapter covers using Dynamic HTML (DHTML) in your web applications. DHTML is a term used to define the powerful combination of HTML, CSS, and JavaScript. The hacks in this chapter use DHTML to create all types of interactive interfaces for your web applications, from spreadsheets to dynamic graphs, pop ups, slideshows, vector graphics, and more.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Put an Interactive Spreadsheet on Your Page
Use the ActiveWidgets spreadsheet library to put an interactive JavaScript data control on your page.
Let's face it: some data—particularly financial and statistical data—just looks better when it's presented as a spreadsheet. Unfortunately, HTML does a poor job of giving you an interactive spreadsheet-style feel, especially when it comes to scrolling around, sorting, or any of the truly interactive user experience elements of a spreadsheet.
This hack uses the ActiveWidgets (http://activewidgets.com/) grid control to create a spreadsheet-style interface on a web page.
Save the code in Example 3-1 as index.php.
Example 3-1. A script that provides state-specific data in a spreadsheet format
<?php $states = array(
	array( "Alabama",4447100,1963711,52419.02,1675.01,50744,87.6,38.7 ),
	array( "Alaska",626932,260978,663267.26,91316,571951.26,1.1,0.5 ),
	array( "Arizona",5130632,2189189,113998.3,363.73,113634.57,45.2,19.3 ),
	array( "Arkansas",2673400,1173043,53178.62,1110.45,52068.17,51.3,22.5 ),
	array( "California",33871648,12214549,163695.57,7736.23,155959.34,217.2,78.3 ),

	array( "Colorado",4301261,1808037,104093.57,376.04,103717.53,41.5,17.4 ),
	array( "South Dakota",754844,323208,77116.49,1231.85,75884.64,9.9,4.3 ),
	…
	array( "Tennessee",5689283,2439443,42143.27,926.15,41217.12,138,59.2 ),
	array( "Texas",20851820,8157575,268580.82,6783.7,261797.12,79.6,31.2 ),
	array( "Utah",2233169,768594,84898.83,2755.18,82143.65,27.2,9.4 ),
	array( "Vermont",608827,294382,9614.26,364.7,9249.56,65.8,31.8 ),
	array( "Virginia",7078515,2904192,42774.2,3180.13,39594.07,178.8,73.3 ),
	array( "Washington",5894121,2451075,71299.64,4755.58,66544.06,88.6,36.8 ),
	array( "West Virginia",1808344,844623,24229.76,152.03,24077.73,75.1,35.1 ),
	array( "Wisconsin",5363675,2321144,65497.82,11187.72,54310.1,98.8,42.7 ),
	array( "Wyoming",493782,223854,97813.56,713.16,97100.4,5.1,2.3 ),
	array( "Puerto Rico",3808610,1418476,5324.5,1899.94,3424.56,1112.1,414.2 )
);
?>
<html>
<head>
<link href="runtime/styles/xp/grid.css" rel="stylesheet" type="text/css" ></link>
<script src="runtime/lib/grid.js"></script>
</head>
<body>
<div style="width:500px;height:300px;">
<script>
var data = [
<?php $first = true; foreach( $states as $state ) { if ( !$first ) echo( "," );
?>
[ "<?php echo($state[0]); ?>", <?php echo($state[1]); ?>,
	<?php echo($state[2]); ?>, <?php echo($state[3]); ?>,
	<?php echo($state[4]); ?>, <?php echo($state[5]); ?>,
	<?php echo($state[6]); ?>, <?php echo($state[7]); ?> ]
<?php $first = false; } ?>
];

var columns = [ "State", "Population", "Housing Units", "Total Area",
 "Total Water", "Total Land", "Population Density", "Housing Density" ];

function dataLookup( row, col )
{
	return data[row][col];
}

function headerLookup( col )
{
	return columns[ col ];
}

var grid = new Active.Controls.Grid;
grid.setRowCount( data.length );
grid.setColumnCount( columns.length );
grid.setDataText( dataLookup );

grid.setColumnText( headerLookup );
document.write( grid );
</script>
</div>
</body>
</html>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Create Pop-Up Hints
Use the overLIB library to pop up hints for words on your web page using JavaScript and PHP.
With the overLIB JavaScript library (http://www.bosrup.com/web/overlib/), you can have handy pop-up labels that appear above text on your page. This hack makes it a little easier to create these links by providing a PHP wrapper function to invoke the library.
Save the code shown in Example 3-2 as index.php.
Example 3-2. A wrapper function that simplifies overLIB use, courtesy of PHP
<?php
function popup( $text, $popup )
{
?>
<a href="javascript:void(0);" onmouseover="return overlib('<?php echo($popup); ?>
');" onmouseout="return nd();"><?php echo($text); ?></a>
<?php
}
?>
<html>
<head>
<script type="text/javascript" src="overlib.js"><!-- overLIB (c) Erik Bosrup -->
</script>
</head>
<body>
<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;">
</div>
So this is just a test of popups. Not something interesting about <?php popup(
	'rabbits', 'Small furry woodland creatures.<br/>Rabbits also make good pets.'
	); ?>. Because that would just be silly.
</body>
</html>
You could also put the wrapper function into a PHP library, include that library in your PHP pages, and turn this into a nice, reusable utility function.
Download and unpack the overLIB library into your web server's documents directory. Then add in the index.php file and surf to it on your browser. You should see something similar to Figure 3-2.
Figure 3-2: The page with the pop-up link
Next, move the mouse over the word rabbits, and you will see the pop up appear, which gives you a little more information about rabbits (as seen in Figure 3-3).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Create Drag-and-Drop Lists
Use JavaScript, DHTML, and PHP to create and use drag-and-drop lists.
Creating an interface that allows the user to prioritize a list has always been a problem when working with HTML. With PHP, though, this is no longer the case. This hack uses an open source drag-and-drop library from ToolMan (http://tool-man.org/) to create drag-and-drop lists.
Enter the code shown in Example 3-3 and save it as index.html.
Example 3-3. Building a drag-and-drop list with HTML and CSS
<html>
<head>

<style>
#states li { margin: 0px; }
	
ul.boxy li { margin: 3px; }

ul.sortable li {
		position: relative;
}

ul.boxy {
		list-style-type: none;
		padding: 0px;
		margin: 2px;
		width: 20em;
		font-size: 13px;
		font-family: Arial, sans-serif;
}
ul.boxy li {
		cursor:move;
		padding: 2px 2px;
		border: 1px solid #ccc;
		background-color: #eee;
}
.clickable a {
		 display: block;
		 text-decoration: none;
		 cursor: pointer;
		 cursor: hand;
}
.clickable li:hover {
		background-color: #f6f6f6;
}

</style>

<script language="JavaScript" type="text/javascript"
		src="source/org/tool-man/core.js"></script>
<script language="JavaScript" type="text/javascript"
		src="source/org/tool-man/events.js"></script>
<script language="JavaScript" type="text/javascript"
		src="source/org/tool-man/css.js"></script>
<script language="JavaScript" type="text/javascript"
		src="source/org/tool-man/coordinates.js"></script>
<script language="JavaScript" type="text/javascript"
		src="source/org/tool-man/drag.js"></script>
<script language="JavaScript" type="text/javascript"
		src="source/org/tool-man/dragsort.js"></script>
<script language="JavaScript" type="text/javascript"
		src="source/org/tool-man/cookies.js"></script>

<script language="JavaScript" type="text/javascript">
<!--
var dragsort = ToolMan.dragsort()
var junkdrawer = ToolMan.junkdrawer()

window.onload = function()
{
		dragsort.makeListSortable(document.getElementById("states"),
			verticalOnly, saveOrder)
}

function verticalOnly(item) { item.toolManDragGroup.verticalOnly() }

function saveOrder(item) { }

function prepFields()
{
		document.getElementById( "states_text" ).value = junkdrawer.
serializeList( document.getElementById( "states" ) );
		return true;
}
//-->
</script>
</head>
<body>

<ul id="states" class="boxy">
<li>California</li>
<li>Texas</li>
<li>Alaska</li>
</ul>

<form method="post" action="tellme.php">
<input type="hidden" name="states" value="" id="states_text" />
<input type="submit" onclick="return prepFields();">
</form>

</body>

</html>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Build Dynamic HTML Graphs
Using DHTML, you can build graphs that change without requiring even a page refresh. The result? Your users can play with data in real time.
Something is fundamentally unsatisfying about the way the Web works. You click on a link, the page disappears, and that lovely spinning ball or ticking clock grinds by as a new page appears section by section, (hopefully) with the information you want. This certainly is not the interactivity we're all used to from our client-side applications.
But, thank goodness, you can make an application that works without a page refresh. This hack shows you how to make an interactive scatter plot using a few graphics, some PHP, and a whole slew of JavaScript.
The index file, index.php, is shown in Example 3-5.
Example 3-5. JavaScript, the real workhorse in this hack
<?php $states = array(
	array( "Alabama",4447100,1963711,52419.02,1675.01,50744,87.6,38.7 ),
	array( "Alaska",626932,260978,663267.26,91316,571951.26,1.1,0.5 ),
	array( "Arizona",5130632,2189189,113998.3,363.73,113634.57,45.2,19.3 ),
	array( "Arkansas",2673400,1173043,53178.62,1110.45,52068.17,51.3,22.5 ),
	array( "California",33871648,12214549,163695.57,7736.23,155959.34,217.2,78.3 ),
	array( "Colorado",4301261,1808037,104093.57,376.04,103717.53,41.5,17.4 ),
…
	array( "Washington",5894121,2451075,71299.64,4755.58,66544.06,88.6,36.8 ),
	array( "West Virginia",1808344,844623,24229.76,152.03,24077.73,75.1,35.1 ),
	array( "Wisconsin",5363675,2321144,65497.82,11187.72,54310.1,98.8,42.7 ),
	array( "Wyoming",493782,223854,97813.56,713.16,97100.4,5.1,2.3 ),
	array( "Puerto Rico",3808610,1418476,5324.5,1899.94,3424.56,1112.1,414.2 )
);
?>
<html>
<head>
<script language="Javascript">
var width = 300;
var height = 300;

var axes = [ "population", "housing_units", "total_area", "total_water", "total_
land", "people_density", "housing_density" ];

var data = [
<?php $first = true; foreach( $states as $state ) { if ( !$first ) echo( "," );
?>
{ state: "<?php echo($state[0]); ?>", population: <?php echo($state[1]); ?>,
  housing_units: <?php echo($state[2]); ?>, total_area: <?php echo($state[3]); ?>,
  total_water: <?php echo($state[4]); ?>, total_land: <?php echo($state[5]); ?>,
  people_density: <?php echo($state[6]); ?>, housing_density: <?php
echo($state[7]); ?> }
<?php $first = false; } ?>
];

var axmin = {};
var axmax = {};

for( axind in axes )
{
	axmin[ axes[axind] ] = 100000000;
	axmax[ axes[axind] ] = -100000000;
}
for( ind in data )
{
	row = data[ind];
	for( axind in axes )
	{
	  axis = axes[axind];
	  if ( row[axis] < axmin[axis] )
	    axmin[axis] = row[axis];

	  if ( row[axis] > axmax[axis] )
	    axmax[axis] = row[axis];
	}
}

function cleargraph()
{
	graph = document.getElementById( "graph" );
	graph.innerHTML = "";
}

function adddot( value, size, x, y, text )
{
	var left = x - ( size / 2 );
	var top = width - ( y + ( size / 2 ) );

	var cleft = "auto";
	var ctop = "auto";
	var cright = "auto";
	var cbottom = "auto";

	if ( left < 0 ) { cright = ( left * -1 ) + "px"; }
	if ( left + size > width ) { cleft = ( width - left ) + "px"; }
	if ( top < 0 ) { ctop = ( top * -1 ) + "px"; }
	if ( top + size > height ) { cbottom = ( height - top ) + "px"; }

	if ( value <= 0.25 )
		img = "ltgray.gif";
	else if ( value <= 0.50 )
		img = "gray.gif";
	else if ( value <= 0.75 )
		img = "dkgray.gif";
	else
		img = "black.gif";

	html = "<img src=\""+img+"\" width=\""+size+"\" height=\""+size+"\" ";
	html += "style=\"position:absolute;left:"+left+"px;top:"+top+"px;";
	html += "clip:rect( "+ctop+" "+cleft+" "+cbottom+" "+cright+" );";
	html += "\" onclick=\"alert(\'"+text+"\')\"/>";

	graph = document.getElementById( "graph" );
	graph.innerHTML += html;
}

function calculate_value( row, field, min, max )
{
	var val = row[ field ] - axmin[ field ];
	var scale = ( max - min ) / ( axmax[ field ] - axmin[ field ] );
	return min + ( scale * val );
}

function drawgraph()
{
	cleargraph();

	var xvar = document.getElementById( "bottom" ).value;
	var yvar = document.getElementById( "side" ).value;
	var sizevar = document.getElementById( "size" ).value;
	var valuevar = document.getElementById( "color" ).value;

	for( rowind in data )
	{
		var row = data[rowind];
		var x = calculate_value( row, xvar, 5, width - 5 );
		var y = calculate_value( row, yvar, 5, height - 5 );
		var size = calculate_value( row, sizevar, 5, 30 );
		var value = calculate_value( row, valuevar, 0, 1 );
		adddot( value, size, x, y, row.state );
	}
}

function buildselect( axis, current )
{
	var html = "<select id=\""+axis+"\" onchange=\"drawgraph()\">";
	for( axind in axes )
	{
	  var selected = "";
	  if ( axes[axind] == current )
	    selected = " selected=\"true\"";
	  html += "<option value=\""+axes[axind]+"\""+selected+">"+axes[axind]+"
	    </option>";
	}
	html += "</select>";
	document.write( html );
}
</script>
</head>
<body onload="drawgraph();">
Side: <script language="Javascript">buildselect( "side", "population" );</script>
Bottom: <script language="Javascript">buildselect( "bottom", "housing_units" );</
script>
Size: <script language="Javascript">buildselect( "size", "total_area" );</script>
Color: <script language="Javascript">buildselect( "color", "total_water" );</
script>
<div style="position:relative;border:1px solid #eee; clip:rect(0px 0px 300px
300px); width:300px; height:300px;" id="graph">
</div>
</body>
</html>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Section Your Content with Spinners
Use spinners to divide your page content into sections, each of which you can show or hide individually.
Sometimes there is just too much great content to have visible on a single page at one time. One approach is to use tabs [Hack #6] , and another is to section the content with spinners that allow the user to open up specific sections of content. This hack shows how to create sections on your page with spinners that open and show sections of the content interactively.
The code for index.php is shown in Example 3-6.
Example 3-6. PHP allowing for user selection of a specific spinner
<?php
function start_section( $id, $title )
{
?>
<table cellspacing="0" cellpadding="0">
<tr>
<td width="30" valign="top">
<a href="javascript: void twist('<?php echo($id); ?>');">
<img src="up.gif" border="0" id="img_<?php echo($id); ?>"/>
</a>
</td>
<td width="90%">
<h1><?php echo( $title ); ?></h1>
<div style="visibility:hidden;position:absolute;"
  id="<?php echo($id); ?>" class="spin-content">
<?php
}
function end_section()
{
?>
</div>
</td>
</tr>
</table>
<?php
}
function spinner_header()
{
?>
<style type="text/css">

body { font-family: arial, verdana; }
h1 { font-size: medium; border-bottom: 1px solid black; }
.spin-content { font-size: small; margin-left: 10px; padding: 10px; }
</style>
<script language="Javascript">
function twist( sid )
{
  imgobj = document.getElementById( "img_"+sid );
  divobj = document.getElementById( sid );
  if ( imgobj.src.match( "up.gif" ) )
  {
	imgobj.src = "down.gif";
	divobj.style.position = "relative";
	divobj.style.visibility = "visible";
  }
  else
  {
	imgobj.src = "up.gif";
	divobj.style.visibility = "hidden";
	divobj.style.position = "absolute";
  }
}
</script>
<?php
}
?>
<html>
<head>
<?php spinner_header() ?>
</head>
<body>
<?php start_section( "one", "Report part one" ) ?>
This report will tell you a lot of stuff you didn't know before.
And that's good. Because that's what a report should do.<br/><br/>
But it will tell you so much that it needs to be rolled up into sections
so that you don't have to gasp as you see it all at once.
<?php end_section() ?>
<?php start_section( "two", "Report part two" ) ?>
This is a table of numbers and such:<br/>
<table>
<tr><th>State</th><th>Total</th></tr>
<tr><td>CA</td><td>$35M</td></tr>
<tr><td>PA</td><td>$22M</td></tr>
<tr><td>NC</td><td>$5M</td></tr>
<tr><td>FL</td><td>$15M</td></tr>
</table>
<?php end_section() ?>
</body>
</html>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Create Drop-Down Stickies
Use DHTML to position sticky drop-down windows relative to keywords in your HTML.
Attaching a drop-down sticky to a word or phrase in your document is an easy way to add valuable information close to the word, without obscuring it. That way, the user can click on the word and get more contextual information, all without scrolling or lots of mouse movement.
Save the code in Example 3-7 as index.php.
Example 3-7. PHP and JavaScript cooperate to make drop-down stickies work
<?php
$nextid = 1;
function start_link( $text )
{
  global $nextid;
  $idtext = "a"+$nextid;

?><a href="javascript: void drop( '<?php echo($idtext); ?>' );">
	<span id="a_<?php echo($idtext); ?>"><?php echo($text); ?></span></a>
	<div id="<?php echo($idtext); ?>" class="drop" style="visibility:hidden;">
<table cellspacing="0" cellpadding="0" width="170"><tr>
<td valign="top" width="20">
<a href="javascript: void close(<?php echo($idtext); ?>)"><img src="close.gif"
border="0"></a>
</td>
<td valign="top" width="150">
<?php
}

function end_link()
{
?>
</td>
</tr></table>
</div><?php
}

function link_header()
{
?>
<style type="text/css">
body { font-family: arial, verdana; }
.drop {
  padding: 5px;
  font-size: small;
  background: #eee;
  border: 1px solid black;
  position: absolute;
}
</style>
<script language="Javascript">
function drop( sid )
{
  aobj = document.getElementById( "a_"+sid );
  divobj = document.getElementById( sid );
  divobj.style.top = aobj.offsetBottom+10;
  divobj.style.left = aobj.offsetLeft+10;
  divobj.style.visibility = "visible";
}
function close( sid )
{
  divobj = document.getElementById( sid );
  divobj.style.visibility = "hidden";
}
</script>
<?php
}
?>

<html>
<head>
<?php link_header(); ?>
</head>
<body>
Hey <?php start_link( "this is interesting" ); ?>
That really<br/>
Is interesting <?php end_link(); ?>. How about that.
<br/>
The popup will go over text and all that.<br/>
And it will stay up until it's dismissed with the close
button.
</body>
</html>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Create Dynamic Navigation Menus
Use PHP to build a navigation menu widget that works consistently across your site.
Writing the navigation menu for your site can be a pain. You don't want to write the same code over and over on every page. Ideally, you would have a PHP menu function that would render the menu with the current page highlighted. This hack gives you that simple menu function (for the low cost of this book, no less!).
Save the code in Example 3-8, which demonstrates the use of menu.php as index.php.
Example 3-8. Using the menu library
<?php
require_once( "menu.php" );

$page = "home";
if ( $_GET['page'] )
		$page = $_GET['page'];
?>
<html>
<head>
<title>Page - <?php echo($page); ?></title>
<?php echo menu_css(); ?>
</head>
<body>
<table cellspaceing="0" cellpadding="5">
<tr>
<td width="200" valign="top">
<?php page_menu( $page ); ?>
</td>
<td width="600" valign="top">
Page: <?php echo( $page ); ?>

</td>
</tr>
</table>
</body>
</html>
Example 3-9 shows the library, which is surprisingly simple.
Example 3-9. Making everything work with the PHP library, menu.php
<?php
function menu_css() {
?>
<style type="text/css">
.menu-inactive, .menu-active {
		padding: 2px;
		padding-left: 20px;
		font-family: arial, verdana;
}
.menu-inactive { background: #ddd; }
.menu-active { background: #000; font-weight: bold; }
.menu-inactive a { text-decoration: none; }
.menu-active a { color: white; text-decoratio