Antoine Boursin

Créez un éditeur de texte WYSIWYG


Vous êtes le propriétaire d'un site et vous voulez ajouter du contenu facilement dessus ? En ce moment, vous utilisez le HTML pour mettre en page vos contenus mais vos contributeurs ne maîtrisent pas ce langage ?

Dans ce cours, je vous propose une solution simple : créer un éditeur de texte WYSIWYG.

Un quoi ??

Un éditeur WYSIWYG, vous avez bien lu, mais je devine que le problème n'est pas là… WYSIWYG signifie "What You See Is What You Get", c'est-à-dire “ce que vous voyez est ce que vous obtiendrez”. En quelques mots, un éditeur WYSIWYG permet d'éditer visuellement du texte, c'est-à-dire sans en passer par l'utilisation du HTML que connaissent bien les développeurs de sites web.

Comme exemples d'éditeurs de texte WYSIWYG, on peut citer des logiciels comme Microsoft Word, Libre Office Writer ou encore des éditeurs spécifiques au Web comme TinyMCE, CKEditor ou Froala.

Voici un exemple de ce que vous pourrez faire à la fin du cours :

Résultat final
Résultat final

Tester le code

Pour suivre ce cours, vous devez avoir des connaissances de base en HTML et en JavaScript.

Si ce n'est pas le cas, je vous invite à lire sur OpenClassrooms les parties 1 et 2 du cours sur HTML5 et CSS3 ainsi que la partie 1 du cours sur JavaScript.

Le HTML

Pour réaliser notre éditeur, nous aurons besoin de plusieurs éléments :

Une balise <div> pour un éditeur de texte ? Mais son contenu ne sera pas éditable !

Eh bien si ! Tout est possible grâce à l'attribut contentEditable qui permet d'éditer le contenu de n'importe quelle balise HTML directement via le navigateur. Vous pouvez par exemple placer cette page dans le back office de votre site Web, lieu de rédaction et de mise en forme de son contenu.

Voici le code de la page que nous utiliserons :

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>Mon éditeur WYSIWYG</title>
	</head>
	<body>
		<input type="button" value="G" style="font-weight:bold;" /> // Un bouton pour mettre en gras le texte
		<input type="button" value="I" style="font-style:italic;" /> // Un autre pour le mettre en italique
		<input type="button" value="S" style="text-decoration:underline;" /> // Et enfin un bouton pour le souligner
		<div id="editeur" contentEditable ></div> // Et votre <div> devient éditable !
	</body>
</html>

Vous pouvez tester le code en l'état mais le résultat ne sera pas très lisible. Il manque quelque chose, vous ne trouvez pas ? Avec un peu de CSS appliqué à votre <div>, ça change tout ! Pour améliorer le rendu visuel, nous allons créer une feuille de style CSS qu'on inclura dans le fichier principal grâce au code <link rel="stylesheet" href="style.css" /> placé sous la balise <title></title>. Voici son contenu :

#editeur {
	width: 500px; // La largeur de l'éditeur
	height: 200px; // La hauteur de l'éditeur
	border: 1px solid black; // Une bordure pour bien voir l'éditeur
	padding: 5px; // Une petite marge intérieure
	overflow: auto; // Cette propriété sert à envoyer le texte à la ligne au cas où il dépasse la largeur définie avant
}

Vous pouvez tester l'écriture dans le cadre, ça fonctionnera ! :magicien:

Voici un aperçu du résultat :

On peut éditer le texte directement dans le div
On peut éditer le texte directement dans le div.

Tester le code

Mise en forme basique du texte

On peut maintenant écrire du texte dans un cadre, mais ce n'est pas fini ! Notre but est de pouvoir le mettre en forme et, pour cela, nous allons avoir besoin d'instructions en JavaScript et d'une fonction commande pour la mise en forme.

Créer une fonction commande

Nous mettrons les instructions JavaScript dans un fichier editeur.js. N'oubliez pas de l'inclure dans votre page principale grâce aux balises <script src="editeur.js"></script>, sous la balise <link />.

Voici le code JavaScript de base à inclure dans ce fichier :

function commande(nom, argument) {
	if (typeof argument === 'undefined') {
		argument = '';
	}
	// Exécuter la commande
}

On peut remarquer que le second paramètre de la fonction (qui est nommé argument) est facultatif. Quand il n'est pas présent, ce qui est le cas pour l'instant, on lui donne une valeur par défaut (ici une chaîne vide).

