Complétion de code

Description

voilà ma version BETA de complétion d'un code que j'ai inventé pour formater le texte des forums d'un site de programmation...

DONC ça permet d'écrire du code qui n'a pas encore de documentation puisque c'est encore en dév et tout et tout...

Source / Exemple :


<html>
<head>
<title>Test d'éditeur avec complétion de code</title>
<style>
<!--
textarea
{
    font-family: 'Courier New';
    font-size: 13px;
    border: solid 1px #7F9DB9;
    width: 768px;
    height: 200px;
}

.normal
{
    color: #474747;
    font-family: Tahoma, Helvetica, "Bitstream Vera Sans", sans-serif;
    font-size: 11px;
    font-weight: normal;
}

.Editeurbleu
{
    color: #6699CC;
    font-weight: bold;
}

.Editeuraide
{
    font-style: italic;
    color: #A0A0A0;
}

tr.Editeurnormal
{
    font-family: Tahoma; 
    font-size: 11px; 
    color: #606060;
    background-color: #FFFFEE;
    cursor: pointer;
}

tr.Editeurmover
{
    font-family: Tahoma; 
    font-size: 11px; 
    color: #606060;
    background-color: #DDEEFF;
    cursor: pointer;
}
-->
</style>
<script type="text/javascript">

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 Objet Mot, contient les données d'un mot à compléter
 ------------------------------------------------------------
 Propriété  Construction    Description
 ------------------------------------------------------------
 mot        strMot          le mot
 aide       strAide         l'aide concernant ce mot
 apres      bApres          vrai s'il y a quelque chose après sinon faux
 ferme      bFerme          vrai si la balise doit être fermée sinon faux (uniquement pour niveau zéro)

  • * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
