11521 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

J'ai ce petit code qui me permet via un sélecteur d'afficher une réponse. Le code fonctionne pour 2 sélecteurs mais je voudrai en rajouter 1 et passer le programme à 3 une liste de 3 questions donc 3 sélecteurs.

Exemple avec 2 sélecteurs : http://alsacreations.matthieurebillard.fr/024/

Je voudrais le même mais avec 3 sélecteurs !!!

Voici le code complet.

 <?php
require_once 'connexion.php';
$req = $connexion->query('SELECT family FROM items GROUP BY family');
$req->execute();
$families = $req->fetchAll();
?>
<!DOCTYPE html>
<html>
<head>
  <title>Test de select AJAX</title>
  <meta charset="utf8">
  <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
  <script type="text/javascript">
    $(function(){
      var form = $('#form'),
          family_select = $('#family'),
          url = form.attr('action'),
          items_container = $('#items');

      $('body').on('change', '#family', function(ev){
        $.post(
          url,
          form.serializeArray(),
          function(data){
            items_container.html(data);
          }
        );
      });
    });
  </script>
</head>
<body>


<form id="form" method="post" action="data.php">  
  <div id="families">
    <label for="family">Famille : </label>
    <select name="family" id="family">
      <option value="">--</option>
      <?php foreach( $families as $family) : ?>
      <option value="<?php echo $family['family']; ?>"><?php echo $family['family']; ?></option>
      <?php endforeach; ?>
    </select>
  </div>
  <div id="items"></div>
</form>
</body>
</html>

data.php
<?php
require_once 'connexion.php';

if( !isset($_POST['family']) || empty($_POST['family'])){
  echo '';
  return;
}

$family = htmlspecialchars($_POST['family']);

$sql = 'SELECT item FROM items WHERE family LIKE :family ORDER BY item';

$req = $connexion->prepare($sql);
$req->execute(array(':family' => $family));
$data = $req->fetchAll(PDO::FETCH_ASSOC);

$output = '<label for="item">Elément : </label>';
$output .= '<select name="item">';
$output .= '<option value="">--</option>';
foreach ($data as $item) {
  $output .= '<option value="' . $item['item'] . '">' . $item['item'] . '</option>';
}
$output .= '</select>';

echo $output;
return;
?>

--
-- Structure de la table `items`
--

CREATE TABLE IF NOT EXISTS `items` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `family` varchar(255) CHARACTER SET latin1 NOT NULL,
  `item` varchar(255) CHARACTER SET latin1 NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ;

--
-- Contenu de la table `items`
--

INSERT INTO `items` (`id`, `family`, `item`) VALUES
(1, 'Légume', 'Courgette'),
(2, 'Fruit', 'Fraise'),
(3, 'Fruit', 'Orange'),
(4, 'Fruit', 'Banane'),
(5, 'Légume', 'Navet'),
(6, 'Légume', 'Betterave'); 


Avec un 3 ème sélecteur bon ou mauvais par exemple.

J'y suis depuis 1 journée et je n'avance pas Smiley bawling

Si je pouvais avoir un exemple ça serait sympa.

Merci d'avance.
Modifié par Tintin75 (14 May 2016 - 09:48)
Bonjour,

Pour le JS, tu peux faire un truc dans le genre (en ajoutant un attribut data-child sur tes select) :
$('body').on('change', 'select[data-child]', function(e){
  var $el = $(this),
      datas = $el.serializeArray(),
      $child = $('.'+$el.data('child')),
      html = "";
  
  $el.parent().nextAll('.select-container').empty()
  
  $.post(
    url,
    data : datas[0],
    function(html){
      $child.html(html);
    }
  );
})

Avec l'HTML qui va bien :
<form action="" id="form">
  <div class="families select-container">
    <select name="family" id="family" data-child="items">
      <option value="">--</option>
      <option value="1">Un</option>
      <option value="2">Deux</option>
    </select>
  </div>
  <div class="items select-container"></div>
  <div class="statuses select-container"></div>
</form>


