TUTOS.EU

Combobox filtrée dynamiquement avec pour source une requête SQL

Filtrer dynamiquement le contenu d'une combobox qui a été remplie via une requête SQL

Le principe

On a une requête SQL qui permet de remplir un tableau Javascript qui contient l'ensemble des valeurs à assigner à la combobox.

Ce tableau créé, avec une boucle Javascript on remplit la combobox avec les valeurs du tableau Javascript.

Ensuite, quand on entre du texte dans un champ de saisi, une fonction spécifique à ce champ récupère sa valeur et cela permet de filter le contenu de la combobox.

Cette fonction sait forcément de quel champ input cela provient vu que cette fonction lui est spécifique.

Du coup dans cette fonction on précise également quelle combobox on doit filter avec le contenu du champ input

Donc pour résumer, quand j'entre du texte dans mon champ input, sur keyup je récupère sa valeur et je filtre une combobox avec.

Pour chaque champ de saisi input, une fonction jquery spécifique récupère sa valeur et, dans cette même fonction, on défini le nom de la combobox à filtrer.

Comme déjà indiquée en première instance, la combobox a été remplie une première fois au chargement avec l'ensemble des valeurs du tableau Javasript.

Dès que l'on saisis quelquechose dans le champ input, la combobox est vidée puis reremplie avec le contenu du tableau javascript qui aura été au préalable filtré avec la valeur récupérée dans le champ input.

Choses à retenir pour faire fonctionner le principe :

Créer un tableau Javascript qui contient toutes les valeurs

En fin de page, remplir une première fois la combobox avec toutes les valeurs du tableau Javascript

Une fonction jQuery par champ input permet de déclencher une action pour un champ input

Dans cette fonction on définit le nom de la combobox à filtrer, on rappel le nom du champ inputbox et on indique le nom du tableau javascript qui contient les valeurs.

Le code en utilisant du jQuery

<!DOCTYPE html>
<HTML>
	<HEAD>
		<meta charset="utf-8" />
		<script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
		<style>
			.sectionArticle{
				margin: 10px;
			}
			
			.MyButton {
				margin: 2px 0;
				width:155px;
			}
		</style>
	</HEAD>

	<BODY>

		<div id="sectionArticle" class="sectionArticle">
			<!-- La liste qui va recevoir les éléments de la requête SQL. Notez bien l'ID -->
			<Select Name="Liste01" ID="Liste01">
				<!--<Option Selected></Option>-->
			</Select>
			<!-- Le champ de saisi qui va permettre de filtrer. -->
			<input type="text" id="TxtFenetreSaisie">
			</div>

		<SCRIPT TYPE="text/javascript">
		
			$(function() {

				$( "#TxtFenetreSaisie" ).keyup(function() {
				
					//Avec la valeur récupérée par le champ input, on va ici filtrer la combobox Liste01
					var ObjAFiltrer = $("#Liste01");
					var TxtAChercher = $("#TxtFenetreSaisie").val();
					var TabTableauAvecLesValeurs = TabMonCombo; // On défini ici le nom du tableau qui doit être utilisé et qui contient les valeurs à filtrer

					var varPosition = 0;
					var Compteur;

					//On vide la liste
					ObjAFiltrer.empty();

					//Si il y a un élément à trouver
					if (TxtAChercher.length > 0){
						for (var CompteurTableau in TabTableauAvecLesValeurs['text'])
						{
							varText = TabTableauAvecLesValeurs['text'][CompteurTableau];
							varValue = TabTableauAvecLesValeurs['value'][CompteurTableau];
							
							
							//Passage en minuscules
							varText = varText.toLowerCase();
							TxtAChercher = TxtAChercher.toLowerCase();

							var varPosition=varText.indexOf(TxtAChercher)							
							if (varPosition != -1){ //Si on a trouvé le caractère recherché
								varText = TabTableauAvecLesValeurs['text'][CompteurTableau];
								//alert(varText);
								//AjouterElement($ObjAFiltrer,varText,varValue);
								ObjAFiltrer.append($('<option></option>').val(varValue).html(varText));
							}
						}
					
					}
					else{ //Si il n'y a rien à trouver, on remet toutes les valeurs dans la combobox
						for (var CompteurTableau in TabTableauAvecLesValeurs['value'])
						{
								//AjouterElement($ObjAFiltrer,TabTableauAvecLesValeurs['text'][CompteurTableau],TabTableauAvecLesValeurs['value'][CompteurTableau]);
								varText = TabTableauAvecLesValeurs['text'][CompteurTableau];
								varValue = TabTableauAvecLesValeurs['value'][CompteurTableau];
								ObjAFiltrer.append($('<option></option>').val(varValue).html(varText));
						}				
					}
				});

			});				
		
		</SCRIPT>

