Solving Formatting Problems With Modulo (Or Fun With Modulo)

Solving Formatting Problems With Modulo (Or Fun With Modulo)

Making Tables More Readable With Alternating Row Colors

Typographers have known for a long time that tabular data is easier to read when presented with alternating colors for each row. Most people have at one time or another seen computer printer paper with the light green bars alternating with white. To give your web listings and tables greater readability add alternating row background colors.

The question is how to implement this. Some way of keeping track of which row we are on and assigning a color is needed. This tutorial is too short to go into all the various ways you might try to do this by brute force. Instead I will offer a technique whose origin is lost in the mists of programmer lore.

We will turn to modular arithmetic to do the trick. Most programming languages offer a modulo operator, which returns the remainder of a division. I will not go into modular arithmetic here, you can find detailed explanations by doing a web search on the topic. We are interested in a particular behavior of the modulo function. It has the curious property that if you take a number modulo a second number, the first number never exceeds the value of the second. In other words, it acts to limit the value of a variable and that value will “wrap around” back to zero no matter how large the first number becomes.

Suppose we want to limit a value to 256 (0-255) the amount a single byte can express.

0   modulo 256 = 0
100 modulo 256 = 100
255 modulo 256 = 255
256 modulo 256 = 0 (wraps around here)

The modulo is usually expressed in mathematical notation by mod as in 2 mod 7. In PHP, the modulo operator is the percent sign.

If we keep track of how many rows have been displayed we can use modulo to determine whether the row should use one color or another (given a total of two colors). We know that any number modulo will result in the following table:

(row, frequency, color)
0 % 2 = 0
1 % 2 = 1
2 % 2 = 0
3 % 2 = 1
4 % 2 = 0

Zero modulo two is zero, one modulo two is one, two modulo two is zero because we wrap around at the point the numbers are equal, any number greater than two continues this alternating pattern of one and zero.

This result is very useful. We now have a way of deciding for any given row which color should be displayed. If the result is 0, we display one color, if the result is 1, we display the alternate color for that row.

Here is a function I use frequently. Especially when displaying the output from relational database queries, which is naturally arranged into tables. This function returns either of two colors depending on a given row index. The colors are termed ‘light’ and ‘dark’ because typically alternating colors are designed to either alternate a light and dark color against which black type is readable. Typically white and light green or perhaps two light colors such as medium and light gray. The default parameters define white and gray when no colors are specified by the calling program.

function get_alt_row_color($i,$light_color="#ffffff",$dark_color="#e4e4e4") {
if ($i % 2 == 0) {
		return $light_color;
	} else {
		return $dark_color;
	}
}

You can call it directly in HTML code. When generating a HTML table, use something like this inside the loop:


/* ... looping through database records ... */

// code to generate a table row
$content .= '
<tr>
	<td bgcolor="'. get_alt_row_color($i,$light_color="#ffffff",$dark_color="#eeeeee") .'">' $row[data]. '</td>
</tr>';

$i++; // increment row index

/* ... continue looping through database records ... */

Take note of how the function is used directly in string concatenation. This is a good technique: create a function that generates the text string you want, then drop it into the concatenation anywhere you want the output. Here the BGCOLOR attribute gets its value from the get_alt_row_color() function. This makes it portable, flexible and generic compared to a function that generates a predefined table row. A function is less error prone than repeating the same code everywhere.

There is another way to write code to alternate colors.

function get_alt_row_color($i) {

if ($i % 2 == 0) {
		return '#FFFFFF';
	} else {
		return $GLOBALS['COLOR_ROW_ALT'];
	}
}

This function takes its alternate color from a global variable, perhaps allowing the user to specify the alternate color in a configuration file. Calling the function is simplified by avoiding the color parameters and assuming the first color is white. Use your imagination to invent other more configurable functions.

Presenting Content in Two Columns

If you’ve read a newspaper then you are familiar with text arranged into columns. It is a very efficient way of displaying text and helps keep content at the top of the page reducing scrolling.

You might ask how do they do that when you see a dynamic website presenting varying content in two columns. How do they distribute content evenly between the two columns when they do not know the number of items until they are retrieved from a database or other source?

Modular arithmetic comes to the rescue again. First we find the number of items in the content. Then we calculate a division point where items will go into one column or the other. For two columns this division point is about half the number of items. We will use half the number of items as our division point.

Once we have these values, we can begin looping through the query results, array or list of items. In this example the array is from a database query result. However, it could be any array, we could just pass the function an array along with the division point.

