IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez / Téléchargez Sources et Outils PHP Discussion :

ProgressBar pour scripts personnels [Sources]


Sujet :

Contribuez / Téléchargez Sources et Outils PHP

  1. #1
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut ProgressBar pour scripts personnels
    Pour ceux qui font des gros scripts PHP pour leur faciliter la vie (du genre qui commencent par "set_time_limit(0);" ^^) j'ai fait une petite classe pour afficher une ou plusieurs barres de progression lors des grosses boucles FOR du script.

    Ce script ne devrait PAS se retrouver en production, il est assez "crade" au niveau du code HTML final produit, mais sinon, dans pas mal de cas, il peux être utile je pense.

    Regardez les commentaires ou directement la methode statique "test" pour savoir comment utiliser le script

    Basiquement, pour le tester il suffit de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <?php
    include_once('Percent.class.php');
    Percent::test();
    ?>
    Percent.class.php :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    <?php
    /**
    *****************************************************************
    * Merci de laisser les indications de copyright dans le code ;o)
    *****************************************************************
    *
    * Percent.class.php
    * @author Fladnag
    * @date 06/11/2008 15:32
    * @version 1.0
    * @description Fournit une ou plusieurs barres de progression pour un script PHP long.
    *
    * Utilisation :
    * Percent::start($pID, $pNbElement, $pTitle, $pFormat = self::FORMAT_PERCENT, $pMinimumStep=0.01);
    * for(...) {
    *	// traitement
    *	Percent::run($pID);
    * }
    *
    * En cas d'interruption prématurée de la boucle, on DOIT forcer la barre a se terminer avec :
    * Percent::stop($pID);
    *
    * == Quand utiliser cette classe ? ==
    *	Pour des scripts personnels travaillant sur des gros fichiers, de gros traitements, ou encore 
    *	des chargements multiples de pages distantes (cURL ou autre)
    *
    * == Quand NE PAS utiliser cette class ? ==
    *	- dans un contexte de PRODUCTION, ou alors uniquement dans une partie administration.
    *		En effet, les barres de progressions peuvent augmenter considérablement la taille finale de la page HTML.
    *		Ni le client si le serveur n'apprecient.
    *	- dans le cas ou l'affichage est bufferisé (Zend ou autre).
    *		Le script FORCE l'affichage en vidant les buffers.
    */
    class Percent {
    	// Uniquement pour eviter les collisions de noms au sein de la page HTML
    	const UNIQUE_NAME='Fladnag_Percent';
     
    	// La largeur de la barre de progression
    	const PERCENT_BAR_WIDTH=400;
    	// Le décalage d'affichage d'une barre de progression si une barre existe déjà
    	const OFFSET_TOP=50;
    	const OFFSET_LEFT=10;
    	// La hauteur de la barre bleue de progression
    	const PERCENT_BAR_HEIGHT=10;
     
    	// Les deux format d'affichage possibles :
    	const FORMAT_PERCENT=1; // affiche un pourcentage : xx,xx% (par exemple 33,33%)
    	const FORMAT_NUMERIC=2; // affiche les chiffres exacts : x/X (par exemple 3/10)
     
    	// Les noms courts utilisés pour enregistrer les elements dans l'objet javascript "document"
    	const LOAD_CONTAINER='L';
    	const LOAD_TEXT='LT';
    	const PERCENT_TEXT='PT';
    	const PERCENT_BAR='PB';
     
    	// la liste des barres crées
    	static $mpListeInstance = array();
     
    	// le nombre d'instances crées
    	static $mpNbInstances=0;
    	// le nombre de barre visibles
    	static $mpNbVisibles=0;
     
    	// numero d'une barre
    	var $mpId;
    	// nombre maximum d'iterations
    	var $mpMaxElement;
    	// avancement de la barre par rapport au nombre maximum d'iterations
    	var $mpIndice;
    	// booleen, indique si la barre est affichée ou pas
    	var $mpDisplayed;
    	// indique le format d'affichage
    	var $mpFormat;
    	// indique le nombre d'iterations a l'interieur d'un "pas" affichable
    	var $mpStep;
    	// indique le nombre d'iterations a atteindre pour faire progresser la barre
    	var $mpMinimumStep;
     
    	/** Methodes statiques publiques **/
     
    	/**
    	* @description		Crée, initialise et affiche une barre de progression
    	* @param $pID			Un identifiant numerique ou chaine de caractere qui represente la barre
    	* @param $pNbElement	Le nombre maximum d'iterations. C'est a dire le nombre de fois ou l'on va appeler
    	*						la fonction Pourcent::run($pID) pour arriver a 100%
    	* @param $pTitle		Facultatif, le titre de la barre de progression.
    	* @param $pFormat		Facultatif, le format d'affichage, soit en pourcentage (self::FORMAT_PERCENT), soit 
    	*						en numérique (self::FORMAT_NUMERIC) avec les valeurs exactes
    	* @param $pMinimumStep	Facultatif, le pourcentage minimal de mise a jour de la barre de progression.
    	*						Un taux inferieur a 0.01% (par defaut) est inutile car l'affichage de la barre se fait
    	*						sur 2 chiffres. Si on spécifie 1 (pour 1%) ici, la barre ne se mettra a jour que tout
    	*						les 1% d'itérations (ie : elle ne se mettra a jour que 100 fois dans la boucle)
    	*/
    	static public function start($pID, $pNbElement, $pTitle=NULL, $pFormat = self::FORMAT_PERCENT, $pMinimumStep=0.01) {
    		self::$mpListeInstance[$pID]=new Percent($pNbElement, $pTitle, $pFormat, $pMinimumStep);
    	}
     
    	/**
    	* @description		Cache prématurement une barre de progression. Cette fonction ne doit normalement pas être
    	*					appelée a moins qu'on interrompe la boucle principale. Elle peut toutefois être appelée
    	*					"par précaution" après la fin de la boucle, mais c'est en principe inutile.
    	* @param $pID			L'identifiant de la barre utilisé pour appeler la fonction Percent::start()
    	*/
    	static public function stop($pID) {
    		self::$mpListeInstance[$pID]->stopPercent();
    	}
     
    	/**
    	* @description		Met a jour la barre de progression. Doit etre appelé dans la boucle souhaitée
    	* @param $pID			L'identifiant de la barre utilisé pour appeler la fonction Percent::start()
    	*/
    	static public function run($pID) {
    		self::$mpListeInstance[$pID]->runPercent();
    	}
     
    	/**
    	* @description		Une methode simple qui montre comment utiliser la classe Percent
    	*/
    	static public function test() {
    		set_time_limit(0);
    		Percent::start('BOUCLE 1', 5, 'Titre Boucle 1 : 5 elements');
    		for($i=1; $i<=5; $i++) {
    			usleep(300000); // 300ms
     
    			Percent::start('BOUCLE 2', 10, 'Titre Boucle 2 : 10 elements');
    			for($j=1; $j<=10; $j++) {
    				usleep(300000); // 300ms
     
    				Percent::run('BOUCLE 2');
    			}
     
    			Percent::start('BOUCLE 3', 3, 'Titre Boucle 3 : 3 elements', Percent::FORMAT_NUMERIC);
    			for($j=1; $j<=3; $j++) {
    				usleep(100000); // 100ms
     
    				Percent::start('BOUCLE 4', 1000, 'Titre Boucle 4 : 10000 elements');
    				for($k=1; $k<=1000; $k++) {
    					usleep(200);
    					Percent::run('BOUCLE 4');
     
    					if (($j==2) && ($k==500)) {
    						echo 'Interruption Boucle 4 !<br>';
    						Percent::stop('BOUCLE 4');
    						break;
    					}
    				}
    				Percent::run('BOUCLE 3');
    			}
    			Percent::run('BOUCLE 1');
    		}
    	}
     
    	/** Methodes statiques PRIVEES **/
     
    	// renvoi le style commun aux elements HTML des barres de progression
    	private static function getCommonStyle() {
    		return 'text-align:center;color:white;padding:0px;border:0px;margin:0px;';
    	}
     
    	// renvoi le style du conteneur principal d'une barre (contenant le Titre de la barre)
    	private static function getContainerStyle() {
    		return self::getCommonStyle().'display:none;position:absolute;top:0px;left:0px;border:1px;background-color:black;border-style:solid;border-color:red;';
    	}
     
    	// renvoi le style de la zone de texte (contenant le pourcentage en format texte)
    	private static function getPercentTextStyle() {
    		return self::getCommonStyle().'background-color:red;font-weight:bold;width:'.self::PERCENT_BAR_WIDTH.'px;';
    	}
     
    	// renvoi le style de la barre de pourcentage
    	private static function getPercentBarStyle() {
    		return self::getCommonStyle().'background-color:blue;width:0px;height:'.self::PERCENT_BAR_HEIGHT.'px;';
    	}
     
    	// renvoi le style de la zone de copyright
    	private static function getCopyrightBarStyle() {
    		return self::getCommonStyle().'position:absolute;bottom:'.self::PERCENT_BAR_HEIGHT.'px;right:0px;font-size:8pt;color:white;';
    	}
     
    	/** Methodes PRIVEES non statiques **/
     
    	// renvoi un identifiant unique pour l'element passé en parametre
    	private function getId($pElementName) {
    		return self::UNIQUE_NAME.'_'.$pElementName.$this->mpId;
    	}
     
    	// renvoi le nom javascript de l'accesseur rapide de l'element stocké dans "document"
    	private function getLocalObjectName($pElementName) {
    		return 'document.'.self::UNIQUE_NAME.'[\''.$pElementName.$this->mpId.'\']';
    	}
     
    	// renvoi le texte a afficher dans la barre de pourcentage en fonction du format choisi
    	private function getFormatedText() {
    		switch($this->mpFormat) {
    			case self::FORMAT_PERCENT :
    				return round($this->mpIndice*100/$this->mpMaxElement, 2).'%';
    			break;
    			case self::FORMAT_NUMERIC :
    				return $this->mpIndice.'/'.$this->mpMaxElement;
    			break;
    		}
    	}
     
    	// constructeur PRIVE ! On doit utiliser Percent::start() pour l'appeler
    	private function __construct($pNbElement, $pTitle, $pFormat, $pMinimumStep) {
    		$this->mpId = self::$mpNbInstances++;
     
    		$this->mpMinimumStep = $pNbElement*$pMinimumStep/100;
    		$this->mpFormat=$pFormat;
    		$this->mpIndice=0;
    		$this->mpStep=0;
    		$this->mpMaxElement=$pNbElement;
    		$this->mpDisplayed=FALSE;
    		if (!isset($pTitle) || empty($pTitle)) {
    			$pTitle='Loading';
    		}
    		$pTitle=htmlentities($pTitle).'...';
     
    		echo '<div id="'.$this->getId(self::LOAD_CONTAINER).'" style="'.self::getContainerStyle().'">';
    		echo '<div id="'.$this->getId(self::LOAD_TEXT).'"></div>';
    		echo '<div id="'.$this->getId(self::PERCENT_TEXT).'" style="'.self::getPercentTextStyle().'">'.$this->getFormatedText().'</div>';
    		echo '<div id="'.$this->getId(self::PERCENT_BAR).'" style="'.self::getPercentBarStyle().'"></div>';
    		if (($this->mpId % 42)===0) {
    			echo '<div style="'.self::getCopyrightBarStyle().'">&copy; 2008 Fladnag</div>';
    		}
    		echo '</div>';
    		echo '<script>'
    		.'if (document.'.self::UNIQUE_NAME.' == undefined) {'
    		.'	document.'.self::UNIQUE_NAME.'=[];'
    		.'}'
    		.$this->getLocalObjectName(self::LOAD_CONTAINER).'=document.getElementById("'.$this->getId(self::LOAD_CONTAINER).'");'
    		.$this->getLocalObjectName(self::LOAD_TEXT).'=document.getElementById("'.$this->getId(self::LOAD_TEXT).'");'
    		.$this->getLocalObjectName(self::PERCENT_TEXT).'=document.getElementById("'.$this->getId(self::PERCENT_TEXT).'");'
    		.$this->getLocalObjectName(self::PERCENT_BAR).'=document.getElementById("'.$this->getId(self::PERCENT_BAR).'");'
     
    		.'var aDiv='.$this->getLocalObjectName(self::LOAD_CONTAINER).';'
    		.'aDiv.style.display="block";'
    		.'aDiv.style.left=(document.body.clientWidth-aDiv.clientWidth)/2+'.(self::$mpNbVisibles*self::OFFSET_LEFT).';'
    		.'aDiv.style.top=(document.body.clientHeight-aDiv.clientHeight)/3+'.(self::$mpNbVisibles*self::OFFSET_TOP).';'
    		.$this->getLocalObjectName(self::LOAD_TEXT).'.innerHTML="'.$pTitle.'";'
    		.'</script>';
     
    		$this->mpDisplayed = TRUE;
    		self::$mpNbVisibles++;
     
    		flush(); ob_flush();
    	}
     
    	// cache la barre de progression. On doit utiliser Percent::stop pour cela
    	private function stopPercent() {
    		$this->mpIndice = max($this->mpIndice-1, 0);
    		$this->runPercent(TRUE);
    	}
     
    	// met a jour la barre de progression. On doit utiliser Percent::run pour cela
    	function runPercent($pForceEnding = FALSE) {
    		if ($this->mpMaxElement < 2) {
    			return;
    		}
     
    		$this->mpIndice++;
    		$this->mpStep++;
     
    		if (!$this->mpDisplayed) {
    			echo '<script>'
    			.$this->getLocalObjectName(self::LOAD_CONTAINER).'.style.display="block";'
    			.'</script>';
    			$this->mpDisplayed = TRUE;
    			self::$mpNbVisibles++;
    		}
     
    		if (($this->mpIndice >= $this->mpMaxElement) || $pForceEnding) {
    			echo '<script>'
    			.$this->getLocalObjectName(self::LOAD_CONTAINER).'.style.display="none";'
    			.'</script>';
    			$this->mpDisplayed = FALSE;
    			self::$mpNbVisibles--;
     
    		} elseif ($this->mpStep > $this->mpMinimumStep) {
    			echo '<script>'
    			.$this->getLocalObjectName(self::PERCENT_TEXT).'.innerHTML="'.$this->getFormatedText().'";'
    			.$this->getLocalObjectName(self::PERCENT_BAR).'.style.width="'.round($this->mpIndice*self::PERCENT_BAR_WIDTH/$this->mpMaxElement).'px";'
    			.'</script>';
     
    			$this->mpStep = 0;
    		}
    		flush(); ob_flush();
    	}
    }
    ?>

  2. #2
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    Comme d'habitude, j'ai livré un peu trop tot ^^

    Voici la derniere version :

    ChangeList :
    1.0 => 1.1
    - Superposition du texte de la barre et de la barre de progression : moins de place utilisée sur la page
    - Passage en constantes des couleurs
    - Ajout de vérifications en cas de mauvaise utilisation (ID de la barre inconnue, NbElement <= 0)
    - Correction d'un bug avec une barre d'un seul element
    - Compatibilité avec IE 6.0.x
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    <?php
    /**
    *****************************************************************
    * Merci de laisser les indications de copyright dans le code ;o)
    *****************************************************************
    *
    * Percent.class.php
    * @author Fladnag
    * @email fladnag / zerezo.com
    * @date 09/11/2008 15:24
    * @version 1.1
    * @description Fournit une ou plusieurs barres de progression pour un script PHP.
    *
    * Utilisation :
    * include_once('Percent.class.php');
    * Percent::start($pID, $pNbElement, $pTitle, $pFormat = self::FORMAT_PERCENT, $pMinimumStep=0.01);
    * for(...) {
    *	// traitement
    *	Percent::run($pID);
    * }
    *
    * En cas d'interruption prématurée de la boucle, on DOIT forcer la barre a se terminer avec :
    * Percent::stop($pID);
    *
    * == Quand utiliser cette classe ? ==
    *	Pour des scripts personnels travaillant sur des gros fichiers, de gros traitements, ou encore 
    *	des chargements multiples de pages distantes (cURL ou autre)
    *
    * == Quand NE PAS utiliser cette class ? ==
    *	- dans un contexte de PRODUCTION, ou alors uniquement dans une partie administration.
    *		En effet, les barres de progressions peuvent augmenter considérablement la taille finale de la page HTML.
    *		Ni le client si le serveur n'apprecient.
    *	- dans le cas ou l'affichage est bufferisé (Zend ou autre).
    *		Le script FORCE l'affichage en vidant les buffers.
    *
    * == ChangeList ==
    * 1.1
    *	- Superposition du texte de la barre et de la barre de progression : moins de place utilisée sur la page
    *	- Passage en constantes des couleurs
    *	- Ajout de vérifications en cas de mauvaise utilisation (ID de la barre inconnue, NbElement <= 0)
    *	- Correction d'un bug avec une barre d'un seul element
    *	- Compatibilité avec IE 6.0.x
    * 1.0
    *	- Compatible avec FF 3.0.3
    */
    class Percent {
    	// Uniquement pour eviter les collisions de noms au sein de la page HTML
    	const UNIQUE_NAME='Fladnag_Percent';
     
    	// La largeur de la barre de progression
    	const PERCENT_BAR_WIDTH=400;
    	// Le décalage d'affichage d'une barre de progression si une barre existe déjà
    	const OFFSET_TOP=40;
    	const OFFSET_LEFT=10;
    	// Couleurs
    	const BACKGROUND_COLOR='black';
    	const TEXT_COLOR='white';
    	const BORDER_COLOR='darkblue';
    	const BAR_COLOR='blue';
     
    	// Les deux format d'affichage possibles :
    	const FORMAT_PERCENT=1; // affiche un pourcentage : xx,xx% (par exemple 33,33%)
    	const FORMAT_NUMERIC=2; // affiche les chiffres exacts : x/X (par exemple 3/10)
     
    	// Les noms courts utilisés pour enregistrer les elements dans l'objet javascript "document"
    	const LOAD_CONTAINER='L';
    	const LOAD_TEXT='LT';
    	const PERCENT_TEXT='PT';
    	const PERCENT_BAR='PB';
     
    	// la liste des barres crées
    	static $mpListeInstance = array();
     
    	// le nombre d'instances crées
    	static $mpNbInstances=0;
    	// le nombre de barre visibles
    	static $mpNbVisibles=0;
     
    	// numero d'une barre
    	var $mpId;
    	// nombre maximum d'iterations
    	var $mpMaxElement;
    	// avancement de la barre par rapport au nombre maximum d'iterations
    	var $mpIndice;
    	// booleen, indique si la barre est affichée ou pas
    	var $mpDisplayed;
    	// indique le format d'affichage
    	var $mpFormat;
    	// indique le nombre d'iterations a l'interieur d'un "pas" affichable
    	var $mpStep;
    	// indique le nombre d'iterations a atteindre pour faire progresser la barre
    	var $mpMinimumStep;
     
    	/** Methodes statiques publiques **/
     
    	/**
    	* @description		Crée, initialise et affiche une barre de progression
    	* @param $pID			Un identifiant numerique ou chaine de caractere qui represente la barre
    	* @param $pNbElement	Le nombre maximum d'iterations. C'est a dire le nombre de fois ou l'on va appeler
    	*						la fonction Pourcent::run($pID) pour arriver a 100%
    	* @param $pTitle		Facultatif, le titre de la barre de progression.
    	* @param $pFormat		Facultatif, le format d'affichage, soit en pourcentage (self::FORMAT_PERCENT), soit 
    	*						en numérique (self::FORMAT_NUMERIC) avec les valeurs exactes
    	* @param $pMinimumStep	Facultatif, le pourcentage minimal de mise a jour de la barre de progression.
    	*						Un taux inferieur a 0.01% (par defaut) est inutile car l'affichage de la barre se fait
    	*						sur 2 chiffres. Si on spécifie 1 (pour 1%) ici, la barre ne se mettra a jour que tout
    	*						les 1% d'itérations (ie : elle ne se mettra a jour que 100 fois dans la boucle)
    	*/
    	static public function start($pID, $pNbElement, $pTitle=NULL, $pFormat = self::FORMAT_PERCENT, $pMinimumStep=0.01) {
    		if ($pNbElement <=0) {
    			die('Le nombre d\'elements de la barre ['.$pID.'] doit etre superieur a 0');
    		}
     
    		self::$mpListeInstance[$pID]=new Percent($pNbElement, $pTitle, $pFormat, $pMinimumStep);
    	}
     
    	/**
    	* @description		Cache prématurement une barre de progression. Cette fonction ne doit normalement pas être
    	*					appelée a moins qu'on interrompe la boucle principale. Elle peut toutefois être appelée
    	*					"par précaution" après la fin de la boucle, mais c'est en principe inutile.
    	* @param $pID			L'identifiant de la barre utilisé pour appeler la fonction Percent::start()
    	*/
    	static public function stop($pID) {
    		self::checkID($pID);
    		self::$mpListeInstance[$pID]->stopPercent();
    	}
     
    	/**
    	* @description		Met a jour la barre de progression. Doit etre appelé dans la boucle souhaitée
    	* @param $pID			L'identifiant de la barre utilisé pour appeler la fonction Percent::start()
    	*/
    	static public function run($pID) {
    		self::checkID($pID);
    		self::$mpListeInstance[$pID]->runPercent();
    	}
     
    	/**
    	* @description		Arrete le script si l'ID passé en parametre n'existe pas
    	* @param $pID			Un identifiant de barre de progression
    	*/
    	static public function checkID($pID) {
    		if (!isset(self::$mpListeInstance[$pID])) {
    			die('Barre de progression ['.$pID.'] inconnue');
    		}
    	}
     
    	/**
    	* @description		Une methode simple qui montre comment utiliser la classe Percent
    	*/
    	static public function test() {
    		set_time_limit(0);
     
    		Percent::start('BOUCLE 1', 5, 'Titre Boucle 1 : 5 elements');
    		for($i=1; $i<=5; $i++) {
    			usleep(300000); // 300ms
     
    			Percent::start('BOUCLE 2', 10, 'Titre Boucle 2 : 10 elements');
    			for($j=1; $j<=10; $j++) {
    				usleep(300000); // 300ms
     
    				Percent::run('BOUCLE 2');
    			}
     
    			Percent::start('BOUCLE 3', 3, 'Titre Boucle 3 : 3 elements', Percent::FORMAT_NUMERIC);
    			for($j=1; $j<=3; $j++) {
    				usleep(100000); // 100ms
     
    				Percent::start('BOUCLE 4', 1000, 'Titre Boucle 4 : 10000 elements', Percent::FORMAT_NUMERIC, 5);
    				for($k=1; $k<=1000; $k++) {
    					usleep(200);
    					Percent::run('BOUCLE 4');
     
    					if (($j==2) && ($k==500)) {
    						echo 'Interruption Boucle 4 !<br>';
    						Percent::stop('BOUCLE 4');
    						break;
    					}
    				}
    				Percent::run('BOUCLE 3');
    			}
    			Percent::run('BOUCLE 1');
    		}
    	}
     
    	/** Methodes statiques PRIVEES **/
     
    	// renvoi le style du conteneur principal d'une barre (contenant le Titre de la barre)
    	private static function getContainerStyle() {
    		return	'padding:0px;margin:0px;position:absolute;top:0px;left:0px;border:2px;border-style:solid;'
    				.'color:'.self::TEXT_COLOR.';'
    				.'background-color:'.self::BACKGROUND_COLOR.';'
    				.'border-color:'.self::BORDER_COLOR.';'
    				.'width:'.self::PERCENT_BAR_WIDTH.'px;';
    	}
     
    	private static function getTitleStyle() {
    		return 'text-align:center;';
    	}
     
    	// renvoi le style de la zone de texte (contenant le pourcentage en format texte)
    	private static function getPercentTextStyle() {
    		return 'position:absolute;bottom:0px;right:'.(self::PERCENT_BAR_WIDTH/2).'px;';
     
    	}
     
    	// renvoi le style de la barre de pourcentage
    	private static function getPercentBarStyle() {
    		return 'background-color:'.self::BAR_COLOR.';width:0px;';
    	}
     
    	// renvoi le style de la zone de copyright
    	private static function getCopyrightBarStyle() {
    		return 'position:absolute;bottom:0px;right:0px;font-size:x-small;';
    	}
     
    	/** Methodes PRIVEES non statiques **/
     
     
     
    	// renvoi un identifiant unique pour l'element passé en parametre
    	private function getId($pElementName) {
    		return self::UNIQUE_NAME.'_'.$pElementName.$this->mpId;
    	}
     
    	// renvoi le nom javascript de l'accesseur rapide de l'element stocké dans "document"
    	private function getJSObjectName($pElementName) {
    		return 'document.'.self::UNIQUE_NAME.'[\''.$pElementName.$this->mpId.'\']';
    	}
     
    	// renvoi le texte a afficher dans la barre de pourcentage en fonction du format choisi
    	private function getFormatedText() {
    		switch($this->mpFormat) {
    			case self::FORMAT_PERCENT :
    				return round($this->mpIndice*100/$this->mpMaxElement, 2).'%';
    			break;
    			case self::FORMAT_NUMERIC :
    				return $this->mpIndice.'/'.$this->mpMaxElement;
    			break;
    		}
    	}
     
    	// constructeur PRIVE ! On doit utiliser Percent::start() pour l'appeler
    	private function __construct($pNbElement, $pTitle, $pFormat, $pMinimumStep) {
    		$this->mpId = self::$mpNbInstances++;
     
    		$this->mpMinimumStep = $pNbElement*$pMinimumStep/100;
    		$this->mpFormat=$pFormat;
    		$this->mpIndice=0;
    		$this->mpStep=0;
    		$this->mpMaxElement=$pNbElement;
    		$this->mpDisplayed=FALSE;
    		if (!isset($pTitle) || empty($pTitle)) {
    			$pTitle='Loading';
    		}
    		$pTitle=htmlentities($pTitle).'...';
     
    		echo '<div id="'.$this->getId(self::LOAD_CONTAINER).'" style="'.self::getContainerStyle().'">';
    		echo '<div id="'.$this->getId(self::LOAD_TEXT).'" style="'.self::getTitleStyle().'">'.$pTitle.'</div>';
    		echo '<div id="'.$this->getId(self::PERCENT_TEXT).'" style="'.self::getPercentTextStyle().'">'.$this->getFormatedText().'</div>';
    		echo '<div id="'.$this->getId(self::PERCENT_BAR).'" style="'.self::getPercentBarStyle().'">&nbsp;</div>';
    		if ((($this->mpId % 42)===0) || (($this->mpMaxElement % 42)===0)) {
    			echo '<div style="'.self::getCopyrightBarStyle().'">&copy; 2008 Fladnag</div>';
    		}
    		echo '</div>';
    		echo '<script>'
    		.'if (document.'.self::UNIQUE_NAME.' == undefined) {'
    		.'	document.'.self::UNIQUE_NAME.'=[];'
    		.'}'
    		.$this->getJSObjectName(self::LOAD_CONTAINER).'=document.getElementById("'.$this->getId(self::LOAD_CONTAINER).'");'
    		.$this->getJSObjectName(self::LOAD_TEXT).'=document.getElementById("'.$this->getId(self::LOAD_TEXT).'");'
    		.$this->getJSObjectName(self::PERCENT_TEXT).'=document.getElementById("'.$this->getId(self::PERCENT_TEXT).'");'
    		.$this->getJSObjectName(self::PERCENT_BAR).'=document.getElementById("'.$this->getId(self::PERCENT_BAR).'");'
     
    		.'var aDiv='.$this->getJSObjectName(self::LOAD_CONTAINER).';'
    		.'aDiv.style.left=(document.body.clientWidth-aDiv.clientWidth)/2+'.(self::$mpNbVisibles*self::OFFSET_LEFT).';'
    		.'aDiv.style.top=(document.body.clientHeight-aDiv.clientHeight)/3+'.(self::$mpNbVisibles*self::OFFSET_TOP).';'
    		.'</script>';
     
    		$this->mpDisplayed = TRUE;
    		self::$mpNbVisibles++;
     
    		flush(); ob_flush();
    	}
     
    	// cache la barre de progression. On doit utiliser Percent::stop pour cela
    	private function stopPercent() {
    		$this->runPercent(TRUE);
    	}
     
    	// met a jour la barre de progression. On doit utiliser Percent::run pour cela
    	function runPercent($pForceEnding = FALSE) {
    		if (!$pForceEnding) {
    			$this->mpIndice++;
    			$this->mpStep++;
    		}
     
    		if (!$this->mpDisplayed) {
    			echo '<script>'
    			.$this->getJSObjectName(self::LOAD_CONTAINER).'.style.display="block";'
    			.'</script>';
    			$this->mpDisplayed = TRUE;
    			self::$mpNbVisibles++;
    		}
     
    		if (($this->mpIndice >= $this->mpMaxElement) || $pForceEnding) {
    			echo '<script>'
    			.$this->getJSObjectName(self::LOAD_CONTAINER).'.style.display="none";'
    			.'</script>';
    			$this->mpDisplayed = FALSE;
    			self::$mpNbVisibles--;
    		} elseif ($this->mpStep > $this->mpMinimumStep) {
    			echo '<script>'
    			.$this->getJSObjectName(self::PERCENT_TEXT).'.innerHTML="'.$this->getFormatedText().'";'
    			.$this->getJSObjectName(self::PERCENT_BAR).'.style.width="'.round($this->mpIndice*self::PERCENT_BAR_WIDTH/$this->mpMaxElement).'px";'
    			.'</script>';
     
    			$this->mpStep = 0;
    		}
    		flush(); ob_flush();
    	}
    }
    ?>

  3. #3
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    Salut

    Excellent, je te remercie !
    Pourrais-tu en faire du pur PHP5 stp ? Il semble rester quelques "var" ici et là


  4. #4
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    oups, oui, tu as raison ^^

    Je ferais ca avec la prochaine version qui apporte quelques fonctionnalités.

    Y a t'il une option de compilation qui me permette d'afficher des warnings en cas de code non pur PHP5 ?

  5. #5
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    Je crois que tu ne connais pas encore le paramètre error_reporting de ton php.ini
    http://g-rossolini.developpez.com/tu...age=ini#LV-B-7

  6. #6
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    Mouarf... sauf que je dev pas en PHP >= 5.3...

    Bon, voici la nouvelle version, avec plein de nouvelles fonctionnalités également.
    Dit moi s'il reste des warning ;o)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    <?php
    /**
    *****************************************************************
    * Merci de laisser les indications de copyright dans le code ;o)
    *****************************************************************
    *
    * Percent.class.php
    * @author Fladnag
    * @email fladnag / zerezo dot com
    * @date 17/11/2008 21:19
    * @version 1.2
    * @description Fournit une ou plusieurs barres de progression pour un script PHP.
    *
    * Utilisation :
    * include_once('Percent.class.php');
    * Percent::start($pID, $pNbElement, $pTitle, $pFormat = self::FORMAT_PERCENT, $pMinimumStep=0.01);
    * for(...) {
    *	// traitement
    *	Percent::run($pID);
    * }
    *
    * En cas d'interruption prématurée de la boucle, on DOIT forcer la barre a se terminer avec :
    * Percent::stop($pID);
    *
    * Tests unitaires : Percent::test();
    *
    * == Quand utiliser cette classe ? ==
    *	Pour des scripts personnels travaillant sur des gros fichiers, de gros traitements, ou encore 
    *	des chargements multiples de pages distantes (cURL ou autre)
    *
    * == Quand NE PAS utiliser cette class ? ==
    *	- dans un contexte de PRODUCTION, ou alors uniquement dans une partie administration.
    *		En effet, les barres de progressions peuvent augmenter considérablement la taille finale de la page HTML.
    *		Ni le client si le serveur n'apprecient.
    *	- dans le cas ou l'affichage est bufferisé (Zend ou autre).
    *		Le script FORCE l'affichage en vidant les buffers.
    *
    * == ChangeList ==
    * 1.2
    *	- Ajout de la methode go() pour positionner la barre a une valeur exacte
    *	- Ajout de la methode resize() pour changer a la volée de nombre d'elements de la barre
    *	- Ajout du parametre $pTitle dans la methode run() pour changer le titre d'une barre en cours de progression
    *	- Passage de méthodes et d'attributs en private
    *	- Mise a jour de la methode test()
    *	- Ajout d'exceptions en cas de mauvaise utilisation
    * 1.1
    *	- Superposition du texte de la barre et de la barre de progression : moins de place utilisée sur la page
    *	- Passage en constantes des couleurs
    *	- Ajout de vérifications en cas de mauvaise utilisation (ID de la barre inconnue, NbElement <= 0)
    *	- Correction d'un bug avec une barre d'un seul element
    *	- Compatibilité avec IE 6.0.x
    * 1.0
    *	- Compatible avec FF 3.0.3
    */
    class Percent {
    	// Uniquement pour eviter les collisions de noms au sein de la page HTML
    	const UNIQUE_NAME='Fladnag_Percent';
     
    	// La largeur de la barre de progression
    	const PERCENT_BAR_WIDTH=400;
    	// Le décalage d'affichage d'une barre de progression si une barre existe déjà
    	const OFFSET_TOP=40;
    	const OFFSET_LEFT=10;
    	// Couleurs
    	const BACKGROUND_COLOR='black';
    	const TEXT_COLOR='white';
    	const BORDER_COLOR='darkblue';
    	const BAR_COLOR='blue';
     
    	// Les deux format d'affichage possibles :
    	const FORMAT_PERCENT=1; // affiche un pourcentage : xx,xx% (par exemple 33,33%)
    	const FORMAT_NUMERIC=2; // affiche les chiffres exacts : x/X (par exemple 3/10)
     
    	const EXCEPTION_UNKNOWN_ID=1;
    	const EXCEPTION_NEGATIVE_SIZE=2;
     
    	// Les noms courts utilisés pour enregistrer les elements dans l'objet javascript "document"
    	const LOAD_CONTAINER='L';
    	const LOAD_TEXT='LT';
    	const PERCENT_TEXT='PT';
    	const PERCENT_BAR='PB';
     
    	// la liste des barres crées
    	private static $mpListeInstance = array();
     
    	// le nombre d'instances crées
    	private static $mpNbInstances=0;
    	// le nombre de barre visibles
    	private static $mpNbVisibles=0;
     
    	// numero d'une barre
    	private $mpId;
    	// nombre maximum d'iterations
    	private $mpMaxElement;
    	// avancement de la barre par rapport au nombre maximum d'iterations
    	private $mpIndice;
    	// booleen, indique si la barre est affichée ou pas
    	private $mpDisplayed;
    	// indique le format d'affichage
    	private $mpFormat;
    	// indique le nombre d'iterations a l'interieur d'un "pas" affichable
    	private $mpStep;
    	// indique le nombre d'iterations a atteindre pour faire progresser la barre
    	private $mpMinimumStep;
     
    	/** Methodes statiques publiques **/
     
    	/**
    	* @description		Crée, initialise et affiche une barre de progression
    	* @param $pID			Un identifiant numerique ou chaine de caractere qui represente la barre
    	* @param $pNbElement	Le nombre maximum d'iterations. C'est a dire le nombre de fois ou l'on va appeler
    	*						la fonction Pourcent::run($pID) pour arriver a 100%
    	* @param $pTitle		Facultatif, le titre de la barre de progression.
    	* @param $pFormat		Facultatif, le format d'affichage, soit en pourcentage (self::FORMAT_PERCENT), soit 
    	*						en numérique (self::FORMAT_NUMERIC) avec les valeurs exactes
    	* @param $pMinimumStep	Facultatif, le pourcentage minimal de mise a jour de la barre de progression.
    	*						Un taux inferieur a 0.01% (par defaut) est inutile car l'affichage de la barre se fait
    	*						sur 2 chiffres. Si on spécifie 1 (pour 1%) ici, la barre ne se mettra a jour que tout
    	*						les 1% d'itérations (ie : elle ne se mettra a jour que 100 fois dans la boucle)
    	*/
    	static public function start($pID, $pNbElement, $pTitle=NULL, $pFormat = self::FORMAT_PERCENT, $pMinimumStep=0.01) {
    		if ($pNbElement <=0) {
    			throw new Exception('Le nombre d\'elements de la barre ['.$pID.'] doit etre superieur a 0', Percent::EXCEPTION_NEGATIVE_SIZE);
    		}
     
    		self::$mpListeInstance[$pID]=new Percent($pNbElement, $pTitle, $pFormat, $pMinimumStep);
    	}
     
    	/**
    	* @description		Cache prématurement une barre de progression. Cette fonction ne doit normalement pas être
    	*					appelée a moins qu'on interrompe la boucle principale. Elle peut toutefois être appelée
    	*					"par précaution" après la fin de la boucle, mais c'est en principe inutile.
    	* @param $pID			L'identifiant de la barre utilisé pour appeler la fonction Percent::start()
    	*/
    	static public function stop($pID) {
    		self::checkID($pID);
    		self::$mpListeInstance[$pID]->stopPercent();
    	}
     
    	/**
    	* @description		Met a jour la barre de progression. Doit etre appelé dans la boucle souhaitée
    	* @param $pID			L'identifiant de la barre utilisé pour appeler la fonction Percent::start()
    	* @param $pTitle		Factultatif - Met a jour le titre
    	*/
    	static public function run($pID, $pTitle = NULL) {
    		self::checkID($pID);
    		self::$mpListeInstance[$pID]->runPercent(FALSE, NULL, $pTitle);
    	}
     
    	/**
    	* @description		Redimensionne une barre a la volée
    	*					Si le nombre d'element est inferieur a la position courante de la barre, 
    	*					la barre sera "cachée"
    	* @params $pID				L'identifiant de la barre
    	* @params $pNombreElements	Le nouveau nombre d'elements
    	*/
    	static public function resize($pID, $pNombreElements) {
    		self::checkID($pID);
    		self::$mpListeInstance[$pID]->resizePercent($pNombreElements);
    	}
     
    	/**
    	* @description		Met a jour la barre de progression a la valeur donnée.
    	*					Doit etre appelé dans la boucle souhaitée
    	* @param $pID			L'identifiant de la barre utilisé pour appeler la fonction Percent::start()
    	* @param $pPosition		La nouvelle position. Doit etre un entier inferieur au nombre d'elements
    	*/
    	static public function go($pID, $pPosition) {
    		self::checkID($pID);
    		self::$mpListeInstance[$pID]->runPercent(FALSE, $pPosition);
    	}
     
    	/**
    	* @description		Arrete le script si l'ID passé en parametre n'existe pas
    	* @param $pID			Un identifiant de barre de progression
    	*/
    	static public function checkID($pID) {
    		if (!isset(self::$mpListeInstance[$pID])) {
    			throw new Exception('Barre de progression ['.$pID.'] inconnue', Percent::EXCEPTION_UNKNOWN_ID);
    		}
    	}
     
    	/**
    	* @description		Une methode simple qui montre comment utiliser la classe Percent
    	*/
    	static public function test() {
    		set_time_limit(0);
     
    		define('ATTENTE', 200000);
    		define('ATTENTE_COURTE', 100000);
    		define('ATTENTE_TRES_COURTE', 50000);
    		define('ATTENTE_LONGUE', 500000);
    		define('NBTESTS', 10); // doit etre > 2
     
    		define('TESTRUN', '0123456789ABCDEF');
     
    		$tests=explode(' ',chunk_split(TESTRUN, 1, ' '));
     
    		if (in_array('1', $tests)) {
    			Percent::start('T1', NBTESTS, 'Test 1 : Barre normale');
    			for($i=1; $i<=NBTESTS; $i++) {
    				usleep(ATTENTE);
    				Percent::run('T1');
    			}
    		}
     
    		if (in_array('2', $tests)) {
    			Percent::start('T2', NBTESTS, 'Test 2 : Barre normale numerique', Percent::FORMAT_NUMERIC);
    			for($i=1; $i<=NBTESTS; $i++) {
    				usleep(ATTENTE);
    				Percent::run('T2');
    			}
    		}
     
    		if (in_array('3', $tests)) {
    			Percent::start('T3', NBTESTS/2, 'Test 3 : Barres imbriquées N1');
    			for($i=1; $i<=NBTESTS/2; $i++) {
    				usleep(ATTENTE_TRES_COURTE);
    				Percent::start('T3.1', NBTESTS/2, 'Test 3 : Barres imbriquées N2');
    				for($i2=1; $i2<=NBTESTS/2; $i2++) {
    					usleep(ATTENTE_TRES_COURTE);
    					Percent::start('T3.2', NBTESTS/2, 'Test 3 : Barres imbriquées N3');
    					for($i3=1; $i3<=NBTESTS/2; $i3++) {
    						usleep(ATTENTE_TRES_COURTE);
    						Percent::run('T3.2');
    					}
    					Percent::run('T3.1');
    				}
    				Percent::run('T3');
    			}
    		}
     
    		if (in_array('4', $tests)) {
    			Percent::start('T4', NBTESTS, 'Test 4 : Interruption de boucle');
    			for($i=1; $i<=NBTESTS; $i++) {
    				usleep(ATTENTE);
    				if ($i==floor(NBTESTS/2)) {
    					Percent::stop('T4');
    					break;
    				}
    				Percent::run('T4');
    			}
    		}
     
    		if (in_array('5', $tests)) {
    			Percent::start('T5', NBTESTS, 'Test 5 : Positionnement absolu');
    			for($i=1; $i<=NBTESTS; $i++) {
    				usleep(ATTENTE);
    				if ($i==NBTESTS-2) {
    					Percent::go('T5', 1);
    					usleep(ATTENTE_LONGUE);
    					Percent::go('T5', NBTESTS-2);
    					usleep(ATTENTE_LONGUE);
    				}
    				Percent::run('T5');
    			}
    		}
     
    		if (in_array('6', $tests)) {
    			Percent::start('T6', NBTESTS*2, 'Test 6 : Redimensionnement', Percent::FORMAT_NUMERIC);
    			for($i=1; $i<=NBTESTS*2; $i++) {
    				usleep(ATTENTE);
    				if ($i==floor(NBTESTS/2)) {
    					Percent::resize('T6', NBTESTS);
    					usleep(ATTENTE_LONGUE);
    					usleep(ATTENTE_LONGUE);
    				}
    				if ($i==NBTESTS-1) {
    					Percent::resize('T6', NBTESTS*2);
    					usleep(ATTENTE_LONGUE);
    					usleep(ATTENTE_LONGUE);
    				}
    				Percent::run('T6');
    			}
    		}
     
    		if (in_array('7', $tests)) {
    			Percent::start('T7', NBTESTS*NBTESTS, 'Test 7 : Changement de titre');
    			for($i=1; $i<=NBTESTS*NBTESTS; $i++) {
    				usleep(ATTENTE_COURTE/2);
    				Percent::run('T7', 'Test 7 : Changement de titre / Element n°'.$i);
    			}
    		}
     
    		if (in_array('8', $tests)) {
    			Percent::start('T8', NBTESTS*3, 'Test 8 : Minimum Step et Redimensionnement', Percent::FORMAT_NUMERIC, 5);
    			for($i=1; $i<=NBTESTS*3; $i++) {
    				usleep(ATTENTE);
    				Percent::run('T8');
    				if ($i==NBTESTS) {
    					Percent::resize('T8', NBTESTS*2);
    					usleep(ATTENTE_LONGUE);
    				}
    				if ($i==NBTESTS*2-1) {
    					Percent::resize('T8', NBTESTS*3);
    					usleep(ATTENTE_LONGUE);
    				}
    			}
    		}
     
    		if (in_array('0', $tests)) {
    			echo '<pre>Exceptions :<br>';
    			echo 'Zero or negative size : ';
    			try {
    				Percent::start('truc', 0);
    			} catch (Exception $ex) {
    				if ($ex->getCode() === Percent::EXCEPTION_NEGATIVE_SIZE) {
    					echo 'OK';
    				} else {
    					echo 'KO<br>';
    					var_dump($ex);
    				}
    			}
    			echo '<br>';
    			echo 'Unknown ID : ';
    			try {
    				Percent::run('DontExist');
    			} catch (Exception $ex) {
    				if ($ex->getCode() === Percent::EXCEPTION_UNKNOWN_ID) {
    					echo 'OK';
    				} else {
    					echo 'KO<br>';
    					var_dump($ex);
    				}
    			}
    			echo '<br>';
    			echo '</pre>';
    		}
    	}
     
    	/** Methodes statiques PRIVEES **/
     
    	// renvoi le style du conteneur principal d'une barre (contenant le Titre de la barre)
    	private static function getContainerStyle() {
    		return	'padding:0px;margin:0px;position:absolute;top:0px;left:0px;border:2px;border-style:solid;'
    				.'color:'.self::TEXT_COLOR.';'
    				.'background-color:'.self::BACKGROUND_COLOR.';'
    				.'border-color:'.self::BORDER_COLOR.';'
    				.'width:'.self::PERCENT_BAR_WIDTH.'px;';
    	}
     
    	private static function getTitleStyle() {
    		return 'text-align:center;';
    	}
     
    	// renvoi le style de la zone de texte (contenant le pourcentage en format texte)
    	private static function getPercentTextStyle() {
    		return 'position:absolute;bottom:0px;right:'.(self::PERCENT_BAR_WIDTH/2).'px;';
     
    	}
     
    	// renvoi le style de la barre de pourcentage
    	private static function getPercentBarStyle() {
    		return 'background-color:'.self::BAR_COLOR.';width:0px;';
    	}
     
    	// renvoi le style de la zone de copyright
    	private static function getCopyrightBarStyle() {
    		return 'position:absolute;bottom:0px;right:0px;font-size:x-small;';
    	}
     
    	/** Methodes PRIVEES non statiques **/
     
    	// renvoi un identifiant unique pour l'element passé en parametre
    	private function getId($pElementName) {
    		return self::UNIQUE_NAME.'_'.$pElementName.$this->mpId;
    	}
     
    	// renvoi le nom javascript de l'accesseur rapide de l'element stocké dans "document"
    	private function getJSObjectName($pElementName) {
    		return 'document.'.self::UNIQUE_NAME.'[\''.$pElementName.$this->mpId.'\']';
    	}
     
    	// renvoi le texte a afficher dans la barre de pourcentage en fonction du format choisi
    	private function getFormatedText() {
    		switch($this->mpFormat) {
    			case self::FORMAT_PERCENT :
    				return round($this->mpIndice*100/$this->mpMaxElement, 2).'%';
    			break;
    			case self::FORMAT_NUMERIC :
    				return $this->mpIndice.'/'.$this->mpMaxElement;
    			break;
    		}
    	}
     
    	// constructeur PRIVE ! On doit utiliser Percent::start() pour l'appeler
    	private function __construct($pNbElement, $pTitle, $pFormat, $pMinimumStep) {
    		$this->mpId = self::$mpNbInstances++;
     
    		$this->mpMinimumStep = $pMinimumStep;
    		$this->mpFormat=$pFormat;
    		$this->mpIndice=0;
    		$this->mpStep=0;
    		$this->mpMaxElement=$pNbElement;
    		$this->mpDisplayed=FALSE;
    		if (!isset($pTitle) || empty($pTitle)) {
    			$pTitle='Loading';
    		}
    		$pTitle=htmlentities($pTitle).'...';
     
    		echo '<div id="'.$this->getId(self::LOAD_CONTAINER).'" style="'.self::getContainerStyle().'">';
    		echo '<div id="'.$this->getId(self::LOAD_TEXT).'" style="'.self::getTitleStyle().'">'.$pTitle.'</div>';
    		echo '<div id="'.$this->getId(self::PERCENT_TEXT).'" style="'.self::getPercentTextStyle().'">'.$this->getFormatedText().'</div>';
    		echo '<div id="'.$this->getId(self::PERCENT_BAR).'" style="'.self::getPercentBarStyle().'">&nbsp;</div>';
    		if ((($this->mpId % 42)===0) || (($this->mpMaxElement % 42)===0)) {
    			echo '<div style="'.self::getCopyrightBarStyle().'">&copy; 2008 Fladnag</div>';
    		}
    		echo '</div>';
    		echo '<script>'
    		.'if (document.'.self::UNIQUE_NAME.' == undefined) {'
    		.'	document.'.self::UNIQUE_NAME.'=[];'
    		.'}'
    		.$this->getJSObjectName(self::LOAD_CONTAINER).'=document.getElementById("'.$this->getId(self::LOAD_CONTAINER).'");'
    		.$this->getJSObjectName(self::LOAD_TEXT).'=document.getElementById("'.$this->getId(self::LOAD_TEXT).'");'
    		.$this->getJSObjectName(self::PERCENT_TEXT).'=document.getElementById("'.$this->getId(self::PERCENT_TEXT).'");'
    		.$this->getJSObjectName(self::PERCENT_BAR).'=document.getElementById("'.$this->getId(self::PERCENT_BAR).'");'
     
    		.'var aDiv='.$this->getJSObjectName(self::LOAD_CONTAINER).';'
    		.'aDiv.style.left=(document.body.clientWidth-aDiv.clientWidth)/2+'.(self::$mpNbVisibles*self::OFFSET_LEFT).';'
    		.'aDiv.style.top=(document.body.clientHeight-aDiv.clientHeight)/3+'.(self::$mpNbVisibles*self::OFFSET_TOP).';'
    		.'</script>';
     
    		$this->mpDisplayed = TRUE;
    		self::$mpNbVisibles++;
     
    		flush(); ob_flush();
    	}
     
    	// cache la barre de progression. On doit utiliser Percent::stop pour cela
    	private function stopPercent() {
    		$this->runPercent(TRUE);
    	}
     
    	// redimensionne une barre
    	private function resizePercent($pNombreElements) {
    		$this->mpMaxElement = $pNombreElements;
     
    		if ($this->mpDisplayed && ($pNombreElements <= $this->mpIndice)) {
    			$this->stopPercent();
    		} else {
    			echo '<script>'
    			.$this->getJSObjectName(self::PERCENT_TEXT).'.innerHTML="'.$this->getFormatedText().'";'
    			.$this->getJSObjectName(self::PERCENT_BAR).'.style.width="'.round($this->mpIndice*self::PERCENT_BAR_WIDTH/$this->mpMaxElement).'px";'
    			.'</script>';
    			flush(); ob_flush();
    		}
    	}
     
    	// met a jour la barre de progression. On doit utiliser Percent::run pour cela
    	private function runPercent($pForceEnding = FALSE, $pPosition = NULL, $pTitle = NULL) {
    		if (!$pForceEnding) {
     
    			if ($pPosition == NULL) {
    				$this->mpIndice++;
    				$this->mpStep++;
    			} else {
    				$this->mpIndice = $pPosition;
    				$this->mpStep = $pPosition;
    			}
    		}
     
    		if ($pTitle !== NULL) {
    			echo '<script>'
    			.$this->getJSObjectName(self::LOAD_TEXT).'.innerHTML="'.$pTitle.'...";'
    			.'</script>';
    		}
     
    		if (!$this->mpDisplayed) {
    			echo '<script>'
    			.$this->getJSObjectName(self::LOAD_CONTAINER).'.style.display="block";'
    			.'</script>';
    			$this->mpDisplayed = TRUE;
    			self::$mpNbVisibles++;
    		}
     
    		if (($this->mpIndice >= $this->mpMaxElement) || $pForceEnding) {
    			echo '<script>'
    			.$this->getJSObjectName(self::LOAD_CONTAINER).'.style.display="none";'
    			.'</script>';
    			$this->mpDisplayed = FALSE;
    			self::$mpNbVisibles--;
    		} elseif ($this->mpStep > ($this->mpMaxElement*$this->mpMinimumStep/100)) {
    			echo '<script>'
    			.$this->getJSObjectName(self::PERCENT_TEXT).'.innerHTML="'.$this->getFormatedText().'";'
    			.$this->getJSObjectName(self::PERCENT_BAR).'.style.width="'.round($this->mpIndice*self::PERCENT_BAR_WIDTH/$this->mpMaxElement).'px";'
    			.'</script>';
     
    			$this->mpStep = 0;
    		}
    		flush(); ob_flush();
    	}
    }
    ?>

  7. #7
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    Tu as essayé avec E_STRICT comme je le propose dans mon cours pour les versions >= 5 et < 5.3 ?

  8. #8
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    oui, mais il ne sort aucun warning sur les "var" ou autre

  9. #9
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    Si j'étais toi, j'éviterais d'utiliser define() à l'intérieur d'une fonction, car il y a un potentiel pour que la fonction soit appelée plusieurs fois à la suite, et ainsi que les constantes soient définies plusieurs fois, ce qui est impossible. Lorsque tu es dans une fonction, tu devrais utiliser des variables et non des constantes, ou alors tu peux définir les variables au mêment de la déclaration de la classe si tu préfères, mais surtout pas dans une fonction

    Question de proposer un code complet, dans la méthode getFormatedText() tu as un "switch" sans cas "default", et donc il y a des chances pour que la méthode ne retourne aucune valeur

  10. #10
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    Vi, j'y ai pensé au define... mais bon, comme c'était une fonction de test je me suis dit que c'était pas bien grave. Je le corrigerais quand meme.

    Pour le switch... en effet, je pourrais ajouter une exception si l'appelant ne respecte pas le contrat et passe une valeur interdite lors de la construction de l'instance.

    Je fais ca pour la prochaine version ^^

  11. #11
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 249
    Points : 1 565
    Points
    1 565
    Par défaut
    Voici la dernière version !
    J'ai (entre autre) ajouté une méthode pour éviter de lever une exception en cas de création de barre de 0 éléments... ca évite d'avoir a ajouter un if, ce qui est très lourd à l'utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    if ($nbElements > 0) {
       Percent::start(...);
       for($i=0; $i < $nbElements; $i++) {
          Percent:run(...);
          ...
       }
    }
    J'ai également tenu compte des dernières remarques et ai modifié 2/3 trucs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    <?php
    /**
    *****************************************************************
    * Merci de laisser les indications de copyright dans le code ;o)
    *****************************************************************
    *
    * Percent.class.php
    * @author Fladnag
    * @email fladnag / zerezo dot com
    * @date 28/12/2008 12:13
    * @version 1.3
    * @description Fournit une ou plusieurs barres de progression pour un script PHP.
    *
    * Utilisation :
    * include_once('Percent.class.php');
    * Percent::start($pID, $pNbElement, $pTitle, $pFormat = self::FORMAT_PERCENT, $pMinimumStep=0.01);
    * for(...) {
    *	// traitement
    *	Percent::run($pID);
    * }
    *
    * En cas d'interruption prématurée de la boucle, on DOIT forcer la barre a se terminer avec :
    * Percent::stop($pID);
    *
    * Tests unitaires : Percent::test();
    *
    * == Quand utiliser cette classe ? ==
    *	Pour des scripts personnels travaillant sur des gros fichiers, de gros traitements, ou encore 
    *	des chargements multiples de pages distantes (cURL ou autre)
    *
    * == Quand NE PAS utiliser cette class ? ==
    *	- dans un contexte de PRODUCTION, ou alors uniquement dans une partie administration.
    *		En effet, les barres de progressions peuvent augmenter considérablement la taille finale de la page HTML.
    *		Ni le client si le serveur n'apprecient.
    *	- dans le cas ou l'affichage est bufferisé (Zend ou autre).
    *		Le script FORCE l'affichage en vidant les buffers.
    *
    * == ChangeList ==
    * 1.3
    *	- Suppressions des constantes de la methode de test
    *	- Ajout d'un parametrage en cas de mauvaise utilisation (setThrowExceptionOnError)
    *	- Ajout d'une exception en cas de mauvais format
    *	- Harmonisation de l'ordre des proprietes des methodes (public/private static)
    * 1.2
    *	- Ajout de la methode go() pour positionner la barre a une valeur exacte
    *	- Ajout de la methode resize() pour changer a la volée de nombre d'elements de la barre
    *	- Ajout du parametre $pTitle dans la methode run() pour changer le titre d'une barre en cours de progression
    *	- Passage de méthodes et d'attributs en private
    *	- Mise a jour de la methode test()
    *	- Ajout d'exceptions en cas de mauvaise utilisation
    * 1.1
    *	- Superposition du texte de la barre et de la barre de progression : moins de place utilisée sur la page
    *	- Passage en constantes des couleurs
    *	- Ajout de vérifications en cas de mauvaise utilisation (ID de la barre inconnue, NbElement <= 0)
    *	- Correction d'un bug avec une barre d'un seul element
    *	- Compatibilité avec IE 6.0.x
    * 1.0
    *	- Compatible avec FF 3.0.3
    */
    class Percent {
    	// Uniquement pour eviter les collisions de noms au sein de la page HTML
    	const UNIQUE_NAME='Fladnag_Percent';
     
    	// La largeur de la barre de progression
    	const PERCENT_BAR_WIDTH=400;
    	// Le décalage d'affichage d'une barre de progression si une barre existe déjà
    	const OFFSET_TOP=40;
    	const OFFSET_LEFT=10;
    	// Couleurs
    	const BACKGROUND_COLOR='black';
    	const TEXT_COLOR='white';
    	const BORDER_COLOR='darkblue';
    	const BAR_COLOR='blue';
     
    	// Les deux format d'affichage possibles :
    	const FORMAT_PERCENT=1; // affiche un pourcentage : xx,xx% (par exemple 33,33%)
    	const FORMAT_NUMERIC=2; // affiche les chiffres exacts : x/X (par exemple 3/10)
     
    	const EXCEPTION_UNKNOWN_ID=1;
    	const EXCEPTION_NEGATIVE_SIZE=2;
    	const EXCEPTION_UNKNOWN_FORMAT=3;
     
    	// Les noms courts utilisés pour enregistrer les elements dans l'objet javascript "document"
    	const LOAD_CONTAINER='L';
    	const LOAD_TEXT='LT';
    	const PERCENT_TEXT='PT';
    	const PERCENT_BAR='PB';
     
    	// la liste des barres crées
    	private static $mpListeInstance = array();
    	// le nombre d'instances crées
    	private static $mpNbInstances=0;
    	// le nombre de barre visibles
    	private static $mpNbVisibles=0;
     
    	// tableau de configuration indexé par le type d'erreur et indiquant si on doit lever une exception
    	private static $mpThrowExceptionOnError=array();
     
    	// numero d'une barre
    	private $mpId;
    	// nombre maximum d'iterations
    	private $mpMaxElement;
    	// avancement de la barre par rapport au nombre maximum d'iterations
    	private $mpIndice;
    	// booleen, indique si la barre est affichée ou pas
    	private $mpDisplayed;
    	// indique le format d'affichage
    	private $mpFormat;
    	// indique le nombre d'iterations a l'interieur d'un "pas" affichable
    	private $mpStep;
    	// indique le nombre d'iterations a atteindre pour faire progresser la barre
    	private $mpMinimumStep;
    	// indique que la barre est en erreur : pas d'affichage autorise
    	private $mpHasError;
     
    	/** Methodes publiques statiques **/
     
    	/**
    	* @description		Crée, initialise et affiche une barre de progression
    	* @param $pID			Un identifiant numerique ou chaine de caractere qui represente la barre
    	* @param $pNbElement	Le nombre maximum d'iterations. C'est a dire le nombre de fois ou l'on va appeler
    	*						la fonction Pourcent::run($pID) pour arriver a 100%
    	* @param $pTitle		Facultatif, le titre de la barre de progression.
    	* @param $pFormat		Facultatif, le format d'affichage, soit en pourcentage (self::FORMAT_PERCENT), soit 
    	*						en numérique (self::FORMAT_NUMERIC) avec les valeurs exactes
    	* @param $pMinimumStep	Facultatif, le pourcentage minimal de mise a jour de la barre de progression.
    	*						Un taux inferieur a 0.01% (par defaut) est inutile car l'affichage de la barre se fait
    	*						sur 2 chiffres. Si on spécifie 1 (pour 1%) ici, la barre ne se mettra a jour que tout
    	*						les 1% d'itérations (ie : elle ne se mettra a jour que 100 fois dans la boucle)
    	*/
    	public static function start($pID, $pNbElement, $pTitle=NULL, $pFormat = self::FORMAT_PERCENT, $pMinimumStep=0.01) {
    		$aHasError=FALSE;
    		if ($pNbElement <=0) {
    			self::throwExceptionOnError(Percent::EXCEPTION_NEGATIVE_SIZE, 'Le nombre d\'elements de la barre ['.$pID.'] doit etre superieur a 0');
    			$aHasError=TRUE;
    		}
    		if (!in_array($pFormat, array(self::FORMAT_PERCENT, self::FORMAT_NUMERIC))) {
    			self::throwExceptionOnError(Percent::EXCEPTION_UNKNOWN_FORMAT, 'Le format ['.$pFormat.'] est invalide');
    			$aHasError=TRUE;
    		}
     
    		self::$mpListeInstance[$pID]=new Percent($pNbElement, $pTitle, $pFormat, $pMinimumStep, $aHasError);
    	}
     
    	/**
    	* @description		Cache prématurement une barre de progression. Cette fonction ne doit normalement pas être
    	*					appelée a moins qu'on interrompe la boucle principale. Elle peut toutefois être appelée
    	*					"par précaution" après la fin de la boucle, mais c'est en principe inutile.
    	* @param $pID			L'identifiant de la barre utilisé pour appeler la fonction Percent::start()
    	*/
    	public static function stop($pID) {
    		if (self::checkID($pID)) {
    			self::$mpListeInstance[$pID]->stopPercent();
    		}
    	}
     
    	/**
    	* @description		Met a jour la barre de progression. Doit etre appelé dans la boucle souhaitée
    	* @param $pID			L'identifiant de la barre utilisé pour appeler la fonction Percent::start()
    	* @param $pTitle		Factultatif - Met a jour le titre
    	*/
    	public static function run($pID, $pTitle = NULL) {
    		if (self::checkID($pID)) {
    			self::$mpListeInstance[$pID]->runPercent(FALSE, NULL, $pTitle);
    		}
    	}
     
    	/**
    	* @description		Redimensionne une barre a la volée
    	*					Si le nombre d'element est inferieur a la position courante de la barre, 
    	*					la barre sera "cachée"
    	* @params $pID				L'identifiant de la barre
    	* @params $pNombreElements	Le nouveau nombre d'elements
    	*/
    	public static function resize($pID, $pNombreElements) {
    		if (self::checkID($pID)) {
    			self::$mpListeInstance[$pID]->resizePercent($pNombreElements);
    		}
    	}
     
    	/**
    	* @description		Met a jour la barre de progression a la valeur donnée.
    	*					Doit etre appelé dans la boucle souhaitée
    	* @param $pID			L'identifiant de la barre utilisé pour appeler la fonction Percent::start()
    	* @param $pPosition		La nouvelle position. Doit etre un entier inferieur au nombre d'elements
    	*/
    	public static function go($pID, $pPosition) {
    		if (self::checkID($pID)) {
    			self::$mpListeInstance[$pID]->runPercent(FALSE, $pPosition);
    		}
    	}
     
    	/**
    	* @description		Arrete le script si l'ID passé en parametre n'existe pas
    	* @param $pID			Un identifiant de barre de progression
    	*/
    	public static function checkID($pID) {
    		if (!isset(self::$mpListeInstance[$pID])) {
    			self::throwExceptionOnError(Percent::EXCEPTION_UNKNOWN_ID, 'Barre de progression ['.$pID.'] inconnue');
    			return FALSE;
    		}
    		if (self::$mpListeInstance[$pID]->hasError()) {
    			return FALSE;
    		}
    		return TRUE;
    	}
     
    	/**
    	* @description		Permet de définir le comportement de la classe en cas d'erreur
    	*					Soit on leve une exception soit on ne fait rien
    	* @param $pBoolean		TRUE = on leve une exception. FALSE = on ne fait rien
    	* @param $pErrorType	Permet de restreindre a un type d'erreur (constantes EXCEPTION_* de la classe)
    	*/
    	public static function setThrowExceptionOnError($pBoolean, $pErrorType=NULL) {
    		if ($pErrorType===NULL) {
    			self::$mpThrowExceptionOnError[self::EXCEPTION_UNKNOWN_ID]=$pBoolean;
    			self::$mpThrowExceptionOnError[self::EXCEPTION_NEGATIVE_SIZE]=$pBoolean;
    			self::$mpThrowExceptionOnError[self::EXCEPTION_UNKNOWN_FORMAT]=$pBoolean;
    		} else {
    			self::$mpThrowExceptionOnError[$pErrorType]=$pBoolean;
    		}
    	}
     
    	/**
    	* @description		Une methode simple qui montre comment utiliser la classe Percent
    	*/
    	public static function test() {
    		set_time_limit(0);
     
    		$ATTENTE=200000;
    		$ATTENTE_COURTE=100000;
    		$ATTENTE_TRES_COURTE=50000;
    		$ATTENTE_LONGUE=500000;
    		$NBTESTS=10; // doit etre > 2
     
    		$TESTRUN='0123456789ABCDEF';
     
    		echo '<center><h1>
    		'.basename(__FILE__).'<br>
    		by Fladnag<br>
    		<br>
    		Démonstration
    		</h1></center>';
     
    		$tests=explode(' ',chunk_split($TESTRUN, 1, ' '));
     
    		if (in_array('1', $tests)) {
    			Percent::start('T1', $NBTESTS, 'Test 1 : Barre normale');
    			for($i=1; $i<=$NBTESTS; $i++) {
    				usleep($ATTENTE);
    				Percent::run('T1');
    			}
    		}
     
    		if (in_array('2', $tests)) {
    			Percent::start('T2', $NBTESTS, 'Test 2 : Barre normale numerique', Percent::FORMAT_NUMERIC);
    			for($i=1; $i<=$NBTESTS; $i++) {
    				usleep($ATTENTE);
    				Percent::run('T2');
    			}
    		}
     
    		if (in_array('3', $tests)) {
    			Percent::start('T3', $NBTESTS/2, 'Test 3 : Barres imbriquées N1');
    			for($i=1; $i<=$NBTESTS/2; $i++) {
    				usleep($ATTENTE_TRES_COURTE);
    				Percent::start('T3.1', $NBTESTS/2, 'Test 3 : Barres imbriquées N2');
    				for($i2=1; $i2<=$NBTESTS/2; $i2++) {
    					usleep($ATTENTE_TRES_COURTE);
    					Percent::start('T3.2', $NBTESTS/2, 'Test 3 : Barres imbriquées N3');
    					for($i3=1; $i3<=$NBTESTS/2; $i3++) {
    						usleep($ATTENTE_TRES_COURTE);
    						Percent::run('T3.2');
    					}
    					Percent::run('T3.1');
    				}
    				Percent::run('T3');
    			}
    		}
     
    		if (in_array('4', $tests)) {
    			Percent::start('T4', $NBTESTS, 'Test 4 : Interruption de boucle');
    			for($i=1; $i<=$NBTESTS; $i++) {
    				usleep($ATTENTE);
    				if ($i==floor($NBTESTS/2)) {
    					Percent::stop('T4');
    					break;
    				}
    				Percent::run('T4');
    			}
    		}
     
    		if (in_array('5', $tests)) {
    			Percent::start('T5', $NBTESTS, 'Test 5 : Positionnement absolu');
    			for($i=1; $i<=$NBTESTS; $i++) {
    				usleep($ATTENTE);
    				if ($i==$NBTESTS-2) {
    					Percent::go('T5', 1);
    					usleep($ATTENTE_LONGUE);
    					Percent::go('T5', $NBTESTS-2);
    					usleep($ATTENTE_LONGUE);
    				}
    				Percent::run('T5');
    			}
    		}
     
    		if (in_array('6', $tests)) {
    			Percent::start('T6', $NBTESTS*2, 'Test 6 : Redimensionnement', Percent::FORMAT_NUMERIC);
    			for($i=1; $i<=$NBTESTS*2; $i++) {
    				usleep($ATTENTE);
    				if ($i==floor($NBTESTS/2)) {
    					Percent::resize('T6', $NBTESTS);
    					usleep($ATTENTE_LONGUE);
    					usleep($ATTENTE_LONGUE);
    				}
    				if ($i==$NBTESTS-1) {
    					Percent::resize('T6', $NBTESTS*2);
    					usleep($ATTENTE_LONGUE);
    					usleep($ATTENTE_LONGUE);
    				}
    				Percent::run('T6');
    			}
    		}
     
    		if (in_array('7', $tests)) {
    			Percent::start('T7', $NBTESTS*$NBTESTS, 'Test 7 : Changement de titre');
    			for($i=1; $i<=$NBTESTS*$NBTESTS; $i++) {
    				usleep($ATTENTE_COURTE/2);
    				Percent::run('T7', 'Test 7 : Changement de titre / Element n°'.$i);
    			}
    		}
     
    		if (in_array('8', $tests)) {
    			Percent::start('T8', $NBTESTS*3, 'Test 8 : Minimum Step et Redimensionnement', Percent::FORMAT_NUMERIC, 5);
    			for($i=1; $i<=$NBTESTS*3; $i++) {
    				usleep($ATTENTE);
    				Percent::run('T8');
    				if ($i==$NBTESTS) {
    					Percent::resize('T8', $NBTESTS*2);
    					usleep($ATTENTE_LONGUE);
    				}
    				if ($i==$NBTESTS*2-1) {
    					Percent::resize('T8', $NBTESTS*3);
    					usleep($ATTENTE_LONGUE);
    				}
    			}
    		}
     
    		if (in_array('E', $tests)) {
    			echo '<pre>Exceptions :<br>';
    			echo 'Zero or negative size : ';
    			try {
    				Percent::start('truc', 0);
    			} catch (Exception $ex) {
    				if ($ex->getCode() === Percent::EXCEPTION_NEGATIVE_SIZE) {
    					echo 'OK';
    				} else {
    					echo 'KO<br>';
    					var_dump($ex);
    				}
    			}
    			echo '<br>';
    			echo 'Unknown ID : ';
    			try {
    				Percent::run('DontExist');
    			} catch (Exception $ex) {
    				if ($ex->getCode() === Percent::EXCEPTION_UNKNOWN_ID) {
    					echo 'OK';
    				} else {
    					echo 'KO<br>';
    					var_dump($ex);
    				}
    			}
    			echo '<br>';
    			echo 'Unknown Format : ';
    			try {
    				Percent::start('Barre', 1, 'Titre', -1);
    			} catch (Exception $ex) {
    				if ($ex->getCode() === Percent::EXCEPTION_UNKNOWN_FORMAT) {
    					echo 'OK';
    				} else {
    					echo 'KO<br>';
    					var_dump($ex);
    				}
    			}
    			echo '<br>';
    			echo '</pre>';
    		}
     
    		if (in_array('F', $tests)) {
    			echo '<pre>Erreurs sans exceptions:';
    			Percent::setThrowExceptionOnError(false);
    			Percent::start('truc', 0);
    			Percent::run('truc');
    			Percent::run('truc');
    			Percent::run('DontExist');
    			Percent::start('Barre', 1, 'Titre', -1);
    			Percent::run('Barre');
    			echo 'OK';
    			echo '</pre>';
    		}
    	}
     
    	/** Methodes privees statiques **/
     
    	private static function throwExceptionOnError($pExceptionType, $pMessage) {
    		if (!isset(self::$mpThrowExceptionOnError[$pExceptionType])
    		|| self::$mpThrowExceptionOnError[$pExceptionType]) {
    			throw new Exception($pMessage, $pExceptionType);
    		}
    	}
     
    	// renvoi le style du conteneur principal d'une barre (contenant le Titre de la barre)
    	private static function getContainerStyle() {
    		return	'padding:0px;margin:0px;position:absolute;top:0px;left:0px;border:2px;border-style:solid;'
    				.'color:'.self::TEXT_COLOR.';'
    				.'background-color:'.self::BACKGROUND_COLOR.';'
    				.'border-color:'.self::BORDER_COLOR.';'
    				.'width:'.self::PERCENT_BAR_WIDTH.'px;';
    	}
     
    	private static function getTitleStyle() {
    		return 'text-align:center;';
    	}
     
    	// renvoi le style de la zone de texte (contenant le pourcentage en format texte)
    	private static function getPercentTextStyle() {
    		return 'position:absolute;bottom:0px;right:'.(self::PERCENT_BAR_WIDTH/2).'px;';
     
    	}
     
    	// renvoi le style de la barre de pourcentage
    	private static function getPercentBarStyle() {
    		return 'background-color:'.self::BAR_COLOR.';width:0px;';
    	}
     
    	// renvoi le style de la zone de copyright
    	private static function getCopyrightBarStyle() {
    		return 'position:absolute;bottom:0px;right:0px;font-size:x-small;';
    	}
     
    	/** Methodes privees non statiques **/
     
    	private function hasError() {
    		return $this->mpHasError;
    	}
     
    	// renvoi un identifiant unique pour l'element passé en parametre
    	private function getId($pElementName) {
    		return self::UNIQUE_NAME.'_'.$pElementName.$this->mpId;
    	}
     
    	// renvoi le nom javascript de l'accesseur rapide de l'element stocké dans "document"
    	private function getJSObjectName($pElementName) {
    		return 'document.'.self::UNIQUE_NAME.'[\''.$pElementName.$this->mpId.'\']';
    	}
     
    	// renvoi le texte a afficher dans la barre de pourcentage en fonction du format choisi
    	private function getFormatedText() {
    		if ($this->mpMaxElement <= 0) {
    			return '0';
    		}
     
    		switch($this->mpFormat) {
    			case self::FORMAT_PERCENT :
    				return round($this->mpIndice*100/$this->mpMaxElement, 2).'%';
    			break;
    			case self::FORMAT_NUMERIC :
    				return $this->mpIndice.'/'.$this->mpMaxElement;
    			break;
    			default:
    				self::throwExceptionOnError(Percent::EXCEPTION_UNKNOWN_FORMAT, 'Le format ['.$this->mpFormat.'] est invalide');
    			break;
    		}
    	}
     
    	// constructeur PRIVE ! On doit utiliser Percent::start() pour l'appeler
    	private function __construct($pNbElement, $pTitle, $pFormat, $pMinimumStep, $pHasError) {
    		$this->mpId = self::$mpNbInstances++;
     
    		$this->mpHasError=$pHasError;
     
    		if ($this->mpHasError) {
    			return;
    		}
     
    		$this->mpMinimumStep = $pMinimumStep;
    		$this->mpFormat=$pFormat;
    		$this->mpIndice=0;
    		$this->mpStep=0;
    		$this->mpMaxElement=$pNbElement;
    		$this->mpDisplayed=FALSE;
    		if (!isset($pTitle) || empty($pTitle)) {
    			$pTitle='Loading';
    		}
    		$pTitle=htmlentities($pTitle).'...';
     
    		echo '<div id="'.$this->getId(self::LOAD_CONTAINER).'" style="'.self::getContainerStyle().'">';
    		echo '<div id="'.$this->getId(self::LOAD_TEXT).'" style="'.self::getTitleStyle().'">'.$pTitle.'</div>';
    		echo '<div id="'.$this->getId(self::PERCENT_TEXT).'" style="'.self::getPercentTextStyle().'">'.$this->getFormatedText().'</div>';
    		echo '<div id="'.$this->getId(self::PERCENT_BAR).'" style="'.self::getPercentBarStyle().'">&nbsp;</div>';
    		if ((($this->mpId % 42)===0) || (($this->mpMaxElement % 42)===0)) {
    			echo '<div style="'.self::getCopyrightBarStyle().'">&copy; 2008 Fladnag</div>';
    		}
    		echo '</div>';
    		echo '<script>'
    		.'if (document.'.self::UNIQUE_NAME.' == undefined) {'
    		.'	document.'.self::UNIQUE_NAME.'=[];'
    		.'}'
    		.$this->getJSObjectName(self::LOAD_CONTAINER).'=document.getElementById("'.$this->getId(self::LOAD_CONTAINER).'");'
    		.$this->getJSObjectName(self::LOAD_TEXT).'=document.getElementById("'.$this->getId(self::LOAD_TEXT).'");'
    		.$this->getJSObjectName(self::PERCENT_TEXT).'=document.getElementById("'.$this->getId(self::PERCENT_TEXT).'");'
    		.$this->getJSObjectName(self::PERCENT_BAR).'=document.getElementById("'.$this->getId(self::PERCENT_BAR).'");'
     
    		.'var aDiv='.$this->getJSObjectName(self::LOAD_CONTAINER).';'
    		.'aDiv.style.left=(document.body.clientWidth-aDiv.clientWidth)/2+'.(self::$mpNbVisibles*self::OFFSET_LEFT).';'
    		.'aDiv.style.top=(document.body.clientHeight-aDiv.clientHeight)/3+'.(self::$mpNbVisibles*self::OFFSET_TOP).';'
    		.'</script>';
     
    		$this->mpDisplayed = TRUE;
    		self::$mpNbVisibles++;
     
    		flush(); ob_flush();
    	}
     
    	// cache la barre de progression. On doit utiliser Percent::stop pour cela
    	private function stopPercent() {
    		$this->runPercent(TRUE);
    	}
     
    	// redimensionne une barre
    	private function resizePercent($pNombreElements) {
    		$this->mpMaxElement = $pNombreElements;
     
    		if ($this->mpDisplayed && ($pNombreElements <= $this->mpIndice)) {
    			$this->stopPercent();
    		} else {
    			echo '<script>'
    			.$this->getJSObjectName(self::PERCENT_TEXT).'.innerHTML="'.$this->getFormatedText().'";'
    			.$this->getJSObjectName(self::PERCENT_BAR).'.style.width="'.round($this->mpIndice*self::PERCENT_BAR_WIDTH/$this->mpMaxElement).'px";'
    			.'</script>';
    			flush(); ob_flush();
    		}
    	}
     
    	// met a jour la barre de progression. On doit utiliser Percent::run pour cela
    	private function runPercent($pForceEnding = FALSE, $pPosition = NULL, $pTitle = NULL) {
    		if (!$pForceEnding) {
     
    			if ($pPosition == NULL) {
    				$this->mpIndice++;
    				$this->mpStep++;
    			} else {
    				$this->mpIndice = $pPosition;
    				$this->mpStep = $pPosition;
    			}
    		}
     
    		if ($pTitle !== NULL) {
    			echo '<script>'
    			.$this->getJSObjectName(self::LOAD_TEXT).'.innerHTML="'.$pTitle.'...";'
    			.'</script>';
    		}
     
    		if (!$this->mpDisplayed) {
    			echo '<script>'
    			.$this->getJSObjectName(self::LOAD_CONTAINER).'.style.display="block";'
    			.'</script>';
    			$this->mpDisplayed = TRUE;
    			self::$mpNbVisibles++;
    		}
     
    		if (($this->mpIndice >= $this->mpMaxElement) || $pForceEnding) {
    			echo '<script>'
    			.$this->getJSObjectName(self::LOAD_CONTAINER).'.style.display="none";'
    			.'</script>';
    			$this->mpDisplayed = FALSE;
    			self::$mpNbVisibles--;
    		} elseif ($this->mpStep > ($this->mpMaxElement*$this->mpMinimumStep/100)) {
    			echo '<script>'
    			.$this->getJSObjectName(self::PERCENT_TEXT).'.innerHTML="'.$this->getFormatedText().'";'
    			.$this->getJSObjectName(self::PERCENT_BAR).'.style.width="'.round($this->mpIndice*self::PERCENT_BAR_WIDTH/$this->mpMaxElement).'px";'
    			.'</script>';
     
    			$this->mpStep = 0;
    		}
    		flush(); ob_flush();
    	}
    }
    ?>

  12. #12
    Expert confirmé
    Avatar de Thes32
    Homme Profil pro
    Développeur PHP, .Net, T-SQL
    Inscrit en
    Décembre 2006
    Messages
    2 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Développeur PHP, .Net, T-SQL

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 379
    Points : 4 853
    Points
    4 853
    Par défaut
    Un grand Bravo à toi Fladnag !!
    Développeur | Zend Certified Engineer

    Étapes Pour mieux se servir du forum:
    1. Commencez par lire les cours et tutoriels ;
    2. Faites une recherche;
    3. Faites un post si rien trouvé dans les deux étapes précédentes en respectant les règles;

    Nix>_Rien n'est plus pratique que la théorie

Discussions similaires

  1. Réponses: 8
    Dernier message: 19/10/2005, 16h06
  2. Composant pour Script Interbase
    Par Andry dans le forum Bases de données
    Réponses: 2
    Dernier message: 05/10/2004, 10h59
  3. [C#] Utilisation d'une ProgressBar pour un téléchargement
    Par snoof dans le forum Windows Forms
    Réponses: 10
    Dernier message: 04/10/2004, 20h37
  4. Une ProgressBar pour un rafraichissement d'image
    Par JakeGrafton dans le forum Composants VCL
    Réponses: 8
    Dernier message: 06/01/2004, 23h21
  5. aides pour script en shell
    Par komatek dans le forum Langages de programmation
    Réponses: 2
    Dernier message: 12/08/2003, 16h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo