<!--
/******************************************************************************
  Editeur de BBCodes pour Phortail 2.0

  http://phortail.free.fr

  Nécessite JavaScript 1.3 ou supérieur,
  IE 5, Netscape 6, Firefox, Opera (6 ?)...

  Testé sous Win32 avec IE 6/7, Firefox 1.5-2.0 (Mozilla/Gecko), Opera 8.5-9.1

******************************************************************************/
newlineString = null;       // Séquence de saut de ligne (CR/LF, CR ou LF)
lineDelimiterChar = null;   // Caractère de détection des lignes (CR ou LF)
//
// Edition d'un bbcode
//
function inserer_bbcode (nom, valeur, champ)
{
  if (nom == null) return false;
  if (valeur == null) valeur = "";
  if (champ == null) champ = "bbcodes_txt";
  var result = false;
  if (!document.getElementById) return false;
  var oField = document.getElementById(champ);

  if (oField.setSelectionRange) {                       // Mozilla/Gecko, Opera
    var scrollPos = oField.scrollTop;
    var scrollHeight = oField.scrollHeight;
    var field = new Object();
    field.value = oField.value;
    field.selectionStart = oField.selectionStart;
    field.selectionEnd = oField.selectionEnd;

    result = edit_bbcode(nom, valeur, field);
    if (result) {
      // Mise à jour du champ de formulaire
      oField.value = field.value;
      // Sélection du texte
      oField.focus();
      oField.setSelectionRange(field.selectionStart, field.selectionEnd);
      if (scrollPos + oField.clientHeight == scrollHeight)
        oField.scrollTop = scrollPos + oField.scrollHeight - scrollHeight;
      else oField.scrollTop = scrollPos;
    }
  }
  else if (document.selection && document.selection.createRange &&
    document.selection.createRange().moveToElementText &&
    document.selection.createRange().setEndPoint) {     // Internet Explorer
    oField.focus();
    // Récupère le contenu de la sélection
    var range1 = document.selection.createRange();
    var selectionText = range1.text;
    // Récupère le contenu complet du champ
    var range2 = document.selection.createRange();
    range2.moveToElementText(oField);

    // Déplace le début de range1 au début du champ, pour déterminer la
    // position de la sélection par rapport au début du champ
    range1.setEndPoint('StartToStart', range2);
    var field = new Object();
    field.value = range2.text;
    field.selectionStart = range1.text.length - selectionText.length;
    field.selectionEnd = range1.text.length;
    result = edit_bbcode(nom, valeur, field);
    if (result) {
      var n1 = 0, n2 = 0;

      if (newlineString.length > 1) {
        // Comptage du nombre de sauts de ligne après la sélection.
        // Chaque saut de ligne compte pour deux caractères (\r\n) dans la valeur,
        // mais pour un seul dans les méthodes moveStart et moveEnd.
        // Il faut donc faire une correction.
        var re = RegExp(newlineString, "g");
        // Comptage des sauts de ligne après de début de la sélection
        n1 = field.value.substring(field.selectionStart).match(re);
        if (n1) n1 = n1.length * (newlineString.length - 1); else n1 = 0;
        // Comptage des sauts de ligne après la fin de la selection
        var n2 = field.value.substring(field.selectionEnd).match(re);
        if (n2) n2 = n2.length * (newlineString.length - 1); else n2 = 0;
      }

      // Mise à jour du champ de formulaire
      range2.text = field.value;
      // Sélection du texte
      range2.moveStart('character', field.selectionStart - field.value.length + n1);
      range2.moveEnd('character',  field.selectionEnd - field.value.length + n2);
      range2.select();
    }
  }

  return result;
}
//
// Edition d'un bbcode (création, modification ou suppression)
//
// Cette fonction est indépendante du navigateur.
//
function edit_bbcode (bbcNames, bbcValue, field)
{
  if (! isArray(bbcNames)) bbcNames = [bbcNames];
  else if (bbcNames.length == 0) return false;
  for (var i = 0; i < bbcNames.length; i++) {
    bbcNames[i] = trim(bbcNames[i]);
    if (! bbcNames[i]) return false;  // Si vide ou null
  }
  detect_line_break(field.value);
  var action = 0;

  var editText = field.value;
  var selectionStart = field.selectionStart;
  var selectionEnd = field.selectionEnd;
  // Recherche du (des) bbcode(s) autour de la sélection...
  // Les "blancs" (espaces, tabulations, sauts de ligne, etc...)
  // sont ignorés lors de cette recherche.
  var bbcFound = false;
  var bbcName = bbcNames[0];
  var foundStartCode = "";
  var foundBbcValue = "";

  for (var iName = 0; iName < bbcNames.length; iName++) {
    var aName = bbcNames[iName];

    var aStartCodePrefix = "[" + aName;
    var aEndCode = "[/" + aName + "]";
    // Recherche du préfixe de début...
    var re = new RegExp('^(\\s*)\\[' + aName);
    var startMatch = re.exec(editText.substring(selectionStart));   // ...en avant
    if (startMatch != null) {
      var iStartCode = selectionStart + startMatch[1].length;
    } else {
      var iStartCode =
        editText.lastIndexOf(aStartCodePrefix, selectionStart);     // ...en arrière
    }
    if (iStartCode != -1) {
      // Le préfixe de début a été trouvé en position iStartCode
      // Vérification du code de début complet
      re = new RegExp('^(\\[' + aName + '(=([^\\]]*))?\\])\\s*');
      startMatch = re.exec(editText.substring(iStartCode));
      if (startMatch != null &&
        iStartCode + startMatch[0].length >= selectionStart) {
        // Le code de début a été trouvé en position iStartCode
        // Recherche du code de fin...
        re = new RegExp('^(\\s*)\\[/' + aName + '\\]');
        var endMatch = re.exec(editText.substring(selectionEnd));       // ...en avant
        if (endMatch != null) {
          var iEndCode = selectionEnd + endMatch[1].length;
        } else {
          var iEndCode = editText.lastIndexOf(aEndCode, selectionEnd);  // ...en arrière
        }
        if (iEndCode != -1) {
          // Un code de fin possible a été trouvé en position iEndCode
          // Vérification de la position du code de fin
          re = new RegExp('^\\[/' + aName + '\\]\\s*');
          endMatch = re.exec(editText.substring(iEndCode));
          if (endMatch != null &&
            iEndCode + endMatch[0].length >= selectionEnd) {
            // Le code de fin a été trouvé en position iEndCode

            bbcFound = true;
            bbcName = aName;
            foundStartCode = startMatch[1];
            if (startMatch[3]) foundBbcValue = startMatch[3];   // S'il y a une valeur
            // Ajuste la sélection sur le texte intérieur
            selectionStart = iStartCode + foundStartCode.length;
            selectionEnd = iEndCode;
            break;
          }
        }
      }
    }
  }
  var startCodePrefix = "[" + bbcName;
  var endCode = "[/" + bbcName + "]";
  var bbcText = editText.substring(selectionStart, selectionEnd);
  // Détection de texte vide dans le bbcode (ou sélection vide)
  if (trim(bbcText) == "") {
    // Dialogue utilisateur si ce bbcode requiert un texte non vide
    var text = prompt_bbcode_text(bbcName);
    if (text == null) return false;   // Abandon par l'utilisateur
    else if (text !== false) {        // Si texte saisi
      text = trim(text);
      if (text == "") action = 2;     // Suppression du bbcode
      else {
        action = 1;                   // Insertion ou modification du bbcode
        bbcText = text;

        // Insère le nouveau texte
        editText = editText.substring(0, selectionStart) +
          bbcText + editText.substring(selectionEnd);
        selectionEnd = selectionStart + bbcText.length;
      }
    }
  }
  // Détection de valeur vide dans le nouveau bbcode
  if (bbcValue == "" && action != 2) {

    // Dialogue utilisateur si ce bbcode requiert une valeur non vide
    var value = prompt_bbcode_value(bbcName, bbcText, foundBbcValue);
    if (value == null) return false;  // Abandon par l'utilisateur
    else if (value !== false) {       // Si valeur saisie
      value = trim(value);
      if (value == "") action = 2;    // Suppression du bbcode
      else {
        action = 1;                   // Insertion ou modification du bbcode
        bbcValue = value;
      }
    }
  }
  // Insertion, modification ou suppression du bbcode
  // action: 0=auto, 1=insertion/modification, 2=suppression

  if (bbcValue == "") var startCode = startCodePrefix + "]";
  else var startCode = startCodePrefix + "=" + bbcValue + "]";
  if (bbcFound) {
    // Suppression du bbcode si aucun changement n'a été effectué
    if (action == 0 && bbcValue == foundBbcValue) action = 2;

    if (action == 2) {

      // Suppression du bbcode existant
      var text = format_bbcode_text(bbcName, bbcText, 2);
      if (text != null) {
        bbcText = text;
        editText = editText.substring(0, iStartCode) +
          bbcText +
          editText.substring(selectionEnd + endCode.length);
        selectionStart = iStartCode;
        selectionEnd = selectionStart + bbcText.length;
        bbcFound = false;
      }
    }
    else {
      // Modification de la valeur du bbcode existant
      editText = editText.substring(0, iStartCode) +
        startCode + bbcText +
        editText.substring(selectionEnd);
      selectionStart = iStartCode + startCode.length;
      selectionEnd = selectionStart + bbcText.length;
    }
  }
  else if (action != 2) {

    // Insertion du bbcode

    var text = format_bbcode_text(bbcName, bbcText, 1);
    if (text != null) {
      bbcText = text;
      editText = editText.substring(0, selectionStart) +
        startCode + bbcText + endCode +
        editText.substring(selectionEnd);
      selectionStart = selectionStart + startCode.length;
      selectionEnd = selectionStart + bbcText.length;
      bbcFound = true;
    }
  }
  // Sélection du bbcode complet si le texte n'est pas vide
  if (bbcFound && bbcText != "") {
    selectionStart -= startCode.length;
    selectionEnd += endCode.length;
  }
  // Renvoi du champ modifié
  field.value = editText;
  field.selectionStart = selectionStart;
  field.selectionEnd = selectionEnd;

  return true;
}
function prompt_bbcode_text (bbcName)
{
  if (bbcName == "img")
    return prompt("Entrez l'adresse complète de l'image :", "");
  else if (bbcName == "email")
    return prompt("Entrez le nom (ou à défaut, l'adresse) de l'email :", "");
  else if (bbcName == "url" || bbcName == "siteurl")
    return prompt("Entrez le texte représentant le lien :", "");

  return false;
}
function prompt_bbcode_value (bbcName, bbcText, bbcValue)
{
  if (bbcName == "url" || bbcName == "siteurl") {
    if (bbcText.search(/^(http|https|ftp):\/\/.+/i) != -1) return false;
    if (bbcValue == "") bbcValue = "http://";
    bbcValue = prompt("Entrez l'adresse complète du lien :", bbcValue);
    if (bbcValue == "http://") bbcValue = "";
    return bbcValue;
  }
  else if (bbcName == "email") {
    if (bbcText.search(/^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-z]{2,3}$/i) != -1) return false;
    return prompt("Entrez l'adresse email :", bbcValue);
  }
  return false;
}
function format_bbcode_text (bbcName, bbcText, mode)
{ // mode de formatage: 1=insertion, 2=suppression
  if (bbcName == "list") {

    // Ne gère pas les listes imbriquées !
    if (bbcText.search(/\[list(=.*)?\]/) != -1) return null;

    if (mode == 1) {            // Insertion
      bbcText = trim(bbcText);
      var result = newlineString;
      if (bbcText != "") {
        var lignes = bbcText.split(lineDelimiterChar);
        for (var i = 0; i < lignes.length; i++) {
          if (trim(lignes[i]) != "") result += "[*]" + trim(lignes[i]);
          result += newlineString;
        }
      }
      else result += "[*]" + newlineString + "[*]" + newlineString;
      return result;
    }
    else if (mode == 2) {       // Suppression
      bbcText = trim(bbcText.replace(/\[\*\]/g, ""));
    }
  }

  return bbcText;
}
function detect_line_break (text)
{
  // newlineString et lineDelimiterChar sont des variables globales

  if (newlineString == null || lineDelimiterChar == null) {
    // Recherche la séquence de saut de ligne (CR/LF, CR ou LF)
    newlineString = search_line_break(text);
    if (newlineString == null) {
      // En cas d'échec, on tente de détecter le navigateur
      if (navigator.appName == "Microsoft Internet Explorer" ||
        navigator.appName == "Opera") newlineString = "\r\n";
      else newlineString = "\n";
    }
    // Caractère de détection des lignes : CR ou LF
    if (newlineString == "\r") lineDelimiterChar = "\r";
    else lineDelimiterChar = "\n";
  }
}
function search_line_break (text)
{
  // Recherche la séquence de saut de ligne (CR/LF, CR ou LF)
  // dans le texte
  if (text.search(/^[^\r\n]*\r\n/) != -1) return "\r\n";
  else if (text.search(/^[^\r\n]*\r/) != -1) return "\r";
  else if (text.search(/^[^\r\n]*\n/) != -1) return "\n";
  else return null;
}
function trim (str)
{
  return str.replace(/^\s*|\s*$/g, "");
}
function isArray (a) {
  return a && typeof a == "object" && a.constructor == Array;
}
//-----------------------------------------------------------------------------
// Gestion des smilies
//-----------------------------------------------------------------------------
//
// Insertion d'un smiley
//
function inserer_smiley (code, champ)
{
  return inserer_chaine(" " + code + " ", champ);
}
function inserer_chaine (chaine, champ)
{
  if (chaine == null) return false;
  if (champ == null) champ = "bbcodes_txt";
  var result = false;
  if (!document.getElementById) return false;
  var oField = document.getElementById(champ);
  if (document.selection &&
      document.selection.createRange) {     // Internet Explorer, Opera
    oField.focus();
    var range = document.selection.createRange();
    range.text = chaine;
    range.select();
    result = true;
  }
  else if (oField.setSelectionRange) {      // Mozilla/Gecko, Opera

    var selectionStart = oField.selectionStart;
    var scrollPos = oField.scrollTop;
    var scrollHeight = oField.scrollHeight;

    oField.value =
      oField.value.substring(0, oField.selectionStart) +
      chaine +
      oField.value.substring(oField.selectionEnd);
    oField.focus();
    oField.setSelectionRange(
      selectionStart + chaine.length,
      selectionStart + chaine.length);
    if (scrollPos + oField.clientHeight == scrollHeight)
      oField.scrollTop = scrollPos + oField.scrollHeight - scrollHeight;
    else oField.scrollTop = scrollPos;
    result = true;
  }

  return result;
}
//-----------------------------------------------------------------------------
//-->