function make_columns_from_array($result,$division_point) {
$division_point = mysql_num_rows($result) / 2;

$i=0;
while ( $row = mysql_fetch_array($result) )
{
$item = sprintf("<p class=item><b><a href="$PHP_SELF?category=%s">%s</a></b> (%s)<br><span class=description>%s</span></p>",$row[category_id],decat($row[category_title]),$row[items],$row[category_description]);

	if($i % $division_point) {
		$a .= "$item";
	}
	else {
		$b .= "$item";
	}
	$i++; // increment index
}
$content = '
<table>
<tr valign="top">
	<td>'. $a; .'</td>
	<td>'. $b; .'</td>
</tr>
</table>';
return $content;
}

Using modulo we place an item in one of two strings, $a or $b distributing them between the columns. After that we put the $a items in the left table column and the $b items in the right column. There are probably more elegant and efficient ways to do this. I leave that to others.

Modular Arithmetic

The code in this tutorial is based on modular arithmetic. It is so useful in programming that the modulo operator appears in nearly all computer languages and has been used since the dawn of programming for all kinds of tricks. It is well worth your time learning about it.

[ul]Clock (Modular) Arithmetic - Easy to understand explanation.
Modular Arithmetic - Mathematical and algebraic explanation.
Google Search for Modular Arithmetic[/ul]

Ok

The first part of this code is :-/

Heres what I have

[code]<?php

/*********************************

  • Lets add the functions *
    *********************************/

function get_alt_row_color($i,$light_color="#ffffff",$dark_color="#e4e4e4") {
if ($i % 2 == 0) {
return $light_color;
} else {
return $dark_color;
}
}
?>[/code]

echo "<td bgcolor='". get_alt_row_color($i,$light_color='#ffffff',$dark_color='#eeeeee') . "'>" . $row["size"] . "</td>"; echo "<td bgcolor='". get_alt_row_color($i,$light_color='#ffffff',$dark_color='#eeeeee') . "'>" . $row["version"] . "</td>";

When you refresh the page they change, I want them always to be the same :-/

also tried using {get_alt_row_color}

If you see on phpbb, thats how i want it lol

http://www.phphelp.com/phpBB2/memberlist.php

light
dark
light
dark
etc

$list_of_items = array('Sandbox One','Sandbox Two','Sandbox Three','Sandbox Four');

$content = '<table width="100%">';

	$line_count = 0;
	foreach ($list_of_items as $title) {
		$content .= '<tr bgcolor="'. get_alt_row_color($line_count). '">';
		$content .= '<a href="view.php?name='. urlencode($title) .'">'. $title .'</a></td></tr>';
		$content .= "n";
		$line_count++;
	}

$content .= '</table>';

print $content;

The output looks like this.

[code]

Sandbox OneSandbox TwoSandbox ThreeSandbox Four
[/code] I put together this example, which I will add to the tutorial later. If you call get_alt_row_color() with only the line count argument, the default colors are used. This is what I have done in the example and frequently use the function this way, setting the colors in the function.

It should work with your own values for the colors. One word of caution, if there the color variables do not exist or empty strings are given for the colors, no color will be set.

Hope this helps,

Steve

isnt this a depreciated variable-type?

$GLOBALS[’’];

Actuatly got a dif code and it worked, this one, each time the page is reloaded the colors alternate

I guess I found this way to be pretty easy and simple. Maybe your way is better though. I just know this one works also.

[php]<?
$light = “#bdd9f4”;
$dark = “#93c6f0”;
$color = $light;

while($row=mysql_fetch_array($result))
{
if ($color == $dark)
{
?>


TD 1
TD 2
<? $color = $light; } else { ?>
    <tr>
             <td bgcolor="<?echo $light;?>">TD 1 </td>
             <td bgcolor="<?echo $light;?>">TD 2 </td>
        </tr>
<? $color = $dark; } } [/php]

Here’s an article I wrote covering this topic. I figured some of you might get some use out of it.

http://www.msbware.com/articles/php/alternating_row_colors.html

@MSBWare: the XOR function doesn’t work because

  • 1 ^ 1 = 0
  • 2 ^ 1 = 3
  • 3 ^ 1 = 2
  • 4 ^ 1 = 5
  • 5 ^ 1 = 4
    etc.

What you’re probably looking for is the AND function:

  • 1 & 1 = 1
  • 2 & 1 = 0
  • 3 & 1 = 1
  • 4 & 1 = 0
  • 5 & 1 = 1
    etc.

Ah okay. Someone posted a comment at the end of the article suggesting the bitwise operator ^ so that’s why I tried that out. Thanks for the suggestion though, I will have to give that a try and post the results to the article.

The only credits I want is the linky to phphelp.com :wink:

Sponsor our Newsletter | Privacy Policy | Terms of Service