Suite à l’inauguration du site de mon agence web à Mâcon (clementguillemain.fr), ce blog va être prochainement supprimé, je vous invite à sauvegarder les articles qui vous intéressent. Un nouveau blog, plus dans l’air du temps et très accès sur Symfony 2 verra également le jour. Suivez mon profil twitter @Sybio01 pour des news !

Tutoriel: utiliser l’éditeur de texte (wysiwyg) MarkItUp!

15 septembre 2010 par Sybio | Catégorie: Ressources | 1 commentaire

MarkItUp!Dans ce tutoriel, nous allons mettre en place l’éditeur de texte MarkItUp! que j’utilise la plupart du temps sur l’un de vos sites. Pratique, il permet à vos internautes d’avoir des messages personnalisables (BBCode…). Cependant, il vous faudra inclure la librairie JQuery.

Le but de ce tutoriel est clairement de permettre d’écrire du BBCode comme sur les forums.

Tout d’abord, rendez-vous sur le site pour télécharger MarkItUp!, vous pourrez au passage lire la très riche documentation du site pour aller un peu plus loin, après ce tutoriel évidemment :P . Dans la rubrique Downloads, téléchargez la dernière version de l’éditeur (markItUp! pack x.x.x).

Vous pouvez vous apercevoir que l’on peut télécharger différents « sets », en fait c’est juste des configurations toutes prêtes, avec plus ou moins d’options (gras, souligné…), histoire de gagner du temps.

Nous y reviendront.

installationI) Installation de MarkItUp

Dézippez le fichier. Seul le sous-dossier markitup nous intéresse, placez-le dans un répertoire de votre site.

Dans votre page index.php (votre template quoi…), pour que votre éditeur fonctionne correctement, vous devez inclure la librairie JQuery si ce n’est pas déjà fait, le fichier js de MarkItUp, le fichier js du set que vous voulez utiliser (pour le moment default, livré avec l’éditeur), ainsi que les styles de l’éditeur.

<!-- Librairie Jquery -->
 <script type="text/javascript" src="jquery.js"></script>

<!-- Moteur de l'éditeur -->
 <script type="text/javascript" src="chemin_vers_markitup/jquery.markitup.js"></script>

