ADD un objet permettant l'attente des événements. Utilisé pour la page 'chat' et...
[euphorik.git] / js / euphorik.js
index 88ef6e7..8aaf875 100755 (executable)
@@ -21,19 +21,27 @@ var conf = {
       "bigsmile" : [/:D/g, /:-D/g],\r
       "clin" : [/;\)/g, /;-\)/g],\r
       "cool" : [/8\)/g, /8-\)/g],\r
-      "eheheh" : [/:P/g, /:-P/g],\r
-      "oh" : [/:o/g, /:O/g],\r
+      "eheheh" : [/:P/g, /:-P/g],
+      "lol" : [/\[-lol\]/g],
+      "spliff" : [/\[-spliff\]/g],\r
+      "oh" : [/:o/g, /:O/g],
+      "heink" : [/\[-heink\]/g],
+      "hum" : [/\[-hum\]/g],
+      "boh" : [/\[-boh\]/g],
+      "sniff" : [/:\(/g, /:-\(/g],
+      "triste" : [/\[-triste\]/g],\r
       "pascontent" : [/>\(/g, />\(/g],\r
-      "sniff" : [/:\(/g, /:-\(/g],\r
-      "argn" : [/\[:argn\]/g],\r
-      "bunny" : [/\[:lapin\]/g],\r
-      "chat" : [/\[:chat\]/g],\r
-      "renne" : [/\[:renne\]/g],\r
-      "lol" : [/\[:lol\]/g],\r
-      "spliff" : [/\[:spliff\]/g],\r
-      "star" : [/\[:star\]/g],\r
-      "triste" : [/\[:triste\]/g],\r
-      "kirby" : [/\[:kirby\]/g]\r
+      "argn" : [/\[-argn\]/g],
+      "redface" : [/\[-redface\]/g],\r
+      "bunny" : [/\[-lapin\]/g],\r
+      "chat" : [/\[-chat\]/g],\r
+      "renne" : [/\[-renne\]/g],\r
+      "star" : [/\[-star\]/g],\r
+      "kirby" : [/\[-kirby\]/g],
+      "slurp" : [/\[-slurp\]/g],
+      "agreed" : [/\[-agreed\]/g],
+      "dodo" : [/\[-dodo\]/g],
+      "bn" : [/\[-bn\]/g]\r
    }\r
 }\r
 
@@ -61,8 +69,8 @@ String.prototype.rtrim = function()
   */
 function Util()
 {
-   jQuery("#info .fermer").click(function(){
-      jQuery("#info").slideUp(50) 
+   $("#info .fermer").click(function(){
+      $("#info").slideUp(50) 
    })
 }
 
@@ -81,21 +89,21 @@ Util.prototype.messageDialogue = function(message, type, boutons)
    if (this.timeoutMessageDialogue != undefined)
       clearTimeout(this.timeoutMessageDialogue)
       
-   var fermer = function(){jQuery("#info").slideUp(100)}
+   var fermer = function(){$("#info").slideUp(100)}
    fermer()   
    
-   jQuery("#info .message").html(message)
+   $("#info .message").html(message)
    switch(type)
    {
-      case messageType.informatif : jQuery("#info #icone").attr("class", "information"); break
-      case messageType.question : jQuery("#info #icone").attr("class", "interrogation"); break
-      case messageType.erreur : jQuery("#info #icone").attr("class", "exclamation"); break
+      case messageType.informatif : $("#info #icone").attr("class", "information"); break
+      case messageType.question : $("#info #icone").attr("class", "interrogation"); break
+      case messageType.erreur : $("#info #icone").attr("class", "exclamation"); break
    }   
-   jQuery("#info .boutons").html("")
+   $("#info .boutons").html("")
    for (var b in boutons)
-      jQuery("#info .boutons").append("<div>" + b + "</div>").find("div:last").click(boutons[b]).click(fermer)
+      $("#info .boutons").append("<div>" + b + "</div>").find("div:last").click(boutons[b]).click(fermer)
    
-   jQuery("#info").slideDown(200)
+   $("#info").slideDown(200)
    this.timeoutMessageDialogue = setTimeout(fermer, conf.tempsAffichageMessageDialogue)   
 }
 
@@ -106,8 +114,7 @@ var messageType = {informatif: 0, question: 1, erreur: 2}
   */
 Util.prototype.jsonVersAction = function(json)
 {
-   // FIXME : ne plus encapsuler json dans de l'xml (problème avec yaws)
-   return {action: "<json>" + JSON.stringify(json) + "</json>" }
+   return {action : JSON.stringify(json) }
 }
 \r
 Util.prototype.md5 = function(chaine)\r
@@ -184,6 +191,29 @@ Util.prototype.replaceSelection = function(input, replaceString) {
    }\r
 }
 
+Util.prototype.rot13 = function(chaine)
+{
+   var ACode = 'A'.charCodeAt(0)
+   var aCode = 'a'.charCodeAt(0)
+   var MCode = 'M'.charCodeAt(0)
+   var mCode = 'm'.charCodeAt(0)
+   var ZCode = 'Z'.charCodeAt(0)
+   var zCode = 'z'.charCodeAt(0)
+
+   var f = function(ch, pos) {
+      if (pos == ch.length)
+         return ""
+      
+      var c = ch.charCodeAt(pos);
+      return String.fromCharCode(
+         c +
+         (c >= ACode && c <= MCode || c >= aCode && c <= mCode ? 13 :
+         (c > MCode && c <= ZCode || c > mCode && c <= zCode ? -13 : 0))
+      ) + f(ch, pos + 1)
+   }
+   return f(chaine, 0)
+}
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 function Pages()
@@ -208,11 +238,11 @@ Pages.prototype.afficherPage = function(nomPage, forcerChargement)
    if (this.pageCourante != null && this.pageCourante.decharger)
       this.pageCourante.decharger()
   
-   jQuery("#menu div").removeClass("courante")
-   jQuery("#menu div." + nomPage).addClass("courante")
+   $("#menu div").removeClass("courante")
+   $("#menu div." + nomPage).addClass("courante")
       
    this.pageCourante = page
-   jQuery("#page").html(this.pageCourante.contenu()).removeClass().addClass(this.pageCourante.nom)
+   $("#page").html(this.pageCourante.contenu()).removeClass().addClass(this.pageCourante.nom)
    
    if (this.pageCourante.charger)
       this.pageCourante.charger()
@@ -275,7 +305,8 @@ Formateur.prototype.traiterLiensConv = function(M)
 }
 \r
 /**\r
-  * FIXME : Cette méthode est attrocement lourde ! A optimiser.\r
+  * FIXME : Cette méthode est attrocement lourde ! A optimiser.
+  * moyenne su échantillon : 234ms\r
   */
 Formateur.prototype.traiterSmiles = function(M)
 {  
@@ -306,7 +337,7 @@ Formateur.prototype.traiterURL = function(M, pseudo)
       if (!thisFormateur.regexTestProtocoleExiste.test(url))\r
          url = "http://" + url
       var extension = thisFormateur.getShort(url)
-      return "<a " + (extension[1] ? "title=\"" + thisFormateur.traiterPourFenetreLightBox(pseudo, url) + ": " +  thisFormateur.traiterPourFenetreLightBox(M, url) + "\"" + " rel=\"lightbox[groupe]\"" : "") + " href=\"" + url + "\" >[" + extension[0] + "]</a>"
+      return "<a " + (extension[1] ? "title=\"" + thisFormateur.traiterPourFenetreLightBox(pseudo, url) + ": " +  thisFormateur.traiterPourFenetreLightBox(M, url) + "\"" + " rel=\"lightbox\"" : "") + " href=\"" + url + "\" >[" + extension[0] + "]</a>"
    }
    return M.replace(this.regexUrl, traitementUrl)
 }
@@ -319,8 +350,8 @@ Formateur.prototype.getShort = function(url)
 {\r
       var estUneImage = false
       var versionShort = null
-      var rechercheImg = this.regexImg.exec(url)\r
-      //alert(url)
+      var rechercheImg = this.regexImg.exec(url)
+      
       if (rechercheImg != null)\r
       {
          versionShort = rechercheImg[1].toLowerCase()\r
@@ -392,9 +423,11 @@ Client.prototype.resetDonneesPersonnelles = function()
    this.login = ""\r
    this.password = ""\r
    this.email = ""\r
-   this.css = jQuery("link#cssPrincipale").attr("href")
+   this.css = $("link#cssPrincipale").attr("href")
+   this.nickFormat = "nick"
    
    this.pagePrincipale = 1
+   this.ekMaster = false
    
    // les conversations, une conversation est un objet possédant les attributs suivants :
    // - racine (entier)
@@ -404,11 +437,11 @@ Client.prototype.resetDonneesPersonnelles = function()
 
 Client.prototype.setCss = function(css)
 {
-   if (this.css == css)
+   if (this.css == css || css == "")
       return
 
    this.css = css
-   jQuery("link#cssPrincipale").attr("href", this.css)
+   $("link#cssPrincipale").attr("href", this.css)
    this.majMenu()
 }
 
@@ -459,10 +492,10 @@ Client.prototype.ajouterConversation = function(racine)
 {
    // vérification s'il elle n'existe pas déjà
    for (var i = 0; i < this.conversations.length; i++)
-      if (this.conversations[i].racine == racine)
+      if (this.conversations[i].root == racine)
          return false
          
-   this.conversations.push({racine : racine, page : 1})
+   this.conversations.push({root : racine, page : 1})
    return true
 }
 
@@ -514,7 +547,7 @@ Client.prototype.getJSONConversations = function()
 {
    var conversations = new Array()
    for (var i = 0; i < this.conversations.length; i++)
-      conversations.push({ "racine" : this.conversations[i].racine, "page" : this.conversations[i].page})
+      conversations.push({ "root" : this.conversations[i].root, "page" : this.conversations[i].page})
    return conversations
 }
 
@@ -525,8 +558,10 @@ Client.prototype.getJSONProfile = function()
       "cookie" : this.cookie,
       "login" : this.login,
       "password" : this.password,
+      "nick" : this.pseudo,
       "email" : this.email,
       "css" : this.css,
+      "nick_format" : this.nickFormat,
       "main_page" : this.pagePrincipale < 1 ? 1 : this.pagePrincipale,
       "conversations" : this.getJSONConversations()
    }
@@ -568,7 +603,7 @@ Client.prototype.setStatut = function(statut)
    if (typeof(statut) == "string")\r
    {
       statut =
-         statut == "registered" ?
+         statut == "auth_registered" ?
             statutType.auth_registered :
          (statut == "auth_not_registered" ? statutType.auth_not_registered : statutType.deconnected)\r
    }   \r
@@ -636,16 +671,19 @@ Client.prototype.connexion = function(messageJson)
 }\r
 \r
 Client.prototype.deconnexion = function()\r
-{\r
+{
+   this.flush()
+   this.delCookie()\r
    this.setStatut(statutType.deconnected) // deconnexion\r
    this.resetDonneesPersonnelles()\r
-   this.delCookie ()\r
 }
 
 Client.prototype.chargerDonnees = function(data)
 {
-   var thisClient = this
-
+   // la modification du statut qui suit met à jour le menu, le menu dépend (page admin)
+   // de l'état ekMaster
+   this.ekMaster = data["ek_master"] != undefined ? data["ek_master"] : false
+   
    this.setStatut(data["status"]) 
    
    if (this.authentifie())
@@ -656,20 +694,14 @@ Client.prototype.chargerDonnees = function(data)
       this.login = data["login"]
       this.pseudo = data["nick"]\r
       this.email = data["email"]\r
-      this.css = data["css"]
+      this.setCss(data["css"])
+      this.nickFormat = data["nick_format"]
       
       // la page de la conversation principale
       this.pagePrincipale = data["main_page"] == undefined ? 1 : data["main_page"]
       
-      // met à jour la css
-      if (this.css != "")
-      {
-         jQuery("link#cssPrincipale").attr("href", this.css)
-         this.majMenu()
-      }
       // les conversations
-      thisClient.conversations = data["conversations"]
-      
+      this.conversations = data["conversations"]
    }
    this.dernierMessageErreur = data["error_message"]
 }
@@ -688,7 +720,7 @@ Client.prototype.flush = function(async)
       return false
 
    thisClient = this
-   //this.util.jsonVersAction(this.getJSONProfile()).action.dump("Flush client")      
+   ;;; dumpObj(this.getJSONProfile())
    jQuery.ajax(
       {
          async: async,
@@ -709,46 +741,180 @@ Client.prototype.flush = function(async)
 
 Client.prototype.majMenu = function()
 {
+   // TODO : à virer : ne plus changer de style de display ... spa beau .. ou trouver une autre méthode
    var displayType = this.css == "css/3/euphorik.css" ? "block" : "inline" //this.client
 
+   $("#menu .admin").css("display", this.ekMaster ? "inline" : "none")
+
    // met à jour le menu   
    if (this.statut == statutType.auth_registered)
    {
-      jQuery("#menu .profile").css("display", displayType).text("profile")\r
-      jQuery("#menu .logout").css("display", displayType)
-      jQuery("#menu .register").css("display", "none")
+      $("#menu .profile").css("display", displayType).text("profile")\r
+      $("#menu .logout").css("display", displayType)
+      $("#menu .register").css("display", "none")
    }
    else if (this.statut == statutType.auth_not_registered)
    {
-      jQuery("#menu .profile").css("display", "none")\r
-      jQuery("#menu .logout").css("display", displayType)
-      jQuery("#menu .register").css("display", displayType)
+      $("#menu .profile").css("display", "none")\r
+      $("#menu .logout").css("display", displayType)
+      $("#menu .register").css("display", displayType)
    }
    else
    {
-      jQuery("#menu .profile").css("display", displayType).text("login")\r
-      jQuery("#menu .logout").css("display", "none")
-      jQuery("#menu .register").css("display", displayType)
+      $("#menu .profile").css("display", displayType).text("login")\r
+      $("#menu .logout").css("display", "none")
+      $("#menu .register").css("display", displayType)
    }
 }
 
+Client.prototype.slap = function(userId, raison)
+{
+   var thisClient = this
+   
+   jQuery.ajax({
+      type: "POST",
+      url: "request",
+      dataType: "json",
+      data: this.util.jsonVersAction(
+         {
+            "action" : "slap",
+            "cookie" : thisClient.cookie,
+            "user_id" : userId,
+            "reason" : raison
+         }),
+      success: 
+         function(data)
+         {
+            if (data["reply"] == "error")
+               thisClient.util.messageDialogue(data["error_message"])
+         }
+   })
+}
+
+Client.prototype.ban = function(userId, raison, minutes)
+{
+   var thisClient = this
+
+   // par défaut un ban correspond à 3 jours
+   if (typeof(minutes) == "undefined")
+      minutes = 60 * 24 * 3
+      
+   jQuery.ajax({
+      type: "POST",
+      url: "request",
+      dataType: "json",
+      data: this.util.jsonVersAction(
+         {
+            "action" : "ban",
+            "cookie" : thisClient.cookie,
+            "duration" : minutes,
+            "user_id" : userId,
+            "reason" : raison
+         }),
+      success: 
+         function(data)
+         {
+            if (data["reply"] == "error")
+               thisClient.util.messageDialogue(data["error_message"])
+         }
+   })
+}
+
+Client.prototype.kick = function(userId, raison)
+{
+   this.ban(userId, raison, 15)
+}
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-jQuery.noConflict()
+/**
+   * classe permettant de gérer les événements (push serveur).
+   * @page la page
+   */
+function PageEvent(page, util)
+{
+   this.page = page
+   this.util = util
+   
+   // l'objet JSONHttpRequest représentant la connexion d'attente
+   this.attenteCourante = null
+}
+
+/**
+  * Arrête l'attente courante s'il y en a une.
+  */
+PageEvent.prototype.stopAttenteCourante = function()
+{
+   if (this.attenteCourante != null)
+      this.attenteCourante.abort()   
+}
+
+/**
+  * Attend un événement lié à la page. 
+  * @funSend une fonction renvoyant les données json à envoyer
+  * @funReceive une fonction qui accepte un paramètre correspondant au données reçues
+  */
+PageEvent.prototype.waitEvent = function(funSend, funReceive)
+{
+   var thisPageEvent = this
+      
+   this.stopAttenteCourante()
+      
+   // on doit conserver l'ordre des valeurs de l'objet JSON (le serveur les veux dans l'ordre définit dans le protocole)
+   // TODO : ya pas mieux ?
+   var dataToSend = 
+   {
+      "action" : "wait_event",
+      "page" : this.page
+   }
+   var poulpe = funSend()
+   for (v in poulpe)
+      dataToSend[v] = poulpe[v]
+   
+   ;;; dumpObj(dataToSend)
+   this.attenteCourante = jQuery.ajax({
+      type: "POST",
+      url: "request",
+      dataType: "json",
+      data: this.util.jsonVersAction(dataToSend),
+      success:
+         function(data)
+         {            
+            ;;; dumpObj(data)
+            
+            funReceive(data)
+            
+            // rappel de la fonction dans 100 ms
+            setTimeout(function(){ thisPageEvent.waitEvent(funSend, funReceive) }, 100);
+         },
+      error:
+         function(XMLHttpRequest, textStatus, errorThrown)
+         {
+            setTimeout(function(){ thisPageEvent.rafraichirMessages(funSend, funReceive) }, 1000);
+         }
+   })
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+function initialiserListeStyles(client)
+{
+   $("#menuCss").change(
+      function()
+      {
+         client.setCss("css/" + $("option:selected", this).attr("value") + "/euphorik.css")
+      }
+   )
+}
             
 // charge dynamiquement le script de debug
 ;;; jQuery.ajax({async : false, url : "js/debug.js", dataType : "script"})
       \r
 // le main
-jQuery(document).ready(
+$(document).ready(
    function()
    {  
-      /* FIXME : ce code pose problème sur konqueror, voir : http://www.kde-forum.org/thread.php?threadid=17993
-      var p = new DOMParser();
-      var doc =  p.parseFromString("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<action/>", "text/xml")
-      var s = new XMLSerializer()
-      alert(s.serializeToString(doc)) */
-   
       var util = new Util()
       var client = new Client(util)
       var pages = new Pages()
@@ -757,25 +923,15 @@ jQuery(document).ready(
       // connexion vers le serveur (utilise un cookie qui traine)\r
       client.connexionCookie()
       
-      // les styles css
-      for (var i = 1; i <= 3; i++)
-      {
-         jQuery("#css"+i).click(function(){
-            client.setCss("css/" + jQuery(this).attr("id").charAt(3) + "/euphorik.css")
-         })
-      }
+      initialiserListeStyles(client)
 
-      jQuery(document).unload(
-         function()
-         {
-            alert("ok")
-            client.flush()
-         }
-      )
+      // TODO : pourquoi $(document).unload ne fonctionne pas ?
+      $(window).unload(function(){client.flush(false)})
       
-      jQuery("#menu .minichat").click(function(){ pages.afficherPage("minichat") })
-      jQuery("#menu .profile").click(function(){ pages.afficherPage("profile") })\r
-      jQuery("#menu .logout").click(function(){
+      $("#menu .minichat").click(function(){ pages.afficherPage("minichat") })
+      $("#menu .admin").click(function(){ pages.afficherPage("admin") })
+      $("#menu .profile").click(function(){ pages.afficherPage("profile") })\r
+      $("#menu .logout").click(function(){
          util.messageDialogue("Êtes-vous sur de vouloir vous délogger ?", messageType.question,
             {"Oui" : function()
                {
@@ -786,11 +942,14 @@ jQuery(document).ready(
             }
          )
       })
-      jQuery("#menu .register").click(function(){ pages.afficherPage("register") })
+      $("#menu .register").click(function(){ pages.afficherPage("register") })
+      $("#menu .about").click(function(){ pages.afficherPage("about") })
 
       pages.ajouterPage(new PageMinichat(client, formateur, util))
+      pages.ajouterPage(new PageAdmin(client, formateur, util))
       pages.ajouterPage(new PageProfile(client, formateur, util))
       pages.ajouterPage(new PageRegister(client, formateur, util))
+      pages.ajouterPage(new PageAbout(client, formateur, util))
       pages.afficherPage("minichat")
    }
 )
\ No newline at end of file