11548 sujets

JavaScript, DOM et API Web HTML5

Bonsoir les Alsanautes ! Smiley smile

J'ai ici un petit problème vis-à-vis d'une prévalidation en JS. Du code pour la gestion de l'évènement :

window.onload = function()
{
	var form = document.getElementById("main_form");
	
	addEvent(form, "submit", function() {
		return prevalidate(form);
	});
}


Et la fonction proprement dite, qui pour l'instant se cantonne à un simple essai :

function prevalidate(form)
{
	alert("hello world!");
	return false;
};


En théorie, donc, la fonction, quoi qu'il arrive, devrait systématiquement retourner false ; et par conséquent stopper l'envoi du formulaire. Or, le formulaire reste soumis. Smiley murf

Quelqu'un aurait-il une idée de la source du problème ? Je m'efforce de bien séparer les couches (pas de onclick=blabla dans le code HTML, par exemple) il se peut donc que j'aie des ratés et que le problème vienne tout simplement de...moi. D'autant plus que je ne suis pas un JS freak. Smiley ravi

Je vous remercie d'avance ! Smiley smile

/edit/
Le truc fun, c'est que là où Firefox continue la soumission du formulaire, Internet Explorer (8) cesse l'envoi. Smiley eek
Modifié par SolykZ (15 Sep 2009 - 17:42)
Bon, finalement, j'obtiens cette fonction :

function prevalidate(form)
{
	if (form.preventDefault) { 
		form.preventDefault(); 
	}
	form.returnValue = false;
	return false;
};


Et au niveau de l'ajout d'évènement, je repasse par un DOM 0, toujours en gardant une fonction anonyme :

form.onsubmit = function(e) { return prevalidate(form); }


Ça m'a tout l'air de marcher correctement (IE me fait cependant des blagues ; quand je modifie le code il n'actualise pas son cache donc il me faut systématiquement ouvrir un nouvel onglet, sur le coup je ne l'avais pas remarqué... -.-), cependant j'aimerais être sûr que c'est une bonne façon de procéder ? Smiley smile
Modifié par SolykZ (14 Sep 2009 - 01:53)
Non, tu as mélangé les deux méthodes :

- soit tu utilise un gestionnaire d'évènement DOM0, et pour annuler l'action par défaut tu retourne "false". Mais dans ce cas la tu n'as pas d'objet event, et donc pas de méthode stopPropagation :

function prevalidate() 
{ 
   return false; 
};

form.onsubmit = prevalidate;


- soit tu utilise ton wrapper "addEvent" qui utilise les vrais gestionnaires d'évènements DOM. Dans ce cas la tu as un objet event (1er argument) qui a une méthode stopPropagation (ou pour IE, respectivement, un objet statique window.event et une propriété returnValue) et donc pas besoin de retourner false :

function prevalidate(e) 
{ 
    if (e.preventDefault) {  
        e.preventDefault();  
    }
    else {  
        e.returnValue = false;  
    }
};


PS : dans le second cas, pour ton callback, la convention veut que l'on nomme le premier argument "e" ou "evt". Si tu nommes ton argument "form" on va s'attendre plutôt à recevoir un HTMLFormElement.
Merci pour ta réponse ! Smiley smile

Effectivement, c'était une belle soupe. Smiley langue Ceci dit j'ai prévenu que j'étais pas très bon en JS (vaguement quelques userscripts pour Greasemonkey, mais dans ce cas-là, pas de soucis interopérabilité, donc). Smiley smile