<?php

	define("SQLServerName","NomServeurMySQL");
	define("sqldbname","NomBaseDeDonnees");
	define("sqllogin","LoginSQL");
	define("sqlpass","MotDePasseSQL");

	
	function ConvertMySQLRequestToJavascriptArray($Resultat,$NomTableauJavaScript,$CreerBalisesJavaScript)
	{
		//Version du 22 fevrier 2013
		//Fonction créer un tableau JavaScript à partir d'un jeu d'enregistrement SQL passé en paramètres.
		//La connexion à la base de données et la requête SQL a donc déjà été envoyée au préalable à la base de données.

		//Récupération d'informations sur les champs
		//http://php.net/manual/en/function.mysql-fetch-field.php
		$CompteurChamp = 0;

		if ($CreerBalisesJavaScript == 1){
			echo "<SCRIPT TYPE=\"text/javascript\">\n";
		}

		echo "//Création du tableau JavaScript\n";
		echo $NomTableauJavaScript."=new Array();\n";
		echo "\n";
		
		//Création du tableau PHP qui va contenir les noms des champs de la requêtes SQL
		while ($CompteurChamp < mysql_num_fields($Resultat)) {
			$meta = mysql_fetch_field($Resultat, $CompteurChamp);
			if (!$meta) {
				//echo "No information available<br />\n";
			}
			//echo "$meta->name<br />";
			$ChampsDeLaRequeteSQL[$CompteurChamp] = $meta->name;
			$CompteurChamp++;
		}

		//Création des différents champs dans le tableau en JavaScript
		echo "//Création des différents champs du tableau JavaScript\n";
		$count = count($ChampsDeLaRequeteSQL);
		for ($CompteurChampsDeLaRequete = 0; $CompteurChampsDeLaRequete < $count; $CompteurChampsDeLaRequete++) {
			//echo $ChampsDeLaRequeteSQL[$CompteurChampsDeLaRequete]."\n";
			echo $NomTableauJavaScript."['".$ChampsDeLaRequeteSQL[$CompteurChampsDeLaRequete]."']=new Array();\n";
		}
		echo "\n";

		mysql_data_seek($Resultat, 0); //On revient au début de l'enregistrement
		$CompteurResultats = 1; //Initialisation
		echo "//Copie des valeurs dans les différents champs du tableau JavaScript\n";
		while ($MaLigne=mysql_fetch_array($Resultat, MYSQL_ASSOC)){
			for ($CompteurChampsDeLaRequete = 0; $CompteurChampsDeLaRequete < $count; $CompteurChampsDeLaRequete++) {
				$line = $MaLigne[$ChampsDeLaRequeteSQL[$CompteurChampsDeLaRequete]];
				if (mb_detect_encoding($line, 'UTF-8', true) === false) {$line = utf8_encode($line);}
				//htmlspecialchars avec le paramètre ENT_COMPAT est essentiel. En effet on affecte une valeur, par exemple Ma_valeur, au tableau javascript ainsi :
				//MonTableauJava['macle'] = "Ma_valeur"; Mais si Ma_valeur contient un double quote alors cela fait bugger le code avec une affectation du style
				//MonTableauJava['macle'] = "Ma_"valeur"";
				$line = htmlspecialchars ($line, ENT_COMPAT, 'UTF-8');
				echo $NomTableauJavaScript."['".$ChampsDeLaRequeteSQL[$CompteurChampsDeLaRequete]."'][".$CompteurResultats."] = \"".$line."\";\n";
			}
			$CompteurResultats++;
		}

		if ($CreerBalisesJavaScript == 1){
			echo "</SCRIPT>\n";
		}		

		/* Types de méta possibles :
		blob:         $meta->blob
		max_length:   $meta->max_length
		multiple_key: $meta->multiple_key
		name:         $meta->name
		not_null:     $meta->not_null
		numeric:      $meta->numeric
		primary_key:  $meta->primary_key
		table:        $meta->table
		type:         $meta->type
		unique_key:   $meta->unique_key
		unsigned:     $meta->unsigned
		zerofill:     $meta->zerofill
		*/
	}
	
	echo "<SCRIPT TYPE=\"text/javascript\">\n";
	echo "//Scripts JavaScripts qui doivent être exécuté à la fin sinon des éléments nécessaires ne sont pas encore chargés\n";
	echo "//Exemple : des Combobox\n";

	//Pour la liste déroulante des mots clés
		//On passe ici une requête SQL dont les résultats seront stockés dans un tableau JavaScript. Ce tableau remplira ensuite une ComboBox.
		//Comme la requête est destinée à remplir une combobox dont les résultats seront ensuite filtrée via une fonction JavaScript nommée FiltrerCombo(),
		//alors la requête SQL ne doit comporter que 2 champs nommés [text] et [value]
		//(Regardez le contenu de la fonction FiltrerCombo() et vous verrez qu'elle appelle un tableau avec 2 champs nommés text et value). C'est elle qui fixe cette contrainte.
		$sqlrequest = "SELECT CONCAT(Champ01, ' : ', Champ02, ' / ', Champ03) as text, Champ04 as value FROM NomTable order by Champ01";

		$MaConnection = mysql_connect(constant('SQLServerName'),constant('sqllogin'),constant('sqlpass'));
		mysql_select_db(constant('sqldbname'), $MaConnection);
		mysql_query("SET NAMES UTF8"); //On utilise le codage UTF8
		$Resultat = mysql_query($sqlrequest, $MaConnection);
		if (!$Resultat) {die('Erreur sur la requête : ' . mysql_error());}
		else{ // Si la requête est bien passée
			$num_rows = mysql_num_rows($Resultat);
			if ($num_rows > 0){
				ConvertMySQLRequestToJavascriptArray($Resultat,"TabMonCombo",0); //Appel de la fonction qui va créer un tableau Javascript avec le résultat de la requête SQL
			
				//Création de la fonction jQuery qui va remplir la combobox avec le contenu du tableau JavaScript		
				echo "	$(function() {\n";
				echo "		var objComboBox = $(\"#Liste01\");\n";
				echo "		for (var Compteur in TabMonCombo['text'])\n";
				echo "		{\n";
				echo "			varText = TabMonCombo['text'][Compteur];\n";
				echo "			varValue = TabMonCombo['value'][Compteur];\n";
				echo "			objComboBox.append($('<option></option>').val(varValue).html(varText));\n";
				echo "		}\n";
				echo "	});\n";
			}		
		}
			
	echo "</SCRIPT>\n";	
	