Voilà un EXEMPLE (http://codepen.io/anon/pen/YqMWmX)

EDIT : je te laisse le traitement à faire pour le PHP ! Smiley cligne
Modifié par SolidSnake (13 May 2016 - 10:49)
Bonjour,


SolidSnake a écrit :
EXEMPLE (http://codepen.io/anon/pen/YqMWmX)
Je vais peut-être mettre un petit peu le bazar dans votre conversation.

En effet, quand j'utilise l'exemple de SolidSnake voici ce que j'observe:
- je choisis "un"
- puis "trois"
- puis "six".
Et zut, c'était pas "un" que je devais choisir mais "deux"
- je change "un" en "deux" => "trois" s'efface mais "six" reste apparent.

C'est bien le comportement attendu ?

Bon courage !
Modifié par Greg_Lumiere (13 May 2016 - 10:56)
Greg_Lumiere a écrit :
C'est bien le comportement attendu ?

Non Smiley lol , j'ai fait une modif' en cours de route, et j'ai oublié de le remettre d'aplomb.

Mais c'était bon dans le code ci-dessus ! (un .parent() qui est parti), donc :
$el.parent().nextAll('.select-container')
// et pas...
$el.nextAll('.select-container')

Modifié par SolidSnake (13 May 2016 - 11:01)
Les loups loups, et si pour rigoler on m'était 4 sélecteurs ?

Juste histoire de voir ou ça se passe pour moi pour le rajout, c'est possible ?

Il faut que je pige ou se trouve la modification du code par rapport à la version à 2 sélecteurs pour apprendre.

Je suis entrain de regarder et je n'arrive pas à rajouter un select

Merci d'avance.

Smiley smile
Modifié par Tintin75 (13 May 2016 - 11:30)
Autre chose, c'est normal que quel que soit le choix effectué sur un sélecteur, les choix suivants ne diffèrent pas ?
Par exemple, que je choisisse "un" ou"deux" les propositions faites sont les mêmes ("trois" et "quatre").

Je ne trouve pas ça logique à moins que je n'ai pas saisi la finalité de ce bout de code. Smiley murf
No soucis, c'était là l'intérêt, tu peux mettre autant de selecteurs que tu le souhaites.

Pour ce faire, il faudra rajouter le data-child correspondant sur le select "parent" (donc ce sera probablement côté PHP), et la classe correspondantes sur la <div> wrappée autour de ton nouveau <select>

Revoir l'exemple !
Greg_Lumiere a écrit :
Autre chose, c'est normal que quel que soit le choix effectué sur un sélecteur, les choix suivants ne diffèrent pas ?

Oui et non, là je n'ai pas de traitement php, mais c'est lui qui sortira tel ou tel code.
Moi je ne fais que du fake en JS.

EDIT : bon, j'ai fait dans mon exemple une version fake "amélioré" ! Smiley lol
Modifié par SolidSnake (13 May 2016 - 12:43)
Je viens d'étudier le code mais on fait comment pour que ça fonctionne en php ?

Le but du code est de faire une aide à la commande.

Voiture / bateau -> Rouge / blanc -> Long / large -> Prix

La personne se sert du sélecteur pour affiner sa recherche.

Si voiture -> blanc -> long -> 33 €

Code de mon sélecteur data. Je souhaite rajouter un 2ème sélecteur à code.

<?php
if( !isset($_POST['da']) || empty($_POST['da'])){
  echo '';
  return;
}

$da = htmlspecialchars($_POST['da']);
$l = htmlspecialchars($_POST['l']);
$l = $_POST['l']; 

$sql = 'SELECT l FROM Equivalence WHERE da LIKE :da ORDER BY l';

$req = $connexion->prepare($sql);
$req->execute(array(':da' => $da));
$data = $req->fetchAll(PDO::FETCH_ASSOC);

$output = '<label for="l"><strong><u>Mode</u> :</strong> </label>'. "<br /><br />";
$output .= '<select name="l" id="l">';
$output .= '<option value="">-- Notre liste  --</option>';

foreach ($data as $l) 
{
  $output .= '<option value="' . $l['l'] . '">' . $l['l'] . '</option>';
}
  $output .= '</select>';

echo  $output;

return;

?>

// JavaScript Document

 $(function(){
      var form = $('#form'),
          family_select = $('#da'),
          url = 'Equivalence_data.php';
          items_container = $('#items');

      $('body').on('change', '#da', function(ev){
        $.post(
          url,
          form.serializeArray(),
          function(data){
            $('#result').text('');
            items_container.html(data);
          }
        );
      });

      $('body').on('change', '#l', function(){
        var result,
            l = $(this).val(),
            da = $('#da').val();
        if(l != ''){
		   result = '<u>TEST1</u>' + ' : '  + '<b>'+  l.toLowerCase() +'</b>';
		   $('#result').html(result);
        }
      });
    });

Modifié par Tintin75 (14 May 2016 - 10:09)
SolidSnake a écrit :
EDIT : bon, j'ai fait dans mon exemple une version fake "amélioré" ! Smiley lol
C'est magnifique ! A le voir comme ça ça a l'air tellement simple.

Si j'ai bien compris, c'est la fonction $('body') qui assure la maj des enfants directs ET indirects. C'est ça ?


@Tintin75: Ca ne change rien du point de vue du serveur, tu récupères le contenu de tes select en récupérant les valeurs de ta super-globale.
Ces valeurs, une fois vérifiées, pourront être chargées par, par exemple, un moteur de recherche pour servir de mot clé.
La seule chose à ne pas oublier, en cas d'ajout d'un select côté JS et html, est d'ajouter la vérification correspondante côté php.
Bien sûr, pour que tout ceci soit valable, tu dois prévoir une méthode de soumission :
- soit classique par un élément de soumission (input/button)
- soit en live en donnant la capacité au dernier select de pouvoir faire la soumission dès sélection (ce qui a l’inconvénient de ne pas laisser la possibilité à l'utilisateur de modifier le dernier choix).

Par contre, si le fait de "remplir" le dernier sélecteur de ta série a pour but de provoquer l'insertion d''un élément le traitement peut être fait par une fonction JS supplémentaire. Par exemple si tu souhaite afficher une promo liée à un produit dans une déclinaison spécifique ou personnaliser le descriptif en fonction de la déclinaison.


Voilà comment je vois le truc. Smiley smile


Il n'y a que notre imagination qui nous impose des limites. A l'intérieur de celles-ci, tout est possible.
Modifié par Greg_Lumiere (14 May 2016 - 10:12)
Ok, merci pour l'explication, c'est trop compliqué pour moi.

Je n'avais pas vue toutes les difficultés.

Merci pour tes lumières, le truc du débutant qui croit que c'est simple alors que c'est compliqué Smiley murf
Modifié par Tintin75 (14 May 2016 - 11:37)
Bonjour,
Greg_Lumiere a écrit :
Si j'ai bien compris, c'est la fonction $('body') qui assure la maj des enfants directs ET indirects. C'est ça ?

$('body').on('change', 'select[data-child]', function(e){ ... })

En fait $('body') n'est pas une fonction, c'est juste un sélecteur jQuery , la méthode c'est le change (ou plutôt l'écouteur ou listener).
Et même s'il est placé sur le <body>, il n'écoute que les changements sur les <select> qui ont l'attribut data-child (j'aurais d'ailleurs plutôt dû mettre l'écouteur sur #form pour être au plus prêt des <select>)
@SolidSnake:

Super l'explication ! Smiley biggrin

Si j'ai bien compris, à titre d'exemple,
$('li').on('hover','a[title]',function(){..})
signifierai :
au survol d'un élément li, applique la fonction suivante aux liens qui possèdent l'attribut title qu'elle contient

C'est bien ça ?
Bonjour,
Greg_Lumiere a écrit :
Si j'ai bien compris, à titre d'exemple,
$('li').on('hover','a[title]',function(){..})
signifierai :
au survol d'un élément li, applique la fonction suivante aux liens qui possèdent l'attribut title qu'elle contient

Non, c'est bien au survol de <a title=""> qui sont dans des <li> que la fonction sera appelée.
En gros, c'est sur le principe identique à :
$('li a[title]').on('hover',function(){..})
// ou même
$('li a[title]').hover(function(){..})

Mais alors tu vas me dire, à quoi ça sert si l'on peut l'écrire plus simplement ?
Et bien c'est une BONNE question, merci à mon cerveau de l'avoir posée avant que tu ne le fasses.
La différence, c'est la délégation... Keuwa ?
En fait, les deux lignes de code juste au dessus vont ajouter un écouteur sur tous les <a> présents dans le DOM et correspondant aux sélecteurs.
Alors que la ligne tout au dessus ne va ajouter qu'un écouteur que sur le <li> (mais pointant sur les <a>) et ce, même si les <a> sont rajoutés dans le DOM après (problème récurrent avec Ajax), donc un gain performance.