Jquery : Trier des éléments en fonction d’attributs data-*

Nous allons voir aujourd’hui comment classer des éléments d’une page en fonctions de certaines données (nom, position) grâce à quelques lignes de javascript.
La démonstration du résultat que l’on va obtenir est visible ici

On commence par créer notre html de manière classique, comme d’habitude j’importe bootstrap et jquery pour la forme et la simplicité.
En plus de ça on affiche dans notre page une série d’élément ayant la classe « card » ainsi que des attributs « data-position », « data-note » et « data-name » pour stocker les valeurs sur lesquelles on va effectuer le classement. On affiche auparavant un « select » qui nous permettra de choisir l’ordre que l’on souhaite afficher.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <!-- CSS -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
        <link rel="stylesheet" href="./css/style.css">
        <!-- JS -->
        <script src="./js/jquery-3.3.1.min.js"></script>
        <script src="./js/custom.js"></script>
    </head>
    <body>
        <div class="container main-container">
            <div class="form-group">
                <label for="select-order">Classer par</label>
                <select class="form-control" id="select-order">
                    <option value="position">Position</option>
                    <option value="note">Note</option>
                    <option value="name">Nom</option>
                </select>
            </div>
            <div class="card-container row">
                <div class="item col-md-4" data-position="1" data-note="8" data-name="Paul">
                    <div class="card mb-3">
                        <img class="card-img-top" src="http://lorempixel.com/400/200/abstract" alt="illustration">
                        <div class="card-body">
                            <h3 class="card-title">Paul</h3>
                            <div class="card-subtitle">Position : 1</div>
                            <div class="card-text">Note : 8</div>
                        </div>
                    </div>
                </div>
                <!-- d'autres éléments avec différentes valeurs -->
            </div>
        </div>
    </body>
</html>

On va maintenant s’occuper du javascript qui nous permettra de réordonner les éléments, il s’agit de détecter le choix sélectionné et de lancer le tri (numérique, numérique inversé ou alphabétique) sur nos attributs data-*. Le code suivant est suffisant :

$(document).ready(function () {
    /* à la sélection du classement on met à jour */
    $(document).on("change", "#select-order", function () {
        updateOrder();
    });
    /* au chargement de la page on lance le classement */
    updateOrder();
});

function updateOrder() {
    var order = $("#select-order").val();
    if (order == 'position' || order == 'note' || order == 'name') {
        var divList = $(".card");
        if (order == 'position') { //tri numerique croissant
            divList.sort(function (a, b) {
                return  $(a).data(order) - $(b).data(order);
            });
        } else if (order == 'note') {//tri numerique decroissant
            divList.sort(function (a, b) {
                return $(b).data(order) - $(a).data(order);
            });
        } else if (order == 'name') { //tri alphabetique
            divList.sort(function (a, b) {
                var compA = $(a).data(order).toUpperCase();
                var compB = $(b).data(order).toUpperCase();
                return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
            });
        }
        $(".card-container").html(divList);
    }
}

jQuery : Accéder à des champs de formulaire ayant un nom dans un tableau

Avec jQuery on peux récupérer la valeur d’un champ en le sélectionnant grâce à son nom (attribut name).
Par exemple pour connaitre la valeur sélectionné des radio boutons suivants :

<label for="radio1"><input name="choix" value="1" type="radio" id="radio1"> Choix 1</label>
<label for="radio2"><input name="choix" value="2" type="radio" id="radio2"> Choix 2</label>
<label for="radio3"><input name="choix" value="3" type="radio" id="radio3"> Choix 3</label>

Il suffit de faire :

$("input[name='choix']:checked").val();

Par contre si le nom est composé, comme dans l’exemple ci-dessous :

<label for="radio1"><input name="mon_formulaire[choix]" value="1" type="radio" id="radio1"> Choix 1</label>
<label for="radio2"><input name="mon_formulaire[choix]" value="2" type="radio" id="radio2"> Choix 2</label>
<label for="radio3"><input name="mon_formulaire[choix]" value="3" type="radio" id="radio3"> Choix 3</label>

Il faut utiliser les carractères d’échappement « \\ » pour que ça fonctionne. Comme ci-dessous.

$("input[name='mon_formulaire\\[choix\\]']:checked").val()

jQuery : Sélection des départements français sur une carte

Dans cet article nous allons voir comment transformer un select multiple contenant la liste des département français en carte permettant de sélectionner/désélectionner les départements en cliquant dessus.

Nous allons passer d’un select multiple classique comme celui-ci :

à un sélecteur visuel comme ci-dessous :

Une page de démonstration est visible ici.

Pour cela nous utiliseront jQuery, le plugin jVectorMap et sa carte pour les départements français disponible ici

On attaque par la mise en place du code html, il s’agit d’un select multiple classique, on va juste prendre soin de lui donner un identifiant « map-selector » et de l’englober dans un « div » parent. Pour l’utiliser avec la carte, nous allons donner pour chaque département la valeur « FR-CODE_DU_DEPARTEMENT », exemple « FR-34 » pour l’Hérault.