?>		
		
	</BODY>
</HTML>
Lien vers le fichier : cliquez ici

Un code plus ancien et plus complexe qu'il vaut mieux abandonner au profit du premier

<!DOCTYPE html>
<HTML>
	<HEAD>
		<meta charset="utf-8" />
		<style>
			.sectionArticle{
				margin: 10px;
			}
			
			.MyButton {
				margin: 2px 0;
				width:155px;
			}
		</style>
	</HEAD>

	<BODY>

		<div id="sectionArticle" class="sectionArticle">
			<!-- La liste qui va recevoir les éléments de la requête SQL. Notez bien l'ID -->
			<Select Name="Liste01" ID="Liste01">
				<!--<Option Selected></Option>-->
			</Select>
			<!-- Le champ de saisi qui va permettre de filtrer. Passez y en paramètre 1) Le tableau qui contient les éléments de la Combobox 2) l'ID de la liste ci-dessus 3) Le nom de la balise input -->
			<input type="text" id="TxtFenetreSaisie" onkeyup="FiltrerCombo(TabMonCombo, 'Liste01','TxtFenetreSaisie');">
			</div>

		<SCRIPT TYPE="text/javascript">

			function recupValeurElement(IdElement)
			{
				if (document.getElementById)
				{
					return document.getElementById(IdElement);
				}
				else if (document.all)
				{
					return document.all[IdElement];
				}
			}

			function FiltrerCombo(TabMonCombo, $ElemAFilter,$ElemARechercher){

				var ObjAFiltrer = recupValeurElement($ElemAFilter);
				var TxtAChercher = recupValeurElement($ElemARechercher).value;
				var varPosition = 0;
				var Compteur;

				//On vide la liste
				ObjAFiltrer.length = 0;

				//Si il y a un élément à trouver
				if (TxtAChercher.length > 0){
					for (var CompteurTableau in TabMonCombo['text'])
					{
						UneValeur = TabMonCombo['text'][CompteurTableau];
						
						//Passage en minuscules
						UneValeur = UneValeur.toLowerCase();
						TxtAChercher = TxtAChercher.toLowerCase();
						//alert(UneValeur);

						varPosition = InStr(UneValeur,TxtAChercher,0);
						if (varPosition != -1){ //Si on a trouvé le caractère recherché
							AjouterElement($ElemAFilter,TabMonCombo['text'][CompteurTableau],TabMonCombo['value'][CompteurTableau]);
						}
					}
				
				}
				else{ //Si il n'y a rien à trouver, on remet toutes les valeurs dans la combobox
					for (var CompteurTableau in TabMonCombo['value'])
					{
							AjouterElement($ElemAFilter,TabMonCombo['text'][CompteurTableau],TabMonCombo['value'][CompteurTableau]);
					}				
				}
			}

			function InStr(varMaChaineDeCarac, CaracRecherche, PositionDebutRecherche)
			{

				var varPosition = 0;
			
				varPosition = varMaChaineDeCarac.indexOf(CaracRecherche, PositionDebutRecherche);

				/*
				if (varPosition != -1){ //Si on a trouvé le caractère recherché
					varMaChaineDeCarac = varMaChaineDeCarac.substring(0, varPosition); //On prend tout ce qui est avant
				}
				*/

				return varPosition; //On retourne le résultat				

			}

			function AjouterElement($IdElementSource,TextAAjouter,ValueAAjouter){

				MaListe = recupValeurElement($IdElementSource);

				var ElemAAjouter = document.createElement('option');
				ElemAAjouter.text = TextAAjouter;
				ElemAAjouter.value = ValueAAjouter;

				try {
					MaListe.add(ElemAAjouter, null); // standards compliant; doesn't work in IE
				}
				catch(ex) {
					MaListe.add(ElemAAjouter); // IE only
				}

			}
			
		</SCRIPT>

		
