Pages

Affichage des articles dont le libellé est Evt. Afficher tous les articles
Affichage des articles dont le libellé est Evt. Afficher tous les articles

event


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>Show Event properties</title>

<style>
table { border-collapse: collapse; }
thead { font-weight: bold; }
td { padding: 2px 10px 2px 10px; }

.odd { background-color: #efdfef; }
.even { background-color: #ffffff; }
</style>

<script>

function showEventProperties(e) {
  console.log("entre");
  function addCell(row, text) {
    var cell = row.insertCell(-1);
    cell.appendChild(document.createTextNode(text));
  }

  var e = e || window.event;
  document.getElementById('eventType').innerHTML = e.type;

  var table = document.getElementById('tab');
  table.innerHTML=""; //reset
  var thead = table.createTHead();
  var row = thead.insertRow(-1);
  var lableList = ['#', 'Property', 'Value'];
  var len = lableList.length;

  for (var i=0; i<len; i++) {
    addCell(row, lableList[i]);
  }

  var tbody = document.createElement('tbody');
  table.appendChild(tbody);

  for (var p in e) {
    row = tbody.insertRow(-1);
    row.className = (row.rowIndex % 2)? 'odd':'even';
    addCell(row, row.rowIndex);
    addCell(row, p);
    addCell(row, e[p]);
  }

  document.body.appendChild(table);
}

window.onload = function(event){
  //showEventProperties(event);
}
</script>
</head>

<body>
<h1>Properties of the DOM <span id="eventType"></span> Event Object</h1>
<table id="tab"></table> 
<script>
  var elem = document.getElementById('eventType').parentElement;
  //elem.addEventListener("mouseenter", showEventProperties, false);
  elem.addEventListener("mouseleave", showEventProperties, false);
  //elem.addEventListener("mousemove", showEventProperties, false);
  elem.addEventListener("click", showEventProperties, false);
</script>

</body>

</html>

event : onload

Il est classique de lancer une fonction lorsque la page est chargée (on garantie que la structure du dom est en mémoire).

   window.onload = function() {
        corps de la fonction 

      };

ici la fonction est anonyme, elle ne sera pas réutilisée.

Par exemple : 

   window.onload = function() {
        
        test("Compris ?", function() {
          assert("oui", "oui");
        });
       

      };

Remarquer la syntaxe classique de la fonction test. Elle dispose d'un argument qui est elle même une fonction. Cette fonction est souvent une fonction de callBack. Ici la fonction de callBack est anonyme est contient un appel à une fonction assert.


Exemple complet :

(function() {
        var results;
        this.assert = function assert(value, desc) {
          var li = document.createElement("li");
          li.className = value ? "pass" : "fail";
          li.appendChild(document.createTextNode(desc));
          results.appendChild(li);
          if (!value) {
            li.parentNode.parentNode.className = "fail";
            // si un faux le test est faux
          }
          return li;
        };
        this.test = function test(name, fn) {
          results = document.getElementById("results");
          results = assert(true, name).appendChild(
              document.createElement("ul"));
          fn();
        };
})();

      window.onload = function() {
        test(" test ", function() {
          assert(2==2, "2==2");
          assert(1=='1', "1=='1'");
          assert(1==='1', "1==='1'");
        });
        test("Compris ?", function() {
          assert("oui", "oui");
          assert(true,"oui oui oui");
        });
        test("(function(){})()", function() {
          assert(null, "dur dur");
          assert(5, " du courage");
        });
      };

Paramêtres des fonctions


Un argument passé par valeur est copié, et c'est la copie qui est manipulée par la fonction. Ainsi toute modification de cette copie n'entraîne donc aucun changement dans la donnée d'origine. Ce qui n'est pas le cas pour un passage par référence.

Comment sont passés les arguments en JS ?

 les variables ou objets sont toujours passés par valeur


Mais la valeur dépend du type de l'argument. 

Pour les types natifs (number, string ....), c'est par valeur et pour les tableaux et autres objets se sera la valeur de la référence.

Passage valeur

let age = 50;

function changeAgeNatif(age) { 
  age++; 
}
function changeAgeObject(person) {
 person.age++;  


changeAgeNatif(age);
console.log(age);


Passage référence

function Person(age) {
    this.age = age;
}

let denis = new Person(50);

function changeAgeObject(person) {
  person.age++; 
}

changeAgeObject(denis);
console.log(denis.age);


fichier⏩


  JS Bin on jsbin.com

Des fonctions peuvent être passées en arguments


exemple :

var values = [0,3,2,1];
console.log(values);

values.sort(function(value1,value2){ return value2 - value1; });

console.log(values);

fichier2⟴


Cas des fonctions en argument : perte du contexte.

function Person(age) {
    this.age = age;
}

Person.prototype.changeAgeObject = function(){
     this.age++;
};

let denis = new Person(50);


denis.changeAgeObject();
console.log(denis.age);

// passage fonction en argument et perte du this

function test(methode) {
    methode();
}

test(denis.changeAgeObject);
console.log(denis.age);



En Javascript, quand on passe une méthode en argument, on perd le contexte. 



Voici la correction, il faut explicitement lier la fonction au contexte !


test(denis.changeAgeObject.bind(denis));
console.log(denis.age);


 

On s'accroche voici le code de bind :

Function.prototype.bind = function(obj) { 
  var method = this;
   temp = function() { 
    return method.apply(obj, arguments); 
   }; 
  
  return temp; 
};

Comprendre ce code est l'objectif de J. rezig dans son livre Javascript Ninja

Paramètres sur les events


Evenements sur des inputs : have fun

Entrez successivement quatre entrées différentes !





Cette exemple montre que nous pouvons développer nos propres événements sur les inputs.

Amusons nous en créant des massages délirant lorsque l'utilisateur ne tape pas le même adresse !

var messages=["Verifiez  vos adresses. Merci.",
                         " Soyez attentif, merci",
                         "Vous commencez à me fatiguer",
                         "Bravo, j'abandonne !"]

1) recupération de l'input

var mailC = document.getElementById('mailC');


2) mise en place de l'écouteur

mailC.addEventListener('change', checkPasswordValidity, false);


3) définition du gestionnaire