<!-- Set (que l'on va voir...) -->
 <script type="text/javascript" src="chemin_vers_markitup/sets/default/set.js"></script>

<!-- Style de l'éditeur -->
<link href="../markitup/templates/preview.css" rel="stylesheet" type="text/css" /> 

<!-- Style personnalisé du set -->
 <link rel="stylesheet" type="text/css" href="chemin_vers_markitup/sets/default/style.css" />

Enfin, vous pouvez choisir comment activer markItUp sur un textarea, en incluant ce bout de code à la suite des précédents :

<!-- Paramètre pour activer l'éditeur -->
 <script type="text/javascript" >
$(document).ready(function() {
$('#wysiwyg').markItUp(mySettings);
});
 </script>

Par exemple, si je veux assigner markitup à un textearea selon le code précédent, je devrais lui ajouter l’id wysiwyg.

<textarea id="wysiwyg"></textarea>

Imaginons que vous avez plusieurs éditeurs à afficher sur une même page, truc très pratique, vous pouvez également assigner via une classe, en remplaçant (‘#wysiwyg’).markItUp(mySettings); par (‘.wysiwyg’).markItUp(mySettings);

On appellera donc markItUp comme ça:

 <textarea class="wysiwyg"></textarea> 

Enfin, sachez que tous vos textarea peuvent se transformer automatiquement via (‘textarea’).markItUp(mySettings);, mais bon, ce n’est pas ce que je recommanderai…

Voila le code actuel de notre page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head profile="http://gmpg.org/xfn/11">

<!-- Librairie Jquery -->
 <script type="text/javascript" src="jquery.js"></script>

<!-- Moteur de l'éditeur -->
 <script type="text/javascript" src="chemin_vers_markitup/jquery.markitup.js"></script>

<!-- Set (que l'on va voir...) -->
 <script type="text/javascript" src="chemin_vers_markitup/sets/default/set.js"></script>

<!-- Style de l'éditeur -->
 <link rel="stylesheet" type="text/css" href="chemin_vers_markitup/skins/markitup/style.css" />

<!-- Style personnalisé du set -->
 <link rel="stylesheet" type="text/css" href="chemin_vers_markitup/sets/default/style.css" />

<!-- Paramètre pour activer l'éditeur, choisir entre un id, une class ou appliquer à touste les balises textarea -->
 <script type="text/javascript" >
$(document).ready(function() {
$('.wysiwyg').markItUp(mySettings);
 });</script>

</head>

<body>

<form action="blabla.php" method="post">
   <textarea name="message" class="wysiwyg"></textarea>
   <input type="submit" value="Valdider" />
</form>

</body>

</html>

L’éditeur s’affiche, et au clic d’un bouton il affiche des balises html… Imaginons dans la suite de ce tutoriel que nous voulons implémenter un système de BBCode pour nos utilisateurs, il faut que l’on configure un set pour ça, et celui sur lequel on pointe actuellement (default) a ses propres options qui affichent de l’html pour le moment.

configurationII) Configuration des boutons pour le BBCode

Intéressons nous à présent au dossier contenant MarkItUp, vous y verrez à sa racine les sous-dossiers sets, skins et templates. Ouvrez sets, et vous y trouvez notre set par défaut, représenté par le dossier default !

Un set est donc représenté par un dossier à la racine du répertoire sets. Un set contient uniquement des images, un fichier set.js (pour le configurer) et un fichier style (pour personnaliser le style de notre set).

Bref, ouvrez le dossier set.js:

mySettings = {

onShiftEnter:  	{keepDefault:false, replaceWith:'<br />\n'},

onCtrlEnter:  	{keepDefault:false, openWith:'\n<p>', closeWith:'</p>'},

onTab:    		{keepDefault:false, replaceWith:'    '},

markupSet:  [

{name:'Bold', key:'B', openWith:'(!(<strong>|!|<b>)!)', closeWith:'(!(</strong>|!|</b>)!)' },

{name:'Italic', key:'I', openWith:'(!(<em>|!|<i>)!)', closeWith:'(!(</em>|!|</i>)!)'  },

{name:'Stroke through', key:'S', openWith:'<del>', closeWith:'</del>' },

{separator:'---------------' },

{name:'Picture', key:'P', replaceWith:'<img src="[![Source:!:http://]!]" alt="[![Alternative text]!]" />' },

{name:'Link', key:'L', openWith:'<a href="[![Link:!:http://]!]"(!( title="[![Title]!]")!)>', closeWith:'</a>', placeHolder:'Your text to link...' },

{separator:'---------------' },

{name:'Clean', className:'clean', replaceWith:function(markitup) { return markitup.selection.replace(/<(.*?)>/g, "") } },

{name:'Preview', className:'preview',  call:'preview'} ]

}

C’est dans ce fichier que l’on déclare une option (= un bouton), comme par exemple activer le gras, l’italique…

De plus, si vous êtes attentifs, les options sont contenues dans une variable, mySettings, qui est utilisée lorsque l’on défini comment activer l’éditeur:

$(document).ready(function() {
$('#wysiwyg').markItUp(mySettings);
});

Tout ça pour dire que vous pouvez la renommer si vous voulez :P

Maintenant regardons de plus près cette option:

{name:’Bold’, key:’B', openWith:’(!(<strong>|!|<b>)!)’, closeWith:’(!(</strong>|!|</b>)!)’ }

Au clic de ce bouton, il affiche une balise <strong> qui se ferme avec une balise </strong>. Son raccourci au clavier est la touche B et le nom de ce bouton « Bold ».

Généralement, la balise pour le gras en BBCode est [b][/b]. Modifions la ligne précédente:

 {name:'Bold', key:'B', openWith:'[b]', closeWith:'[/b]' }

Au clic sur le gras apparaîtra à présent non pas les balises <strong> mais bien [b] !

Je vous laisse découvrir les autres options qui diffèrent un peu (regardez pour une image), mais ne perdez pas de temps à tout changer, téléchargez le set Basic BBcode Set qui génère déjà des balises en BBCode !

Si vous avez bien suivi, mettez le dossier du set dans le répertoire sets de markitup.

Dans index.php, vous ne devez plus appeler le set par défaut, mais bien le nouveau set bbcode !

<!-- Set utilisé -->
<script type="text/javascript" src="chemin_vers_markitup/sets/bbcode/set.js"></script>

Je vous laisse découvrir le fichier de configuration (set.js) du set bbcode.

Enfin, lorsque vous créez une nouvelle option, l’image ne va pas s’afficher par magie, il faudra la configurer dans le fichier style.css de votre set. Vous devrez ajouter l’image par ordre d’apparition des boutons (Etudiez le fichier css, vous allez tout de suite comprendre).

phpIII) Créer les fonctions PHP pour traduire le BBCode

Notre éditeur côté visuel fonctionne ! Quand on clic sur l’image Bold, ça nous affiche la balise [b] !

Cependant, il va falloir afficher le message sous forme HTML. Pour ça nous avons 2 choix, le premier: on sauvegarde dans la base de données les balises BBCode telles qu’elles et lorsque l’on affiche le message, on traduit le BBCode en HTML. Deuxième choix, on traduit directement le BBCode en HTML lorsqu’on enregistre le message dans la base de données, comme ça pas de problème à l’affichage !

Le plus performant est le second choix, en effet si l’on doit retraduire à chaque fois le message BBCode à l’affichage en HTML, on utilise pas mal de ressource ! Opter pour le second choix sous entend cependant de ne pas laisser la porte ouverte aux balises qui craignent, mais bon il faut le vouloir pour autoriser les mauvaises…

Donc pour résumer, il nous faut des fonctions qui traduisent le BBCode en HTML, et voici celles que j’utilise:

<!-- Votre librairie -->
<?php
class System
{
	static public function BBCodeToHtml($t) // remplace les balises BBCode par des balises HTML
	{
	   // barre horizontale
	   $t=str_replace("[/]", "<hr width=\"100%\" size=\"1\" />", $t);
	   $t=str_replace("[hr]", "<hr width=\"100%\" size=\"1\" />", $t);

	   // gras
	   $t = preg_replace("(\[b\](.+?)\[\/b])is",'<strong>$1</strong>',$t);

	   // citation
	   $t=str_replace("[quote]", "<pre class='quote'>", $t);
	   $t=str_replace("[/quote]", "</pre>", $t);

	   // italique
	   $t = preg_replace("(\[i\](.+?)\[\/i\])is",'<em>$1</em>',$t);

	   //liste
           $t = preg_replace("/\[list\](.+?)\[\/list\]/is", '<ul>$1</ul>' ,$t);
           $t = preg_replace("/\[list=1\](.+?)\[\/list\]/is", '<ul class="listdecimal">$1</ul>' ,$t);
           $t = preg_replace("/\[list=i\](.+?)\[\/list\]/s", '<ul class="listlowerroman">$1</ul>' ,$t);
           $t = preg_replace("/\[list=I\](.+?)\[\/list\]/s", '<ul class="listupperroman">$1</ul>' ,$t);
           $t = preg_replace("/\[list=a\](.+?)\[\/list\]/s", '<ul class="listloweralpha">$1</ul>' ,$t);
           $t = preg_replace("/\[list=A\](.+?)\[\/list\]/s", '<ul class="listupperalpha">$1</ul>' ,$t);
           $t = preg_replace("/\[item\](.+?)\[\/item\]/s", "<li>$1</li>", $t);

	   // souligné
	   $t = preg_replace("(\[u\](.+?)\[\/u\])is",'<u>$1</u>',$t);

	   // alignement centré
           $t = preg_replace("(\[center\](.+?)\[\/center\])is",'<div style="text-align: center;">$1</div>',$t);

	   // alignement à droite
	   $t = preg_replace("(\[right\](.+?)\[\/right\])is",'<div style="text-align: right;">$1</div>',$t);

	   // alignement à gauche
	   $t = preg_replace("(\[left\](.+?)\[\/left\])is",'<div style="text-align: left;">$1</div>',$t);

	   // alignement justifié
	   $t = preg_replace("(\[justify\](.+?)\[\/justify\])is",'<div style="text-align: justify;">$1</div>',$t);

	   // taille des caractères
	   $t = preg_replace("(\[size=(.+?)\](.+?)\[\/size\])is","<span style=\"font-size: $1px\">$2</span>",$t);

	   // Code
	   $code_html = "'<div class=\"codecontainer\"><div class=\"quotecodeheader\"> Code \\1:</div><div class=\"codebody\"><pre name=\"code\" class=\"brush: \\1\">' . str_replace('<br />', '', '\\2') . '</pre></div></div>'";
	   $t = preg_replace("#\[code=(.+?)\](.+?)\[\/code\]#sie",$code_html,$t);

	   // lien
	   $regLienSimple="\[url\] ?([^\[]*) ?\[/url\]";
	   $regLienEtendu="\[url ?=([^\[]*) ?] ?([^]]*) ?\[/url\]";
	   if (ereg($regLienSimple, $t)) $t=ereg_replace($regLienSimple, "<a href=\"\\1\">\\1</a>", $t);
	   else $t=ereg_replace($regLienEtendu, "<a href=\"\\1\" rel='nofollow' onclick='window.open(this.href); return false;'>\\2</a>", $t);

	   // image
	   $regImage="\[img\] ?([^\[]*) ?\[/img\]";
	   $regImageAlternatif="\[img ?= ?([^\[]*) ?\]";
	   if (ereg($regImage, $t)) $t=ereg_replace($regImage, "<img src=\"\\1\" alt=\"\" border=\"0\" />", $t);
	   else $t=ereg_replace($regImageAlternatif, "<img src=\"\\1\" alt=\"\" border=\"0\" />", $t);

	   return $t;
	}
}
?> 

Ainsi, lorsque vous vous apprêtez à sauvegarder, vous n'aurez qu'à faire ceci:

// on inclut la librairie
// ...
// On désactive les balises HTML contenues dans le message pour un futur affichage
// Puis on transforme nos balises BBCode en HTML, qui elles seront actives !
// nl2br pour prendre transformer les saut d'espace en balise <br />
// Enfin je vous laisse le soin de protéger votre bdd (mysql_escape_...)
 $message = System::BBCodeToHtml(nl2br(htmlentities($_POST["message"])));
// ... On sauvegarde notre message dans la bdd, et le tour est joué !

Et voila, notre éditeur est entièrement fonctionnel.

Reste un dernier point à aborder: et si je veux donner la possibilité à l'utilisateur d'éditer son message, ce sera alors des balises HTML qui vont s'afficher dans le textearea, et non des balises BBCode :o ?

Pas de soucis, il suffit de faire l'inverse, quand un utilisateur édite son message, on traduit les balises HTML en BBCode.

Voila la méthode inverse, à ajouter dans votre classe System (ou l'équivalente dans votre projet):


    static public function HtmlToBBCode($t) // remplace les balises HTML par des balises BBCode
    {
       // format d'un url
       $URLSearchString = "a-zA-Z0-9\:\/\-\?\&\.\=\_\~\#\'";
       $MAILSearchString = $URLSearchString . " a-zA-Z0-9\.@";

	// Remplace les liens. A savoir que l'on rajoute un attribut nofollow pour pas que les googlebots prennent ces liens en compte
       $t = preg_replace('#<a href="(['.$URLSearchString.']*)" rel=\'nofollow\' onclick=\'window.open(this.href); return false;\'>([\'.$URLSearchString.\']*)<\/a>#s',"[url]$1[/url]", $t);
       $t = preg_replace('#<a href="(['.$URLSearchString.']*)" rel=\'nofollow\' onclick=\'window.open(this.href); return false;\'>(.+?)<\/a>#s',"[url=$1]$2[/url]", $t);

       // saut de ligne
       $t = str_replace("<br />", "", $t);

	// citation
       $t = preg_replace('#<pre class=\'quote\'>(.+?)<\/pre>#s', "[quote]$1[/quote]",$t);

       // gras
       $t = preg_replace('#<strong>(.+?)<\/strong>#s', "[b]$1[/b]",$t);

       // italique
       $t = preg_replace('#<em>(.+?)<\/em>#s',"[i]$1[/i]",$t);

       // souligné
       $t = preg_replace('#<u>(.+?)<\/u>#s', "[u]$1[/u]",$t);

       // alignement
       $t = preg_replace('#<div style="text-align: center;">(.+?)<\/div>#s', "[center]$1[/center]",$t);
       $t = preg_replace('#<div style="text-align: left;">(.+?)<\/div>#s', "[left]$1[/left]",$t);
       $t = preg_replace('#<div style="text-align: right;">(.+?)<\/div>#s', "[right]$1[/right]",$t);
       $t = preg_replace('#<div style="text-align: justify;">(.+?)<\/div>#s', "[justify]$1[/justify]",$t);

       // taille de la police
       $t = preg_replace('#<span style="font-size: (.+?)px">(.+?)<\/span>#s',"[size=$1]$2[/size]",$t);

      // listes
       $t = preg_replace('#<ul>(.+?)<\/ul>#s', "[list]$1[/list]"  ,$t);
       $t = preg_replace('#<ul class="listlowerroman">(.+?)<\/ul>#s', "[list=i]$1[/list]"  ,$t);
       $t = preg_replace('#<ul class="listupperroman">(.+?)<\/ul>#s', "[list=I]$1[/list]"  ,$t);
       $t = preg_replace('#<ul class="listloweralpha">(.+?)<\/ul>#s', "[list=a]$1[/list]"  ,$t);
       $t = preg_replace('#<ul class="listupperalpha">(.+?)<\/ul>#s', "[list=A]$1[/list]"  ,$t);
       $t = preg_replace('#<ul class="listdecimal">(.+?)<\/ul>#s', "[list=1]$1[/list]"  ,$t);
       $t = preg_replace("#<li>(.+?)<\/li>#s", "[item]$1[/item]", $t);

       // Code
       $code_html = '#<div class="codecontainer"><div class="quotecodeheader"> Code (.+?):</div><div class="codebody"><pre name="code" class="brush: (.+?)">(.+?)</pre></div></div>#s';
       $t = preg_replace($code_html,"[code=$1]$3[/code]",$t);

       return $t;
    }

Voila comment l"utiliser:

<?php
// on inclut la librairie
// ...
// On récupère depuis la bdd le message à éditer
// Méthode inverse
 $message = System::HtmlToBBCode($message);
?>
<!-- Et on repose notre message avec BBCode dans l'éditeur de texte ! -->
<textarea class='wysiwyg'><?php echo $message; ?></textarea> 

Et voila, on peut dire que notre éditeur de texte MarkItUp! est entièrement fonctionnel... entièrement, ou à 95% ...

Et oui, vous n'avez peut-être pas vu mais il y a un bouton pour faire une prévisualisation du message avec l'éditeur tout à droite héhéhé !

previewIV) Mettre en place le mode de prévisualisation du message

Lorsque vous cliquez sur le bouton preview, markitup va chercher à afficher le fichier preview.php dans le dossier de votre set. Si vous n'en avez pas, celui-ci va afficher le fichier preview.html dans le répertoire templates (ce qui affiche une preview vide...) Copiez le contenu HTML de preview.html du répertoire templates puis collez le dans un nouveau fichier preview.php que vous placerez à la racine de votre set (ici bbcode).

Après, rien de plus simple, incluez votre librairie et mettez ce bout de code:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Preview markItUp!</title>
<link href="../markitup/templates/preview.css" rel="stylesheet" type="text/css" />
</head>
<body>
<?php
    // On inclut notre librairie (à adapter bien sûr)
    include("../../../../class/system.class.php");
    // On affiche le contenu actuel
    echo System::BBCodeToHtml(htmlentities($_POST["data"]));
?>
</body>
</html> 

Par défaut, MarkItUp va afficher le contenu actuel de l'éditeur représenté par la variable $_POST["data"]. Voila, lorsque vous cliquez sur le bouton preview, cela inclura une iframe qui ouvrira cette page !

designV) Retoucher le design de MarkItUp!

Nous voila dans la dernière partie de ce tutoriel qui consiste simplement à vous indiquer où se trouve le fichier css qui gère l'aspect de MarkItUp!... et bien c'est tout simplement le fichier que l'on a inclut en début de tutoriel (chemin_vers_markitup/skins/markitup/style.css). Vous pourrez modifier la largeur de l'éditeur. Et si vous voulez changer le logo du fond sur l'éditeur, il faudra que vous bidouillez les images (chemin_vers_markitup/skins/markitup/images) ou encore que vous ajoutez les vôtres pour plus de personnalisation.

Ce tutoriel arrive à sa fin, j'espère qu'il vous a été utile et qu'il va vous permette de mettre en place votre éditeur de texte MarkItUp! rapidement sur vos sites.
1 commentaire pour cet article:
  • 10 éditeurs HTML WYSIWYG et WYSIWYM, le 13 mars 2012 à 01:03 #1083

    [...] compatibilité avec des éléments extérieurs comme Farbastic, Simplemodal ou jQuery UI. Lire le tutoriel très complet de Clément Guillemain. [...]

Laissez votre commentaire: