PROJET AUTOBLOG


Planet-Libre

source: Planet-Libre

⇐ retour index

®om : Commentaires statiques avec Jekyll

lundi 9 janvier 2017 à 18:06

Pour ce blog, j’ai abandonné Wordpress pour Jekyll, un moteur de blog statique.

Ainsi, j’écris mes articles en markdown dans mon éditeur favori, je les commite dans un dépôt git, et je génère le blog avec :

jekyll build

Le contenu hébergé étant statique, les pages ainsi générées à partir des sources sont renvoyées telles quelles.

Ce fonctionnement a beaucoup d’avantages :

Sans commentaires

L’inconvénient, c’est qu’un contenu statique est difficilement conciliable avec le support des commentaires (il faut bien d’une manière ou d’une autre exécuter du code lors de la réception d’un commentaire).

Il y a plusieurs manières de contourner le problème.

Il est par exemple possible d’en déporter la gestion (sur un service en ligne comme Disqus ou un équivalent libre – isso – à héberger soi-même). Ainsi, les commentaires peuvent être chargés séparément par le client en Javascript.

Au lieu de cela, j’ai choisi d’intégrer les commentaires aux sources du blog. Voici comment.

L’objectif est d’une part de pouvoir stocker et afficher les commentaires existants, et d’autre part de fournir aux lecteurs la possibilité d’en soumettre de nouveaux, qui me seront envoyés par e-mail.

Je me suis principalement inspiré du contenu de Jekyll::StaticComments, même si, comme nous allons le voir, je n’utilise pas le plug-in lui-même.

Stockage

L’idée est de stocker les commentaires quelque part dans les sources du site au format YAML.

Le plugin Jekyll::StaticComments nécessite de stocker un fichier par commentaire dans un dossier spécial (_comments) parsé par un script à insérer dans le répertoire _plugins.

Personnellement, je préfère avoir tous les commentaires d’un même post regroupés au sein d’un même fichier. Et pour cela, pas besoin de plug-in : nous pouvons faire correspondre à chaque post dans _posts une liste de commentaires dans _data (un répertoire géré nativement par Jekyll).

Par exemple, ce billet est stocké dans :

_posts/2017-01-09-commentaires-statiques-avec-jekyll.md

Dans l’idéal, je voudrais que les commentaires associés soient stockés dans :

_data/comments-2017-01-09-commentaires-statiques-avec-jekyll.yaml

En pratique, pour des raisons techniques (Jekyll ne donne pas accès au nom du fichier), le nom du fichier ne contient pas le numéro du jour :

_data/comments-2017-01-commentaires-statiques-avec-jekyll.yaml

Il suffit alors de stocker dans ces fichiers les commentaires sous cette forme :

- id: 1
  author: this_is_me
  date: 2017-01-02 10:11:12+01:00
  contents: |
    Bonjour,

    Ceci est un commentaire écrit en _markdown_.
