Accéder au contenu principal

[jQuery-ui] Mettre en place plusieurs boutons coulissants

Ce blog est crée à cause du mal que j'ai eu autant de mal en anglais qu'en français à trouver les ressources me permettant de mettre en place des boutons coulissants qui interagissent entre eux et qui soient un peu customisés. Comme un exemple vaut souvent mieux que de longs discours, je voulais faire le simulateur de crédit disponible sur http://www.meilleur-credit.org/.
Pour cela, il fallait que le changement de montant ou de durée puisse influer sur la mensualité. J'ai eu recours pour me simplifier la vie à jQuery-UI (comme User Interface) qui permet d'avoir des boutons coulissants (appelés Sliders dans la langue de Shakespeare ou Seek bars pour l'interface android).

La mise en place graphique

La mise en place est assez simple pour avoir une apparence standard mais elle se complique un peu si on veut une apparence plus personnalisée. J'ai essayé de dire à mon graphiste que je m'en foutais mais vous savez, vous développeurs, comment ils sont intransigeants sur certains points de leurs conceptions. L'idée est de se servir des margins et des widths pour que le bouton coulissant ne coulisse pas trop loin.

.slider { 
    width : 180px;
    height: 40px;
}

.ui-slider-horizontal{
    background: url('../images/barre.png') no-repeat;
    border: none;
    width : 195px;
    height: 39px;
    float: left;
}

.ui-slider-horizontal .ui-state-default{
    background: url('../images/bouton_barre.png') no-repeat;
    border: none;
    height: 39px;
    width : 36px;
    margin-left : -18px;
    z-index: 0;
}

.ui-slider-handle .ui-slider {
    background: url('../images/bouton_barre.png') no-repeat;
    height: 39px;
    width : 36px;
    cursor:  pointer;
    margin-left : -18px;
    z-index: 0;
}

La configuration de l'interaction des boutons

 Pour pouvoir gérer les différentes actions que l'utilisateur peut effectuer sur les boutons et les interactions des boutons coulissants entre eux, j'ai besoin de quelques variables et de fonctions.
var montant = 0;
var duree = 0;
var mensualite = 0;
var index = 0;

/**
 * Retourne un nouveau montant
 * @Duree Integer
 * @Mensualite Integer
 * @return Integer
 */


/**
 * Retourne un nouveau montant
 * @Duree Integer
 * @Mensualite Integer
 * @return Integer
 */
function changerMontant (Duree,Mensualite,Pas){
    return Math.round(Duree*Mensualite/Pas)*Pas;
}

function changerDuree (Montant,Mensualite){
    return Math.round(Montant/Mensualite);
}

function changerMensualite (Montant,Duree){
    var Mensualite = Montant/Duree;
    return Math.round(Mensualite);
}

function triTableau(ordre,premier){
    var achanger = ordre.pop();                     //Enlève un élément à la fin du tableau et le retourne
    if (achanger == premier){                       //Si le dernier élément était montant
        achanger = ordre.pop();                     //On récupère l'avant dernier
        ordre.unshift(premier);                     //On met le montant comme premier élément
        ordre.push(achanger);                       //On remet l'avant dernier en dernier
    }
    else if (premier == ordre[0]){             //Sinon, si montant était le premier élément du tableau
        ordre.push(achanger);                       //On remet l'avant dernier en dernier
    } else {                                        //Sinon, l'élément est le second
        second = ordre.shift();                     //On récupère celui qui va passer second
        ordre.push(second);                         //On le met en second
        ordre.push(achanger);                       //Puis le dernier
    }
    return ordre, achanger;
}


/**
 * Mets à jour les données quand la valeur d'un slider change
 */
function miseajourdonnees(){
    mensualiteInt = Math.round((montant*taux/12)/(1-(Math.pow((1+taux),(-(duree*multiduree/12)))))*100)/100;
    totalCredit= Math.round(mensualiteInt*duree*multiduree*100)/100;
    interets = Math.round((totalCredit-montant)*100)/100;
    //On change la valeur du montant car il a été arrondi
    $("#montant").slider({value : montant});
    //Celle de la durée
    $("#duree").slider({value : duree});
    //En fonction du montant et de la durée, on corrige la mensualité minimum ou maximum
    $("#mensualite").slider({
        value : Math.sqrt(mensualiteInt), 
        min : Math.sqrt(Math.round((montant*taux/12)/(1-(Math.pow((1+taux),(-(parseInt(donneeType[index]['DureeMax'])*multiduree/12)))))*100)/100), 
        max : Math.sqrt(parseInt(donneeType[index]['MontantMax'])/(parseInt(donneeType[index]['DureeMin']))/multiduree)
    });
    //On affiche les données modifiées à droite de la barre avec le formatage adéquat
    $("#valeur-montant").html(formatage(montant,' €'));
    $("#valeur-duree").html(formatage(duree, ' '+donneeType[index]['UniteDuree']));
    $("#valeur-mensualite").html(formatage(mensualiteInt, ' €'));
    $("#valeur-taux").html((Math.round(taux*10000)/100)+' % ');
    $("#total-interet").html(interets+' € ');
    $("#total-credit").html(totalCredit+' € ');
}

Ensuite, il faut traiter les interactions. L'idée générale est de changer le bouton coulissant dans les limites qui me sont permises par la logique des crédits. De plus, je devais gérer des crédits qui avaient des échelles de durée différentes (mois dans la plupart des cas mais années dans le cas d'un crédit immobilier). Je récupère les données directement écrites dans le html en JSON. Voici le code commenté :
$(document).ready(function() {
    //Ecoute les changements sur le select
    $('.titre-picto').bind("click", function (e){
        //On récupère l'index du crédit pour savoir à quel type on a affaire (immobilier, consommation...)
        index = parseInt(this.getAttribute('attr'));
        $.ajax({
            type : "POST",
            url : "../helpers/affiche-sliders.php",
            data : "type="+index,
            success : function(retour){
                $('#contenu-simul').html(retour);            
                $('#valider').show();

                var ordre = new Array("#montant", "#duree", "#mensualite"); //Sert à savoir quel slide va faire variable d'ajustement

                if (donneeType[index]['UniteDuree']=="années"){
                    multiduree=12;
                }
                montant = parseInt(donneeType[index]['MontantMin']);    //On récupère les données pour l'affichage suivant le type de crédit qui a été choisi
                duree = parseInt(donneeType[index]['DureeMin']);
                mensualite = montant/duree;
                var PasMontant = parseInt(donneeType[index]['Pas']);
                var mensualiteMin = montant/parseInt(donneeType[index]['MontantMax'])/multiduree;
                var mensualiteMax = parseInt(donneeType[index]['MontantMax'])/(parseInt(donneeType[index]['DureeMin']))/multiduree;
                var achanger;                       //Va servir à savoir quelle valeur peut être modifiée
                var premier;                        //Sert à savoir quel doit être le premier élément du tableau


                //Gère le slider montant
                $("#valeur-montant").html(formatage(montant,' €'));  //Formate et affecte la valeur par défaut à l'affichage
                $("#montant").slider({
                    disabled: false, 
                    value : Math.sqrt(parseInt(donneeType[index]['MontantMin'])),  //Définit la valeur par défaut
                    min : Math.sqrt(parseInt(donneeType[index]['MontantMin'])),    //Minimum
                    max : Math.sqrt(parseInt(donneeType[index]['MontantMax'])),    //Maximum
                    step : 5,                                  //Pas entre deux valeurs du slider
                    slide : function (e, ui){                  //Fonction déclenchée quand l'utilisateur fait glisser le bouton
                        //On arrondi le montant au pas qu'on veut qu'il prenne
                        montant = Math.round(Math.pow(ui.value,2)/PasMontant)*PasMontant;
                        premier = "#montant";                       //Sert à savoir quel doit être le premier élément du tableau

                        ordre, achanger = triTableau(ordre, premier);
                        //Si nous devons changer la mensualité
                        if (achanger == "#mensualite"){
                            mensualite = changerMensualite(montant, duree*multiduree);
                            if (mensualite < mensualiteMin)
                                mensualite = mensualiteMin;
                            if (mensualite > mensualiteMax)
                                mensualite = mensualiteMax;
                            duree = changerDuree(montant, mensualite*multiduree);
                        //Sinon la durée
                        } else if (achanger == "#duree") {
                            duree = changerDuree(montant, mensualite*multiduree);
                            if (duree < parseInt(donneeType[index]['DureeMin']))
                                duree = parseInt(donneeType[index]['DureeMin']);
                            if (duree > parseInt(donneeType[index]['DureeMax']))
                                duree = parseInt(donneeType[index]['DureeMax']);
                            mensualite = changerMensualite(montant, duree*multiduree);
                        }
                        miseajourdonnees();
                    }
                });

                //Gère le slider durée (le fonctionnement est le même que pour le 
                //montant mais on considère qu'on influe pas sur le montant choisi,
                //seulement sur la mensualité
                $("#valeur-duree").html(formatage(parseInt(donneeType[index]['DureeMin']), ' '+donneeType[index]['UniteDuree']));
                $("#duree").slider({
                    disabled: false, 
                    value : duree,
                    min : duree,
                    max : parseInt(donneeType[index]['DureeMax']),
                    step : 1,
                    slide : function (e, ui){
                        duree = ui.value;
                        premier = "#duree"; //Pour que durée soit changé après mensualité si le montant change

                        ordre, achanger = triTableau(ordre, premier);
                        mensualite = changerMensualite(montant, duree*multiduree);
                        if (mensualite < mensualiteMin)
                            mensualite = mensualiteMin;
                        if (mensualite > mensualiteMax)
                            mensualite = mensualiteMax;
                        miseajourdonnees();
                    }
                }); 

                //Gère le slider mensualité (fonctionne comme durée)
                $("#valeur-mensualite").html(formatage(100, ' €'));
                $("#mensualite").slider({
                    disabled: false, 
                    value : Math.sqrt(mensualite),
                    min : Math.sqrt(mensualiteMin),
                    max : Math.sqrt(mensualiteMax),
                    step : 1,
                    slide : function (e, ui){
                        mensualite = Math.round(Math.pow(ui.value,2));
                        premier = "#mensualite";

                        ordre, achanger = triTableau(ordre, premier);

                        duree = changerDuree(montant, mensualite*multiduree);
                        if (duree < parseInt(donneeType[index]['DureeMin']))
                            duree = parseInt(donneeType[index]['DureeMin']);
                        if (duree > parseInt(donneeType[index]['DureeMax']))
                            duree = parseInt(donneeType[index]['DureeMax']);
                        miseajourdonnees();
                    }
                });

                $("#valeur-taux").html('5 % ');
                $("#taux").slider({
                    disabled: false, 
                    value : 5,
                    min : 3,
                    max : 20,
                    step : 0.25,
                    slide : function (e, ui){
                        taux = (ui.value/100);
                        miseajourdonnees();
                    }
                });
            }
        });

    });
    $('#affichbanque').bind("click", function(){
        if (index!=0){
            _gaq.push(['_trackEvent', 'Affichage des banques', donneeType[index]['Nom'], montant, duree]);
             $.ajax({
                type : "POST",
                url : "../helpers/banque-simul.php",
                data : "type="+index+"&montant="+montant+"&duree="+duree,
                success : function(retour){
                    $('#affiche-detail').html(retour);   
                }
            });
        }
    });
    $('#planremb').bind("click", function(){
        if (index!=0){
            _gaq.push(['_trackEvent', 'Plan de remboursement', donneeType[index]['Nom'], montant, duree]);
             $.ajax({
                type : "POST",
                url : "../helpers/plan-remboursement.php",
                data : "&montant="+montant+"&duree="+(duree*multiduree)+"&taux="+taux,
                success : function(retour){
                    $('#affiche-detail').html(retour);   
                }
            });
        }
    });
});
Si vous n'y arrivez pas, un petit commentaire et j'essaierais de répondre.