Je me rends compte, finalement, que DOM 0 me simplifie grandement la vie. Sachant que DOM 2 n'est pas le copain de chambrée préféré d'Internet Explorer... (et puis, la longueur du code se voit clairement revue à la hausse, sachant qu'on doit alors passer par des wrappers censés éviter de vérifier une condition en plein milieu du code quant à savoir si le navigateur prend en charge addEventListener ou non). Bref, y a-t-il des inconvénients à l'employer à l'heure actuelle, ce faux level 0 ?

Par contre si j'essaie de faire passer une variable en argument de la fonction prevalidate, ça ne marche plus très fort. Dans ce cas présent, il me faut donc utiliser this ? Mais que faire si j'ai plusieurs arguments à passer ? Je viens à l'instant d'essayer une fonction anonyme, ça ne fonctionne pas vraiment.

Tiens, j'ai du mal à saisir cette convention du e. Parce qu'en théorie, ma fonction prevalidate, elle est censée pré-valider les champs d'un formulaire HTML, pas d'un évènement. Smiley rolleyes
SolykZ a écrit :
Bref, y a-t-il des inconvénients à l'employer à l'heure actuelle, ce faux level 0 ?


A part le fait que cela soit déprécié ? Tu ne peux lier qu'un seul callback à un élément, si tu en définit un deuxième cela efface le premier.
Cela peut être un vrai problème quand tu n'es pas le seul à travailler sur un site, ou une appli complexe.

Je te conseille vraiment d'investir du temps dans le modèle évenementiel DOM : c'est plus évolutif, complet et carré.
Le javascript a beau avoir une mauvaise réputation, il faut l'avouer son modèle évenementiel est béton : il est repris quasi à l'identique dans pas mal de frameworks et langages. L'apprendre c'est un peu comme apprendre les expressions régulières : celà te servira toujours.

SolykZ a écrit :
Par contre si j'essaie de faire passer une variable en argument de la fonction prevalidate, ça ne marche plus très fort. Dans ce cas présent, il me faut donc utiliser this ? Mais que faire si j'ai plusieurs arguments à passer ? Je viens à l'instant d'essayer une fonction anonyme, ça ne fonctionne pas vraiment.


Tu ne peux pas passer d'arguments car c'est le gestionnaire qui éxecute le callback. C'est donc lui qui passe les arguments à ta fonction.

SolykZ a écrit :
Tiens, j'ai du mal à saisir cette convention du e. Parce qu'en théorie, ma fonction prevalidate, elle est censée pré-valider les champs d'un formulaire HTML, pas d'un évènement. Smiley rolleyes


Comme dit plus haut c'est le gestionnaire qui a le contrôle sur les arguments, et il ne passe qu'un seul et unique argument : un objet Event.
Si tu veux acceder à l'objet auquel est attaché l'évènement tu peut le faire via Event.target ou window.event.srcElement.
Modifié par Ywg (14 Sep 2009 - 21:59)
D'accord, je commence doucement à y voir plus clair. Smiley smile

Un grand merci à toi pour ces explications ! Smiley cligne

/edit/
J'ai été trop vite en lisant. Donc vis-à-vis de event.target et consorts, si j'ai besoin d'accéder à plusieurs objets de ma page, je les appelle au sein de ma fonction ?
Modifié par SolykZ (15 Sep 2009 - 17:59)
3 solutions, de la plus facile à la plus dure :

- 1 : tu récupères tes éléments depuis ta fonction si ce sont des éléments DOM (l'arbre est public et donc accessible de n'importe ou) ou des données référencées dans l'espace global. Ex :

var form = getElementById("monform");

form.addEvent("click", callback);

function callback(e){

  mesSelects = e.target.getElementsByTagName("select");
}


- 2 : tu stocke des références à tes objets supplémentaires sur l'objet auquel tu lie ton évènement (c'est pas le plus propre si tu n'en as besoin que pour un seul callback). ex :

var form = getElementById("monform");
var mesSelects = form.getElementsByTagName("select");

form.mesSelects = mesSelects;
form.addEvent("click", callback);

function callback(e){

  mesSelects = e.target.mesSelects;
}


- 3 : le top du raffinement tu crée une closure. Cela consiste à rendre inéligible un espace mémoire pour le ramasse miette en retournant une fonction qui a accès à l'objet d'activation de sa fonction parente, fonction parente qui elle a expirée et n'est plus référencée dans l'espace global... Ce qui te donne donc, si tu as bien suivi : des variables privées ! Ex :



(function /*initForm*/(){ // on évite les NFE (fonctions expressions nommées) c'est trop de galères (fuites de mémoire un peu chez tout le monde)...

  var form = getElementById("monform");
  var mesSelects = form.getElementsByTagName("select");

  form.addEvent("click", callback);

  function callback(e){

    // rien à faire, j'ai accès directement aux variables "form" et "mesSelects"
  }
})();


PS : la deuxième solution peut provoquer des fuites de mémoire sous IE, mais c'est négligeable, du moment que ta page ne reste pas affichée plusieurs heures d'affilée avec plein d'ajouts/retraits de noeuds et sans rafraîchissement, rien à craindre.
Je viens de faire quelques essais avec chacune des trois méthodes, la plus concluante reste (à mon goût, mais les goûts peuvent changer Smiley cligne ) encore la première. Par contre, je remarque l'absence de document. lorsque tu récupères l'élément formulaire. Lorsque je teste, la console de Firefox me retourne que la fonction est indéfinie. :o

M'enfin, ce n'est qu'un détail qui éveille ma curiosité, car en l'état, tout fonctionne. Smiley smile
(je suis, au passage, repassé à DOM 2, sans rencontrer de problèmes : ça commence à rentrer. Smiley langue )
Yep, effectivement il manque document, j'ai écrit ça sans relire ni tester, donc il y a peut être deux trois petits trucs à corriger.

Je remarque d'ailleurs dans les solutions 1 et 2, que j'ai oublié le "var" devant mesSelect.
Hors, pas de var => variable globale => les variables globales c'est le mal et ça attire les raptors