11521 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous,
Je travaille actuellement sur le développement d'une web application de création de devis...
Un SELECT relié à la table "prestations" de ma base de donnée propose différents services. Chaque changement de ce select modifie l'INPUT à sa droite pour afficher le prix de la prestation sélectionnée (ça fonctionne !). Un autre INPUT, à droite également, propose de saisir une quantité... Jusque là rien de bien révolutionnaire. Enfin un troisième INPUT, inaccessible en saisie, calcule le prix de la prestation x la quantité...
Le prix et la quantité interagissent bien ensemble (ouf)mais le changement du SELECT fonctionne de manière chaotique une fois qu'une première sélection avait été faite...

Voici mon code, merci d'avance à ceux qui pourraient m'aider !


<form id="formulaire" name="formulaire" method="post" action="contrat-ajout2.php">
<select name="prestation" id="prestation" required="" >
                            <option value="">Choisir une prestation</option>
                            <?php
                                foreach($prestations as $valeur3) {
                                    echo '<option value="' . $valeur3['id_prestation'] . '">' . $valeur3['designation'] . '</option>';
                                }
                            ?>
                        </select>
                        <input name="prix" id="prix" type="text" value="" onkeypress="return chiffres(event);"/>
                        <input name="quantite" id="quantite" type="text" value="" onkeypress="return chiffres(event);"/>
                        <input name="total" id="total" type="text" value="" readonly="true;"/>
                        <input type="button" value="AJOUTER" onclick="plus_contrat();">
                        <br />
                        <input type="reset" value="EFFACER">
                        <input type="submit" value="VALIDER">
                        <input type="text" name="chaine_contrat" id="chaine_contrat" style="visibility: hidden;">
                    </form>



<!--  ######### SCRIPT MISE À JOUR TARIFS ############-->
        <script type="text/javascript">
            $(function(){  
                $("#prestation").change(function(){   

                    var choix = $(this).val();      
                    $.post("verifcontrat.php", {    verifcontrat.php
                        "valeurChoisie" :  choix
                    })
                    .done(function(data){      
                        document.getElementById("prix").value = data ;
                    })
                    .fail(function(){   
            		    alert('Accès aux tarifs impossible actuellement !');
        		    });
                })
            })
        </script>
        <!--  ############# CALCUL TOTAL PRESTATION ###########-->
        <script type="text/javascript" language="javascript">
            $("#prestation, #prix, #quantite").change(function(){
                var prix_ligne = prix.value;
                var quantite_ligne = quantite.value;
                var TotLi = prix_ligne*quantite_ligne;
                document.getElementById("total").value = TotLi;
            })
        </script>

Modifié par etienne69 (08 Sep 2021 - 14:33)
Salut,

j'ai l'impression qu'il nous manque des bouts Smiley ohwell
C'est quoi :
onkeypress="return chiffres(event);"

et
onclick="plus_contrat();"


