- PeterMoulding.com
- Author
- Trainer
- Speaker
- Business Coach
- How to write a How To book
- PHP Courses
- Speaking
- Web Architect
- Australia
- Books
- Authors
- Akkana Peck
- Alex Berenson
- Andrew Nugent
- Ben Sanders
- Brock Clarke
- Chris Simms
- David Mercer
- Dianna Mullet
- Don Winslow
- Dori Smith
- Harlan Coben
- Jack McDevitt
- James Wines
- Jerry Yudelson
- John Grisham
- Kevin Mullet
- L. E. Modesitt Jr.
- Laurell K. Hamilton
- Marshall Karp
- Martina Cole
- Michael Marshall Smith
- Michel Roux Jr
- Nadia Sawalha
- Philip Pullman
- Raymond Khoury
- Richard North Patterson
- Robert Masello
- Sally Roth
- Sarah Langan
- Stella Rimington
- Stephen King
- Stephen Leather
- T.C. Boyle
- Tom Negrino
- Tony Hillerman
- Urban Waite
- Val McDermid
- Valerio Massimo Manfredi
- Beginning GIMP
- Beginning Visual C++
- Culturalism
- Fiction
- A Drink Before The War
- A Talent for War
- Bag of Bones
- Blood and Ice
- Burn
- Dark Lady
- Dead Line
- Eclipse
- Empress of Eternity
- Exley
- Flipping Out
- Just One Look
- Nightfall
- Pet Sematary
- Savage Moon
- Skinwalkers
- Starvation Lake
- The Fallen
- The Gardens of the Dead
- The Jump
- The Last Templar
- The Mermaids Singing
- The Midnight Mayor
- The Secret Soldier
- The Summons
- The Terror of Living
- The Testament
- The Tower
- Under the Dome
- Virus
- AJAX and PHP
- Aging with Grace
- Food books
- Green Architecture
- Life Is So Good
- SQL: The Complete Reference
- The Backyard Bird Lover's Ultimate How-to Guide
- The Garden Gurus
- Authors
- Sustainability
- -18 hours left to decide the future of Australia
- Campbells vegetable stock or Massel vegetable stock?
- Carbon Sequestration
- Carbon tax for Australia is a fraud
- Copenhagen will fail
- Cost of living in Australia
- Dick Smith jumps on the population bandwagon
- Dry Run: Preventing the Next Urban Water Crisis
- Energy Saving Lights
- Garlic
- How many people can live in Australia?
- Julia Gillard offers 9.9 billion dollars bribe to Rob Oakeshott
- Laundry detergent
- Petrol or Diesel?
- Reflective foil batts kill
- RoHS
- Sea level to rise 3mm due to climate change
- Solar power
- Spring again in Sydney
- Sustainable fuels
- The CRUD Tax is back
- The people who make building regulations do not own houses
- Water efficiency
- Which insulation is safer, foil or wool?
- Will Australia reduce greenhouse gas emissions?
- Technology
- Android or Blackberry or iPhone or a flip phone?
- Apple versus Google 2011
- Cameras
- Cars
- Colour
- Burgundy
- Colour Blindness
- Colour Names
- Dulux colours
- Pantone colours
- Safe Colours
- Seculine ProDisk Mini colour balance card
- What Causes Colour Blindness?
- Hardware
- Batteries for the Digital Age
- Cables
- Cases
- Computer reliability
- Computrace
- Disks
- Astone ISO Gear 481E
- Best SSD for your notebook computer
- Disk block size
- Hitachi disk HDS722020ALA330
- LaCie USB 2.0 250 GB mobile hard drive design by F.A. Porsche
- SMART disk
- Samsung 2 TB HD204UI quiet low power disk for mass storage
- Seagate and Samsung merge disk business
- Select the right disk for your RAID array
- USB disk speed
- Western Digital WD20EARX 2 GB SATA 3 disk
- How long should computer hardware last?
- Keyboards
- Mainframe
- Memory cards
- Monitors
- Netbooks, notebooks, tablets, and xPads
- Network Attached Storage
- OLED Displays
- PC's are a thing of the past
- Printers
- Quiet
- Samsung Galaxy S
- Speed
- Television
- Tools
- USB
- Worst computer movies
- Xserve is dead. What next?
- Your backup will not work
- iPad or Acer Aspire One?
- IQ
- Its obsolete, throw it out!
- LG Intello Washing Machine
- Lack of a challenge
- NBN spends another $12 billion of our tax money on nothing
- Networks
- 802.11n wireless networking
- D-Link DIR-655 wireless router
- D-Link DWA-160 Xtreme N dual band USB adapter
- D-Link DWA-556 Xtreme N PCI Express desktop adapter
- MIMO
- National Broadband Network
- Netgear wireless modem router DGND3300 with 300 Mbps 802.11n
- Refrigerator kills wireless broadband
- Small Wireless Network
- TP-LINK TL-SG10005D 5 port gigabit switch
- TP-Link TL-WR1043N wireless N gigabit router
- Telstra Pre-paid Mobile Wi-Fi
- Where are the router plus proxy server combinations?
- Open Source documentation
- Software
- 7-zip
- Accounting
- Asterisk
- Audacity
- Backup software
- Bloat only in Windows
- CAD
- CDex
- Disk imaging software for copying and backup
- Exact Audio Copy
- Filezilla
- Firefox
- Java
- LibreOffice or OpenOffice?
- Linux
- 1 in 5 servers will ship with Linux
- Android phones outsell iPhone
- Another Move to Linux
- CentOS 5.5 installation on SSD and RAID 5
- Debian
- Debian 5.0.5 AMD64 installation
- Fedora
- Fedora or Ubuntu?
- Gnome or KDE?
- K9copy
- Linux 2.6.38
- Linux Gnome login settings lost
- Linux Mint
- Linux RAID, a rant
- Linux Speed
- Linux Time
- Linux reliability as demonstrated by Ubuntu 10.10
- Linux reliability as demonstrated by Ubuntu 11.4
- Linux still a struggle in 2011
- Linux workstation disk RAID 1
- Linux, NT, Windows, and SETI
- Linux, three years of progress
- London Stock Exchange switches to Linux
- Mandrake Linux 9.2
- The partition is misaligned by 48128 bytes - warning from Linux RAID
- Ubuntu
- How to fix the scroll bars in Ubuntu 11.4 Gnome
- Kubuntu 10.10 alternate installation on desktop with RAID 1
- POWbuntu
- Ubuntu 10.10 after 6 months use
- Ubuntu 10.10 alternate installation
- Ubuntu 10.10 desktop RAID 1
- Ubuntu 10.10 desktop RAID 5
- Ubuntu 10.10 desktop install on a netbook
- Ubuntu 10.10 desktop installation
- Ubuntu 10.10 netbook install on a netbook
- Ubuntu 10.10 server AMD64
- Ubuntu 10.10 upgrade to version 11.4 beta 2
- Ubuntu 10.4
- Ubuntu 11.10
- Ubuntu 11.10 first upgrade
- Ubuntu 11.4 after one month use
- Ubuntu One
- Ubuntu by Microsoft?
- Ubuntu desktop upgrade 10.4 to 10.10 failed because I did not check the media
- Ubuntu strikes again
- Yes, use Linux but not that distribution!
- Nero
- OpenOffice
- OpenOffice is now Apache Office
- Project management
- Scribus
- Software for Windows and Linux
- Time
- Todo applications
- Tomboy notes
- Top text editors
- Version control
- VideoLAN VLC media player
- Visio
- Webmin
- Webmin installation on CentOS for Web development
- Webmin installation on Ubuntu
- What is the most popular open source software today?
- Windows
- Another Windows person goes Linux
- BAD_POOL_CALLER
- Cygwin
- Microsoft Malicious Software Removal Tool cannot find a common virus
- One of the developers of Windows XP is criminally insane
- There are unused icons on your desktop
- W32time
- Which Windows version?
- Windows 7 Home Premium
- Windows XP Stop 0x0000007B during installation
- Windows XP is a disaster
- Windows processes
- XML
- Zip, bzip, gzip, or 7zip?
- configFree
- Technology Succession Planning
- VoIP
- Web Sites
- Drupal
- Do Drupal themes have to use the GPL?
- Drupal 7
- A better search facility for Drupal
- Drupal - performance or flexibility
- Drupal 7 new features
- Drupal 7 ships on January 5
- Drupal 7.4 hits PeterMoulding.com
- Drupal function sequence
- The evolution of a module
- Undefined index: headers in DefaultMailSystem->mail() (line 54 of /modules/system/system.mail.inc).
- Undefined index: to in DefaultMailSystem->mail() (line 83 of /modules/system/system.mail.inc).
- implode(): Invalid arguments passed in DefaultMailSystem->format() (line 23 of /modules/system/system.mail.inc).
- Drupal Code Load Cut
- Drupal How To
- Drupal Modules
- Backup and Migrate
- Browscap
- CKEditor with Drupal WYSIWYG
- Captcha
- Colorbox
- Content Construction Kit
- Content type
- Devel module for Drupal
- Drupal Rules as an automation language
- Drupal Spam add-on module
- IMCE
- IMCE Wysiwyg bridge
- ImageAPI
- Lightbox2
- Node Gallery Access
- Node_Gallery
- Path
- Path redirect
- Pathauto
- Pet
- Search
- Service links
- Session Variable
- Taxonomy
- Token
- Transliteration
- Trigger
- Variable module
- Other modules
- Drupal Training
- Drupal access controls need a major rewrite
- Drupal coding tricks
- Drupal performance
- Drupal themes for the future
- Drupal.org colours
- Import existing data into Drupal
- Multiple Web sites made easy using Drupal multisite and the right start
- drupal_lookup_path()
- Adobe PDF
- Apache
- Apache Mahout
- Audi.com
- Bleet
- CSS Strikes Again
- CSS or xCSS
- Can you believe Facebook or email?
- Content Management Systems
- Databases
- Facebook scam
- Font
- Fonts
- HTML
- Install Apache, MySQL, and PHP 5 in Ubuntu 11.4 using the Ubuntu Software Centre
- Language Codes
- Marketing
- Memcache
- Nginx
- Oscars
- PHP
- SPDY
- Search software
- Techoni.com.au
- Theme themes
- U.S. Patent No. 6,985,875
- Virtual Private Server
- Visible Improvement
- Web 4.0
- Web browser usage
- Web browsers
- Web site development
- Bluefish
- Eclipse and PHP
- Getting a Git client, a story of ancient technology and pain
- HTTrack
- MVC
- Netbeans
- Nvu
- PHP
- PHP or ..., CakePHP/Symfony/ZF versus ...
- Programming
- Superfish
- Web browser emulators for testing your Web site
- Web development frameworks
- Web site books
- Web site development on your own computer
- Webmin or phpMyAdmin or cPanel for creating databases?
- aiki framework
- jQuery
- Views development - Learn Fields first
- Views development - Learn Actions and Rules
- jQuery .each()
- jQuery .has()
- jQuery .is()
- jQuery and Firefox Firebug
- jQuery children
- jQuery for people not using Drupal - Installation and getting started
- jQuery hover
- jQuery hover de-duplication example
- jQuery or CSS?
- jQuery performance
- jQuery tests
- Web site hosting
- Westpac Web site still broken after two years and ten months
- Wordpress wins another CMS survey
- Drupal
Charts
Line Charts
Here is an extra section I added online after the PHP Black Book was printed.
You can draw line charts with PHP and basic HTML. The example can be refined using GIF, JPEG or PNG files. This version is slow to display in Netscape and some other browsers but can be tuned. A version built with more sophisticated code would display faster in problem browsers and would be a step toward using a higher resolution.
Data
First you need data. The following code simple converts a string to numbers in an array using ord(). $data contains a string of characters, the for() loop steps through the characters, ord() returns the binary integer value of each character, and the integer is stored in $numbers.
$data = "The quick brown fox jumped!";
$data_length = strlen($data);
for($i = 0; $i < $data_length; $i++)
{
$numbers[] = ord(substr($data, $i, 1));
}
Display the contents of the number array using implode(). implode() connects all the values in an array using the string specified as the first parameter.
print(implode(", ", $numbers));
The code produces:
84, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 32, 106, 117, 109, 112, 101, 100, 33
Chart Function
This is the function to produce the chart. Skip the code, look at the result, then read the code explanation.
function linearchart($data, $colour="blue", $origin=0, $increments=20)
{
$maximum_value = 0;
foreach($data as $value)
{
if($value > $maximum_value)
{
$maximum_value = $value;
}
}
$increment = $maximum_value / $increments;
$percent = intval(90 / $increments); // 90% of the chart is available.
// $origin is not yet implemented.
$edge_line = '<td bgcolor="Black" width="1%"> </td>';
$rows = '<tr><td width="4%"><em>Item </em></td>' . $edge_line;
for($i = 1; $i <= $increments; $i++)
{
$rows .= '<td bgcolor="Black" width="1%"> </td>';
}
$rows .= '<td width="5%"><em> Value</em></td></tr>' . "\n";
$separator_repeat = 10;
$separator = '<tr><td> </td>' . $edge_line;
for($i = 1; $i <= $increments; $i++)
{
$separator .= '<td bgcolor="Black" width="' . $percent . '"> </td>';
}
$separator .= '<td> </td></tr>' . "\n";
foreach($data as $key >= $value)
{
if($key > 0 and ($key % $separator_repeat) == 0)
{
$rows .= '';
$rows .= $separator;
}
$rows .= '';
$rows .= '<tr><td>' . $key . ' </td>' . $edge_line;
$x = $value / $increment;
for($i = 1; $i <= $x; $i++)
{
$rows .= '<td bgcolor="blue" width="' . $percent . '"> </td>';
}
for($i = $i; $i <= $increments; $i++)
{
$rows .= '<td> </td>';
}
$rows .= '<td width="' . $percent . '"> ' . $value . '</td></tr>' . "\n";
}
if(($key % $separator_repeat) != 0)
{
$rows .= $separator;
}
return('<table border="0" cellspacing="0" cellpadding="0">' . "\n"
. $rows . "</table>\n");
}
Chart Display
Here is a chart built with HTML and no graphics. You can convert this chart to higher resolution by replacing the character elements with pixel size files of type GIF, JPEG, or PNG.
print(linearchart($numbers));
The code produces:
| Item | Value | |||||||||||||||||||||
| 0 | 84 | |||||||||||||||||||||
| 1 | 104 | |||||||||||||||||||||
| 2 | 101 | |||||||||||||||||||||
| 3 | 32 | |||||||||||||||||||||
| 4 | 113 | |||||||||||||||||||||
| 5 | 117 | |||||||||||||||||||||
| 6 | 105 | |||||||||||||||||||||
| 7 | 99 | |||||||||||||||||||||
| 8 | 107 | |||||||||||||||||||||
| 9 | 32 | |||||||||||||||||||||
| 10 | 98 | |||||||||||||||||||||
| 11 | 114 | |||||||||||||||||||||
| 12 | 111 | |||||||||||||||||||||
| 13 | 119 | |||||||||||||||||||||
| 14 | 110 | |||||||||||||||||||||
| 15 | 32 | |||||||||||||||||||||
| 16 | 102 | |||||||||||||||||||||
| 17 | 111 | |||||||||||||||||||||
| 18 | 120 | |||||||||||||||||||||
| 19 | 32 | |||||||||||||||||||||
| 20 | 106 | |||||||||||||||||||||
| 21 | 117 | |||||||||||||||||||||
| 22 | 109 | |||||||||||||||||||||
| 23 | 112 | |||||||||||||||||||||
| 24 | 101 | |||||||||||||||||||||
| 25 | 100 | |||||||||||||||||||||
| 26 | 33 | |||||||||||||||||||||
The Code Explained
Here is a chart built with HTML and no graphics. You can convert this chart to higher resolution by replacing the character elements with pixel size files of type GIF, JPEG, or PNG.
The code is implemented as a function so you can change things within the function without worrying about variable names. If the function became more complicated or the chart generation process required more functions, you would be better off looking at defining a class and generating an object.
Note the variables passed to the chart function. $data receives an array of values for display. Each array entry supplies a value for one line in the chart and the value is displayed on the right to let people easily see the exact values. The entry keys are displayed on the left and could be used for time, date, or any value that continually changes. If you need to display data that could have duplicate keys, you would change the array to have both values as part of the entry and let the key default to a system generated vlaue.
$colour provides the name of the colour for the value bars and can contain #RGB numbers. $origin is not yet implemented but could let you start a value bar from a value other than zero. If you look at the example, there are no values under 32 so so you could increase the resolution of this chart by starting the chart at 32 on the left hand side. $increments supplies the number of line size increments included in the chart. When I tested this script with Netscape, twice as many lines, and twice as many increments, the display was noticeably slow. At four times as many llines and 100 increments, Netscape 4.78 choked.
function linearchart($data, $colour= 'blue', ;$origin=0, $increments=20)
{
The next code loops through the input data to find the largest value so the chart increments can be calculated. If you are collecting many charts run on separate days or months, you will find some charts easier to follow if they are set to the same fixed maximum value. You can more easily perform a quick visual comparison of charts when their size and layout are the same.
$maximum_value = 0;
foreach($data as $value)
{
if($value > $maximum_value)
{
$maximum_value = $value;
}
}
$increment and $percent are used to space out the blue bars on the chart. $increment is vidided in to values to decide how many increments will be blue. $percent is the percentage value supplied in the HTML for the columns containing increments.
$increment = $maximum_value / $increments;
$percent = intval(90 / $increments); // 90% of the chart is available.
The following code creates the first line or row of the chart. You can add any headings you line in this cpde as it is performed just once per chart.
$rows = '<tr><td width="4%"><em>Item </em></td>' . $edge_line;
for($i = 1; $i <= $increments; $i++)
{
$rows .= '<td bgcolor="Black" width="1%"> </td>';
}
$rows .= '<td width="5%"><em> Value</em></td></tr>' . "\n";
The separator code adds an extra line at regular intervals to help you line up keys and values on charts that have very few full rows. You can leave the separators out when your charts has lots of lines running most of the way toward the value column.
$separator_repeat = 10;
$separator = '<tr><td> </td>' . $edge_line;
for($i = 1; $i <= $increments; $i++)
{
$separator .= '<td bgcolor="Black" width="' . $percent . '"> </td>';
}
$separator .= '<td> </td></tr>' . "\n";
The big foreach() loop steps through the value array using the new foreach() funtion in PHP. If your version of PHP does not contain foreach() and you cannot update, use the while(list($key, $value) = each($data)) structure shown in the PHP Black Book.
foreach($data as $key >= $value)
{








