11548 sujets

JavaScript, DOM et API Web HTML5

Boujour à tous. ! Attention, post à rallonge à l'horizon !

Après moultes recherches infructueuses, réponses "à côté de la plaque", litres de café engloutis et paquets de chewing-gums atomisé je viens finalement appeler au secours ici. Je préviens tout de suite, c'est une idée tordue qui me travaille depuis un certain temps déjà et je n'arrive à rien pour l'instant.

Dans le cadre d'un "plug-in" pour forum/CMS, je cherche un moyen de parcourir une page (x)HTML afin de trouver, de récupérer et de remplacer des balises particulières type BBCode.

Actuellement, le traitement est effectué par PHP, le problème est que chaque système de gestion de forum / CMS gère l'affichage des posts à sa façon, et souvent par des moyens qui n'ont rien à voir (la logique reste la même mais les différences d'implémentation compliquent le déploiement du "plug-in") et celà reste de la modification assez "barbare".

Je souhaiterai donc, pour palier aux difficultés d'intégration, et pour rendre cette intégration plus "propre", utiliser javascript pour le traitement de ces 'tags' BBCode particulier, sans toucher aux fichiers du CMS ou forum (mis à part l'appel du fichier JS dans l'en-tête html).

Le script PHP utilise la fonction preg_replace_callback() pour gérer les différentes formes de balise, j'ai donc déjà les regex nécessaires que je pourrais adapter mais je n'ai pas trouvé d'équivalent javascript pour cette fonction (ou alors j'ai mal cherché) et surtout je ne vois pas comment faire pour passer le contenu de la page dans la moulinette JS .

le "squelette" actuel est le suivant :

function parse_MyBBCodes(string chaine_a_traiter){
chaine_a_traiter = preg_replace_callback(regex1, fonction_balisetype1, chaine_a_traiter);
chaine_a_traiter = preg_replace_callback(regex2, fonction_balisetype2, chaine_a_traiter);
(...)
chaine_a_traiter = preg_replace_callback(regexN, fonction_balisetypeN, chaine_a_traiter);

return chaine_a_traiter
}


Quelqu'un saura-t-il éclairer ma lanterne en m'indiquant la piste à suivre pour passer le contenu de la page dans cette fonction et comment reproduire le comportement de preg_replace_callback() ?

<edit>
J'oubliai, on ma conseillé d'éviter le fameux innerHTML, mais si il n'y a pas moyen de passer à côté... bein je ferai avec
</edit>
-----
Will, un bricoleur qui va bientôt ne plus avoir de cheveux
Smiley biggol
Modifié par Willmore (06 Nov 2007 - 00:20)
Salut Willmore.

Il n'y a pas d'équivalent JavaScript officiel. Du BBcode reste du BBcode et les expressions régulières restent les mêmes, à ceci prêt que JavaScript n'utilise pas le moteur PCRE de la série "preg" de PHP. La syntaxe est donc légèrement différente. Tout ça, tu le sais.

Bon, maintenant il y a aussi le fait que JavaScript ne pourra pas faire grand chose derrière PHP, si ce dernier parse le BBcode en premier. Après chargement total de la page, les balises sont ce qu'elles sont: de l'html.

Pour le reste, parser du BBcode est ultra simple et ne nécessite pas plus d'effort en JavaScript qu'en PHP, ou autre. Un exemple concocté en 5 min :

var BBCode = {
	parse: function(str) {
		for(var tag in BBCode.tags) {
			tag = BBCode.tags[ tag ];
			while(tag.pattern.test(str))
				str = str.replace(tag.pattern, tag.replace);
		}
		return str;
	},

	tags: {
		'bold': {
			pattern: /\[b\](.*?)\[\/b\]/,
			replace: '<b>$1</b>'
		},

		'italic': {
			pattern: /\[i\](.*?)\[\/i\]/,
			replace: '<i>$1</i>'
		},
	
		'underlined': {
			pattern: /\[u\](.*?)\[\/u\]/,
			replace: '<u>$1</u>'
		},

		'link': {
			pattern: /\[link=([^\]]+)\](.*?)\[\/link\]/,
			replace: '<a href="$1">$2</a>'
		}
	}
};

<div id="test">[b]Voici un texte en gras [i]sauf [u]là[/u][/i][/b] et [link=http://www.google.fr][b]gooooogle[/b][/link]</div>
<script type="text/javascript">
	var test = document.getElementById('test');
	test.innerHTML = BBCode.parse(test.innerHTML);
</script>

Pour finir :
Willmore a écrit :
J'oubliai, on ma conseillé d'éviter le fameux innerHTML, mais si il n'y a pas moyen de passer à côté... bein je ferai avec

On pourrait effectivement passer à côté en utilisant une fonction récursive qui "scannerait" le nodeValue de tous les noeuds textes finaux et les modifierait selon les besoins.

Encore quelques cafés/chewing gun si cette réponse ne te convient pas.
Bon courage quand même Smiley cligne
Salut Ze Nenex, merci de ta réponse !
a écrit :
On pourrait effectivement passer à côté en utilisant une fonction récursive qui "scannerait" le nodeValue de tous les noeuds textes finaux
Je n'avais pas pensé a une fonction récursive, je vais creuser de ce côté là.

Concernant le parsing, je vais essayer en adaptant le code que tu as fourni.
Le nombre de tag à gérer est assez élevé, j'espère que celà ne va pas envoyer dans les choux le navigateur.

J'ai juste besoin d'une petite précision : dans
'bold': {
	pattern: /\[b\](.*?)\[\/b\]/,
	replace: '<b>$1</b>'
},
peut-on définir le replace en appelant une fonction, comme ci-dessous par exemple
'image1': {
	pattern: /\[img1\](.*?)\[\/img1\]/,
	replace: monTraitement('$1')
},
afin de simuler le fameux callback?

Merci encore de ton aide Smiley cligne
Alors voilà, je poste le résultat des fois que celà soit utile à quelqu'un par la suite.

Le code de la fonction de parcours des TextNodes d'une page :
function parseHTML(node){
	if(!isNaN(node.nodeType)){
		if(node.nodeType == 3) // type 3 = noeud texte
			parseBBCode(node); // fonction rech/remplace
		if(node.hasChildNodes){
			for(key in node.childNodes){
				parseHTML(node.childNodes[ key]);
			}
		}
	}
	return 0;
}


Je vais continuer de bricoler pour trouver un moyen de reproduire le fonctionnement callback. J'ai déjà transposé mes expressions régulières pour les utiliser avec JS, me reste à trouver comment passer en paramètre la chaine trouvée à ma fonction de traitement puis la remplacer dans la page par le résultat de la fonction...

Vive le café Smiley lol
Modifié par Willmore (05 Nov 2007 - 20:37)
Il semblerai que j'ai oublié le fonctionnement de la fonction String.replace() Smiley ohwell .
Effectivement, celle-ci gère l'appel à une fonction de callback en lieu et place du motif de remplacement :
String.replace(RegExp, callBackFunction);


Le prototype de la fonction de callback est le suivant :
String anonymous (String $0, String $1, ...., String $n, Integer index, String input)
a écrit :
OÛ $0 contient la totalité de l'occurence trouvée, $1 à $n le contenu des parenthèses capturantes de l'expression, index la position du premier caractère de l'occurence dans la chaîne d'entrée, et input la chaîne d'entrée.

source

Mon fonctionnement "à la preg_replace_callback()" existe bien Smiley biggrin . En espérant que ça puisse aider quelqu'un d'autre Smiley cligne