11525 sujets

JavaScript, DOM et API Web HTML5

Pages :
Bonjour à tous,

J'ai déjà eu l'occasion d'utiliser la fonction JS pour afficher son email en limitant les risques de spam, proposée ici par Julien Royer.

Elle est très sympa, mais ça demande d'avoir la main sur le code HTML, ce qui n'est pas toujours le cas. Pour un petit forum que je monte (punBB), mais aussi pour ma propre information, je me demandais s'il était possible de faire un script parsant du texte brut, texte brut répondant à un schéma donné, pour le remplacer par un code HTML donné. Je sais faire ça avec des regexp mais ne sais pas comment les utiliser en JS, ni si c'est possible de remplacer un bout de texte dans un document sans toucher au texte autour.

Concrètement, il faudrait transformer ceci:
Pour m'écrire: user +arobase+ host.com

en ceci:
Pour m'écrire: <a href="mailto:moi@site.com">user@host.com</a>

Si JS désactivé, on retombe sur la version texte, qui reste relativement lisible et compréhensible même si moins pratique.

Techniquement, on fixe un format simple de chaine de caractères (<user> +arobase+ <host avec tld>). C'est moins protégé que ce que propose Julien, et pour un gros site ça n'ira probablement pas, mais pour un petit site ça devrait faire l'affaire.
Aussi, si c'est nécessaire, on peut partir d'un code ressemblant à ceci:
Pour m'écrire: <em>user +arobase+ host.com</em>

si ça facilite ou permet le parsing.

Voili voilou. Ça vous semble jouable? Ça existe déjà quelque part en belle petite fonction bien propre comme il faut?

Merci d'avance pour vos lumières. Smiley smile
Modifié par Florent V. (23 Jul 2007 - 15:59)
Hello,

Parcourir tout le texte du document, c'est possible techniquement, mais ça me paraît un peu lourd, et potentiellement cause de problème : rien n'empêche a priori que "user +arobase+ host.com" n'apparaisse dans du contenu que l'on ne maîtrise pas, ou à un endroit où l'on ne voudra pas qu'il soit remplacé, par exemple dans un <textarea>.

