Angular nous permet de filtrer une {{expression}} de manière simple et performante. Les filtres permettent d’adapter de trier des éléments dans notre vue. Encore de super pouvoir que nous offre angular.
Exemple d’utilisation de filtre avec Angular
Exemple d’un filtre currency
Exemple, en reprenant notre dernier exemple nous aimerions peut être mieux afficher les prix de produits. Angular à un filtre pour ca, le filtre currency, il formate notre prix.
<div ng-controller="StoreController as store">
<div ng-repeat="product in store.products">
<h1> {{product.name}}</h1>
<h2> {{product.price | currency}}</h2>
</div>
</div>
Angular utilise toujours le même procédé sur les filtres
{{data | filter:options }}
date: un filtre timestamp vers date
{{data | filter:options }}
{{18289393949030303 | date:"MM/dd/yyyy @ h:mma" }} // retourne la date et l'heure
uppercase & lowercase
{{ 'Une chaine ' | uppercase }} // retourne : UNE CHAINE
limitTo: un filtre pour limiter un nombre de caractère
{{ "Ma Chaine de caractère" | limitTo: 4 }} // retourne Ma ch
Mentions particulières pour ce filtre qui nous permet de limiter le nombre d’item affichés depuis un array. Exemple avec nos produits
<li ng-repeat="product in store.products | limitTo:3">
oderBy: un filtre pour trier
Ce filtre nous permet de trier notre boucle ng-repeat, ce qui est vraiment super utile !
<li ng-repeat="product in store.products | orderBy:'-price' ">
Dans notre exemple nous trions par prix. Le « – » devant price indique que nous voulons obtenir les prix du plus petit au plus grand, sans le moins cela sera de plus cher au moins cher.
En reprenant notre exemple du magasin, cela donnerait donc :
<div ng-controller="StoreController as store">
<div ng-repeat="product in store.products | orderBy:'price'">
<h1> {{product.name}}</h1>
<h2> {{product.price}}</h2>
<p> {{product.description}} </p>
</div>
</div>
Le modèle a pour objectif de récupérer des données, le controller lui fera des traitements sur ces données (c’est l’interface) et pour finir la vue s’occupera seulement de l’affichage. C’est cette séparation des tâches qui permet à notre application d’être plus facilement évolutive et maintenable.
Plongeons dans le vif du sujet :
La base : interaction HTML / AJAX / les directives
Une directive avec Angular.js est marker sur un élément HTML qui fait référence à un code JavaScript.
En fait Angular permet de lier facilement du JavaScript avec du HTML. C’est ce qui donne de super pouvoirs à nos éléments HTML
Petit exemple pour vous montrer comment angular lie du code JavaScript avec du html.
Voilà notre controller pour sa partie HTML
<!DOCTYPE html>
<html>
<body ng-controller="StoreController">
<!-- alert Hello World -->
</body>
</html>
Voilà notre controller pour sa partie JavaScript
function StoreController(){
alert('Hello World');
}
Démarer avec angular
Pour commencer, insérez le script d’Angular dans votre page :
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>
Lorsque vous aurez mis en place Angular, la première chose à faire est de déclarer votre application.
Dans notre JavaScript :
var app = angular.module('store',[]);
Dans notre HTML
<!DOCTYPE html>
<html>
<body ng-app="store">
</body>
</html>
Les expressions
Les expressions avec Angular.js permettre d’insérer des valeurs dynamiques dans notre html. Ce sont un peu comme des variables. Nous pouvons même faire des opérations avec
<p>J'ai {{ 20 + 8 }} ans</p>
L’utilisation des accolades indique à Angular.js d’interpréter ces instructions. Ici angular affichera 28.
Les controllers
Les controllers nous permettent d’effectuer des opérations sur des données et les renvoyer dans notre page.
Exemple d’un controller
Voilà les infos que nous voulons afficher dans notre page (un simple objet JS)
var gem = {
name : 'Dodecahedron',
price: 2.95,
description : " ... "
}
Comment pouvons-nous transférer ces infos dans notre page ? Pour le faire, nous avons justement besoin d’un controller. Les controller sont là où nous définissions le comportement de notre application en définissant des fonctions et des valeurs.
Reprenons notre exemple de code :
(function(){
var app = angular.module('store',[]);
app.controller('StoreController',function(){
this.product = gem;
});
var gem = {
name : 'Dodecahedron',
price: 2.95,
description : " Lorem ipsum dolor sit amet, consectetur adipisicing eli "
}
})();
Observons notre code, nous pouvons voir que nous sommes dans une closure, c’est une bonne pratique sur Angular et moi j’aime les bonnes pratiques 🙂
Vous remarquez aussi que le nom de notre controller (ici StoreController ) commence par une majuscule, c’est aussi une bonne pratique sur Angular.
Ensuite nous créons une propriété (this.product)à notre controller qui n’est autre que l’objet avec lequel nous pourrons communiquer dans notre page.
Ici nous assignons une valeur à notre propriété product, un simple objet contenant quelques données que nous pourrons récupérer dans notre page HTML.
Dans tous les exemples qui vont suivre, nous prendrons comme exemple un magasin qui souhaiterait vendre des produits et afficher des informations relatives à la vente de ceux-ci.
Comment afficher le contenu de notre controller dans notre page ?
Maintenant que nous avons mis en place notre controller nous aimerions bien récupérer les infos qu’il contient dans notre page. Mais comment faire ? En fait il faut que nous attachions notre controller à un élément HTML…
Pour ce faire nous devons rajouter un attribut (une directive) à notre balise HTML, l’attribut ng-controller= » »
<div ng-controller="StoreController as store">
<h1> {{store.product.name}}</h1>
<h2> {{store.product.price}}</h2>
<p> {{store.product.description}} </p>
</div>
Nous pouvons spécifier un alias avec « as » qui fait référence à notre controller
StoreController as store
Il est important de comprendre qu’il n’est pas possible d’accéder aux propriétés de notre controller en dehors de notre élément contenant la directive ng-controller associée
En effet si vous tentez de faire :
<div ng-controller="StoreController as store">
</div>
{{store.product.name}}
Cela ne fonctionnera tout simplement pas…
Les directives d’Angular.js
Imaginons que dans notre magasin nous voulions rendre certains produits disponibles et d’autres indisponibles… Pour savoir si le produit est disponible, nous avons récupéré l’info dans notre controller avec une nouvelle propriété : canPurchase.
Dans cet exemple la directive permet de tester le contenu de notre propriété.
app.controller('StoreController',function(){
this.product = gem;
});
var gem = {
name : 'Dodecahedron',
price: 2.95,
description : " Lorem ipsum dolor sit amet, consectetur adipisicing eli ",
canPurchase : false,
soldOut : true
}
Afficher (ng-show) et cacher ng-hide
Avec cette information comment pouvons conditionner l’affichage de notre bouton d’achat. Cela grace à une directive qu’Angular : ng-show
Dans notre HTML il suffit donc d’utiliser cette directive avec comme attribut la valeur de la propriété que nous voulons tester. Dans notre cas la valeur est égale à false et donc ne s’affiche pas.
ng-show affichera l’élément si la valeur de l’attribut est égale à true et le cachera si c’est égale à false.
<div ng-controller="StoreController as store">
<h1> {{store.product.name}}</h1>
<h2> {{store.product.price}}</h2>
<p> {{store.product.description}} </p>
<button ng-show="store.product.canPurchase"> Add to Cart </button>
</div>
A noter que si la propriété est absente de notre objet dans le controller ng-show l’interprètera comme false
Imaginons maintenant que notre produit est hors stock, nous voudrions peut-être ne pas l’afficher du tout.
Nous pourrions donc faire ng-show= »!store.product.soldout »
<div ng-controller="StoreController as store">
<article ng-show="!store.product.soldout">
<!-- notre content -->
</article>
</div>
Mais il existe une directive qui fait l’inverse de ng-show c’est ng-hide. Cette directive cachera l’élément si la valeur de la propriété qu’on lui soumet renvoit true.
<div ng-controller="StoreController as store">
<article ng-hide="store.product.soldout">
<!-- notre content -->
</article>
</div>
A noter que vous pouvez aussi choisir de cacher un élément si une propriété est vide
Exemple :
<div class="gallery" ng-show="{{product.images.length}}">
</div>
Utiliser des boucles
Peut être que notre magasin na va pas vendre un seul produit, il serait donc intéressant d’avoir plusieurs items dans notre controller. Ajoutons maintenant plusieurs produits dans notre controller.
app.controller('StoreController',function(){
this.products = gems;
});
var gems = [
{
name : 'Dodecahedron',
price: 2.95,
description : " Lorem ipsum dolor sit amet, consectetur adipisicing eli ",
canPurchase : true
},
{
name : 'Pentagonal Gem',
price: 5.95,
description : " Lorem ipsum dnsectetur adipisicing eli olor sit amet, co",
canPurchase : false
}
]
Voilà nous avons modifié notre controller et on a maintenant un array d’objet qui nourrit notre propriété product de notre controller. (propriété que l’on retrouvera dans notre page grâce à notre controller)
Mais comment pouvons-nous maintenant afficher le contenu de cet objet dans notre page ?
Vous l’aurez surement deviné nous allons utiliser une directive qu’il s’appelle ng-repeat
ng-repeat permet de faire une boucle comme en php avec foreach ou encore for in en JavaScript
foreach ($variable as $key ) {
# code...
}
Nous pouvons donc faire :
<div ng-controller="StoreController as store">
<div ng-repeat="product in store.products">
<h1> {{store.product.name}}</h1>
<h2> {{store.product.price}}</h2>
<p> {{store.product.description}} </p>
<button ng-show="store.product.canPurchase"> Add to Cart </button>
</div>
</div>
Jouez avec la démonstration sur code pen :
See the Pen Introduciton à Angular.js by BROSSAULT (@antoinebr) on CodePen.
Ce qu'il faut retenir / à propos d'Angular.js
Les directives
Ce sont des attributs HTML qui permettent de déclencher du code JavaScript
Les modules
C’est là où notre application évolue, son environnement.
(function(){
var app = angular.module('store',[]);
)
Les controllers
C’est là que nous effectuons nos opérations applicatives, vérifications des donnés, rearrangement…
{{Les expressions}}
Se sont des éléments entre accolades qui sont interprétés par angular pour être affiché dans la page. Ce sont comme des echo en php.
Créer un objet / avec Object.create();
var shoe = {size: 6, gender: "women",construction: "slipper"};
var magicShoe = Object.create(shoe);
La particularité de Object.create() est que l’argument qui lui est passé (dans notre cas shoe) devient le prototype de notre nouvel objet.
Si vous affichez le contenu de l’objet magic Shoe, vous verrez qu’il ne contient aucune propriété native, toutes les propriétés qu’il contient sont sous forme de prototype hérité de l’objet shoe.
Examinons la chaine d'héritage / le processus...
Rappelez-vous (si vous avez lu les articles précédents) que nous avons une méthode pour savoir si une propriété est native ou héritée d’un prototype grâce à isPrototypeOf();
Object.prototype.isPrototypeOf(shoe);
// retourne true
Cette instruction retourne true car shoe hérite des propriétés de l’objet Object (qui est l’objet par défaut, le parent de tous les objets).
shoe.isPrototypeOf(magicShoe);
// retourne true
Cette instruction retourne true car magicShoe à hérité dans son prototype de toutes les propriétés de shoe.
magicShoe.isPrototypeOf(shoe);
// retourne false
Très logiquement cette instruction retourne false car c’est l’objet shoe qui est est le prototype de magicSHoe et pas l’inverse.
Utilisez les constructions / d'objets
Un constructeur en javascript est en fait une function qui déclare des propriétés d’un objet.
function Shoe (shoeSize, shoeColor, forGender, styleOfShoe){
this.size = shoeSize;
this.color = shoeColor;
this.gender = forGender;
this.styleOfShoe = styleOfShoe;
this.putOn = function(){ alert("Shoe's on, dood !")};
this.takeOff = function(){ alert("Uj, what's that smell?")};
}
var beachShoe = new Shoe(10,"blue","women","flipflop");
beachShoe.putOn();
Le mot-clé new permet d’instancier (de créer une image) l’objet dans une variable pour créer un objet. Mais notre objet à un petit problème… Si par exemple nous voulons créer un objet magicShoe nous allons devoir répéter des éléments de notre constructeur. Et les répétitions dans notre code sont à éviter.
Utiliser le concept d'héritage / pour créer un objet ??
Il suffit de créer un prototype à notre function de construction. nous avions l’habitude de créer des prototype pour des Array, String , Object. Là c’est la même chose
Shoe.prototype = {
putOn: function (){alert ("Shoe's on, dood !");},
takeOff: function (){ alert("Uh, what's that smell?");}
}
Grace à notre prototype on force tous les objets de type Shoe à avoir ces propriétés (stockés dans leur prototype !).
Ce qui nous donne au final une function de construction, le prototype de cette function de construction ainsi que l’instance qui a été créer gràce à notre constructeur.
// Notre prototype défini les propriétés partagées par les objets Shoe
Shoe.prototype = {
putOn: function (){alert ("Shoe's on, dood !");},
takeOff: function (){ alert("Uh, what's that smell?");}
}
// Notre function de construction
function Shoe (shoeSize, shoeColor, forGender, styleOfShoe){
this.size = shoeSize;
this.color = shoeColor;
this.gender = forGender;
this.styleOfShoe = styleOfShoe;
}
// Notre instanciation
var beachShoe = new Shoe(10,"blue","women","flipflop");
// On appel une function du prototype
beachShoe.putOn(); // retourne "Shoe's on, dood !"
Faire référence à l'instance / dans les prototypes
Les prototypes peuvent faire référence à l’instance an utilisant le mot-clé this qui représentera l’objet instancié.
Exemple en modifiant légèrement le prototype du constructeur.
// Notre prototype défini les propriétés partagées par les objets Shoe
Shoe.prototype = {
putOn: function (){alert ("Your "+this.styleOfShoe+" 's on, dood !");},
takeOff: function (){ alert("Uh, what's that smell?");}
}
beachShoe.putOn();
// retourne Your flipflop 's on, dood !
En JavaScript les string, numbers, les objets.. Ont des propriétés héritées par des objets parents, appelés prototypes.
Par exemple quand on créer un objet des propriétés vont s’ajouter à celui-ci.Des propriétés que nous n’avons pas créées ! Mais si ces propriétés ne sont pas dans l’objet courant alors d’où viennent ces propriétés ??!
var aquarium = {
Nemo : {type : "fish", species : "clownfish", length: 3.7}
}
Cet objet contient aussi ces méthodes. Vous pouvez voir la liste des méthodes contenues en affichant votre objet dans la console de votre navigateur.
hasOwnProperty: hasOwnProperty()
isPrototypeOf: isPrototypeOf()
propertyIsEnumerable: propertyIsEnumerable()
toLocaleString: toLocaleString()
toString: toString()
valueOf: valueOf()
En fait ces méthodes sont héritées de l’objet parent.
Il en est de même pour les array qui hérite des propriétés length() pop() push() slice()…
var myArray = ["this","array","inherits"];
myArray.length
// renvoi 3
Pareil pour les functions
function myFunction(){
return "Functions have secret properties too!";
}
myFunction.name
myFunction.bind();
Non de Zeus Marty ! Mais ça voudrait dire que l’on peut créer un héritage, comme dans d’autres langages ?
Oui !
Comment / fonctionne l'héritage
Lorsque l’on demande une function à un objet, array.. JavaScript va d’abord regarder si cet élément contient la function demandée, si ce n’est pas le cas JavaScript vérifiera dans l’objet parent si cette function existe jusqu’à remonter au premier objet qui à servi de base à l’héritage (le prototype).
Ajouter des propriétés héritables / à un objet d'un type particulier
En suivant notre raisonnement, nous pouvons donc ajouter des functions à un type d’objet particulier que nous pourrons retrouver dans tous les futurs objet de ce « type ». Mais concrètement comment pouvons-nous le faire ? Il nous suffit d’ajouter une propriété héritable dans ce que l’on appelle le prototype !
En fait le prototype est une base, comme une voiture de base sans option, toutes les voitures de ce modèle sont faites à partir de ce modèle de base. Ensuite viennent se rajouter des options (ici des propriétés)
Concrètement, imaginons que nous voulions créer une function qui compterait le nombre de fois ou une lettre précise est utilisée dans une chaine. Nous voulons donc que cette function soit accessible sur tous les objets de type string, de la même manière que length par exemple.
Démo :
var firstName = "Hello World ! I'm Antoine, and you ? ";
var lastName = " What's your lastname ?";
String.prototype.countAll = function(letter){
var letterCount = 0;
for(var i = 0; i < this.length; i++){ // this fait référence à l'objet courant
if(this.charAt(i).toUpperCase() == letter.toUpperCase()){
letterCount++;
}
}
return letterCount;
}
};
Maintenant nous avons ajouté ce prototype à toutes les string nous pouvons appeler cette function sur toutes les strings.
LastName.countAll('a');
// retourne 3
Réécrire une propriété / issue d'un prototype (héritage)
Comme vous le savez les objet JavaScript ont de base des méthodes hérités. En effet nous pouvons par exemple appeler .valueOf() sur un array, string, object…Mais si nous voulions modifier le comportement de valueof() ?
Exemple de réécriture de valueof()
Pourquoi modifier une fonction native me direz-vous ? valueof() ne permet pas d’afficher le contenu complet d’un objet, un petit exemple :
var Tornado = function(category, affectedAreas, windGust){
this.category = category;
this.affectedAreas = affectedAreas;
this.windGust = windGust;
}
var cities = [ ["Kansas", 46310],["Torpeka",123939],["Lenexa", 49398]];
var twister = new Tornado("F5",cities,220);
twister.valueOf();
// retourne Tornado {category: "F5", affectedAreas: Array[3], windGust: 220}
En effet affectedAreas retourne Array[3]… Impossible de connaitre le contenu de affectedAreas en utilisant valueOf. Et si nous reécrivions le comportement de valueOf uniquement dans cet objet ? Oui nous pouvons le faire :p
C’est parti, dans cet exemple nous allons re-ecrire valueOf pour que cette fonction retourne le nombre de personnes affectées par la tornade.
(Valeur contenue dans la seconde cellule de chaque sous array de cities).
Tornado.prototype.valueOf = function(){
var sum = 0;
for (var i = 0; i < this.affectedAreas.length; i++){
sum += this.affectedAreas[i][1];
}
return sum;
}
// Utilisation
twister.valueOf();
// retourne 219647
Il est important de souligné que nous avons réécrit valueOf uniquement dans l’objet Tornado nous n’avons pas touché à la définition de cette function dans l’objet parent.
Exemple de réécriture de toString();
Vous connaissez peut-être la function toString(). Celle-ci permet de convertir un array, un nombre etc… en une string (plutôt logique pour une fonction avec ce nom ^^ )
Exemple d’utilisation de toString();
var x = 4;
x.toString();
// renvoi "4"
var a = [3,"Hello","World"];
a.toString();
// renvoi "3,Hello,World"
Toujours dans notre exemple de tornade nous voulons que la function toString() sur cet objet renvoie la liste des villes affectées par cette tornade avec d’autres informations plus globale sur la situation dans une belle phrase.
Tornado.prototype.toString = function(){
var list = "";
for (var i = 0; i < this.affectedAreas.length; i++){
list = list +this.affectedAreas[i][0]+', ';
}
return "This Tornado has bess classified as an "+this.category+", with wind gusts up to"+this.windGust+"mph Affected areas are: "+list+", potentially affecting a population of "+this.valueOf();
}
// Pour appeler la function
twister.toString();
Trouver le constructeur / de l'objet et son prototype
À force de créer des héritages, nous allons peut être avoir parfois besoin de trouver d’où vient l’objet, par quelle fonction à t’il été créé. Il existe une méthode pour ça. C’est la méthode constructor.
(nous verrons dans un prochain article comment créer un constructor)
Il suffit donc d’appeler
twister.constructor;
//Va renvoyer :
// function (category, affectedAreas, windGust){
// this.category = category;
// this.affectedAreas = affectedAreas;
// this.windGust = windGust;
// }
Mais si je souhaite connaitre les functions que j’ai précédemment reécrites dans le proptotype de mon objet ?
Et oui cela peut être très utile de savoir si la function va se comporter nativement, ousi celle-ci à un comportement différent (car re-écrite). Nous pouvons appeler de la même façon le constructeur du prototype avec constructor.prototype.
Exemple :
twister.constructor.prototype;
//renvoit
// Tornado {}
// constructor: (category, affectedAreas, windGust)
// toString: ()
// valueOf: ()
// __proto__: Object
A noté que nous pouvons obtenir exactement le même retour avec une syntaxe légèrement plus courte
twister.__proto__;
Identifier l'origine / d'une propriété
Il est utile de savoir d’où vient la propriété d’un objet. En fait l’objectif est de savoir si l propriété est héritée ou native à l’objet. JavaScript à pensé à tout avec la function hasOwnProperty(); imaginons que nous voulions savoir d’où vient une propriété, nous pourrions créer une function qui chercherait la propriété dans l’objet courant, puis si elle n’est pas là, dans l’objet parent, etc…
Exemple :
Object.prototype.findOwnerOfProperty = function(propName){
var currentObject = this;
while (currentObject !== null){
if(currentObject.hasOwnProperty(propName)){
return currentObject; // La propriété est trouvé
}else{
currentObject = currentObject.__proto__; // On remonte au parent pour reverifier
}
}
return "No property found !"; // On a rien trouvé :(
}
twister.findOwnerOfProperty("valueOf");
// retourne
//
//Tornado {}
// constructor: (category, affectedAreas, windGust)
// valueOf: ()
// __proto__: Object
Nous avons réussi à retrouver depuis quel objet valueOf à été en dernier défini.
Voilà concernant l’héritage prototypal en JavaScript, il ne vous manque plus qu’a savoir comment créer des objet avec un constructeur en utilisant la notion d’héritage prototypal sur celui-ci 🙂
Un petit exemple pour que vous voyiez bien de quoi je parle ici
var bookArray = ["Big Brother", "1984", "Peter Pan"];
var myBox = {
height: 6,
width: 10,
length: 730,
meterial : "cardboard",
content : bookArray
};
Accéder à une propriété / de l'objet
Pour accéder à une propriété de l’objet, c’est très simple. Imaginons que nous voulons afficher la hauteur de notre boite.
Il suffit de faire
console.log(myBox.height);
Mais nous pourrions aussi faire légèrement différemment
console.log(myBox["height"]);
Les deux notations fonctionneront parfaitement, je vous conseille cependant de privilégier la notation pointée (la première) qui est plus répandue.
Créer / une propriété
Nous pouvons ajouter une propriété à notre objet pour ce faire nous pouvons utiliser la notation pointée. Mais si la clé de notre propriété contient des espaces, il faudra absolument utiliser la notation entre crochets.
myBox.nbStops = 2;
// avec des espaces dans le nom de la propriété
myBox["# of stops"] = 2;
Construire dynamiquement / des propriétés
for (var i = 1; i <= myBox["# of stops"]; i++){
console.log(myBox["destination"+i] = "Orlando");
}
Va rajouter les propriétés suivantes à l’objet :
destination1: "Orlando-1"
destination2: "Orlando-1"
Supprimer / une propriété et son contenu
Il existe une méthode pour supprimer une propriété et son contenu dans un objet. C’est la méthode delete.
Si par exemple nous voulons supprimer la propriété contents de l’objet.
delete myBox.contents;
La méthode delete supprimera la propriété dans son ensemble pas seulement son contenu, mais sa clé et sa valeur.
Attention à la valeur de retour de delete
il est important de faire attention à la valeur de retour de delete en effet celle si retournera true si une suppression s’est effectuée sur une propriété existante dans l’objet ,mais aussi sur une propriété qui n’existait pas
Si j’effectue une suppression d’une propriété non existante
delete myBox.proprioeteInconnue
// retourne true
Ajouter dynamiquement une propriété / avec comme valeur un objet
Pour ce faire nous allons créer une fonction
var myBox = {
'# of books' : 2,
height: 6,
width: 10,
length: 730,
meterial : "cardboard"
};
function addBook(box,name,writer){
box["# of books"]++; // on incrémente de 1e nb de livre
box["book" + box["# of books"]] = {title : name, author: writer}; // ajoute une propriété bookN avec comme paramètre un objet contenant le title et le writer
}
addBook(myBox,"Le title du livre","Good Writer");
Accéder à une valeur / contenue dans un sous objet
var myBox = {
book1 : {
title : "Le title du livre",
writer : "Good Writer"
}
}
Pour accéder à la valeur title il suffit de faire :
myBox.book1.title;
// retourne "Le title du livre"
Il est aussi possible d’utilise la notation entre crochet pour obtenir le même résultat
myBox['book1']['title'];
// retourne "Le title du livre"
Les functions / dans les objets
Les objets JavaScript peuvent contenir des valeurs (string, interger, bloeen) rattachées à une clé.,Mais les objets peuvent aussi contenir des functions plus exactement des functions anonymes rattachées à une clé.
Petit exemple
var aquarium = {
Nemo : {type : "fish", species : "clownfish", length: 3.7},
Marlin : {type : "fish", species : "clownfish", lenght: 4.2},
addCritter : function (name, type,species,lenght){
this[name] = {type: type, species: species, lenght: lenght};
}
}
Ici nous avons un objet avec une function addCriter permettant d’ajouter une nouvelle propriété à l’objet.
Il est important de remarquer que nous utilisons le mot clé ‘this’ qui fait référence à l’objet à l’intérieur de celui-ci.
Appeler une function contenue dans un objet
aquarium.addCritter('Bubbles','fish','yellow tang',5.6);
supprimer une propriété d’un objet
Pour supprimer une propriété d’un objet nous pouvons utiliser un fonction anonyme.
exemple
aquarium.takeOut = function(name){
var temp = this[name];
delete this[name];
return temp
}
var fishOutofWater = aquarium.takeOut("Marlin");
console.log(fishOutofWater); // retourne l'objet supprimé (temp)
Cependant l’objet supprimé de contient pas la clé (le nom de notre valeur).
Comment pouvons-nous donc faire pour récupérer le nom ?
Voilà comment
aquarium.takeOut = function(name){
this[name].name = name; // On rajoute une valeur name dans la valeure
var temp = this[name];
delete this[name];
return temp
}
Itérer / un objet
Lorsque l’on souhaite connaitre le nombre de valeurs d’un array il est très simple d’utiliser length.
var monArray = ["Hello","Wor","ld"];
monArray.length; // retourne 2
Mais length ne marche pas sur les objet, pas de chance… Nous pourrions par contre faire une boucle sur l’objet.
Mais si nous voulions connaitre le nombre de propriété avec une valeur précise ?
C’est là que rentre en jeux la loop for-in ! Petite démonstration :
var aquarium = {
Nemo : {type : "fish", species : "clownfish", length: 3.7},
Marlin : {type : "fish", species : "clownfish", lenght: 4.2},
addCritter : function (name, type,species,lenght){
this[name] = {type: type, species: species, lenght: lenght};
}
}
for (key in aquarium){
console.log(key);
}
la boucle for in va ittérer notre objet en transposant chaque propriété dans la variable key.
A noté que la variable key peut changer de nm pour n’importe quoi.
Donc si nous voulions savoir exactement le nombre de propriétés avec une valeur particulières c’est assez simple.
Par exemple si nous voulons connaitre le nombre de propriété de type « fish » il nous suffit de mettre en place cette loop.
var numFish = 0;
for (key in aquarium){
if(aquarium[key].type == "fish"){
numFish++
}
}
console.log('Le Nombre de poissons dans l\'objet est : '+numFish);
Nous pourrions aussi améliorer notre objet en intégrant une fonction qui permettrait de comptabiliser le nombre de poissons dans notre objet.
aquarium.countFish = function(){ // on rajoute une function à l'objet
var numFish = 0;
for (key in this){
if(this[key].type == "fish"){
numFish++
}
}
return numFish;
}
Ensuite nous pouvons appeler cette function de l’objet
aquarium.countFish();
Closure / simple
function testClosure(){
var x = 4;
return x;
}
testClosure(); // retourne 4
console.log(x) // retourne "undefined"
La variable x retourne « undefined » car elle à été définie à l’intérieur d’une fonction, elle n’est donc accessible uniquement dans la fonction dans laquelle elle a été définie.
Closure avec une fonction / retournant une function expression
function testClosure(){
var x = 4;
function closeX(){
return x;
}
return closeX;
}
En suivant la même logique que dans le point précédant, il n’est pas possible d’accéder depuis l’extérieur à la variable x.
Mais comme cette function retourne une function, lorsque l’on assigne son résultat à une variable. L’exécution de celle-ci nous retourne la valeur de x !
var checkLocal = testClosure();
checkLocal(); // retourne 4
testClosure()(); // retourne aussi 4
Paramètres multiples dans des closures
Mais si nous voulions insérer des paramètres avec une closure. Comment procéder ?
function buildCoverTicketMaker(transport){
return function(name){
alert("Here is your transportation ticket via the "+transport+".\n" +
" Welcome to the Cold Coldclosur Cove "+name+" !");
};
}
Pour exécuter cette function nous avons donc deux solutions. La première avec la création d’une function expression.
var getSubmarineTicket = buildCoverTicketMaker('Battleship');
getSubmarineTicket('Mario');
// retourne
// Here is your transportation ticket via the Giant Seagull. Welcome to the Cold Coldclosur Cove Mario !
La deuxième avec les paramètres de chaque function dans des groupes de parenthèses individuelles.
buildCoverTicketMaker('Battleship')('Mario');
Attention aux erreurs !
Avec les closures il faut faire extrêmement attention au moment ou sont retourné les valeurs. spécialement dans les boucles car dans une closure le retour se fait au dernier moment possible.
Petite démo :
function assignTorpedo(name,passengerArray){
var torpedoAssignment;
for(var i = 0; i < passengerArray.length; i++){
if(passengerArray[i] == name){
torpedoAssignment = function(){
alert(name+' You are in charge at torpedo #'+i);
};
}
}
return torpedoAssignment;
}
var passengerArray = ["Batman","Superman","Homer","Smithers"]
var giveAssignement = assignTorpedo('Homer',passengerArray);
giveAssignement();
// retourne Homer You are in charge at torpedo #4 alors que homer est à la #2 :/
Cela retourne « Homer You are in charge at torpedo # 4 » alors que Homer est à la position 2 ! En fait le problème est que la boucle continue de tourner et donc la valeur de i avant de retourner torpedoAssignment
Pour éviter ce problème il ne faut pas attendre la fin de l’exécution de la boucle pour retourner la function
Il faut donc faire :
function assignTorpedo(name,passengerArray){
for(var i = 0; i < passengerArray.length; i++){
if(passengerArray[i] == name){
return function(){
alert(name+' You are in charge at torpedo #'+i);
};
}
}
}
var passengerArray = ["Batman","Superman","Homer","Smithers"]
var giveAssignement = assignTorpedo('Homer',passengerArray);
giveAssignement();
// retourne Homer You are in charge at torpedo #2 (parfait !)
On pourrait aussi le faire avec la loop directement dans la function qui est retournée.
function assignTorpedo(name,passengerArray){
return function(){
for(var i = 0; i < passengerArray.length; i++){
if(passengerArray[i] == name){
alert(name+' You are in charge at torpedo #'+i);
}
}
};
}
var passengerArray = ["Batman","Superman","Homer","Smithers"]
var giveAssignement = assignTorpedo('Homer',passengerArray);
giveAssignement();
// retourne Homer You are in charge at torpedo #2 (parfait !)
Dans le cas d’une function déclarée de manière classique, toute la function est chargée dans la mémoire du navigateur même si elle n’est pas utilisée immédiatement. À la différence des expressions de fonction (ou function expression) qui elles sont appelées quand l’interpréteur atteint cette ligne de code.
Exemple basique
une déclaration de fonction basique
function kingOfCool(){
alert('Im k!nG of C00L');
}
Cette instruction est stockée en mémoire, même si celle-ci n’est pas appelée. À la différence d’une function expression qui ne sera chargée que lorsqu’elle sera appelée.
On peut déclarer une function avec un nom. Ne pas oublier le ; à la fin, car cela reste une variable comme une autre
var message = kingOfCool function(){
alert('Im k!nG of C00L');
};
La déclaration du nom de la function « kingOfCool » n’est pas obligatoire, car on peut faire une « function anonyme ».
var message = function(){
alert('Im k!nG of C00L');
};
C’est la même chose quand on utilise une function de la librairie jQuery par exemple. Dans cet exemple on passe une function anonyme en 2nd paramètre. On ne déclare donc pas de nom à la function que l’on passe en paramètre
$(element).on('click',function(){
});
Passer une function expression / à la place d'un paramètre
Exemple avec la méthode array.map();
Pour rappel array.map() permet d’appliquer un traitement à n’importe quelle valeur d’un array (de manière individuelle) et renvoyer cette nouvelle version de l’array. Le paramètre arrayCell peut être n’importe quoi
var monArray = [1,2,3,4,5,6];
var result = monArray.map(function(arrayCell){
return arrayCell *2;
});
console.log(result);
// affiche 2,4,6,8,10,12
Exemple avancé / Une function retournant des functions
var parkRides = [
["Birch Bumper", 40],
["Pines Plunge", 55],
["Cedar Coaster", 20],
["Ferris Wheel of firs", 90]
];
var fastPassQueue = [
"Cedar Coaster",
"Pines Plunge",
"Birch Bumper",
"Pines Plunge"
];
function buildTicket(allRides, parkRides, pick){
if(parkRides[0] == pick){
var pass = parkRides.shift();
return function() {
alert("Rapide ! Vous avez un fast pass pour "+pass+"!");
};
}else{
for(var i = 0; i<allRides.length; i++){
if(allRides[i][0] == pick){
return function(){
alert("Je vous imprime un ticket pour "+pick+" !\n"+
"Votre temps d'attente est de "+allRides[i][1]+"min :)");
};
}
}
}
}
var wantsRide = "Cedar Coaster";
var ticket = buildTicket(parkRides,fastPassQueue,wantsRide);
ticket();
On peut retourner une fonction depuis une autre function.
Cependant dans l’exemple précédent si on appelle seulement
buildTicket(parkRides,fastPassQueue,wantsRide);
Le retour ne sera pas exécuté, tant que l’on ne stocke pas la function dans une function expression
var ticket = buildTicket(parkRides,fastPassQueue,wantsRide);
Il existe un moyen d’exécuter les function retournées sans passer par une function expression. Il s’agit en fait d’une syntaxe qu’il faut utiliser la voici :
buildTicket(parkRides,fastPassQueue,wantsRide)();
Notez bien l’utilisation des parenthèses comme sur une function à la fin.
Voilà pour la partie sur les expressions de fonction j’espère que cet article / bloc note vous sera utile.
Les logs c’est quoi ?
On parle de log ou de « fichier journal », derrière ces mots barbares se cache un principe simplisme. Les logs ont pour rôle d’enregistrer sous format texte des évènements. Cela peut être des logs d’erreurs qui enregistreront les problèmes rencontrés ou encore des log d’accès. Ce sont ces derniers qui nous intéressent, les logs d’accès ou « access logs » sous apache enregistrent tous les accès HTTP à un domaine ou une série de domaines. L’avantage de l’analyse de logs (contrairement à une analyse de crawl) c’est que l’on ne rate rien. En effet si vous avez des pages orphelines (non reliés par des liens à la structure de votre site) l’analyse de log va les trouver à la différence d’une simple analyse de crawl.
Que trouvons-nous dans les logs d’accès ?
Dans les logs nous allons trouver tout un tas de choses, les accès à nos pages, les accès images, aux ressources (JavaScript, CSS…). Ces logs sont présentés sous forme de lignes contenant le domaine concerné, l’ip de la machine ayant accédé au fichier, ainsi que son nom (UserAgent)
Quel intérêt ?
Savoir qui accède et qui voit quoi est primordiale. En quoi l’analyse de log peut améliorer votre SEO, quelques exemples (non exhaustif).
- Éliminer le duplicate content : en SEO nous essayons d’éviter le plus possible le contenu dupliqué (2 contenus identiques sur 2 URL distinctes), si votre site génère des URL avec des paramètres, il y’a de grandes chances que vous vous retrouviez avec pas mal de contenus dupliqués. Exemple (http://exemple.com?article=4&category=3) si ensuite vous inversez (http://exemple.com?category=3&article=4) et que vous tombez sur le même contenu il y’a de grandes chances que votre site soit truffé de contenu dupliqué. Mais ce n’est pas toujours évident de découvrir le contenu dupliqué avant que Google vous ne l’annonce de manière violente en vous affichant 100 fois plus de résultats que vous avez de page quand vous tapez site:exemple.com dans Google.
- Eviter les 404 : en SEO nous avons aussi pour objectif d’éviter que Google rencontre des pages non trouvés. Imaginez que votre superbe Landing page optimisé pour le SEO est du jour au lendemain introuvable par Googlebot, je ne vous donne pas longtemps avant que vous perdiez la position associée à cette page.
- Localiser les 302 : les redirections 302 sont des redirections temporaires, mais elles ont le désavantage de ne pas transmettre la popularité d’un lien. Si la redirection doit durer dans le temps il faut qu’elle soit faite en 301, mais comment localiser toutes mes 302 ? Grâce à l’analyse de log
- Lister ses pages stratégiques : Trouvez vos pages qui génèrent du trafic depuis google sans pour autant utiliser Google Analytics. Vous pouvez par exemple avoir des pages orphelines (non reliés à la strucutre de votre sir mais qui génèrent des visites SEO, cela serait dommage de supprimer ces pages sans les rediriger.
- Identifier les tentatives de hack : c’est particulièrement vrai pour les sites sous WordPress, vous pourrez voir que des bots (robots) essayent d’utiliser des failles sur des plug-ins que vous n’utilisez pas…
L’intérêt de l’analyse de log c’est donc d’être à l’écoute de l’ensemble des accès de votre site.
Commment accéder à mes logs ?
Maintenant que vous, vous dites qu’explorer vos logs c’est indispensable et super vous vous demandez surement comment concrètement le faire.
Pour ce faire vous aurez besoin de récupérer vos logs, pour ce faire vous avez plusieurs choix en fonction de votre configuration. Soit vous êtes sur un hébergement mutualisé et il faudra surement se connecter à votre panel d’administration pour télécharger les précieux fichiers ( exemple pour OVH ) pour les traiter sur votre machine.
Sur un serveur dédié c’est plus simple, il suffit de se rendre dans (apache)
cd /var/log/apache2
Puis téléchargez l’ensemble de vos fichiers de logs en les zipant tapez
zip -r mes-logs.zip other_vhosts_access.log*
Puis téléchargez cette archive grâce à FTP, ou SFTP. Vous pouvez aussi déplacez ce fichier dans un dossier accessible en HTTP pour le télécharger exemple : (mv mes-logs.zip /home/antoine-home/www/)
Vous pouvez aussi laisser vos fichiers sur le serveur et les trier directement sur place, cependant il faudra faire attention à ne pas utiliser toutes les ressources de votre serveur en triant.
Pre-trier mes logs
La manière la plus simple de pre-trier vos logs c’est de le faire en ligne de commande grâce à grep puis de diriger la sortie vers un fichier séparé grâce à >>
Vous pouvez récupérer plusieurs types de données grâce aux commandes suivantes :
// Récupérer toutes les 404 rencontrés par Googlebot dans le fichier google.log
cat other_vhosts_access.log* | grep 'monbraceletnato.fr' | grep 'HTTP/1.1" 404' | grep -i 'googlebot' >> google.log
// Récupérer toutes les pages explorés par GoogleBot dans le fichier googleCrawl.log
cat other_vhosts_access.log* | grep 'monbraceletnato.fr' | grep 'HTTP/1.1" 200' | grep -i 'googlebot' >> googleCrawl.log
// Récupérer les tentatives de hack d un WordPress
cat other_vhosts_access.log* | grep 'monbraceletnato.fr' | grep 'HTTP/1.1" 404' | grep 'plugins' >> security.log
// lister les pages actives (pages ayant recu au moins une visite SEO)
cat other_vhosts_access.log* | grep 'monbraceletnato.fr' | grep 'HTTP/1.1" 200' | grep -i 'google.fr/url?' >> referer.log
Trier le fichier de sorti avec Excel
Vous allez donc obtenir un fichier se terminant en .log , mais vous aimeriez peut être utiliser Excel pour finement trier, non ?
Pour cela, ouvrez le fichier que nous venons de créer en ligne de commande avec Excel.
Sélectionnez la première colonne, et cliquez dans le menu sur « Donnés » puis sur « convertir ». Sélectionnez l’option « Délimité » puis sélectionnez l’option « séparé par un espace »
Et vous obtenez des logs tout propres que vous pouvez maintenant analyser
Vous pouvez maintenant facilement explorer vos logs, comprendre ce qui se passe débusquer des tentatives de hack… Bref vous n’allez plus rien rater. Si vous avez aimé cet article n’hésitez pas à cliquer sur le bouton j’aime en bas de l’article.
Le Webmarketing du projet / augmenter la conversion
Le design & l’expérience utilisateur
D’un point de vue design, j’ai décidé de créer un site sobre, moderne et efficace. Étant sur une thématique mode, accessoire de mode j’ai donc offert une place importante à de grands visuels, l’objectif était de mettre en scène les produits dans le quotidien pour permettre à l’utilisateur de se projeter plus facilement.
Au niveau de l’expérience utilisateur je me suis concentré à rendre le site simple et à éviter de parasiter le comportement d’achat. Cette stratégie se traduit notamment par l’utilisation massive d’éléments dépliants. L’exemple le plus parlant est celui du formulaire intégré directement dans la sidebar (barre latérale), il permet de garder l’internaute dans la page d’achat et d’éviter toute fuite du client vers une page tierce. Il en est de même pour la « like box Facebook », pour éviter toute distraction intempestive afin de canaliser le comportement d’achat dans l’objectif d’améliorer le taux de conversion global du site.
L’enjeu de la confiance
L’un des enjeux majeurs d’un site e-commerce, est d’appuyer le plus possible sur le levier de la confiance. Si l’internaute à l’ombre d’un doute sur la qualité de vos services, vous ratez la vente. En 2013 la confiance était le quatrième critère le plus important après le prix, la disponibilité et la promotion (FIA net).
Pour maximiser cette confiance dans le site j’ai mis en place des avis défilants sur l’ensemble du site, cela permet à l’utilisateur de voir les avis, quelle que soit la page qu’il visite. Pour que ce système soit efficace il faut que récolter des avis, j’ai donc mis en place une demande d’évaluation automatique qui se déclenche (envoie d’un mail) pour acquérir l’avis des clients. Pour maximiser le nombre d’avis, j’ai réduit le parcours au plus simple. En effet le formulaire est prérempli avec le prénom du client, et celui-ci doit donner son avis dans un message de 100 caractères maximum.
Toujours dans l’objectif d’augmenter la confiance des visiteurs dans le site j’ai intégré Instagram sur la page d’accueil su site, dessus nous retrouvons des photos de clients qui permet au client de découvrir les produits dans un environnement quotidien.
Suivi de la performance commerciale
Comme dans tout projet web l’évaluation de la performance est une étape indispensable. Le déploiement d’un outil d’analyse comme Google Analytics est d’autant plus important quand on parle d’un site e-Commerce.
Google à pensé aux e-commercants avec un mode dédié au e-commerce « Le suivi du commerce électronique ». J’ai donc mis en place dans le plan de tagage (installation du tracking), la remonté des informations de commande (produit, quantité, catégorie…), cela me permet par exemple de connaitre les produits qui ont le plus de succès par ville ou par tranche d’âge, informations indispensables pour tout marqueteur.
Le Développement technique / l'enjeu de la performance
Le développement Front End et la performance
Le site Monbraceletnato est bien évidement responsive design, celui-ci s’adapte donc à l’ensemble des terminaux mobiles (tablette, smartphone…). (Le front-end est basé sur la grille Bootstrap 3, mais le projet ne fais qu’utiliser la grille, tout les autres ajouts propres à Bootstrap 3 ont été retirés.)
Lors du développement de ce site, j’ai employé des technologies visant à augmenter la performante globales (vitesse du site), la maintenabilité, et l’évolutivité du projet. En effet j’ai déployé sur le projet des technologies comme SASS et Compass pour la gestion du CSS. Sass est un préprocesseur qui permet en plus de la maintenabilité de garantir un nombre de feuilles de styles très bas (grâce à une concaténation native) cela diminue le nombre de requêtes HTTP envoyé vers le serveur et donc améliore la vitesse globale de l’application.
En ce qui concerne la gestion du JavaScript, je me suis tourné comme toujours vers le gestionnaire de tâche Grunt, qui permet grâce à la création de règles poussées de vérifier (linté) et de vinifier et de concaténer à la volée les fichiers JavaScript.
Le développement Back End
Woocomerce
Étant expert sur le CMS WordPress j’ai décidé tout naturellement d’orienter le développement du site vers WooCommerce.
WooCommerce est la solution e-commerce rattachée à WordPress, cette solution permet tout ce que prennent en charge d’autres solutions e-commerce comme Prestashop ou encore Magento (gestion des stocks, mails, suivi…) mais cela dans l’écosystème WordPress. Cela garanti notamment une interface de gestion simple et intuitive qui ne demande pas ou peu de formation, contrairement autres autres solutions s.
De plus WooCommerce est une application légère comparée à ses concurrents ce qui lui permet d’assurer de très bonne performance en terme de vitesse et de charge même sur un serveur peu puissant.
Les fonctionnalités de Mon Bracelet Nato
Mis à part les fonctionnalités de base que nous trouvons sur tous les sites commerce (gestion des stocks, bons de réductions,statistiques, espace mon compte) j’ai mis en place et développés quelques fonctionnalités pour améliorer la productivité générale de la boutique.
J’ai par exemple mis en place le Facebook Conncect qui permet aux internautes de saisir leurs informations plus facilement et plus rapidement sur les pages d’achats.
Une autre fonctionnalité que j’ai développée est la création d’un module d’impression d’étiquettes qui me permet de gagner un temps précieux. En effet le module que j’ai développé permet d’imprimer les adresses des clients en attente de livraison.
L’organisation du code et du déploiement
Dans tout projet professionnel, l’organisation du code est essentielle, cela assure une aisance prononcée dans l’évolutivité du site. L’ensemble du code de MonbraceletNato est donc versionné avec un outil nommé GIT, cet outil permet de créer des points d’arrêt dans le développement et donc de pouvoir revenir en arrière facilement.
Au niveau du déploiement du code j’ai mis en place deux environnements , le premier dit de ‘préproduction’ est sur le même serveur que la version de production (version live). L’ensemble des modifications faites en local est d’abord envoyé au serveur de préproduction. Cela permet de s’assurer d’une compatibilité parfaite entre le code et l’environnement. Une fois que les modifications sont validées, celles-ci sont poussées sur le serveur de production.
Pour réaliser les déploiements j’ai mis en place l’outil Dploy qui permet de comparer le commit (la version) présent sur l’environnement distant et la version en local. Dploy procède donc à une mise à jour en comparant les deux versions. L’utilisation active de Dploy a permis un gain de temps important sur l’ensemble du projet.
La performance Back end
Dans l’objectif de fournir un site rapide et performant, la performance backend n’est pas en reste. J’ai utilisé un cache php qui permet d’éviter des appels trop fréquents à la base de données ou aux diverses API (Instagram).
Du côté du serveur le site est sur un VPS qui tourne sous Debian 7 et Apache 2, pour améliorer la vitesse j’ai effectué des réglage coté serveur avec la mise en place d’un cache OPcode (APC), et l’activation des mod apache2 comme deflate, les expires ont aussi été définis pour éviter à l’internaute de recharger sans cesse les ressources front-end.
Conclusion
Vous cherchez un prestataire pour réaliser une boutique sur mesure et performante ? Vous cherchez à construire une boutique qui prend en compte dès la conception l’optimisation de la conversion ? Contactez-moi !
Gagnez / du temps et de l'argent
Avant la mise en place de ce petit dev je glissais dans chaque commande le cadeau. Cependant je recevais beaucoup de coups de fil me demandant si le cadeau sera bien inclus dans le colis (car ce n’était pas notifié dans le résumé de commande).
J’ai donc décidé de remédier à ça avec un développement maison que je vous partage aujourd’hui.
En pratique / comment ca marche
Si la condition pour obtenir la promo n’est pas remplie, on informe l’utilisateur (cela permet d’améliorer le taux d’utilisation de la promo. Si la condition est remplie alors on ajoute le cadeau dans le panier. Si le panier est mis à jour (suppression d’un produit) et que la condition n’est plus remplie alors on re check le panier.
<?php
function promo_product($productPromoID,$minItemBuy,$minPriceBuy){
$productPromo = get_product($productPromoID);
// On vérifie si le produit à ofrir est en stock
if($productPromo->stock == 0 || $productPromo->stock < 0){
define('PROMO', false);return false;
}else{
define('PROMO', true);
}
global $woocommerce;
// On regarde si le produit à offrir est déja dans le panier
foreach($woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if( $productPromoID == $_product->id ) {
$tools = true;
}
}
// on récupère le nombre de produits dans le panier
$nbItems = WC()->cart->get_cart_contents_count();
// on récupère le prix total du panier
$prix = WC()->cart->cart_contents_total;
// on verifie si les conditions (minimum produits ) (minimum prix ) (outil pas déjà dans le panuer)
if( $nbItems > $minItemBuy && $prix >= $minPriceBuy && !isset($tools)){
WC()->cart->add_to_cart($productPromoID,1);
}elseif( $nbItems == $minItemBuy && $prix < $minPriceBuy && $tools == true){
// Si le produit est dans le panier mais la condition n'est plus remplie
$cart = WC()->instance()->cart;
$cart_id = $cart->generate_cart_id($productPromoID);
$cart_item_id = $cart->find_product_in_cart($cart_id);
// On supprime le cadeau
if($cart_item_id){
$cart->set_quantity($cart_item_id,0);
}
}elseif($nbItems < $minItemBuy && $nbItems > 0 ){
// Si la conditions n'est pas remplie alors on affiche un message
echo "<div class='woocommerce-message promo-outil-msg'>Achetez un produit supplémentaire pour obtenir un produit gratuit !</div>";
}
}
?>
Le principe de la fonction que j’ai développé est assez simple, en premier paramètre indiquez l’ID du produit que vous souhaitez offrir. En deuxième paramètre, indiquez le minimum de produit qu’il faut dans le panier pour que la promo s’applique. En dernier paramètre, il faut ajouter le montant minium total de la commande qui rend la promo applicable. Voilà ce que cela donne quand on appelle la fonction.
<?php
promo_product(get_field('gift-Product-ID','option'),2,18);
?>
Vous noterez que pour récupérer l’ID du produit offert j’utilise une fonction héritée de Advanced Custom Field Pro. Cependant vous pouvez faire la même chose avec la fonction add_option() et get_option() l’avantage de ACF c’est que vous allez gagnez du temps et vous épargner la création d’une page d’option.
Si vous avez des questions, n’hésitez pas à me contacter par mail ou par Twitter 😉
Attention la compression augmentera le niveau d’utilisation du processeur, mais dans beaucoup de cas ceci n’est pas un problème surtout mis en parallèle avec le gain de vitesse que cela va vous apporter.
Je parlerai dans cet article du mod_delfate, qui est le successeur du mod_gzip (Apache1).
Installation / sur serveur dédié
Activer le mode deflate sur votre serveur
Activez le mode deflate sur votre serveur en éxécutant les commandes suivantes.Vous aurez besoin de vous loger en tant que root pour executer ces commandes.
a2enmod deflate service apache2 restart
Rendez vous dans votre fichier de configuration de votre site
Vous pouvez aussi ajouter ces infos dans le .htaccess si vous avez activé l’overwrite.
nano /etc/apache2/sites-available/antoinebrossault.com
Ajoutez les directives de compression
Directives avant tout d’abord activer la compression Gzip. Refuser la compression des images. Ne pas compresser les fichiers déjà compressé. Ne pas compresser les PDF. Et donner quelques exclusions aux anciens navigateurs
SetOutputFilter DEFLATE SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|ico|png)$ \ no-gzip dont-vary SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|sit|rar)$ \no-gzip dont-vary SetEnvIfNoCase Request_URI \.pdf$ no-gzip dont-vary BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4\.0[678] no-gzip BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
N’oubliez pas de redémarrer apache
service apache2 restart
Tester / la compression
Maintenant que vous avez mis en place le système de compression sur votre serveur il est important de tester la performance de celle-ci. Pour ce faire il existe tout un tas d’outils pour se faire une idée du bien de performances. Vous pouvez essayer le site DNS Queries .
Qu’est ce qu’une LightBox ? / Pourquoi l’utiliser ?
Une Lighbox est souvent un petit plug-in JavaScript Qui permet lors du clic ou d’un autre événement de faire flotter l’élément au-dessus de tout le site. Les LightBox sont très souvent utilisées pour présenter des Photos et des vidéos.
Cela donne une meilleure immersion dans le contenu c’est c’est une technique particulièrement intéressante lors de l’affichage d’images. Avec une Lightbox ou pouvez aussi créer des Pop-in et/ou modal box pour informer vos utilisateurs.
Installer dans WordPress / sans plugins
Nous allons voir ensemble comment il est possible d’installer ce système sans avoir recours à un plug-in. Premièrement vous allez avoir besoin de Jquery normalement celui ci est chargé sur la plupart des sites, mais vérifiez quand même que celui-ci est bien chargée sur vos pages.
Vous vous allez aussi avoir besoin du plug-in Magnific pop up que vous pouvez télécharger sur Github. Vous pouvez aussi charger ce plug-in sur un CDN comme Cloudflare.
Avec Jquery nous allons ajouter une classe Lightbox À tous les liens don l’ancre est une image et don les liens sont bien des images.
/**
*
* Ajoute une lightbox à toutes les images
* qui ont pour lien une image
*
*/
// On sélectionne nos images
var $linkImg = $('.entry-content a img').parent();
$linkImg.each(function(){
var parts = $(this).attr('href').split('.');
last_part = parts[parts.length - 1];
last_part = last_part.toLowerCase();
var formatsImg = ["tif", "tiff","gif","jpeg", "jpg", "jif", "jfif", "jp2", "jpx", "j2k", "j2c", "fpx", "pcd", "png", "pdf"];
// On vérifie bien si le lien à comme attribut href une image en checkant l'extension
if(formatsImg.indexOf(last_part) !== -1){
$(this).addClass('lightbox');
}
});
$('.lightbox').magnificPopup({
type: 'image'
});