var checkPasswordValidity = function() {
        if (mail.value != mailC.value) {
           
           compteur=++compteur%4;
           mailC.setCustomValidity(messages[compteur]);
          
        } else {
            mailC.setCustomValidity('');
        }        
    };
 
 
 

    

Passage de paramètres

Nous voulons écrire un code qui affiche le numéro du div !

"this particular topic can be very powerful and very complex" J. Resig.

















Je vous laisse tester les codes suivant : bonne chance

Code ! 

JS Bin on jsbin.com

Explication :
Lire l’article pour comprendre que la valeur des variables peut être modifiée (portée par copie d’adresse et non de valeur)

Code !


JS Bin on jsbin.com

Code ! 


JS Bin on jsbin.com

Code ! 

  JS Bin on jsbin.com

Code final

JS Bin on jsbin.com

Regarder un autre exemple de closure !

JS Bin on jsbin.com

Passage de paramêtres Event

Prenons l'exemple de mozilla pour illustrer le passage de paramètre à un événement
JS Bin on jsbin.com

JS Bin on jsbin.com
JS Bin on jsbin.com
Cette solution n'est pas applicables dans le cas de boucles !
 Les closures sont très utiles pour le passages de paramètre lors d'un événement
JS Bin on jsbin.com

Événement propagation

Dans le exemples suivant cliquer sur un élément.

 Cas de la propagation montante


Cas de la propagation descendante

Valeur de e et de this


Evénements la propagation

Nous allons utiliser le débogeur pour mieux comprendre la propagation des événements dans le DOM.

Il va de soit que body contient les balises. Supposons que Body contienne un p. Si vous cliquer à l'endroit où se trouve le paragraphe, vous avez cliqué sur le body et sur le paragraphe ?
Mais dans quel ordre !

  "Qui de la poule ou de l’œuf était avant  ?" 


un p dans un body : sens de propagation des événement

La réponse est la suivante  : c'est vous qui choisissez.

Examinons le cas, où l'on considère que vous avez cliqué d'abord sur le Body puis sur le paragraphe ; autrement dit il y a propagation de l'événement par le bas (voir figure précédente)

Cas Body->paragraphe


Remarquez le troisième paramètre de EventListener à true.

addEventListener(event, callback , true);

Utiliser le débogueur pour observer les priorités en mettant deux points d'arrêts (lig. 30, 37) et relancer le débogueur.


Lancer l'exécution et cliquer sur le paragraphe


Avancer le débogueur : on voit que body a réagi.

Avancer le débogueur : on voit que le paragraphe à réagi.


Cas paragraphe->body



Remarquez le troisième paramètre à false.
addEventListener(event, callback , False);

Comme précédemment, mettre deux points d'arrêts et lancer l'exécution puis cliquer sur le paragraphe



Avancer le débogueur : c'est maintenant le paragraphe qui réagi en premier.



Avancer le débogueur : c'est au tour du body.



Comparaison : le troisième paragraphe permet de contrôle le sens de propagation.

Le style est d'abord appliqué au body (1 cas)

Le style est d'abord appliqué au paragraphe (2 cas)



Stop propagation

