blog.roxing.net

weblog roxing.net - astuces spip, php, bash, linux & more

Il y a 31 articles
  • Virtualisation facile !

    Installer et configurer LXC sur Debian Jessie en trois coups de cuiller à pot

    Installation de LXC

    1. apt-get install lxc lxctl

    Création d’un container

    1. lxc-create -n NomContainer -t debian

     -n nom du container
     -t template de l’OS à utiliser

    Bien noter le mot de passe root qui s’affichera à la fin de la création du container lxc.

    Configuration du réseau sur l’hôte

    Il y a plusieurs façons de configurer le réseau, pour ma part je préfère créer un (ou plusieurs) sous-réseaux pour mes containers qui seront "natter" par la machine hôte.
    Pour illustrer, on pourrait dire que les sous-réseaux sont cloisonnés à l’intérieur de l’hôte qui fera office de pare-feu vers l’extérieur.

    Autoriser "l’ip forwarding"

    1. nano /etc/sysctl.conf
    2. net.ipv4.ip_forward=1

    Télécharger

    Recharger la configuration du système pour prendre en compte la modification.

    1. sysctl -p

    Configurer l’interface qui servira de bridge

    La paquet bridge-utils est nécessaire, il est normalement installé en dépendance de lxc, au cas ou :

    1. apt-get install bridge-utils

    Paramétrage de /etc/network/interfaces

    Redémarrer le service réseau afin de prendre en compte la nouvelle interface br0

    1. service networking restart

    Vérifier que l’interface réseau est bien présente :
    ifconfig devrait renvoyer quelque chose comme ça

    1. br0       Link encap:Ethernet  HWaddr 22:ce:06:00:1d:7f  
    2.           inet adr:192.168.100.254  Bcast:192.168.100.255  Masque:255.255.255.0
    3.           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
    4.           RX packets:0 errors:0 dropped:0 overruns:0 frame:0
    5.           TX packets:24 errors:0 dropped:0 overruns:0 carrier:0
    6.           collisions:0 lg file transmission:0
    7.           RX bytes:0 (0.0 B)  TX bytes:3915 (3.8 KiB)

    Télécharger

    Activer le partage de connexion internet pour les containers LXC :

    On va donner l’accès internet aux containers LXC à travers wlan0 (On verra comment automatiser ça sur un hôte au profil itinérant qui se connecte sur des interfaces diverses et variées : wlan0 eth0 usb0... )

    1. iptables -t nat -F POSTROUTING
    2. iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE

    Télécharger

    Configuration du réseau sur les containers LXC

    Attention ! il ne s’agit pas de paramétrer le réseau à l’intérieur du container mais d’éditer un fichier de configuration qui se chargera de configurer le réseau au démarrage de celui-ci.

    Par défaut, Debian installe les nouveaux containers dans /var/lib/lxc ; ce dossier contient tous les containers créés, qui eux-même contiennent des fichiers de logs, de configs et le dossier rootfs qui comme son nom l’indique, correspond à la racine du système virtualisé ( / ).

    Afin de configurer le réseau sur notre container LXC, nous allons éditer son fichier de config /var/lib/lxc/NomContainer
    Extrait de la configuration réseau d’un container /var/lib/lxc/NomContainer/config

    1. lxc.network.type = veth
    2. lxc.network.name = veth0
    3. lxc.network.flags = up
    4. lxc.network.link = br0
    5. lxc.network.veth.pair = veth0
    6. lxc.network.ipv4 = 192.168.100.1/24
    7. lxc.network.ipv4.gateway = 192.168.100.254

    Télécharger

    Démarrage du container et test du réseau

    1. lxc-start -n NomContainer -d


     -n nom du container
     -d en mode daemon

    La commande pour contrôler si notre container LXC est bien démarré :

    1. lxc-ls -f

    Devrait retourner

    1. NAME           STATE       IPV4              IPV6  AUTOSTART  
    2. ---------------------------------------------------------
    3. NomContainer  RUNNING  192.168.100.1  -     NO  

    Télécharger

    Sur l’hôte un petit ping 192.168.100.1 devrait retourner :

    1. PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data.
    2. 64 bytes from 192.168.100.1: icmp_seq=1 ttl=64 time=0.087 ms

    Télécharger

    On va se connecter directement au container LXC

    1. lxc-console -n NomContainer

    Se connecter au container, j’espère que vous avez bien noté le mot de passe root lors de sa création sinon vous pouvez toujours consulter l’article dédié au changement de mot de passe root d’un container LXC.
    Une fois connecté, on va tester l’accès internet en utilisant apt pour installer ping afin de "pinguer" la machine hôte :

    1. root@NomContainer:~#apt-get install inetutils-ping
    2. Les NOUVEAUX paquets suivants seront installés :
    3.   inetutils-ping
    4. (...)
    5. Paramétrage de inetutils-ping (2:1.9.2.39.3a460-3) ..
    6. root@NomContainer:~#ping 192.168.100.254
    7. PING 192.168.100.254 (192.168.100.254): 56 data bytes
    8. 64 bytes from 192.168.100.254: icmp_seq=0 ttl=64 time=0,163 ms
    9. 64 bytes from 192.168.100.254: icmp_seq=1 ttl=64 time=0,163 ms

    Télécharger

    Et voilà, Juste ça marche !


    Pierrox

    P.-S.

    Pour quitter un container, utilisez la combinaison de touche ctrl+a puis q

  • Exemple de redirection 301 par entête http via le pipeline affichage_entetes_final

    Utilisation du pipeline affichage_entetes_final sur SPIP pour faire des redirections HTTP 301,404. Dans l’exemple suivant, lorsqu’un utilisateur tente d’afficher la page d’inscription, on le redirige sur sa page personnelle.

    Au sein d’un plugin

    Dans le cadre de la création d’un plugin, après avoir déclaré le pipeline dans paquet.xml

    1. function prefixPlugin_affichage_entetes_final($entetes){
    2. # Rediriger un auteur authentifié vers sa page perso lorsque il demande  à afficher la page inscription
    3.    if ( isset($GLOBALS['auteur_session']['id_auteur'])
    4.         AND (_request('page') === "inscription") ) {
    5.             $entetes["status"]= "301 Moved Permanently";
    6.             $entetes["Location"]=  generer_url_entite($GLOBALS['auteur_session']['id_auteur'],"auteur");
    7.     }
    8. return $entetes;
    9. }

    Télécharger

    Dans le dossier de personnalisation

    Dans le dossier squelette habituel, il faut ajouter au fichier mes_fonctions.php une fonction que l’on peut nommer par exemple "redirections_persos".

    1. # squelettes/mes_fonctions.php
    2. function redirections_persos($entetes){
    3.     # Rediriger un auteur authentifié vers sa page perso lorsque il demande  à afficher la page inscription
    4.    if ( isset($GLOBALS['auteur_session']['id_auteur'])
    5.         AND (_request('page') === "inscription") ) {
    6.             $entetes["status"]= "301 Moved Permanently";
    7.             $entetes["Location"]=  generer_url_entite($GLOBALS['auteur_session']['id_auteur'],"auteur");
    8.     }
    9. return $entetes;
    10. }

    Télécharger

    Puis dans config/mes_options.php on lie notre fonction au pipeline affichage_entetes_final

    1. # config/mes_options.php
    2. $GLOBALS['spip_pipeline']['affichage_entetes_final'] .= "|redirections_persos";

    Télécharger


  • Astuce pour scinder un titre et styliser son affichage

    On est parfois confronté au souhait d’afficher une version raccourcie d’un #TITRE d’article ; typiquement dans un menu de navigation latéral où l’espace est précieux, ou bien si l’on souhaite mettre en exergue une partie seulement du titre (les n premiers mots).

    Prenons l’exemple trivial d’un #TITRE un peu long :

    La buvette des joyeux pétanqueurs reprend du service à la fin du mois de juin.

    Comment faire pour gérer toute la longueur du titre dans une mise en page où la titraille est imposante ?

    Il existe le fameux filtre |couper qui s’avère souvent très efficace, quoiqu’il peut opérer une césure malvenue, et que l’on perd une partie de l’information.
    D’aucun serait tenté de jouer entre les valeurs des champs #TITRE, #SURTITRE (voire #SOUSTITRE) ; par exemple, ces derniers étant une version étendue du premier. Il s’agit, je pense, d’une mauvaise solution qui implique une certaine redondance d’information, sans compter un usage fastidieux.

    Et donc l’astuce je vous la donne.
    En insérant un espace insécable   au bon endroit :

    La buvette des joyeux pétanqueurs reprend du service à la fin du mois de juin.

    Combiner à cela, un petit filtre maison à mettre dans son fichier mes_fonctions.php

    1. function scinder($texte){
    2.   $txt = explode(" ", $texte);
    3.   if (is_array($txt) AND isset($txt[1]))
    4.     $texte = "<strong>".$txt[0]."</strong><span> ".$txt[1]."</span>";
    5.   return $texte;
    6. }

    Télécharger

    On obtient un titre dont la première partie est contenue dans un <strong>, et la suite dans un <span>.
    Dès lors on peut faire ce que l’on veut avec du CSS, sans trop de vérification de conditions ni de variantes de squelette.

    1. h2{}
    2. h2 strong {color: #954141;font-size: 3em}
    3. h2 span {color:#437788;font-size: 1em}

    Télécharger

    Libre à vous d’inclure le code où vous le souhaitez dans votre squelette, au cas par cas :

    [<h2>(#TITRE|scinder)</h2>]

    Enfin, si vous souhaitez l’appliquer à toutes les balises #TITRE de manière automatique, vous pouvez définir une règle sur la table des traitements dans mes_options.php :

    $GLOBALS['table_des_traitements']['TITRE'][]= 'scinder(%s)';

  • Description des tables d’un objet

    Comment ajouter un statut de publication personnalisé à un objet spip ?

    L’avantage de bien décrire une table d’objet spip et de bénéficier des mécanismes de publication sans avoir à retoucher les boucles et les fonctions "d’institution".

    Dans l’exemple ci-dessous on va créer un statut supplémentaire ’a_completer’ afin de pouvoir mettre en ligne un objet éditorial dont la rédaction serait incomplète.

    Ajouter un statut ’a_completer’ considéré comme publiable.

    1. //(...)
    2.  'statut_textes_instituer' => array(
    3.                 'prepa'    => 'texte_statut_en_cours_redaction',
    4.                 'prop'     => 'texte_statut_propose_evaluation',
    5.                 'publie'   => 'texte_statut_publie',
    6.                 'refuse'   => 'texte_statut_refuse',
    7.                 'poubelle' => 'texte_statut_poubelle',
    8.                 'a_completer' => 'texte_statut_publiable_mais_a_completer',
    9.             ),
    10.             'statut'=> array(
    11.                 array(
    12.                     'champ'     => 'statut',
    13.                     'publie'    => 'publie,a_completer',
    14.                     'previsu'   => 'publie,prop,prepa,a_completer',
    15.                     'post_date' => 'date',
    16.                     'exception' => array('statut','tout')
    17.                 )
    18.             ),
    19. //(...)
    20. )

    Télécharger

    Inutile de se soucier des critères de boucles et de passer par l’édition de squelettes !


  • Désactiver la prévisu message forum à l’aide du pipeline formulaire_verifier

    Il est souvent pénible de devoir surcharger tout le formulaire forum de spip pour désactiver seulement la prévisualisation. Je vais présenter une astuce simple et rapide à mettre en place sans avoir besoin de toucher au squelette ni surcharger quoi que ce soit.

    Supprimer la prévisualisation sur SPIP 3.0

    Dans le cadre d’un plugin, on déclare les pipelines dans un fichier paquet.xml.

    Pour un squelette spip classique, il faut déclarer les pipelines dans mes_options.php et "appeler" la fonction dans mes_fonctions.php

    1. //mes_options.php
    2. $GLOBALS['spip_pipeline']['formulaire_verifier'] .= "|supprimer_previsu";

    Télécharger

    1. //mes_fonctions.php
    2. function supprimer_previsu($flux){
    3.     if($flux['args']['form'] === 'forum')  
    4.         unset($flux['data']['previsu']);
    5.     return $flux;
    6. }

    Télécharger

    A noter qu’il existe également un plugin tout prêt disponible sur les dépots de spip contrib.

    Supprimer la prévisualisation sur SPIP 3.1 et supérieur

    On se contentera de $GLOBALS["meta"]["forums_forcer_previsu"]="non"; dans mes_options.php pour un résultat similaire.

    Voilà

    *** Pensez à vider les caches ***

    Et voilà, les messages postés dans les formulaires forum ne passeront plus par l’étape de prévisualisation !


  • Lire directement les vidéos youtube (& cie) dans VLC

    S’affranchir efficacement de flash pour lire les vidéos directement dans VLC

    Vous le savez comme moi, flash c’est le mal. Et voici LA solution qui vous fera franchir le pas d’un bannissement (espérons permanent) du vil greffon sans pour autant faire une croix sur les vidéos des plateformes d’hébergement (youtube, dailymotion, vimeo, etc).

    Cela consiste en l’emploi coordonné de deux scripts qui vont vous permettre de lire directement une vidéo distante dans votre lecteur habituel (VLC, mplayer ou autre).

    1) Installation de youtube-dl

    Sous GNU-Linux, la méthode que je trouve la plus simple est de passer par le gestionnaire d’environnement python pip.

    1. sudo apt-get install python-pip
    2. sudo pip install youtube-dl

    Veillez à mettre à jour l’application de temps en temps, car les plugins de gestion par plateforme sont nombreux et les modifications fréquentes.

    1. sudo pip install -U youtube-dl

    2) Lancement illico grâce à vlcopen.sh

    youtude-dl est un super logiciel, efficace dans bien des situations, mais son utilisation en ligne de commande s’avère à la longue un peu rédhibitoire pour une utilisation en tant que simple utilisateur.

    D’où le recours à un second script, mis à disposition par swarminglogic,qui va apporter un peu de souplesse d’utilisation et ouvrir la vidéo encore plus vite que si vous y aviez accédée directement depuis la page youtube, grâce à un raccourci clavier.

    1. #!/bin/bash
    2.  
    3. if [ $# -eq 1 ] ; then
    4.     path=$1
    5. else
    6.     clipboard=$(xclip -selection clipboard -o)
    7.     if [ $(<<<$clipboard grep -P "^http") ] ; then
    8.         path=$clipboard
    9.     else
    10.         if [ -t 1 ] ; then
    11.             echo "Bad clipboard path: $clipboard" >&2
    12.         else
    13.             notify-send "Bad clipboard path: $clipboard"
    14.         fi
    15.         exit 1
    16.     fi
    17. fi
    18.  
    19. #$1 processid, $2 tempdir $3 logfile
    20. function cleanup {
    21.     echo "-------------------------------------------"
    22.     echo "Cleaning up"
    23.     kill -9 $1 &> /dev/null
    24.     if [ -n "$2" ] ; then rm $2/* ; fi
    25.     if [ -n "$2" ] ; then rmdir $2 ; fi
    26.     if [ -n "$3" ] ; then rm $3 ; fi
    27. }
    28.  
    29.  
    30. echo "Opening $path"
    31. tmpvlcopen=/tmp/vlcopen/
    32. [ ! -d $tmpvlcopen ] && mkdir $tmpvlcopen
    33. tmpdir=$(mktemp -d --tmpdir=$tmpvlcopen)
    34.  
    35. # If the tmpdir path doesn't include "/tmp/vlcopen" something went bad!
    36. if [ "${tmpdir/$tmpvlcopen}" = "$tmpdir" ] ; then
    37.     echo "Aborting: failed to create proper temporary directories" >&2
    38.     exit 1
    39. fi
    40.  
    41. cd $tmpdir
    42. echo "Temporary directory: $tmpdir"
    43. echo "Getting video: $path"
    44. downloadlog=$(tempfile)
    45. (youtube-dl --restrict-filenames --no-part "$path" &> $downloadlog)&
    46. processId=$!
    47. echo "ProcessID: $processId"
    48. echo "Waiting for file creation"
    49.  
    50. count=0
    51. while [ $(ls -1 | wc -l) -eq 0 ] ; do
    52.     # check if process is done.
    53.     if ! kill -0 $processId &>/dev/null ; then
    54.         if [ -t 1 ] ; then
    55.             echo "-------------------------------------------">&2
    56.             echo "Error: youtube-dl finished without output." >&2
    57.             echo "Error: Bad URL?" >&2
    58.             echo "---------------- Download Log -------------">&2
    59.             cat $downloadlog >&2
    60.         else
    61.             notify-send "Bad URL: $path $(cat $downloadlog)"
    62.         fi
    63.         cleanup $processId "$tmpdir" "$downloadlog"
    64.         exit 0
    65.     fi
    66.     sleep 0.5
    67.     ((count++))
    68.     if [ $count -eq 20 ] ; then
    69.         if [ -t 1 ] ; then
    70.             echo "Timed out" >&2
    71.         else
    72.             notify-send "Timed out"
    73.         fi
    74.         exit 0
    75.     fi
    76. done
    77.  
    78. sleep 0.1
    79. echo "Opening file: $(ls -1 | head -n 1)"
    80. vlc "$(ls -1 | head -n 1)" &>/dev/null
    81. cleanup $processId "$tmpdir" "$downloadlog"

    Télécharger

    Ce script se comporte comme une capsule pour youtube-dl. Il va analyser le contenu du presse-papier, et s’il détecte une url prise en charge, va créer un répertoire temporaire, y télécharger la vidéo, l’ouvrir avec VLC après quelques instants et supprimer automatiquement tous les fichiers temporaires à la fermeture.

    Il suffit d’enregistrer le script (sous le nom vlcopen.sh par exemple) dans un répertoire inclus dans votre $PATH, le rendre exécutable (chmod +x vlcopen.sh) et d’associer un raccourci clavier à son exécution.

    Typiquement sous openbox, j’ai rajouté une section comme suit à mon rc.xml.

    1. <keybind key="W-y">
    2.   <action name="Execute">
    3.     <startupnotify>
    4.       <enabled>true</enabled>
    5.       <name>vlcopen</name>
    6.     </startupnotify>
    7.     <command>vlcopen.sh</command>
    8.   </action>
    9. </keybind>

    Dès lors, dans les faits, lorsque je veux regarder une vidéo, je fais un clic-droit > copier l’url de la page soit sur la page courante, soit sur le lien à analyser, puis super + y (oui j’ai choisi y pour "youtube" mais à vous d’adapter au besoin), et voilà !

    Seul bémol, si la vidéo est longue et que vous êtes impatient, vous ne pourrez pas avancer directement la lecture à un point qui n’a pas encore été téléchargé.

    source github.com/swarminglogic


  • Dans le cadre d’une installation en dual boot MAC OS / Debian, il peut s’avérer fastidieux de synchroniser ses périphériques bluetooth avec un identifiant commun entre les systèmes.

    La marche à suivre consiste à opérer la synchronisation sous OS X, puis booter sous GNU/Linux, monter la partition OS X, par exemple :
    sudo mount -t hfsplus /dev/sda2 /media/OSX/

    Puis à exécuter ce script [1] :

    1. #!/bin/sh
    2. # sync-bt-os.sh
    3. cd /var/lib/bluetooth
    4. for i in *; do
    5.     cd "$i"
    6.     plutil -i /media/OSX/private/var/root/Library/Preferences/blued.plist -o /dev/stdout |
    7.     perl -0777 -MMIME::Base64 -ne 's|\s||g; $s = $_; while ($s =~ m|<key>(..-..-..-..-..-..)</key><data>(.*?)</data>|g) { $mac = uc($1); $key = uc(unpack("H*",reverse decode_base64($2))); $mac =~ s/-/:/g; $pinlength = 6; $pinlength = 4 if $mac eq "C4:2C:03:A0:C7:20"; print "$mac $key 0 $pinlength\n"; }' |
    8.     tee linkkeys
    9.     cd ..
    10. done
    11. service bluetooth restart

    Télécharger


    placido

    Notes

    [1Il vous faudra probablement installer le paquet plutil, via apt par exemple.

  • Une fonction qui permet de créer/supprimer des liens symboliques facilement vers les répertoires couramment utilisés. Classe non ?

    Il faut rajouter ceci dans son /.bash_aliases :

    1. #Filesystem Markers & Jump
    2. ###########################
    3. export MARKPATH=$HOME/.marks
    4. function jump {
    5.     cd -P $MARKPATH/$1 2>/dev/null || echo "No such mark: $1"
    6. }
    7. function mark {
    8.     mkdir -p $MARKPATH; ln -s $(pwd) $MARKPATH/$1
    9. }
    10. function unmark {
    11.     rm -i $MARKPATH/$1
    12. }
    13. function marks {
    14.     ls -l $MARKPATH | sed 's/  / /g' | cut -d' ' -f9- | sed 's/ -/\t-/g' && echo
    15. }

    Télécharger

    Le code est assez explicite, mais à l’usage voilà ce que cela donne :

    Créer un raccourci

    1. cd chemin/vers/mon/projet1
    2. mark projet1

    Télécharger

    Usage

    1. jump projet1

    Lister les raccourcis déjà créés

    1. marks

    Supprimer le raccourci

    1. unmark projet1

  • Aide mémoire listant toutes les variables # !shell utiles pour l’écriture de # !scripts .

    Manipulation de variables simples

    var=val
    var="a b"
    affectation de la variable "var"
    $var
    ${var}
    contenu de la variable "var"
    ${#var} longueur de la variable "var"
    ${var:-valeur} affectation conditionnelle, si "var" non défini alors var = valeur
    export var
    declare -x var
    exportation de la variable "var" vers les shells fils
    set affichage de l’ensemble des variables définies dans le shell
    unset var suppression de la variable "var"

    Tableaux

    tab[0]=val affectation du premier enregistrement du tableau "tab"
    ${tab[0]}
    $tab
    contenu du premier enregistrement du tableau "tab"
    ${tab[11]} contenu du douzième enregistrement du tableau "tab"
    ${tab[*]} ensemble des enregistrements du tableau "tab"
    ${#tab[11]} longueur du douzième enregistrement du tableau "tab"
    ${#tab[*]} nombre d’enregistrements du tableau "tab"
    ${!tab[@]} liste des clefs ( Index ) du tableau "tab"

    Paramètres positionnels et arguments

    $0 nom du script
    $1 $2 ... ${10} paramètres positionnels (1, 2 et 10)
    $# nombre de paramètres positionnels
    $*
    $@
    ensemble des paramètres positionnels, équivalant à $1 $2 ... $n

    Variables spéciales

    $$ PID du shell courant
    $! PID du dernier travail lancé en arrière plan
    $? code retour de la dernière commande
    ${PIPESTATUS[0]} code retour de la première commande d’un pipe

    Variables d’environnement

    $HOME chemin du répertoire personnel de l’utilisateur
    $OLDPWD chemin du répertoire précédent
    $PATH liste des chemins de recherche des commandes exécutables
    $PPID PID du processus père du shell
    $PS1 invite principale du shell
    $PS2 invite secondaire du shell
    $PS3 invite de la structure shell "select"
    $PS4 invite de l’option shell de débogage "xtrace"
    $PWD chemin du répertoire courant
    $RANDOM nombre entier aléatoire compris entre 0 et 32767
    $REPLY variable par défaut de la commande "read" et de la structure shell "select"
    $SECONDS nombre de secondes écoulées depuis le lancement du shell

  • Quelques commandes bash utiles pour mysql

    1. su -c "mysqldump -u$user-p$password $mydatabase | bzip2 > /$mypath/`date +%F-%H%M`_$output.sql.bz2" $user

    Sauvegarder toute la base en concaténant le nom de l’hostname + la date pour le nom du fichier de sauvegarde :

    1. mysqldump -u$user -p$password --all-database | bzip2 > $(date +%F-%H%M)-$(hostname -A).tar.bz2

    En théorie la commande ci-dessus devrait fonctionner sans problème.
    J’ai eu un bug ? sur ma debian, avec le résultat de la commande de hostname -a qui me renvoyait systématique un espace en fin de chaîne.

    Je vous laisse apprécier la basherie ci-dessous visant a nommer le fichier de sortie en supprimant l’espace indisposant avec la commande sed.

    1. mysqldump -u$user-p$pass --all-databases | bzip2 > $(echo "$(date +%F-%H%M)-$(hostname -A)" | sed 's/ //g').sql.bz2

    Pour importer une sauvegarde Mysql au format bz2 sans faire une décompression préalable.

    1. bunzip2 < dump.sql.bz2 | mysql -uuser -ppass database

  • Charger le contenu depuis un CDN

    Plutôt que de stocker JQuery sur votre serveur, vous pouvez choisir un CDN [1] notoire. Cela devrait réduire le temps de chargement de la page.

    <!--:( -->
    <script src="/vendor/jquery/jquery.min.js"></script>
    <!-- :) -->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

    Voici une liste de CDN fournissant un accès à la bibliothèque JQuery :

    Les bonnes pratiques ne concernent pas seuelement JQuery ; les éléments d’affichage - type CSS ou autre - peuvent aussi être chargés parallèlement.

    Prévoir une méthode de chargement alternative en cas de défailllance du CDN

    1. <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    2. <script>window.jQuery || document.write("<script src='/vendor/jquery/jquery.min.js'>\x3C/script>");</script>

    Télécharger

    Préférer les versions compressées

    1. <!-- :( -->
    2. <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.js"></script>
    3. <!-- :) -->
    4. <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

    Télécharger

    Placer l’appel au script en fin de page plutôt qu’en en-tête

    1. <!doctype html>
    2. <head>
    3. ...
    4. <!-- :( -->
    5. <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    6. </head>
    7. <body>
    8. ...
    9. <!-- :) -->
    10. <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    11. </body>
    12. ...

    Télécharger

    Utiliser des URLs en chemins relatif

    Pas besoin de spécifier le protocole http ou https. Le navigateur optera de lui-même pour le protocole https s’il se trouve déjà dans un environemment sécurisé.

    1. <!-- :( -->
    2. <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    3. <!-- :) -->
    4. <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

    Télécharger

    Raccourci pour l’événement ready

    1. // Appel classique
    2. $(document).ready(function() {
    3. ...
    4. });
    5. // Version rapide
    6. $(function() {
    7. });

    Télécharger

    Garder le $ lors de la déclaration d’une variable de type jQuery.

    Grâce à cette convention de nommage, on distingue facilement la nature de l’objet JQuery.

    1. // :(
    2. var form = $('#contactForm');
    3. // :)
    4. var $form = $('#contactForm');

    Télécharger

    Du bon usage de $this

    La variable $this s’utilise avantageusement au début des fonctions non déclarées, par exemple dans une boucle de type each.

    1. // :(
    2. $('li').each(function() {
    3. $(this).on('click', function() {
    4. $(this).addClass('active');
    5. });
    6. });
    7. // :)
    8. $('li').each(function() {
    9. var $this = $(this);
    10. $this.on('click', function() {
    11. $this.addClass('active');
    12. });
    13. });

    Télécharger

    Certains préfèrent utiliser that ou self. Attention de ne pas oublier qu’il s’agit d’un objet jQuery.

    Mettre en cache les objets jQuery

    Si un objet jQuery est utilisé plusieurs fois, le mettre en cache permet d’optimiser les performances.

    1. // :(
    2. $('.menu li').each(function() { ... });
    3. $('.menu li').each(function() { ... });
    4. // :)
    5. var $items = $('.menu li');
    6. $items.each(function() { ... });
    7. // on recycle :)
    8. $items.each(function() { ... });

    Télécharger

    Enchaînement des fonctions

    C’est asssurément l’une des fonctionalités les plus appréciée de jQuery. On peut ainsi appeler une série de méthodes dans la même foulée.

    "Write less, do more", garder en tête le slogan de jQuery
    1. // :(
    2. var $a = $('#about');
    3. $a.hide();
    4. $a.addClass();
    5. $a.fadeIn();
    6. $a.hide();
    7. // :)
    8. $('#about').hide().addClass().fadeIn().hide();
    9. // c'est mieux
    10. // Retour à la ligne et identation améliorent la visibilité
    11. $('#about')
    12. .hide()
    13. .addClass()
    14. .fadeIn()
    15. .hide();

    Télécharger

    Déclarer un nouvel élément

    Lors de la création d’un élément, faîtes en sorte de manipuler les éléments via les méthodes jQuery plutôt que d’insérer du code HTML brut.

    1. // Don't
    2. var $hidden = $('<input class="form-control" type="hidden" name="foo" value="bar" />').appendTo('#form');
    3. // :)
    4. var $hidden = $('<input/>')
    5. .addClass('form-control')
    6. .attr('type', 'hidden')
    7. .attr('name', 'foo')
    8. .val('bar')
    9. .appendTo('#form');
    10. // ou bien
    11. var $hidden = $('<input/>', {
    12. class: 'form-control',
    13. type: 'hidden',
    14. name: 'foo',
    15. value: 'bar'
    16. }).appendTo('#form');

    Télécharger

    Garder le CSS loin des manipulations de jQuery

    Pas la peine de déclarer le style CSS directement à un élément. Le recours aux classes est fait pour ça.

    1. // :(
    2. $('#button').css({
    3. 'background-color': '#5cb85c',
    4. 'border-color': '#4cae4c'
    5. });
    6. // :)
    7. .success {
    8. background-color: #5cb85c;
    9. border-color: #4cae4c;
    10. }
    11. $('#button').addClass('success');

    Télécharger

    Choisir le bon sélecteur

    Le sélecteur désignant l’id est le plus rapide

    Pour retrouver un élément du DOM en fonction de son id, jQuery utilise la méthode native document.getElementById() qui s’avère bien plus efficace que Sizzle.

    Sizzle is a pure-JavaScript CSS selector engine used by jQuery
    1. // :(
    2. $('#wrapper #inner');
    3. $('div#inner');
    4. $('.wrapper #inner');
    5. // :)
    6. $('#inner');

    Télécharger

    Du coup, mieux vaut introduire une recherche sur un id, quitte à enchaîner les recherches.

    1. // :(
    2. $('#container .row');
    3. // + rapide
    4. $('#container').find('.row');

    Télécharger

    Sélecteurs restrictifs

    Il faut être spécifique sur le partie gauche de votre sélecteur, et moins en début.

    1. // pas glup
    2. $('div.data .gonzalez');
    3. // glup glup
    4. $('.data td.gonzalez');

    Télécharger

    Éviter le recours aux sélecteurs universels

    1. // moins rapide
    2. $('div.container > *');
    3. // Plus rapide
    4. $('.container').children();

    Télécharger

    Mieux vaut faire précéder les sélecteurs pseudo-class (ex :before) avec un tag ou un autre sélecteur. Car, si ce n’est pas le cas, le sélecteur universel * est implicitement employé.

    1. // :(
    2. $('.category :radio');
    3. // :)
    4. $('.category input:radio');

    Télécharger

    Privilégiez les méthodes de tri plutôt que les pseudos-sélecteurs.

    Lorsque cele est possible, utiliser la méthode de tri jQuery plutôt que des pseudos-sélecteurs. La méthode querySelectorAll s’avère là encore plus rapide que la méthode Sizzle.

    1. // :(
    2. $('.item:first')
    3. // :)
    4. $('.item').eq(0)

    Télécharger

    Pas de javascript inline sur les élements HTML

    Mieux vaut attacher un écouteur d’événement à l’objet.

    1. <!-- :( -->
    2. <button id="saveButton" onclick="javascript: save();">Save</button>
    3. // :)
    4. $('#saveButton').on('click', function() {
    5. ...
    6. });

    Télécharger

    Choisir un namespace personnalisé pour les événements

    Ainsi il est plus facile de désactiver un événement sans affecter les autres écouteurs d’événements assignés à l’élément.

    1. $('#saveButton').on('click.bv', function() { ... });
    2. //Plus tard, on peut retirer sans crainte l'écouteur l'événement
    3. $('#saveButton').off('click.bv');

    Télécharger

    Ne pas passer les paramètres Ajax "en dur"

    Lorsque d’un requête de type xmlHttpRequest, il faut utiliser le paramètre data, et non concaténer l’information au sein de l’URL.

    1. // :(
    2. $.ajax({
    3. url: '/remote/url?param1=value1&amp;param2=value2...'
    4. }});
    5. // :)
    6. $.ajax({
    7. url: '/remote/url',
    8. data: {
    9. param1: 'value1',
    10. param2: 'value2'
    11. ...
    12. }
    13. });

    Télécharger

    Dans le cas où les paramètres à transmettre sont très long (ex : le contenu intégral d’un article), on privilégiera la méthode POST, à la fois pour Ajax et le traitement côté serveur.

    Internet Explorer 8 (and earlier) limits 2083 characters in URL

    source Best jQuery practices · Programmer Tips


    placido

    Notes

    [1Content Delivery Network : Un content delivery network (CDN) est constitué d’ordinateurs reliés en réseau à travers Internet et qui coopèrent afin de mettre à disposition du contenu ou des données (généralement du contenu multimédia volumineux) à des utilisateurs.