innerHTML et le w3c

Vous ne le saviez peut-être pas mais innerHTML n'est pas reconnu par le W3C… Peut-importe, me direz-vous car tous les navigateur (ou presque ?) le gère.
Il n'empêche que l'on peu faire la même chose en utilisant le DOM
Certes, c'est moins pratique, mais c'est plus rigoureux.

J'ai développer une fonction qui va, lorsqu'on lui passe une chaîne de caractère contenant des balises, créer les balises et le contenu adapter…
L'utilisation ressemble donc a innerHTML.

javascript
DOMinnerHTML(document.body,'add',"<em>tic</em> et <strong>tac</strong>");

La fonction

javascript
function trim(string) {
	return string.replace(/(^\s*)|(\s*$)/g,'');
}
function DOMinnerHTML(obj,method,data) {
	/*si vide, pas la peine de ocntinuer*/
	if (data.length==0) return '';
	/*detection du < de début de balise*/
	var pbalise=data.indexOf('<');
	if (pbalise>0) {
		var text=data.substring(0,pbalise);
		/*supprime ce qu'on va ajouter*/
		data=data.substring(pbalise,data.length);
		/*ajoute le node*/	
		text=document.createTextNode(text);
		if (method=="add")
			obj.appendChild(text);
		else
			obj.replaceChild(text, obj.firstChild);
		DOMinnerHTML(obj,'add',data);
	}
	else if (pbalise==0) {
		/*ici, on commence par une balise*/
		var posSelfClose=data.indexOf('/>');		
		var posClose=data.indexOf('>');
 
		/*detection des attributs*/
		var balise=trim(data.substring(1,((posSelfClose==posClose-1)?posSelfClose:posClose)));	
 
		var attr=Array();
		if (balise.indexOf('=')!=-1)
			attr=balise.split('=');
 
		if (balise.indexOf(' ')!=-1)
			balise=balise.substring(0,balise.indexOf(' '));
 
		if (posSelfClose==posClose-1) {
			/*cas d'une balise autofermé*/
			/*on crée la balise et on continu en mode normal*/
			var cible=document.createElement(balise);
			/*supprime la balise des data restante*/
			data=data.substring(posSelfClose+2,data.length);
		} else {
			/*creation de la blise puis recursivité pour le contenu*/
 
			var cible=document.createElement(balise);
			/*place a part la balise et son contenu*/
			var contenu=data.substring(posClose+1,data.length);
			contenu=contenu.substring(0,contenu.indexOf('</'+balise));
			/*supprime la balise et son contenu des data restante*/
			data=data.substring(data.indexOf('</'+balise)+3+balise.length,data.length);
			if (contenu!='')
				DOMinnerHTML(cible,'add',contenu);
 
		}
 
 
 
		for(var i = 0; i <= attr.length-1; i++) {	
			if (!attr[i]) continue;
			if (!attr[i+1]) continue;		
			if (trim(attr[i])=='') continue;
			if (trim(attr[i+1])=='') continue;	
 
			/*recupere l'attribut*/
			var att=trim(attr[i].substring(attr[i].indexOf(' '),attr[i].length));
			/*pour la valeur, on vire le 1er "*/
			attr[i+1]=attr[i+1].substring(1,attr[i+1].length);			
			/*puis on chppe la parti avant le " restant*/
			var attVal=trim(attr[i+1].substring(0,attr[i+1].indexOf('"')));
 
			var tmp=attr[i+1].substring(attVal.length+2,attr[i+1].length);
 
			if (document.all) {
				var tmp2=att.toLowerCase();
				if (tmp2=="class")
					cible.setAttribute("className", attVal);
				else if (tmp2.substring(0,2)=="on") /*evenement onclick, onmouseover, etc...*/
					eval('cible.'+att+' = function() {'+attVal+'};');
				else if (tmp2=="checked")
					cible.setAttribute("defaultChecked", attVal);
				else if (tmp2=="style") {
					/*on doit décomposé et appliquez les attribut 1 à 1*/
					var sty=attVal.split(';');
					for(var j = 0; j <= sty.length-1; j++) {	
						var style=sty[j].split(':');
						if (trim(style[0])=='') continue;
						/*traduction des mot composé en camelCase*/
						var pt=style[0].indexOf('-');
						if (pt!=-1) {
							var tmp3=style[0].substring(pt+1,pt+2);
							tmp3=style[0].substring(0,pt)+tmp3.toUpperCase()+style[0].substring(pt+2,style[0].length);
							style[0]=tmp3;
						}
						cible.style.setAttribute(style[0], style[1]);	
					}
				} else
					cible.setAttribute(att, attVal );				
			}  else
				cible.setAttribute(att, attVal );
 
			if (tmp!='')
				attr[i+1]="_ "+tmp;
		}
 
		if (method=="add")
			obj.appendChild(cible);
		else
			obj.replaceChild(cible, obj.firstChild);
 
		DOMinnerHTML(obj,'add',data);
	}
	else if (pbalise=-1) {
		/*ajoute le texte trouvé*/	
		var text=document.createTextNode(data);
		if (method=="add")
			obj.appendChild(text);
		else
			obj.replaceChild(text, obj.firstChild);
	}
}