- id: 2
  author: dev42
  author-url: https://github.com
  date: 2017-01-02 12:11:10+01:00
  contents: |
    > Ceci est un commentaire écrit en _markdown_.

    Et ça supporte aussi le [Liquid](https://jekyllrb.com/docs/templates/) :

    {% highlight c %}
    int main() {
        return 0;
    }
    {% endhighlight %}

Pour des exemples réels, voir les sources des commentaires de ce blog.

Affichage

Maintenant que nous avons les données des commentaires, nous devons les afficher.

Il faut d’abord trouver la liste des commentaires associée à la page courante.

Comme nous ne pouvons pas récupérer directement le nom du fichier d’une page, nous devons reconstruire la chaîne à partir de la variable page.id, qui ici vaut :

/2017/01/commentaires-statiques-avec-jekyll

Cette ligne de Liquid :

comments{{ page.id | replace: '/', '-' }}

donne la valeur :

comments-2017-01-commentaires-statiques-avec-jekyll

Nous avons donc tout ce dont nous avons besoin pour créer le template de commentaires (à stocker dans _include/comments.html) :

{% capture commentid %}comments{{ page.id | replace: '/', '-' }}{% endcapture %}
{% if site.data[commentid] %}
 id="comments">Commentaires
 class="comments">
    {% for comment in site.data[commentid] %}
         id="comment-{{ comment.id }}" class="comment" />
             class="comment-author">
                {% if (comment.author-url) %}
                     href="{{comment.author-url}}">
                {% endif %}
                {{ comment.author }}
                {% if (comment.author-url) %}
                    
                {% endif %}
            
class="comment-date"> href="#comment-{{ comment.id }}"> {{ comment.date | date: "%-d %B %Y, %H:%M" }}
class="comment-contents"> {{ comment.contents | liquify | markdownify }} {% endfor %}

Il suffit alors d’inclure cette page à l’endroit où vous souhaitez insérer les commentaires (typiquement dans _layout/post.html) :

{% include comments.html %}

Formulaire

Pour proposer aux utilisateurs de poster de nouveaux commentaires, il nous faut un formulaire.

À titre d’exemple, voici le mien (intégré à _include/comments.html) :

 class="comment-title">Poster un commentaire
 method="POST" action="/comments/submit.php">
     type="hidden" name="post_id" value="{{ page.id }}" />
     type="hidden" name="return_url" value="{{ page.url }}" />
     class="comment-table">
        
            Nom :
            
                 type="text" size="25" name="name" />
                (requis)
            
        
        
            E-mail :
            
                 type="text" size="25" name="email" />
                (requis, non publié)
            
        
        
            Site web :
            
                 type="text" size="25" name="url" />
                (optionnel)
            
        
        
             colspan="2">
                 name="comment" rows="10">
            
        
        
             colspan="2">
                 class="comment-submit" type="submit" value="Envoyer" />
            
        
    

Ce formulaire est affiché sous les commentaires existants.

Traitement

L’action du formulaire précédent pointait sur comments/submit.php. Il nous reste donc à écrire dans ce fichier le code à exécuter lorsqu’un utilisateur envoie un commentaire au serveur.

Ce sera la seule partie “dynamique” du site.

Voici les parties importantes de comments/submit.php (basé sur la version de Jekyll::StaticComments) :


$DATE_FORMAT = "Y-m-d H:i:sP";
$EMAIL_ADDRESS = "your@email";
$SUBJECT = "Nouveau commentaire";
$COMMENT_SENT = "sent.html";

$msg = "post_id: " . $_POST["post_id"] . "\\n";
$msg .= "email: " . $_POST["email"] . "\\n";
$msg .= "---\\n";
$msg .= "- id: ?\\n";
$msg .= "  author: " . $_POST["name"] . "\\n";
if ($_POST["url"] !== '')
{
    $msg .= "  author-url: " . $_POST["url"] . "\\n";
}
$msg .= "  date: " . date($DATE_FORMAT) . "\\n";
$msg .= "  contents: |\\n" . $_POST["comment"];

$headers = "From: $EMAIL_ADDRESS\\n";
$headers .= "Content-Type: text/plain; charset=utf-8";

if (mail($EMAIL_ADDRESS, $SUBJECT, $msg, $headers))
{
    include $COMMENT_SENT;
}
else
{
    echo "Le commentaire n'a pas pu être envoyé.";
}

Quand un commentaire est envoyé avec succès, la page comments/sent.html est affichée à l’utilisateur.

Ainsi, lorsqu’un commentaire est posté, je reçois un mail :

post_id: /2017/01/commentaires-statiques-avec-jekyll
email: my@email
---
- id: ?
  author: ®om
  author-url: http://blog.rom1v.com
  date: 2017-01-09 19:27:10+01:00
  contents: |
Ceci est un test.

J’ai d’ailleurs ajouté une règle procmail pour que ces mails arrivent dans un dossier dédié.

Je peux alors copier le contenu dans le .yaml correspondant, formatter le commentaire (entre autres l’indenter de 4 espaces, ce qu’on pourrait automatiser), et le commiter.

Résumé

Une fois mis en place, vous devriez donc avoir les fichiers suivants :

Conclusion

Je souhaitais depuis longtemps migrer vers un moteur de blog statique, qui correspond davantage à ma façon d’écrire des articles, et offre beaucoup d’avantages (légèreté, sécurité, maintenance…).

Je suis très content d’y être parvenu sans perdre les commentaires ni la possibilité d’en poster de nouveaux.

Certes, la validation est très manuelle, mais c’est le prix à payer pour avoir des commentaires statiques. Pour un blog avec une fréquence de commentaires assez faible, je pense que ce n’est pas très gênant.

Gravatar de ®om
Original post of ®om.Votez pour ce billet sur Planet Libre.

Journal du hacker : Liens intéressants Journal du hacker semaine #01

lundi 9 janvier 2017 à 00:01

Pour la première semaine de 2017, voici 5 liens intéressants que vous avez peut-être ratés, relayés par le Journal du hacker, votre source d’informations pour le Logiciel Libre francophone !

Pour ne plus rater aucun article de la communauté francophone, voici :

De plus le site web du Journal du hacker est « adaptatif (responsive) ». N’hésitez pas à le consulter depuis votre smartphone ou votre tablette !

Le Journal du hacker fonctionne de manière collaborative, grâce à la participation de ses membres. Rejoignez-nous pour proposer vos contenus à partager avec la communauté du Logiciel Libre francophone et faire connaître vos projets !

Et vous ? Qu’avez-vous pensé de ces articles ? N’hésitez pas à réagir directement dans les commentaires de l’article sur le Journal du hacker ou bien dans les commentaires de ce billet :)

