CSS styleswitcher

Op sites waar vooruitstrevend gewerkt wordt, wordt content van opmaak gescheiden door middel van CSS. Op deze manier kan, als men dit wil, een visuele updates snel doorvoeren over de gehele site. Ook kan met de site in verschillende visuele vormen aanbieden. Zo kan er een aparte stylesheet zijn voor slechtzienden, mensen speciaal van de phpvereniging of kunnen er gewoon voor de fun verschillende stylesheets aangeboden worden.

Voor mijn eigen site heb ik “gewoon voor de fun verschillende stylesheets gemaakt, een erg leuke extra feature. Wat ik in dit artikel wil beschrijven is het maken van een styleswitcher. Na het inladen van een standaard ingestelde stylesheet kan de bezoeker dmv een drop down select box de gewenste style te kiezen. Deze blijft bewaart in een cookie.

Omdat voor verschillende stylesheets verschillende files (css+plaatjes) nodig zijn
is het van belang dat we een overzichtelijke directory structuur hanteren.
Ik heb gekozen voor de volgende directory structuur op de server:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
- [dir]style
  - [dir]1
    - [dir]css
      css.php
      index.css
      archief.css
      algemeen.css
    hier alle plaatjes voor stylesheet 1
  - [dir]2
    - [dir]css
      css.php
      index.css
      archief.css
      algemeen.css
    hier alle plaatjes voor stylesheet 2
  - enz

Zoals je ziet zijn de bestandnamen hetzelfde, alleen het nummer van de directory is verschillend.

Ik ben er vanuit gegaan dat je meer dan één pagina op je website hebt en dat je per pagina dusdanige andere content hebt dat je daar een aparte stylesheet voor hebt. Voor de globale layout (kolomstructuur, uitlijning of header) hanteren we een algemeen bestand (algemeen.css) wat op alle pagina’s geldt.

Verschillende pagina’s, (deels) verschillende stylesheets dus. Ik ga even voor het gemak uit van 2 pagina’s, index.php en archief.php.
Deze delen een gezamelijke html-kop (<html><head></head><body>), opgeslagen in top.php.
Probleem: we gebruiken dezelfde <head> voor zowel archief.php als voor index.php, we moeten onderscheid maken in het aanroepen van de stylesheet (wat gebeurt in de <head>).

Hoe lossen we dit op:
In de <head> wordt standaard maar 1 stylesheet ingeladen, namelijk css.php. Aan de hand van een doorgegeven GET variabele bepalen we welke extra stylesheet we moeten includen in css.php.

In archief.php en index.php moeten we een variabele doorgeven, we gebruiken de filenaam:
archief.php en index.php

001
002
003
004
<?php
$thiscssfile=$_SERVER['PHP_SELF'];
include ('top.php');
?>

in top.php is nu de variabele $thiscssfile aanwezig en die geven we door aan css.php door middel van een GET variabele:
top.php

001
002
003
004
005
006
007
008
009
010
011
012
<body><head>
<?php
echo '<link href="style/'.$css_dir_nr.'/css/css.php';
if (isset ($thiscssfile)){
	//$thiscssfile bevat bijvoorbeeld "/subdirectory/index.php"
	$thiscssfile=str_replace('/subdirectory/','',$thiscssfile); //strip ‘/subdirectory/’
	$thiscssfile=str_replace('.php','',$thiscssfile); //strip ‘.php’
	echo '?file='.$thiscssfile;
}
echo '" rel="stylesheet" type="text/css" />';
?>
</head><body>

we roepen nu in de <head> dus aan:
<link href=”style/’.$css_dir_nr.’/css/css.php?file=index’ rel=”stylesheet” type=”text/css” />

We halen nu een php file aan als een css file, om aan de verwachtingen van de browser te voldoen, passen we de header aan in css.php

001
<?php header("Content-type: text/css"); ?>

In css.php gaan we nu aan de hand van de GET variabele de juiste stylesheet inladen:
css.php