<div>
    <select id="map-selector" name="departements" multiple="multiple">
        <option value="FR-01">Ain</option>
        <option value="FR-02">Aisne</option>
        <option value="FR-03">Allier</option>
        <!-- etc... -->
    </select>
</div>

On inclus dans la page les script nécessaires (jquey, jvectormap, la carte, un fichier « map-selector.js » ou l’on mettra notre code ainsi qu’une feuille de styles css.)

<link rel="stylesheet" href="jquery-jvectormap-2.0.3.css">
<link rel="stylesheet" href="style.css">
<script src="jquery-3.2.1.min.js"></script>
<script src="jquery-jvectormap-2.0.3.min.js"></script>
<script src="jquery-jvectormap-fr-merc.js"></script>
<script src="map-selector.js"></script>

Tout est prêt ! Il nous reste plus qu’à coder notre fichier « map-selector.js » pour mettre en place le système. Le code de quelques lignes commenté ci-dessous :

$(document).ready(function () {
    //on masque le select classique
    $("#map-selector").css("display", "none");
    //on ajoute un div #container-map-selector qui contiendra la carte
    $("#map-selector").parent().append("<div id='container-map-selector'></div>");
    //on initie la carte sur cet élément
    var map = new jvm.Map({
        container: $("#container-map-selector"),
        map: 'fr_merc',
        regionsSelectable: true,
       //à chaque clic sur un département
        onRegionSelected: function () {
            //on vide le select
            $("#map-selector").val("");
            //et on sélectionne chaque options correspondant au département sélectionné sur la carte
            $.each(map.getSelectedRegions(), function (index, region) {
                $("#map-selector option[value=" + region + "]").prop("selected", true);
            });
        }
    });
    //au départ si des options du select sont présélectionnés, on les sélectionnes sur la carte
    $("#map-selector option:selected").each(function () {
        map.setSelectedRegions($(this).val());
    });
});

jQuery : rendre l’option d’un select permanente avec le plugin « select2 »

Le plugin jQuery « Select2 » permet d’améliorer les champs de type « select » (liste déroulante). Une de ces principales fonctionnalité et d’intégrer un champs de recherche à la liste. Très pratique pour retrouver et sélectionner un éléments dans une longue liste.

Nous allons voir ci-dessous comment mettre en place une astuce afin qu’une option de la liste reste toujours disponible. Afin qu’un résultat de secours soit toujours sélectionnable quand on recherche un élément inexistant.

Notre exemple consiste à sélectionner un instrument dans la liste, avec la possibilité toujours visible de sélectionner « Autre instrument » si celui que l’on recherche n’est pas disponible. On en profitera pour afficher des champs supplémentaires quand cette option est sélectionné afin de pouvoir récolter les informations concernant l’instrument réellement recherché.

L’exemple est disponible ici

Comme d’habitude on commence par inclure jQuery, le plugin select2 et un fichier qui contiendra notre script dans le head de la page :

<!-- jQuery -->
<script src="./js/jquery-3.2.1.min.js"></script>
<!-- select2 -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/js/select2.min.js"></script>
<!--custom -->
<script src="./js/main.js"></script>

On met en place notre html de manière classique, avec une option de valeur « autre » dans la liste des option de notre champs « select »

<div class="form-group">
    <label for="instrument">Instrument</label>
    <select id="instrument" class="form-control" name="instrument">
        <option value="1">accordéon</option>
        <option value="2">bandonéon</option>
        <option value="3">banjo</option>
        <option value="4">batterie</option>
        <!-- Toutes les autres options -->
        <!-- Notre option de valeur "autre" -->
        <option value="autre">Autre instrument</option>
    </select>
</div>
<!-- les autre champs à afficher/masquer selon le choix dans la liste précédente -->
<div class="form-group">
    <label for="otherInstrumentCategory">Catégorie de l'instrument</label>
    <select class="form-control" id="otherInstrumentCategory" name="otherInstrumentCategory" >
        <option value="1">Instrument à corde</option>
        <option value="2">Percussion</option>
        <option value="4">Instrument à vent</option>
        <option value="5">MAO</option>
        <option value="6">Autre</option>
    </select>
</div>
<div class="form-group">
    <label for="otherInstrument">Nom de l'
instrument</label>
    <input type="text" id="otherInstrument" name="otherInstrument" class="form-control">
</div>

Et pour finir notre javascript qui va permettre de toujours laisser en place l’option « autre instrument » malgré une recherche, ainsi que d’afficher ou masquer les champs supplémentaires. Rien de bien complexe, suivez les commentaires dans le code pour comprendre.

$(document).ready(function () {
    /*au changement du champs instrument on met à jour l'affichage des champs*/
    $(document).on("change", "#instrument", function () {
        updateFields();
    });
    /*initialisation du champs instrument, pour l'utilisation du plugin select2 avec un filtre de recherche particulier*/
    $('select#instrument').select2({matcher: select2matchCustomInstrument});
    /*initialisation de 'laffichage des champs*/
    updateFields();
});