Gravatar de Journal du hacker
Original post of Journal du hacker.Votez pour ce billet sur Planet Libre.

Carl Chenet : Journal du hacker et francophonie

lundi 9 janvier 2017 à 00:00

Petite précision avant de commencer, le terme francophonie est à prendre ici comme l’utilisation commune de la langue française par différentes communauté. Nous laissons de côté les liens politiques et historiques qui peuvent être recouverts par ce terme et qui sont hors-sujet dans le cadre de cet article. Si cette précision vous étonne, je pourrais développer à la demande dans les commentaires.

La démarche

Lorsque j’ai fondé le Journal du hacker, j’avais dans l’idée de réaliser un média participatif de la communauté du Logiciel Libre et open source francophone. Donc un média pas seulement dédié à la France, ce qui avec un peu de recul apparaîtrait comme arbitrairement restrictif quand on parle et agit via le web et qu’on souhaite s’exprimer en français.

Aujourd’hui le Journal du hacker vit grâce à ses utilisateurs et la formidable équipe qui l’anime. Nous sommes déjà bien au-dessus de mes espérances lorsque j’ai lancé le projet en terme de visites et de visibilité via les réseaux sociaux. Pourtant le point concernant l’ouverture du Journal du hacker à la francophonie reste pour l’instant largement en arrière par rapport aux autres axes de développement.

En effet, il est assez simple de lancer un projet dans la communauté la plus proche de nous, de se faire connaître par les médias qui nous entourent et les acteurs avec qui l’on peut échanger au quotidien. Et cela a été notre axe de développement jusqu’ici. Me rendant compte peu à peu du fossé qui nous séparait des autres communautés de la francophonie, j’ai été amené à commencer à découvrir les médias et communautés du Logiciel Libre hors de France. Il ne serait pas honnête de passer sous silence que le déclencheur de cette prise de conscience a été l’arrivée dans l’équipe du Journal du hacker du très sympathique Cloug, de nationalité belge.

Découvertes des acteurs

Je me suis donc lancé dans l’exploration des différentes communautés francophones du Libre. J’ai découvert avec grand plaisir un acteur québecois QuebecOS, qui vient de fêter ses 10 ans. Chapeau.

quebecos

En tournant ensuite mes recherches vers l’Afrique, j’ai donc découvert depuis l’association du Logiciel Libre CLibre en Tunisie, très active, ayant organisée cette année l’événement Software Freedom Day 2016. Également de nombreux acteurs individuels en Côte d’Ivoire, comme Florent Youzan, mettant en avant le Logiciel Libre et l’innovation mais aussi au Bénin, où a été organisé en 2016 les Rencontres Nationales du Logiciel Libre et les sympathiques activités du fablab Blolab toujours au Bénin.

Réalisation d'un Jerry au Blolab au Bénin

Réalisation d’un Jerry au Blolab au Bénin

J’ai également découvert l’engouement des communautés OpenStreeMaps, très (très) actives en Afrique qui sont un formidable moteur des idées du Libre auprès des acteurs locaux, car propulsés par un besoin réel et pressant : le besoin de cartographier des environnements se modifiant très rapidement en  l’absence d’un acteur étatique assurant ce service. Citons OpenStreetMaps Côté d’Ivoire et OpenStreetMaps Burkina Faso.

Collecte de données sur le terrain de contributeurs OpenStreetMaps

Collecte de données sur le terrain de contributeurs OpenStreetMaps

