Previously, in Code me, I’m Famo.us
Petit rappel du premier post, nous souhaitons créer cette démo.
Dans le premier post de la série Code me, I’m famo.us, nous avions vu comment installer la nouvelle version du FamousEngine, ainsi que comment créer les bulles représentant les auteurs. Dans ce nouvel article, nous allons voir comment ajouter l’évènement « click » sur une bulle ainsi que faire apparaître un article. Commençons donc sans plus attendre.
Création d’un article
Pour la création d’un article, nous pouvons soit créer un article dynamiquement en utilisant FamousEngine, soit placer l’article dans le DOM et ensuite le cibler en JS. C’est pour cet exemple, la seconde option que nous allons utiliser.
Commençons donc en éditant le fichier index.html, et en ajoutant le bloc de code suivant juste après la balise <body> .
<div class="article"> <h1 class="title">Cras malesuada nisl id luctus.</h1> <div class="author">By <span class="author-name"></span></div> <h2 class="hat">Fusce porta nisl at urna fermentum blandit. Curabitur suscipit nibh magna, nec fermentum nunc consequat sit amet. Nunc mollis mattis mattis. Aenean id mauris congue, laoreet metus sed, semper lectus. Duis justo nibh, lobortis vel mauris ut, hendrerit congue quam. Suspendisse potenti. Suspendisse tortor diam, tempor vel mi vel, molestie elementum arcu.</h2> <div class="content"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin sollicitudin lectus nec dui dignissim auctor. Nulla vitae purus rhoncus, mattis mauris vitae, viverra elit. Praesent dignissim convallis magna, et sagittis dolor lacinia convallis. Sed aliquam diam sed augue facilisis, a ultrices sem ultrices. Phasellus convallis est nibh, sed dapibus velit iaculis quis. Phasellus accumsan congue nunc, quis auctor nisi vehicula ac. Aenean viverra tristique elit non accumsan. Vestibulum aliquet eu tortor vitae porta. Nam ut blandit enim. Quisque a euismod tellus. Pellentesque facilisis purus blandit dui congue, in varius nibh efficitur. Nullam ac fringilla ipsum.<br /><br /> Maecenas ultricies, nisi et accumsan viverra, elit nulla molestie mi, egestas maximus justo ligula non ex. Phasellus ullamcorper facilisis viverra. Sed elementum rhoncus ipsum, a tincidunt nibh bibendum eu. Proin nec nisi feugiat, accumsan tortor quis, efficitur odio. Donec eu condimentum lacus. In maximus felis tellus, vel malesuada sapien euismod sit amet. Mauris ornare ex eros, nec egestas nibh venenatis eget. Sed ullamcorper pretium dui.<br /><br /> Cras vestibulum nisl sit amet magna facilisis, eget dignissim nunc lacinia. Curabitur non diam sed orci condimentum aliquet. Cras nec tellus placerat, blandit felis sit amet, fringilla leo. Vestibulum convallis dui id libero convallis, vitae vestibulum lacus maximus. Phasellus consectetur erat non velit viverra, ac tempor nisi ultricies. Nullam egestas nisi urna, eget vulputate mauris iaculis in. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam rhoncus risus sit amet arcu accumsan, a molestie leo commodo. Nulla facilisi. Nullam pulvinar tincidunt tincidunt.<br /><br /> Morbi id nisl cursus, interdum nunc at, maximus sapien. Fusce eu nibh nec tellus condimentum ultrices at sit amet neque. Sed viverra nec ligula nec semper. Praesent ut elementum nibh. Quisque eu lacus molestie, lobortis urna eu, volutpat neque. Fusce sit amet sem dui. Suspendisse consectetur finibus magna eu ornare. Quisque ac nisl bibendum, faucibus sapien tincidunt, volutpat lectus. Nam venenatis elementum risus ut lobortis. Vestibulum eleifend nisl vitae lectus consectetur feugiat. Curabitur quis tortor a eros lobortis convallis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Etiam ullamcorper hendrerit pulvinar. Maecenas commodo sem nunc, id cursus eros vestibulum imperdiet. Cras imperdiet tempus felis at dignissim.<br /><br /> Integer efficitur posuere mauris in pulvinar. In vestibulum, est id aliquet pretium, elit eros volutpat dolor, hendrerit fermentum lacus nisi quis dolor. Nunc interdum cursus enim vitae tempor. Fusce vehicula lectus eu eros rhoncus, sed fermentum sapien vestibulum. Phasellus pulvinar leo vitae tellus placerat feugiat. Praesent dictum enim ac tempor viverra. Sed hendrerit nec augue non ultricies. Integer eu enim lobortis, pulvinar diam quis, facilisis neque. Morbi pellentesque dui ac leo vestibulum malesuada. Integer laoreet aliquam magna, in rhoncus ante tincidunt sed. Donec nec massa vel odio venenatis gravida. Curabitur rutrum ante a porttitor laoreet. Aliquam erat volutpat. Suspendisse egestas viverra varius. Donec quis urna et velit posuere mollis vel et tortor.<br /><br /> </div> </div>
Vous l’aurez compris nous ajoutons ici, la structure d’un article. Afin que ce dernier soit correctement affiché, ajoutons maintenant une feuille de style dans la balise <head> .
<link rel= »stylesheet » type= »text/css » href= »styles.css »>
La feuille de style, s’appelle donc styles.css, elle se trouve dans le répertoire /public, à la racine et voici sans plus tarder son contenu :
* { box-sizing: border-box; } html, body { width: 100%; height: 100%; margin: 0px; padding: 0px; font-family: Arial, Helvetica, sans-serif; background-color: #f5f5f5; } body { -webkit-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-font-smoothing: antialiased; -webkit-tap-highlight-color: transparent; -webkit-perspective: 0; perspective: none; } .copied-article { position: absolute; top: 0; left: 0; height: 100%; width: 100%; color: #7b7b7b; } .article { display: none; } .title { font-family: serif; font-size: 40px; text-align: center; width: 100%; margin-bottom: 85px; margin-top: 25px; } .author { text-align: center; font-size: 14px; } .author span { font-weight: bold; } .hat { margin-top: 35px; margin-bottom: 35px; font-weight: 100; text-align: justify; font-size: 20px; line-height: 34px; width: 100%; padding: 0 5%; } .content { width: 100%; font-size: 16px; line-height: 24px; text-align: justify; padding: 0 5%; }
Nous nous contentons de cacher l’article présent dans le DOM, et d’appliquer quelques styles basiques. Maintenant que nous avons fait cela, voyons comment faire apparaître l’article au clique sur l’un des auteurs. Mais avant il est important de présenter une notion importante, la notion d’évènement.
Les évènements en Famous
Lorsqu’un composant est ajouté en tant qu’enfant d’un autre composant, il peut alors émettre des évènements à son parent, et vice-versa. C’est ce qu’on appelle le principe de publiser-subscriber. Pour réceptionner les différents évènements d’un composant, nous utilisons la méthode onReceive. Cela est possible car nos composants héritent tous de la classe Node.
Apparition de l’article
Dans notre fichier Flog.js, ajoutons ces quelques lignes :
import Article from ‘./Article’
A rajouter en dessous des précédents imports.
this.createArticle()
A rajouter dans le constructeur.
createArticle() { this.addChild(new Article()) }
Méthode à rajouter dans la classe.
Voici donc à quoi doit ressembler notre fichier Flog.js après ces différents ajouts :
import Node from 'famous/core/Node' import Author from './Author' import Article from './Article' let authors = [ { id : 0, name : 'Julien Boulevart', image : 'julien.jpg' }, { id : 1, name : 'Nicolas Labbé', image : 'nico.jpg' }, { id : 2, name : 'Fabrice Labbé', image : 'fabrice.jpg' }, { id : 3, name : 'Fabien Logarinho', image : 'fabien.jpg' }, { id : 4, name : 'John Doe', image : 'julien.jpg' }, { id : 5, name : 'Eric Apple', image : 'nico.jpg' }, { id : 6, name : 'Cindy Schmidt', image : 'fabrice.jpg' }, { id : 7, name : 'Oli Sykes', image : 'fabien.jpg' } ] class Flog extends Node { constructor() { super() this.createAuthors() this.createArticle() } onSizeChange() { this.emit('window:resize', { width : window.innerWidth, countAuthors : authors.length }) } createAuthors() { for(var i = 0; i < authors.length; i++) { this.addChild(new Author(authors[i])) } } createArticle() { this.addChild(new Article()) } } export default Flog;
Nous devons à présent créer notre composant Article, pour cela, ajouter un ficher Article.js, dans le répertoire /src.
Article.js
import Node from 'famous/core/Node' import DOMElement from 'famous/dom-renderables/DOMElement' import Transitionable from 'famous/transitions/Transitionable' import Position from 'famous/components/Position' import Close from './Close' class Article extends Node { constructor() { super() this.open = false // Define if the article is open or not // Adding some basic properties to the DOM element this.element = new DOMElement(this, { classes : ['copied-article'], properties : { 'background-color' : '#FFF' } }) // Setting some sizing and positioning values this .setSizeMode('relative', 'relative') .setMountPoint(0, 0) .setOrigin(0.5, 0.5) .setScale(0, 0) } // When we receive an event from the parent ( Flog ) // We check the event's name and call the right method onReceive(event, payload) { if(event === 'article:open') { this._openAnimation(payload) } if(event === 'article:close') { this._openAnimation() } } // Open/close the article _openAnimation(options) { if(this.open) { this.setScale(0, 0) } else { this.setScale(1, 1) } if(!this.open) { var article = document.querySelector('.article') var author = article.querySelector('.author-name') author.innerText = options.name this.element.setContent(article.innerHTML) } this.open = !this.open } } export default Article
Allez c’est parti pour une petite explication :
Le constructeur ressemble beaucoup à celui du composant Author, il crée un élément DOM et lui assigne des propriétés, il définit un point d’origine sur le noeud ainsi qu’une scale à 0, cela nous permettra plus tard de faire apparaître l’article. Nous définissons également un attribut open, qui est un booléen, il nous servira pour savoir si l’article est affiché ou non.
La méthode onReceive réceptionne les différents évènements envoyés par son parent. Elle reçoit en premier paramètre une chaîne de caractères représentant le nom de l’évènement. C’est comme cela que l’on peut définir des actions selon l’évènement reçu.
Enfin, la méthode _openAnimation, permet d’afficher et de fermer l’article. Il vérifie si l’article est affiché ou non et augmente la propriété scale de notre noeud en fonction. C’est également dans cette méthode que nous récupérons notre article déjà dans le DOM mais caché ( celui créé dans index.html ), pour l’ajouter dans l’élément DOM de notre composant ( ligne 52 à 56 ).
Author.js
Dans ce fichier, nous allons ajouter une ligne dans le constructeur : this.addUIEvent(‘click’) . Avec cette ligne nous informons notre parent ainsi que notre composant Author, qu’un évènement de type click est bindé sur notre composant.
Flog.js
Nous devons à présent réceptionner l’évènement click, afin de prévenir le composant Article qu’il doit s’afficher. Comme expliqué précédemment, les évènements d’un enfant sont automatiquement envoyés à son parent, ainsi ce dernier peut s’occuper de les dispatcher à ses différents enfants. C’est que nous allons faire ici dans notre composant Flog.
onReceive(event, payload) { if(event === 'click') { if(payload.node instanceof Author) { this.emit('article:open', payload.node.options) } else { this.emit('article:close') } } }
Nous ajoutons alors la méthode onReceive, elle vérifie quel est l’évènement envoyé, ainsi que l’émetteur, puis émet à son tour 2 évènements, un pour afficher l’article, et un pour le fermer.
En l’état lorsque l’on clique sur un auteur, on a bien l’article qui apparaît puisque souvenez-vous, nous réceptionnons les deux évènements envoyés par le composant Flog. Cependant nous ne pouvons pas fermer l’article une fois ouvert. Nous allons tout de suite mettre cela en place.
Fermeture de l’article
Nous allons créer un nouveau composant, que nous allons appeler Close.
Close.js
import Node from 'famous/core/Node' import DOMElement from 'famous/dom-renderables/DOMElement' class Close extends Node { constructor(options) { super() var element = new DOMElement(this, { classes : ['close'], properties : { 'font-size' : '22px', 'font-weight' : 'bold', 'cursor' : 'pointer' }, content : 'x' }) this .setSizeMode('absolute', 'absolute') .setPosition(window.innerWidth - 50, 30) .addUIEvent('click') } onReceive(event) { if(event === 'window:resize') { this.setPosition(window.innerWidth - 50, 30) } } } export default Close
Ce composant n’est pas très complexe, il va simplement nous permettre de fermer l’article.
Article.js
Enfin dans le constructeur de notre composant Article, ajoutons notre tout nouveau composant Close en tant qu’enfant.
this.addChild(new Close())
Vous pouvez maintenant constater que l’article s’ouvre correctement, et se ferme correctement également : )
Voilà pour ce second épisode, notre article s’affiche et se ferme correctement. Nous avons presque terminé notre petite démo, nous devons à présent ajouter des animations pour rendre l’ensemble plus dynamique. Mais ce sera dans le prochain et dernier épisode.