11552 sujets

JavaScript, DOM et API Web HTML5

Bonjour à toutes et à tous,

Nous avons souvent les mêmes méthodes javascript qui reviennent de façon récurrente :

Nous chargeons des données avec Ajax, pour remplir un formulaire plus ou moins grand.
Lorsque l'utilisateur a fait ses modifications, il clique sur le bouton enregistrer, et nous chargeons la saisie dans un objet que nous parsons en JSON (ou autre) et que nous envoyons au serveur pour être traité...
Et ce, inlassablement, au fil des pages nécessaires à nos applications.

Une idée à germer dans mon esprit, et je me suis dit :
"Est il possible de charger les éléments HTML d'un formulaire et, dès qu'une valeur est modifiée, répercuter immédiatement sur l'évènement la modification dans l'objet ?"
Cela nous épargnerait des lignes non négligeables de codes.


Comme un exemple vaut mieux qu'un discours, voici ce que j'ai fait pour le moment:
(Attention: j'utilise prototype, mais cela doit être adaptable avec d'autres framework javascript)

le formulaire HTML :

Nom : <input type="text" id="Nom" class="saisie"><br/>
Prenom : <input type="text" id="Prenom" class="saisie"><br/>
Sexe : <input type="text" id="Sexe" class="saisie"><br/>
Age : <input type="text" id="Age" class="saisie"><br/>
Expérience : <input type="text" id="Experience" class="saisie"><br/>
Téléphone : <input type="text" id="Telephone" class="saisie"><br/>


L'objet de données javascript (prototype) :

var Martin = {};
Martin.Nom = 'Martin';
Martin.Prenom = 'Jean';
Martin.Sexe = 'Masculin';
Martin.Age = "40ans";
Martin.Experience = "13ans";
Martin.Telephone = "XX XX XX XX XX";


L'objet Formwork (toujours en prototype, et faut bien lui donner un nom Smiley cligne ) :

var FormWork = {};
FormWork = Class.create();

FormWork.prototype = 
	{
		initialize : function()
		{

		},
		AjouteMethode : function(elt)
		{
			if (!(elt = $(elt))) return;
			Element.addMethods({
				DatatoHtml : function(element, Obj)
				{
					element.value = Obj[element.id];
				},
				HtmltoData : function(element, Obj)
				{
					Obj[element.id] = element.value;
				}
			});
		},
		InstancieHTML : function(element, TabData)
		{
			this.AjouteMethode(element);
			element.DatatoHtml(TabData);
			
			element.on('blur', function(e)
			{
				$(Event.element(e)).HtmltoData(TabData);
			}.bind(this));
		}
	}


Et le petit bout de code, en bas de la page où se trouve le formulaire pour déclencher tout ça :

document.observe('dom:loaded', function() {
	var FW = new FormWork();
	$$('.saisie').each(function(elt)
	{
		FW.InstancieHTML(elt, Martin);
	});
});



sur le principe :
1. Au chargement de la page, les éléments de formulaire (avec la classe 'saisie') sont chargés
2. Si une valeur est modifiée dans une zone de saisie, la propriété de l'objet est modifiée sur le blur

Pour le moment, ce n'est pas optimisé.

Mais j'aimerais avoir votre avis sur ce système.
Bonne ou mauvaise idée ?
Quid de la sécurité ?

Merci de vos retours Smiley cligne
Hello.

Disclaimer : Je n'ai jamais utilisé Prototype, donc je vais peux-être répondre à côté.

Si je devais réaliser la même chose en vanilla JS ou en jQuery, je passerais l'id du formulaire au constructeur FormWork, je virerai le $$('.saisie').each ainsi que la méthode InstancieHTML ; et à la place j'utiliserai la délégation d'événement pour binder le blur au niveau du form.
Côté sécu, vu que tu ne fais qu'envoyer des infos au serveur, à condition qu'elle soient validées correctement de ce côté ça me semble OK.

FranckD a écrit :
Nous chargeons des données avec Ajax, pour remplir un formulaire plus ou moins grand.
Une raison particulière à cela? Pourquoi ne pas pré-remplir le formulaire via le HTML?
Salut Florian Smiley cligne

l'idée est pas mauvaise, mais je partais du principe que l'on ne connaissais pas le nombre d'éléments HTML et de propriété.
d'où le $$('saisie').each()

De plus, je suis une feignasse (parait que cela peut être une qualité en informatique Smiley langue Smiley ravi ), je veux pas faire une ligne par élément du formulaire. La boucle s'en charge pour moi.

a écrit :

Une raison particulière à cela? Pourquoi ne pas pré-remplir le formulaire via le HTML?

Un exemple comme un autre, ça peut être au chargement directement en PHP qui remplit le formulaire, ou avec de l'AJAX. peut importe le contexte je serais tenter de dire.

Par contre, dans ta réponse, il y a un élément qui m'intéresse :
a écrit :
à la place j'utiliserai la délégation d'événement pour binder le blur au niveau du form


Tu fais comment pour binder un event sur un input ?
j'ai trouvé ça sur le net :
http://triaslama.wordpress.com/2008/07/22/four-ways-javascript-binding-event-listeners/

txtContent = document.getElementById("txtContent");
txtContent.onfocus = txtFocusHandler;
txtContent.onblur = txtBlurHandler;


en prototype on peut utiliser un observer :
http://api.prototypejs.org/dom/Event/on/
c'est bien la même chose ?

Merci de tes lumières Smiley cligne
FranckD a écrit :
Tu fais comment pour binder un event sur un input ?
C'est juste le fait d'attacher l'événement à l'objet du DOM, que ce soit en dur dans le HTML (ex: onClick), ou via le JS (dans ton exemple sous Prototype : element.on('blur', ...))

L'idée ici est de ne pas d'attacher l'événement à chaque input, mais bien sur le formulaire. Comme les événements "remontent" dans le DOM (on dit qu'ils bouillonnent), ils seront interceptés.

Les avantages de la délégation sont dans le cas présent :
- Tu peux te passer de ta boucle.
- Événement attaché une fois VS autant de fois que d'éléments => meilleurs performances.
- En cas d'insertion dynamique de champs, ils sont déjà liés à l'événement => maintenance easy.

Je connais peu Prototype mais apparemment l'API de .on est la même que jQuery (délégation si un sélecteur est passé en argument optionnel). Dans ton cas, ça donnera quelque chose comme :
Event.on(tonForm, 'blur', .saisie, callback)
Salut Florian Smiley cligne

Je viens de prendre connaissance de ta réponse. Encore merci de ce débat passionnant Smiley cligne

Je n'ai pas encore tester ta méthode.
Mais en lisant, le fait de binder un event sur élément (Form ou input) fait que c'est dans le callback que tu gère la liaison entre l'élément et la propriété de l'objet de données (Martin dans l'exemple). Ce qui au final revient au même, ou je suis pas encore bien réveillé Smiley cligne

Je teste ça au plus vite, et je viendrais faire un retour ici Smiley cligne