Appeler la fonction commande

Pour chaque bouton, il faut appeler cette fonction en employant l'événement onclick.

Par exemple, pour le bouton qui met le texte en gras :

<input type="button" value="G" style="font-weight:bold;" onclick="commande('bold');" />

Vous pouvez répéter l'opération avec les commandes suivantes pour commencer :

Commande Effet
bold Met le texte en gras
italic Met le texte en italique
underline Souligne le texte
strikethrough Barre le texte

Une fois que la fonction est appelée dans le HTML, il faut répercuter son effet sur le texte saisi dans l'éditeur.

Appliquer la mise en forme

Pour cela, nous allons utiliser la fonction execCommand dans le code JavaScript.

Elle comporte 3 paramètres :

Ces paramètres étant définis, nous écrivons :

document.execCommand(nom, false, argument);

Après cette partie, vous obtenez un éditeur dans lequel vous pouvez écrire du texte et le mettre en forme.

Voici un aperçu du résultat :

Notre éditeur a des fonctions de mise en forme basiques
Notre éditeur a des fonctions de mise en forme basiques

Tester le code

Les options de mise en forme ne se limitent pas à ces quelques paramètres. Que diriez vous d'aller encore plus loin ?

Des balises un peu plus complexes

Il est également possible, et vivement conseillé, d'ajouter des éléments comme des liens ou des images dans votre texte. Pour cela, nous allons utiliser le 3e paramètre de la fonction execCommand : argument. Je vous avais bien dit qu'il servirait !

Les liens

Dans les éditeurs, généralement, l'utilisateur peut renseigner des liens dans une petite fenêtre et les intégrer à son texte. Pour obtenir cet effet, ce n'est pas compliqué. La commande à utiliser est createLink mais pour commencer, n'oubliez pas de rajouter un bouton Lien.

<input type="button" value="Lien" onclick="commande('createLink');" />

Ensuite, pour pouvoir demander le lien à l'utilisateur, nous utiliserons la fonction prompt("texte") qui permet de renseigner des informations sous forme de texte. Nous allons la rajouter dans la fonction commande de votre code JavaScript. Voici comment elle se présente :

switch (nom) {
	case "createLink":
		argument = prompt("Quelle est l'adresse du lien ?");
	break;
}

Pour ouvrir la page via l'éditeur et vérifier si le lien fonctionne, vous pouvez cliquer dessus en maintenant la touche Ctrl enfoncée. Vous pouvez supprimer le lien grâce à la commande unlink. Dans ce cas, il faut l'appeler comme les commandes précédentes grâce au code JavaScript onclick="commande('unlink');" inséré dans un bouton.

Les images

Le fonctionnement est le même que pour les liens : on demande à l'utilisateur de renseigner l'adresse de l'image dans une petite fenêtre puis on utilise la commande insertImage pour qu'elle s'affiche convenablement. Avant, n'oublions pas de rajouter un bouton Image :

<input type="button" value="Image" onclick="commande('insertImage');" />

et une partie dans notre switch dans le code JavaScript :

case "insertImage":
	argument = prompt("Quelle est l'adresse de l'image ?");
break;

Vous pouvez redimensionner l'image une fois qu'elle est insérée en cliquant dessus. Plutôt pratique comme commande, non ?

Les titres

Pour les titres, je vous conseille d'utiliser une liste déroulante qui permet de choisir les différents styles. En plus, ce sera l'occasion d'utiliser un autre élément des formulaires en HTML. Pour cela, nous allons utiliser la balise <select> et l'attribut onchange. La commande à utiliser est heading et elle requiert un argument dans la fonction commande() : le niveau du texte. Dans le code suivant, on lui donne la valeur de l'option sélectionnée grâce au code JavaScript this.value.

<select onchange="commande('heading', this.value); this.selectedIndex = 0;">
	<option value="">Titre</option>
	<option value="h1">Titre 1</option>
	<option value="h2">Titre 2</option>
	<option value="h3">Titre 3</option>
	<option value="h4">Titre 4</option>
	<option value="h5">Titre 5</option>
	<option value="h6">Titre 6</option>
</select>
Aperçu des nouvelles balises
Aperçu des nouvelles balises

Tester le code

Les autres commandes