Il serait donc à mon avis plus simple que les mails à remplacer soient balisés (par exemple comme tu l'as fait avec <em>), et encore mieux marqués par une classe HTML. Mais évidemment, ça dépend comme tu le fais remarquer de ton contrôle sur le code HTML.

Qu'est-ce que tu en penses ?
Balisés avec <em>, c'est jouable pour la saisie dans un petit forum ou CMS. Marqués avec une classe, ça ne sera à priori pas possible.

La problématique du contrôle sur le code HTML, c'est celle de l'insertion de contenu par des non techniciens (ou l'insertion dans un cadre technique limité: forum avec BBcode, CMS avec éditeur WYSIWYG ou saisie en mode wiki, etc.).

Pour les textarea, je n'y avais pas pensé. Travailler uniquement sur les <em> (ou, au choix, un autre élément de type en-ligne comme <span> -- à priori peu utile --, <i>, <u>, <b>, <strong>...) règle-t-il le problème? Ou bien faut-il une sécurité supplémentaire?
Déjà, une version qui devrait marcher dans ton cas si tu balises avec des <em> :
if (document.getElementById && document.createTextNode && {}.hasOwnProperty) {
(function(tagName, regExp) {
	function init() {
		if (document.body && !init.done) {
			init.done = true;

			initEls(getEls());
		}
	}

	function getEls() {
		var elsTn = document.getElementsByTagName(tagName), els = [];
		for (var i = 0, el; (el = elsTn[ i]); ++i) {
			els[els.length] = el;
		}

		return els;
	}

	function initEls(els) {
		for (var i = 0, el; (el = els[ i]); ++i) {
			initEl(el);
		}
	}

	function initEl(el) {
		var str = el.firstChild && el.firstChild.nodeValue, m, email;
		if (str && (m = regExp.exec(str))) {
			email = m[1] + "@" + m[2];

			el.parentNode.replaceChild(createEl("a", {href: "mailto:" + email}, email), el);
		}
	}

	// DOM
	function createEl(n) {
		var a, i = 0, e = document.createElementNS ? document.createElementNS("http://www.w3.org/1999/xhtml", n) : document.createElement(n);
		while ((a = arguments[++i])) {
			if (typeof a === "string") {
				e.appendChild(document.createTextNode(a));
			} else {
				for (var p in a) {
					if (a.hasOwnProperty(p)) {
						e[p] = a[p];
					}
				}
			}
		}

		return e;
	}

	// Events
	function addLoadEvent(f) {
		if (document.addEventListener) {
			document.addEventListener("DOMContentLoaded", f, false);
		}

		if (window.addEventListener) {
			addEventListener("load", f, false);
		} else if (document.addEventListener) {
			document.addEventListener("load", f, false);
		} else if (window.attachEvent) {
			attachEvent("onload", f);
		}
	}

	addLoadEvent(init);
})(
	"em", /^\s*([^\s]+)\s+\+arobase\+\s+([^\s]+\.[^\s]+)\s*$/
);
}

Sinon, il est envisageable à mon avis de faire quelque chose qui parcourra tout le texte, mais ça risque d'être lourd, et il faut être sûr que le remplacement pourra se faire sans problème (par exemple en limitant le parcours du texte à un élément particulier du document).
Modifié par Julien Royer (23 Jul 2007 - 17:34)
Waouh, joli boulot, ça marche nickel (FF2, Opera9, IE5.5+). Smiley smile

Je parcours ça du regard mais je comprend pas tout ( Smiley biggol ).
Je crois comprendre que tu testes des méthodes (si ça s'appelle bien comme ça), et si elles sont disponibles tu définies une fonction que tu appelles en même temps, avec une syntaxe du type:
(function(nomparam1, nomparam2) {détail de la fonction}) (param1, param2);

ce qui revient au même que:
function nomdelafonction (nomparam1, nomparam2) {détail de la fonction}
nomdelafonction (param1, param2);

J'ai bon?
(Je vais aller apprendre JS, moi, plutôt que poser des questions à deux francs...)

En tout cas, merci bien. Avec la modification facile de la balise HTML englobante et de la syntaxe du texte à l'intérieur, c'est une solution très souple. Smiley smile

Je te paie au noir?
(Au chocolat noir.) Smiley lol
Modifié par Florent V. (23 Jul 2007 - 21:46)
Florent V. a écrit :
J'ai bon?

Oui, bon résumé. Smiley smile
Florent V. a écrit :
Je te paie au noir?
(Au chocolat noir.) Smiley lol

Pourquoi pas, j'aime bien le chocolat noir.

Remarque, je vais plutôt faire payer le SAV, c'est une solution rentable à long terme. Smiley lol

P.S. : le script est améliorable (support de IE 5 par exemple), et tu peux changer le type de balises (<em>) et l'expression régulière.
Modifié par Julien Royer (23 Jul 2007 - 20:11)
Julien Royer a écrit :
et tu peux changer le type de balises (<em>) et l'expression régulière.

Oui, j'ai noté. Smiley smile

Au fait, peut-être faudrait-il un lien depuis le post que j'indique (celui avec le script qui se base sur une syntaxe HTML complète) vers ce sujet?
Florent V. a écrit :
Au fait, peut-être faudrait-il un lien depuis le post que j'indique (celui avec le script qui se base sur une syntaxe HTML complète) vers ce sujet?

Voilà chose faite.
Ce script pose moins de problème que celui à base de <span>u,h,d qui dans certains cas (pourquoi et comment je ne sais pas... j'ai pas trop cherché - Julien as-tu déjà constaté ça ?) force IE6 ou 7 à recharger la page sans arrêt.

Est-ce que <address>user +arobase+ host.com</address> ne serait pas plus pratique ?

a+
Arsene a écrit :
Julien as-tu déjà constaté ça ?

Non. Est-ce que tu as un exemple ?
Arsene a écrit :
Est-ce que <address>user +arobase+ host.com</address> ne serait pas plus pratique ?

Le problème c'est que <address> est de type bloc.
Arsene a écrit :
Est-ce que <address>user +arobase+ host.com</address> ne serait pas plus pratique ?

Comment fais-tu saisir <adress> à un non technicien sur un forum ou dans un CMS? Smiley cligne
@Florent
... de la même façon qu' <em> ou n'importe quelle autre balise html valide... au pire un script php détecte la chaine +arobase+ et l'encadre là où il faut par ce qu'il faut. Bon, c'était juste pour dire que <address> me paraissait dans ce cas précis plus pertinent en terme de balisage que <em> mais j'en fais pas un fromage non plus, hein?

@Julien : pas trop le temps maintenant mais je te passe en MP un lien vers une page test dès que je la retrouve. Pas non plus celui de me pencher sur la question de <address> comme block mais un display:inline ne ferait-il pas l'affaire ?
Arsene a écrit :
@Julien : pas trop le temps maintenant mais je te passe en MP un lien vers une page test dès que je la retrouve.

Merci. Smiley smile
Arsene a écrit :
Pas non plus celui de me pencher sur la question de <address> comme block mais un display:inline ne ferait-il pas l'affaire ?

Ce que je voulais dire, c'est qu'à l'heure actuelle le script remplace l'élément existant par un élément a, ce qui peut poser problème étant donné que address et a ne peuvent pas forcément apparaître aux mêmes endroits dans un document HTML. Ceci dit, c'est vrai que le script pourrait insérer l'élement a dans address.

Je suis d'accord avec toi sur le fait qu'une solution hybride PHP pour le parsing du texte dans une syntaxe Wiki/BBCode... et JavaScript serait sans doute intéressante.
Modifié par Julien Royer (24 Jul 2007 - 22:23)
Y compris (soyons fous !) un contact@domaine.ext en dur que PHP parse en contact+at+domaine.ext ??? Smiley lol

Autre prob rencontré un jour avec le script <span>h,h,d : une liste de contacts. Tu es obligé d'insérer une ligne contenant une adresse vide entre deux adresses valables... pas glop.
Arsene a écrit :
Y compris (soyons fous !) un contact@domaine.ext en dur que PHP parse en contact+at+domaine.ext ??? Smiley lol

En effet, grand fou ! Smiley smile
Arsene a écrit :
Autre prob rencontré un jour avec le script <span>h,h,d : une liste de contacts. Tu es obligé d'insérer une ligne contenant une adresse vide entre deux adresses valables... pas glop.

Ah mais décidément, il y a plein de choses à reprocher à ce script, mais vous ne me le dites que maintenant. Smiley langue

Je ne vois pas trop ce que tu veux dire en l'occurrence par contre.
Ben... je viens d'aller sur la page du script pour copier-coller et je vois que Benjamin a déjà apparemment fait la remarque Smiley cligne

Essaie ça :
<span class="email"><span class="u">nom</span><span class="h">domaine</span><span class="d">com</span></span>
<span class="email"><span class="u">autrenom</span><span class="h">domaine</span><span class="d">com</span></span> 


puis ça :
<span class="email"><span class="u">nom</span><span class="h">domaine</span><span class="d">com</span></span> 
<span class="email"><span class="u"></span><span class="h"></span><span class="d"></span></span> 
<span class="email"><span class="u">autrenom</span><span class="h">domaine</span><span class="d">com</span></span> 


Il est donc probable qu'entre temps ça a été corrigé ????
Modifié par Arsene (25 Jul 2007 - 09:33)
Ah OK, je n'avais pas saisi ce que tu voulais dire.
Arsene a écrit :
Il est donc probable qu'entre temps ça a été corrigé ????

Oui. Smiley smile
Hé hé, peut-être y'a t'il une piste de ce côté-là concernant le prob évoqué hier... il est possible (à vérifier donc) que l'ancienne version ne produisait pas ce bug. Je vais regarder ça, je tiens au courant.

Juste histoire de gagner du temps, tu pourrais vite fait me dire ce qui a été modifié entre la version 1 et la 2 ???
Arsene a écrit :
Juste histoire de gagner du temps, tu pourrais vite fait me dire ce qui a été modifié entre la version 1 et la 2 ???

Franchement, je ne sais plus trop. Smiley confused

Correction du bug en question, et le reste c'est du cosmétique.
Hélas je ne retrouve pas comment reconstituer le problème. J'avais additionné ce script à deux autres, l'un pour détecter la pos du curseur et l'autre pour le fil d'ariane, mais au moment de tester sur les IE PC, horreur, la page se rechargeait sans arrêt... alors que tous les autres navigateurs tournaient sans problème. Du coup comme j'avais vraiment besoin des deux autres scripts j'ai supprimé le masquage de mail. J'ai cherché en vain si il n'y avait pas un doublon de variable mais rien de bizarre à l'horizon.
En reprenant ce script et en le replaçant avec les deux autres tout marche nickel... Disons que c'était un accident aléatoire comme il en arrive quelques-uns de temps en temps ???
Pages :