Skip to page content or Skip to Accesskey List.

Work

Main Page Content

Write Once Almost With Php

Rated 3.58 (Ratings: 1)

Want more?

  • More articles in Code
 

benjamin deboute

Member info

User since: 14 Dec 1999

Articles written: 2

Write Once ! (almost) :: the print "" method

An approach to browser specific content and easy maintenance through PHP3 ::

How much would you pay for Godlike power given to mere Webdevs? Nothing? So enter PHP! i plan to do three of this courses, this one is an intro to PHP and the first method to our Grail (easy maintainable code which WORKS).

-- Warning :: i'm no PHP wiz, my code may be bloated, but it actually does what i expect from it...--

Well, since we all started webdev, we were trapped in the Evil Browser Specs, struck by headaches/fury/insomnia/nightmares. Once i got fed up with designing several pages, i took a look at this PHP thing everybody's talking about.

Yeah, PHP is a neat-FREE-powerful-FREE-adaptive-FREE-versatile Open-Source language. There are ports for nearly all operating systems, it's easy to install, and there are so many features that it's almost insane...

Just to help you to make your opinion :: total db interaction, HTML/PDF/img on-the-fly generation, SNMP, POSIX, XML, WDDX, LDAP, IMAP, FTP, encryption....

Well, how can PHP turn you into a sexy coder (that's what we all want to be, no?)?

We're gonna see the different ways to write an adaptive PHP page, which will ensure our content to be sent to the masses, whatever browser they might use.

My problems were that when a page is sent to Netscape it doesn't reacts the same than ie and can screw up my design (cell and tables background is VERY VERY bad supported by the Lizard), there were too the DOM issues, the Javascript... I ended up with putting online different pages, with just some lines being different. What i wanted was to write one page, which could tweak itself before being sent.

First step :: agent sniffing.

I decided to sniff once and then to set a session cookie. If it is set, i don't include the detection code, and vice-versa.

The detection code is based on the work of Leon Atkinson and Chris Mospaw. It parses the $HTTP_USER_AGENT string to get the browser name and version. Then it sets a variable that i'll call to send the browser the specific code.

browserdet.inc i.e. :

if(ereg( "MSIE", $HTTP_USER_AGENT))

{

$Browser_Name = "MSIE";

$Browser_Version = strtok( "MSIE");

$Browser_Version = strtok( " ");

$Browser_Version = strtok( ";");

}

...

//$cap stands for browser capatibility.

elseif($Browser_Name == "MSIE")

{

if($Browser_Version >= 4.0) { $cap = 3; }

else { $cap = 1; }

}

//cookie

setcookie("nerdsoul", $cap);

Written before any header, in top of your page, due to the cookies specs, stands the PHP script which triggers the browser detection.

<?php

//if the cookie is set

elseif($nerdsoul) { $cap = $nerdsoul;}

else { include("browsdet.inc");}

?>

Now we got a page that knows what browser the user uses.

Second step :: writing up the javascript

My javascript is in a included file which shouldn't be loaded ONLY if the browser's got $cap=1 (netscape/ie < 4). A little more complex is the fact that if users with ie/ns4+ want to see the page as old browsers get it (information inline and not layered), $cap==1, and the additional javascript eye-candy will not be loaded. So i needed to check BEFORE including my javascript that $cap!=1 AND $ovride doesn't exists.

Got the scheme? If you don't, relax, look at the source, look at my page w/ several browsers, and keep reading.

I wanted clean code to be served, so depending on which flavour hits my server, the javascript will include the correspondent coding. window.all will be served to ie, window.layers to netscape, code not implemented in ie won't be thrown in netscape's gears. EASY!

in my page ::

<?php if ($cap!=1) {include("basejs.inc");}?>

in my basejs.inc ::

print "

function previous(){

xxx=xxx-1;

if(xxx < 0){false}

";

if($cap == 2) { print "

else {

window.document.layers[xxx].visibility=\"hide\";

window.document.layers[xxx-1].visibility = \"show\";}

}

";

}

else { print "

else {

content[xxx].style.visibility=\"hidden\";

content[xxx-1].style.visibility = \"visible\";}

}

";

}

Serve what's needed. That's all.

Third step :: serving specific tag attributes.

Netscape has this stupid bug w/ layers disappearing when you resize a window. problem solved ONLY in ns4+, so ONLY in the version of my page that includes layers in netscape.

<body bgcolor="#666666" LEFTMARGIN="0" TOPMARGIN="0" MARGINWIDTH="0" MARGINHEIGHT="0"

<?php

if($cap == 2) { print " onResize=replace()"; }

?>

>

Let's say that i want a rollover effect to take place only in ie4+ ::

<a href="/portfolio/portfolio.php3"

<?php

if ($cap == 3) { print " onMouseover=\"chgcolor(0,0)\" onMouseout=\"chgcolor(0,0,1)\""; }

?>

id="linkk">

Fourth step :: TOTALLY different layouts depending on your browser's capatibility.

To clearly understand what will be developed here, point your machines toward my blog. i remind you it's still beta and that the file may (will) be huge (around 100k), lots of content.

The power of conditionalisation starts there to reach the insanity.

I rely on blogger's free services to generate my blog. When i find something interesting on the web, i highlight it, i trigger the active-X i installed, it opens a window in which i can modify the content, and it is posted to blogger's server. There it is stored in their db, the template i gave them is parsed with the data form the databases, and published on my site.

A 300 lines template -> 5000 lines webpage.

In the template file, i indicate where the entries will be rendered with their <BLOGGER> </BLOGGER> self-made tags.

What i wanted to do is that lesser browsers get the content in-line / up-to date browsers get the content layered. The html is totally different, a big table, instead of divs! No problem.

in my blogger template ::

<?php

//if lesser browser or plain design contain the entries in the main table

if ($cap == 1 || $ovride == 1) {

print "

<TABLE BORDER="\"0\"" CELLSPACING="\"1\""

CELLPADDING="\"2\"" ALIGN="\"CENTER\""

BGCOLOR="\"#333333\"" HEIGHT="\"200\""

NAME="\"STUFF\"">

<TD WIDTH="\"20%\"" BACKGROUND="\"t.gif\"">   </TD>

<TD WIDTH="\"60%\"">";

/*

if plain design called, give the ability to switch back to layered design.

Watch the $PHP_SELF variable, it's a build-in var which means 'the current URL',

very useful. By appending '?ovride=2' to it, next page will be processed with

the variable $ovride already defined and set to 2. Magic!

*/

if ($ovride == 1) {

print "

<DIV ALIGN="\"CENTER\"" BGCOLOR="\"#666666\""> <A HREF="\"$PHP_SELF?OVRIDE="2\" ""> eye-candy </A> </DIV>

";

}

print "

<DIV ALIGN="\"CENTER\"" BGCOLOR="\"#666666\""><A HREF="\"archives.php3\"">ARCHIVES</A></DIV>

<TABLE WIDTH="\"100%\"" BORDER="\"0\"" CELLPADDING="\"4\"" BGCOLOR="\"#666666\"">

";

}

?>

<BLOGGER>

<?php

//if netscape AND dhtml presentation, classic div

if ($cap == 2 && $ovride != 1) {

print "

<DIV CLASS="\"CONT\"">

<TABLE BORDER="\"1\"" BGCOLOR="\"LIME\""

CELLPADDING="\"4\"">

";

}

elseif ($cap == 3 && $ovride != 1) {

//if ie AND dhtml presentation, DIV+CSS filters

print "

<DIV ID="\"CONTENT\"" STYLE="\"POSITION:ABSOLUTE;

RIGHT:20PX; TOP:42PX; WIDTH:60%; Z-INDEX:4; VISIBILITY: HIDDEN;\">

<TABLE WIDTH="\"100%\"" BORDER="\"0\""

CELLPADDING="\"4\"" STYLE="\"BACKGROUND-COLOR:LIME;

FILTER: ALPHA( OPACITY="80," FINISHOPACITY="80," ) \">

";

}

...

?>

Take a look at my source to see where it can go. It may seem complex, but when i made that, i didn't knew anything about PHP (almost ; ) ).

Next entry :: the HTML heresy : class.layout (how to make cleaner code? don't write tags!)

The access keys for this page are: ALT (Control on a Mac) plus:

evolt.org Evolt.org is an all-volunteer resource for web developers made up of a discussion list, a browser archive, and member-submitted articles. This article is the property of its author, please do not redistribute or use elsewhere without checking with the author.