Pour le input prix j'ai l'impression que cela devrait être du readonly comme pour total (et les deux pourraient même ne pas être des inputs vu qu'ils ne servent qu'à faire de l'affichage)
Salut Mathieuu,
Merci de te pencher sur mon problème...

Je n'ai pas mis tout le code parce que certaines parties n'affectaient en rien mon
erreur. onkeypress="return chiffres(event);" appelle un bout de code qui interdit de
taper au clavier autre chose que des chiffres, backspace, enter et del...

onclick="plus_contrat();" lui aussi n'était pas concerné par l'erreur puisqu'il appelle
un bout de code qui ajoute dans une chaîne les prestations que l'on valide les une
à la suite des autres pour être envoyées ensuite vers l'enregistrement dans une base
de données...

Voici la piste que l'on m'a donné à l'instant qui vient de résoudre mon problème :
"Attention, par défaut les appels ajax sont asynchrones...
Il y a donc certainement des fois où la réponse renvoyée du serveur arrive après
le calcul .."

On m'a conseillé d'appeler une fonction de calcul majPrix(); dès mon retour Ajax
dans le .done :


<script type="text/javascript">
            $(function(){
                $("#prestation").change(function(){
                    var choix = $(this).val();
                    $.post("verifcontrat.php", {
                        "valeurChoisie" :  choix
                    })
                    .done(function(data){
                        document.getElementById("prix").value = data ;
                        majPrix();
                    })
                    .fail(function(){
                        alert('Accès aux tarifs impossible actuellement !');
                    });
                });
            });
            // ############# CALCUL TOTAL PRESTATION ###########
            $("#quantite, #prix").change(function(){
                majPrix();
            });


             function majPrix(){
                var prix_ligne = parseFloat(prix.value);
                var quantite_ligne = parseFloat(quantite.value);

                if (prix_ligne !=0 && prix_ligne !="" && quantite_ligne !=0 && quantite_ligne !="") {
                    var TotLi = prix_ligne*quantite_ligne;
                    alert(isNaN(TotLi));
                    document.getElementById("total").value = TotLi;
                }
            }
        </script>


Et ça fonctionne !
Modifié par etienne69 (09 Sep 2021 - 14:34)
Meilleure solution
@Mathieuu

Pour le INPUT prix je le laisse car je veux pouvoir agir sur le prix proposé par
la validation du SELECT prestation parce que je veux pouvoir baisser le prix pour
faire un geste commercial par exemple...

Pour l'autre, celui du total, il n'a effectivement aucun intérêt, il est même trompeur
dans la mesure où on a envie de cliquer dedans alors qu'il est bloqué...
Je vais suivre ton conseil et le remplacer par l'écriture dans une div...

Merci Mathieuu
Nickel si tu as trouvé Smiley lol

J'attendais d'avoir toutes les infos pour te proposer d'essayer d'enlever
#prestation
de la ligne
$("#prestation, #prix, #quantite").change
parce que j'avais l'impression que la ligne
document.getElementById("prix").value = data ;
implique un change de #prix et donc en quelque sorte un "double appel" inutile.

Edit (pour rappel au cas où) : ce n'est pas parce que tu as des fonctions coté client qui empêche de saisir des lettres qu'il ne faut pas également faire une vérification du coté serveur.

Edit 2 : Pour le geste commercial, je ne sais pas à quel point cela ne serait pas mieux d'avoir un "champs dédié" (cela permet de faire plus facilement des vérifications de calculs coté serveur et cela me semble plus carré pour faire de la compta derrière)
Modifié par Mathieuu (09 Sep 2021 - 17:02)
@Mathieuu :

En réponse à ton premier édit, je vais effectivement ajouter des conditions d'enregistrement
qui s'assurent que les champs ont été bien remplis avant de remplir la base de donnée...

Ton 2° edit : Remarque judicieuse ne serait-ce que pour indiquer au client le montant de
la remise que nous lui accordons ! Adopté ! Smiley cligne

D'autre part, comment faudrait-il coder pour que le calcul du total s'effectue à chaque fois que je modifie le prix ou la quantité, je veux dire en cours de saisie plutôt que lorsque je quitte le
champs ?
De base je pensais que le "on change" se faisait au fur et a mesure que tu faisais la saisie, mais en effet en lisant la doc de jquery ce n'est pas le cas : https://api.jquery.com/change/ :
For select boxes, checkboxes, and radio buttons, the event is fired immediately when the user makes a selection with the mouse, but for the other element types the event is deferred until the element loses focus.

J'aurai dit de voir du coté des events liés au clavier (de mémoire key press/key down/key up) mais en cherchant sur le net je viens de tomber sur ce message https://stackoverflow.com/questions/12797700/jquery-detect-change-in-input-field qui suggère un event "input" et renvoie vers ce jsfiddle http://jsfiddle.net/6bSX6/ qui illustre bien la différence entre "change" et "on input".

Du coup avec ton code a priori cela transforme
$("#quantite, #prix").change(function(){

en
$("#quantite, #prix").on('input', function() {


Mini edit : je m'étais loupé sur les id, j'avais mis l'id du select au lieu des 2 inputs ..
Modifié par Mathieuu (10 Sep 2021 - 16:46)
Je ne comprend pas pourquoi ça fonctionne sur jsfiddle.net et pas dans mon code !
Firefox me dit dans la console, avant même de toucher au select :
Uncaught TypeError: $(...).on is not a function

D'autre part, j'essaie ça :
$("#quantite, #prix").keydown(function(){
Il se passe un truc étrange : rien ne se calcule dans total à la saisie du premier chiffre
quantité (ou prix c'est idem) par contre le calcul se fait dès la saisie du 2°, 3°, 4° chiffre
etc...
Le select, par contre (si quantité est renseignée) affecte bien le total, même quand on
monte ou on descend dans les options à l'aide des flèches du clavier haut ou bas !

<select name="prestation" id="prestation" required="" >
    <option value="0">Choisir une prestation</option>
        <?php
        foreach($prestations as $valeur3) {
            echo '<option value="' . $valeur3['id_prestation'] . '">' . $valeur3['designation'] . '</option>';
        } ?>
</select>
<input name="prix" id="prix" type="text" value="" onkeypress="return chiffres(event);"/>
<input name="quantite" id="quantite" type="text" value="" onkeypress="return chiffres(event);"/>
<input name="total" id="total" type="text" value="" readonly="true;"/>
<br />
<input type="reset" value="EFFACER">
<input type="submit" value="VALIDER">



<script type="text/javascript">
            // ################ INTERROGATION BDD AU CHGT DU SELECT ###########
            $(function(){
                $("#prestation").change(function(){
                    var choix = $(this).val();
                    $.post("verifcontrat.php", {
                        "valeurChoisie" :  choix
                    })
                    .done(function(data){
                        document.getElementById("prix").value = data ;
                        majPrix();
                    })
                    .fail(function(){
                        alert('Accès aux tarifs impossible actuellement !');
                    });
                });
            });
            // ################ SURVEILLANCE CHGT D'UN INPUT #######################
            $("#quantite, #prix").keydown(function(){
                majPrix();
            });
            // ################ FONCTION CALCUL DE LA PRESTATION TOTALE  ###########
            function majPrix(){
                var prix_ligne = parseFloat(prix.value);
                var quantite_ligne = parseFloat(quantite.value);

                if (!isNaN(prix_ligne) && prix_ligne != 0 && !isNaN(quantite_ligne) && quantite_ligne != 0) {
                    var TotLi = prix_ligne*quantite_ligne;
                    document.getElementById("total").value = TotLi;
                }
            }


            // ################ AUTORISATION SAISIE CHIFFRES UNIQUEMENT ##############-->
            function chiffres(autorise){ // (0 à 9) + . + flèches directions + backspace + del 
                if( 47 < autorise.which && autorise.which< 57 || autorise.which ==46 || autorise.which ==8 || autorise.which ==0) {
                }
                else{
                    autorise.preventDefault();
                    return false;
                }
            }

        </script>


Résolu de cette manière :


$("#quantite, #prix").keyup(function(){
      majPrix();
});


Encore merci Mathieuu pour ton temps et tes remarques judicieuses pour améliorer mon
programme !