Example Pepper: Window Width
This article is part of a series on developing Pepper for Mint introduced here.
Now that we’ve covered the basics, we’re going to walk through building a simple Pepper. This Pepper will determine the viewer’s browser window width using JavaScript. The width will be stored in a single column added to the Mint visit table. The Pepper will present its findings as percentages in a single tab of a single pane. It will offer a grouping preference. Let’s call this Pepper “Window Width.” You can grab the finished files here to better understand how this all fits together.
Once we’ve decided on a purpose and a name we can start building our Pepper. Begin by creating a developer directory. We’ll use mine, which is /shauninman/
, in this example. Next create the Pepper directory, typically the lowercase Pepper name without spaces, eg. /windowwidth/
. This is where all of our Pepper files will live. Create a new PHP document named class.php
and add a PHP comment identifying yourself as the developer, the Pepper name, and any terms of use.
<?php
/******************************************************************************
Pepper
Developer : Shaun Inman
Plug-in Name : Window Width
[shauninman.com](www.shauninman.com/)
******************************************************************************/
if (!defined('MINT')) { header('Location:/'); }; // Prevent viewing this file directly
?>
Below the comment (but before the closing ?>
) we need to define our Pepper class and add the class name to the $installPepper
variable. (The $installPepper
variable appears to be in the global space but since this file will only be included from within a method of the Mint object the variable’s scope will be limited to that method.) Pepper class names should be CamelCase prefixed with a developer token and an underscore. Using my developer token we end up with:
$installPepper = "SI_WindowWidth";
class SI_WindowWidth extends Pepper
{
}
Now we need to define some properties for our Pepper.
var $version = 1; // Displays as 0.01
var $info = array
(
'pepperName' => 'Window Width',
'pepperUrl' => 'www.haveamint.com/',
'pepperDesc' => 'The Window Width Pepper picks up where User Agent 007 leaves off by tracking the width of the browser window on each page load allowing you to make more informed design decisions regarding page width than you could with screen dimensions alone.',
'developerName' => 'Shaun Inman',
'developerUrl' => 'www.shauninman.com/'
);
var $panes = array
(
'Window Width' => array
(
'Refresh'
)
);
var $prefs = array
(
// Common resolutions widths minus worst-case browser chrome width (56)
'widthGroups' => '584, 744, 968, 1096, 1344, 1384, 1544, 1624, 1824'
);
var $manifest = array
(
'visit' => array
(
'window_width' => "TINYINT(5) NOT NULL"
)
);
The $version
and $info
properties are self-explanatory. This Pepper has a single pane labeled “Window Width” with a single tab labeled “Refresh.” It also has a single widthGroups
preference. The $manifest
property indicates that a single column named “window_width” should be added to the Mint visit table. The Window Width Pepper doesn’t store any additional data so the $data
property is omitted.
Because this is the first version of this Pepper and it doesn’t need to react to updates to Mint, we don’t need to define the onUpdate()
event handler or update()
method. The isCompatible()
method may also be omitted but omission results in a disclaimer being added before the Pepper description in the list of uninstalled Pepper. So we’ll do a quick check to make sure that this Mint installation meets our minimum requirements.
/**************************************************************************
isCompatible()
**************************************************************************/
function isCompatible()
{
if ($this->Mint->version >= 120)
{
return array
(
'isCompatible' => true
);
}
else
{
return array
(
'isCompatible' => false,
'explanation' => '<p>This Pepper is only compatible with Mint 1.2 and higher.</p>'
);
}
}
Since PHP is a server-side technology we need to employ some JavaScript to determine the width of the browser window. The following steps are not necessary if your Pepper can do what it needs to do using information already available on the server-side.
The Mint JavaScript object provides a way to prevent collisions with local scripts and pass additional data back to the Mint PHP object. To prevent collisions with other Pepper developers and to utilize the onsave()
event handler you need to create your own developer object as a property of the Mint object. If you have more than one Pepper that utilizes JavaScript you’ll need to make sure that your developer object doesn’t already exist before defining it. This is necessary because Pepper are loaded and the Mint JavaScript include is written in the order each Pepper was installed. Also, take care that your code does not interfere with any existing element event handlers (eg. the body onload
event or anchor onclick
events).
So now we’ll create script.js
in our Pepper directory. We’ll use my developer token as the name of the developer object:
if (!Mint.SI) { Mint.SI = new Object(); }
Then we add the WindowWidth object as a property of my developer object and write the onsave()
event handler for the new object. The Mint JavaScript object expects the onsave()
event handler to return a query string containing &name=value
pair(s) that it will then pass to the Mint PHP object.
Mint.SI.WindowWidth =
{
onsave : function()
{
var width = -1;
if (window.innerWidth)
{
width = window.innerWidth;
}
else if (document.getElementsByTagName)
{
var html = document.getElementsByTagName('html');
if (html[0].offsetWidth)
{
width = html[0].offsetWidth;
}
}
return '&window_' + width;
}
};
Now that we’ve written our script we need to let Mint know to include it by adding the onJavaScript()
event handler. The path to our file should be relative to the Mint directory (not the Pepper class file). It should not start with a slash.
/**************************************************************************
onJavaScript()
**************************************************************************/
function onJavaScript()
{
$js = "pepper/shauninman/windowwidth/script.js";
if (file_exists($js))
{
include_once($js);
}
}
At this point Mint is aware of the data this Pepper tracks. Using the onRecord()
event handler, we’ll validate the width and tell Mint where to store it.
/**************************************************************************
onRecord()
**************************************************************************/
function onRecord()
{
$windowWidth = $this->Mint->escapeSQL($_GET['window_width']);
return array
(
'window_width' => (float) $windowWidth
);
}
The onDisplay()
event handler is pretty straight forward in this Pepper. The nested switch statements are present only to comform with the structure of the onDisplay()
handler of other Pepper that have multiple tabs and panes.
/**************************************************************************
onDisplay()
**************************************************************************/
function onDisplay($pane, $tab, $column = '', $sort = '')
{
$html = '';
switch($pane)
{
/* Window Width ***************************************************/
case 'Window Width':
switch($tab)
{
/* Refresh ************************************************/
case 'Refresh':
$html .= $this->getHTML_WindowWidth();
break;
}
break;
}
return $html;
}
The getHTML_WindowWidth()
function does the heavy lifting here. It is a little different from the getHTML
functions of most Pepper since it performs multiple SELECT
queries to gather its data. (Take a look at the Default Pepper for an example of typical getHTML
functions.) However it is still useful in illustrating how to use Mint’s generateTable()
method which takes a specially organized array and returns the HTML table that displays your Pepper’s data.
The array (referrerd to here as $tableData
) has three indices, table
, thead
, and tbody
, each containing an array.
$tableData['table']
has two indices, id
and class
. These values are mapped to the HTML table attributes of the same name. The table
index may be omitted (as it is in this example) if the table doesn’t require an id
or class
attribute.
$tableData['thead'] = array
(
// display name, CSS class(es) for each column
array('value'=>'Width','class'=>''),
array('value'=>'% of Total','class'=>'')
);
$tableData['thead']
contains an array for each column in the HTML table we’re generating. Each array should have two indices, value
and class
. This is used to generate the table heads. The class
index is applied to the <th>
and all <td>
s in that column.
$tableData['tbody'][] = array
(
"Greater than $width",
$this->Mint->formatPercents($r['total']/$total*100)
);
$tableData['tbody']
contains an array for each row in the table. Each row is represented by an array containing an value for each column.
The generateTable()
method takes this array and generates an HTML table adding in first-child
, only-child
, last-child
and alt
classes where appropriate—ensuring that the CSS has the proper hooks to style the table so a consistent presentation is maintained across all panes.
The last thing we need to worry about for this Pepper is the Preferences. Both preference event handlers are pretty straight forward so we’ll end here with a link to the completed Window Width Pepper.
And this concludes the Introduction to Pepper Development series. Questions? Visit the Mint Forum.
- Previous
- Pepper Event Handlers and Methods
- Next
- Champions of Multimedia Design
- Author
- Shaun Inman
- Posted
- October 21st, 2005 at 2:26 pm
- Categories
-
PHP
Mint
Web