Je n’ai pas prétention à avoir identifier tout le monde et je dois rater un nombre incroyable d’initiatives francophones autour du Libre. Les commentaires sont ouverts pour m’informer à ce sujet 😉

Relayer les initiatives

Suite à l’identification des acteurs, j’ai commencé à utiliser le Journal du hacker pour relayer les initiatives francophones du Logiciel Libre, par exemple les Rencontres Nationales du Logiciel Libre 2016 au Bénin ou le Software Freedom Day 2016. C’est encore nettement insuffisant par rapport à ce qui doit se faire et j’espère motiver les acteurs à se saisir de l’outil Journal du hacker pour communiquer eux-mêmes sur les initiatives. Je souhaite par ces contributions montrer que nous sommes ouverts, attentifs à ces initiatives et que nous souhaitons les relayer.

Car le point critique est là. Les acteurs doivent eux-mêmes relayer leurs initiatives, sans dépendre du fait qu’ils pourraient ou non être relayés par un tiers. Le Journal du hacker est simple d’utilisation, très simple. Un lien, un titre (souvent récupéré automatiquement) et une marque. Et pour les initiatives intéressantes, une grande visibilité en retour.

Gravatar de Carl Chenet
Original post of Carl Chenet.Votez pour ce billet sur Planet Libre.

Ilphrin : Traduction: Maitriser $watch dans AngularJS