Commentaires

  1. es ce possible d'avoir le script complet ?

    RépondreSupprimer
    Réponses
    1. Vous avez le script complet, il suffit juste de mettre dans le même fichier les deux parties.

      Supprimer
  2. c'est ce que j'ai fait mais ma page est blanche.

    RépondreSupprimer
    Réponses
    1. C'est à dire ? Pourriez-vous mettre le code html que vous avez utiliser ? Il doit ressembler à celui de cette page : http://www.meilleur-credit.org/ressources/simulateur.html une fois que vous avez choisi le crédit.

      Supprimer
  3. Bonjour,
    il y a aucune partie html pour les sliders ? ? ?

    RépondreSupprimer
    Réponses
    1. Vous pouvez voir un exemple en cliquant sur un des types de crédits dans le lien fourni dans l'introduction. Je n'ai pas le code sous les yeux mais un div avec les classes correspondantes à jquery ui suffit, à ce qu'il me semble. Je regarderai ce soir pour modifier cette réponse le cas échéant.

      Supprimer
    2. Ca marche. Si vous avez le code ca serait vraiment nickel sinon je mettrai le nez dans les exemples.
      Merci

      Supprimer

Enregistrer un commentaire

Posts les plus consultés de ce blog

[PHP] Faire un petit MVC avec des routes

