Afficher les résultats d'une recherche sans recharger la pag

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

03 juil. 2007, 16:22

Regarde l'exemple qui va suivre, c'est de la magie Dom HTML, ça respecte le standard et marche donc sur la majorité si c'est pas tous les navigateurs. Mais dépond de javascript.

C'est pour créer dynamiquement des balises, les positionner, les remplir etc... C'est simple:
[Edité]

Code : Tout sélectionner

<p><button id="b1" onClick="créerDiv('div_1', 'je suis un div, tralala!', 'avant', document.getElementById('b1'));" >Créer Div avant</button></p> <p><button id="b2" onClick="créerDiv('div_1', 'je suis un div, tralala!', 'après', document.getElementById('b2'));" >Créer Div après</button></p> <p><button id="b2" onClick="créerDiv('div_1', 'je suis un div, tralala!', 'après', null);" >Créer Div à la fin du document</button></p> <script> function créerDiv(id_donné, contenu_donné, avant_ou_après, emplacement_donné){ // crée un nouveau div var div = document.createElement("div"); // fixer l'id div.setAttribute("id", id_donné); // placer son contenu var contenu = document.createTextNode(contenu_donné); div.appendChild(contenu); // insère le div avant_ou_après l'emplacement donné if (avant_ou_après == 'avant' && emplacement_donné!=null) emplacement_donné.parentNode.insertBefore(div, emplacement_donné); else if (emplacement_donné!=null) emplacement_donné.parentNode.insertBefore(div, emplacement_donné.nextSibling); else document.body.insertBefore(div, document.body.nextSibling); //retourne la référence du div créé return div; } </script>
Cette fonction javascript pourrait t'inspirer pour céer tes divs de réponse dans la boucle où tu appelle Ajax, comme ça à chaque appel Ajax un div réponse.

Inspiré de la Source: http://developer.mozilla.org/fr/docs/DO ... sertBefore
Modifié en dernier par sadeq le 04 juil. 2007, 13:35, modifié 5 fois.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Mammouth du PHP | 536 Messages

03 juil. 2007, 16:32

oula !
Je dois éxecuter cette fonction dans ma page de formulaire ou dans la page qui va afficher le résultat ?
Un prof désespéré à son élève :
- Et maintenant, dessinez-moi un cercle au tableau... Voila... Alors qu'est-ce que c'est?
- Ben un cercle ?
- Non, c'est votre note, sortez !!

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

03 juil. 2007, 16:39

Réfléchis, dans la page formulaire là où t'as ton div "ajax".
Mais il faut réfléchir plus sur comment tu comptes l'utiliser dans ta boucle for qui appelle les getByAjax().

Mais il faut travailler doucement, d'abord il faut la tester comme elle est dans une page à part et si t'as compris le fonctionnement c'est la fonction seulement qui nous intéresse, tu l'intégre dans ton programme.
Mais il n'est pas question de la copier sans savoir la remanier. Si t'as pas compris laisse tombée cette solution.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Mammouth du PHP | 536 Messages

03 juil. 2007, 16:55

non je l'ai testé, j'ai bien compris.

Il va me rajouter une balise <div> à chaque fois qu'il va trouver une réponse à ma requête.

Je vois bien le fonctionnement de la fonction.

Seulement, je n'arrive pas à récupérer la valeur des variables dans mon premier fichier search-engine.php (celui où il y a mon formulaire) que j'obtiens après avoir examiner mes fichiers xml dans ma deuxieme page result-request.php.

Tu comprends ce que je veux dire ?

En fait, j'envoi des info de ma première page à ma deuxième page, mais il faudrait que je puisse envoyer des infos de ma seconde à ma première pour afficher les résultats
Un prof désespéré à son élève :
- Et maintenant, dessinez-moi un cercle au tableau... Voila... Alors qu'est-ce que c'est?
- Ben un cercle ?
- Non, c'est votre note, sortez !!

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

03 juil. 2007, 17:09

C'est ajax qui le fais par la fonction getByAjax(). Il me semblais qu'on dépassé la phase de correction des données par Ajax et tu as dis que ça marchait. :lol:
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Mammouth du PHP | 536 Messages

03 juil. 2007, 17:19

ca marchait oui, mais comme tu l'as deviné, ca marchait sans vraiment marcher car les dernières données trouvées écrasaient les plus anciennes.

Je vais regarder ta fonction ce soir et voir comment l'appliquer.

[EDIT] Bon j'ai regardé la fonction ce matin et hier soir, mais je ne vois pas comment l'appliquer (même si je cmprends comment elle marche) et je ne vois pas où l'appliquer et comment récupérer le contenu qu'on souhaite afficher.
Un prof désespéré à son élève :
- Et maintenant, dessinez-moi un cercle au tableau... Voila... Alors qu'est-ce que c'est?
- Ben un cercle ?
- Non, c'est votre note, sortez !!

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

06 juil. 2007, 02:25

Voici la solution la plus simple, utiliser le même div de réponse mais en y cumulant les réponses Ajax.
L'astuce est de modifier la ligne suivante dans la fonction ajax d'appel "getByAjax"

Code : Tout sélectionner

if(xhr.readyState == 4 && xhr.status == 200){ reponse.innerHTML += xhr.responseText; //Ecrit la réponse du serveur }
Remarques le += qui fait le cumul des réponses reçues par Ajax dans le même conteneur reponse.

Le formulaire Ajax:
<script>
          /** 
         * Moteur Ajax 
         */       
         function getXhr(){ 
            var xhr = null; 
            if(window.XMLHttpRequest) // Firefox et autres 
               xhr = new XMLHttpRequest(); 
            else if(window.ActiveXObject){ // Internet Explorer 
               try { 
                         xhr = new ActiveXObject("Msxml2.XMLHTTP"); 
                     } catch (e) { 
                         xhr = new ActiveXObject("Microsoft.XMLHTTP"); 
                     } 
            } 
            else { // XMLHttpRequest non supporté par le navigateur 
               alert("Votre navigateur ne supporte pas les objets XMLHTTPRequest..."); 
               xhr = false; 
            } 
          return xhr; 
         } 
          
          /** 
         * Méthode qui appelle un script serveur et renvoit sa réponse
         * 
         * serveur: l'url du script serveur appelé
         * reponse: objet devant recevoir la réponse Ajax
         * paramètres: liste des paramètres éventuellement passés au script serveur (param1=valeur1&param2=valeur2...)
         */
         function getByAjax(serveur, reponse, parametres){ 
           var xhr = getXhr(); //Nouvelle instance Ajax
           if (xhr && serveur){
            // On défini la fonction observant la communication Ajax/serveur 
            xhr.onreadystatechange = function(){ 
               // le code 4/200: détermine que Ajax a reçu une réponse du serveur 
               if(xhr.readyState == 4 && xhr.status == 200){ 
                  reponse.innerHTML += xhr.responseText;  //Ecrit la réponse du serveur
               } 
            } 

            // Déclenchement de l'appel Ajax/serveur (avec passage de paramètres en POST)
            xhr.open("POST" ,serveur ,true); 
            xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); 
            xhr.send(parametres); 
           }
        }
//Cette fonction envoit plusieurs posts au serveur de recherches via ajax et reçoit plusieurs réponses
function AfficheResult() {
  ////vider le div de reponse avant de lancer la recherche
  document.getElementById('div_reponse').innerHTML = ""; 
  
  //Elements du form à traiter
  var critInputs = document.criteria.elements;
  var myInput; 
  for ( var i = 0 ; i < critInputs.length ; i++ ) {
     myInput = critInputs[i]; 
	 
	//traiter seulement les checkbox cochées
    if ( myInput.type == 'checkbox' && myInput.checked ) {
	
	  //Déterminer les paramètres de recherche id_cat et id_crit (seront envoyés par Post via Ajax)
      var explode = myInput.value.split('/');
      var id_cat = explode[0];
      var id_crit = explode[1];
	  var post_params = "cat=" + id_cat + "&crit=" + id_crit;
	   
	  //Envoit le postage au serveur de recherche via Ajax et attend la réponse
      getByAjax('result-request.php', document.getElementById('div_reponse'), post_params);
    }
  }  
}

</script>
<?php 
echo "<br /><br />Choose the different criteria which correspond to your request : ";
/*---------------------------------*/
//on ouvre le fichier criteria.xml
if (!$cfg['ressources_root']) $cfg['ressources_root'] = ".";
$criteriaFile = $cfg['ressources_root'].'/criteria.xml';
$domCriteria = new DOMDocument('1.0','UTF-8');
$domCriteria->load($criteriaFile);
$xpCriteria = new DOMXPath($domCriteria);
$cat_criteria = $domCriteria->getElementsByTagName('cat');
$result_find_criteria = $domCriteria->getElementsByTagName('criteria');

echo "<form name='criteria' method='post'>"; 

echo "<table align='center'><tr>";
foreach($cat_criteria as $cat){
  $name_cat = $cat->getAttribute('name');
  $id_cat = $cat->getAttribute('id');
  echo "<td valign='top'><br /><strong>".$name_cat." : </strong>";
  foreach ($cat->childNodes as $criteria)
  {
    if ($criteria->nodeType != XML_ELEMENT_NODE) continue;
    if ($criteria->tagName == 'criteria')
    {
      $name_criteria = $criteria->getAttribute('name');
      $id_criteria = $criteria->getAttribute('id');      
      echo "<ul><input type='checkbox' id='crit[]' name='crit[]' value='$id_cat/$id_criteria'>$name_criteria</input></ul>";
    }
  }
}
echo "</tr></table>";

?>
<div align="center"><input type="button" onClick="AfficheResult();" value="Search (Ajax)" /></div>
</form>
<p>Result</p>
<div id="div_reponse"></div>
Et pour ceux qui nous lisent et qui veulent tester:

La page de recherche: result-request.php
<?php 
/*-----------------------------------------------------*/
//on affiche le résultat en fonction d'un seul critère //
/*-----------------------------------------------------*/
if (!$cfg['ressources_root']) $cfg['ressources_root'] = ".";
$link_file = $cfg['ressources_root'].'/matrix/criteria-practice.xml';
$xml = simplexml_load_file($link_file);//on ouvre le fichier xml

//on vérifie l'existence des varaibles passées par le formulaire si elles n'existent pas, on meur affecte une valeur vide
if (!isset($_POST['cat'])) { $_POST['cat'] = ''; }
if (!isset($_POST['crit'])) { $_POST['crit'] = ''; }

//si les variables ne sont pas vides
if ( ($_POST['cat'] != '') or ($_POST['crit'] != '') )
{
  $id_practice = null;
  foreach($xml->link as $value)
  {
  	foreach($value->criteria as $criteria)
  	{	 
  		if( trim($criteria->idcat)==trim($_POST['cat']) and trim($criteria->idcrit) == trim($_POST['crit']) )
     	{
          $id_practice = $criteria->practice->id;
          break;
     	}
	}
  }
  if ( (isset($id_practice)) and ($id_practice != '') ) // si $id_practice est trouvé
  { 
    //on ouvre le document xml qui correspond à la recherche
    $practiceFile = $cfg['ressources_root'].'/content/practice/'.$id_practice.'.xml';
    $domPractice = new DOMDocument('1.0','UTF-8');
    $domPractice->load($practiceFile);
    $xpPractice = new DOMXPath($domPractice);
    $item_practice = $domPractice->getElementsByTagName('item');


    foreach ($item_practice as $item) 
    {
      foreach ($item->childNodes as $child)
      {
        if($child->nodeType != XML_ELEMENT_NODE) continue;
        if($child->tagName == 'title')
        {
          $titre = utf8_decode($child->firstChild->nodeValue);
        }
        elseif ($child->tagName == 'short_description')
        {
          $short_description = utf8_decode($child->firstChild->nodeValue);
        }
      }
      $msg = "<p>$titre<br/>$short_description</p>";
    }
  }
  else
  { 
    $msg = "<p>There is no practice which corresponds to your request. Please refine your search</p>";
  }
}  
else
  { 
    $msg = "<p>Choose your crireria before starting your search</p>";
  }
echo $msg;
?> 
Et les fichiers XML de test:

criteria.xml (contenant les critères de recherche)

Code : Tout sélectionner

<doc> <cat name="name_cat_1" id="id_cat_1"> <criteria name="name_criteria_1.1" id="id_criteria_1.1" /> <criteria name="name_criteria_1.2" id="id_criteria_1.2" /> <criteria name="name_criteria_1.3" id="id_criteria_1.3" /> </cat> <cat name="name_cat_2" id="id_cat_2"> <criteria name="name_criteria_2.1" id="id_criteria_2.1" /> <criteria name="name_criteria_2.2" id="id_criteria_2.2" /> <criteria name="name_criteria_2.3" id="id_criteria_2.3" /> </cat> <cat name="name_cat_3" id="id_cat_3"> <criteria name="name_criteria_3.1" id="id_criteria_3.1" /> <criteria name="name_criteria_3.2" id="id_criteria_3.2" /> <criteria name="name_criteria_3.3" id="id_criteria_3.3" /> </cat> </doc>
matrix/criteria-practice.xml (contenant les liens entre critères et les "practice" recherchés)

Code : Tout sélectionner

<doc> <link> <criteria> <idcat>id_cat_1</idcat> <idcrit>id_criteria_1.1</idcrit> <practice><id>id_practice_1</id></practice> </criteria> <criteria> <idcat>id_cat_1</idcat> <idcrit>id_criteria_1.2</idcrit> <practice><id>id_practice_2</id></practice> </criteria> <criteria> <idcat>id_cat_1</idcat> <idcrit>id_criteria_1.3</idcrit> <practice><id>id_practice_3</id></practice> </criteria> </link> <link> <criteria> <idcat>id_cat_2</idcat> <idcrit>id_criteria_2.1</idcrit> <practice><id>id_practice_4</id></practice> </criteria> <criteria> <idcat>id_cat_2</idcat> <idcrit>id_criteria_2.2</idcrit> <practice><id>id_practice_5</id></practice> </criteria> <criteria> <idcat>id_cat_2</idcat> <idcrit>id_criteria_2.3</idcrit> <practice><id>id_practice_6</id></practice> </criteria> </link> <link> <criteria> <idcat>id_cat_3</idcat> <idcrit>id_criteria_3.1</idcrit> <practice><id>id_practice_7</id></practice> </criteria> <criteria> <idcat>id_cat_3</idcat> <idcrit>id_criteria_3.2</idcrit> <practice><id>id_practice_8</id></practice> </criteria> <criteria> <idcat>id_cat_3</idcat> <idcrit>id_criteria_3.3</idcrit> <practice><id>id_practice_9</id></practice> </criteria> </link> </doc>
Et finalement des fichiers "practice" qu'on recherche par les critères
exemple:
content/practice/id_practice_1.xml

Code : Tout sélectionner

<item> <title>Practice 1</title> <short_description>Short description of Practice 1</short_description> </item>
content/practice/id_practice_2.xml

Code : Tout sélectionner

<item> <title>Practice 2</title> <short_description>Short description of Practice 2</short_description> </item>
etc... jusqu'à 9 pour cet exemple
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Mammouth du PHP | 536 Messages

06 juil. 2007, 09:14

oui j'avais fais ça en fait. J'avais pas utilisé la syntaxe += mais j'avais tout récris du genre x = x + y;

Voilà, merci bien en tout cas.

Dernière petite question, comment peut-on faire pour que le message de résultat ne soit afficher qu'une fois si j'amais il y a plusieurs critères qui n'ont pas de résultats. Et comment faire pour que ce message n'apparaisse pas si il y a au moins un résultat ?
Un prof désespéré à son élève :
- Et maintenant, dessinez-moi un cercle au tableau... Voila... Alors qu'est-ce que c'est?
- Ben un cercle ?
- Non, c'est votre note, sortez !!

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

06 juil. 2007, 10:21

Dans ce cas tu dois gérer les messages du côté de la procédure Ajax et non du côté du serveur de recherche.
C'est à dire que ton programme de recherche ne doit plus afficher les messages d'echec mais simplement les données trouvées. Et c'est au récepteur (le programme Ajax du formulaire) de compter le nombre de données reçues et cumulées dans le div_reponse. Si ce nombre est >0 c'est bon il y a des résultats sinon le résultat est vide et donc afficher le message d'echec.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Mammouth du PHP | 536 Messages

06 juil. 2007, 10:42

dernières nouvelles : changement de programme ! j'adore les changements quand on est en plein développement.
Le client veut en fait que ce soit un ET la recherche. C'est à dire, que les critères sélectionnés doivent être les critères d'une seule practice.
Comment puis-je alors adapter ce code ?
Un prof désespéré à son élève :
- Et maintenant, dessinez-moi un cercle au tableau... Voila... Alors qu'est-ce que c'est?
- Ben un cercle ?
- Non, c'est votre note, sortez !!

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

06 juil. 2007, 11:00

T'as pas regardé La page de recherche: result-request.php que j'ai postée dernièrement, elle est différente de la tienne car elle fait justement un ET de idcat et idcrit, donc elle cherche 1 et 1 seul practice par idcat/idcrit.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Mammouth du PHP | 536 Messages

06 juil. 2007, 11:19

oui j'ai vu, d'ailleurs il doit y avoir une erreur car à chaque fois il me dit qu'il n'y a pas de résultats qui correspondent à ma requête.

Mais en fait, là désormais, une practice peut correspondre à plusieurs critères.
C'est à dire que une practice peut être définie par plusieurs critères.

Exemple, lorsqu'une practice est soumise, on choisit à quels critères elle va être associée. Elle peut en avoir plusierus comme ceci :

Code : Tout sélectionner

<link id="1"> <criteria idcat="1" idcrit="3"/> <criteria idcat="2" idcrit="1"/> <practice id="2"/> </link>
Il faut alors pour trouver cette practice, que l'utilisateur coche les critères 3 de la première catégorie ET le critère 1 de la 2eme catégrie uniquement. S'il clique sur un troisième critère, la practice ne s'affichera pas c'est à dire qu'on aura pas de résultat.

Tu comprends ? Et donc, j'aurais voulu savoir comment adapter le code qu'on a fait ensemble jusqu'à présent pour ceci.
Un prof désespéré à son élève :
- Et maintenant, dessinez-moi un cercle au tableau... Voila... Alors qu'est-ce que c'est?
- Ben un cercle ?
- Non, c'est votre note, sortez !!

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

06 juil. 2007, 13:11

Je suis d'accord, mais il suffit d'enlever le break; dans la boucle de recherce xml, de transformer $id_practice en tableau pour mémoriser toutes les occurences répondants, comme ça:
$id_practice[] = $criteria->practice->id;
En suite, parcourir ce tableau pour extraire et afficher un par un les infos practice.

Ceci sans démolir l'ensemble du mécanisme.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Invité
Invité n'ayant pas de compte PHPfrance

06 juil. 2007, 14:00

voilà ce que j'ai alors fais, comme tu as expliqué :
<?php 
/*-----------------------------------------------------*/
//on affiche le résultat en fonction d'un seul critère //
/*-----------------------------------------------------*/
if (!$cfg['ressources_root']) $cfg['ressources_root'] = ".";
$link_file = $cfg['ressources_root'].'/matrix/criteria-practice.xml';
$xml = simplexml_load_file($link_file);//on ouvre le fichier xml

//on vérifie l'existence des varaibles passées par le formulaire si elles n'existent pas, on meur affecte une valeur vide
if (!isset($_POST['cat'])) { $_POST['cat'] = ''; }
if (!isset($_POST['crit'])) { $_POST['crit'] = ''; }

//si les variables ne sont pas vides
if ( ($_POST['cat'] != '') or ($_POST['crit'] != '') )
{
  $id_practice = null;
  foreach($xml->link as $value)
  {
      foreach($value->criteria as $criteria)
      {     
          if( trim($criteria->idcat)==trim($_POST['cat']) and trim($criteria->idcrit) == trim($_POST['crit']) )
         {
          $id_practice[] = $criteria->practice->id;
          //break;
         }
    }
  }
  if ( (isset($id_practice)) and ($id_practice != '') ) // si $id_practice est trouvé
  { 
    //on ouvre le document xml qui correspond à la recherche
    $practiceFile = $cfg['ressources_root'].'/content/practice/'.$id_practice.'.xml';
    $domPractice = new DOMDocument('1.0','UTF-8');
    $domPractice->load($practiceFile);
    $xpPractice = new DOMXPath($domPractice);
    $item_practice = $domPractice->getElementsByTagName('item');


    foreach ($item_practice as $item) 
    {
      foreach ($item->childNodes as $child)
      {
        if($child->nodeType != XML_ELEMENT_NODE) continue;
        if($child->tagName == 'title')
        {
          $titre = utf8_decode($child->firstChild->nodeValue);
        }
        elseif ($child->tagName == 'short_description')
        {
          $short_description = utf8_decode($child->firstChild->nodeValue);
        }
      }
      $msg = "<p>$titre<br/>$short_description</p>";
    }
  }
  else
  { 
    $msg = "<p>There is no practice which corresponds to your request. Please refine your search</p>";
  }
}  
else
  { 
    $msg = "<p>Choose your crireria before starting your search</p>";
  }
echo $msg;
?> 
mais là ca ne marche toujours pas. J'ai toujours le message signifiant "aucun résultat pour votre requete"

Mammouth du PHP | 536 Messages

06 juil. 2007, 14:01

désolé, ma session était expirée, je n'ai pas fait attention.

J'ai vu que t'avais quelques erreurs, en effet, il faut mettre
if( $criteria->idcat == $_POST['cat'] and $criteria->idcrit == $_POST['crit'] )
         {
          $practice = $value->practice;
          $id_practice[] = $practice->id;
          //break;
         }
au lieu de
$id_practice[] = $criteria->practice->id;
          //break; 

Et également mettre
if( (string)$criteria['idcat'] == $_POST['cat'] and (string)$criteria['idcrit'] == $_POST['crit'] )
au lieu de
if( trim($criteria->idcat)==trim($_POST['cat']) and trim($criteria->idcrit) == trim($_POST['crit']) )
Après maintenant, il faudra faire une boucle pour ouvrir toutes les practices qui correspondent à cette requête. Mais là je ne vois pas comment ? Utilisation de foreach de for de while ?
Un prof désespéré à son élève :
- Et maintenant, dessinez-moi un cercle au tableau... Voila... Alors qu'est-ce que c'est?
- Ben un cercle ?
- Non, c'est votre note, sortez !!