Table des matières
Niveau
..........
En rapport...

Quoi

Cette classe permet de creer des sondages a choix simple ou multiple. Sont point fort est l'ulisation d'ajax qui permet d'enregistrer le choix et d'afficher les resultat du sondage sans poster la page et donc sans refresh.

Code

php
<?php
/*****************************
Auteur 		:iDo (ido@woow-fr.com)
License		:CreativeCommons (http://creativecommons.org/licenses/by-nc-sa/2.0/)
Date Creation	:07/11/05
Derniere modif.	:07/11/05
*****************************/
class Poll {
	/*****************************
	Cree le sondage
	$question		= string 	-> Question
	$reponse		= array 	-> [0] réponse 1 [1] Réponse 2...
	$classes		= array 	-> ['p'] classe de barre de progression ['q'] classe de la question ['r'] classe de la liste de réponse ['b'] classe du bouton valider [0] classe de la réponse 1 [1] classe de la réponse 2...
	$Ip			= String	-> Contient l'ip du votant, laisser vide pour ne pas le géré
	$TpsEntreVote	= integer	-> Tps en seconde entre chaque autorisation de vote
	$ProgressShade	= string	-> Si il contient une couleur hexadecimale (sans le #), cette couleur sera utlisé pour géré la barre de progression (avec nuance)
	$ChoixMultiple	= boolean	-> True pour des check, False pour des radio
	$nomFichier	= string	-> Fichier de sauvegarde des resultats
	*****************************/
	function Poll($question,$reponses,$classes,$Ip='',$TpsEntreVote=10,$ProgressShade='',$ChoixMultiple=false,$nomFichier="poll.txt") {
		$this->IdQuestion	=md5($question);
		$this->nomFichier	=$nomFichier;
		$this->nbQuestion	=count($reponses);
		$this->classes		=$classes;
		$this->question		=$question;
		$this->reponses		=$reponses;
		$this->ChoixMultiple=$ChoixMultiple;
		$this->IP			=$Ip;
		$this->TpsEntreVote =$TpsEntreVote;
		$this->ProgressShade=$ProgressShade;
	}
	/*****************************
	Assombri ou eclairci une couleur
	*****************************/
	function correctshade($color, $shade) {
		$r = hexdec(substr($color,0,2));
		$g = hexdec(substr($color,2,2));
		$b = hexdec(substr($color,4,2));
		$sum = ($r + $g + $b);
		$x = (($shade * 3) - $sum) / $sum;
		if ($x >= 0) {
			$x = $x + 1;
		} else {
			$x = 1 + $x;
		}
		$r = intval($x * $r);
		$g = intval($x * $g);
		$b = intval($x * $b);
		$r = dechex($r);
		$g = dechex($g);
		$b = dechex($b);
		$r=(strlen($r)<2)?'0'.$r:$r;
		$g=(strlen($g)<2)?'0'.$g:$g;
		$b=(strlen($b)<2)?'0'.$b:$b;
		return $r.$g.$b;
	}
	/*****************************
	Donne la couleur opposé d'une couleur
	*****************************/
	function OppositeHex($color) {
		$r = dechex(255 - hexdec(substr($color,0,2)));
		$r = (strlen($r) > 1) ? $r : '0'.$r;
		$g = dechex(255 - hexdec(substr($color,2,2)));
		$g = (strlen($g) > 1) ? $g : '0'.$g;
		$b = dechex(255 - hexdec(substr($color,4,2)));
		$b = (strlen($b) > 1) ? $b : '0'.$b;
		return $r.$g.$b;
	}
	/*****************************
	Renvoie True si l'ip a déja voté, false sinon
	*****************************/
	function AdejaVoter() {
		$ret=false;
		if ($this->IP=='') return $ret;
		//cree le fichier si c la premiere fois
		$handle = fopen($this->nomFichier, "a");
		fclose ($handle);
		//lit le fichier
		$fline = file($this->nomFichier);
		//recupere ke les ip et strip le \n
		$started=false;
		$cptvotes=0;
		$cptip=0;
		$ip[0]='';
		for ($j=0;$j!=count($fline);$j++) {
			$fline[$j]=rtrim($fline[$j]);
			if ($fline[$j]=='') continue;
			//si je suis dans la récupération des ips
			if ($started==true) {
				//si c pas encore la fin de la liste des ip
				if ($fline[$j]{0} != '[') {
					$tmp=split(' ',$fline[$j]);
					if ((floatval(trim($tmp[0]))+$this->TpsEntreVote) >= date('YmdHis')) {
						//date encore valide
						if ((trim($tmp[1])==$this->IP) && (trim($tmp[2])==$this->IdQuestion)) {
							//mm ip, mm question !! tu peu pas revoté
							$ret = true;
						}//else on continu a vérifier les autre ligne
						$ip[$cptip]=$fline[$j];
						$cptip++;
					} else {
						//date delai dépassé
						$fline[$j]="";
					}
				} else {
				//si la liste est fini
					$started=false;
					$votes[$cptvotes]=$fline[$j];
					$cptvotes++;
				}
			} else {
				$votes[$cptvotes]=$fline[$j];
				$cptvotes++;
			}
			//la liste va commencer
			if ($fline[$j]=='[IP]') {
				$started=true;
			}
		}
		//Si j'arrive ici c'est que j'ai parcouru toute la liste d'ip et que celle en cours n'a pas été trouvé
		//au pasage, on va sauvegarder la liste vidé des ligne obsolete
		if (!@$votes) return $ret;
		for ($j=0;$j!=count($votes);$j++) {
			$votes[$j].="\n";
		}
		for ($j=0;$j!=count($ip);$j++) {
			$ip[$j].="\n";
		}
		//Stoket le array dans une variable string
		$votes = @implode ('', $votes);
		$ip = @implode ('', $ip);
		$votes .= $ip."\r\n";
		//Ecrit le fichier definit
		//php5 => file_put_contents ($_POST['nf'], $fline);
		$handle = fopen($this->nomFichier, "w");
		fwrite($handle, $votes);
		fclose($handle);
 
		return $ret;
	}
	/*****************************
	Affiche le sondage
	*****************************/
	function ShowPoll() {
		if ($this->AdejaVoter()==true) {
			return $this->ShowPollResult();
		}
		$this->Poll	 = '';
		$this->Poll .= sprintf($this->_GetHTML('q'),$this->IdQuestion,@$this->classes['q'],$this->question);
		$tmp		 = '';
		$tmp2		 = '';
		foreach ($this->reponses as $key => $value) {
			$tmp2	 = sprintf($this->_GetHTML('i'),(($this->ChoixMultiple)?"Checkbox":"Radio"),$this->IdQuestion.strval($key),$this->IdQuestion.strval($key),@$this->classes[$key],$this->IdQuestion.strval($key),@$this->classes[$key],$value);
			$tmp	.= sprintf($this->_GetHTML($key),@$this->classes[$key],$this->IdQuestion.strval($key),$tmp2);
		}
		$this->Poll	.= sprintf($this->_GetHTML('r'),$this->IdQuestion,@$this->classes['r'],$tmp);
		$this->Poll	.= sprintf($this->_GetHTML('b'),$this->IdQuestion,@$this->classes['b'],$this->IdQuestion,@$this->classes['p'],$this->nomFichier,$this->nbQuestion,$this->IP,$this->ProgressShade);
 
		$this->Poll	 = sprintf($this->_GetHTML('c'),'i'.$this->IdQuestion,$this->Poll);
		return $this->Poll;
	}
	/*****************************
	Affiche le résultat du sondage
	*****************************/
	function ShowPollResult() {
		//initialise le tableau des valeur
		$Q='['.$this->IdQuestion.']';
		for ($j=0;$j<$this->nbQuestion;$j++) {
			$v='R'.$j;
			$$v=0;
		}
		//cree le fichier si c la premiere fois
		$handle = fopen($this->nomFichier, "a");
		fclose ($handle);
		//Vire les \n
		$fline = file($this->nomFichier);
		for ($j=0;$j!=count($fline);$j++) {
			$fline[$j]=rtrim($fline[$j]);
		}
		$cpt=0;
		$startL=0;
		//recupere les precedente valeur
		foreach ($fline as $key => $value) {
			if ($value == $Q) {
				$cpt++;
				$startL=$cpt;
				for ($j=0;$j<$this->nbQuestion;$j++) {
					$v='R'.$j;
					$$v+=floatval($fline[$cpt+$j]);
				}
			}
			$cpt++;
		}
		$total=0;
		for ($j=0;$j<$this->nbQuestion;$j++) {
			$v='R'.$j;
			$total+=floatval($$v);
		}
 
		$this->rPoll	 = '';
		$this->rPoll .= sprintf($this->_GetHTML('q'),'R'.$this->IdQuestion,@$this->classes['q'],$this->question.' ('.$total.' vote(s))');
		$tmp		 = '';
		$tmp2		 = '';
		foreach ($this->reponses as $key => $value) {
			$v		 = 'R'.$key;
			$prc	 = @round(($$v*100)/$total);
			$v		 = $$v;
			$back=($this->ProgressShade!='')?';background:#'.$this->correctshade($this->ProgressShade,(101-$prc)):'';
			$col =($this->ProgressShade!='')?';color:#'.$this->OppositeHex($this->correctshade($this->ProgressShade,(101-$prc))):'';
			$tmp2	 = sprintf($this->_GetHTML('is'),@$this->classes[$key],$value,$prc.'%'.$back.$col,@$this->classes['p'],$prc.'%');
			$tmp	.= sprintf($this->_GetHTML($key),@$this->classes[$key],'R'.$this->IdQuestion.strval($key),$tmp2);
		}
		$this->rPoll	.= sprintf($this->_GetHTML('r'),'R'.$this->IdQuestion,@$this->classes['r'],$tmp);
 
		$this->rPoll	 = sprintf($this->_GetHTML('c'),'i'.'R'.$this->IdQuestion,$this->rPoll);
		return $this->rPoll;
	}
	/*****************************
	Implemente les javascripts obligatoire
	/!\ Attention, a n'appeller qu'une fois par page
	*****************************/
	function AjaxPoll() {
		return "<script type=\"text/javascript\">\n
				function correctshade(color, shade) {\n
					r = hexToDec(color.substring(0,2));\n
					g = hexToDec(color.substring(2,4));\n
					b = hexToDec(color.substring(4,6));\n
					sum = (r + g + b);\n
					x = ((shade * 3) - sum) / sum;\n
					if (x >= 0) {\n
						x = x + 1;\n
					} else {\n
						x = 1 + x;\n
					}\n
					r = (x * r);\n
					g = (x * g);\n
					b = (x * b);\n
					r = decToHex(r);\n
					g = decToHex(g);\n
					b = decToHex(b);\n
					r=(r.length<2)?'0'+r:r;\n
					g=(g.length<2)?'0'+g:g;\n
					b=(b.length<2)?'0'+b:b;\n
					return r+g+b;\n
				}\n
				function OppositeHex(color) {\n
					r = decToHex(255 - hexToDec(color.substring(0,2)));\n
					r = (r.length > 1) ? r : '0'+r;\n
					g = decToHex(255 - hexToDec(color.substring(2,4)));\n
					g = (g.length > 1) ? g : '0'+g;\n
					b = decToHex(255 - hexToDec(color.substring(4,6)));\n
					b = (b.length > 1) ? b : '0'+b;\n
					return r+g+b;\n
				}\n
				function decToHex(dec) {\n
					var hexa=\"0123456789ABCDEF\";\n
					var hex=\"\";\n
					while (dec>15) {\n
						tmp=dec-(Math.floor(dec/16))*16;\n
						hex=hexa.charAt(tmp)+hex;\n
						dec=Math.floor(dec/16);\n
					}\n
					hex=hexa.charAt(dec)+hex;\n
					return(hex);\n
				}\n
				function hexToDec(hex) {\n
					return parseInt(hex,16);\n
				} \n
				function SendPollAjax(page,retfonc,methode,data) { \n
				var xhr_object = null; \n
				if(window.XMLHttpRequest) // Firefox \n
				   xhr_object = new XMLHttpRequest(); \n
				else if(window.ActiveXObject) // Internet Explorer \n
				   xhr_object = new ActiveXObject(\"Microsoft.XMLHTTP\"); \n
				else { // XMLHttpRequest non supporté par le navigateur \n
				   alert(\"Votre navigateur ne supporte pas les objets XMLHTTPRequest...\"); \n
				   return; \n
				} \n
				if (data=='') \n
					data=null; \n
				if(methode == \"GET\" && data != null) { \n
				   page += \"?\"+data; \n
				   data = null;  \n
				} \n
				xhr_object.open(methode, page, true); \n
				xhr_object.onreadystatechange = function() { \n
					if(xhr_object.readyState == 4) \n
						eval(retfonc+'(\''+xhr_object.responseText+'\');'); \n
				} \n
				if(methode == \"POST\") \n
				   xhr_object.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded\"); \n
				xhr_object.send(data); \n
				} \n
				function SendPoll(mdid,p,n,b,i,c) { \n
					var x = document.forms['P'+mdid].elements; \n
					var data = 'p='+p+'&mdid='+mdid+'&nf='+n+'&nbq='+b+'&ip='+i+'&c='+c; \n
					for (var i = 0; i < x.length; i++) { \n
						if (x[i].checked==true) \n
							data += '&'+x[i].id+'='+x[i].value; \n
						\n
					} \n
					SendPollAjax('".basename(__FILE__)."','GetPollResult','POST',data); \n
				}
				function GetPollResult(r) { \n
					var d=r.split(';'); \n
					var id=d[0]; \n
					var classe=d[1]; \n
					var total=d[2]; \n
					var col=d[3]; \n
 
					var cpt=0; \n
					document.getElementById('Q'+id).innerHTML+=' ('+total+' vote(s))'; \n
					for(i=4;i<d.length-1;i++) { \n
						var prc=Math.round((d[i]*100)/total); \n
						var back=(col!='')?';background:#'+correctshade(col,101-prc):'';
						var fon =(col!='')?';color:#'+OppositeHex(correctshade(col,101-prc)):'';
						document.getElementById('R'+id+cpt).style.display='none'; \n
 
						document.getElementById('L'+id+cpt).innerHTML+='<div style=\"width:100%\"><div style=\"width:'+prc+'%'+back+fon+'\" class=\"'+classe+'\">'+prc+'%</div></div>'; \n
						cpt++; \n
					} \n
					document.getElementById('B'+id).style.display='none'; \n
				} \n
				</script>\n";
	}
	/*****************************
	fonction interne qui regroupe les différentes balise html utlisée
	*****************************/
	function _GetHTML($w) {
		$Cr="\n";
		if (is_numeric($w)) return '<li class="%s" id="L%s">%s</li>'.$Cr;
		if ($w=='q') return '<div id="Q%s" class="%s">%s</div>'.$Cr;
		if ($w=='c') return '<div id="%s">%s</div>'.$Cr;
		if ($w=='r') return '<form name="P%s" action="?" method="POST"><ul class="%s">%s</ul></form>'.$Cr;
		if ($w=='is') return'<label class="%s">%s</label><div style="width:100%%"><div style="width:%s" class="%s">%s</div></div>'.$Cr;
		if ($w=='i') return '<input type="%s" name="Reponse" id="R%s" value="R%s" class="%s" /><label for="R%s" class="%s">%s</label>'.$Cr;
		if ($w=='b') return '<input type="button" id="B%s" value="Ok" class="%s" OnClick="SendPoll(\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\');" />';
	}
}
/*****************************
Gestion de la sauvegarde des resultat dans le fichier 
*****************************/
if (@$_GET['mdid']) {
	$_POST=$_GET;
}
if (@$_POST['mdid']) {
	//initialise le tableau des valeur
	$Q='['.$_POST['mdid'].']';
	for ($j=0;$j<$_POST['nbq'];$j++) {
		$v='R'.$j;
		$$v=0;
	}
	//cree le fichier si c la premiere fois
	$handle = fopen($_POST['nf'], "a");
	fclose ($handle);
	//Vire les \n
	$fline = file($_POST['nf']);
	for ($j=0;$j!=count($fline);$j++) {
		$fline[$j]=rtrim($fline[$j]);
	}
	$cpt=0;
	$startL=0;
	//recupere les precedente valeur
	foreach ($fline as $key => $value) {
		if ($value == $Q) {
			$cpt++;
			$startL=$cpt;
			for ($j=0;$j<$_POST['nbq'];$j++) {
				$v='R'.$j;
				$$v+=floatval($fline[$cpt+$j]);
			}
		}
		$cpt++;
	}
	//Ajoute les nouvelle valeur
	foreach ($_POST as $key => $value) {
		if ($key == 'mdid') continue;
		if ($key == 'nf') continue;
		if ($key == 'nbq') continue;
		if ($key == 'p') continue;
		if ($key == 'c') continue;
		if ($key == 'ip') continue;
		$value=str_replace($_POST['mdid'],'',$value);
		eval('$'.$value.'++;');
	}
	//replace les valeur dans le tableau
	if ($startL == 0) {
		$startL=$cpt;
		$fline[$startL]=$Q;
		$startL++;
	}
	for ($j=0;$j<$_POST['nbq'];$j++) {
		$v='R'.$j;
		$fline[$startL]=$$v;
		$startL++;
	}
	//Rajoute les \n
	for ($j=0;$j!=count($fline);$j++) {
		$fline[$j].="\n";
	}
	//Stoket le array dans une variable string
	$fline = implode ('', $fline);
	//Ecrit le fichier definit
	//php5 => file_put_contents ($_POST['nf'], $fline);
	$handle = fopen($_POST['nf'], "w");
	fwrite($handle, $fline);
	fclose($handle);
	//Genere et affiche la chaine de retour
	$tmp='';
	$total=0;
	for ($j=0;$j<$_POST['nbq'];$j++) {
		$v='R'.$j;
		$tmp .= $$v.';';
		$total+=floatval($$v);
	}
	if (@$_POST['ip']!='') {
	//Rajoute l'ip du voteur (format => Date(YmdHis) IP $md5question
	$insert_key = '[IP]';
	$string='';
  	$old_data = file($_POST['nf']);
 	$new_data = date('YmdHis').' '.$_POST['ip'].' '.$_POST['mdid'];
	$trouve=false;
 
 	for($x=0;$x<count($old_data);$x++) {
 	    if(rtrim($old_data[$x]) != $insert_key) {
 	        $string .= $old_data[$x];
  	    }else{
  	        $string .= $insert_key."\r\n".$new_data."\r\n";
			$trouve=true;
  	    }
  	}
	if ($trouve==false) {
		$string .= "\r\n".$insert_key."\r\n".$new_data."\r\n";
	}
 
 
  	// write $string to file
	$handle = fopen($_POST['nf'], "w");
	fwrite($handle, $string);
	fclose($handle);
	}
	//Affiche le retour
	echo $_POST['mdid'].';'.$_POST['p'].';'.$total.';'.$_POST['c'].';'.$tmp;
	exit;
}
?>
Les parametre pour l'instanciation de la classe sont décrit en haut du code.

Les fonctions

Poll : instancie la classe et crée le sondage, sans l'afficher
ShowPoll : Affiche le sondage
ShowPollResult : Affiche le résultat du sondage sans poser la question.
AjaxPoll : Ajoute a la page les javascripts indispensable au post du sondage
AdejaVoter : Renvoie True si l'ip passé à Poll() à déja voté, false sinon.

Pour l'essayer

Vous pouvez utliser ce bout de code pour essayer la classe :

php
<style type="text/css">
.progress {
	background:#654;
	font-size :10px;
	text-align:center
}
.rep {
	background:#789;
	font-size :12px
}
.quest {
	background:#987;
	font-weight:bold;
	text-align: center;
	font-size :14px
}
.btn {
	border:1px solid #000;
	background:#789
}
.r {
	list-style-type:none
}
</style>
<?php
$r[0]="oui";
$r[1]="non";
$r[2]="c pas";
$c['r']="rep";
$c['p']="progress";
$c['q']="quest";
$c['b']="btn";
$c[0]="r";
$c[1]="r";
$c[2]="r";
$a= new Poll("sa va ?",$r,$c,'',3600,'112233',false);
echo $a->AjaxPoll();
echo $a->ShowPoll();
echo $a->ShowPollResult();
$b= new Poll("sa va bien?",$r,$c,'',3600,'',true);
echo $b->ShowPoll();
?>
Même si votre page comporte plusieurs sondage, la fonction AjaxPoll() ne doit pas être appellée plus d'ue fois.