Les balises BBCode (Bulletin Board Code) ont été inventées afin d’éviter l’ajout de code malveillant tout en permettant et simplifiant la mise en forme de messages, articles, ou tout autres éléments textuels ou visuels.
On les retrouve essentiellement dans les formulaires des forums de discutions ou dans des CMS du type WordPress ou Prestashop.

Il peut également être utile d’implémenter un système BBCode lors du développement d’un site web pour un client qui souhaiterait pouvoir lui-même ajouter, modifier ou supprimer le contenu de certaines pages de son site depuis le backoffice (ou panneau d’administration), et ce, en toute sécurité et sans avoir de connaissances particulières en HTML.

Dans cet article, nous allons voir pas à pas comment implémenter son propre système BBCode.
Le code présenté ici concerne uniquement le côté « client » du site (HTML/CSS, Javascript/JQuery).
Le code côté « serveur » permettant d’interpréter et de transformer les balises BBCode en balises HTML fera l’objet d’un second article.

Etape 1 : la mise en page du formulaire et des boutons du BBCode

Le code du formulaire

Ici, rien de bien compliqué. On crée juste notre textarea où sera saisi le contenu textuel auquel on ajoute un bouton pour enregistrer le tout.

[pastacode lang= »markup » manual= »%3Cform%20id%3D%22form_bbcode%22%20name%3D%22form_bbcode%22%20method%3D%22post%22%20%3E%0A%20%20%20%20%3Ctextarea%20id%3D%22monContenu%22%20name%3D%22monContenu%22%20rows%3D%2215%22%20cols%3D%22100%22%3E%3C%2Ftextarea%3E%0A%20%20%20%20%3Cbutton%20type%3D%22submit%22%20name%3D%22bouton_enregistrer%22%20class%3D%22bouton_enregistrer%22%20id%3D%22bouton_enregistrer%22%3EEnregistrer%20les%20modifications%3C%2Fbutton%3E%09%09%09%09%0A%3C%2Fform%3E%0A » message= » » highlight= » » provider= »manual »/]

Le code des boutons des différentes balises BBCode

Pour chaque bouton, on fera appel à un événement « onclick » qui permettra d’ajouter la balise BBCode en question au sein de notre contenu textuel. Pour le moment notre évènement « onclick » ne contient aucun code. Nous y reviendrons un peu plus loin 😉

[pastacode lang= »markup » manual= »%3Cdiv%20id%3D%22bouton_bbcode%22%3E%0A%20%20%20%20%3Cbutton%20type%3D%22button%22%20class%3D%22bbcode_button%22%20onclick%3D%22%22%3ESous-titre%3C%2Fbutton%3E%0A%20%20%20%20%3Cbutton%20type%3D%22button%22%20class%3D%22bbcode_button%22%20onclick%3D%22%22%3EParagraphe%3C%2Fbutton%3E%0A%20%20%20%20%3Cbutton%20type%3D%22button%22%20class%3D%22bbcode_button%22%20onclick%3D%22%22%3ERetour%20%C3%A0%20la%20ligne%3C%2Fbutton%3E%0A%20%20%20%20%3Cbutton%20type%3D%22button%22%20class%3D%22bbcode_button%22%20onclick%3D%22%22%3EItalique%3C%2Fbutton%3E%0A%20%20%20%20%3Cbutton%20type%3D%22button%22%20class%3D%22bbcode_button%22%20onclick%3D%22%22%3EGras%3C%2Fbutton%3E%0A%20%20%20%20%3Cbutton%20type%3D%22button%22%20class%3D%22bbcode_button%22%20onclick%3D%22%22%3EListe%3C%2Fbutton%3E%0A%20%20%20%20%3Cbutton%20type%3D%22button%22%20class%3D%22bbcode_button%22%20onclick%3D%22%22%3EEl%C3%A9ment%20de%20la%20liste%3C%2Fbutton%3E%0A%3C%2Fdiv%3E%0A » message= » » highlight= » » provider= »manual »/]