Voici une liste (non exhaustive) de commandes que vous pouvez utiliser. Ces commandes sont reconnues par la plupart des navigateurs mais peuvent avoir un rendu différent. Nous y reviendrons plus loin.

Commande Effet sur le texte
justifyleft Aligné à gauche
justifyright Aligné à droite
justifycenter Centré
justifyfull Justifié
insertunorderedlist Liste à puces
insertorderedlist Liste numérotée
backcolor Couleur de fond
forecolor Couleur du texte
fontname Police d'écriture
inserthorizontalrule Insère une ligne horizontale (<hr>)
subscript Indice
superscript Exposant

Vous pourrez trouver une liste plus complète des commandes reconnues par Mozilla Firefox sur la page dédiée.

Ces commandes sont reconnues par la plupart des navigateurs mais ce n'est pas le cas de toutes les commandes. Pour savoir quelles commandes sont compatibles avec votre navigateur, vous pouvez aller sur cette page Codepen qui affiche en vert les commandes reconnues par votre navigateur.

Vous pouvez trouver la spécification des commandes par le w3c sur cette page.

Récupérer le HTML

Une fois que vous avez votre texte tout beau et parfaitement mis en forme, vous souhaitez peut-être le récupérer et l'intégrer ailleurs ? Pas de souci, tout est prévu !

Pour récupérer la version en HTML du texte, nous allons créer une balise textarea dans votre page HTML qui affichera une zone de texte en dessous de la zone d'édition délimitée par la balise <div>. Voici comment elle se présente :

<input type="button" onclick="resultat();" value="Obtenir le HTML" /><br />
<textarea id="resultat"></textarea>

J'ai appliqué à la balise textarea le même style qu'à la balise div en changeant le sélecteur CSS :

#editeur, #resultat { // On applique les mêmes styles à la balise textarea qu'à la balise div
  width: 500px;
  height: 200px;
  border: 1px solid black;
  padding: 5px;
  overflow: auto;
}

Maintenant que la zone d'affichage du texte en HTML a été délimitée, nous pouvons créer la fonction resultat() en dessous de la fonction commande() dans le code en JavaScript. Pour récupérer le HTML, on utilise la fonction innerHTML qui, comme son nom l'indique, permet de révéler le code HTML.

function resultat() {
	document.getElementById("resultat").value = document.getElementById("editeur").innerHTML;
}
Affichage du code HTML
Affichage du code HTML

Le résultat peut varier selon le navigateur utilisé. Par exemple, sur Internet Explorer, le texte en gras sera remplacé par la balise <strong> alors que sur Firefox ou Chrome, il sera remplacé par <b>.

Tester le code

Idées d'améliorations

Pour faciliter le travail de mise en forme d'un texte, de nombreux éditeurs utilisent la fonction queryCommandValue. Intégrée au code JavaScript, elle permet de changer le style d'un bouton quand il est utilisé, c'est-à-dire si vous placez votre curseur sur un texte en gras, le bouton B change d'apparence. La fonction queryCommandValue prend un seul paramètre qui est celui de la commande à tester. Voici un code d'exemple pour vous lancer :

if (document.queryCommandValue("bold")) {
	document.getElementById("bouton_bold").className = "actif";
}
else {
	document.getElementById("bouton_bold").className = "";
}

N'oubliez pas de rajouter un attribut id au bouton qui permet d'utiliser la fonction getElementById, ni de répéter ce code autant de fois qu'il y a de boutons !

Vous pouvez bien évidemment améliorer le design, rajouter d'autres boutons ou dynamiser l'éditeur. Voici un exemple d'un éditeur WYSIWYG assez complet mais qui suit le même principe : wysihtml. Vous pouvez trouver la source de cet éditeur sur ce répertoire GitHub.

Voilà, vous venez de créer un éditeur de texte visuel que vous pourrez utiliser sur vos sites, blogs ou autres. C'est quand même plus sympathique que d'écrire le HTML à la main, n'est-ce pas ? :pirate:

À propos

Ce cours a été initialement publié sur OpenClassrooms après avoir remporté le vote des lecteurs lors d'un évènement.
Suite à son retrait indépendant de ma volonté, il est désormais republié sur mon propre site internet.

Licence Creative Commons
Ce(tte) œuvre est mise à disposition selon les termes de la Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International.

Dernière mise à jour : 20 octobre 2021.