On peut empêcher la propagation de l'événement.

Les événements : quoi faire

Voici dans l'ordre le code à générer


  1.         // Step : Find the element we want the event on
  2.         // Step : Define the event listener function
  3.         // Step : Attach event listener to element

Utilisation de PreventDefault

Preventing default behavior of events

Made using: Khan Academy Computer Science.

bug ! : Event en action

Corriger le code suivant pour faire apparaître correctement votre nom !

JS Bin

Event : have fun

JS Bin

Event : en action

Exemple d'utilisation de l'événement window.onscroll 

  JS Bin

How to do

 



http://html5-demos.appspot.com/static/css/sticky.html


Les événements en action

Partie code :

var tabBtns = document.querySelectorAll('.tab-bar > .tab-btn');

      for(var i = 0; i < tabBtns.length; i++) {
        tabBtns[i].addEventListener('click', 
                    onTabClick(i, tabBtns[i]), true);
      }

      function onTabClick(index, btn) {
        return function(e) {
          currentSelectedTab = index;  
          selectTab(btn); 
        };
      }

      function selectTab(btn) {
        var currentTab = document.querySelector('.tab-bar > .tab-btn.selected');
        if(currentTab) {
          currentTab.classList.remove('selected');
        }
        btn.classList.add('selected');
      }

Partie test

var currentSelectedTab = 0;

countUp = function () {
    currentSelectedTab++;
    currentSelectedTab=currentSelectedTab%tabBtns.length;
    console.log( currentSelectedTab );
    selectTab(tabBtns[currentSelectedTab]);
};

var anim = setInterval( countUp, 1000 );

// on peut mettre un bouton : ici action sur le body
var stopBtn = document.querySelector('body');

stopBtn.addEventListener('click',function(){clearInterval(anim);},true);


JS Bin

Les évenements en JS



Nous avons déjà vu les pièges à éviter lors de l'écriture de la gestion d'événements.
  • perte du this
  • passage de paramètres. 
Voici un exemple des problèmes de passage de paramètres :
Voici donc comment écrire la gestion d'événements en Javascript.

Pré-requis : La compréhension fait appel à la notion de closure.

Pour exemple, nous simulons un comportement basique (code jquery)
$( "p" ).on( "click", function() {
  $(this).toggleClass("selected");
});

En JavaScript
for (var i = 0; i < ps.length; i++) {
  ps[i].addEventListener("click", function(){  
    this.classList.toggle('selected');  
  }, true);
}

Allons plus loin.Nous voulons manipuler l'objet cliqué et connaître son indice.

Voici le code en JS (code que nous allons rendre beaucoup plus compréhensif par la suite)
(function(){
var zone = document.body.querySelector("div");
var zonePs = zone.querySelectorAll('p','div'); 

for (var i = 0; i < zonePs.length; i++) {
  zonePs[i].addEventListener("click", 
                             (function(index, para){ 
                                  return function(e) { 
                                     console.log("nb =" + index);
                                     para.classList.toggle('selected'); 
                                  };
                              })(i,zonePs[i]), 
                             true);
}
})();

Nous allons décomposer le code en trois étapes

  1. sélection
  2. closure
  3. action
Etape de sélection

var zone = document.body.querySelector("div");
var zonePs = zone.querySelectorAll('p'); 

Ecriture de la closure

L'idée est simple, la closure va permettre de rendre accessibles à une fonction (portée des variables) des paramètres. 

  • Les paramètres sont ici le paragraphe et son numéro dans la liste des paragraphe à traiter.
  •  La fonction est l'action a réaliser lors du clique.

Par défaut seul l'événement est disponible dans la fonction action, la closure rajoute des variables supplémentaires (par exemple : le numéro de paragraphe et l'identifiant).

Sans closure seul l'événement est accessible à l'action
Grace à la closure, d'autres paramètres sont disponibles


for (var i = 0; i < zonePs.length; i++) {
  zonePs[i].addEventListener("click", 
                             closure(i, zonePs[i]), 
                             true);

}

Remarquez que la fonction closure est immédiatement exécutée.


function closure(index, para) {
   //closure index et para dispo pour la fonction suivante
        console.log("closure index = "+ index);
        console.log("closure type = "+ para.nodeName);
  
  //déclaration d'une fonction anonyme actionnée lors du clic
        return function(e) { 
          console.log(e.type + " index = "+ index);
          console.log(e.type + " typeNode " + para.nodeName);
          action(para); 
        };

}

Ainsi, lors de l'exécution de la boucle, on exécute deux fois la fonction closure.


Exemple d'application :

Remarque

L'arrivée de Array.from et de la délégation permet de simplifier le code et diminue le nombre d'événement à écrire.