<?php


	define("SQLServerName","NomServeurMySQL");
	define("sqldbname","NomBaseDeDonnees");
	define("sqllogin","LoginSQL");
	define("sqlpass","MotDePasseSQL");
	
	function ConvertMySQLRequestToJavascriptArray($Resultat,$NomTableauJavaScript,$CreerBalisesJavaScript)
	{
		//Version du 22 fevrier 2013
		//Fonction créer un tableau JavaScript à partir d'un jeu d'enregistrement SQL passé en paramètres.
		//La connexion à la base de données et la requête SQL a donc déjà été envoyée au préalable à la base de données.

		//Récupération d'informations sur les champs
		//http://php.net/manual/en/function.mysql-fetch-field.php
		$CompteurChamp = 0;

		if ($CreerBalisesJavaScript == 1){
			echo "<SCRIPT TYPE=\"text/javascript\">\n";
		}

		echo "//Création du tableau JavaScript\n";
		echo $NomTableauJavaScript."=new Array();\n";
		echo "\n";
		
		//Création du tableau PHP qui va contenir les noms des champs de la requêtes SQL
		while ($CompteurChamp < mysql_num_fields($Resultat)) {
			$meta = mysql_fetch_field($Resultat, $CompteurChamp);
			if (!$meta) {
				//echo "No information available<br />\n";
			}
			//echo "$meta->name<br />";
			$ChampsDeLaRequeteSQL[$CompteurChamp] = $meta->name;
			$CompteurChamp++;
		}

		//Création des différents champs dans le tableau en JavaScript
		echo "//Création des différents champs du tableau JavaScript\n";
		$count = count($ChampsDeLaRequeteSQL);
		for ($CompteurChampsDeLaRequete = 0; $CompteurChampsDeLaRequete < $count; $CompteurChampsDeLaRequete++) {
			//echo $ChampsDeLaRequeteSQL[$CompteurChampsDeLaRequete]."\n";
			echo $NomTableauJavaScript."['".$ChampsDeLaRequeteSQL[$CompteurChampsDeLaRequete]."']=new Array();\n";
		}
		echo "\n";

		mysql_data_seek($Resultat, 0); //On revient au début de l'enregistrement
		$CompteurResultats = 1; //Initialisation
		echo "//Copie des valeurs dans les différents champs du tableau JavaScript\n";
		while ($MaLigne=mysql_fetch_array($Resultat, MYSQL_ASSOC)){
			for ($CompteurChampsDeLaRequete = 0; $CompteurChampsDeLaRequete < $count; $CompteurChampsDeLaRequete++) {
				$line = $MaLigne[$ChampsDeLaRequeteSQL[$CompteurChampsDeLaRequete]];
				if (mb_detect_encoding($line, 'UTF-8', true) === false) {$line = utf8_encode($line);}
				//htmlspecialchars avec le paramètre ENT_COMPAT est essentiel. En effet on affecte une valeur, par exemple Ma_valeur, au tableau javascript ainsi :
				//MonTableauJava['macle'] = "Ma_valeur"; Mais si Ma_valeur contient un double quote alors cela fait bugger le code avec une affectation du style
				//MonTableauJava['macle'] = "Ma_"valeur"";
				$line = htmlspecialchars ($line, ENT_COMPAT, 'UTF-8');
				echo $NomTableauJavaScript."['".$ChampsDeLaRequeteSQL[$CompteurChampsDeLaRequete]."'][".$CompteurResultats."] = \"".$line."\";\n";
			}
			$CompteurResultats++;
		}

		if ($CreerBalisesJavaScript == 1){
			echo "</SCRIPT>\n";
		}		

		/* Types de méta possibles :
		blob:         $meta->blob
		max_length:   $meta->max_length
		multiple_key: $meta->multiple_key
		name:         $meta->name
		not_null:     $meta->not_null
		numeric:      $meta->numeric
		primary_key:  $meta->primary_key
		table:        $meta->table
		type:         $meta->type
		unique_key:   $meta->unique_key
		unsigned:     $meta->unsigned
		zerofill:     $meta->zerofill
		*/
	}
	
	echo "<SCRIPT TYPE=\"text/javascript\">\n";
	echo "//Scripts JavaScripts qui doivent être exécuté à la fin sinon des éléments nécessaires ne sont pas encore chargés\n";
	echo "//Exemple : des Combobox\n";

	//Pour la liste déroulante des mots clés
		//On passe ici une requête SQL dont les résultats seront stockés dans un tableau JavaScript. Ce tableau remplira ensuite une ComboBox.
		//Comme la requête est destinée à remplir une combobox dont les résultats seront ensuite filtrée via une fonction JavaScript nommée FiltrerCombo(),
		//alors la requête SQL ne doit comporter que 2 champs nommés [text] et [value]
		//(Regardez le contenu de la fonction FiltrerCombo() et vous verrez qu'elle appelle un tableau avec 2 champs nommés text et value). C'est elle qui fixe cette contrainte.
		$sqlrequest = "SELECT CONCAT(Champ01, ' : ', Champ02, ' / ', Champ03) as text, Champ04 as value FROM NomTable order by Champ01";

		$MaConnection = mysql_connect(constant('SQLServerName'),constant('sqllogin'),constant('sqlpass'));
		mysql_select_db(constant('sqldbname'), $MaConnection);
		mysql_query("SET NAMES UTF8"); //On utilise le codage UTF8
		$Resultat = mysql_query($sqlrequest, $MaConnection);
		if (!$Resultat) {die('Erreur sur la requête : ' . mysql_error());}
		else{ // Si la requête est bien passée
			$num_rows = mysql_num_rows($Resultat);
			if ($num_rows > 0){
				ConvertMySQLRequestToJavascriptArray($Resultat,"TabMonCombo",0); //Appel de la fonction
				echo "for (var Compteur in TabMonCombo['text'])\n";
				echo "{\n";
					echo "AjouterElement('Liste01',TabMonCombo['text'][Compteur],TabMonCombo['value'][Compteur]);\n";
				echo "}\n";
			}		
		}
			
	echo "</SCRIPT>\n";	

?>		
		
	</BODY>
</HTML>
Lien vers le fichier : cliquez ici

Notes sur l'utilisation du code plus ancien