Le script d'insertion n'est absolument pas compliqué (d'ailleurs, il n'y a rien de compliqué dans ce tuto

).
Je vais créer la fonction
insertTag() qui permettra d'insérer une balise autour de la sélection (ou juste le curseur, s'il n'y a pas de sélection).
Code : JavaScript - Fonction insertTag() | function insertTag(startTag, endTag, textareaId, tagType) {
var field = document.getElementById(textareaId); // On récupère la zone de texte
var scroll = field.scrollTop; // On met en mémoire la position du scroll
field.focus(); // On remet le focus sur la zone de texte, suivant les navigateurs, on perd le focus en appelant la fonction.
// Reste du code ici ^^
}
|
Les arguments
startTag et
endTag représentent respectivement la balise d'ouverture et la balise de fermeture.
textareaId est l'
ID de la zone de texte dans laquelle sera insérée la balise.
tagType servira pour après pour les insertions de balises "exotiques", comme les citations, les liens, enfin, pour tout ce qui demande un traitement autre que simplement ajouter une balise d'ouverture et une balise de fermeture.
Maintenant que la fonction principale est définie, on peut créer les appels au sein du code HTML, avec un événement
onClick :
Code : HTML | onclick="insertTag('<balise>','</balise>','textarea');"
|
Donc, ajoutez cet événement sur les différents éléments cliquables, comme ceci :
Code : HTML | <input type="button" value="G" onclick="insertTag('<gras>','</gras>','textarea');" />
|
Comme cela, quand l'utilisateur cliquera sur le bouton G (pour mettre en gras), les balises
<gras> et </gras> seront insérées de part et d'autre du curseur, ou de la sélection.
Fonctionnement de la fonction d'insertion
Dans un premier temps, il faut récupérer la portion de texte sélectionnée (la sélection). Ensuite, il faut introduire, de part et d'autre de la sélection les balises. Dans les deux cas, la manière de procéder diffère suivant les navigateurs. Internet Explorer ne gère pas du tout les sélections de la même façon que les autres navigateurs. Enfin, en réalité, IE gère bien la sélection, car il est possible de ne récupérer que la sélection directement, alors qu'avec les autres navigateurs, il faut faire un peu plus d'analyses.
Récupérer la sélection
La première étape de la fonction
insertTag() est de récupérer la sélection. Si l'utilisateur n'a rien sélectionné, la sélection est vide (ouais, logique ça

).
Internet Explorer possède son propre système pour récupérer une sélection.
Internet Explorer
Internet Explorer utilise l'objet
selection pour manipuler les sélections de texte (pas seulement dans les zones de texte). Le principe est le suivant : on récupère la sélection (on crée un
TextRange) avec la méthode
createRange(), et on convertit cette sélection en texte pour pouvoir l'utiliser. La méthode
createRange() récupère en fait le début et la fin de la sélection, c'est pour cela qu'il faut transformer, avec la propriété
text :
Code : JavaScript | var textRange = document.selection.createRange(); // On récupère sous forme de TextRange
var currentSelection = textRange.text; // On convertit ce TextRange en chaine de caractères
|
La variable
currentSelection contient donc le texte de la sélection.
Les autres navigateurs
La méthode n'est pas du tout la même que pour Internet Explorer. Ici, il faut récupérer la position du début de la sélection, ainsi que la fin, et récupérer "manuellement" la sélection courante. Pour trouver le début et la fin de la sélection, on doit utiliser respectivement les propriétés
selectionStart et
selectionEnd :
Code : JavaScript | var startSelection = field.value.substring(0, field.selectionStart);
var currentSelection = field.value.substring(field.selectionStart, field.selectionEnd);
var endSelection = field.value.substring(field.selectionEnd);
|
Remarquez que field intervient ici, car les propriétés doivent s'appliquer sur l'objet considéré (le textarea), au contraire d'IE qui récupère une sélection n'importe où dans la page !
Mais en fait, quelle était l'utilité de récupérer la sélection ?
Bah c'est assez simple en fait : ça permet de savoir où se trouve le curseur (le curseur est en fait une sélection dont le début est égal à la fin, elle est nulle). Et en connaissant ça, on va pouvoir injecter les balises avant et après... De plus, on pourra agir et analyser le texte sélectionné pour faire des insertions spéciales, comme des liens ou des citations.
Réintroduire les balises
Ici encore, les méthodes pour les deux navigateurs sont différentes.
Internet Explorer
On continue avec l'objet
selection ! On va reprendre la variable
textRange et modifier son contenu. La sélection dans le champ de texte est alors "mise à jour" :
Code : JavaScript | textRange.text = startTag + currentSelection + endTag;
|
En théorie, tout fonctionne. Mais en pratique, il y a quelque chose d'embêtant : le curseur d'écriture : il n'est plus dans le champ ! Ce qu'on veut arriver à faire, c'est resélectionner ce qui se trouve entre les balises fraîchement insérées. Ainsi par exemple, réinsérer une nouvelle paire de balises sans devoir resélectionner.
Internet Explorer offre 3 méthodes permettant d'agir sur une sélection :
move() moveStart() et
moveEnd().
- move() sert à déplacer la sélection complète. On ne va pas l'utiliser, mais elle peut être utile ;
- moveStart() sert à déplacer le début de la sélection ;
- moveEnd() sert donc à déplacer la fin de la sélection.
Voici comment effectuer ces déplacements :
Code : JavaScript | textRange.moveStart("character", -endTag.length - currentSelection.length);
textRange.moveEnd("character", -endTag.length);
|
Les méthodes
move(sUnit, iCount) prennent deux arguments :
sUnit et
iCount.
sUnit est un peu spécial : c'est la manière de déplacer la sélection. En indiquant
character on indique qu'on veut déplacer lettre par lettre. D'autres valeurs sont acceptées comme
word ou
sentence.
iCount, c'est tout simplement la grandeur du déplacement.
Dans le cas du
moveStart(),
iCount vaudra la longueur de la balise de fin (endTag) plus la longueur de la sélection. C'est présenté sous la forme d'une soustraction car on recule le début de la sélection.
Dans le cas du
moveEnd(),
iCount vaudra juste la longueur de endTag, toujours en négatif.
Pour terminer, on applique la méthode
select() à notre TextRange pour remplacer sélectionner.
Code : JavaScript
Les autres navigateurs
Le principe n'est toujours pas le même que pour IE. Ici, nous allons tout simplement remplacer le contenu de la zone de texte par le nouveau contenu comprenant les balises :
Code : JavaScript | field.value = startSelection + startTag + currentSelection + endTag + endSelection;
field.focus(); // On remet le focus sur la zone de texte
|
Comme avec Internet Explorer, on va redéfinir la sélection. On va utiliser la méthode
setSelectionRange(Debut, Fin) que l'on va appliquer sur
field.
Cette méthode requiert deux arguments : la position de départ de la sélection, et la position de fin. Pas besoin de deux méthodes comme avec Internet Explorer.
- La position de départ se calcule en faisant la somme de tout ce qu'il y a avant : startSelection et startTag.
- Pour la position de fin, on ajoute simplement la longueur de currentSelection.
Code : JavaScript | field.setSelectionRange(startSelection.length + startTag.length, startSelection.length + startTag.length + currentSelection.length);
|
Récapitulatif du script
Pour détecter si le navigateur est Internet Explorer, il suffit théoriquement de vérifier s'il gère l'objet
document.selection. J'ai bien dit
théoriquement, car il y a un petit fauteur de trouble qui est... Opera.
Opera, non content de supporter le JavaScript, supporte aussi le
JScript, qui est l'implémentation de Javascript dans Internet Explorer. Les exceptions que nous avons vues précédemment pour IE sont en fait du JScript, qui ajoutait à l'époque des fonctions en plus au Javascript.
Donc, comme Opera gère le JScript, si on fait un
document.selection, la valeur retournée sera
true.
Mais si Opera gère le JScript, où est le problème ?
Le problème est juste que Opera gère mal le JScript et plus particulièrement le repositionnement du curseur si il n'y a pas de sélection. C'est plutôt gênant. Il faut donc faire en sorte que seul IE utilise les portions de code en Jscript, et pour cela, il suffit de tester si le navigateur prend en charge ActiveX, que seul IE gère !
Voici donc ce que peut donner le script :
Code : JavaScript 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | function insertTag(startTag, endTag, textareaId, tagType) {
var field = document.getElementById(textareaId);
var scroll = field.scrollTop;
field.focus();
if (window.ActiveXObject) { // C'est IE
var textRange = document.selection.createRange();
var currentSelection = textRange.text;
textRange.text = startTag + currentSelection + endTag;
textRange.moveStart("character", -endTag.length - currentSelection.length);
textRange.moveEnd("character", -endTag.length);
textRange.select();
} else { // Ce n'est pas IE
var startSelection = field.value.substring(0, field.selectionStart);
var currentSelection = field.value.substring(field.selectionStart, field.selectionEnd);
var endSelection = field.value.substring(field.selectionEnd);
field.value = startSelection + startTag + currentSelection + endTag + endSelection;
field.focus();
field.setSelectionRange(startSelection.length + startTag.length, startSelection.length + startTag.length + currentSelection.length);
}
field.scrollTop = scroll; // et on redéfinit le scroll.
}
|
Et voilà. Le script principal est quasi fini. Il est temps maintenant de l'améliorer pour qu'il puisse gérer les différentes sortes d'insertions (comme les liens, les citations...).