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/fro…

[Magento 2]Le système de cache

A la lecture de l'article d'Alan Kent sur le système de cache de Magento 2, on ne peut que se réjouir d'une vraie prise de conscience du problème qui avait été déjà pris en compte avec la mise en place des modules Redis de Colin Mollenhour dans Magento 1.8 qui avait permis d'améliorer considérablement les performances sur des Magento à moyen et gros volumes. J'avais pris l'initiative de mettre en place ces deux modules (Session et Backend) sur des 1.7 au grand soulagement des clients qui ont vu les temps de réponses s'améliorer avec un temps de chargement parfois divisé par trois.
Pour la future version de Magento, le système de cache se basera a priori sur un cache de page complète du type Varnish avec un chargement en Ajax pour les parties de la pages qui sont spécifiques à l'utilisateur. On pense notamment au récapitulatif du panier, aux liens vers les différentes parties du compte... En s'appuyant tout de même sur le cache du navigateur pour cac…

Ajouter un administrateur à Magento 1 en SQL

On vous balance sur un projet, vous devez récupérer la base de données et travailler dessus dans votre environnement de développement. Le problème est que vous n'avez pas d'accès à l'administration car vous n'avez pas d'utilisateur créé en production ou en staging. Ce n'est pas une fatalité !

Il est possible de créer facilement un utilisateur qui aura les rôles suffisants dans Magento avec seulement un accès à la base de données. Pour faire cela, il faut comprendre que les administrateurs sont inscrits dans une table et leur rôle dans une autre. Dans le script suivant, on créera un administrateur avec les pleins pouvoirs mais vous pouvez adapter ce script à vos besoin en jetant un oeil à la table admin_role et en modifiant parent_id dans le script. La colonne parent_id définit le parent du rôle en question pour l'utilisateur. Si vous voulez créer un utilisateur avec des pouvoirs différents, regardez le rôle qui correspond au pouvoir que vous accorder et mo…