Etape 2 : le code Javascript

Entrons dans le vif du sujet avec l’ajout des fonctions Javascript qui nous permettront d’ajouter les balises BBCode dans notre textarea.
Les éléments à prendre en compte pour l’écriture de notre code :
– nous pouvons avoir deux types de balises : des balises doubles, ouvrantes et fermantes (exemple : [p][/p]) ; ainsi que des balises uniques (exemple : [br])
– les balises doivent pouvoir s’insérer avant ou après le texte, ou bien entre une portion de texte sélectionnée par l’utilisateur

Fonction d’ajout des balises

Il s’agit de la fonction principale. On lui passe trois paramètres : l’id de notre textarea ; la balise BBCode ouvrante ; la balise BBCode fermante (si elle existe).

[pastacode lang= »javascript » manual= »function%20addBalises(idTextarea%2C%20baliseOpen%2C%20baliseClose)%20%7B%7D » message= » » highlight= » » provider= »manual »/]

Avant d’écrire le code de notre fonction addBalises() nous allons avoir besoin de définir trois autres fonctions qui vont récupérer notre contenu textuel :
– une pour récupérer le texte présent avant la position du curseur
– une pour récupérer le texte présent après la position du curseur
– une pour récupérer le texte présent dans la sélection du curseur (sélection en « surbrillance »)

Fonction permettant de récupérer le texte présent avant la position du curseur

La fonction prend deux paramètres : notre texte en question (celui présent dans le textarea) et la position de notre curseur (nous verrons comment la récupérer un peu plus loin grâce à JQuery).
Quant au code de la fonction, il s’agit d’une simple boucle qui récupère tous les caractères présents avant la position de notre curseur pour nous retourner ensuite le tout 🙂