function Mot (strMot, strAide, bApres, bFerme) { this.mot = strMot; this.aide = strAide; this.apres = bApres; this.ferme = bFerme; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Objet Liste de mots, contient une liste des mots disponibles ------------------------------------------------------------ Propriété Construction Description ------------------------------------------------------------ niveau iNiveau niveau de la liste avant strAvant mot qui DOIT précéder mots arrMots tableau d'objets mot
  • * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
function ListeMot (iNiveau, strAvant, arrMots) { this.niveau = iNiveau; this.avant = strAvant; this.mots = arrMots; // Crée la liste HTML à afficher en tenant compte de l'égalité éventuelle // strAvant: chaine du texte déjà écrit // strEgalite: égalité à vérifier this.creerListe = function (strAvant, strEgalite) { // Soyons fous ! strEgalite = strEgalite.split(" ")[0].split("\r")[0].split("\n")[0].split("\t")[0]; if (strEgalite == "") strEgalite == null; var retour = ""; for (i = 0; i < this.mots.length; i++) { if (strEgalite == null || this.mots[i].mot.substr(0, strEgalite.length) == strEgalite) { if (retour == "") retour = "<table border=\"0\" cellpadding=\"2\" cellspacing=\"0\">"; if (strEgalite == null) strCompletion = this.mots[i].mot; else strCompletion = this.mots[i].mot.substr(strEgalite.length, this.mots[i].mot.length - strEgalite.length); if (this.mots[i].apres) strCompletion += ":"; else strCompletion += "]"; retour += "<tr class=\"Editeurnormal\" onmouseover=\"javascript:this.className = 'Editeurmover'\" onmouseout=\"javascript:this.className = 'Editeurnormal';\" onmouseup=\"javascript:ajouteTexte('" + strCompletion + "');\">"; retour += "<td>"; retour += strAvant + " <span class=\"Editeurbleu\">" + this.mots[i].mot + "</span>"; if (this.mots[i].apres) retour += " :"; else retour += " ]"; retour += "</td>"; retour += "<td class=\"Editeuraide\">" + this.mots[i].aide; retour += "</td>"; retour += "</tr>"; } } if (retour == "") retour = "<div style=\"font-family: Tahoma; font-size: 11px; font-weight: bold; color: #FFFFFF; background-color: #DD0000; padding: 4px;\">Erreur dans le code !</div>"; else retour += "</table>"; return retour; } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Objet Code, contient les données d'un code ------------------------------------------------------------ Propriété Construction Description ------------------------------------------------------------ niveaux arrNiveaux tableau des niveaux de la balise position iPosition position dans le texte en caractères (0 = 1er carac, etc...) longueur iLongueur longueur du texte original du code ferme bFerme vrai si la balise est finie par un "]" sinon faux balisefin bBaliseFin vrai si la balise commence pa "[/" et donc est une balise de fin abalisefin bABaliseFin si la balise n'est pas une balise de fin, est-ce qu'elle possède une balise de fin ?
  • * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
function Code (arrNiveaux, iPosition, iLongueur, bFerme, bBaliseFin, bABaliseFin) { this.niveaux = arrNiveaux; this.position = iPosition; this.longueur = iLongueur; this.ferme = bFerme; this.balisefin = bBaliseFin; this.abalisefin = bABaliseFin; // ce qu'on a déjà tapé (pour affichage en début de chaque mot de la liste) this.avant = "[" + this.niveaux.join(":"); while (this.avant.substr(this.avant.length - 1, 1) != ":" && this.avant.length > 1) this.avant = this.avant.substr(0, this.avant.length - 1); } // Tableau des listes // c'est lui qui contient TOUT var LM = new Array(); // Liste des mots de la racine var tmp = new Array(); tmp[0] = new Mot("citer", "Insérer une citation", true, true); tmp[1] = new Mot("code", "Insérer du code source", true, true); tmp[2] = new Mot("correct", "Insérer une correction", false, true); // ToDo: gérer uniquement dans un [code]/code à gérer tmp[3] = new Mot("el", "Insérer un élément de liste", false, true); // ToDo: gérer uniquement dans un [liste]/liste à gérer tmp[4] = new Mot("err", "Insérer une erreur", false, true); // ToDo: gérer uniquement dans un [code]/code à gérer tmp[5] = new Mot("expr", "Insérer une expression", true, true); tmp[6] = new Mot("liste", "Insérer une liste", true, true); tmp[7] = new Mot("titre", "Insérer un titre", true, true); LM.push(new ListeMot(0, null, tmp)); // Liste des langages pour le code var tmp = new Array(); tmp[0] = new Mot("c", "Langage C", true, false); tmp[1] = new Mot("cpp", "C++", true, false); tmp[2] = new Mot("csharp", "C#", true, false); LM.push(new ListeMot(1, "code", tmp)); // Liste des langages pour le expr var tmp = new Array(); tmp[0] = new Mot("c", "Langage C", false, false); tmp[1] = new Mot("cpp", "C++", false, false); tmp[2] = new Mot("csharp", "C#", false, false); LM.push(new ListeMot(1, "expr", tmp)); // Liste des types de listes var tmp = new Array(); tmp[0] = new Mot("num", "Numérique", false, false); tmp[1] = new Mot("puces", "A puces", false, false); LM.push(new ListeMot(1, "liste", tmp)); // Liste des tailes de titres var tmp = new Array(); tmp[0] = new Mot("1", "Très grand", false, false); tmp[1] = new Mot("2", "Grand", false, false); tmp[2] = new Mot("3", "Moyennement grand", false, false); tmp[3] = new Mot("4", "Moyennement petit", false, false); tmp[4] = new Mot("5", "Petit", false, false); tmp[5] = new Mot("6", "Très petit", false, false); LM.push(new ListeMot(1, "titre", tmp)); // on dégage tmp pour libérer la mémoire tmp = null; function texte_KeyPress(objTextarea, keyCode) { // on récupère l'objet divListe objListe = document.getElementById("divListe"); // on récupère le caractère d'à la ligne if (objTextarea.value.indexOf("\r\n") > -1) crlf = "\r\n"; // Windows else if (objTextarea.value.indexOf("\r") > -1) crlf = "\r"; // Mac OS else crlf = "\n"; // Unix/Linux // on récupère la position du curseur dans le texte iPosCurseur = trouvePosCurseur(objTextarea); iCode = -1; // on sépare les mots et les "codes" potentiels tampon = ""; mots = new Array(); for (i = 0; i < objTextarea.value.length; i++) { carac = objTextarea.value.substr(i, 1); if (carac == "[") { if (tampon != "") { mots.push(tampon); } tampon = carac; } else if (carac == "]") { mots.push(tampon + carac); tampon = ""; } else { tampon += carac; } } if (tampon != "") mots.push(tampon); // on crée la liste des objets de chaque mot DE CODE uniquement iPosition = 0; codTexte = new Array(); for (i = 0; i < mots.length; i++) { lemot = mots[i]; if (lemot.substr(0, 1) == "[") { // la balise est elle fermee ? if (lemot.substr(lemot.length - 1, 1) == "]") ferme = true; else ferme = false; // est-ce une balise de fin ? if (lemot.length > 1) { if (lemot.substr(1, 1) == "/") { balisefin = true; abalisefin = false; } else { balisefin = false; abalisefin = true; } } else { balisefin = false; // on ne peut pas chercher la balise de fin abalisefin = false; } // on récupère les niveaux lemot = lemot.substr(1, lemot.length - (ferme ? 2 : 1)); if (lemot.substr(0, 1) == "/") lemot = lemot.substr(1, lemot.length - 1); niveaux = lemot.split(":"); // si on peut chercher une balise de fin éventuelle if (abalisefin) { abalisefin = false; // on cherche la balise de fin (ou la prochaine balise similaire) for (j = i + 1; j < mots.length; j++) { // trouvé, ok, on quitte if (mots[j] == "[/" + niveaux[0] + "]") { abalisefin = true; break; } else if (mots[j].substr(0, niveaux[0].length + 2) == "[" + niveaux[0] + "]" || mots[j].substr(0, niveaux[0].length + 2) == "[" + niveaux[0] + ":") { abalisefin = false; break; } } } // on peut enfin créer notre objet codNouveau = new Code(niveaux, iPosition, mots[i].length, ferme, balisefin, abalisefin); codTexte.push(codNouveau); // On regarde si c'est le Code pour lequel .position <= iPosCurseur && .position + .longueur >= iPosCurseur // ce code est celui sur lequel se trouve actuellement le curseur if (codNouveau.position < iPosCurseur && codNouveau.position + codNouveau.longueur >= iPosCurseur) iCode = codTexte.length - 1; } // on actualise la position iPosition += mots[i].length; } // si le curseur n'est sur aucun code if (iCode == -1) { objTextarea.focus(); objListe.style.visibility = "hidden"; return; } else // Sinon { if (!codTexte[iCode].ferme && !codTexte[iCode].balisefin) // Si on est pas fermé { // On cherche la liste de .niveau == codTexte[iCode].niveaux.length - 1 // et dont .avant == codTexte[iCode].niveaux[codTexte[iCode].niveaux.length - 2] iListe = -1; for (i = 0; i < LM.length; i++) { if (LM[i].niveau == codTexte[iCode].niveaux.length - 1 && LM[i].avant == codTexte[iCode].niveaux[codTexte[iCode].niveaux.length - 2]) { iListe = i; // trouvée break; } } // Si on ne l'a pas trouvée if (iListe == -1) { objTextarea.focus(); objListe.style.visibility = "hidden"; return; } else // Sinon { objListe.innerHTML = LM[iListe].creerListe(codTexte[iCode].avant, codTexte[iCode].niveaux[codTexte[iCode].niveaux.length - 1]); positionneListe(objTextarea, objListe); objListe.style.visibility = "visible"; } } else if (!codTexte[iCode].balisefin && !codTexte[iCode].abalisefin && codTexte[iCode].niveaux[0] != "citer" && keyCode != 8 && keyCode != 46) // Si on est pas une balise de fin et si on a pas de balise de fin { // On ajoute la balise de fin correspondante ajouteTexte("[/" + codTexte[iCode].niveaux[0] + "]"); objTextarea.focus(); if (objTextarea.createTextRange) // IE { iPosition = trouvePosCurseur(objTextarea); posCurseur = objTextarea.createTextRange(); posCurseur.move("character", iPosition - (codTexte[iCode].niveaux[0].length + 3)); posCurseur.select(); } else if (objTextarea.setSelectionRange) // NN/Mozilla { objTextarea.selectionStart -= (codTexte[iCode].niveaux[0].length + 3); objTextarea.selectionEnd = objTextarea.selectionStart; } objListe.style.visibility = "hidden"; } else { // En attendant la suite... objTextarea.focus(); objListe.style.visibility = "hidden"; } } } function positionneListe(objTextarea, objListe) { // on récupère le caractère d'à la ligne if (objTextarea.value.indexOf("\r\n") > -1) crlf = "\r\n"; // Windows else if (objTextarea.value.indexOf("\r") > -1) crlf = "\r"; // Mac OS else crlf = "\n"; // Unix/Linux objTextarea.focus(); if (objTextarea.createTextRange) // IE { posCurseur = window.document.selection.createRange().duplicate(); objListe.style.left = posCurseur.boundingLeft + posCurseur.boundingWidth + objTextarea.scrollLeft; objListe.style.top = posCurseur.boundingHeight * (objTextarea.value.substr(0, trouvePosCurseur(objTextarea)).split(crlf).length) + objTextarea.scrollTop + lHaut(objTextarea); } else if (objTextarea.setSelectionRange) // NN/Mozilla { // Comment faire ? } } function lHaut (objTextarea) { i = objTextarea.offsetTop; obj = objTextarea.offsetParent; while (obj) { i += obj.offsetTop; obj = obj.offsetParent; } return i; } // Trouve la position du curseur dans le texte function trouvePosCurseur(objTextarea) { objTextarea.focus(); if (objTextarea.createTextRange) // IE { posCurseur = document.selection.createRange().duplicate(); posCurseur.collapse(); posCurseur.moveStart("textedit", -1); return posCurseur.text.length; } else if (objTextarea.setSelectionRange) return objTextarea.selectionStart; // NN/Mozilla else return -1; // ? } // Ajoute du texte là ou est le curseur function ajouteTexte(strAjout) { objTextarea = document.frmEditeur.texte; objTextarea.focus(); if (objTextarea.createTextRange) document.selection.createRange().text += strAjout; // IE else if (objTextarea.setSelectionRange) // NN/Mozilla { iLongueur = objTextarea.selectionEnd; objTextarea.value = objTextarea.value.substr(0, iLongueur) + strAjout + objTextarea.value.substr(iLongueur); objTextarea.setSelectionRange(iLongueur + strAjout.length, iLongueur + strAjout.length); } else objTextarea.value += strAjout; // ? texte_KeyPress(objTextarea, 0); } // Vérifie que les données soumises sont correctes function verifEditeur(objTextarea) { if (objTextarea.value.replace("\r", "").replace("\n", "").replace("\t", "").replace(" ", "") == "") { alert("Vous devez saisir un message !"); objTextarea.focus(); return false; } else return true; } </script> </head> <body> <!-- Editeur --> <form name="frmEditeur" action="" method="post"> <textarea name="texte" onkeyup="javascript:if (frmEditeur.aidesaisie.checked) texte_KeyPress(this, event.keyCode);"></textarea> <table border="0" cellspacing="0" cellpadding="2"> <tr> <td><input type="checkbox" name="aidesaisie" checked></td> <td class="normal">Aide à la saisie</td> </tr> </table> </form> <div id="divListe" style="position: absolute; border: outset 1px; padding: 0px; visibility: hidden"></div> </body> </html>

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.