001
002
003
004
005
006
007
008
009
010
011
012
013
014
<?php
header("Content-type: text/css");
if (isset ($_GET['file'])){
	//eerst laden we het css bestand in wat de ‘algemene’ opmaak bevat, wat geldt voor alle pagina’s
	readfile('algemeen.css');
	//hierna kijken we welke pagina’s we extra moeten inladen
	if ($_GET['file'] == 'index'){
		readfile('index.css');
	}
	if ($_GET['file'] == 'archief'){
		readfile('archief.css');
	}
}
?>

Nu hebben we dus een systeem wat bij de juiste pagina de juiste stylesheet filenaam inlaadt. We hebben echter nog niet de juiste styledirectory geselecteerd.

Mensen die net goed opgelet hebben, hebben in top.php de variabele $css_dir_nr zien staan. Deze variabele bevat, zoals de naam zegt, het directorynummer van de geselecteerde stylesheet. Maar hoe wordt deze variabele gevuld? Aan de hand van de keuze van de bezoeker natuurlijk.

Deze keuze kan op 3 niveaus doorgegeven worden:
1. mensen die via de style-kiezer net een nieuwe stylesheet geselecteerd hebben
2. mensen die eerder hebben gekozen en een cookie hebben
3. mensen die ingelogd zijn en die in hun preferences een voorkeur hebben ingesteld (variabele $aUserinfo[‘stylesheetid’])

De stylekiezer
Stylenaam “1″ en “2″ zeggen niet veel, dus in de dropdown select box willen we zinnige namen kunnen geven aan de stylesheets.
Om de namen te koppelen aan de directory nummers gebruiken we een kleine mysql tabel:

CREATE TABLE `style` (
  `styleid` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `active` tinyint(1) DEFAULT ’0′,
  PRIMARY KEY  (`styleid`)
) TYPE=MyISAM;

Om de te kiezen stylesheets in de drop down selectbox weer te geven gebruiken we de volgende functie:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
<?php
function printstylechooser($returnadress){
	global $aUserInfo;
	global $css_dir_nr;

	if (isset ($css_dir_nr)){
		$q="SELECT * FROM style WHERE active=1";
		if (!$r=mysql_query($q))
		echo 'failed to select styles'.mysql_error();
		echo '<select name="style" onchange="location.href=this.options[this.selectedIndex].value">';
		while ($a=mysql_fetch_assoc($r)){
			echo '<option ';
			if (isset ($_GET['stylesheetid'])){
				if ($_GET['stylesheetid']==$a['styleid'])
				echo ' selected="selected" ';
			}elseif (isset ($_COOKIE['stylesheetid'])){
				if ($_COOKIE['stylesheetid']==$a['styleid'])
				echo ' selected="selected" ';
			}elseif (isset ($aUserInfo)){
				if ($aUserInfo['stylesheetid']==$a['styleid'])
				echo ' selected="selected" ';
			}elseif ($a['styleid']==1)  //DEFAULT STYLESHEET IS NR 1
			echo ' selected="selected" ';
			echo 'value="'.$returnadress.'?stylesheetid='.$a['styleid'].'">'.$a['name'].'</option>';
		}
		echo '<option ';
		if ((isset ($_GET['stylesheetid']) && $_GET['stylesheetid']==0) || (isset ($_COOKIE['stylesheetid']) && $_COOKIE['stylesheetid']==0) || (isset ($aUserInfo) && $aUserInfo['stylesheetid']==0))
		echo ' selected="selected ';
		echo 'value="'.$returnadress.'?stylesheetid=0">Random</option>';
		echo '</select>';
	}
}
?>

de laatste optie is optie 0: een random stylesheet. Het is een extratje wat waarschijnlijk niet gebruikt gaat worden, maar toch leuk voor de heb.