[pastacode lang= »javascript » manual= »function%20getTextBeforeCursor(text%2C%20value)%0A%7B%0A%20%20%20%20var%20textBefore%20%3D%20 »%3B%0A%20%20%20%20for%20(var%20i%20%3D%200%20%3B%20i%20%3C%20value%20%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20textBefore%20%2B%3D%20text%5Bi%5D%3B%0A%20%20%20%20%7D%0A%20%20%20%20return%20textBefore%3B%0A%7D%0A » message= » » highlight= » » provider= »manual »/]

Fonction permettant de récupérer le texte présent après la position du curseur

La fonction prend trois paramètres : notre texte en question ; la position de notre curseur ; le nombre total de caractères de notre texte.
La boucle de notre fonction récupère les caractères présents à partir de la position du curseur jusqu’à la fin de notre texte.

[pastacode lang= »javascript » manual= »function%20getTextAfterCursor(text%2C%20value%2C%20textSize)%0A%7B%0A%20%20%20%20var%20textAfter%20%3D%20 »%3B%0A%20%20%20%20for%20(var%20i%20%3D%20value%20%3B%20i%20%3C%20textSize%20%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20textAfter%20%2B%3D%20text%5Bi%5D%3B%0A%20%20%20%20%7D%0A%20%20%20%20return%20textAfter%3B%0A%7D%0A » message= » » highlight= » » provider= »manual »/]

Fonction permettant de récupérer le texte présent dans la sélection du curseur

La fonction prend trois paramètres : notre texte en question ; la position de notre curseur au début de la sélection ; la position de notre curseur à la fin de la sélection.
Toujours à l’aide d’une boucle For (ou structure itérative pour les puristes 🙂 ), on récupère le texte présent au sein de la sélection en surbrillance : du premier au dernier caractère de la sélection.

[pastacode lang= »javascript » manual= »function%20getTextSelectionCursor(text%2C%20startValue%2C%20endValue)%0A%7B%0A%09var%20textSelection%20%3D%20 »%3B%0A%09for%20(var%20i%20%3D%20startValue%20%3B%20i%20%3C%20endValue%20%3B%20i%2B%2B)%20%7B%0A%09%09textSelection%20%2B%3D%20text%5Bi%5D%3B%0A%09%7D%0A%09return%20textSelection%3B%0A%7D%0A » message= » » highlight= » » provider= »manual »/]

Revenons à notre fonction principale

Maintenant que nous avons écrit les trois fonctions permettant de récupérer notre contenu textuel, nous allons pouvoir revenir à notre fonction principale : addBalises(idTextarea, baliseOpen, baliseClose).

Comme nous l’avons vu au tout début de la 2nd étape, nous devons pouvoir gérer deux types de balises BBCode : les balises doubles (ouvrantes et fermantes) et les balises uniques.
Nous allons donc définir une première structure conditionnelle au sein de notre fonction pour ces deux cas de figure.

[pastacode lang= »javascript » manual= »function%20addBalises(idTextarea%2C%20baliseOpen%2C%20baliseClose)%0A%7B%0A%09%2F%2F%20Si%20baliseClose%20est%20diff%C3%A9rent%20de%20NULL%2C%20nous%20avons%20affaire%20%C3%A0%20une%20balise%20double%0A%09if%20(baliseClose%20!%3D%20null)%20%7B%7D%0A%09%2F%2F%20Si%20non%2C%20nous%20avons%20affaire%20%C3%A0%20une%20balise%20unique%0A%09else%20%7B%7D%0A%7D%0A » message= » » highlight= » » provider= »manual »/]

Pour une balise unique

Commençons par écrire le code pour le cas où nous avons à faire à une balise unique :

[pastacode lang= »javascript » manual= »var%20textBefore%20%3D%20getTextBeforeCursor(%24(idTextarea).val()%2C%20%24(idTextarea).prop(‘selectionStart’))%3B%0Avar%20textAfter%20%3D%20getTextAfterCursor(%24(idTextarea).val()%2C%20%24(idTextarea).prop(‘selectionStart’)%2C%20%24(idTextarea).val().length)%3B%09%09%0A%24(idTextarea).val(textBefore%2BbaliseOpen%2BtextAfter)%3B%0A » message= » » highlight= » » provider= »manual »/]

Avec la première ligne, on récupère le texte éventuellement présent avant la position du curseur grâce à notre fonction getTextBeforeCursor() en lui passant deux paramètres : le texte présent dans le textarea ; et enfin la position de notre curseur. On récupère cette dernière à l’aide de la fonction prop() de JQuery, qui va nous permettre de lire les propriétés de notre textarea, en lui passant en paramètre selectionStart pour lui demander de nous retourner le nombre de caractères présents avant la position du curseur.

La deuxième ligne nous permet de récupérer le texte éventuellement présent après la position du curseur. La fonction getTextAfterCursor() fait la même chose que getTextBeforeCursor(), à la différence qu’elle prend un troisième paramètre qui est le nombre total de caractères de notre texte.

Enfin, avec la troisième ligne, on modifie le contenu de notre textarea à l’aide d’une simple concaténation : le texte éventuellement présent avant la position du curseur + notre balise BBCode + le texte éventuellement présent après la position du curseur.

Note informative : comme notre fonction ne peut pas savoir s’il y a du texte avant ou après notre contenu textuel (ou pas de texte du tout, si notre textarea est vide !), nous devons tester les deux éventualités. Si aucun contenu textuel n’existe avant et/ou après notre balise BBCode, getTextBeforeCursor() et/ou getTextAfterCursor() nous retournera tout simplement un résultat NULL.

Pour une balise double

Pour une balise BBCode ouvrante et fermante, nous avons deux cas de figure possibles :
– L’ajout de balises sans portion de texte (exemple : [p][/p])
– L’ajout de balises où une portion de texte aurait été sélectionnée par l’utilisateur (exemple : [p]ma portion de texte[/p])

Nous allons donc implémenter une seconde structure conditionnelle :

[pastacode lang= »javascript » manual= »%2F%2F%20Si%20la%20position%20de%20d%C3%A9part%20du%20curseur%20est%20identique%20%C3%A0%20la%20position%20de%20fin%2C%20cela%20signifie%20qu%E2%80%99aucune%20portion%20de%20texte%20n%E2%80%99a%20%C3%A9t%C3%A9%20s%C3%A9lectionn%C3%A9e%20par%20l%E2%80%99utilisateur%0Aif%20(%24(idTextarea).prop(‘selectionStart’)%20%3D%3D%20%24(idTextarea).prop(‘selectionEnd’))%20%7B%7D%0A%2F%2F%20Sinon%2C%20nous%20sommes%20dans%20le%20cas%20o%C3%B9%20une%20portion%20de%20texte%20a%20%C3%A9t%C3%A9%20s%C3%A9lectionn%C3%A9e%20par%20l%E2%80%99utilisateur%0A%7D%20else%20%7B%7D%0A » message= » » highlight= » » provider= »manual »/]

Cas de figure où aucune portion de texte n’a été sélectionnée

[pastacode lang= »javascript » manual= »var%20textBefore%20%3D%20getTextBeforeCursor(%24(idTextarea).val()%2C%20%24(idTextarea).prop(‘selectionStart’))%3B%0Avar%20textAfter%20%3D%20getTextAfterCursor(%24(idTextarea).val()%2C%20%24(idTextarea).prop(‘selectionStart’)%2C%20%24(idTextarea).val().length)%3B%0A%24(idTextarea).val(textBefore%2BbaliseOpen%2BbaliseClose%2BtextAfter)%3B%0A » message= » » highlight= » » provider= »manual »/]

Inutile de détailler le code, il est identique à celui que nous avons vu dans le cadre où nous avons affaire à une balise BBCode unique.
La seule différence se trouve dans la 3e ligne où l’on retrouve une balise ouvrante (« baliseOpen ») et une balise fermante (« baliseClose ») dans notre concaténation.

Cas de figure où une portion de texte a été sélectionnée

[pastacode lang= »javascript » manual= »var%20textBefore%20%3D%20getTextBeforeCursor(%24(idTextarea).val()%2C%20%24(idTextarea).prop(‘selectionStart’))%3B%0Avar%20textAfter%20%3D%20getTextAfterCursor(%24(idTextarea).val()%2C%20%24(idTextarea).prop(‘selectionEnd’)%2C%20%24(idTextarea).val().length)%3B%0Avar%20textSelection%20%3D%20getTextSelectionCursor(%24(idTextarea).val()%2C%20%24(idTextarea).prop(‘selectionStart’)%2C%20%24(idTextarea).prop(‘selectionEnd’))%3B%0A%24(idTextarea).val(textBefore%2BbaliseOpen%2BtextSelection%2BbaliseClose%2BtextAfter)%3B%0A » message= » » highlight= » » provider= »manual »/]

Avec les deux premières lignes, nous commençons par récupérer le texte présent avant et après la position du curseur.

La troisième ligne nous permet de récupérer le texte mis en surbrillance par l’utilisateur. La fonction getTextSelectionCursor() prend en paramètres : le texte présente dans le textarea ; la position de départ du curseur (où débute la surbrillance) ; la position de fin du curseur (où s’arrête la surbrillance).

On modifie ensuite le contenu de notre textera toujours à l’aide d’une concaténation de variables : le texte éventuellement présent avant la position du curseur + notre balise BBCode ouvrante + le texte mis en surbrillance par l’utilisateur + notre balise BBCode fermante + le texte éventuellement présent après la position du curseur.

Télécharger le code source

Bien entendu, le code présenté dans cet article ne comporte pas toutes les balises BBCode de mise en forme existantes. Il est tout à fait possible d’en implémenter de nouvelles. Libre à vous donc de modifier le code source selon vos besoins 😉

N’hésitez pas à poster un commentaire et/ou partager cet article s’il vous a aidé ou si vous pensez qu’il pourra aider des personnes de votre entourage.

Pour télécharger le code source complet : Code source (partie 1)

Pour voir la seconde partie du tutoriel : Créer son système BBCode (partie 2 : côté serveur)