lundi 9 janvier 2017 à 00:00
Ce qui suit est une traduction d'un article sur [Sitepoint.com \\[lien d'origine\\]](https://www.sitepoint.com/mastering-watch-angularjs/), rédigé par [Marcello La Rocca](https://www.sitepoint.com/author/mlarocca/) et [Francisco Paulo.](https://www.sitepoint.com/author/fpaulo/) Je ne suis en aucun cas l'auteur de cet article, j'ai simplement eu envie de le traduire parce que j'aime ça et que je considère que beaucoup de ressources anglophones devraient être aussi à la portée des personnes qui ne parlent pas anglais. # Maitriser $watch dans AngularJS [AngularJS](https://angularjs.org/) dispose de plusieurs options pour appliquer le modèle [Publish-subscribe](https://fr.wikipedia.org/wiki/Publish-subscribe) à travers trois différentes méthodes "watch". Chacune prend différent paramètres optionnels qui peuvent modifier son comportement. La documentation officielle de $watch ne va pas vraiment en profondeur: un problème récurrent qui a affecté l'entièreté d'AngularJS 1 après tout. Même la plupart des ressources en ligne qui en expliquent le fonctionnement sont éparpillées. Et au final, il devient difficile pour un développeur de choisir la bonne méthode pour une situation donnée. Et cela est particulièrement vrai pour les débutants. Le résultat peut être pleins de surprises et est imprévisible, amenant inévitablement à des bugs. Dans cet article, je (Ndt: Les auteurs d'origine de cet article) vais partir du principe que vous avez les bases d'AngularJS. Si vous avez besoin de vous rafraichir la mémoire, vous pourriez vous tourner vers des lectures sur [$scope](https://docs.angularjs.org/guide/scope), [binding](http://www.sitepoint.com/angularjs-tutorial-build-an-app-using-directives-and-data-binding/) et [$apply et $digest](http://www.sitepoint.com/understanding-angulars-apply-digest/). ## Testez vos connaissances Par exemple, quel est le meilleur moyen de surveiller le premier élément d'un tableau? Supposons que nous avons un tableau dans notre scope, $scope.letters = ['A', 'B', 'C']; * Est-ce que $scope.$watch('letters', function() {...}) va lancer sa callback lorsque nous ajouterons un élément au tableau? * Le lancera-t-il si nous changeons le premier élément? * Et pour $scope.$watch('letters[0]', function() {...}); ? Fonctionnera-t-il de la même manière ou mieux? * Les éléments sont des valeurs primitives, que se passe-t-il si nous changeons le premier élément par la meme valeur? * Et maintenant supposons que notre tableau contienne des objets? Que se passe-t-il? * Quelle est la différence entre $watch, $watchCollection, et $watchGroup? Si vous vous sentez confus par ces questions, continuez de lire cet article. Mon but est de rendre tout ça aussi clair que possible au travers de plusieurs example en vous guidant. ## $scope.$watch Commençons avec $scope.$watch. C'est la bête de somme des toutes les fonctionnalités de surveillance: chacune des autres méthodes que nous verrons sera juste un raccourci pour $watch ### $watch-ez ça Ce qui est bien avec Angular est que l'on peut utilise le même mécanisme explicitement pour accomplir des actions complexes dans nos controllers, activées par des changements dans les données. Par example, vous pourriez placer un observater/watcher sur des données qui peuvent changer en réponse aux: * Timeouts * UI * Calculs asynchrones complexes par des Web Workers * Appels Ajax Vous pouvez mettre un 'listener' pour vérifier les changements de données, sans vous soucier de ce qui l'a causé. Pour ce faire, vous allez devoir appeler $scope.$watch vous-même. ### En pratique Regardons le code de $rootscope.watch(). Voici sa signature: function(watchExp, listener, objectEquality, prettyPrintExpression). En détail, ces 4 paramètres sont: * watchExp L'expression à observer. Cela peut être une fonction ou une chaine de caractères, elle est évaluée à chaque cycle. Un aspect à noter ici est que _si_ l'expression est évaluée comme une fonction, alors cette fonction doit être idempotent. En d'autres termes, pour une même valeur en entré la fonction doit retourner la même sortie. Si ce n'est pas le cas, Angular va penser que les données ont changées. Et donc il va continuer à détecter une différence et appeler le listener à chaque itération du cycle. * listener Une callback lancé lorsque l'observateur/watch est crée, et ensuite à chaque fois que, pendant un cycle, un changement watchExp est détecté. L'appel initial à la configuration est faite pour enregistrer une première valeur de l'expression. * objectEquality L'observateur/watcher va faire une comparaison profonde si, et seulement si cette variable est vraie. Sinon elle opérera une comparaison en surface, ce qui veut dire que seules les références seront comparées.
Prenons un exemple: $scope.fruit = ["banana", "apple"];.
objectEquality == false signifie que seul une réassignation de "fruit" lancera un appel au listener. Nous avons aussi besoin de savoir a quelle "profondeur" la comparaison se fera. Nous verrons ça plus tard. * prettyPrintExpression Si elle est indiquée, va surcharger l'expression observée. Ce paramètre n'est __PAS__ fait pour être utilisé lors d'un appel normal à $watch();, elle est utilisée en interne par le parser d'expression.
__Faites attention__, comme vous pouvez le voir par vous-même il est très facile d'obtenir des résultats inatendus en passant le 4e argument par erreur. Maintenant nous sommes en passe de répondre à quelques questions de l'introduction. Regardons nos examples pour cette section:

See the Pen Angular $watch demo - $scope.$watch() by SitePoint (@SitePoint) on CodePen.

Prenez le temps de vous familiariser avec. Vous pouvez comparer les différences de comportement directement, ou suivre l'ordre dans l'article. #### Observer un Array Vous voulez observer les changements d'un Array de votre scope, mais que signifie "changement"? Disons que vôtre controller ressemble à ceci:
app.controller('watchDemoCtrl', ['$scope', function($scope) {
  $scope.letters = ['A', 'B', 'C'];
}]);
L'une des options serait de faire un appel comme ceci:
$scope.$watch('letters', function(newValue, oldValue, scope) {
  // Faire quelque chose ici avec $scope.letters
});
Dans la fonction au-dessus, newValue et oldValue parlent d'eux-mêmes, et seront mis à jour à chaque fois qu'elle est appelée par le cycle $digest. La signification de scope est assez intuitive aussi, elle contient une référence au scope courant. Mais la question est: quand le listener sera-t-il appelé? Si vous essayez d'ajouter, supprimer, ou remplacer des éléments du tableau letters, et rien de se passera. C'est parce que par défaut $watch par du principe que vous ne voulez vérifier que _l'égalité de références_, donc si vous assignez une nouvelle valeur à $scope.letters, la callback sera lancée. Si vous voulez observer les changements d'un élément du tableau, vous devez passer true en 3e paramètre a l'observateur (c'est-à-dire mettre une valeur au paramètre objectEquality décrit plus haut).
$scope.$watch('letters', function(newValue, oldValue, scope) {
  // Faire quelque chose ici avec $scope.letters
});
#### Observer un Objet Pour les objets c'est la même chose. Si objectEquality est a false, on observe juste la réassignation de cette variable dans le scope. Alors qu'à true, a chaque changement d'un élément dans l'objet, la callback est appélée. #### Observer le premier élément d'un Array Il faut rappeler qu'avec objectEquality == true, chaque fois que la callback est appelée, newValue est oldValue seront l'ancienne et nouvelle valeur du tableau __en entier__. Donc il faut faire la différence entre les deux à chaque fois pour savoir ce qui a changé. Imaginons que vous ne vouliez observer les changements du premier élément seulement (ou le 4e, c'est le même principe). Eh bien puisque Angular est génial, il vous permet de faire ça: vous pouvez l'écrire naturellement dans l'expression que vous passez en premier paramètre à $watch:
$scope.$watch('letter[4]', function(newValue, oldValue, scope) {
  //
}, true);
Et si le tableau n'avait que 2 éléments? Eh bien pas de problème, la callback ne sera lancé que lorsque vous ajouterez un 4e élément. Enfin, elle sera lancée quand vous initialiserez pour la première fois l'observateur/watch, et ensuite seulement lorsque vous mettrez un 4e élément. Si vous affichez oldValue, vous que les deux fois elle vaudra undefined. Comparez ceci avec ce qu'il se passe si on observe un élément existant: À l'initialisation, vous aurez toujours oldValue == undefined. Donc rien que $watch ne peut gérer! Maintenant passons à une question plus intéressante: doit-on passer objectEquality == true ici? Malheureusement il n'y a pas de réponse simple à cette question. Cela dépend: * Dans cet exemple, puisque nous avons des valeurs primitives, nous n'avons pas besoin de comparaison profonde, donc nous pouvons omettre objectEquality. * Mais supposons que nous ayons une matrice $scope.board = [[1, 2, 3], [4, 5, 6]];, et que nous voulions observer la première ligne. Alors nous voudrions surement être alertés d'un changement comme $scope.board[0][1] = 7. #### Observer le champ d'un Objet Sûrement encore plus utile qu'observer un élément arbitraire d'un tableau, nous pouvons observer un champ arbitraire dans un objet. Mais il n'y a là aucune surprise hein? Les Arrays en JavaScript sont des objets après tout.
$scope.obj = {'a': 1, 'b': 2};
$scope.$watch('obj["a"]', function(newValue, oldValue, scope) {
  //
})
### Une comparaison jusqu'à quelle profondeur? Nous devons éclaircir un dernier point crucial: que se passe-t-il si nous devons observer un objet complexe imbriqué avec uniquement des valeurs non-primitives? Comme un graphe ou un arbre, ou des données en JSON. Regardons tout ça! D'abord nous avons besoin d'un objet à observer:
$scope.obj = {
  'a': 1,
  'b': {
    'ba': {
      'bab': 2
    },
    'bb': [
      {
        'bb1a': 3,
        'bb1b': 4
      },
      {
        'bb2a': 5
      }
    ]
  }
};
Appliquons notre watch sur l'objet en entier: Je suppose que maintenant il est assez clair que objectEquality doit valoir true dans ce cas.
$scope.$watch('obj', function (newValue, oldValue, scope) {
    //...
}, true);
La question est la suivante: Angular sera-t-il assez sympa pour nous prévenir lorsque nous ferons quelque chose du genre $scope.b.bb[1].bb2a = 7? La réponse est oui, heureusement pour nous (vérifiez sur la démo CodePen précédente). ## D'autres méthodes ### $scope.$watchGroup Est-ce que $watchGroup est vraiment une méthode? La réponse est non. $watchGroup est un raccourci pratique qui vous permet de placer plusieurs observateurs/watchers avec une même callback, en lui passant un tableau de watchExpressions. Chaque expression passé sera observée en utilisant la méthode $scope.$watch():
$scope.$watchGroup(['obj.a', 'obj.b.bb[1]', 'letters[2]'], function(newValues, oldValues, scope) {
  //
});
Il est à noter qu'avec $watchGroup, newValues et oldValues vont avoir une liste de valeur pour les expressionns, celles qui ont changées et celles d'avant, dans le __même ordre__ que le tableau que vous lui donnez en paramètre. En regardant la documentation de cette méthode, on peut remarquer que cette méthode ne prend pas objectEquality. C'est parce qu'elle ne prends que les expressions en elle-même, et ne réagit qu'aux changements de référence. En jouant avec la démo ci-dessous de $watchGroup, vous pourriez remarquerer quelques subtilités. Par exemple unshift va provoquer un appel du listener, au moins dans certains cas: c'est parce qu'en passant une liste d'expressionsns à $watchGroup, _chacune d'entre elles_ pourra provoquer l'execution de la callback.