aan deze functie kun je een aantal dingen opmerken:
- we hebben een variabele $css_dir_nr nodig om hem te laten werken
- het gekozen style_dir_nr wordt voorgeselecteerd in de select box
- na een keuze van de gebruiker wordt de gekozen stylesheet doorgegeven als nummer in de url. Dus na het klikken in de style-kiezer wordt men doorverwezen naar bijvoorbeeld index.php?stylesheetid=1.
- de variabele $returnadress wordt gebruikt om de styleswitcher op verschillende pagina’s te kunnen weergeven en de gebruiker na keuze terug te laten keren naar deze specifieke pagina.

$css_dir_nr
De variabele $css_dir_nr is de door de user gekozen stylesheet, deze moet bekend zijn voordat de pagina geladen wordt en wordt gebruikt om
- in de stylesheet selector de huidige keuze te voorselecteren (zoals we net gezien hebben)
- de juiste stylesheet te laden (duh)

Voor het bepalen van het juiste directory nummer gebruiken we de volgende functie:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
<?php
function stylesheetselector(){
	global $cssnr;
	global $aUserInfo;

	//set new stylesheet
	if (isset ($_GET['stylesheetid'])){
		if (isset ($aUserInfo)){
			$q="UPDATE account SET stylesheetid=".$_GET['stylesheetid']." WHERE account_id=".$aUserInfo['account_id'];
			if (!$r=mysql_query($q))
			die ('Failed to select stylesheet'.mysql_error().$q);
		$aUserInfo['stylesheetid']=$_GET['stylesheetid'];
		}
		setcookie('stylesheetid',$_GET['stylesheetid'],time()+60*60*24*7);
	}
	//which one should be loaded?
	if (isset ($_GET['stylesheetid']) && $_GET['stylesheetid']!=0)
	$cssnr=$_GET['stylesheetid']; //this step is needed because the cookie is set but not available until next pageload
	elseif (isset ($_COOKIE['stylesheetid']) && $_COOKIE['stylesheetid']!=0){
		$cssnr=$_COOKIE['stylesheetid'];
	}elseif (isset ($aUserInfo['stylesheetid']) && $aUserInfo['stylesheetid']!=0)
	$cssnr=$aUserInfo['stylesheetid'];
	elseif ((isset ($_GET['stylesheetid']) && $_GET['stylesheetid']==0) || (isset($_COOKIE['stylesheetid']) && $_COOKIE['stylesheetid']==0) || (isset ($aUserInfo['stylesheetid']) && $aUserInfo['stylesheetid']==0)){
		//stylesheet is set to random
		if (!$r=mysql_query("SELECT styleid FROM style WHERE active=1"))
		enot ('Failed to select stylesheet'.mysql_error(),1);
		else{
			$max=mysql_num_rows($r);
			$cssnr=rand(1,$max);
		}
	}else{
		//set stylesheet to default
		$cssnr=1;
	}
}
?>

Beide hier besproken functies slaan we op in functions.php.

Actie
Om nu de zaak in actie te zien hoeven we eigenlijk maar 2 dingen te doen:
- verschillende stylesheets maken en deze in de bovenaan genoemde directorystructuur te zetten
- de mysql tabel te updaten met de aanwezige stylesheets (en ze hier ook benamen)

files
Hoe zien de files er nu uit na afloop.

index.php & archive.php

001
002
003
004
005
006
<?php
$thiscssfile=$_SERVER['PHP_SELF'];
include ('top.php');
printstyleselector('index.php');
?>

top.php

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
<?php
include_once ('functions.php');
stylesheetselector();
?>
<head>
<?php
echo '<link href="style/'.$css_dir_nr.'/css/1.php';
if (isset ($thiscssfile)){
	$thiscssfile=str_replace('/moraalridder/','',$thiscssfile);
	$thiscssfile=str_replace('.php','',$thiscssfile);
	echo '?file='.$thiscssfile;
}
echo '" rel="stylesheet" type="text/css" />';
?>
</head>
<body>

Geef een reactie

You must be logged in to post a comment.