Pour bon nombre de petits projets, il n'est pas nécessaire de taper dans les frameworks MVC comme Zend ou Symphony qui sont très lourds et un petit truc maison doit suffire. Je vais essayer de donner quelques tuyaux pour pouvoir faire son MVC maison avec des routes qui dirigent vers les contrôleurs et les actions. Tout d'abord, il faut créer un fichier index.php à la racine de votre site qui va contenir le lien vers tout ce dont vous avez besoin pour faire vos routes. Ensuite, vous devez créer un dossier controlleur (si vous voulez reproduire la faute de frappe de l'exemple) dans lequel vous aurez tous vos contrôleurs. Vous pouvez éventuellement diviser ce dossier en plusieurs dossiers distincts qui contiendront les différentes parties de votre site. Veillez à appeler vos classes en rapport avec vos règles de is_callable. Dans mon exemple, le chemin vers le dossier est en minuscule et la première lettre du fichier est en majuscule. Par exemple : la classe /controlleur/fron

Injecter des icônes font-awesome via JavaScript

Les icônes de font-awesome sont traduites en SVG ( Scalable Vector Graphics) à la volée grâce à un script. Le problème quand on injecte du HTML dans le DOM est que le script ne s'exécute pas correctement et l'icône n’apparaît pas. Pour palier à cela, il est possible d'utiliser un générateur de ressources qui est embarqué dans la librairie font-awesome. Pour éviter au script de s'exécuter sur des icônes qui se répètent, la librairie comprend un script qui permet de traduire une seule fois l'image en SVG pour être réutiliser dans des listes. Comme disent les anglo-saxons, et voilà ! Il y a d'autres exemples d'utilisation :  https://fontawesome.com/how-to-use/on-the-web/advanced/svg-symbols