Utilisation

DOMinnerHTML(obj,method,data)
Voici les paramètres a passer à la fonction :

  • obj : l'objet que l'on désire modifier
  • method : “add” ou “replace” selon que vous voulez ajouter du contenu ou remplacer le contenu
  • data : une chaîne de type string contenant les données (html ou simple texte) que vous voulez mettre dans l'objet.
le contenu de data DOIT être au format xhtml, a savoir les balises doivent toujours être fermées : &lt;br /&gt;, &lt;img /&gt;, etc…

Si vous tentez d'insérer un tableau, N'oubliez pas la balise &lt;tbody&gt; sans quoi votre tableau n'apparaitra pas sous IE

Reste a faire

Pour l'instant, tous ne fonctionne pas.

  • Pour l'instant la fonction est “write only” impossible de récupérer le contenu d'un objet
  • on ne peu utiliser ni égal ( = ) ni guillemet ( ” ) dans le contenu d'un attributs

N'hésitez pas a nous faire part des évolution que vous apporterez a cette fonction !


23/05/2006 11:30 -

iDo –

Discussion

Guiguix, 17/05/2007 16:28:

Merci pour ce code ! Génial, j’allais commencé a le taper moi meme, mais je l’ai toruvé et ca m’evite un boulot assez conséquent ! Merci beaucoup ! Par contre chez moi les “=” et ““” ont l’air de bien passer...

Felicitations !

 
MaT77, 13/07/2007 15:38:

Bonjour, Merci pour ce code qui m'a bien aidé par contre il ne fonctionnait pas sur IE (apparemment à cause de l'instruction cible.style.setAttribute(style[0], style[1]);). J'ai donc un peu modifié le code:

J'ai supprimé tout le contenu du “else if (tmp2==“style”) {….}” et je l'ai remplacé par “cible.setAttribute(“cssText”,attVal);”

Voilà ça fonctionne parfaitement maintenant.

Enconre une chose, dans mes balises j'utilises colspan et rowspan, cela ne fonctionne pas sur IE avec le setAttribute. Après le “else if (tmp2==“style”) {….}” j'ai donc rajouté :

else if (tmp2==“colspan”) { cible.colSpan = attVal; } else if (tmp2==“rowspan”) { cible.rowSpan = attVal; }

 
MaT77, 13/07/2007 16:06:

Euh, enfait ma solution avec cible.setAttribute(“cssText”,attVal); ne fonctione pas, enfin ça ajoute bien les balises mais le style n'est pas appliqué.

Par contre avec le code d'origine ça ne marche pas du tout, quand je clic sur le bouton qui appelle la fonction, rien ne se passe.

La solution pour colspan et rowpsan est bonne elle par contre.

Je vais devoir continuer à chercher.

Sur firefox aucun problème.

Edit: c'est bien l'instruction cible.style.setAttribute(style[0], style[1]); qui pose problème. Si je la mets en commentaire, tout fonctionne correctement si ce n'est que le style n'est pas appliqué.

 
MaT77, 13/07/2007 17:01:

C'est bon, après avoir passé mes nerfs sur ce truc, j'ai enfin trouvé. La solution c'est tout simplement qu'il ne faut pas mettre d'espace dans l'attribut style, pour que cela fonctionne sur IE. Il faut mettre style=“height:23px;width:60px;”.

style=“height: 23px; width: 60px; ne fonctionne pas et “style=“height:23px; width:60px;” non plus. Il faut enlever les espaces partout !

 
Si vous ne pouvez pas lire les lettres, tlchargez ce fichier WEV et coutez les.