See the Pen Angular $watch demo - $scope.$watchGroup by SitePoint (@SitePoint) on CodePen.

Notez aussi que changer un champ à l'intérieur de $scope.obj.j ne provoquera pas de mise à jour, seulement l'assignation de b le fera. ### $scope.$watchCollection C'est un autre raccourci pourriez observer des tableaux ou des objets. Pour les tableaux, le listener sera appelé à chaque fois qu'un élément est déplacé, supprimé ou ajouté. Pour les objets, c'est lorsqu'une propriété change. Encore une fois, objectEquality n'est pas autorisé, la fonction ne regardera que le premier niveau de champs/éléments, et ne réagira pas aux changements de leurs sous-champs.

See the Pen Angular $watch demo - $scope.$watchCollection() by SitePoint (@SitePoint) on CodePen.

## Conclusion J'espère que ces exemples vous auront aidé à découvrir la puissance de cette fonctionnalité d'Angular, et à quel point il est important d'utiliser les bonnes options. N'hésitez pas à retoucher et forker les CodePens et à éxperimenter avec les méthodes des différents contextes, et n'oubliez pas de faire des retours en commentaires! (Ndlt: Du site original, moi les commentaires ne marche plus pour le moment, encore x) ) Si vous voulez en savoir plus sur les différents concepts que nous avons abordés dans cet article, voici quelques suggestions de lectures: * [AngularJS scope](https://docs.angularjs.org/guide/scope) * [Understanding Angular's $apply() and $digest()](http://www.sitepoint.com/understanding-angulars-apply-digest/) * [Emerging Patterns in JavaScript Event Handling](http://www.sitepoint.com/emerging-patterns-javascript-event-handling/) * [Prototypal Inheritance in AngularJS Scopes](https://www.sitepoint.com/premium/books/angularjs-novice-to-ninja/preview/prototypal-inheritance-in-angularjs-scopes-14afa0b) * [Documentation for watch &co](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watch) ## Conclusion Bis (D'Ilphrin cette fois-ci) J'ai vraiment aimé faire cette traduction et je pense que j'en ferais bien plus par la suite car j'ai beaucoup appris. Que ce soit au niveau technique parce que...bah c'est un article technique quand même, et moi qui utilise AngularJS au travail c'est toujours un plus d'avoir des articles comme ça. Mais aussi au niveau rédactionnel, je me suis beaucoup imprégné de la façon d'écrire de l'auteur original, ce qui m'aidera pour écrire les prochains articles. J'en ai aussi profité pour faire quelques petits changements sur le site, notamment maintenant je peux faire de la coloration syntaxique avec highlight.js, et je peux maintenant écrie du code dans une ligne. J'éspère que cet article vous aura plu, j'en ferais d'autres par la suite ;)