/*On va utiliser le système de recherche classique du plugin select2*/
var defaultMatcher = $.fn.select2.defaults.defaults.matcher;
function select2matchCustomInstrument(params, data) {
    /* Si l'option est "Autre" on l'affiche toujours */
    if (params.term && data.id == "autre") {
        return data;
    }
    /* Sinon utilisation de la recherche classique */
    return defaultMatcher(params, data);
}

/*la fonction de mise à jour de l'affichage des champs*/
function updateFields() {
    /* Si la valeur du champ instrument est "autre" on affiche les champs supplémentaire, sinon on les masque */
    if ($("#instrument").val() == "autre") {
        $("#otherInstrumentCategory").parents(".form-group").css("display", "block");
        $("#otherInstrument").parents(".form-group").css("display", "block");
    } else {
        $("#otherInstrumentCategory").parents(".form-group").css("display", "none");
        $("#otherInstrument").parents(".form-group").css("display", "none");
    }
}

Ce plugin peux être adapté de façon diverse, comme par exemple pour générer un font-picker comme vu dans un article précédent.

jQuery : soumettre un formulaire contenant des fichiers grâce à FormData

Aujourd’hui il est possible d’uploader des fichiers en ajax grâce à XMLHttpRequest Niveau 2 et l’interface FormData de javascript. Pour l’utiliser avec la méthode ajax de jQuery il suffit de lui passer comme données l’objet FormData et de configurer les options correctement comme ci-dessous.

    //au clic du bouton submit des formulaires ayant la classe "form-ajax"
    $(document).on("submit", ".form-ajax", function (e) {
        e.preventDefault();//on bloque l'envoie classique
        var formData = new FormData($(this)[0]);//récupération des données du formulaire dans l'objet FormData
        //appel ajax jQuery
        $.ajax({
            url: '/ma/route/ajax',
            method: "POST",
            data: formData,
            processData: false,//ne pas oublier cette option
            contentType: false,//ne pas oublier cette option
            error: function (msg, string) {
                //gestion des erreurs
            },
            success: function (response) {
                //gestion de la réponse
            }
        });
    });

De cette manière vous pouvez traiter coté serveur le formulaire de la même manière que si il n’était pas en ajax.

Pour un exemple de traitement d’upload d’image coté serveur en php vous pouvez vous référer a cet article

jQuery : Créer un « font picker » avec le plugin Select2

Créer une liste déroulante (select) proposant un choix parmi plusieurs polices de caractères, tout en permettant de prévisualiser le style d’écriture de la police dans cette liste n’est pas la chose la plus évidente à mettre en place.
Ci-dessous une image présentant le résultat recherché. Et ici une page de démonstration

font-picker

Pour réaliser cela nous allons utiliser le plugin jQuery select2 qui permet de transformer les listes déroulantes. On peux grâce à lui avoir un champs de recherche dans la liste -ce n’est pas la fonctionnalité qui nous intéresse- on peux aussi donner du styles aux options, c’est ce que l’on va utiliser.

On commence donc par importer jQuery et ce plugin sur notre page, ainsi que les polices que l’on va proposer, j’utilise ici l’outil google fonts pour cela.

<!-- google fonts -->
<link href="https://fonts.googleapis.com/css?family=Alfa+Slab+One|Amatic+SC|Anton|Cinzel|Cutive+Mono|Frijole|Great+Vibes|Indie+Flower|Josefin+Sans|Just+Another+Hand|Lobster|Monoton|Pacifico|Permanent+Marker|Playfair+Display|Raleway|Righteous|Roboto+Condensed|Roboto+Slab|Saira+Semi+Condensed|Sedgwick+Ave+Display" rel="stylesheet">
<!-- jquery + select2 -->
<script src="./js/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
<!-- le script nous permettant de mettre en place le font picker -->
<script src="./js/font-picker.js"></script>

Dans la page on utiliser une balise select classique à laquelle on attribue un identifiant particulier (ici « select-font »)

<select id="select-font" class="form-control">
 <option value="Arial">Arial</option>
 <option value="Times New Roman">Times New Roman</option>
 <option value="Alfa Slab One">Alfa Slab One</option>
 <option value="Amatic SC">Amatic SC</option>
 <option value="Anton">Anton</option>
 ....
</select>

Et voici ci-dessous les quelques lignes de javascript permettant de faire fonctionner le système.

$(document).ready(function () {
    //on applique le plugin "select2" sur notre liste deroulante en lui indiquant d'utiliser un template particulier
    $("#select-font").select2({templateResult: formatFont}).on('change', function (e) {
        updateSelectFontStyle($(this));
    });
    //on initialise la liste au chargement de la page en fonction de la police sélectionné.
    updateSelectFontStyle($("#select-font"));
});

/**
 * Permet d'appliquer la bonne police sur l'option du select2
 */

function formatFont(opt) {
    if (!opt.id) {
        return opt.text;
    }
    var $state = $('<span style="font-family:\'' + opt.element.value + '\';"> ' + opt.text + '</span>');
    return $state;
}

/**
 * Donne la font family sélectionné à l'élément passé en paramètre
 */

function updateSelectFontStyle($el) {
    var font = $el.val();
    var id = '#select2-' + $el.attr("id") + '-container';
    $(id).css("font-family", "'" + font + "'");
}

Terminé !