<!--

/******************************************************************************

  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, Firefox 1.5 (Mozilla/Gecko), Opera 8.5/9.0
  
******************************************************************************/


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;
}

//-----------------------------------------------------------------------------

//-->