Gravatar de Ilphrin
Original post of Ilphrin.Votez pour ce billet sur Planet Libre.

Eddy33 : Création du dépôt Fedora eddy33

samedi 7 janvier 2017 à 17:49

Salut.

Cela faisait pas mal de temps que je cherchais l'occasion de créer un dépôt Fedora... C'est fait !

J'utilise le logiciel libre AMC (Auto Multiple Choice) pour créer des QCM avec autocorrection après scan des copies afin d'évaluer certains de mes cours.

AMC est un logiciel plutôt génial pour cela : http://home.gna.org/auto-qcm/

Malheureusement, il n'est plus maintenu sous forme de paquetages RPM pour Fedora depuis la version 21. J'ai ainsi comblé ce vide avec la création du dépôt eddy33. Le dépôt eddy33 propose AMC pour Fedora 23 et supérieur en version 32 et 64 bits. Voici donc le premier paquetage que je maintiens. Il faut bien un début ;-)

L'accès au dépôt eddy33 se fait par la commande :
# dnf install http://kadionik.vvv.enseirb-matmeca.fr/fedora/repo-eddy33-1.0-1.fc25.noarch.rpm

Les paquetages disponibles sont signés.

++

Gravatar de Eddy33
Original post of Eddy33.Votez pour ce billet sur Planet Libre.

Articles similaires